]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: integrate new bootstrap state machine
authorJason Dillaman <dillaman@redhat.com>
Mon, 14 Mar 2016 02:12:15 +0000 (22:12 -0400)
committerJosh Durgin <jdurgin@redhat.com>
Tue, 15 Mar 2016 00:26:18 +0000 (17:26 -0700)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/tools/Makefile-client.am
src/tools/rbd_mirror/ImageReplayer.cc
src/tools/rbd_mirror/ImageReplayer.h

index a21d338fa104889d1e12333aa3f5eed16dffa5f7..3b20aa857ef695d491fbb7c37a3172eff2998075 100644 (file)
@@ -95,6 +95,9 @@ librbd_mirror_internal_la_SOURCES = \
        tools/rbd_mirror/Replayer.cc \
        tools/rbd_mirror/Threads.cc \
        tools/rbd_mirror/types.cc \
+       tools/rbd_mirror/image_replayer/BootstrapRequest.cc \
+       tools/rbd_mirror/image_replayer/CloseImageRequest.cc \
+       tools/rbd_mirror/image_replayer/OpenLocalImageRequest.cc \
        tools/rbd_mirror/image_sync/ImageCopyRequest.cc \
        tools/rbd_mirror/image_sync/ObjectCopyRequest.cc \
        tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc \
@@ -110,6 +113,9 @@ noinst_HEADERS += \
        tools/rbd_mirror/Replayer.h \
        tools/rbd_mirror/Threads.h \
        tools/rbd_mirror/types.h \
+       tools/rbd_mirror/image_replayer/BootstrapRequest.h \
+       tools/rbd_mirror/image_replayer/CloseImageRequest.h \
+       tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h \
        tools/rbd_mirror/image_sync/ImageCopyRequest.h \
        tools/rbd_mirror/image_sync/ObjectCopyRequest.h \
        tools/rbd_mirror/image_sync/SnapshotCopyRequest.h \
index 3148b6dc05e7918db6b6cc2d4c5bad4a3c092ed5..e1be6c0d7cd7dc77a4a49c30a7538c190f29b92d 100644 (file)
 #include "librbd/internal.h"
 #include "librbd/journal/Replay.h"
 #include "ImageReplayer.h"
+#include "ImageSync.h"
 #include "Threads.h"
+#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
+#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h"
 
 #define dout_subsys ceph_subsys_rbd_mirror
 #undef dout_prefix
