]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/ImageReplayer.h
493d38d9d2845e6e4e82dbee53183b7cdafd257f
[ceph.git] / ceph / src / tools / rbd_mirror / ImageReplayer.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_RBD_MIRROR_IMAGE_REPLAYER_H
5 #define CEPH_RBD_MIRROR_IMAGE_REPLAYER_H
6
7 #include "common/AsyncOpTracker.h"
8 #include "common/ceph_mutex.h"
9 #include "include/rados/librados.hpp"
10 #include "cls/rbd/cls_rbd_types.h"
11 #include "ProgressContext.h"
12 #include "tools/rbd_mirror/Types.h"
13 #include "tools/rbd_mirror/image_replayer/Types.h"
14 #include <boost/optional.hpp>
15 #include <string>
16
17 class AdminSocketHook;
18
19 namespace journal { struct CacheManagerHandler; }
20 namespace librbd { class ImageCtx; }
21
22 namespace rbd {
23 namespace mirror {
24
25 template <typename> struct InstanceWatcher;
26 template <typename> struct MirrorStatusUpdater;
27 struct PoolMetaCache;
28 template <typename> struct Threads;
29
30 namespace image_replayer {
31
32 class Replayer;
33 template <typename> class BootstrapRequest;
34 template <typename> class StateBuilder;
35
36 } // namespace image_replayer
37
38 /**
39 * Replays changes from a remote cluster for a single image.
40 */
41 template <typename ImageCtxT = librbd::ImageCtx>
42 class ImageReplayer {
43 public:
44 static ImageReplayer *create(
45 librados::IoCtx &local_io_ctx, const std::string &local_mirror_uuid,
46 const std::string &global_image_id, Threads<ImageCtxT> *threads,
47 InstanceWatcher<ImageCtxT> *instance_watcher,
48 MirrorStatusUpdater<ImageCtxT>* local_status_updater,
49 journal::CacheManagerHandler *cache_manager_handler,
50 PoolMetaCache* pool_meta_cache) {
51 return new ImageReplayer(local_io_ctx, local_mirror_uuid, global_image_id,
52 threads, instance_watcher, local_status_updater,
53 cache_manager_handler, pool_meta_cache);
54 }
55 void destroy() {
56 delete this;
57 }
58
59 ImageReplayer(librados::IoCtx &local_io_ctx,
60 const std::string &local_mirror_uuid,
61 const std::string &global_image_id,
62 Threads<ImageCtxT> *threads,
63 InstanceWatcher<ImageCtxT> *instance_watcher,
64 MirrorStatusUpdater<ImageCtxT>* local_status_updater,
65 journal::CacheManagerHandler *cache_manager_handler,
66 PoolMetaCache* pool_meta_cache);
67 virtual ~ImageReplayer();
68 ImageReplayer(const ImageReplayer&) = delete;
69 ImageReplayer& operator=(const ImageReplayer&) = delete;
70
71 bool is_stopped() { std::lock_guard l{m_lock}; return is_stopped_(); }
72 bool is_running() { std::lock_guard l{m_lock}; return is_running_(); }
73 bool is_replaying() { std::lock_guard l{m_lock}; return is_replaying_(); }
74
75 std::string get_name() { std::lock_guard l{m_lock}; return m_image_spec; };
76 void set_state_description(int r, const std::string &desc);
77
78 // TODO temporary until policy handles release of image replayers
79 inline bool is_finished() const {
80 std::lock_guard locker{m_lock};
81 return m_finished;
82 }
83 inline void set_finished(bool finished) {
84 std::lock_guard locker{m_lock};
85 m_finished = finished;
86 }
87
88 inline bool is_blacklisted() const {
89 std::lock_guard locker{m_lock};
90 return (m_last_r == -EBLACKLISTED);
91 }
92
93 image_replayer::HealthState get_health_state() const;
94
95 void add_peer(const Peer<ImageCtxT>& peer);
96
97 inline int64_t get_local_pool_id() const {
98 return m_local_io_ctx.get_id();
99 }
100 inline const std::string& get_global_image_id() const {
101 return m_global_image_id;
102 }
103
104 void start(Context *on_finish = nullptr, bool manual = false);
105 void stop(Context *on_finish = nullptr, bool manual = false,
106 int r = 0, const std::string& desc = "");
107 void restart(Context *on_finish = nullptr);
108 void flush();
109
110 void print_status(Formatter *f);
111
112 protected:
113 /**
114 * @verbatim
115 * (error)
116 * <uninitialized> <------------------------------------ FAIL
117 * | ^
118 * v *
119 * <starting> *
120 * | *
121 * v (error) *
122 * BOOTSTRAP_IMAGE * * * * * * * * * * * * * * * * * * * *
123 * | *
124 * v (error) *
125 * START_REPLAY * * * * * * * * * * * * * * * * * * * * * *
126 * |
127 * v
128 * REPLAYING
129 * |
130 * v
131 * JOURNAL_REPLAY_SHUT_DOWN
132 * |
133 * v
134 * LOCAL_IMAGE_CLOSE
135 * |
136 * v
137 * <stopped>
138 *
139 * @endverbatim
140 */
141
142 virtual void on_start_fail(int r, const std::string &desc);
143 virtual bool on_start_interrupted();
144 virtual bool on_start_interrupted(ceph::mutex& lock);
145
146 virtual void on_stop_journal_replay(int r = 0, const std::string &desc = "");
147
148 bool on_replay_interrupted();
149
150 private:
151 typedef std::set<Peer<ImageCtxT>> Peers;
152
153 enum State {
154 STATE_UNKNOWN,
155 STATE_STARTING,
156 STATE_REPLAYING,
157 STATE_STOPPING,
158 STATE_STOPPED,
159 };
160
161 struct ReplayerListener;
162
163 typedef boost::optional<State> OptionalState;
164 typedef boost::optional<cls::rbd::MirrorImageStatusState>
165 OptionalMirrorImageStatusState;
166
167 class BootstrapProgressContext : public ProgressContext {
168 public:
169 BootstrapProgressContext(ImageReplayer<ImageCtxT> *replayer) :
170 replayer(replayer) {
171 }
172
173 void update_progress(const std::string &description,
174 bool flush = true) override;
175
176 private:
177 ImageReplayer<ImageCtxT> *replayer;
178 };
179
180 librados::IoCtx &m_local_io_ctx;
181 std::string m_local_mirror_uuid;
182 std::string m_global_image_id;
183 Threads<ImageCtxT> *m_threads;
184 InstanceWatcher<ImageCtxT> *m_instance_watcher;
185 MirrorStatusUpdater<ImageCtxT>* m_local_status_updater;
186 journal::CacheManagerHandler *m_cache_manager_handler;
187 PoolMetaCache* m_pool_meta_cache;
188
189 Peers m_peers;
190 Peer<ImageCtxT> m_remote_image_peer;
191
192 std::string m_local_image_name;
193 std::string m_image_spec;
194
195 mutable ceph::mutex m_lock;
196 State m_state = STATE_STOPPED;
197 std::string m_state_desc;
198
199 OptionalMirrorImageStatusState m_mirror_image_status_state =
200 boost::make_optional(false, cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN);
201 int m_last_r = 0;
202
203 BootstrapProgressContext m_progress_cxt;
204
205 bool m_finished = false;
206 bool m_delete_requested = false;
207 bool m_resync_requested = false;
208
209 image_replayer::StateBuilder<ImageCtxT>* m_state_builder = nullptr;
210 image_replayer::Replayer* m_replayer = nullptr;
211 ReplayerListener* m_replayer_listener = nullptr;
212
213 Context *m_on_start_finish = nullptr;
214 Context *m_on_stop_finish = nullptr;
215 bool m_stop_requested = false;
216 bool m_manual_stop = false;
217
218 AdminSocketHook *m_asok_hook = nullptr;
219
220 image_replayer::BootstrapRequest<ImageCtxT> *m_bootstrap_request = nullptr;
221
222 AsyncOpTracker m_in_flight_op_tracker;
223
224 Context* m_update_status_task = nullptr;
225
226 static std::string to_string(const State state);
227
228 bool is_stopped_() const {
229 return m_state == STATE_STOPPED;
230 }
231 bool is_running_() const {
232 return !is_stopped_() && m_state != STATE_STOPPING && !m_stop_requested;
233 }
234 bool is_replaying_() const {
235 return (m_state == STATE_REPLAYING);
236 }
237
238 void schedule_update_mirror_image_replay_status();
239 void handle_update_mirror_image_replay_status(int r);
240 void cancel_update_mirror_image_replay_status();
241
242 void update_mirror_image_status(bool force, const OptionalState &state);
243 void set_mirror_image_status_update(bool force, const OptionalState &state);
244
245 void shut_down(int r);
246 void handle_shut_down(int r);
247
248 void bootstrap();
249 void handle_bootstrap(int r);
250
251 void start_replay();
252 void handle_start_replay(int r);
253
254 void handle_replayer_notification();
255
256 void register_admin_socket_hook();
257 void unregister_admin_socket_hook();
258 void reregister_admin_socket_hook();
259
260 };
261
262 } // namespace mirror
263 } // namespace rbd
264
265 extern template class rbd::mirror::ImageReplayer<librbd::ImageCtx>;
266
267 #endif // CEPH_RBD_MIRROR_IMAGE_REPLAYER_H