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_WATCHER_H
5 #define CEPH_LIBRBD_WATCHER_H
7 #include "common/AsyncOpTracker.h"
8 #include "common/ceph_mutex.h"
9 #include "common/RWLock.h"
10 #include "include/rados/librados.hpp"
11 #include "librbd/watcher/Notifier.h"
12 #include "librbd/watcher/Types.h"
18 namespace asio
{ struct ContextWQ
; }
19 namespace watcher
{ struct NotifyResponse
; }
23 struct C_NotifyAck
: public Context
{
30 C_NotifyAck(Watcher
*watcher
, uint64_t notify_id
, uint64_t handle
);
31 void finish(int r
) override
;
34 Watcher(librados::IoCtx
& ioctx
, asio::ContextWQ
*work_queue
,
35 const std::string
& oid
);
38 void register_watch(Context
*on_finish
);
39 virtual void unregister_watch(Context
*on_finish
);
40 void flush(Context
*on_finish
);
42 bool notifications_blocked() const;
43 virtual void block_notifies(Context
*on_finish
);
44 void unblock_notifies();
46 std::string
get_oid() const;
47 void set_oid(const std::string
& oid
);
49 uint64_t get_watch_handle() const {
50 std::shared_lock watch_locker
{m_watch_lock
};
51 return m_watch_handle
;
54 bool is_registered() const {
55 std::shared_lock locker
{m_watch_lock
};
56 return is_registered(m_watch_lock
);
58 bool is_unregistered() const {
59 std::shared_lock locker
{m_watch_lock
};
60 return is_unregistered(m_watch_lock
);
62 bool is_blocklisted() const {
63 std::shared_lock locker
{m_watch_lock
};
64 return m_watch_blocklisted
;
70 WATCH_STATE_REGISTERING
,
71 WATCH_STATE_REWATCHING
74 librados::IoCtx
& m_ioctx
;
75 asio::ContextWQ
*m_work_queue
;
78 mutable ceph::shared_mutex m_watch_lock
;
79 uint64_t m_watch_handle
;
80 watcher::Notifier m_notifier
;
82 WatchState m_watch_state
;
83 bool m_watch_blocklisted
= false;
85 AsyncOpTracker m_async_op_tracker
;
87 bool is_registered(const ceph::shared_mutex
&) const {
88 return (m_watch_state
== WATCH_STATE_IDLE
&& m_watch_handle
!= 0);
90 bool is_unregistered(const ceph::shared_mutex
&) const {
91 return (m_watch_state
== WATCH_STATE_IDLE
&& m_watch_handle
== 0);
94 void send_notify(bufferlist
&payload
,
95 watcher::NotifyResponse
*response
= nullptr,
96 Context
*on_finish
= nullptr);
98 virtual void handle_notify(uint64_t notify_id
, uint64_t handle
,
99 uint64_t notifier_id
, bufferlist
&bl
) = 0;
101 virtual void handle_error(uint64_t cookie
, int err
);
103 void acknowledge_notify(uint64_t notify_id
, uint64_t handle
,
106 virtual void handle_rewatch_complete(int r
) { }
122 * REGISTERED * * * * * * * > ERROR
129 * | \---------------------/
131 * | (unregister_watch)
142 struct WatchCtx
: public librados::WatchCtx2
{
145 WatchCtx(Watcher
&parent
) : watcher(parent
) {}
147 void handle_notify(uint64_t notify_id
,
149 uint64_t notifier_id
,
150 bufferlist
& bl
) override
;
151 void handle_error(uint64_t handle
, int err
) override
;
154 struct C_RegisterWatch
: public Context
{
158 C_RegisterWatch(Watcher
*watcher
, Context
*on_finish
)
159 : watcher(watcher
), on_finish(on_finish
) {
161 void finish(int r
) override
{
162 watcher
->handle_register_watch(r
, on_finish
);
166 WatchCtx m_watch_ctx
;
167 Context
*m_unregister_watch_ctx
= nullptr;
169 bool m_watch_error
= false;
171 uint32_t m_blocked_count
= 0;
173 void handle_register_watch(int r
, Context
*on_finish
);
176 void handle_rewatch(int r
);
177 void handle_rewatch_callback(int r
);
181 } // namespace librbd
183 #endif // CEPH_LIBRBD_WATCHER_H