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/AsyncOpTracker.h"
9 #include "common/ceph_mutex.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_migrate(uint64_t request_id
, ProgressContext
&prog_ctx
,
71 void notify_sparsify(uint64_t request_id
, size_t sparse_size
,
72 ProgressContext
&prog_ctx
, Context
*on_finish
);
74 void notify_acquired_lock();
75 void notify_released_lock();
76 void notify_request_lock();
78 void notify_header_update(Context
*on_finish
);
79 static void notify_header_update(librados::IoCtx
&io_ctx
,
80 const std::string
&oid
);
84 TASK_CODE_REQUEST_LOCK
,
85 TASK_CODE_CANCEL_ASYNC_REQUESTS
,
86 TASK_CODE_REREGISTER_WATCH
,
87 TASK_CODE_ASYNC_REQUEST
,
88 TASK_CODE_ASYNC_PROGRESS
91 typedef std::pair
<Context
*, ProgressContext
*> AsyncRequest
;
95 Task(TaskCode task_code
) : m_task_code(task_code
) {}
96 Task(TaskCode task_code
, const watch_notify::AsyncRequestId
&id
)
97 : m_task_code(task_code
), m_async_request_id(id
) {}
99 inline bool operator<(const Task
& rhs
) const {
100 if (m_task_code
!= rhs
.m_task_code
) {
101 return m_task_code
< rhs
.m_task_code
;
102 } else if ((m_task_code
== TASK_CODE_ASYNC_REQUEST
||
103 m_task_code
== TASK_CODE_ASYNC_PROGRESS
) &&
104 m_async_request_id
!= rhs
.m_async_request_id
) {
105 return m_async_request_id
< rhs
.m_async_request_id
;
110 TaskCode m_task_code
;
111 watch_notify::AsyncRequestId m_async_request_id
;
114 class RemoteProgressContext
: public ProgressContext
{
116 RemoteProgressContext(ImageWatcher
&image_watcher
,
117 const watch_notify::AsyncRequestId
&id
)
118 : m_image_watcher(image_watcher
), m_async_request_id(id
)
122 int update_progress(uint64_t offset
, uint64_t total
) override
{
123 m_image_watcher
.schedule_async_progress(m_async_request_id
, offset
,
129 ImageWatcher
&m_image_watcher
;
130 watch_notify::AsyncRequestId m_async_request_id
;
133 class RemoteContext
: public Context
{
135 RemoteContext(ImageWatcher
&image_watcher
,
136 const watch_notify::AsyncRequestId
&id
,
137 ProgressContext
*prog_ctx
)
138 : m_image_watcher(image_watcher
), m_async_request_id(id
),
143 ~RemoteContext() override
{
147 void finish(int r
) override
;
150 ImageWatcher
&m_image_watcher
;
151 watch_notify::AsyncRequestId m_async_request_id
;
152 ProgressContext
*m_prog_ctx
;
155 struct C_ProcessPayload
;
156 struct C_ResponseMessage
: public Context
{
157 C_NotifyAck
*notify_ack
;
159 C_ResponseMessage(C_NotifyAck
*notify_ack
) : notify_ack(notify_ack
) {
161 void finish(int r
) override
;
164 ImageCtxT
&m_image_ctx
;
166 TaskFinisher
<Task
> *m_task_finisher
;
168 ceph::shared_mutex m_async_request_lock
;
169 std::map
<watch_notify::AsyncRequestId
, AsyncRequest
> m_async_requests
;
170 std::set
<watch_notify::AsyncRequestId
> m_async_pending
;
172 ceph::mutex m_owner_client_id_lock
;
173 watch_notify::ClientId m_owner_client_id
;
175 AsyncOpTracker m_async_op_tracker
;
177 void handle_register_watch(int r
);
179 void schedule_cancel_async_requests();
180 void cancel_async_requests();
182 void set_owner_client_id(const watch_notify::ClientId
&client_id
);
183 watch_notify::ClientId
get_client_id();
185 void handle_request_lock(int r
);
186 void schedule_request_lock(bool use_timer
, int timer_delay
= -1);
188 void notify_lock_owner(const watch_notify::Payload
& payload
,
191 Context
*remove_async_request(const watch_notify::AsyncRequestId
&id
);
192 void schedule_async_request_timed_out(const watch_notify::AsyncRequestId
&id
);
193 void async_request_timed_out(const watch_notify::AsyncRequestId
&id
);
194 void notify_async_request(const watch_notify::AsyncRequestId
&id
,
195 const watch_notify::Payload
&payload
,
196 ProgressContext
& prog_ctx
,
199 void schedule_async_progress(const watch_notify::AsyncRequestId
&id
,
200 uint64_t offset
, uint64_t total
);
201 int notify_async_progress(const watch_notify::AsyncRequestId
&id
,
202 uint64_t offset
, uint64_t total
);
203 void schedule_async_complete(const watch_notify::AsyncRequestId
&id
, int r
);
204 void notify_async_complete(const watch_notify::AsyncRequestId
&id
, int r
);
205 void handle_async_complete(const watch_notify::AsyncRequestId
&request
, int r
,
208 int prepare_async_request(const watch_notify::AsyncRequestId
& id
,
209 bool* new_request
, Context
** ctx
,
210 ProgressContext
** prog_ctx
);
212 bool handle_payload(const watch_notify::HeaderUpdatePayload
& payload
,
214 bool handle_payload(const watch_notify::AcquiredLockPayload
& payload
,
216 bool handle_payload(const watch_notify::ReleasedLockPayload
& payload
,
218 bool handle_payload(const watch_notify::RequestLockPayload
& payload
,
220 bool handle_payload(const watch_notify::AsyncProgressPayload
& payload
,
222 bool handle_payload(const watch_notify::AsyncCompletePayload
& payload
,
224 bool handle_payload(const watch_notify::FlattenPayload
& payload
,
226 bool handle_payload(const watch_notify::ResizePayload
& payload
,
228 bool handle_payload(const watch_notify::SnapCreatePayload
& payload
,
230 bool handle_payload(const watch_notify::SnapRenamePayload
& payload
,
232 bool handle_payload(const watch_notify::SnapRemovePayload
& payload
,
234 bool handle_payload(const watch_notify::SnapProtectPayload
& payload
,
236 bool handle_payload(const watch_notify::SnapUnprotectPayload
& payload
,
238 bool handle_payload(const watch_notify::RebuildObjectMapPayload
& payload
,
240 bool handle_payload(const watch_notify::RenamePayload
& payload
,
242 bool handle_payload(const watch_notify::UpdateFeaturesPayload
& payload
,
244 bool handle_payload(const watch_notify::MigratePayload
& payload
,
246 bool handle_payload(const watch_notify::SparsifyPayload
& payload
,
248 bool handle_payload(const watch_notify::UnknownPayload
& payload
,
250 void process_payload(uint64_t notify_id
, uint64_t handle
,
251 const watch_notify::Payload
&payload
);
253 void handle_notify(uint64_t notify_id
, uint64_t handle
,
254 uint64_t notifier_id
, bufferlist
&bl
) override
;
255 void handle_error(uint64_t cookie
, int err
) override
;
256 void handle_rewatch_complete(int r
) override
;
258 void send_notify(const watch_notify::Payload
& payload
,
259 Context
*ctx
= nullptr);
263 } // namespace librbd
265 extern template class librbd::ImageWatcher
<librbd::ImageCtx
>;
267 #endif // CEPH_LIBRBD_IMAGE_WATCHER_H