From: Ricardo Dias Date: Tue, 19 Apr 2016 11:35:49 +0000 (+0100) Subject: rbd-mirror: test: Added unit test for testing image-deleter thread X-Git-Tag: v11.0.0~457^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ac9514941b0accb6c738ce4aa0953c36cdcf69a6;p=ceph.git rbd-mirror: test: Added unit test for testing image-deleter thread Signed-off-by: Ricardo Dias --- diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index 065bc9053df9..9acdbe7ba21a 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -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 diff --git a/src/test/rbd_mirror/CMakeLists.txt b/src/test/rbd_mirror/CMakeLists.txt index dd984e47a11b..4cd2d6a46c01 100644 --- a/src/test/rbd_mirror/CMakeLists.txt +++ b/src/test/rbd_mirror/CMakeLists.txt @@ -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 ) diff --git a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc index 0b72167d03f5..9c697363fd34 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc @@ -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 index 000000000000..b513492a4934 --- /dev/null +++ b/src/test/rbd_mirror/test_ImageDeleter.cc @@ -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()); +} + + diff --git a/src/test/rbd_mirror/test_fixture.cc b/src/test/rbd_mirror/test_fixture.cc index b99b9fc6bd83..b1eb489d97aa 100644 --- a/src/test/rbd_mirror/test_fixture.cc +++ b/src/test/rbd_mirror/test_fixture.cc @@ -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 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(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( diff --git a/src/test/rbd_mirror/test_fixture.h b/src/test/rbd_mirror/test_fixture.h index 79a6f86f73ee..c0ebd55d7d7f 100644 --- a/src/test/rbd_mirror/test_fixture.h +++ b/src/test/rbd_mirror/test_fixture.h @@ -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 _rados; static uint64_t _image_number; }; diff --git a/src/test/rbd_mirror/test_main.cc b/src/test/rbd_mirror/test_main.cc index 71fe23a4334a..a316b0a3fa71 100644 --- a/src/test/rbd_mirror/test_main.cc +++ b/src/test/rbd_mirror/test_main.cc @@ -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); diff --git a/src/tools/rbd_mirror/ImageDeleter.cc b/src/tools/rbd_mirror/ImageDeleter.cc index 1a153eac9737..6590ae55650f 100644 --- a/src/tools/rbd_mirror/ImageDeleter.cc +++ b/src/tools/rbd_mirror/ImageDeleter.cc @@ -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 ImageDeleter::get_delete_queue_items() { + vector 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 > ImageDeleter::get_failed_queue_items() { + vector > 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 diff --git a/src/tools/rbd_mirror/ImageDeleter.h b/src/tools/rbd_mirror/ImageDeleter.h index 1e248b199e4c..591f71a92538 100644 --- a/src/tools/rbd_mirror/ImageDeleter.h +++ b/src/tools/rbd_mirror/ImageDeleter.h @@ -16,6 +16,7 @@ #define CEPH_RBD_MIRROR_IMAGEDELETER_H #include +#include #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 get_delete_queue_items(); + std::vector > get_failed_queue_items(); + void set_failed_timer_interval(double interval); + private: class ImageDeleterThread : public Thread {