]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.h
e3c4c20890287a471d0783fcf0c4cf45e0fb5d5e
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / snapshot / Replayer.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 RBD_MIRROR_IMAGE_REPLAYER_SNAPSHOT_REPLAYER_H
5 #define RBD_MIRROR_IMAGE_REPLAYER_SNAPSHOT_REPLAYER_H
6
7 #include "tools/rbd_mirror/image_replayer/Replayer.h"
8 #include "common/ceph_mutex.h"
9 #include "common/AsyncOpTracker.h"
10 #include "cls/rbd/cls_rbd_types.h"
11 #include "librbd/mirror/snapshot/Types.h"
12 #include "tools/rbd_mirror/image_replayer/TimeRollingMean.h"
13 #include <boost/accumulators/accumulators.hpp>
14 #include <boost/accumulators/statistics/stats.hpp>
15 #include <boost/accumulators/statistics/rolling_mean.hpp>
16 #include <string>
17 #include <type_traits>
18
19 namespace librbd {
20
21 struct ImageCtx;
22 namespace snapshot { template <typename I> class Replay; }
23
24 } // namespace librbd
25
26 namespace rbd {
27 namespace mirror {
28
29 template <typename> struct InstanceWatcher;
30 class PoolMetaCache;
31 template <typename> struct Threads;
32
33 namespace image_replayer {
34
35 struct ReplayerListener;
36
37 namespace snapshot {
38
39 template <typename> class EventPreprocessor;
40 template <typename> class ReplayStatusFormatter;
41 template <typename> class StateBuilder;
42
43 template <typename ImageCtxT>
44 class Replayer : public image_replayer::Replayer {
45 public:
46 static Replayer* create(
47 Threads<ImageCtxT>* threads,
48 InstanceWatcher<ImageCtxT>* instance_watcher,
49 const std::string& local_mirror_uuid,
50 PoolMetaCache* pool_meta_cache,
51 StateBuilder<ImageCtxT>* state_builder,
52 ReplayerListener* replayer_listener) {
53 return new Replayer(threads, instance_watcher, local_mirror_uuid,
54 pool_meta_cache, state_builder, replayer_listener);
55 }
56
57 Replayer(
58 Threads<ImageCtxT>* threads,
59 InstanceWatcher<ImageCtxT>* instance_watcher,
60 const std::string& local_mirror_uuid,
61 PoolMetaCache* pool_meta_cache,
62 StateBuilder<ImageCtxT>* state_builder,
63 ReplayerListener* replayer_listener);
64 ~Replayer();
65
66 void destroy() override {
67 delete this;
68 }
69
70 void init(Context* on_finish) override;
71 void shut_down(Context* on_finish) override;
72
73 void flush(Context* on_finish) override;
74
75 bool get_replay_status(std::string* description, Context* on_finish) override;
76
77 bool is_replaying() const override {
78 std::unique_lock locker{m_lock};
79 return (m_state == STATE_REPLAYING || m_state == STATE_IDLE);
80 }
81
82 bool is_resync_requested() const override {
83 std::unique_lock locker{m_lock};
84 return m_resync_requested;
85 }
86
87 int get_error_code() const override {
88 std::unique_lock locker(m_lock);
89 return m_error_code;
90 }
91
92 std::string get_error_description() const override {
93 std::unique_lock locker(m_lock);
94 return m_error_description;
95 }
96
97 std::string get_image_spec() const {
98 std::unique_lock locker(m_lock);
99 return m_image_spec;
100 }
101
102 private:
103 /**
104 * @verbatim
105 *
106 * <init>
107 * |
108 * v
109 * REGISTER_LOCAL_UPDATE_WATCHER
110 * |
111 * v
112 * REGISTER_REMOTE_UPDATE_WATCHER
113 * |
114 * v
115 * LOAD_LOCAL_IMAGE_META <----------------------------\
116 * | |
117 * v (skip if not needed) |
118 * REFRESH_LOCAL_IMAGE |
119 * | |
120 * v (skip if not needed) |
121 * REFRESH_REMOTE_IMAGE |
122 * | |
123 * | (unused non-primary snapshot) |
124 * |\--------------> PRUNE_NON_PRIMARY_SNAPSHOT---/|
125 * | |
126 * | (interrupted sync) |
127 * |\--------------> GET_LOCAL_IMAGE_STATE ------\ |
128 * | | |
129 * | (new snapshot) | |
130 * |\--------------> COPY_SNAPSHOTS | |
131 * | | | |
132 * | v | |
133 * | GET_REMOTE_IMAGE_STATE | |
134 * | | | |
135 * | v | |
136 * | CREATE_NON_PRIMARY_SNAPSHOT | |
137 * | | | |
138 * | v (skip if not needed)| |
139 * | UPDATE_MIRROR_IMAGE_STATE | |
140 * | | | |
141 * | |/--------------------/ |
142 * | | |
143 * | v |
144 * | REQUEST_SYNC |
145 * | | |
146 * | v |
147 * | COPY_IMAGE |
148 * | | |
149 * | v |
150 * | APPLY_IMAGE_STATE |
151 * | | |
152 * | v |
153 * | UPDATE_NON_PRIMARY_SNAPSHOT |
154 * | | |
155 * | v |
156 * | NOTIFY_IMAGE_UPDATE |
157 * | | |
158 * | (interrupted unlink) v |
159 * |\--------------> UNLINK_PEER |
160 * | | |
161 * | v |
162 * | NOTIFY_LISTENER |
163 * | | |
164 * | \----------------------/|
165 * | |
166 * | (remote demoted) |
167 * \---------------> NOTIFY_LISTENER |
168 * | | |
169 * |/--------------------/ |
170 * | |
171 * | (update notification) |
172 * <idle> --------------------------------------------/
173 * |
174 * v
175 * <shut down>
176 * |
177 * v
178 * UNREGISTER_REMOTE_UPDATE_WATCHER
179 * |
180 * v
181 * UNREGISTER_LOCAL_UPDATE_WATCHER
182 * |
183 * v
184 * WAIT_FOR_IN_FLIGHT_OPS
185 * |
186 * v
187 * <finish>
188 *
189 * @endverbatim
190 */
191
192 enum State {
193 STATE_INIT,
194 STATE_REPLAYING,
195 STATE_IDLE,
196 STATE_COMPLETE
197 };
198
199 struct C_UpdateWatchCtx;
200 struct DeepCopyHandler;
201
202 Threads<ImageCtxT>* m_threads;
203 InstanceWatcher<ImageCtxT>* m_instance_watcher;
204 std::string m_local_mirror_uuid;
205 PoolMetaCache* m_pool_meta_cache;
206 StateBuilder<ImageCtxT>* m_state_builder;
207 ReplayerListener* m_replayer_listener;
208
209 mutable ceph::mutex m_lock;
210
211 State m_state = STATE_INIT;
212
213 std::string m_image_spec;
214 Context* m_on_init_shutdown = nullptr;
215
216 bool m_resync_requested = false;
217 int m_error_code = 0;
218 std::string m_error_description;
219
220 C_UpdateWatchCtx* m_update_watch_ctx = nullptr;
221 uint64_t m_local_update_watcher_handle = 0;
222 uint64_t m_remote_update_watcher_handle = 0;
223 bool m_image_updated = false;
224
225 AsyncOpTracker m_in_flight_op_tracker;
226
227 uint64_t m_local_snap_id_start = 0;
228 uint64_t m_local_snap_id_end = CEPH_NOSNAP;
229 cls::rbd::MirrorSnapshotNamespace m_local_mirror_snap_ns;
230 uint64_t m_local_object_count = 0;
231
232 std::string m_remote_mirror_peer_uuid;
233 uint64_t m_remote_snap_id_start = 0;
234 uint64_t m_remote_snap_id_end = CEPH_NOSNAP;
235 cls::rbd::MirrorSnapshotNamespace m_remote_mirror_snap_ns;
236
237 librbd::mirror::snapshot::ImageState m_image_state;
238 DeepCopyHandler* m_deep_copy_handler = nullptr;
239
240 TimeRollingMean m_bytes_per_second;
241
242 uint64_t m_snapshot_bytes = 0;
243 boost::accumulators::accumulator_set<
244 uint64_t, boost::accumulators::stats<
245 boost::accumulators::tag::rolling_mean>> m_bytes_per_snapshot{
246 boost::accumulators::tag::rolling_window::window_size = 2};
247 utime_t m_snapshot_replay_start;
248
249 uint32_t m_pending_snapshots = 0;
250
251 bool m_remote_image_updated = false;
252 bool m_updating_sync_point = false;
253 bool m_sync_in_progress = false;
254
255 PerfCounters *m_perf_counters = nullptr;
256
257 void load_local_image_meta();
258 void handle_load_local_image_meta(int r);
259
260 void refresh_local_image();
261 void handle_refresh_local_image(int r);
262
263 void refresh_remote_image();
264 void handle_refresh_remote_image(int r);
265
266 void scan_local_mirror_snapshots(std::unique_lock<ceph::mutex>* locker);
267 void scan_remote_mirror_snapshots(std::unique_lock<ceph::mutex>* locker);
268
269 void prune_non_primary_snapshot(uint64_t snap_id);
270 void handle_prune_non_primary_snapshot(int r);
271
272 void copy_snapshots();
273 void handle_copy_snapshots(int r);
274
275 void get_remote_image_state();
276 void handle_get_remote_image_state(int r);
277
278 void get_local_image_state();
279 void handle_get_local_image_state(int r);
280
281 void create_non_primary_snapshot();
282 void handle_create_non_primary_snapshot(int r);
283
284 void update_mirror_image_state();
285 void handle_update_mirror_image_state(int r);
286
287 void request_sync();
288 void handle_request_sync(int r);
289
290 void copy_image();
291 void handle_copy_image(int r);
292 void handle_copy_image_progress(uint64_t object_number,
293 uint64_t object_count);
294 void handle_copy_image_read(uint64_t bytes_read);
295
296 void apply_image_state();
297 void handle_apply_image_state(int r);
298
299 void update_non_primary_snapshot(bool complete);
300 void handle_update_non_primary_snapshot(bool complete, int r);
301
302 void notify_image_update();
303 void handle_notify_image_update(int r);
304
305 void unlink_peer(uint64_t remote_snap_id);
306 void handle_unlink_peer(int r);
307
308 void finish_sync();
309
310 void register_local_update_watcher();
311 void handle_register_local_update_watcher(int r);
312
313 void register_remote_update_watcher();
314 void handle_register_remote_update_watcher(int r);
315
316 void unregister_remote_update_watcher();
317 void handle_unregister_remote_update_watcher(int r);
318
319 void unregister_local_update_watcher();
320 void handle_unregister_local_update_watcher(int r);
321
322 void wait_for_in_flight_ops();
323 void handle_wait_for_in_flight_ops(int r);
324
325 void handle_image_update_notify();
326
327 void handle_replay_complete(int r, const std::string& description);
328 void handle_replay_complete(std::unique_lock<ceph::mutex>* locker,
329 int r, const std::string& description);
330 void notify_status_updated();
331
332 bool is_replay_interrupted();
333 bool is_replay_interrupted(std::unique_lock<ceph::mutex>* lock);
334
335 void register_perf_counters();
336 void unregister_perf_counters();
337 };
338
339 } // namespace snapshot
340 } // namespace image_replayer
341 } // namespace mirror
342 } // namespace rbd
343
344 extern template class rbd::mirror::image_replayer::snapshot::Replayer<librbd::ImageCtx>;
345
346 #endif // RBD_MIRROR_IMAGE_REPLAYER_SNAPSHOT_REPLAYER_H