]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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_LIBRBD_IMAGE_WATCHER_H | |
5 | #define CEPH_LIBRBD_IMAGE_WATCHER_H | |
6 | ||
7 | #include "cls/rbd/cls_rbd_types.h" | |
9f95a23c | 8 | #include "common/ceph_mutex.h" |
7c673cae FG |
9 | #include "include/Context.h" |
10 | #include "include/rbd/librbd.hpp" | |
11 | #include "librbd/Watcher.h" | |
12 | #include "librbd/WatchNotifyTypes.h" | |
13 | #include <set> | |
14 | #include <string> | |
15 | #include <utility> | |
16 | ||
17 | class entity_name_t; | |
18 | ||
19 | namespace librbd { | |
20 | ||
21 | namespace watcher { | |
22 | namespace util { | |
23 | template <typename> struct HandlePayloadVisitor; | |
24 | } | |
25 | } | |
26 | ||
27 | class ImageCtx; | |
28 | template <typename> class TaskFinisher; | |
29 | ||
30 | template <typename ImageCtxT = ImageCtx> | |
31 | class ImageWatcher : public Watcher { | |
32 | friend struct watcher::util::HandlePayloadVisitor<ImageWatcher<ImageCtxT>>; | |
33 | ||
34 | public: | |
35 | ImageWatcher(ImageCtxT& image_ctx); | |
36 | ~ImageWatcher() override; | |
37 | ||
31f18b77 FG |
38 | void unregister_watch(Context *on_finish) override; |
39 | void block_notifies(Context *on_finish) override; | |
7c673cae FG |
40 | |
41 | void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx, | |
42 | Context *on_finish); | |
43 | void notify_resize(uint64_t request_id, uint64_t size, bool allow_shrink, | |
44 | ProgressContext &prog_ctx, Context *on_finish); | |
45 | void notify_snap_create(const cls::rbd::SnapshotNamespace &snap_namespace, | |
46 | const std::string &snap_name, | |
47 | Context *on_finish); | |
48 | void notify_snap_rename(const snapid_t &src_snap_id, | |
49 | const std::string &dst_snap_name, | |
50 | Context *on_finish); | |
51 | void notify_snap_remove(const cls::rbd::SnapshotNamespace &snap_namespace, | |
52 | const std::string &snap_name, | |
53 | Context *on_finish); | |
54 | void notify_snap_protect(const cls::rbd::SnapshotNamespace &snap_namespace, | |
55 | const std::string &snap_name, | |
56 | Context *on_finish); | |
57 | void notify_snap_unprotect(const cls::rbd::SnapshotNamespace &snap_namespace, | |
58 | const std::string &snap_name, | |
59 | Context *on_finish); | |
60 | void notify_rebuild_object_map(uint64_t request_id, | |
61 | ProgressContext &prog_ctx, Context *on_finish); | |
62 | void notify_rename(const std::string &image_name, Context *on_finish); | |
63 | ||
64 | void notify_update_features(uint64_t features, bool enabled, | |
65 | Context *on_finish); | |
66 | ||
11fdf7f2 TL |
67 | void notify_migrate(uint64_t request_id, ProgressContext &prog_ctx, |
68 | Context *on_finish); | |
69 | ||
70 | void notify_sparsify(uint64_t request_id, size_t sparse_size, | |
71 | ProgressContext &prog_ctx, Context *on_finish); | |
72 | ||
7c673cae FG |
73 | void notify_acquired_lock(); |
74 | void notify_released_lock(); | |
75 | void notify_request_lock(); | |
76 | ||
77 | void notify_header_update(Context *on_finish); | |
78 | static void notify_header_update(librados::IoCtx &io_ctx, | |
79 | const std::string &oid); | |
80 | ||
81 | private: | |
82 | enum TaskCode { | |
83 | TASK_CODE_REQUEST_LOCK, | |
84 | TASK_CODE_CANCEL_ASYNC_REQUESTS, | |
85 | TASK_CODE_REREGISTER_WATCH, | |
86 | TASK_CODE_ASYNC_REQUEST, | |
87 | TASK_CODE_ASYNC_PROGRESS | |
88 | }; | |
89 | ||
90 | typedef std::pair<Context *, ProgressContext *> AsyncRequest; | |
91 | ||
92 | class Task { | |
93 | public: | |
94 | Task(TaskCode task_code) : m_task_code(task_code) {} | |
95 | Task(TaskCode task_code, const watch_notify::AsyncRequestId &id) | |
96 | : m_task_code(task_code), m_async_request_id(id) {} | |
97 | ||
98 | inline bool operator<(const Task& rhs) const { | |
99 | if (m_task_code != rhs.m_task_code) { | |
100 | return m_task_code < rhs.m_task_code; | |
101 | } else if ((m_task_code == TASK_CODE_ASYNC_REQUEST || | |
102 | m_task_code == TASK_CODE_ASYNC_PROGRESS) && | |
103 | m_async_request_id != rhs.m_async_request_id) { | |
104 | return m_async_request_id < rhs.m_async_request_id; | |
105 | } | |
106 | return false; | |
107 | } | |
108 | private: | |
109 | TaskCode m_task_code; | |
110 | watch_notify::AsyncRequestId m_async_request_id; | |
111 | }; | |
112 | ||
113 | class RemoteProgressContext : public ProgressContext { | |
114 | public: | |
115 | RemoteProgressContext(ImageWatcher &image_watcher, | |
116 | const watch_notify::AsyncRequestId &id) | |
117 | : m_image_watcher(image_watcher), m_async_request_id(id) | |
118 | { | |
119 | } | |
120 | ||
121 | int update_progress(uint64_t offset, uint64_t total) override { | |
122 | m_image_watcher.schedule_async_progress(m_async_request_id, offset, | |
123 | total); | |
124 | return 0; | |
125 | } | |
126 | ||
127 | private: | |
128 | ImageWatcher &m_image_watcher; | |
129 | watch_notify::AsyncRequestId m_async_request_id; | |
130 | }; | |
131 | ||
132 | class RemoteContext : public Context { | |
133 | public: | |
134 | RemoteContext(ImageWatcher &image_watcher, | |
135 | const watch_notify::AsyncRequestId &id, | |
136 | ProgressContext *prog_ctx) | |
137 | : m_image_watcher(image_watcher), m_async_request_id(id), | |
138 | m_prog_ctx(prog_ctx) | |
139 | { | |
140 | } | |
141 | ||
142 | ~RemoteContext() override { | |
143 | delete m_prog_ctx; | |
144 | } | |
145 | ||
146 | void finish(int r) override; | |
147 | ||
148 | private: | |
149 | ImageWatcher &m_image_watcher; | |
150 | watch_notify::AsyncRequestId m_async_request_id; | |
151 | ProgressContext *m_prog_ctx; | |
152 | }; | |
153 | ||
31f18b77 | 154 | struct C_ProcessPayload; |
7c673cae FG |
155 | struct C_ResponseMessage : public Context { |
156 | C_NotifyAck *notify_ack; | |
157 | ||
158 | C_ResponseMessage(C_NotifyAck *notify_ack) : notify_ack(notify_ack) { | |
159 | } | |
160 | void finish(int r) override; | |
161 | }; | |
162 | ||
163 | ImageCtxT &m_image_ctx; | |
164 | ||
165 | TaskFinisher<Task> *m_task_finisher; | |
166 | ||
9f95a23c | 167 | ceph::shared_mutex m_async_request_lock; |
7c673cae FG |
168 | std::map<watch_notify::AsyncRequestId, AsyncRequest> m_async_requests; |
169 | std::set<watch_notify::AsyncRequestId> m_async_pending; | |
170 | ||
9f95a23c | 171 | ceph::mutex m_owner_client_id_lock; |
7c673cae FG |
172 | watch_notify::ClientId m_owner_client_id; |
173 | ||
174 | void handle_register_watch(int r); | |
175 | ||
176 | void schedule_cancel_async_requests(); | |
177 | void cancel_async_requests(); | |
178 | ||
179 | void set_owner_client_id(const watch_notify::ClientId &client_id); | |
180 | watch_notify::ClientId get_client_id(); | |
181 | ||
182 | void handle_request_lock(int r); | |
183 | void schedule_request_lock(bool use_timer, int timer_delay = -1); | |
184 | ||
185 | void notify_lock_owner(const watch_notify::Payload& payload, | |
186 | Context *on_finish); | |
187 | ||
188 | Context *remove_async_request(const watch_notify::AsyncRequestId &id); | |
189 | void schedule_async_request_timed_out(const watch_notify::AsyncRequestId &id); | |
190 | void async_request_timed_out(const watch_notify::AsyncRequestId &id); | |
191 | void notify_async_request(const watch_notify::AsyncRequestId &id, | |
192 | const watch_notify::Payload &payload, | |
193 | ProgressContext& prog_ctx, | |
194 | Context *on_finish); | |
195 | ||
196 | void schedule_async_progress(const watch_notify::AsyncRequestId &id, | |
197 | uint64_t offset, uint64_t total); | |
198 | int notify_async_progress(const watch_notify::AsyncRequestId &id, | |
199 | uint64_t offset, uint64_t total); | |
200 | void schedule_async_complete(const watch_notify::AsyncRequestId &id, int r); | |
201 | void notify_async_complete(const watch_notify::AsyncRequestId &id, int r); | |
202 | void handle_async_complete(const watch_notify::AsyncRequestId &request, int r, | |
203 | int ret_val); | |
204 | ||
205 | int prepare_async_request(const watch_notify::AsyncRequestId& id, | |
206 | bool* new_request, Context** ctx, | |
207 | ProgressContext** prog_ctx); | |
208 | ||
209 | bool handle_payload(const watch_notify::HeaderUpdatePayload& payload, | |
210 | C_NotifyAck *ctx); | |
211 | bool handle_payload(const watch_notify::AcquiredLockPayload& payload, | |
212 | C_NotifyAck *ctx); | |
213 | bool handle_payload(const watch_notify::ReleasedLockPayload& payload, | |
214 | C_NotifyAck *ctx); | |
215 | bool handle_payload(const watch_notify::RequestLockPayload& payload, | |
216 | C_NotifyAck *ctx); | |
217 | bool handle_payload(const watch_notify::AsyncProgressPayload& payload, | |
218 | C_NotifyAck *ctx); | |
219 | bool handle_payload(const watch_notify::AsyncCompletePayload& payload, | |
220 | C_NotifyAck *ctx); | |
221 | bool handle_payload(const watch_notify::FlattenPayload& payload, | |
222 | C_NotifyAck *ctx); | |
223 | bool handle_payload(const watch_notify::ResizePayload& payload, | |
224 | C_NotifyAck *ctx); | |
225 | bool handle_payload(const watch_notify::SnapCreatePayload& payload, | |
226 | C_NotifyAck *ctx); | |
227 | bool handle_payload(const watch_notify::SnapRenamePayload& payload, | |
228 | C_NotifyAck *ctx); | |
229 | bool handle_payload(const watch_notify::SnapRemovePayload& payload, | |
230 | C_NotifyAck *ctx); | |
231 | bool handle_payload(const watch_notify::SnapProtectPayload& payload, | |
232 | C_NotifyAck *ctx); | |
233 | bool handle_payload(const watch_notify::SnapUnprotectPayload& payload, | |
234 | C_NotifyAck *ctx); | |
235 | bool handle_payload(const watch_notify::RebuildObjectMapPayload& payload, | |
236 | C_NotifyAck *ctx); | |
237 | bool handle_payload(const watch_notify::RenamePayload& payload, | |
238 | C_NotifyAck *ctx); | |
239 | bool handle_payload(const watch_notify::UpdateFeaturesPayload& payload, | |
240 | C_NotifyAck *ctx); | |
11fdf7f2 TL |
241 | bool handle_payload(const watch_notify::MigratePayload& payload, |
242 | C_NotifyAck *ctx); | |
243 | bool handle_payload(const watch_notify::SparsifyPayload& payload, | |
244 | C_NotifyAck *ctx); | |
7c673cae FG |
245 | bool handle_payload(const watch_notify::UnknownPayload& payload, |
246 | C_NotifyAck *ctx); | |
247 | void process_payload(uint64_t notify_id, uint64_t handle, | |
31f18b77 | 248 | const watch_notify::Payload &payload); |
7c673cae FG |
249 | |
250 | void handle_notify(uint64_t notify_id, uint64_t handle, | |
251 | uint64_t notifier_id, bufferlist &bl) override; | |
252 | void handle_error(uint64_t cookie, int err) override; | |
253 | void handle_rewatch_complete(int r) override; | |
254 | ||
255 | void send_notify(const watch_notify::Payload& payload, | |
256 | Context *ctx = nullptr); | |
257 | ||
258 | }; | |
259 | ||
260 | } // namespace librbd | |
261 | ||
262 | extern template class librbd::ImageWatcher<librbd::ImageCtx>; | |
263 | ||
264 | #endif // CEPH_LIBRBD_IMAGE_WATCHER_H |