]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: clean up bootstrap recovery from missing local image
authorJason Dillaman <dillaman@redhat.com>
Wed, 19 Jul 2017 18:24:36 +0000 (14:24 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 7 Aug 2017 14:13:33 +0000 (10:13 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc
src/tools/rbd_mirror/image_replayer/BootstrapRequest.h

index c7b995387e1d3b8e8f0dcf9d3064c028fb7ba008..4ed498370a705953a55bd3a952d6c87741d07fb4 100644 (file)
@@ -325,6 +325,14 @@ public:
                                   })));
   }
 
+  void expect_journaler_unregister_client(::journal::MockJournaler &mock_journaler,
+                                          int r) {
+    EXPECT_CALL(mock_journaler, unregister_client(_))
+      .WillOnce(Invoke([this, r](Context *on_finish) {
+                  m_threads->work_queue->queue(on_finish, r);
+                }));
+  }
+
   void expect_journaler_update_client(::journal::MockJournaler &mock_journaler,
                                       const librbd::journal::ClientData &client_data,
                                       int r) {
@@ -468,6 +476,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteSyncingState) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
@@ -479,12 +494,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteSyncingState) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, false, 0);
 
@@ -521,6 +531,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
@@ -532,12 +549,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -595,6 +607,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
@@ -606,12 +625,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -679,6 +693,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
@@ -690,12 +711,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -751,6 +767,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
@@ -762,12 +785,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -823,6 +841,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
@@ -834,12 +859,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -883,6 +903,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   client = {};
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
@@ -893,12 +920,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
   client_data.client_meta = mirror_peer_client_meta;
   expect_journaler_register_client(mock_journaler, client_data, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -955,6 +977,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
                               librbd::Journal<>::IMAGE_CLIENT_ID,
                               client, 0);
 
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
   // lookup local peer in remote journal
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
     "missing image id"};
@@ -965,12 +994,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
   expect_journaler_get_client(mock_journaler, "local mirror uuid",
                               client, 0);
 
-  // open the remote image
-  librbd::MockJournal mock_journal;
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  MockOpenImageRequest mock_open_image_request;
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+  // test if remote image is primary
   MockIsPrimaryRequest mock_is_primary_request;
   expect_is_primary(mock_is_primary_request, true, 0);
 
@@ -979,6 +1003,15 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
   expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
                           "missing image id", nullptr, -ENOENT);
 
