1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_LIBRBD_IMAGE_WATCHER_H
5 #define CEPH_LIBRBD_IMAGE_WATCHER_H
7 #include "cls/rbd/cls_rbd_types.h"
8 #include "common/Mutex.h"
9 #include "common/RWLock.h"
10 #include "include/Context.h"
11 #include "include/rbd/librbd.hpp"
12 #include "librbd/Watcher.h"
13 #include "librbd/WatchNotifyTypes.h"
24 template <typename> struct HandlePayloadVisitor;
29 template <typename> class TaskFinisher;
31 template <typename ImageCtxT = ImageCtx>
32 class ImageWatcher : public Watcher {
33 friend struct watcher::util::HandlePayloadVisitor<ImageWatcher<ImageCtxT>>;
36 ImageWatcher(ImageCtxT& image_ctx);
37 ~ImageWatcher() override;
39 void unregister_watch(Context *on_finish) override;
40 void block_notifies(Context *on_finish) override;
42 void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx,
44 void notify_resize(uint64_t request_id, uint64_t size, bool allow_shrink,
45 ProgressContext &prog_ctx, Context *on_finish);
46 void notify_snap_create(const cls::rbd::SnapshotNamespace &snap_namespace,
47 const std::string &snap_name,
49 void notify_snap_rename(const snapid_t &src_snap_id,
50 const std::string &dst_snap_name,
52 void notify_snap_remove(const cls::rbd::SnapshotNamespace &snap_namespace,
53 const std::string &snap_name,
55 void notify_snap_protect(const cls::rbd::SnapshotNamespace &snap_namespace,
56 const std::string &snap_name,
58 void notify_snap_unprotect(const cls::rbd::SnapshotNamespace &snap_namespace,
59 const std::string &snap_name,
61 void notify_rebuild_object_map(uint64_t request_id,
62 ProgressContext &prog_ctx, Context *on_finish);
63 void notify_rename(const std::string &image_name, Context *on_finish);
65 void notify_update_features(uint64_t features, bool enabled,
68 void notify_acquired_lock();
69 void notify_released_lock();
70 void notify_request_lock();
72 void notify_header_update(Context *on_finish);
73 static void notify_header_update(librados::IoCtx &io_ctx,
74 const std::string &oid);
78 TASK_CODE_REQUEST_LOCK,
79 TASK_CODE_CANCEL_ASYNC_REQUESTS,
80 TASK_CODE_REREGISTER_WATCH,
81 TASK_CODE_ASYNC_REQUEST,
82 TASK_CODE_ASYNC_PROGRESS
85 typedef std::pair<Context *, ProgressContext *> AsyncRequest;
89 Task(TaskCode task_code) : m_task_code(task_code) {}
90 Task(TaskCode task_code, const watch_notify::AsyncRequestId &id)
91 : m_task_code(task_code), m_async_request_id(id) {}
93 inline bool operator<(const Task& rhs) const {
94 if (m_task_code != rhs.m_task_code) {
95 return m_task_code < rhs.m_task_code;
96 } else if ((m_task_code == TASK_CODE_ASYNC_REQUEST ||
97 m_task_code == TASK_CODE_ASYNC_PROGRESS) &&
98 m_async_request_id != rhs.m_async_request_id) {
99 return m_async_request_id < rhs.m_async_request_id;
104 TaskCode m_task_code;
105 watch_notify::AsyncRequestId m_async_request_id;
108 class RemoteProgressContext : public ProgressContext {
110 RemoteProgressContext(ImageWatcher &image_watcher,
111 const watch_notify::AsyncRequestId &id)
112 : m_image_watcher(image_watcher), m_async_request_id(id)
116 int update_progress(uint64_t offset, uint64_t total) override {
117 m_image_watcher.schedule_async_progress(m_async_request_id, offset,
123 ImageWatcher &m_image_watcher;
124 watch_notify::AsyncRequestId m_async_request_id;
127 class RemoteContext : public Context {
129 RemoteContext(ImageWatcher &image_watcher,
130 const watch_notify::AsyncRequestId &id,
131 ProgressContext *prog_ctx)
132 : m_image_watcher(image_watcher), m_async_request_id(id),
137 ~RemoteContext() override {
141 void finish(int r) override;
144 ImageWatcher &m_image_watcher;
145 watch_notify::AsyncRequestId m_async_request_id;
146 ProgressContext *m_prog_ctx;
149 struct C_ProcessPayload;
150 struct C_ResponseMessage : public Context {
151 C_NotifyAck *notify_ack;
153 C_ResponseMessage(C_NotifyAck *notify_ack) : notify_ack(notify_ack) {
155 void finish(int r) override;
158 ImageCtxT &m_image_ctx;
160 TaskFinisher<Task> *m_task_finisher;
162 RWLock m_async_request_lock;
163 std::map<watch_notify::AsyncRequestId, AsyncRequest> m_async_requests;
164 std::set<watch_notify::AsyncRequestId> m_async_pending;
166 Mutex m_owner_client_id_lock;
167 watch_notify::ClientId m_owner_client_id;
169 void handle_register_watch(int r);
171 void schedule_cancel_async_requests();
172 void cancel_async_requests();
174 void set_owner_client_id(const watch_notify::ClientId &client_id);
175 watch_notify::ClientId get_client_id();
177 void handle_request_lock(int r);
178 void schedule_request_lock(bool use_timer, int timer_delay = -1);
180 void notify_lock_owner(const watch_notify::Payload& payload,
183 Context *remove_async_request(const watch_notify::AsyncRequestId &id);
184 void schedule_async_request_timed_out(const watch_notify::AsyncRequestId &id);
185 void async_request_timed_out(const watch_notify::AsyncRequestId &id);
186 void notify_async_request(const watch_notify::AsyncRequestId &id,
187 const watch_notify::Payload &payload,
188 ProgressContext& prog_ctx,
191 void schedule_async_progress(const watch_notify::AsyncRequestId &id,
192 uint64_t offset, uint64_t total);
193 int notify_async_progress(const watch_notify::AsyncRequestId &id,
194 uint64_t offset, uint64_t total);
195 void schedule_async_complete(const watch_notify::AsyncRequestId &id, int r);
196 void notify_async_complete(const watch_notify::AsyncRequestId &id, int r);
197 void handle_async_complete(const watch_notify::AsyncRequestId &request, int r,
200 int prepare_async_request(const watch_notify::AsyncRequestId& id,
201 bool* new_request, Context** ctx,
202 ProgressContext** prog_ctx);
204 bool handle_payload(const watch_notify::HeaderUpdatePayload& payload,
206 bool handle_payload(const watch_notify::AcquiredLockPayload& payload,
208 bool handle_payload(const watch_notify::ReleasedLockPayload& payload,
210 bool handle_payload(const watch_notify::RequestLockPayload& payload,
212 bool handle_payload(const watch_notify::AsyncProgressPayload& payload,
214 bool handle_payload(const watch_notify::AsyncCompletePayload& payload,
216 bool handle_payload(const watch_notify::FlattenPayload& payload,
218 bool handle_payload(const watch_notify::ResizePayload& payload,
220 bool handle_payload(const watch_notify::SnapCreatePayload& payload,
222 bool handle_payload(const watch_notify::SnapRenamePayload& payload,
224 bool handle_payload(const watch_notify::SnapRemovePayload& payload,
226 bool handle_payload(const watch_notify::SnapProtectPayload& payload,
228 bool handle_payload(const watch_notify::SnapUnprotectPayload& payload,
230 bool handle_payload(const watch_notify::RebuildObjectMapPayload& payload,
232 bool handle_payload(const watch_notify::RenamePayload& payload,
234 bool handle_payload(const watch_notify::UpdateFeaturesPayload& payload,
236 bool handle_payload(const watch_notify::UnknownPayload& payload,
238 void process_payload(uint64_t notify_id, uint64_t handle,
239 const watch_notify::Payload &payload);
241 void handle_notify(uint64_t notify_id, uint64_t handle,
242 uint64_t notifier_id, bufferlist &bl) override;
243 void handle_error(uint64_t cookie, int err) override;
244 void handle_rewatch_complete(int r) override;
246 void send_notify(const watch_notify::Payload& payload,
247 Context *ctx = nullptr);
251 } // namespace librbd
253 extern template class librbd::ImageWatcher<librbd::ImageCtx>;
255 #endif // CEPH_LIBRBD_IMAGE_WATCHER_H