]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: test: Added unit test for testing image-deleter thread
authorRicardo Dias <rdias@suse.com>
Tue, 19 Apr 2016 11:35:49 +0000 (12:35 +0100)
committerJason Dillaman <dillaman@redhat.com>
Sun, 22 May 2016 20:13:21 +0000 (16:13 -0400)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/test/Makefile-client.am
src/test/rbd_mirror/CMakeLists.txt
src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc
src/test/rbd_mirror/test_ImageDeleter.cc [new file with mode: 0644]
src/test/rbd_mirror/test_fixture.cc
src/test/rbd_mirror/test_fixture.h
src/test/rbd_mirror/test_main.cc
src/tools/rbd_mirror/ImageDeleter.cc
src/tools/rbd_mirror/ImageDeleter.h

index 065bc9053df935384e54bba5eb4d9962718d8404..9acdbe7ba21abc7af68e151192524a499fbac00d 100644 (file)
@@ -463,6 +463,7 @@ librbd_mirror_test_la_SOURCES = \
        test/rbd_mirror/test_ClusterWatcher.cc \
        test/rbd_mirror/test_PoolWatcher.cc \
        test/rbd_mirror/test_ImageReplayer.cc \
+        test/rbd_mirror/test_ImageDeleter.cc \
        test/rbd_mirror/test_ImageSync.cc \
        test/rbd_mirror/test_fixture.cc
 
index dd984e47a11b270ca690097a398083408b6c15b2..4cd2d6a46c01e05ff08778f50922efb9785f5e3c 100644 (file)
@@ -2,6 +2,7 @@ set(rbd_mirror_test_srcs
   test_ClusterWatcher.cc
   test_PoolWatcher.cc
   test_ImageReplayer.cc
+  test_ImageDeleter.cc
   test_ImageSync.cc
   test_fixture.cc
   )
