From e31e471796efe658e66693514d07c5b72b1e8314 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Tue, 7 Jan 2020 10:50:34 -0500 Subject: [PATCH] rbd-mirror: created simple shell image replayer state builder This state builder will separate common logic for journal + snapshot mirroring and allow an abstract query and builder APIs for abstracting the deltas between the two implementations. Signed-off-by: Jason Dillaman --- src/tools/rbd_mirror/CMakeLists.txt | 2 + .../rbd_mirror/image_replayer/StateBuilder.cc | 68 ++++++++++++ .../rbd_mirror/image_replayer/StateBuilder.h | 61 +++++++++++ .../image_replayer/journal/StateBuilder.cc | 103 ++++++++++++++++++ .../image_replayer/journal/StateBuilder.h | 64 +++++++++++ 5 files changed, 298 insertions(+) create mode 100644 src/tools/rbd_mirror/image_replayer/StateBuilder.cc create mode 100644 src/tools/rbd_mirror/image_replayer/StateBuilder.h create mode 100644 src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc create mode 100644 src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h diff --git a/src/tools/rbd_mirror/CMakeLists.txt b/src/tools/rbd_mirror/CMakeLists.txt index 4d937d53f67..b920d1d8d80 100644 --- a/src/tools/rbd_mirror/CMakeLists.txt +++ b/src/tools/rbd_mirror/CMakeLists.txt @@ -40,12 +40,14 @@ set(rbd_mirror_internal image_replayer/OpenLocalImageRequest.cc image_replayer/PrepareLocalImageRequest.cc image_replayer/PrepareRemoteImageRequest.cc + image_replayer/StateBuilder.cc image_replayer/Utils.cc image_replayer/journal/CreateLocalImageRequest.cc image_replayer/journal/EventPreprocessor.cc image_replayer/journal/PrepareReplayRequest.cc image_replayer/journal/Replayer.cc image_replayer/journal/ReplayStatusFormatter.cc + image_replayer/journal/StateBuilder.cc image_sync/SyncPointCreateRequest.cc image_sync/SyncPointPruneRequest.cc pool_watcher/RefreshImagesRequest.cc diff --git a/src/tools/rbd_mirror/image_replayer/StateBuilder.cc b/src/tools/rbd_mirror/image_replayer/StateBuilder.cc new file mode 100644 index 00000000000..b740e0bd4d0 --- /dev/null +++ b/src/tools/rbd_mirror/image_replayer/StateBuilder.cc @@ -0,0 +1,68 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "StateBuilder.h" +#include "include/ceph_assert.h" +#include "include/Context.h" +#include "common/debug.h" +#include "common/errno.h" +#include "journal/Journaler.h" +#include "librbd/ImageCtx.h" +#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_rbd_mirror +#undef dout_prefix +#define dout_prefix *_dout << "rbd::mirror::image_replayer::" \ + << "StateBuilder: " << this << " " \ + << __func__ << ": " + +namespace rbd { +namespace mirror { +namespace image_replayer { + +template +StateBuilder::StateBuilder(const std::string& global_image_id) + : global_image_id(global_image_id) { + dout(10) << "global_image_id=" << global_image_id << dendl; +} + +template +StateBuilder::~StateBuilder() { + ceph_assert(local_image_ctx == nullptr); +} + +template +void StateBuilder::close_local_image(Context* on_finish) { + if (local_image_ctx == nullptr) { + on_finish->complete(0); + return; + } + + dout(10) << dendl; + auto ctx = new LambdaContext([this, on_finish](int r) { + handle_close_local_image(r, on_finish); + }); + auto request = image_replayer::CloseImageRequest::create( + &local_image_ctx, ctx); + request->send(); +} + +template +void StateBuilder::handle_close_local_image(int r, Context* on_finish) { + dout(10) << "r=" << r << dendl; + + ceph_assert(local_image_ctx == nullptr); + if (r < 0) { + derr << "failed to close local image for image " << global_image_id << ": " + << cpp_strerror(r) << dendl; + } + + on_finish->complete(r); +} + +} // namespace image_replayer +} // namespace mirror +} // namespace rbd + +template class rbd::mirror::image_replayer::StateBuilder; diff --git a/src/tools/rbd_mirror/image_replayer/StateBuilder.h b/src/tools/rbd_mirror/image_replayer/StateBuilder.h new file mode 100644 index 00000000000..81f26d4c563 --- /dev/null +++ b/src/tools/rbd_mirror/image_replayer/StateBuilder.h @@ -0,0 +1,61 @@ +// -*- 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_STATE_BUILDER_H +#define CEPH_RBD_MIRROR_IMAGE_REPLAYER_STATE_BUILDER_H + +#include "cls/rbd/cls_rbd_types.h" + +struct Context; +namespace librbd { struct ImageCtx; } + +namespace rbd { +namespace mirror { +namespace image_replayer { + +template +class StateBuilder { +public: + StateBuilder(const StateBuilder&) = delete; + StateBuilder& operator=(const StateBuilder&) = delete; + + virtual ~StateBuilder(); + + virtual void destroy() { + delete this; + } + + virtual void close(Context* on_finish) = 0; + + virtual bool is_disconnected() const = 0; + + virtual bool is_local_primary() const = 0; + virtual bool is_linked() const = 0; + + virtual cls::rbd::MirrorImageMode get_mirror_image_mode() const = 0; + + std::string global_image_id; + + std::string local_image_id; + ImageCtxT* local_image_ctx = nullptr; + + std::string remote_mirror_uuid; + std::string remote_image_id; + +protected: + StateBuilder(const std::string& global_image_id); + + void close_local_image(Context* on_finish); + +private: + + void handle_close_local_image(int r, Context* on_finish); +}; + +} // namespace image_replayer +} // namespace mirror +} // namespace rbd + +extern template class rbd::mirror::image_replayer::StateBuilder; + +#endif // CEPH_RBD_MIRROR_IMAGE_REPLAYER_STATE_BUILDER_H diff --git a/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc new file mode 100644 index 00000000000..db8b7ab5f8f --- /dev/null +++ b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc @@ -0,0 +1,103 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "StateBuilder.h" +#include "include/ceph_assert.h" +#include "include/Context.h" +#include "common/debug.h" +#include "common/errno.h" +#include "journal/Journaler.h" +#include "librbd/ImageCtx.h" +#include "librbd/Journal.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_rbd_mirror +#undef dout_prefix +#define dout_prefix *_dout << "rbd::mirror::image_replayer::journal::" \ + << "StateBuilder: " << this << " " \ + << __func__ << ": " + +namespace rbd { +namespace mirror { +namespace image_replayer { +namespace journal { + +template +StateBuilder::StateBuilder(const std::string& global_image_id) + : image_replayer::StateBuilder(global_image_id) { +} + +template +StateBuilder::~StateBuilder() { + ceph_assert(remote_journaler == nullptr); +} + +template +void StateBuilder::close(Context* on_finish) { + dout(10) << dendl; + + // close the remote journaler after closing the local image + // in case we have lost contact w/ the remote cluster and + // will block + auto ctx = new LambdaContext([this, on_finish](int) { + shut_down_remote_journaler(on_finish); + }); + this->close_local_image(ctx); +} + +template +bool StateBuilder::is_disconnected() const { + return (remote_client_state == cls::journal::CLIENT_STATE_DISCONNECTED); +} + +template +bool StateBuilder::is_local_primary() const { + return (!this->local_image_id.empty() && + local_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID); +} + +template +bool StateBuilder::is_linked() const { + return (local_tag_owner == this->remote_mirror_uuid); +} + +template +cls::rbd::MirrorImageMode StateBuilder::get_mirror_image_mode() const { + return cls::rbd::MIRROR_IMAGE_MODE_JOURNAL; +} + +template +void StateBuilder::shut_down_remote_journaler(Context* on_finish) { + if (remote_journaler == nullptr) { + on_finish->complete(0); + return; + } + + dout(10) << dendl; + auto ctx = new LambdaContext([this, on_finish](int r) { + handle_shut_down_remote_journaler(r, on_finish); + }); + remote_journaler->shut_down(ctx); +} + +template +void StateBuilder::handle_shut_down_remote_journaler(int r, + Context* on_finish) { + dout(10) << "r=" << r << dendl; + + if (r < 0) { + derr << "failed to shut down remote journaler: " << cpp_strerror(r) + << dendl; + } + + delete remote_journaler; + remote_journaler = nullptr; + on_finish->complete(r); +} + +} // namespace journal +} // namespace image_replayer +} // namespace mirror +} // namespace rbd + +template class rbd::mirror::image_replayer::journal::StateBuilder; diff --git a/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h new file mode 100644 index 00000000000..751c09bc1c8 --- /dev/null +++ b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h @@ -0,0 +1,64 @@ +// -*- 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_JOURNAL_STATE_BUILDER_H +#define CEPH_RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_STATE_BUILDER_H + +#include "tools/rbd_mirror/image_replayer/StateBuilder.h" +#include "cls/journal/cls_journal_types.h" +#include "librbd/journal/Types.h" +#include "librbd/journal/TypeTraits.h" +#include + +struct Context; + +namespace librbd { struct ImageCtx; } + +namespace rbd { +namespace mirror { +namespace image_replayer { +namespace journal { + +template +class StateBuilder : public image_replayer::StateBuilder { +public: + typedef librbd::journal::TypeTraits TypeTraits; + typedef typename TypeTraits::Journaler Journaler; + + static StateBuilder* create(const std::string& global_image_id) { + return new StateBuilder(global_image_id); + } + + StateBuilder(const std::string& global_image_id); + ~StateBuilder() override; + + void close(Context* on_finish) override; + + bool is_disconnected() const override; + + bool is_local_primary() const override; + bool is_linked() const override; + + cls::rbd::MirrorImageMode get_mirror_image_mode() const override; + + std::string local_tag_owner; + + Journaler* remote_journaler = nullptr; + cls::journal::ClientState remote_client_state = + cls::journal::CLIENT_STATE_CONNECTED; + librbd::journal::MirrorPeerClientMeta remote_client_meta; + +private: + + void shut_down_remote_journaler(Context* on_finish); + void handle_shut_down_remote_journaler(int r, Context* on_finish); +}; + +} // namespace journal +} // namespace image_replayer +} // namespace mirror +} // namespace rbd + +extern template class rbd::mirror::image_replayer::journal::StateBuilder; + +#endif // CEPH_RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_STATE_BUILDER_H -- 2.39.5