1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_RBD_MIRROR_INSTANCE_WATCHER_H
5 #define CEPH_RBD_MIRROR_INSTANCE_WATCHER_H
13 #include "common/AsyncOpTracker.h"
14 #include "librbd/Watcher.h"
15 #include "librbd/managed_lock/Types.h"
16 #include "tools/rbd_mirror/instance_watcher/Types.h"
21 template <typename> class ManagedLock;
28 template <typename> class ImageSyncThrottler;
29 template <typename> class InstanceReplayer;
30 template <typename> struct Threads;
32 template <typename ImageCtxT = librbd::ImageCtx>
33 class InstanceWatcher : protected librbd::Watcher {
35 static void get_instances(librados::IoCtx &io_ctx,
36 std::vector<std::string> *instance_ids,
38 static void remove_instance(librados::IoCtx &io_ctx,
39 ContextWQ *work_queue,
40 const std::string &instance_id,
43 static InstanceWatcher *create(
44 librados::IoCtx &io_ctx, ContextWQ *work_queue,
45 InstanceReplayer<ImageCtxT> *instance_replayer);
50 InstanceWatcher(librados::IoCtx &io_ctx, ContextWQ *work_queue,
51 InstanceReplayer<ImageCtxT> *instance_replayer,
52 const std::string &instance_id);
53 ~InstanceWatcher() override;
55 inline std::string &get_instance_id() {
62 void init(Context *on_finish);
63 void shut_down(Context *on_finish);
64 void remove(Context *on_finish);
66 void notify_image_acquire(const std::string &instance_id,
67 const std::string &global_image_id,
68 Context *on_notify_ack);
69 void notify_image_release(const std::string &instance_id,
70 const std::string &global_image_id,
71 Context *on_notify_ack);
72 void notify_peer_image_removed(const std::string &instance_id,
73 const std::string &global_image_id,
74 const std::string &peer_mirror_uuid,
75 Context *on_notify_ack);
77 void notify_sync_request(const std::string &sync_id, Context *on_sync_start);
78 bool cancel_sync_request(const std::string &sync_id);
79 void notify_sync_complete(const std::string &sync_id);
81 void print_sync_status(Formatter *f, stringstream *ss);
83 void cancel_notify_requests(const std::string &instance_id);
85 void handle_acquire_leader();
86 void handle_release_leader();
87 void handle_update_leader(const std::string &leader_instance_id);
93 * BREAK_INSTANCE_LOCK -------\
96 * GET_INSTANCE_LOCKER * * *>|
99 * <uninitialized> <----------------+---- WAIT_FOR_NOTIFY_OPS
102 * REGISTER_INSTANCE * * * * * *|* *> UNREGISTER_INSTANCE
105 * CREATE_INSTANCE_OBJECT * * * * * *> REMOVE_INSTANCE_OBJECT
108 * REGISTER_WATCH * * * * * * * * * *> UNREGISTER_WATCH
111 * ACQUIRE_LOCK * * * * * * * * * * * RELEASE_LOCK
114 * <watching> -------------------------------/
119 struct C_NotifyInstanceRequest;
120 struct C_SyncRequest;
122 typedef std::pair<std::string, std::string> Id;
124 struct HandlePayloadVisitor : public boost::static_visitor<void> {
125 InstanceWatcher *instance_watcher;
126 std::string instance_id;
127 C_NotifyAck *on_notify_ack;
129 HandlePayloadVisitor(InstanceWatcher *instance_watcher,
130 const std::string &instance_id,
131 C_NotifyAck *on_notify_ack)
132 : instance_watcher(instance_watcher), instance_id(instance_id),
133 on_notify_ack(on_notify_ack) {
136 template <typename Payload>
137 inline void operator()(const Payload &payload) const {
138 instance_watcher->handle_payload(instance_id, payload, on_notify_ack);
143 std::string instance_id;
145 C_NotifyAck *on_notify_ack = nullptr;
147 Request(const std::string &instance_id, uint64_t request_id)
148 : instance_id(instance_id), request_id(request_id) {
151 inline bool operator<(const Request &rhs) const {
152 return instance_id < rhs.instance_id ||
153 (instance_id == rhs.instance_id && request_id < rhs.request_id);
157 Threads<ImageCtxT> *m_threads;
158 InstanceReplayer<ImageCtxT> *m_instance_replayer;
159 std::string m_instance_id;
161 mutable Mutex m_lock;
162 librbd::ManagedLock<ImageCtxT> *m_instance_lock;
163 Context *m_on_finish = nullptr;
165 bool m_removing = false;
166 std::string m_leader_instance_id;
167 librbd::managed_lock::Locker m_instance_locker;
168 std::set<std::pair<std::string, C_NotifyInstanceRequest *>> m_notify_ops;
169 AsyncOpTracker m_notify_op_tracker;
170 uint64_t m_request_seq = 0;
171 std::set<Request> m_requests;
172 std::set<C_NotifyInstanceRequest *> m_suspended_ops;
173 std::map<std::string, C_SyncRequest *> m_inflight_sync_reqs;
174 ImageSyncThrottler<ImageCtxT> *m_image_sync_throttler = nullptr;
176 void register_instance();
177 void handle_register_instance(int r);
179 void create_instance_object();
180 void handle_create_instance_object(int r);
182 void register_watch();
183 void handle_register_watch(int r);
186 void handle_acquire_lock(int r);
189 void handle_release_lock(int r);
191 void unregister_watch();
192 void handle_unregister_watch(int r);
194 void remove_instance_object();
195 void handle_remove_instance_object(int r);
197 void unregister_instance();
198 void handle_unregister_instance(int r);
200 void wait_for_notify_ops();
201 void handle_wait_for_notify_ops(int r);
203 void get_instance_locker();
204 void handle_get_instance_locker(int r);
206 void break_instance_lock();
207 void handle_break_instance_lock(int r);
209 void suspend_notify_request(C_NotifyInstanceRequest *req);
210 bool unsuspend_notify_request(C_NotifyInstanceRequest *req);
211 void unsuspend_notify_requests();
213 void handle_notify_sync_request(C_SyncRequest *sync_ctx, int r);
214 void handle_notify_sync_complete(C_SyncRequest *sync_ctx, int r);
216 void notify_sync_start(const std::string &instance_id,
217 const std::string &sync_id);
219 Context *prepare_request(const std::string &instance_id, uint64_t request_id,
220 C_NotifyAck *on_notify_ack);
221 void complete_request(const std::string &instance_id, uint64_t request_id,
224 void handle_notify(uint64_t notify_id, uint64_t handle,
225 uint64_t notifier_id, bufferlist &bl) override;
227 void handle_image_acquire(const std::string &global_image_id,
229 void handle_image_release(const std::string &global_image_id,
231 void handle_peer_image_removed(const std::string &global_image_id,
232 const std::string &peer_mirror_uuid,
235 void handle_sync_request(const std::string &instance_id,
236 const std::string &sync_id, Context *on_finish);
237 void handle_sync_start(const std::string &instance_id,
238 const std::string &sync_id, Context *on_finish);
240 void handle_payload(const std::string &instance_id,
241 const instance_watcher::ImageAcquirePayload &payload,
242 C_NotifyAck *on_notify_ack);
243 void handle_payload(const std::string &instance_id,
244 const instance_watcher::ImageReleasePayload &payload,
245 C_NotifyAck *on_notify_ack);
246 void handle_payload(const std::string &instance_id,
247 const instance_watcher::PeerImageRemovedPayload &payload,
248 C_NotifyAck *on_notify_ack);
249 void handle_payload(const std::string &instance_id,
250 const instance_watcher::SyncRequestPayload &payload,
251 C_NotifyAck *on_notify_ack);
252 void handle_payload(const std::string &instance_id,
253 const instance_watcher::SyncStartPayload &payload,
254 C_NotifyAck *on_notify_ack);
255 void handle_payload(const std::string &instance_id,
256 const instance_watcher::UnknownPayload &payload,
257 C_NotifyAck *on_notify_ack);
260 } // namespace mirror
263 #endif // CEPH_RBD_MIRROR_INSTANCE_WATCHER_H