struct disconnect_ctx_t {
ObjectContext::watch_key_t key;
- bool send_disconnect{ false };
-
disconnect_ctx_t(const OSDOp& osd_op, const ExecutableMessage& msg)
: key(osd_op.op.watch.cookie, msg.get_reqid().name) {
}
return seastar::do_with(std::move(nh.mapped()),
[ctx](auto&& watcher) {
logger().info("op_effect: disconnect watcher {}", ctx.key);
- return watcher->remove(ctx.send_disconnect);
+ return watcher->remove();
});
} else {
logger().info("op_effect: disconnect failed to find watcher {}", ctx.key);
}
}
-seastar::future<> Watch::remove(const bool send_disconnect)
+seastar::future<> Watch::remove()
{
logger().info("{}", __func__);
- auto disconnected = send_disconnect ? send_disconnect_msg()
- : seastar::now();
- return std::move(disconnected).then([this] {
- return seastar::do_for_each(in_progress_notifies,
- [this_shared=shared_from_this()] (auto notify) {
- return notify->remove_watcher(this_shared);
- }).then([this] {
- discard_state();
- return seastar::now();
- });
+ // in contrast to ceph-osd crimson sends CEPH_WATCH_EVENT_DISCONNECT directly
+ // from the timeout handler and _after_ CEPH_WATCH_EVENT_NOTIFY_COMPLETE.
+ // this simplifies the Watch::remove() interface as callers aren't obliged
+ // anymore to decide whether EVENT_DISCONNECT needs to be send or not -- it
+ // becomes an implementation detail of Watch.
+ return seastar::do_for_each(in_progress_notifies,
+ [this_shared=shared_from_this()] (auto notify) {
+ return notify->remove_watcher(this_shared);
+ }).then([this] {
+ discard_state();
+ return seastar::now();
});
}
void Watch::do_watch_timeout(Ref<PG> pg)
{
- pg->get_shard_services().start_operation<WatchTimeoutRequest>(
+ auto [op, fut] = pg->get_shard_services().start_operation<WatchTimeoutRequest>(
shared_from_this(), pg);
+ std::ignore = std::move(fut).then([op=std::move(op), this] {
+ return send_disconnect_msg();
+ });
}
bool notify_reply_t::operator<(const notify_reply_t& rhs) const