@@ -35,6 +39,7 @@ namespace rbd {
 namespace mirror {
 
 using librbd::util::create_context_callback;
+using namespace rbd::mirror::image_replayer;
 
 namespace {
 
@@ -65,30 +70,6 @@ struct C_ReplayCommitted : public Context {
   }
 };
 
-class BootstrapThread : public Thread {
-public:
-  explicit BootstrapThread(ImageReplayer *replayer,
-                          const ImageReplayer::BootstrapParams &params,
-                          Context *on_finish)
-    : replayer(replayer), params(params), on_finish(on_finish) {}
-
-  virtual ~BootstrapThread() {}
-
-protected:
-  void *entry()
-  {
-    int r = replayer->bootstrap(params);
-    on_finish->complete(r);
-    delete this;
-    return NULL;
-  }
-
-private:
-  ImageReplayer *replayer;
-  ImageReplayer::BootstrapParams params;
-  Context *on_finish;
-};
-
 class ImageReplayerAdminSocketCommand {
 public:
   virtual ~ImageReplayerAdminSocketCommand() {}
@@ -213,8 +194,6 @@ ImageReplayer::ImageReplayer(Threads *threads, RadosRef local, RadosRef remote,
 
 ImageReplayer::~ImageReplayer()
 {
-  m_threads->work_queue->drain();
-
   assert(m_local_image_ctx == nullptr);
   assert(m_local_replay == nullptr);
   assert(m_remote_journaler == nullptr);
@@ -247,6 +226,25 @@ void ImageReplayer::start(Context *on_finish,
     return;
   }
 
+  if (bootstrap_params != nullptr && !bootstrap_params->empty()) {
+    r = m_local->pool_lookup(bootstrap_params->local_pool_name.c_str());
+    if (r < 0) {
+      derr << "error finding local pool " << bootstrap_params->local_pool_name
+           << ": " << cpp_strerror(r) << dendl;
+      on_start_fail_start(r);
+      return;
+    }
+    m_local_pool_id = r;
+  }
+
+  r = m_local->ioctx_create2(m_local_pool_id, m_local_ioctx);
+  if (r < 0) {
+    derr << "error opening ioctx for local pool " << m_local_pool_id
+         << ": " << cpp_strerror(r) << dendl;
+    on_start_fail_start(r);
+    return;
+  }
+
   CephContext *cct = static_cast<CephContext *>(m_local->cct());
 
   double commit_interval = cct->_conf->rbd_journal_commit_age;
@@ -314,54 +312,61 @@ void ImageReplayer::on_start_get_registered_client_status_finish(int r,
        on_start_fail_start(-EINVAL);
        return;
       }
-      librbd::journal::MirrorPeerClientMeta &cm =
-       boost::get<librbd::journal::MirrorPeerClientMeta>(client_data.client_meta);
-      m_local_image_id = cm.image_id;
 
-      // TODO: snap name should be transient
-      if (cm.sync_points.empty()) {
-       derr << "sync points not found" << dendl;
-       on_start_fail_start(-ENOENT);
-       return;
-      }
-      m_snap_name = cm.sync_points.front().snap_name;
+      // TODO: unsafe cast
+      m_client_meta =
+       boost::get<librbd::journal::MirrorPeerClientMeta>(client_data.client_meta);
+      m_local_image_id = m_client_meta.image_id;
 
       dout(20) << "client found, pool_id=" << m_local_pool_id << ", image_id="
-              << m_local_image_id << ", snap_name=" << m_snap_name << dendl;
+              << m_local_image_id << dendl;
 
       if (!bootstrap_params.empty()) {
        dout(0) << "ignoring bootsrap params: client already registered" << dendl;
       }
 
-      on_start_bootstrap_finish(0);
+      on_start_remote_journaler_init_start();
       return;
     }
   }
 
   dout(20) << "client not found" << dendl;
-
-  on_start_bootstrap_start(bootstrap_params);
+  bootstrap(bootstrap_params);
 }
 
-void ImageReplayer::on_start_bootstrap_start(const BootstrapParams &params)
-{
-  dout(20) << "enter" << dendl;
+void ImageReplayer::bootstrap(const BootstrapParams &bootstrap_params) {
+  int r;
+  BootstrapParams params;
 
-  FunctionContext *ctx = new FunctionContext(
-    [this](int r) {
-      on_start_bootstrap_finish(r);
-    });
+  if (!bootstrap_params.empty()) {
+    dout(20) << "using external bootstrap params" << dendl;
+    params = bootstrap_params;
+  } else {
+    r = get_bootstrap_params(&params);
+    if (r < 0) {
+      derr << "error obtaining bootstrap parameters: "
+          << cpp_strerror(r) << dendl;
+      on_start_fail_start(r);
+      return;
+    }
+  }
 
-  BootstrapThread *thread = new BootstrapThread(this, params, ctx);
+  dout(20) << "bootstrap params: "
+           << "local_pool_name=" << params.local_pool_name << ", "
+          << "local_image_name=" << params.local_image_name << dendl;
 
-  thread->create("bootstrap");
-  thread->detach();
-  // TODO: As the bootstrap might take long time it needs some control
-  // to get current status, interrupt, etc...
+  // TODO: add a new bootstrap state and support canceling
+  Context *ctx = create_context_callback<
+    ImageReplayer, &ImageReplayer::handle_bootstrap>(this);
+  BootstrapRequest<> *request = BootstrapRequest<>::create(
+    m_local_ioctx, m_remote_ioctx, &m_local_image_ctx,
+    params.local_image_name, m_remote_image_id, m_threads->work_queue,
+    m_threads->timer, &m_threads->timer_lock, m_client_id, m_remote_journaler,
+    &m_client_meta, ctx);
+  request->send();
 }
 
-void ImageReplayer::on_start_bootstrap_finish(int r)
-{
+void ImageReplayer::handle_bootstrap(int r) {
   dout(20) << "r=" << r << dendl;
 
   if (r < 0) {
@@ -377,6 +382,10 @@ void ImageReplayer::on_start_bootstrap_finish(int r)
 
 void ImageReplayer::on_start_remote_journaler_init_start()
 {
+  if (on_start_interrupted()) {
+    return;
+  }
+
   dout(20) << "enter" << dendl;
 
   FunctionContext *ctx = new FunctionContext(
@@ -400,13 +409,6 @@ void ImageReplayer::on_start_remote_journaler_init_finish(int r)
     return;
   }
 
-  r = m_local->ioctx_create2(m_local_pool_id, m_local_ioctx);
-  if (r < 0) {
-    derr << "error opening ioctx for local pool " << m_local_pool_id
-        << ": " << cpp_strerror(r) << dendl;
-    on_start_fail_start(r);
-    return;
-  }
 
   on_start_local_image_open_start();
 }
@@ -414,69 +416,31 @@ void ImageReplayer::on_start_remote_journaler_init_finish(int r)
 void ImageReplayer::on_start_local_image_open_start()
 {
   dout(20) << "enter" << dendl;
-
-  m_local_image_ctx = new librbd::ImageCtx("", m_local_image_id, NULL,
-                                          m_local_ioctx, false);
-
-  FunctionContext *ctx = new FunctionContext(
-    [this](int r) {
-      on_start_local_image_open_finish(r);
-    });
-  m_local_image_ctx->state->open(ctx);
-}
-
-void ImageReplayer::on_start_local_image_open_finish(int r)
-{
-  dout(20) << "r=" << r << dendl;
-
-  if (r < 0) {
-    derr << "error opening local image " <<  m_local_image_id
-        << ": " << cpp_strerror(r) << dendl;
-
-    FunctionContext *ctx = new FunctionContext(
-      [this, r](int r1) {
-       assert(r1 == 0);
-       delete m_local_image_ctx;
-       m_local_image_ctx = nullptr;
-       on_start_fail_start(r);
-      });
-
-    m_threads->work_queue->queue(ctx, 0);
-    return;
-  }
-  if (on_start_interrupted()) {
+  if (m_local_image_ctx != nullptr) {
+    // already opened during bootstrap
+    on_start_wait_for_local_journal_ready_start();
     return;
   }
 
-  on_start_local_image_lock_start();
+  // open and lock the local image
+  Context *ctx = create_context_callback<
+    ImageReplayer, &ImageReplayer::on_start_local_image_open_finish>(this);
+  OpenLocalImageRequest<> *request = OpenLocalImageRequest<>::create(
+    m_local_ioctx, &m_local_image_ctx, "", m_local_image_id,
+    m_threads->work_queue, ctx);
+  request->send();
 }
 
-void ImageReplayer::on_start_local_image_lock_start()
-{
-  dout(20) << "enter" << dendl;
-
-  RWLock::WLocker owner_locker(m_local_image_ctx->owner_lock);
-  FunctionContext *ctx = new FunctionContext(
-    [this](int r) {
-      on_start_local_image_lock_finish(r);
-    });
-  m_local_image_ctx->exclusive_lock->request_lock(ctx);
-}
-
-void ImageReplayer::on_start_local_image_lock_finish(int r)
+void ImageReplayer::on_start_local_image_open_finish(int r)
 {
   dout(20) << "r=" << r << dendl;
 
   if (r < 0) {
-    derr << "error to lock exclusively local image " <<  m_local_image_id
+    derr << "error opening local image " <<  m_local_image_id
         << ": " << cpp_strerror(r) << dendl;
     on_start_fail_start(r);
     return;
   }
-  if (m_local_image_ctx->journal == nullptr) {
-    on_start_fail_start(-EINVAL);
-    return;
-  }
   if (on_start_interrupted()) {
     return;
   }
@@ -696,12 +660,12 @@ void ImageReplayer::on_stop_local_image_close_start()
 {
   dout(20) << "enter" << dendl;
 
-  FunctionContext *ctx = new FunctionContext(
-    [this](int r) {
-      on_stop_local_image_close_finish(r);
-    });
-
-  m_local_image_ctx->state->close(ctx);
+  // close and delete the image (from outside the image's thread context)
+  Context *ctx = create_context_callback<
+    ImageReplayer, &ImageReplayer::on_stop_local_image_close_finish>(this);
+  CloseImageRequest<> *request = CloseImageRequest<>::create(
+    &m_local_image_ctx, m_threads->work_queue, ctx);
+  request->send();
 }
 
 void ImageReplayer::on_stop_local_image_close_finish(int r)
@@ -712,25 +676,6 @@ void ImageReplayer::on_stop_local_image_close_finish(int r)
     derr << "error closing local image: " << cpp_strerror(r) << dendl;
   }
 
-  on_stop_local_image_delete_start();
-}
-
-void ImageReplayer::on_stop_local_image_delete_start()
-{
-  FunctionContext *ctx = new FunctionContext(
-    [this](int r) {
-      delete m_local_image_ctx;
-      m_local_image_ctx = nullptr;
-      on_stop_local_image_delete_finish(r);
-    });
-
-  m_threads->work_queue->queue(ctx, 0);
-}
-
-void ImageReplayer::on_stop_local_image_delete_finish(int r)
-{
-  assert(r == 0);
-
   m_local_ioctx.close();
 
   m_remote_journaler->stop_replay();
@@ -861,28 +806,7 @@ void ImageReplayer::handle_replay_committed(
   m_remote_journaler->committed(*replay_entry);
 }
 
-int ImageReplayer::register_client()
-{
-  // TODO allocate snap as part of sync process
-  m_snap_name = ".rbd-mirror." + m_client_id;
-
-  dout(20) << "mirror_uuid=" << m_client_id << ", "
-           << "image_id=" << m_local_image_id << ", "
-          << "snap_name=" << m_snap_name << dendl;
-
-  bufferlist client_data;
-  ::encode(librbd::journal::ClientData{librbd::journal::MirrorPeerClientMeta{
-    m_local_image_id, {{m_snap_name, boost::none}}}}, client_data);
-  int r = m_remote_journaler->register_client(client_data);
-  if (r < 0) {
-    derr << "error registering client: " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  return 0;
-}
-
-int ImageReplayer::get_bootrstap_params(BootstrapParams *params)
+int ImageReplayer::get_bootstrap_params(BootstrapParams *params)
 {
   int r = librbd::cls_client::dir_get_name(&m_remote_ioctx, RBD_DIRECTORY,
                                           m_remote_image_id,
@@ -898,244 +822,6 @@ int ImageReplayer::get_bootrstap_params(BootstrapParams *params)
   return 0;
 }
 
-int ImageReplayer::bootstrap(const BootstrapParams &bootstrap_params)
-{
-  // Register client and sync images
-
-  dout(20) << "enter" << dendl;
-
-  int r;
-  BootstrapParams params;
-
-  if (!bootstrap_params.empty()) {
-    dout(20) << "using external bootstrap params" << dendl;
-    params = bootstrap_params;
-  } else {
-    r = get_bootrstap_params(&params);
-    if (r < 0) {
-      derr << "error obtaining bootstrap parameters: "
-          << cpp_strerror(r) << dendl;
-      return r;
-    }
-  }
-
-  dout(20) << "bootstrap params: local_pool_name=" << params.local_pool_name
-          << ", local_image_name=" << params.local_image_name << dendl;
-
-  r = create_local_image(params);
-  if (r < 0) {
-    derr << "error creating local image " << params.local_image_name
-        << " in pool " << params.local_pool_name << ": " << cpp_strerror(r)
-        << dendl;
-    return r;
-  }
-
-  r = register_client();
-  if (r < 0) {
-    derr << "error registering journal client: " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  r = copy();
-  if (r < 0) {
-    derr << "error copying data to local image: " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  dout(20) << "succeeded" << dendl;
-
-  return 0;
-}
-
-int ImageReplayer::create_local_image(const BootstrapParams &bootstrap_params)
-{
-  dout(20) << "enter" << dendl;
-
-  librbd::ImageCtx *image_ctx = new librbd::ImageCtx("", m_remote_image_id, nullptr,
-                                                    m_remote_ioctx, true);
-  int r = image_ctx->state->open();
-  if (r < 0) {
-    derr << "error opening remote image " << m_remote_image_id
-        << ": " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  uint64_t size = image_ctx->size;
-  uint64_t features = image_ctx->features;
-  int order = image_ctx->order;
-  uint64_t stripe_unit = image_ctx->stripe_unit;
-  uint64_t stripe_count = image_ctx->stripe_count;
-
-  image_ctx->state->close();
-
-  r = m_local->pool_lookup(bootstrap_params.local_pool_name.c_str());
-  if (r < 0) {
-    derr << "error finding local pool " << bootstrap_params.local_pool_name
-        << ": " << cpp_strerror(r) << dendl;
-    return r;
-  }
-  m_local_pool_id = r;
-
-  librados::IoCtx ioctx;
-  r = m_local->ioctx_create2(m_local_pool_id, ioctx);
-  if (r < 0) {
-    derr << "error opening ioctx for local pool " << m_local_pool_id
-        << ": " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  r = librbd::create(ioctx, bootstrap_params.local_image_name.c_str(), size,
-                    false, features, &order, stripe_unit, stripe_count);
-  if (r < 0) {
-    derr << "error creating local image " << m_local_image_id
-        << ": " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  r = get_image_id(ioctx, bootstrap_params.local_image_name, &m_local_image_id);
-  if (r < 0) {
-    derr << "error resolving ID for local image " << m_local_image_id
-        << ": " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  dout(20) << "created, image_id=" << m_local_image_id << dendl;
-
-  return 0;
-}
-
-int ImageReplayer::get_image_id(librados::IoCtx &ioctx,
-                               const std::string &image_name,
-                               std::string *image_id)
-{
-  librbd::ImageCtx *image_ctx = new librbd::ImageCtx(image_name, "", NULL,
-                                                    ioctx, true);
-  int r = image_ctx->state->open();
-  if (r < 0) {
-    derr << "error opening remote image " << image_name
-        << ": " << cpp_strerror(r) << dendl;
-    delete image_ctx;
-    return r;
-  }
-
-  *image_id = image_ctx->id;
-  image_ctx->state->close();
-  return 0;
-}
-
-int ImageReplayer::copy()
-{
-  dout(20) << m_remote_pool_id << "/" << m_remote_image_id << "->"
-          << m_local_pool_id << "/" << m_local_image_id << dendl;
-
-  librados::IoCtx local_ioctx;
-  librbd::ImageCtx *remote_image_ctx, *local_image_ctx;
-  librbd::NoOpProgressContext prog_ctx;
-  int r;
-
-  remote_image_ctx = new librbd::ImageCtx("", m_remote_image_id, nullptr,
-                                         m_remote_ioctx, false);
-  r = remote_image_ctx->state->open();
-  if (r < 0) {
-    derr << "error opening remote image " << m_remote_image_id
-        << ": " << cpp_strerror(r) << dendl;
-    delete remote_image_ctx;
-    return r;
-  }
-
-  dout(20) << "creating temporary snapshot " << m_snap_name << dendl;
-
-  // TODO: use internal snapshots
-  r = remote_image_ctx->operations->snap_create(m_snap_name.c_str());
-  if (r == -EEXIST) {
-    // Probably left after a previous unsuccessful bootsrapt.
-    dout(0) << "removing stale snapshot " << m_snap_name << " of remote image "
-           << m_remote_image_id << dendl;
-    (void)remote_image_ctx->operations->snap_remove(m_snap_name.c_str());
-    r = remote_image_ctx->operations->snap_create(m_snap_name.c_str());
-  }
-  if (r < 0) {
-    derr << "error creating snapshot " << m_snap_name << " of remote image "
-        << m_remote_image_id << ": " << cpp_strerror(r) << dendl;
-    goto cleanup;
-  }
-
-  remote_image_ctx->state->close();
-  remote_image_ctx = new librbd::ImageCtx("", m_remote_image_id,
-                                         m_snap_name.c_str(), m_remote_ioctx,
-                                         true);
-  r = remote_image_ctx->state->open();
-  if (r < 0) {
-    derr << "error opening snapshot " << m_snap_name << " of remote image "
-        << m_remote_image_id << ": " << cpp_strerror(r) << dendl;
-    delete remote_image_ctx;
-    remote_image_ctx = nullptr;
-    goto cleanup;
-  }
-
-  r = m_local->ioctx_create2(m_local_pool_id, local_ioctx);
-  if (r < 0) {
-    derr << "error opening ioctx for local pool " << m_local_pool_id
-        << ": " << cpp_strerror(r) << dendl;
-    goto cleanup;
-  }
-
-  local_image_ctx = new librbd::ImageCtx("", m_local_image_id, nullptr,
-                                        local_ioctx, false);
-  r = local_image_ctx->state->open();
-  if (r < 0) {
-    derr << "error opening local image " << m_local_image_id
-        << ": " << cpp_strerror(r) << dendl;
-    delete local_image_ctx;
-    local_image_ctx = nullptr;
-    goto cleanup;
-  }
-
-  dout(20) << "copying" << dendl;
-
-  // TODO: show copy progress in image replay status
-  r = librbd::copy(remote_image_ctx, local_image_ctx, prog_ctx);
-  if (r < 0) {
-    derr << "error copying snapshot " << m_snap_name << " of remote image "
-        << m_remote_image_id << " to local image " << m_local_image_id
-        << ": " << cpp_strerror(r) << dendl;
-  }
-
-  local_image_ctx->state->close();
-  local_image_ctx = nullptr;
-
-  remote_image_ctx->state->close();
-  remote_image_ctx = nullptr;
-
-  dout(20) << "done" << dendl;
-
-cleanup:
-  if (local_image_ctx) {
-    local_image_ctx->state->close();
-  }
-  if (remote_image_ctx) {
-    remote_image_ctx->state->close();
-  }
-  remote_image_ctx = new librbd::ImageCtx("", m_remote_image_id, nullptr,
-                                         m_remote_ioctx, false);
-  int r1 = remote_image_ctx->state->open();
-  if (r1 < 0) {
-    derr << "error opening remote image " << m_remote_image_id
-        << ": " << cpp_strerror(r1) << dendl;
-    delete remote_image_ctx;
-  } else {
-    dout(20) << "removing temporary snapshot " << m_snap_name << dendl;
-    r1 = remote_image_ctx->operations->snap_remove(m_snap_name.c_str());
-    if (r1 < 0) {
-      derr << "error removing snapshot " << m_snap_name << " of remote image "
-          << m_remote_image_id << ": " << cpp_strerror(r1) << dendl;
-    }
-    remote_image_ctx->state->close();
-  }
-
-  return r;
-}
-
 void ImageReplayer::shut_down_journal_replay(bool cancel_ops)
 {
   C_SaferCond cond;
index f3c91768b774d8a2e1bb1bda7ac2eb40e551327a..9dc26e1bf1934e97e2f6d40a2e4cef35f147ba2f 100644 (file)
@@ -12,6 +12,7 @@
 #include "common/WorkQueue.h"
 #include "include/rados/librados.hpp"
 #include "cls/journal/cls_journal_types.h"
+#include "librbd/journal/Types.h"
 #include "types.h"
 
 namespace journal {
@@ -69,7 +70,6 @@ public:
     }
   };
 
-public:
   ImageReplayer(Threads *threads, RadosRef local, RadosRef remote,
                const std::string &client_id, int64_t local_pool_id,
                int64_t remote_pool_id, const std::string &remote_image_id);
@@ -86,8 +86,6 @@ public:
   void stop(Context *on_finish = nullptr);
   int flush();
 
-  int bootstrap(const BootstrapParams &bootstrap_params);
-
   virtual void handle_replay_ready();
   virtual void handle_replay_process_ready(int r);
   virtual void handle_replay_complete(int r);
@@ -98,28 +96,31 @@ protected:
   /**
    * @verbatim
    *                   (error)
-   * <uninitialized> <------------------- FAIL
-   *    |                                  ^
-   *    v                                  |
-   * <starting>                            |
-   *    |                                  |
-   *    v                         (error)  |
-   * GET_REGISTERED_CLIENT_STATUS -------->|
-   *    |                                  |
-   *    v                           (error)|
-   * BOOTSTRAP (skip if not needed) ------>|
-   *    |                                  |
-   *    v                  (error)         |
-   * REMOTE_JOURNALER_INIT --------------->|
-   *    |                                  |
-   *    v             (error)              |
-   * LOCAL_IMAGE_OPEN -------------------->|
-   *    |                                  |
-   *    v             (error)              |
-   * LOCAL_IMAGE_LOCK -------------------->|
-   *    |                                  |
-   *    v                         (error)  |
-   * WAIT_FOR_LOCAL_JOURNAL_READY -------->/
+   * <uninitialized> <------------------------ FAIL
+   *    |                                       ^
+   *    v                                       *
+   * <starting>                                 *
+   *    |                                       *
+   *    v                               (error) *
+   * GET_REGISTERED_CLIENT_STATUS * * * * * * * *
+   *    |                                       *
+   *    | (sync required)                       *
+   *    |\-----\                                *
+   *    |      |                                *
+   *    |      v                                *
+   *    |   BOOTSTRAP_IMAGE * * * * * * * * * * *
+   *    |      |                                *
+   *    |      v                                *
+   *    |/-----/                                *
+   *    |                                       *
+   *    v (no sync required)            (error) *
+   * REMOTE_JOURNALER_INIT  * * * * * * * * * * *
+   *    |                                       *
+   *    v                               (error) *
+   * LOCAL_IMAGE_OPEN (skip if not              *
+   *    |              needed                   *
+   *    v                               (error) *
+   * WAIT_FOR_LOCAL_JOURNAL_READY * * * * * * * *
    *    |
    *    v
    * <replaying>
@@ -134,9 +135,6 @@ protected:
    * LOCAL_IMAGE_CLOSE
    *    |
    *    v
-   * LOCAL_IMAGE_DELETE
-   *    |
-   *    v
    * <stopped>
    *
    * @endverbatim
@@ -147,14 +145,14 @@ protected:
   virtual void on_start_get_registered_client_status_finish(int r,
     const std::set<cls::journal::Client> &registered_clients,
     const BootstrapParams &bootstrap_params);
-  virtual void on_start_bootstrap_start(const BootstrapParams &params);
-  virtual void on_start_bootstrap_finish(int r);
+
+  void bootstrap(const BootstrapParams &params);
+  void handle_bootstrap(int r);
+
   virtual void on_start_remote_journaler_init_start();
   virtual void on_start_remote_journaler_init_finish(int r);
   virtual void on_start_local_image_open_start();
   virtual void on_start_local_image_open_finish(int r);
-  virtual void on_start_local_image_lock_start();
-  virtual void on_start_local_image_lock_finish(int r);
   virtual void on_start_wait_for_local_journal_ready_start();
   virtual void on_start_wait_for_local_journal_ready_finish(int r);
   virtual void on_start_fail_start(int r);
@@ -165,8 +163,6 @@ protected:
   virtual void on_stop_journal_replay_shut_down_finish(int r);
   virtual void on_stop_local_image_close_start();
   virtual void on_stop_local_image_close_finish(int r);
-  virtual void on_stop_local_image_delete_start();
-  virtual void on_stop_local_image_delete_finish(int r);
 
   void close_local_image(Context *on_finish); // for tests
 
@@ -176,25 +172,18 @@ private:
                                     m_state == STATE_STOPPED; }
   bool is_running_() const { return !is_stopped_() && m_state != STATE_STOPPING; }
 
-  int get_bootrstap_params(BootstrapParams *params);
-  int register_client();
-  int create_local_image(const BootstrapParams &bootstrap_params);
-  int get_image_id(librados::IoCtx &ioctx, const std::string &image_name,
-                  std::string *image_id);
-  int copy();
+  int get_bootstrap_params(BootstrapParams *params);
 
   void shut_down_journal_replay(bool cancel_ops);
 
   friend std::ostream &operator<<(std::ostream &os,
                                  const ImageReplayer &replayer);
-private:
+
   Threads *m_threads;
   RadosRef m_local, m_remote;
   std::string m_client_id;
   int64_t m_remote_pool_id, m_local_pool_id;
   std::string m_remote_image_id, m_local_image_id;
-  std::string m_snap_name;
-  ContextWQ *m_work_queue;
   Mutex m_lock;
   State m_state;
   std::string m_local_pool_name, m_remote_pool_name;
@@ -205,6 +194,8 @@ private:
   ::journal::ReplayHandler *m_replay_handler;
   Context *m_on_finish;
   ImageReplayerAdminSocketHook *m_asok_hook;
+
+  librbd::journal::MirrorPeerClientMeta m_client_meta;
 };
 
 } // namespace mirror