]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/InstanceWatcher.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / tools / rbd_mirror / InstanceWatcher.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_RBD_MIRROR_INSTANCE_WATCHER_H
5 #define CEPH_RBD_MIRROR_INSTANCE_WATCHER_H
6
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <vector>
11
12 #include "common/AsyncOpTracker.h"
13 #include "librbd/Watcher.h"
14 #include "librbd/managed_lock/Types.h"
15 #include "tools/rbd_mirror/instance_watcher/Types.h"
16
17 namespace librbd {
18
19 class ImageCtx;
20 template <typename> class ManagedLock;
21
22 }
23
24 namespace rbd {
25 namespace mirror {
26
27 template <typename> class InstanceReplayer;
28 template <typename> struct Threads;
29
30 template <typename ImageCtxT = librbd::ImageCtx>
31 class InstanceWatcher : protected librbd::Watcher {
32 public:
33 static void get_instances(librados::IoCtx &io_ctx,
34 std::vector<std::string> *instance_ids,
35 Context *on_finish);
36 static void remove_instance(librados::IoCtx &io_ctx,
37 ContextWQ *work_queue,
38 const std::string &instance_id,
39 Context *on_finish);
40
41 static InstanceWatcher *create(
42 librados::IoCtx &io_ctx, ContextWQ *work_queue,
43 InstanceReplayer<ImageCtxT> *instance_replayer);
44 void destroy() {
45 delete this;
46 }
47
48 InstanceWatcher(librados::IoCtx &io_ctx, ContextWQ *work_queue,
49 InstanceReplayer<ImageCtxT> *instance_replayer,
50 const std::string &instance_id);
51 ~InstanceWatcher() override;
52
53 inline std::string &get_instance_id() {
54 return m_instance_id;
55 }
56
57 int init();
58 void shut_down();
59
60 void init(Context *on_finish);
61 void shut_down(Context *on_finish);
62 void remove(Context *on_finish);
63
64 void notify_image_acquire(const std::string &instance_id,
65 const std::string &global_image_id,
66 const std::string &peer_mirror_uuid,
67 const std::string &peer_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 const std::string &peer_mirror_uuid,
72 const std::string &peer_image_id,
73 bool schedule_delete, Context *on_notify_ack);
74
75 void cancel_notify_requests(const std::string &instance_id);
76
77 private:
78 /**
79 * @verbatim
80 *
81 * BREAK_INSTANCE_LOCK -------\
82 * ^ |
83 * | (error) |
84 * GET_INSTANCE_LOCKER * * *>|
85 * ^ (remove) |
86 * | |
87 * <uninitialized> <----------------+---- WAIT_FOR_NOTIFY_OPS
88 * | (init) ^ | ^
89 * v (error) * | |
90 * REGISTER_INSTANCE * * * * * *|* *> UNREGISTER_INSTANCE
91 * | * | ^
92 * v (error) * v |
93 * CREATE_INSTANCE_OBJECT * * * * * *> REMOVE_INSTANCE_OBJECT
94 * | * ^
95 * v (error) * |
96 * REGISTER_WATCH * * * * * * * * * *> UNREGISTER_WATCH
97 * | * ^
98 * v (error) * |
99 * ACQUIRE_LOCK * * * * * * * * * * * RELEASE_LOCK
100 * | ^
101 * v (shut_down) |
102 * <watching> -------------------------------/
103 *
104 * @endverbatim
105 */
106
107 struct C_NotifyInstanceRequest;
108
109 struct HandlePayloadVisitor : public boost::static_visitor<void> {
110 InstanceWatcher *instance_watcher;
111 std::string instance_id;
112 C_NotifyAck *on_notify_ack;
113
114 HandlePayloadVisitor(InstanceWatcher *instance_watcher,
115 const std::string &instance_id,
116 C_NotifyAck *on_notify_ack)
117 : instance_watcher(instance_watcher), instance_id(instance_id),
118 on_notify_ack(on_notify_ack) {
119 }
120
121 template <typename Payload>
122 inline void operator()(const Payload &payload) const {
123 instance_watcher->handle_payload(instance_id, payload, on_notify_ack);
124 }
125 };
126
127 struct Request {
128 std::string instance_id;
129 uint64_t request_id;
130 C_NotifyAck *on_notify_ack = nullptr;
131
132 Request(const std::string &instance_id, uint64_t request_id)
133 : instance_id(instance_id), request_id(request_id) {
134 }
135
136 inline bool operator<(const Request &rhs) const {
137 return instance_id < rhs.instance_id ||
138 (instance_id == rhs.instance_id && request_id < rhs.request_id);
139 }
140 };
141
142 Threads<ImageCtxT> *m_threads;
143 InstanceReplayer<ImageCtxT> *m_instance_replayer;
144 std::string m_instance_id;
145
146 mutable Mutex m_lock;
147 librbd::ManagedLock<ImageCtxT> *m_instance_lock;
148 Context *m_on_finish = nullptr;
149 int m_ret_val = 0;
150 bool m_removing = false;
151 librbd::managed_lock::Locker m_instance_locker;
152 std::set<std::pair<std::string, C_NotifyInstanceRequest *>> m_notify_ops;
153 AsyncOpTracker m_notify_op_tracker;
154 uint64_t m_request_seq = 0;
155 std::set<Request> m_requests;
156
157 void register_instance();
158 void handle_register_instance(int r);
159
160 void create_instance_object();
161 void handle_create_instance_object(int r);
162
163 void register_watch();
164 void handle_register_watch(int r);
165
166 void acquire_lock();
167 void handle_acquire_lock(int r);
168
169 void release_lock();
170 void handle_release_lock(int r);
171
172 void unregister_watch();
173 void handle_unregister_watch(int r);
174
175 void remove_instance_object();
176 void handle_remove_instance_object(int r);
177
178 void unregister_instance();
179 void handle_unregister_instance(int r);
180
181 void wait_for_notify_ops();
182 void handle_wait_for_notify_ops(int r);
183
184 void get_instance_locker();
185 void handle_get_instance_locker(int r);
186
187 void break_instance_lock();
188 void handle_break_instance_lock(int r);
189
190 Context *prepare_request(const std::string &instance_id, uint64_t request_id,
191 C_NotifyAck *on_notify_ack);
192
193 void handle_notify(uint64_t notify_id, uint64_t handle,
194 uint64_t notifier_id, bufferlist &bl) override;
195
196 void handle_image_acquire(const std::string &global_image_id,
197 const std::string &peer_mirror_uuid,
198 const std::string &peer_image_id,
199 Context *on_finish);
200 void handle_image_release(const std::string &global_image_id,
201 const std::string &peer_mirror_uuid,
202 const std::string &peer_image_id,
203 bool schedule_delete, Context *on_finish);
204
205 void handle_payload(const std::string &instance_id,
206 const instance_watcher::ImageAcquirePayload &payload,
207 C_NotifyAck *on_notify_ack);
208 void handle_payload(const std::string &instance_id,
209 const instance_watcher::ImageReleasePayload &payload,
210 C_NotifyAck *on_notify_ack);
211 void handle_payload(const std::string &instance_id,
212 const instance_watcher::UnknownPayload &payload,
213 C_NotifyAck *on_notify_ack);
214 };
215
216 } // namespace mirror
217 } // namespace rbd
218
219 #endif // CEPH_RBD_MIRROR_INSTANCE_WATCHER_H