]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/ImageReplayer.h
import 15.2.4
[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 bool restart = false);
106 void stop(Context *on_finish = nullptr, bool manual = false,
107 bool restart = false);
108 void restart(Context *on_finish = nullptr);
109 void flush();
110
111 void print_status(Formatter *f);
112
113 protected:
114 /**
115 * @verbatim
116 * (error)
117 * <uninitialized> <------------------------------------ FAIL
118 * | ^
119 * v *
120 * <starting> *
121 * | *
122 * v (error) *
123 * BOOTSTRAP_IMAGE * * * * * * * * * * * * * * * * * * * *
124 * | *
125 * v (error) *
126 * START_REPLAY * * * * * * * * * * * * * * * * * * * * * *
127 * |
128 * v
129 * REPLAYING
130 * |
131 * v
132 * JOURNAL_REPLAY_SHUT_DOWN
133 * |
134 * v
135 * LOCAL_IMAGE_CLOSE
136 * |
137 * v
138 * <stopped>
139 *
140 * @endverbatim
141 */
142
143 void on_start_fail(int r, const std::string &desc);
144 bool on_start_interrupted();
145 bool on_start_interrupted(ceph::mutex& lock);
146
147 void on_stop_journal_replay(int r = 0, const std::string &desc = "");
148
149 bool on_replay_interrupted();
150
151 private:
152 typedef std::set<Peer<ImageCtxT>> Peers;
153
154 enum State {
155 STATE_UNKNOWN,
156 STATE_STARTING,
157 STATE_REPLAYING,
158 STATE_STOPPING,
159 STATE_STOPPED,
160 };
161
162 struct ReplayerListener;
163
164 typedef boost::optional<State> OptionalState;
165 typedef boost::optional<cls::rbd::MirrorImageStatusState>
166 OptionalMirrorImageStatusState;
167
168 class BootstrapProgressContext : public ProgressContext {
169 public:
170 BootstrapProgressContext(ImageReplayer<ImageCtxT> *replayer) :
171 replayer(replayer) {
172 }
173
174 void update_progress(const std::string &description,
175 bool flush = true) override;
176
177 private:
178 ImageReplayer<ImageCtxT> *replayer;
179 };
180
181 librados::IoCtx &m_local_io_ctx;
182 std::string m_local_mirror_uuid;
183 std::string m_global_image_id;
184 Threads<ImageCtxT> *m_threads;
185 InstanceWatcher<ImageCtxT> *m_instance_watcher;
186 MirrorStatusUpdater<ImageCtxT>* m_local_status_updater;
187 journal::CacheManagerHandler *m_cache_manager_handler;
188 PoolMetaCache* m_pool_meta_cache;
189
190 Peers m_peers;
191 Peer<ImageCtxT> m_remote_image_peer;
192
193 std::string m_local_image_name;
194 std::string m_image_spec;
195
196 mutable ceph::mutex m_lock;
197 State m_state = STATE_STOPPED;
198 std::string m_state_desc;
199
200 OptionalMirrorImageStatusState m_mirror_image_status_state =
201 boost::make_optional(false, cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN);
202 int m_last_r = 0;
203
204 BootstrapProgressContext m_progress_cxt;
205
206 bool m_finished = false;
207 bool m_delete_requested = false;
208 bool m_resync_requested = false;
209 bool m_restart_requested = false;
210
211 image_replayer::StateBuilder<ImageCtxT>* m_state_builder = nullptr;
212 image_replayer::Replayer* m_replayer = nullptr;
213 ReplayerListener* m_replayer_listener = nullptr;
214
215 Context *m_on_start_finish = nullptr;
216 Context *m_on_stop_finish = nullptr;
217 bool m_stop_requested = false;
218 bool m_manual_stop = false;
219
220 AdminSocketHook *m_asok_hook = nullptr;
221
222 image_replayer::BootstrapRequest<ImageCtxT> *m_bootstrap_request = nullptr;
223
224 AsyncOpTracker m_in_flight_op_tracker;
225
226 Context* m_update_status_task = nullptr;
227
228 static std::string to_string(const State state);
229
230 bool is_stopped_() const {
231 return m_state == STATE_STOPPED;
232 }
233 bool is_running_() const {
234 return !is_stopped_() && m_state != STATE_STOPPING && !m_stop_requested;
235 }
236 bool is_replaying_() const {
237 return (m_state == STATE_REPLAYING);
238 }
239
240 void schedule_update_mirror_image_replay_status();
241 void handle_update_mirror_image_replay_status(int r);
242 void cancel_update_mirror_image_replay_status();
243
244 void update_mirror_image_status(bool force, const OptionalState &state);
245 void set_mirror_image_status_update(bool force, const OptionalState &state);
246
247 void shut_down(int r);
248 void handle_shut_down(int r);
249
250 void bootstrap();
251 void handle_bootstrap(int r);
252
253 void start_replay();
254 void handle_start_replay(int r);
255
256 void handle_replayer_notification();
257
258 void register_admin_socket_hook();
259 void unregister_admin_socket_hook();
260 void reregister_admin_socket_hook();
261
262 };
263
264 } // namespace mirror
265 } // namespace rbd
266
267 extern template class rbd::mirror::ImageReplayer<librbd::ImageCtx>;
268
269 #endif // CEPH_RBD_MIRROR_IMAGE_REPLAYER_H