index 0b72167d03f5f514219404730f80c1ec3f391a78..9c697363fd34f4abe9f7dd279ca7f87eea3d6b79 100644 (file)
@@ -358,10 +358,10 @@ TEST_F(TestMockImageSyncImageCopyRequest, RestartPartialSync) {
 
 TEST_F(TestMockImageSyncImageCopyRequest, Cancel) {
   std::string max_ops_str;
-  ASSERT_EQ(0, _rados.conf_get("rbd_concurrent_management_ops", max_ops_str));
-  ASSERT_EQ(0, _rados.conf_set("rbd_concurrent_management_ops", "1"));
+  ASSERT_EQ(0, _rados->conf_get("rbd_concurrent_management_ops", max_ops_str));
+  ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", "1"));
   BOOST_SCOPE_EXIT( (max_ops_str) ) {
-    ASSERT_EQ(0, _rados.conf_set("rbd_concurrent_management_ops", max_ops_str.c_str()));
+    ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", max_ops_str.c_str()));
   } BOOST_SCOPE_EXIT_END;
 
   ASSERT_EQ(0, create_snap("snap1"));
diff --git a/src/test/rbd_mirror/test_ImageDeleter.cc b/src/test/rbd_mirror/test_ImageDeleter.cc
new file mode 100644 (file)
index 0000000..b513492
--- /dev/null
@@ -0,0 +1,442 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2016 SUSE LINUX GmbH
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+#include "include/rados/librados.hpp"
+#include "include/rbd/librbd.hpp"
+#include "include/stringify.h"
+#include "cls/rbd/cls_rbd_client.h"
+#include "tools/rbd_mirror/ImageDeleter.h"
+#include "tools/rbd_mirror/ImageReplayer.h"
+#include "tools/rbd_mirror/Threads.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageState.h"
+#include "librbd/Operations.h"
+#include "librbd/Journal.h"
+#include "librbd/internal.h"
+#include "librbd/Utils.h"
+#include "test/rbd_mirror/test_fixture.h"
+
+#include "test/librados/test.h"
+#include "gtest/gtest.h"
+
+#define GLOBAL_IMAGE_ID "global_image_id"
+#define GLOBAL_CLONE_IMAGE_ID "global_image_id_clone"
+
+#define dout_subsys ceph_subsys_rbd_mirror
+
+using rbd::mirror::RadosRef;
+using rbd::mirror::TestFixture;
+using namespace librbd;
+using cls::rbd::MirrorImageState;
+
+
+void register_test_rbd_mirror_image_deleter() {
+}
+
+class TestImageDeleter : public TestFixture {
+public:
+
+  static int64_t m_local_pool_id;
+
+  const std::string m_local_mirror_uuid = "local mirror uuid";
+  const std::string m_remote_mirror_uuid = "remote mirror uuid";
+
+  static void SetUpTestCase() {
+    TestFixture::SetUpTestCase();
+
+    m_local_pool_id = _rados->pool_lookup(_local_pool_name.c_str());
+  }
+
+  void SetUp() {
+    TestFixture::SetUp();
+
+    librbd::mirror_mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
+
+    m_deleter = new rbd::mirror::ImageDeleter(_rados,
+        m_threads->timer, &m_threads->timer_lock);
+
+    EXPECT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, 1 << 20));
+    ImageCtx *ictx = new ImageCtx(m_image_name, "", "", m_local_io_ctx,
+                                  false);
+    EXPECT_EQ(0, ictx->state->open());
+    m_local_image_id = ictx->id;
+
+    cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
+                                MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
+    EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, ictx->id,
+                                              mirror_image));
+
+    demote_image(ictx);
+    EXPECT_EQ(0, ictx->state->close());
+  }
+
+  void TearDown() {
+    remove_image();
+    TestFixture::TearDown();
+    delete m_deleter;
+  }
+
+  void remove_image(bool force=false) {
+    if (!force) {
+      cls::rbd::MirrorImage mirror_image;
+      int r = cls_client::mirror_image_get(&m_local_io_ctx, m_local_image_id,
+                                           &mirror_image);
+      EXPECT_EQ(1, r == 0 || r == -ENOENT);
+      if (r != -ENOENT) {
+        mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
+        EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx,
+                                                  m_local_image_id,
+                                                  mirror_image));
+      }
+      promote_image();
+    }
+    NoOpProgressContext ctx;
+    int r = remove(m_local_io_ctx, m_image_name.c_str(), ctx, force);
+    EXPECT_EQ(1, r == 0 || r == -ENOENT);
+  }
+
+  void promote_image(ImageCtx *ictx=nullptr) {
+    bool close = false;
+    int r = 0;
+    if (!ictx) {
+      ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                          false);
+      r = ictx->state->open();
+      close = (r == 0);
+    }
+
+    EXPECT_EQ(1, r == 0 || r == -ENOENT);
+
+    if (r == 0) {
+        int r2 = librbd::mirror_image_promote(ictx, true);
+        EXPECT_EQ(1, r2 == 0 || r2 == -EINVAL);
+    }
+
+    if (close) {
+      EXPECT_EQ(0, ictx->state->close());
+    }
+  }
+
+  void demote_image(ImageCtx *ictx=nullptr) {
+    bool close = false;
+    if (!ictx) {
+      ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                          false);
+      EXPECT_EQ(0, ictx->state->open());
+      close = true;
+    }
+
+    EXPECT_EQ(0, librbd::mirror_image_demote(ictx));
+
+    if (close) {
+      EXPECT_EQ(0, ictx->state->close());
+    }
+  }
+
+  void create_snapshot(std::string snap_name="snap1", bool protect=false) {
+    ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                                  false);
+    EXPECT_EQ(0, ictx->state->open());
+    promote_image(ictx);
+
+    EXPECT_EQ(0, ictx->operations->snap_create(snap_name.c_str()));
+
+    if (protect) {
+      EXPECT_EQ(0, ictx->operations->snap_protect(snap_name.c_str()));
+    }
+
+    demote_image(ictx);
+    EXPECT_EQ(0, ictx->state->close());
+  }
+
+  std::string create_clone() {
+    ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                                  false);
+    EXPECT_EQ(0, ictx->state->open());
+    promote_image(ictx);
+
+    EXPECT_EQ(0, ictx->operations->snap_create("snap1"));
+    EXPECT_EQ(0, ictx->operations->snap_protect("snap1"));
+    int order = 20;
+    EXPECT_EQ(0, librbd::clone(m_local_io_ctx, ictx->name.c_str(), "snap1",
+                               m_local_io_ctx,  "clone1", ictx->features,
+                               &order, 0, 0));
+    std::string clone_id;
+    ImageCtx *ictx_clone = new ImageCtx("clone1", "", "", m_local_io_ctx,
+                                        false);
+    EXPECT_EQ(0, ictx_clone->state->open());
+    clone_id = ictx_clone->id;
+    cls::rbd::MirrorImage mirror_image(GLOBAL_CLONE_IMAGE_ID,
+                                MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
+    EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, clone_id,
+                                              mirror_image));
+    demote_image(ictx_clone);
+    EXPECT_EQ(0, ictx_clone->state->close());
+
+    demote_image(ictx);
+    EXPECT_EQ(0, ictx->state->close());
+
+    return clone_id;
+  }
+
+  void check_image_deleted() {
+    ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                                  false);
+    EXPECT_EQ(-ENOENT, ictx->state->open());
+    delete ictx;
+
+    cls::rbd::MirrorImage mirror_image;
+    EXPECT_EQ(-ENOENT, cls_client::mirror_image_get(&m_local_io_ctx,
+                                                    m_local_image_id,
+                                                    &mirror_image));
+  }
+
+
+  librbd::RBD rbd;
+  std::string m_local_image_id;
+  rbd::mirror::ImageDeleter *m_deleter;
+};
+
+int64_t TestImageDeleter::m_local_pool_id;
+
+
+TEST_F(TestImageDeleter, Delete_NonPrimary_Image) {
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+
+  check_image_deleted();
+}
+
+TEST_F(TestImageDeleter, Fail_Delete_Primary_Image) {
+  promote_image();
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(-rbd::mirror::ImageDeleter::EISPRM, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Fail_Delete_Diff_GlobalId) {
+  // This test case represents a case that should never happen, unless
+  // there is bug in the implementation
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, "diff global id");
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(-EINVAL, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Delete_Image_With_Child) {
+  create_snapshot();
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Delete_Image_With_Children) {
+  create_snapshot("snap1");
+  create_snapshot("snap2");
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChild) {
+  create_snapshot("snap1", true);
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChildren) {
+  create_snapshot("snap1", true);
+  create_snapshot("snap2", true);
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Delete_Image_With_Clone) {
+  std::string clone_id = create_clone();
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(-EBUSY, ctx.wait());
+
+  ASSERT_EQ(1u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+
+  m_deleter->schedule_image_delete(m_local_pool_id, clone_id,
+      "clone1", GLOBAL_CLONE_IMAGE_ID);
+
+  C_SaferCond ctx2;
+  m_deleter->wait_for_scheduled_deletion("clone1", &ctx2);
+  EXPECT_EQ(0, ctx2.wait());
+
+  C_SaferCond ctx3;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx3);
+  EXPECT_EQ(0, ctx3.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+}
+
+TEST_F(TestImageDeleter, Delete_NonExistent_Image) {
+  remove_image();
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+
+  check_image_deleted();
+}
+
+TEST_F(TestImageDeleter, Delete_NonExistent_Image_With_MirroringState) {
+  remove_image(true);
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(0, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+
+  check_image_deleted();
+}
+
+TEST_F(TestImageDeleter, Fail_Delete_NonPrimary_Image) {
+  ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                                false);
+  EXPECT_EQ(0, ictx->state->open());
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(-EBUSY, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
+
+  EXPECT_EQ(0, ictx->state->close());
+}
+
+TEST_F(TestImageDeleter, Retry_Failed_Deletes) {
+  ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                                false);
+  EXPECT_EQ(0, ictx->state->open());
+
+  m_deleter->set_failed_timer_interval(2);
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(-EBUSY, ctx.wait());
+
+  EXPECT_EQ(0, ictx->state->close());
+
+  C_SaferCond ctx2;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx2);
+  EXPECT_EQ(0, ctx2.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
+
+  check_image_deleted();
+}
+
+TEST_F(TestImageDeleter, Delete_Is_Idempotent) {
+  ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
+                                false);
+  EXPECT_EQ(0, ictx->state->open());
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  C_SaferCond ctx;
+  m_deleter->wait_for_scheduled_deletion(m_image_name, &ctx);
+  EXPECT_EQ(-EBUSY, ctx.wait());
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
+
+  m_deleter->schedule_image_delete(m_local_pool_id, m_local_image_id,
+      m_image_name, GLOBAL_IMAGE_ID);
+
+  ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
+  ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
+
+  EXPECT_EQ(0, ictx->state->close());
+}
+
+
index b99b9fc6bd83bab5ef11e8dccf71eac04186fb39..b1eb489d97aab04db73658d53604e606d7311895 100644 (file)
@@ -15,27 +15,28 @@ namespace mirror {
 
 std::string TestFixture::_local_pool_name;
 std::string TestFixture::_remote_pool_name;
-librados::Rados TestFixture::_rados;
+std::shared_ptr<librados::Rados> TestFixture::_rados;
 uint64_t TestFixture::_image_number = 0;
 
 TestFixture::TestFixture() {
 }
 
 void TestFixture::SetUpTestCase() {
-  ASSERT_EQ("", connect_cluster_pp(_rados));
-  ASSERT_EQ(0, _rados.conf_set("rbd_cache", "false"));
+  _rados = std::shared_ptr<librados::Rados>(new librados::Rados());
+  ASSERT_EQ("", connect_cluster_pp(*_rados.get()));
+  ASSERT_EQ(0, _rados->conf_set("rbd_cache", "false"));
 
   _local_pool_name = get_temp_pool_name("test-rbd-mirror-");
-  ASSERT_EQ(0, _rados.pool_create(_local_pool_name.c_str()));
+  ASSERT_EQ(0, _rados->pool_create(_local_pool_name.c_str()));
 
   _remote_pool_name = get_temp_pool_name("test-rbd-mirror-");
-  ASSERT_EQ(0, _rados.pool_create(_remote_pool_name.c_str()));
+  ASSERT_EQ(0, _rados->pool_create(_remote_pool_name.c_str()));
 }
 
 void TestFixture::TearDownTestCase() {
-  ASSERT_EQ(0, _rados.pool_delete(_remote_pool_name.c_str()));
-  ASSERT_EQ(0, _rados.pool_delete(_local_pool_name.c_str()));
-  _rados.shutdown();
+  ASSERT_EQ(0, _rados->pool_delete(_remote_pool_name.c_str()));
+  ASSERT_EQ(0, _rados->pool_delete(_local_pool_name.c_str()));
+  _rados->shutdown();
 }
 
 void TestFixture::SetUp() {
@@ -47,8 +48,8 @@ void TestFixture::SetUp() {
     srand(seed);
   }
 
-  ASSERT_EQ(0, _rados.ioctx_create(_local_pool_name.c_str(), m_local_io_ctx));
-  ASSERT_EQ(0, _rados.ioctx_create(_remote_pool_name.c_str(), m_remote_io_ctx));
+  ASSERT_EQ(0, _rados->ioctx_create(_local_pool_name.c_str(), m_local_io_ctx));
+  ASSERT_EQ(0, _rados->ioctx_create(_remote_pool_name.c_str(), m_remote_io_ctx));
   m_image_name = get_temp_image_name();
 
   m_threads = new rbd::mirror::Threads(reinterpret_cast<CephContext*>(
index 79a6f86f73eea016a14b9288984d52a475ab738c..c0ebd55d7d7fafde4c0a24a019186c5c30e46320 100644 (file)
@@ -51,7 +51,7 @@ public:
 
   static std::string _local_pool_name;
   static std::string _remote_pool_name;
-  static librados::Rados _rados;
+  static std::shared_ptr<librados::Rados> _rados;
   static uint64_t _image_number;
 };
 
index 71fe23a4334a6ea3d230f90807568ad5af79ce55..a316b0a3fa714b1668144f201051415d1f67061a 100644 (file)
@@ -11,6 +11,7 @@
 extern void register_test_cluster_watcher();
 extern void register_test_pool_watcher();
 extern void register_test_rbd_mirror();
+extern void register_test_rbd_mirror_image_deleter();
 extern void register_test_image_sync();
 
 int main(int argc, char **argv)
@@ -18,6 +19,7 @@ int main(int argc, char **argv)
   register_test_cluster_watcher();
   register_test_pool_watcher();
   register_test_rbd_mirror();
+  register_test_rbd_mirror_image_deleter();
   register_test_image_sync();
 
   ::testing::InitGoogleTest(&argc, argv);
index 1a153eac97372a45c74b9279e49c76aaaee32602..6590ae55650fa32aa7f1237f0d304a70848f26f2 100644 (file)
@@ -38,6 +38,9 @@
 using std::string;
 using std::map;
 using std::stringstream;
+using std::vector;
+using std::pair;
+using std::make_pair;
 
 using librados::IoCtx;
 using namespace librbd;
@@ -527,5 +530,32 @@ void ImageDeleter::DeleteInfo::print_status(Formatter *f, stringstream *ss,
   }
 }
 
+vector<string> ImageDeleter::get_delete_queue_items() {
+  vector<string> items;
+
+  Mutex::Locker l(m_delete_lock);
+  for (const auto& del_info : m_delete_queue) {
+    items.push_back(del_info->local_image_name);
+  }
+
+  return items;
+}
+
+vector<pair<string, int> > ImageDeleter::get_failed_queue_items() {
+  vector<pair<string, int> > items;
+
+  Mutex::Locker l(m_delete_lock);
+  for (const auto& del_info : m_failed_queue) {
+    items.push_back(make_pair(del_info->local_image_name,
+                              del_info->error_code));
+  }
+
+  return items;
+}
+
+void ImageDeleter::set_failed_timer_interval(double interval) {
+  this->m_failed_interval = interval;
+}
+
 } // namespace mirror
 } // namespace rbd
index 1e248b199e4c9ea8f5b7288955318cec53653d53..591f71a925384127581865a43fff9d6edb0af54c 100644 (file)
@@ -16,6 +16,7 @@
 #define CEPH_RBD_MIRROR_IMAGEDELETER_H
 
 #include <deque>
+#include <vector>
 #include "include/atomic.h"
 #include "common/Mutex.h"
 #include "common/Cond.h"
@@ -50,6 +51,11 @@ public:
 
   void print_status(Formatter *f, std::stringstream *ss);
 
+  // for testing purposes
+  std::vector<std::string> get_delete_queue_items();
+  std::vector<std::pair<std::string, int> > get_failed_queue_items();
+  void set_failed_timer_interval(double interval);
+
 private:
 
   class ImageDeleterThread : public Thread {