Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / ImageWatcher.h
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_IMAGE_WATCHER_H
5 #define CEPH_LIBRBD_IMAGE_WATCHER_H
6
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"
14 #include <set>
15 #include <string>
16 #include <utility>
17
18 class entity_name_t;
19
20 namespace librbd {
21
22 namespace watcher {
23 namespace util {
24 template <typename> struct HandlePayloadVisitor;
25 }
26 }
27
28 class ImageCtx;
29 template <typename> class TaskFinisher;
30
31 template <typename ImageCtxT = ImageCtx>
32 class ImageWatcher : public Watcher {
33   friend struct watcher::util::HandlePayloadVisitor<ImageWatcher<ImageCtxT>>;
34
35 public:
36   ImageWatcher(ImageCtxT& image_ctx);
37   ~ImageWatcher() override;
38
39   void unregister_watch(Context *on_finish) override;
40   void block_notifies(Context *on_finish) override;
41
42   void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx,
43                       Context *on_finish);
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,
48                           Context *on_finish);
49   void notify_snap_rename(const snapid_t &src_snap_id,
50                           const std::string &dst_snap_name,
51                           Context *on_finish);
52   void notify_snap_remove(const cls::rbd::SnapshotNamespace &snap_namespace,
53                           const std::string &snap_name,
54                           Context *on_finish);
55   void notify_snap_protect(const cls::rbd::SnapshotNamespace &snap_namespace,
56                            const std::string &snap_name,
57                            Context *on_finish);
58   void notify_snap_unprotect(const cls::rbd::SnapshotNamespace &snap_namespace,
59                              const std::string &snap_name,
60                              Context *on_finish);
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);
64
65   void notify_update_features(uint64_t features, bool enabled,
66                               Context *on_finish);
67
68   void notify_acquired_lock();
69   void notify_released_lock();
70   void notify_request_lock();
71
72   void notify_header_update(Context *on_finish);
73   static void notify_header_update(librados::IoCtx &io_ctx,
74                                    const std::string &oid);
75
76 private:
77   enum TaskCode {
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
83   };
84
85   typedef std::pair<Context *, ProgressContext *> AsyncRequest;
86
87   class Task {
88   public:
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) {}
92
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;
100       }
101       return false;
102     }
103   private:
104     TaskCode m_task_code;
105     watch_notify::AsyncRequestId m_async_request_id;
106   };
107
108   class RemoteProgressContext : public ProgressContext {
109   public:
110     RemoteProgressContext(ImageWatcher &image_watcher,
111                           const watch_notify::AsyncRequestId &id)
112       : m_image_watcher(image_watcher), m_async_request_id(id)
113     {
114     }
115
116     int update_progress(uint64_t offset, uint64_t total) override {
117       m_image_watcher.schedule_async_progress(m_async_request_id, offset,
118                                               total);
119       return 0;
120     }
121
122   private:
123     ImageWatcher &m_image_watcher;
124     watch_notify::AsyncRequestId m_async_request_id;
125   };
126
127   class RemoteContext : public Context {
128   public:
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),
133         m_prog_ctx(prog_ctx)
134     {
135     }
136
137     ~RemoteContext() override {
138       delete m_prog_ctx;
139     }
140
141     void finish(int r) override;
142
143   private:
144     ImageWatcher &m_image_watcher;
145     watch_notify::AsyncRequestId m_async_request_id;
146     ProgressContext *m_prog_ctx;
147   };
148
149   struct C_ProcessPayload;
150   struct C_ResponseMessage : public Context {
151     C_NotifyAck *notify_ack;
152
153     C_ResponseMessage(C_NotifyAck *notify_ack) : notify_ack(notify_ack) {
154     }
155     void finish(int r) override;
156   };
157
158   ImageCtxT &m_image_ctx;
159
160   TaskFinisher<Task> *m_task_finisher;
161
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;
165
166   Mutex m_owner_client_id_lock;
167   watch_notify::ClientId m_owner_client_id;
168
169   void handle_register_watch(int r);
170
171   void schedule_cancel_async_requests();
172   void cancel_async_requests();
173
174   void set_owner_client_id(const watch_notify::ClientId &client_id);
175   watch_notify::ClientId get_client_id();
176
177   void handle_request_lock(int r);
178   void schedule_request_lock(bool use_timer, int timer_delay = -1);
179
180   void notify_lock_owner(const watch_notify::Payload& payload,
181                          Context *on_finish);
182
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,
189                             Context *on_finish);
190
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,
198                              int ret_val);
199
200   int prepare_async_request(const watch_notify::AsyncRequestId& id,
201                             bool* new_request, Context** ctx,
202                             ProgressContext** prog_ctx);
203
204   bool handle_payload(const watch_notify::HeaderUpdatePayload& payload,
205                       C_NotifyAck *ctx);
206   bool handle_payload(const watch_notify::AcquiredLockPayload& payload,
207                       C_NotifyAck *ctx);
208   bool handle_payload(const watch_notify::ReleasedLockPayload& payload,
209                       C_NotifyAck *ctx);
210   bool handle_payload(const watch_notify::RequestLockPayload& payload,
211                       C_NotifyAck *ctx);
212   bool handle_payload(const watch_notify::AsyncProgressPayload& payload,
213                       C_NotifyAck *ctx);
214   bool handle_payload(const watch_notify::AsyncCompletePayload& payload,
215                       C_NotifyAck *ctx);
216   bool handle_payload(const watch_notify::FlattenPayload& payload,
217                       C_NotifyAck *ctx);
218   bool handle_payload(const watch_notify::ResizePayload& payload,
219                       C_NotifyAck *ctx);
220   bool handle_payload(const watch_notify::SnapCreatePayload& payload,
221                       C_NotifyAck *ctx);
222   bool handle_payload(const watch_notify::SnapRenamePayload& payload,
223                       C_NotifyAck *ctx);
224   bool handle_payload(const watch_notify::SnapRemovePayload& payload,
225                       C_NotifyAck *ctx);
226   bool handle_payload(const watch_notify::SnapProtectPayload& payload,
227                       C_NotifyAck *ctx);
228   bool handle_payload(const watch_notify::SnapUnprotectPayload& payload,
229                       C_NotifyAck *ctx);
230   bool handle_payload(const watch_notify::RebuildObjectMapPayload& payload,
231                       C_NotifyAck *ctx);
232   bool handle_payload(const watch_notify::RenamePayload& payload,
233                       C_NotifyAck *ctx);
234   bool handle_payload(const watch_notify::UpdateFeaturesPayload& payload,
235                       C_NotifyAck *ctx);
236   bool handle_payload(const watch_notify::UnknownPayload& payload,
237                       C_NotifyAck *ctx);
238   void process_payload(uint64_t notify_id, uint64_t handle,
239                        const watch_notify::Payload &payload);
240
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;
245
246   void send_notify(const watch_notify::Payload& payload,
247                    Context *ctx = nullptr);
248
249 };
250
251 } // namespace librbd
252
253 extern template class librbd::ImageWatcher<librbd::ImageCtx>;
254
255 #endif // CEPH_LIBRBD_IMAGE_WATCHER_H