]>
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_WATCHER_H | |
5 | #define CEPH_LIBRBD_WATCHER_H | |
6 | ||
31f18b77 | 7 | #include "common/AsyncOpTracker.h" |
9f95a23c | 8 | #include "common/ceph_mutex.h" |
7c673cae FG |
9 | #include "common/RWLock.h" |
10 | #include "include/rados/librados.hpp" | |
11 | #include "librbd/watcher/Notifier.h" | |
12 | #include "librbd/watcher/Types.h" | |
13 | #include <string> | |
14 | #include <utility> | |
15 | ||
7c673cae FG |
16 | namespace librbd { |
17 | ||
f67539c2 | 18 | namespace asio { struct ContextWQ; } |
7c673cae FG |
19 | namespace watcher { struct NotifyResponse; } |
20 | ||
21 | class Watcher { | |
22 | public: | |
23 | struct C_NotifyAck : public Context { | |
24 | Watcher *watcher; | |
25 | CephContext *cct; | |
26 | uint64_t notify_id; | |
27 | uint64_t handle; | |
28 | bufferlist out; | |
29 | ||
30 | C_NotifyAck(Watcher *watcher, uint64_t notify_id, uint64_t handle); | |
31 | void finish(int r) override; | |
32 | }; | |
33 | ||
f67539c2 | 34 | Watcher(librados::IoCtx& ioctx, asio::ContextWQ *work_queue, |
7c673cae FG |
35 | const std::string& oid); |
36 | virtual ~Watcher(); | |
37 | ||
38 | void register_watch(Context *on_finish); | |
31f18b77 | 39 | virtual void unregister_watch(Context *on_finish); |
7c673cae FG |
40 | void flush(Context *on_finish); |
41 | ||
31f18b77 FG |
42 | bool notifications_blocked() const; |
43 | virtual void block_notifies(Context *on_finish); | |
44 | void unblock_notifies(); | |
45 | ||
7c673cae FG |
46 | std::string get_oid() const; |
47 | void set_oid(const string& oid); | |
48 | ||
49 | uint64_t get_watch_handle() const { | |
9f95a23c | 50 | std::shared_lock watch_locker{m_watch_lock}; |
7c673cae FG |
51 | return m_watch_handle; |
52 | } | |
53 | ||
54 | bool is_registered() const { | |
9f95a23c | 55 | std::shared_lock locker{m_watch_lock}; |
28e407b8 | 56 | return is_registered(m_watch_lock); |
7c673cae FG |
57 | } |
58 | bool is_unregistered() const { | |
9f95a23c | 59 | std::shared_lock locker{m_watch_lock}; |
28e407b8 | 60 | return is_unregistered(m_watch_lock); |
7c673cae | 61 | } |
f67539c2 | 62 | bool is_blocklisted() const { |
9f95a23c | 63 | std::shared_lock locker{m_watch_lock}; |
f67539c2 | 64 | return m_watch_blocklisted; |
91327a77 | 65 | } |
7c673cae FG |
66 | |
67 | protected: | |
68 | enum WatchState { | |
28e407b8 | 69 | WATCH_STATE_IDLE, |
7c673cae | 70 | WATCH_STATE_REGISTERING, |
7c673cae FG |
71 | WATCH_STATE_REWATCHING |
72 | }; | |
73 | ||
74 | librados::IoCtx& m_ioctx; | |
f67539c2 | 75 | asio::ContextWQ *m_work_queue; |
7c673cae FG |
76 | std::string m_oid; |
77 | CephContext *m_cct; | |
9f95a23c | 78 | mutable ceph::shared_mutex m_watch_lock; |
7c673cae FG |
79 | uint64_t m_watch_handle; |
80 | watcher::Notifier m_notifier; | |
91327a77 | 81 | |
7c673cae | 82 | WatchState m_watch_state; |
f67539c2 | 83 | bool m_watch_blocklisted = false; |
91327a77 | 84 | |
31f18b77 | 85 | AsyncOpTracker m_async_op_tracker; |
7c673cae | 86 | |
9f95a23c | 87 | bool is_registered(const ceph::shared_mutex&) const { |
28e407b8 AA |
88 | return (m_watch_state == WATCH_STATE_IDLE && m_watch_handle != 0); |
89 | } | |
9f95a23c | 90 | bool is_unregistered(const ceph::shared_mutex&) const { |
28e407b8 AA |
91 | return (m_watch_state == WATCH_STATE_IDLE && m_watch_handle == 0); |
92 | } | |
93 | ||
7c673cae FG |
94 | void send_notify(bufferlist &payload, |
95 | watcher::NotifyResponse *response = nullptr, | |
96 | Context *on_finish = nullptr); | |
97 | ||
98 | virtual void handle_notify(uint64_t notify_id, uint64_t handle, | |
99 | uint64_t notifier_id, bufferlist &bl) = 0; | |
100 | ||
101 | virtual void handle_error(uint64_t cookie, int err); | |
102 | ||
103 | void acknowledge_notify(uint64_t notify_id, uint64_t handle, | |
104 | bufferlist &out); | |
105 | ||
106 | virtual void handle_rewatch_complete(int r) { } | |
107 | ||
108 | private: | |
109 | /** | |
110 | * @verbatim | |
111 | * | |
112 | * <start> | |
113 | * | | |
114 | * v | |
115 | * UNREGISTERED | |
116 | * | | |
117 | * | (register_watch) | |
118 | * | | |
119 | * REGISTERING | |
120 | * | | |
121 | * v (watch error) | |
122 | * REGISTERED * * * * * * * > ERROR | |
123 | * | ^ | | |
124 | * | | | (rewatch) | |
125 | * | | v | |
126 | * | | REWATCHING | |
127 | * | | | | |
128 | * | | | | |
129 | * | \---------------------/ | |
130 | * | | |
131 | * | (unregister_watch) | |
132 | * | | |
133 | * v | |
134 | * UNREGISTERED | |
135 | * | | |
136 | * v | |
137 | * <finish> | |
138 | * | |
139 | * @endverbatim | |
140 | */ | |
141 | ||
142 | struct WatchCtx : public librados::WatchCtx2 { | |
143 | Watcher &watcher; | |
144 | ||
145 | WatchCtx(Watcher &parent) : watcher(parent) {} | |
146 | ||
147 | void handle_notify(uint64_t notify_id, | |
148 | uint64_t handle, | |
149 | uint64_t notifier_id, | |
150 | bufferlist& bl) override; | |
151 | void handle_error(uint64_t handle, int err) override; | |
152 | }; | |
153 | ||
154 | struct C_RegisterWatch : public Context { | |
155 | Watcher *watcher; | |
156 | Context *on_finish; | |
157 | ||
158 | C_RegisterWatch(Watcher *watcher, Context *on_finish) | |
159 | : watcher(watcher), on_finish(on_finish) { | |
160 | } | |
161 | void finish(int r) override { | |
162 | watcher->handle_register_watch(r, on_finish); | |
163 | } | |
164 | }; | |
165 | ||
166 | WatchCtx m_watch_ctx; | |
167 | Context *m_unregister_watch_ctx = nullptr; | |
168 | ||
28e407b8 AA |
169 | bool m_watch_error = false; |
170 | ||
31f18b77 FG |
171 | uint32_t m_blocked_count = 0; |
172 | ||
7c673cae FG |
173 | void handle_register_watch(int r, Context *on_finish); |
174 | ||
175 | void rewatch(); | |
176 | void handle_rewatch(int r); | |
28e407b8 | 177 | void handle_rewatch_callback(int r); |
7c673cae FG |
178 | |
179 | }; | |
180 | ||
181 | } // namespace librbd | |
182 | ||
183 | #endif // CEPH_LIBRBD_WATCHER_H |