From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/tools/rbd_mirror/ImageReplayer.h | 273 +++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 src/tools/rbd_mirror/ImageReplayer.h (limited to 'src/tools/rbd_mirror/ImageReplayer.h') diff --git a/src/tools/rbd_mirror/ImageReplayer.h b/src/tools/rbd_mirror/ImageReplayer.h new file mode 100644 index 000000000..432fdf225 --- /dev/null +++ b/src/tools/rbd_mirror/ImageReplayer.h @@ -0,0 +1,273 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_RBD_MIRROR_IMAGE_REPLAYER_H +#define CEPH_RBD_MIRROR_IMAGE_REPLAYER_H + +#include "common/AsyncOpTracker.h" +#include "common/ceph_mutex.h" +#include "include/rados/librados.hpp" +#include "cls/rbd/cls_rbd_types.h" +#include "ProgressContext.h" +#include "tools/rbd_mirror/Types.h" +#include "tools/rbd_mirror/image_replayer/Types.h" +#include +#include + +class AdminSocketHook; + +namespace journal { struct CacheManagerHandler; } +namespace librbd { class ImageCtx; } + +namespace rbd { +namespace mirror { + +template struct InstanceWatcher; +template struct MirrorStatusUpdater; +struct PoolMetaCache; +template struct Threads; + +namespace image_replayer { + +class Replayer; +template class BootstrapRequest; +template class StateBuilder; + +} // namespace image_replayer + +/** + * Replays changes from a remote cluster for a single image. + */ +template +class ImageReplayer { +public: + static ImageReplayer *create( + librados::IoCtx &local_io_ctx, const std::string &local_mirror_uuid, + const std::string &global_image_id, Threads *threads, + InstanceWatcher *instance_watcher, + MirrorStatusUpdater* local_status_updater, + journal::CacheManagerHandler *cache_manager_handler, + PoolMetaCache* pool_meta_cache) { + return new ImageReplayer(local_io_ctx, local_mirror_uuid, global_image_id, + threads, instance_watcher, local_status_updater, + cache_manager_handler, pool_meta_cache); + } + void destroy() { + delete this; + } + + ImageReplayer(librados::IoCtx &local_io_ctx, + const std::string &local_mirror_uuid, + const std::string &global_image_id, + Threads *threads, + InstanceWatcher *instance_watcher, + MirrorStatusUpdater* local_status_updater, + journal::CacheManagerHandler *cache_manager_handler, + PoolMetaCache* pool_meta_cache); + virtual ~ImageReplayer(); + ImageReplayer(const ImageReplayer&) = delete; + ImageReplayer& operator=(const ImageReplayer&) = delete; + + bool is_stopped() { std::lock_guard l{m_lock}; return is_stopped_(); } + bool is_running() { std::lock_guard l{m_lock}; return is_running_(); } + bool is_replaying() { std::lock_guard l{m_lock}; return is_replaying_(); } + + std::string get_name() { std::lock_guard l{m_lock}; return m_image_spec; }; + void set_state_description(int r, const std::string &desc); + + // TODO temporary until policy handles release of image replayers + inline bool is_finished() const { + std::lock_guard locker{m_lock}; + return m_finished; + } + inline void set_finished(bool finished) { + std::lock_guard locker{m_lock}; + m_finished = finished; + } + + inline bool is_blocklisted() const { + std::lock_guard locker{m_lock}; + return (m_last_r == -EBLOCKLISTED); + } + + image_replayer::HealthState get_health_state() const; + + void add_peer(const Peer& peer); + + inline int64_t get_local_pool_id() const { + return m_local_io_ctx.get_id(); + } + inline const std::string& get_global_image_id() const { + return m_global_image_id; + } + + void start(Context *on_finish, bool manual = false, bool restart = false); + void stop(Context *on_finish, bool manual = false, bool restart = false); + void restart(Context *on_finish = nullptr); + void flush(); + + void print_status(Formatter *f); + +protected: + /** + * @verbatim + * (error) + * <------------------------------------ FAIL + * | ^ + * v * + * * + * | * + * v (error) * + * BOOTSTRAP_IMAGE * * * * * * * * * * * * * * * * * * * * + * | * + * v (error) * + * START_REPLAY * * * * * * * * * * * * * * * * * * * * * * + * | + * v + * REPLAYING + * | + * v + * JOURNAL_REPLAY_SHUT_DOWN + * | + * v + * LOCAL_IMAGE_CLOSE + * | + * v + * + * + * @endverbatim + */ + + void on_start_fail(int r, const std::string &desc); + bool on_start_interrupted(); + bool on_start_interrupted(ceph::mutex& lock); + + void on_stop_journal_replay(int r = 0, const std::string &desc = ""); + + bool on_replay_interrupted(); + +private: + typedef std::set> Peers; + typedef std::list Contexts; + + enum State { + STATE_UNKNOWN, + STATE_STARTING, + STATE_REPLAYING, + STATE_STOPPING, + STATE_STOPPED, + }; + + struct ReplayerListener; + + typedef boost::optional OptionalState; + typedef boost::optional + OptionalMirrorImageStatusState; + + class BootstrapProgressContext : public ProgressContext { + public: + BootstrapProgressContext(ImageReplayer *replayer) : + replayer(replayer) { + } + + void update_progress(const std::string &description, + bool flush = true) override; + + private: + ImageReplayer *replayer; + }; + + librados::IoCtx &m_local_io_ctx; + std::string m_local_mirror_uuid; + std::string m_global_image_id; + Threads *m_threads; + InstanceWatcher *m_instance_watcher; + MirrorStatusUpdater* m_local_status_updater; + journal::CacheManagerHandler *m_cache_manager_handler; + PoolMetaCache* m_pool_meta_cache; + + Peers m_peers; + Peer m_remote_image_peer; + + std::string m_local_image_name; + std::string m_image_spec; + + mutable ceph::mutex m_lock; + State m_state = STATE_STOPPED; + std::string m_state_desc; + + OptionalMirrorImageStatusState m_mirror_image_status_state = + boost::make_optional(false, cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN); + int m_last_r = 0; + + BootstrapProgressContext m_progress_cxt; + + bool m_finished = false; + bool m_delete_in_progress = false; + bool m_delete_requested = false; + bool m_resync_requested = false; + bool m_restart_requested = false; + + bool m_status_removed = false; + + image_replayer::StateBuilder* m_state_builder = nullptr; + image_replayer::Replayer* m_replayer = nullptr; + ReplayerListener* m_replayer_listener = nullptr; + + Context *m_on_start_finish = nullptr; + Contexts m_on_stop_contexts; + bool m_stop_requested = false; + bool m_manual_stop = false; + + AdminSocketHook *m_asok_hook = nullptr; + + image_replayer::BootstrapRequest *m_bootstrap_request = nullptr; + + AsyncOpTracker m_in_flight_op_tracker; + + Context* m_update_status_task = nullptr; + + static std::string to_string(const State state); + + bool is_stopped_() const { + return m_state == STATE_STOPPED; + } + bool is_running_() const { + return !is_stopped_() && m_state != STATE_STOPPING && !m_stop_requested; + } + bool is_replaying_() const { + return (m_state == STATE_REPLAYING); + } + + void schedule_update_mirror_image_replay_status(); + void handle_update_mirror_image_replay_status(int r); + void cancel_update_mirror_image_replay_status(); + + void update_mirror_image_status(bool force, const OptionalState &state); + void set_mirror_image_status_update(bool force, const OptionalState &state); + + void shut_down(int r); + void handle_shut_down(int r); + + void bootstrap(); + void handle_bootstrap(int r); + + void start_replay(); + void handle_start_replay(int r); + + void handle_replayer_notification(); + + void register_admin_socket_hook(); + void unregister_admin_socket_hook(); + void reregister_admin_socket_hook(); + void remove_image_status(bool force, Context *on_finish); + void remove_image_status_remote(bool force, Context *on_finish); + +}; + +} // namespace mirror +} // namespace rbd + +extern template class rbd::mirror::ImageReplayer; + +#endif // CEPH_RBD_MIRROR_IMAGE_REPLAYER_H -- cgit v1.2.3