]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: created simple shell image replayer state builder
authorJason Dillaman <dillaman@redhat.com>
Tue, 7 Jan 2020 15:50:34 +0000 (10:50 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 9 Jan 2020 15:48:52 +0000 (10:48 -0500)
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 <dillaman@redhat.com>
src/tools/rbd_mirror/CMakeLists.txt
src/tools/rbd_mirror/image_replayer/StateBuilder.cc [new file with mode: 0644]
src/tools/rbd_mirror/image_replayer/StateBuilder.h [new file with mode: 0644]
src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc [new file with mode: 0644]
src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h [new file with mode: 0644]

index 4d937d53f670ef015b777fa4f6ff030b1bddccce..b920d1d8d80ffb72dd6c1cd86f8085ca74aed4e4 100644 (file)
@@ -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 (file)
index 0000000..b740e0b
--- /dev/null
@@ -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 <typename I>
+StateBuilder<I>::StateBuilder(const std::string& global_image_id)
+  : global_image_id(global_image_id) {
+  dout(10) << "global_image_id=" << global_image_id << dendl;
+}
+
+template <typename I>
+StateBuilder<I>::~StateBuilder() {
+  ceph_assert(local_image_ctx == nullptr);
+}
+
+template <typename I>
+void StateBuilder<I>::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<I>::create(
+    &local_image_ctx, ctx);
+  request->send();
+}
+
+template <typename I>
+void StateBuilder<I>::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<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_replayer/StateBuilder.h b/src/tools/rbd_mirror/image_replayer/StateBuilder.h
new file mode 100644 (file)
index 0000000..81f26d4
--- /dev/null
@@ -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 <typename ImageCtxT>
+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<librbd::ImageCtx>;
+
+#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 (file)
index 0000000..db8b7ab
--- /dev/null
@@ -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 <typename I>
+StateBuilder<I>::StateBuilder(const std::string& global_image_id)
+  : image_replayer::StateBuilder<I>(global_image_id) {
+}
+
+template <typename I>
+StateBuilder<I>::~StateBuilder() {
+  ceph_assert(remote_journaler == nullptr);
+}
+
+template <typename I>
+void StateBuilder<I>::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 <typename I>
+bool StateBuilder<I>::is_disconnected() const {
+  return (remote_client_state == cls::journal::CLIENT_STATE_DISCONNECTED);
+}
+
+template <typename I>
+bool StateBuilder<I>::is_local_primary() const  {
+  return (!this->local_image_id.empty() &&
+          local_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID);
+}
+
+template <typename I>
+bool StateBuilder<I>::is_linked() const {
+  return (local_tag_owner == this->remote_mirror_uuid);
+}
+
+template <typename I>
+cls::rbd::MirrorImageMode StateBuilder<I>::get_mirror_image_mode() const {
+  return cls::rbd::MIRROR_IMAGE_MODE_JOURNAL;
+}
+
+template <typename I>
+void StateBuilder<I>::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 <typename I>
+void StateBuilder<I>::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<librbd::ImageCtx>;
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 (file)
index 0000000..751c09b
--- /dev/null
@@ -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 <string>
+
+struct Context;
+
+namespace librbd { struct ImageCtx; }
+
+namespace rbd {
+namespace mirror {
+namespace image_replayer {
+namespace journal {
+
+template <typename ImageCtxT>
+class StateBuilder : public image_replayer::StateBuilder<ImageCtxT> {
+public:
+  typedef librbd::journal::TypeTraits<ImageCtxT> 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<librbd::ImageCtx>;
+
+#endif // CEPH_RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_STATE_BUILDER_H