+  // re-register the client
+  expect_journaler_unregister_client(mock_journaler, 0);
+  mirror_peer_client_meta = {};
+  client_data.client_meta = mirror_peer_client_meta;
+  expect_journaler_register_client(mock_journaler, client_data, 0);
+
+  // test if remote image is primary
+  expect_is_primary(mock_is_primary_request, true, 0);
+
   // create the missing local image
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   mock_local_image_ctx.journal = &mock_journal;
index 434aa783c05055bf32c6773ef527b976a97d8abc..8fdf1b270b9ecec35e60d517b0200b90fa8cb3bc 100644 (file)
@@ -143,6 +143,35 @@ void BootstrapRequest<I>::handle_get_remote_tag_class(int r) {
   m_remote_tag_class = client_meta->tag_class;
   dout(10) << ": remote tag class=" << m_remote_tag_class << dendl;
 
+  open_remote_image();
+}
+
+template <typename I>
+void BootstrapRequest<I>::open_remote_image() {
+  dout(20) << dendl;
+
+  update_progress("OPEN_REMOTE_IMAGE");
+
+  Context *ctx = create_context_callback<
+    BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_remote_image>(
+      this);
+  OpenImageRequest<I> *request = OpenImageRequest<I>::create(
+    m_remote_io_ctx, &m_remote_image_ctx, m_remote_image_id, false,
+    ctx);
+  request->send();
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_open_remote_image(int r) {
+  dout(20) << ": r=" << r << dendl;
+
+  if (r < 0) {
+    derr << ": failed to open remote image: " << cpp_strerror(r) << dendl;
+    assert(m_remote_image_ctx == nullptr);
+    finish(r);
+    return;
+  }
+
   get_client();
 }
 
@@ -166,11 +195,12 @@ void BootstrapRequest<I>::handle_get_client(int r) {
     dout(10) << ": client not registered" << dendl;
   } else if (r < 0) {
     derr << ": failed to retrieve client: " << cpp_strerror(r) << dendl;
-    finish(r);
+    m_ret_val = r;
+    close_remote_image();
     return;
   } else if (decode_client_meta()) {
     // skip registration if it already exists
-    open_remote_image();
+    is_primary();
     return;
   }
 
@@ -202,40 +232,12 @@ void BootstrapRequest<I>::handle_register_client(int r) {
   if (r < 0) {
     derr << ": failed to register with remote journal: " << cpp_strerror(r)
          << dendl;
-    finish(r);
+    m_ret_val = r;
+    close_remote_image();
     return;
   }
 
   *m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
-  open_remote_image();
-}
-
-template <typename I>
-void BootstrapRequest<I>::open_remote_image() {
-  dout(20) << dendl;
-
-  update_progress("OPEN_REMOTE_IMAGE");
-
-  Context *ctx = create_context_callback<
-    BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_remote_image>(
-      this);
-  OpenImageRequest<I> *request = OpenImageRequest<I>::create(
-    m_remote_io_ctx, &m_remote_image_ctx, m_remote_image_id, false,
-    ctx);
-  request->send();
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_open_remote_image(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to open remote image: " << cpp_strerror(r) << dendl;
-    assert(m_remote_image_ctx == nullptr);
-    finish(r);
-    return;
-  }
-
   is_primary();
 }
 
@@ -311,7 +313,7 @@ void BootstrapRequest<I>::handle_update_client_state(int r) {
   if (r < 0) {
     derr << ": failed to update client: " << cpp_strerror(r) << dendl;
   } else {
-    m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;;
+    m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
   }
 
   close_remote_image();
@@ -339,7 +341,7 @@ void BootstrapRequest<I>::handle_open_local_image(int r) {
   if (r == -ENOENT) {
     assert(*m_local_image_ctx == nullptr);
     dout(10) << ": local image missing" << dendl;
-    create_local_image();
+    unregister_client();
     return;
   } else if (r == -EREMOTEIO) {
     assert(*m_local_image_ctx == nullptr);
@@ -390,6 +392,33 @@ void BootstrapRequest<I>::handle_open_local_image(int r) {
   update_client_image();
 }
 
+template <typename I>
+void BootstrapRequest<I>::unregister_client() {
+  dout(20) << dendl;
+  update_progress("UNREGISTER_CLIENT");
+
+  m_local_image_id = "";
+  Context *ctx = create_context_callback<
+    BootstrapRequest<I>, &BootstrapRequest<I>::handle_unregister_client>(
+      this);
+  m_journaler->unregister_client(ctx);
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_unregister_client(int r) {
+  dout(20) << ": r=" << r << dendl;
+  if (r < 0) {
+    derr << ": failed to unregister with remote journal: " << cpp_strerror(r)
+         << dendl;
+    m_ret_val = r;
+    close_remote_image();
+    return;
+  }
+
+  *m_client_meta = librbd::journal::MirrorPeerClientMeta("");
+  register_client();
+}
+
 template <typename I>
 void BootstrapRequest<I>::create_local_image() {
   dout(20) << dendl;
@@ -426,10 +455,6 @@ void BootstrapRequest<I>::handle_create_local_image(int r) {
 
 template <typename I>
 void BootstrapRequest<I>::update_client_image() {
-  dout(20) << dendl;
-
-  update_progress("UPDATE_CLIENT_IMAGE");
-
   if (m_client_meta->image_id == (*m_local_image_ctx)->id) {
     // already registered local image with remote journal
     get_remote_tags();
@@ -438,6 +463,7 @@ void BootstrapRequest<I>::update_client_image() {
   m_local_image_id = (*m_local_image_ctx)->id;
 
   dout(20) << dendl;
+  update_progress("UPDATE_CLIENT_IMAGE");
 
   librbd::journal::MirrorPeerClientMeta client_meta{m_local_image_id};
   client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
@@ -459,14 +485,14 @@ void BootstrapRequest<I>::handle_update_client_image(int r) {
   if (r < 0) {
     derr << ": failed to update client: " << cpp_strerror(r) << dendl;
     m_ret_val = r;
-    close_local_image();
+    close_remote_image();
     return;
   }
 
   if (m_canceled) {
     dout(10) << ": request canceled" << dendl;
     m_ret_val = -ECANCELED;
-    close_local_image();
+    close_remote_image();
     return;
   }
 
index cebd568972ba88efaf9c21ed248d30646d54e6d8..668dd8375d4b797c4de824f050a8996f61eed357 100644 (file)
@@ -92,57 +92,55 @@ private:
    * <start>
    *    |
    *    v
-   * GET_REMOTE_TAG_CLASS * * * * * * * * * * * * * * * *
-   *    |                                               *
-   *    v                                               *
-   * GET_CLIENT * * * * * * * * * * * * * * * * * * * * *
-   *    |                                               *
-   *    v (skip if not needed)                          * (error)
-   * REGISTER_CLIENT  * * * * * * * * * * * * * * * * * *
-   *    |                                               *
-   *    v                                               *
-   * OPEN_REMOTE_IMAGE  * * * * * * * * * * * * * * * * *
-   *    |                                               *
-   *    v                                               *
-   * IS_PRIMARY * * * * * * * * * * * * * * * * * * * * *
-   *    |                                               *
-   *    | (remote image primary)                        *
-   *    \----> OPEN_LOCAL_IMAGE * * * * * * * * * * * * *
-   *    |         |   .   ^                             *
-   *    |         |   .   |                             *
-   *    |         |   .   \-----------------------\     *
-   *    |         |   .                           |     *
-   *    |         |   . (image sync requested)    |     *
-   *    |         |   . . > REMOVE_LOCAL_IMAGE  * * * * *
-   *    |         |   .                   |       |     *
-   *    |         |   . (image doesn't    |       |     *
-   *    |         |   .  exist)           v       |     *
-   *    |         |   . . > CREATE_LOCAL_IMAGE  * * * * *
-   *    |         |             |                 |     *
-   *    |         |             \-----------------/     *
-   *    |         |                                     *
-   *    |         v (skip if not needed)                *
-   *    |      UPDATE_CLIENT_IMAGE  * * * * *           *
-   *    |         |                         *           *
-   *    |         v (skip if not needed)    *           *
-   *    |      GET_REMOTE_TAGS  * * * * * * *           *
-   *    |         |                         *           *
-   *    |         v (skip if not needed)    v           *
-   *    |      IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE     *
-   *    |         |                         |           *
-   *    |         \-----------------\ /-----/           *
-   *    |                            |                  *
-   *    |                            |                  *
-   *    | (skip if not needed)       |                  *
-   *    \----> UPDATE_CLIENT_STATE  *|* * * * * * * * * *
-   *                |                |                  *
-   *    /-----------/----------------/                  *
-   *    |                                               *
-   *    v                                               *
-   * CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * *
-   *    |
-   *    v
-   * <finish>
+   * GET_REMOTE_TAG_CLASS * * * * * * * * * * * * * * * * * *
+   *    |                                                   * (error)
+   *    v                                                   *
+   * OPEN_REMOTE_IMAGE  * * * * * * * * * * * * * * * * * * *
+   *    |                                                   *
+   *    v                                                   *
+   * GET_CLIENT * * * * * * * * * * * * * * * * * * * * *   *
+   *    |                                               *   *
+   *    |/----------------------------------------------*---*---\
+   *    v (skip if not needed)                          *   *   |
+   * REGISTER_CLIENT  * * * * * * * * * * * * * * * * * *   *   |
+   *    |                                               *   *   |
+   *    v                                               *   *   |
+   * IS_PRIMARY * * * * * * * * * * * * * * * * * * * * *   *   |
+   *    |                                               *   *   |
+   *    | (remote image primary, no local image id)     *   *   |
+   *    \----> CREATE_LOCAL_IMAGE * * * * * * * * * * * *   *   |
+   *    |         |                                     *   *   |
+   *    |         v                                     *   *   |
+   *    | (remote image primary)                        *   *   |
+   *    \----> OPEN_LOCAL_IMAGE * * * * * * * * * * * * *   *   |
+   *    |         |   .                                 *   *   |
+   *    |         |   . (image doesn't exist)           *   *   |
+   *    |         |   . . > UNREGISTER_CLIENT * * * * * *   *   |
+   *    |         |             |                       *   *   |
+   *    |         |             \-----------------------*---*---/
+   *    |         |                                     *   *
+   *    |         v (skip if not needed)                *   *
+   *    |      UPDATE_CLIENT_IMAGE  * * * * *           *   *
+   *    |         |                         *           *   *
+   *    |         v (skip if not needed)    *           *   *
+   *    |      GET_REMOTE_TAGS  * * * * * * *           *   *
+   *    |         |                         *           *   *
+   *    |         v (skip if not needed)    v           *   *
+   *    |      IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE     *   *
+   *    |         |                         |           *   *
+   *    |         \-----------------\ /-----/           *   *
+   *    |                            |                  *   *
+   *    |                            |                  *   *
+   *    | (skip if not needed)       |                  *   *
+   *    \----> UPDATE_CLIENT_STATE  *|* * * * * * * * * *   *
+   *                |                |                  *   *
+   *    /-----------/----------------/                  *   *
+   *    |                                               *   *
+   *    v                                               *   *
+   * CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * *   *
+   *    |                                                   *
+   *    v                                                   *
+   * <finish> < * * * * * * * * * * * * * * * * * * * * * * *
    *
    * @endverbatim
    */
@@ -199,8 +197,8 @@ private:
   void open_local_image();
   void handle_open_local_image(int r);
 
-  void remove_local_image();
-  void handle_remove_local_image(int r);
+  void unregister_client();
+  void handle_unregister_client(int r);
 
   void create_local_image();
   void handle_create_local_image(int r);