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
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"
20 template <typename
> class ManagedLock
;
27 template <typename
> class InstanceReplayer
;
28 template <typename
> struct Threads
;
30 template <typename ImageCtxT
= librbd::ImageCtx
>
31 class InstanceWatcher
: protected librbd::Watcher
{
33 static void get_instances(librados::IoCtx
&io_ctx
,
34 std::vector
<std::string
> *instance_ids
,
36 static void remove_instance(librados::IoCtx
&io_ctx
,
37 ContextWQ
*work_queue
,
38 const std::string
&instance_id
,
41 static InstanceWatcher
*create(
42 librados::IoCtx
&io_ctx
, ContextWQ
*work_queue
,
43 InstanceReplayer
<ImageCtxT
> *instance_replayer
);
48 InstanceWatcher(librados::IoCtx
&io_ctx
, ContextWQ
*work_queue
,
49 InstanceReplayer
<ImageCtxT
> *instance_replayer
,
50 const std::string
&instance_id
);
51 ~InstanceWatcher() override
;
53 inline std::string
&get_instance_id() {
60 void init(Context
*on_finish
);
61 void shut_down(Context
*on_finish
);
62 void remove(Context
*on_finish
);
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
);
75 void cancel_notify_requests(const std::string
&instance_id
);
81 * BREAK_INSTANCE_LOCK -------\
84 * GET_INSTANCE_LOCKER * * *>|
87 * <uninitialized> <----------------+---- WAIT_FOR_NOTIFY_OPS
90 * REGISTER_INSTANCE * * * * * *|* *> UNREGISTER_INSTANCE
93 * CREATE_INSTANCE_OBJECT * * * * * *> REMOVE_INSTANCE_OBJECT
96 * REGISTER_WATCH * * * * * * * * * *> UNREGISTER_WATCH
99 * ACQUIRE_LOCK * * * * * * * * * * * RELEASE_LOCK
102 * <watching> -------------------------------/
107 struct C_NotifyInstanceRequest
;
109 struct HandlePayloadVisitor
: public boost::static_visitor
<void> {
110 InstanceWatcher
*instance_watcher
;
111 std::string instance_id
;
112 C_NotifyAck
*on_notify_ack
;
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
) {
121 template <typename Payload
>
122 inline void operator()(const Payload
&payload
) const {
123 instance_watcher
->handle_payload(instance_id
, payload
, on_notify_ack
);
128 std::string instance_id
;
130 C_NotifyAck
*on_notify_ack
= nullptr;
132 Request(const std::string
&instance_id
, uint64_t request_id
)
133 : instance_id(instance_id
), request_id(request_id
) {
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
);
142 Threads
<ImageCtxT
> *m_threads
;
143 InstanceReplayer
<ImageCtxT
> *m_instance_replayer
;
144 std::string m_instance_id
;
146 mutable Mutex m_lock
;
147 librbd::ManagedLock
<ImageCtxT
> *m_instance_lock
;
148 Context
*m_on_finish
= nullptr;
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
;
157 void register_instance();
158 void handle_register_instance(int r
);
160 void create_instance_object();
161 void handle_create_instance_object(int r
);
163 void register_watch();
164 void handle_register_watch(int r
);
167 void handle_acquire_lock(int r
);
170 void handle_release_lock(int r
);
172 void unregister_watch();
173 void handle_unregister_watch(int r
);
175 void remove_instance_object();
176 void handle_remove_instance_object(int r
);
178 void unregister_instance();
179 void handle_unregister_instance(int r
);
181 void wait_for_notify_ops();
182 void handle_wait_for_notify_ops(int r
);
184 void get_instance_locker();
185 void handle_get_instance_locker(int r
);
187 void break_instance_lock();
188 void handle_break_instance_lock(int r
);
190 Context
*prepare_request(const std::string
&instance_id
, uint64_t request_id
,
191 C_NotifyAck
*on_notify_ack
);
193 void handle_notify(uint64_t notify_id
, uint64_t handle
,
194 uint64_t notifier_id
, bufferlist
&bl
) override
;
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
,
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
);
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
);
216 } // namespace mirror
219 #endif // CEPH_RBD_MIRROR_INSTANCE_WATCHER_H