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() override {
TestFixture::SetUp();
- m_local_io_ctx_ref.reset(new librados::IoCtx{});
- ASSERT_EQ(0, _rados->ioctx_create2(m_local_pool_id, *m_local_io_ctx_ref));
-
m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
_rados, m_threads));
librbd::api::Mirror<>::mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
- m_deleter = new rbd::mirror::ImageDeleter<>(m_threads->work_queue,
- m_threads->timer,
- &m_threads->timer_lock,
+ m_deleter = new rbd::mirror::ImageDeleter<>(m_local_io_ctx, m_threads,
m_service_daemon.get());
m_local_image_id = librbd::util::generate_image_id(m_local_io_ctx);
librbd::RBD rbd;
std::string m_local_image_id;
- rbd::mirror::IoCtxRef m_local_io_ctx_ref;
std::unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
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_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
promote_image();
demote_image();
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, true,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, true, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
promote_image();
C_SaferCond ctx;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- &ctx);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, &ctx);
EXPECT_EQ(-EPERM, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
demote_image();
C_SaferCond ctx;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- &ctx);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, &ctx);
EXPECT_EQ(-EPERM, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
TEST_F(TestImageDeleter, Delete_Image_With_Child) {
create_snapshot();
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
create_snapshot("snap1");
create_snapshot("snap2");
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChild) {
create_snapshot("snap1", true);
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
create_snapshot("snap1", true);
create_snapshot("snap2", true);
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
std::string clone_id = create_clone();
C_SaferCond ctx;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- &ctx);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, &ctx);
m_deleter->set_busy_timer_interval(0.1);
EXPECT_EQ(-EBUSY, ctx.wait());
C_SaferCond ctx2;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_CLONE_IMAGE_ID,
- false, &ctx2);
+ m_deleter->schedule_image_delete(GLOBAL_CLONE_IMAGE_ID, false, &ctx2);
EXPECT_EQ(0, ctx2.wait());
C_SaferCond ctx3;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx3);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx3);
EXPECT_EQ(0, ctx3.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
mirror_image));
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
mirror_image));
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- nullptr);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, nullptr);
C_SaferCond ctx;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx);
EXPECT_EQ(0, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
remove_image();
C_SaferCond ctx;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- &ctx);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, &ctx);
EXPECT_EQ(-ENOENT, ctx.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
EXPECT_EQ(0, ictx->state->open(false));
C_SaferCond ctx;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- &ctx);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, &ctx);
EXPECT_EQ(-EBUSY, ctx.wait());
EXPECT_EQ(0, ictx->state->close());
EXPECT_EQ(0, ictx->state->open(false));
C_SaferCond ctx;
- m_deleter->schedule_image_delete(m_local_io_ctx_ref, GLOBAL_IMAGE_ID, false,
- &ctx);
+ m_deleter->schedule_image_delete(GLOBAL_IMAGE_ID, false, &ctx);
EXPECT_EQ(-EBUSY, ctx.wait());
EXPECT_EQ(0, ictx->state->close());
C_SaferCond ctx2;
- m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
- &ctx2);
+ m_deleter->wait_for_scheduled_deletion(GLOBAL_IMAGE_ID, &ctx2);
EXPECT_EQ(0, ctx2.wait());
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
m_local_cluster,
m_threads.get()));
m_image_deleter.reset(new rbd::mirror::ImageDeleter<>(
- m_threads->work_queue, m_threads->timer, &m_threads->timer_lock,
- m_service_daemon.get()));
+ m_local_ioctx, m_threads.get(), m_service_daemon.get()));
m_instance_watcher = rbd::mirror::InstanceWatcher<>::create(
m_local_ioctx, m_threads->work_queue, nullptr);
m_instance_watcher->handle_acquire_leader();
delete m_replayer;
delete m_instance_watcher;
+ C_SaferCond ctx;
+ m_image_deleter->shut_down(&ctx);
+ ctx.wait();
+
EXPECT_EQ(0, m_remote_cluster.pool_delete(m_remote_pool_name.c_str()));
EXPECT_EQ(0, m_local_cluster->pool_delete(m_local_pool_name.c_str()));
}
C_SaferCond delete_ctx;
m_image_deleter->wait_for_scheduled_deletion(
- m_local_ioctx.get_id(), m_replayer->get_global_image_id(), &delete_ctx);
+ m_replayer->get_global_image_id(), &delete_ctx);
EXPECT_EQ(0, delete_ctx.wait());
C_SaferCond cond;
C_SaferCond delete_ctx;
m_image_deleter->wait_for_scheduled_deletion(
- m_local_ioctx.get_id(), m_replayer->get_global_image_id(), &delete_ctx);
+ m_replayer->get_global_image_id(), &delete_ctx);
EXPECT_EQ(0, delete_ctx.wait());
C_SaferCond cond3;
C_SaferCond delete_ctx;
m_image_deleter->wait_for_scheduled_deletion(
- m_local_ioctx.get_id(), m_replayer->get_global_image_id(), &delete_ctx);
+ m_replayer->get_global_image_id(), &delete_ctx);
EXPECT_EQ(0, delete_ctx.wait());
C_SaferCond cond2;
ASSERT_EQ(0, cond2.wait());
C_SaferCond delete_cond;
m_image_deleter->wait_for_scheduled_deletion(
- m_local_ioctx.get_id(), m_replayer->get_global_image_id(), &delete_cond);
+ m_replayer->get_global_image_id(), &delete_cond);
EXPECT_EQ(0, delete_cond.wait());
start();
ASSERT_EQ(-ENOTCONN, cond5.wait());
C_SaferCond delete_cond1;
m_image_deleter->wait_for_scheduled_deletion(
- m_local_ioctx.get_id(), m_replayer->get_global_image_id(), &delete_cond1);
+ m_replayer->get_global_image_id(), &delete_cond1);
EXPECT_EQ(0, delete_cond1.wait());
C_SaferCond cond6;
template <>
struct ImageDeleter<librbd::MockTestImageCtx> {
- MOCK_METHOD4(schedule_image_delete, void(IoCtxRef, const std::string&, bool,
+ MOCK_METHOD3(schedule_image_delete, void(const std::string&, bool,
Context*));
- MOCK_METHOD4(wait_for_scheduled_deletion,
- void(int64_t, const std::string&, Context*, bool));
- MOCK_METHOD2(cancel_waiter, void(int64_t, const std::string&));
+ MOCK_METHOD3(wait_for_scheduled_deletion,
+ void(const std::string&, Context*, bool));
+ MOCK_METHOD1(cancel_waiter, void(const std::string&));
};
template<>
const std::string& global_image_id,
int r) {
EXPECT_CALL(mock_image_deleter,
- wait_for_scheduled_deletion(_, global_image_id, _, false))
- .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
+ wait_for_scheduled_deletion(global_image_id, _, false))
+ .WillOnce(WithArg<1>(Invoke([this, r](Context *ctx) {
m_threads->work_queue->queue(ctx, r);
})));
}
void expect_cancel_waiter(MockImageDeleter& mock_image_deleter) {
- EXPECT_CALL(mock_image_deleter, cancel_waiter(m_local_io_ctx.get_id(),
- "global image id"));
+ EXPECT_CALL(mock_image_deleter, cancel_waiter("global image id"));
}
void expect_schedule_image_delete(MockImageDeleter& mock_image_deleter,
const std::string& global_image_id,
bool ignore_orphan) {
EXPECT_CALL(mock_image_deleter,
- schedule_image_delete(_, global_image_id, ignore_orphan, nullptr));
+ schedule_image_delete(global_image_id, ignore_orphan, nullptr));
}
bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) {
#include "cls/rbd/cls_rbd_types.h"
#include "librbd/Utils.h"
#include "ImageDeleter.h"
+#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_deleter/RemoveRequest.h"
#include <map>
#include <sstream>
template <typename I>
class ImageDeleterAdminSocketHook : public AdminSocketHook {
public:
- ImageDeleterAdminSocketHook(CephContext *cct, ImageDeleter<I> *image_del) :
+ ImageDeleterAdminSocketHook(CephContext *cct, const std::string& pool_name,
+ ImageDeleter<I> *image_del) :
admin_socket(cct->get_admin_socket()) {
std::string command;
int r;
- command = "rbd mirror deletion status";
+ command = "rbd mirror deletion status " + pool_name;
r = admin_socket->register_command(command, command, this,
"get status for image deleter");
if (r == 0) {
};
template <typename I>
-ImageDeleter<I>::ImageDeleter(ContextWQ *work_queue, SafeTimer *timer,
- Mutex *timer_lock,
+ImageDeleter<I>::ImageDeleter(librados::IoCtx& local_io_ctx,
+ Threads<librbd::ImageCtx>* threads,
ServiceDaemon<librbd::ImageCtx>* service_daemon)
- : m_work_queue(work_queue), m_timer(timer), m_timer_lock(timer_lock),
+ : m_local_io_ctx(local_io_ctx), m_work_queue(threads->work_queue),
+ m_timer(threads->timer), m_timer_lock(&threads->timer_lock),
m_service_daemon(service_daemon),
- m_lock("rbd::mirror::ImageDeleter::m_lock"),
- m_asok_hook(new ImageDeleterAdminSocketHook<I>(g_ceph_context, this))
-{
+ m_lock(librbd::util::unique_lock_name("rbd::mirror::ImageDeleter::m_lock",
+ this)) {
}
template <typename I>
-ImageDeleter<I>::~ImageDeleter() {
- dout(20) << dendl;
+void ImageDeleter<I>::init(Context* on_finish) {
+ dout(10) << dendl;
+
+ m_asok_hook = new ImageDeleterAdminSocketHook<I>(
+ g_ceph_context, m_local_io_ctx.get_pool_name(), this);
+
+ on_finish->complete(0);
+}
+
+template <typename I>
+void ImageDeleter<I>::shut_down(Context* on_finish) {
+ dout(10) << dendl;
+
+ delete m_asok_hook;
+ m_asok_hook = nullptr;
{
Mutex::Locker timer_locker(*m_timer_lock);
cancel_retry_timer();
}
- C_SaferCond ctx;
- m_async_op_tracker.wait_for_ops(&ctx);
- ctx.wait();
+ wait_for_ops(on_finish);
+}
- // wake up any external state machines waiting on deletions
- assert(m_in_flight_delete_queue.empty());
- for (auto& info : m_delete_queue) {
- if (info->on_delete != nullptr) {
- info->on_delete->complete(-ECANCELED);
- }
- }
- for (auto& info : m_retry_delete_queue) {
- if (info->on_delete != nullptr) {
- info->on_delete->complete(-ECANCELED);
+template <typename I>
+void ImageDeleter<I>::wait_for_ops(Context* on_finish) {
+ auto ctx = new FunctionContext([this, on_finish](int) {
+ cancel_all_deletions(on_finish);
+ });
+ m_async_op_tracker.wait_for_ops(ctx);
+}
+
+template <typename I>
+void ImageDeleter<I>::cancel_all_deletions(Context* on_finish) {
+ {
+ Mutex::Locker locker(m_lock);
+ // wake up any external state machines waiting on deletions
+ assert(m_in_flight_delete_queue.empty());
+ for (auto& queue : {&m_delete_queue, &m_retry_delete_queue}) {
+ for (auto& info : *queue) {
+ if (info->on_delete != nullptr) {
+ info->on_delete->complete(-ECANCELED);
+ }
+ }
+ queue->clear();
}
}
-
- delete m_asok_hook;
+ on_finish->complete(0);
}
template <typename I>
-void ImageDeleter<I>::schedule_image_delete(IoCtxRef local_io_ctx,
- const std::string& global_image_id,
+void ImageDeleter<I>::schedule_image_delete(const std::string& global_image_id,
bool ignore_orphaned,
Context *on_delete) {
- int64_t local_pool_id = local_io_ctx->get_id();
- dout(5) << "local_pool_id=" << local_pool_id << ", "
- << "global_image_id=" << global_image_id << dendl;
+ dout(5) << "global_image_id=" << global_image_id << dendl;
if (on_delete != nullptr) {
on_delete = new FunctionContext([this, on_delete](int r) {
{
Mutex::Locker locker(m_lock);
- auto del_info = find_delete_info(local_pool_id, global_image_id);
+ auto del_info = find_delete_info(global_image_id);
if (del_info != nullptr) {
dout(20) << "image " << global_image_id << " "
<< "was already scheduled for deletion" << dendl;
return;
}
- m_delete_queue.emplace_back(new DeleteInfo(local_pool_id, global_image_id,
- local_io_ctx, ignore_orphaned,
+ m_delete_queue.emplace_back(new DeleteInfo(global_image_id, ignore_orphaned,
on_delete));
}
remove_images();
}
template <typename I>
-void ImageDeleter<I>::wait_for_scheduled_deletion(int64_t local_pool_id,
- const std::string &global_image_id,
+void ImageDeleter<I>::wait_for_scheduled_deletion(const std::string &global_image_id,
Context *ctx,
bool notify_on_failed_retry) {
- dout(5) << "local_pool_id=" << local_pool_id << ", "
- << "global_image_id=" << global_image_id << dendl;
+ dout(5) << "global_image_id=" << global_image_id << dendl;
ctx = new FunctionContext([this, ctx](int r) {
m_work_queue->queue(ctx, r);
});
Mutex::Locker locker(m_lock);
- auto del_info = find_delete_info(local_pool_id, global_image_id);
+ auto del_info = find_delete_info(global_image_id);
if (!del_info) {
// image not scheduled for deletion
ctx->complete(0);
}
template <typename I>
-void ImageDeleter<I>::cancel_waiter(int64_t local_pool_id,
- const std::string &global_image_id) {
- dout(5) << "local_pool_id=" << local_pool_id << ", "
- << "global_image_id=" << global_image_id << dendl;
+void ImageDeleter<I>::cancel_waiter(const std::string &global_image_id) {
+ dout(5) << "global_image_id=" << global_image_id << dendl;
Mutex::Locker locker(m_lock);
- auto del_info = find_delete_info(local_pool_id, global_image_id);
+ auto del_info = find_delete_info(global_image_id);
if (!del_info) {
return;
}
template <typename I>
typename ImageDeleter<I>::DeleteInfoRef
-ImageDeleter<I>::find_delete_info(int64_t local_pool_id,
- const std::string &global_image_id) {
+ImageDeleter<I>::find_delete_info(const std::string &global_image_id) {
assert(m_lock.is_locked());
DeleteQueue delete_queues[] = {m_in_flight_delete_queue,
m_retry_delete_queue,
m_delete_queue};
- DeleteInfo delete_info{local_pool_id, global_image_id};
+ DeleteInfo delete_info{global_image_id};
for (auto& queue : delete_queues) {
auto it = std::find_if(queue.begin(), queue.end(),
[&delete_info](const DeleteInfoRef& ref) {
});
auto req = image_deleter::RemoveRequest<I>::create(
- *delete_info->local_io_ctx, delete_info->global_image_id,
+ m_local_io_ctx, delete_info->global_image_id,
delete_info->ignore_orphaned, &delete_info->error_result, m_work_queue,
ctx);
req->send();
bool print_failure_info) {
if (f) {
f->open_object_section("delete_info");
- f->dump_int("local_pool_id", local_pool_id);
f->dump_string("global_image_id", global_image_id);
if (print_failure_info) {
f->dump_string("error_code", cpp_strerror(error_code));
namespace mirror {
template <typename> class ServiceDaemon;
+template <typename> class Threads;
/**
* Manage deletion of non-primary images.
template <typename ImageCtxT = librbd::ImageCtx>
class ImageDeleter {
public:
- ImageDeleter(ContextWQ *work_queue, SafeTimer *timer, Mutex *timer_lock,
+ ImageDeleter(librados::IoCtx& local_io_ctx,
+ Threads<librbd::ImageCtx>* threads,
ServiceDaemon<librbd::ImageCtx>* service_daemon);
- ~ImageDeleter();
+
ImageDeleter(const ImageDeleter&) = delete;
ImageDeleter& operator=(const ImageDeleter&) = delete;
- void schedule_image_delete(IoCtxRef local_io_ctx,
- const std::string& global_image_id,
+ void init(Context* on_finish);
+ void shut_down(Context* on_finish);
+
+ void schedule_image_delete(const std::string& global_image_id,
bool ignore_orphaned,
Context *on_finish);
- void wait_for_scheduled_deletion(int64_t local_pool_id,
- const std::string &global_image_id,
+ void wait_for_scheduled_deletion(const std::string &global_image_id,
Context *ctx,
bool notify_on_failed_retry=true);
- void cancel_waiter(int64_t local_pool_id,
- const std::string &global_image_id);
+ void cancel_waiter(const std::string &global_image_id);
void print_status(Formatter *f, std::stringstream *ss);
private:
struct DeleteInfo {
- int64_t local_pool_id;
std::string global_image_id;
- IoCtxRef local_io_ctx;
bool ignore_orphaned = false;
Context *on_delete = nullptr;
int retries = 0;
bool notify_on_failed_retry = true;
- DeleteInfo(int64_t local_pool_id, const std::string& global_image_id)
- : local_pool_id(local_pool_id), global_image_id(global_image_id) {
+ DeleteInfo(const std::string& global_image_id)
+ : global_image_id(global_image_id) {
}
- DeleteInfo(int64_t local_pool_id, const std::string& global_image_id,
- IoCtxRef local_io_ctx, bool ignore_orphaned,
- Context *on_delete)
- : local_pool_id(local_pool_id), global_image_id(global_image_id),
- local_io_ctx(local_io_ctx), ignore_orphaned(ignore_orphaned),
+ DeleteInfo(const std::string& global_image_id,
+ bool ignore_orphaned, Context *on_delete)
+ : global_image_id(global_image_id), ignore_orphaned(ignore_orphaned),
on_delete(on_delete) {
}
inline bool operator==(const DeleteInfo& delete_info) const {
- return (local_pool_id == delete_info.local_pool_id &&
- global_image_id == delete_info.global_image_id);
+ return (global_image_id == delete_info.global_image_id);
}
friend std::ostream& operator<<(std::ostream& os, DeleteInfo& delete_info) {
- os << "[" << "local_pool_id=" << delete_info.local_pool_id << ", "
- << "global_image_id=" << delete_info.global_image_id << "]";
+ os << "[global_image_id=" << delete_info.global_image_id << "]";
return os;
}
typedef std::shared_ptr<DeleteInfo> DeleteInfoRef;
typedef std::deque<DeleteInfoRef> DeleteQueue;
+ librados::IoCtx& m_local_io_ctx;
ContextWQ *m_work_queue;
SafeTimer *m_timer;
Mutex *m_timer_lock;
DeleteQueue m_retry_delete_queue;
DeleteQueue m_in_flight_delete_queue;
- AdminSocketHook *m_asok_hook;
+ AdminSocketHook *m_asok_hook = nullptr;
Context *m_timer_ctx = nullptr;
void enqueue_failed_delete(DeleteInfoRef* delete_info, int error_code,
double retry_delay);
- DeleteInfoRef find_delete_info(int64_t local_pool_id,
- const std::string &global_image_id);
+ DeleteInfoRef find_delete_info(const std::string &global_image_id);
void remove_images();
void remove_image(DeleteInfoRef delete_info);
void cancel_retry_timer();
void handle_retry_timer();
+ void wait_for_ops(Context* on_finish);
+ void cancel_all_deletions(Context* on_finish);
+
};
} // namespace mirror
Context *ctx = create_context_callback<
ImageReplayer, &ImageReplayer<I>::handle_wait_for_deletion>(this);
m_image_deleter->wait_for_scheduled_deletion(
- m_local_pool_id, m_global_image_id, ctx, false);
+ m_global_image_id, ctx, false);
}
template <typename I>
dout(20) << "on_finish=" << on_finish << ", manual=" << manual
<< ", desc=" << desc << dendl;
- m_image_deleter->cancel_waiter(m_local_pool_id, m_global_image_id);
+ m_image_deleter->cancel_waiter(m_global_image_id);
image_replayer::BootstrapRequest<I> *bootstrap_request = nullptr;
bool shut_down_replay = false;
delete_requested = true;
}
if (delete_requested || m_resync_requested) {
- m_image_deleter->schedule_image_delete(m_local_ioctx, m_global_image_id,
+ m_image_deleter->schedule_image_delete(m_global_image_id,
m_resync_requested, nullptr);
m_local_image_id = "";
m_local_cluster_watcher.reset(new ClusterWatcher(m_local, m_lock,
m_service_daemon.get()));
-
- m_image_deleter.reset(new ImageDeleter<>(m_threads->work_queue,
- m_threads->timer,
- &m_threads->timer_lock,
- m_service_daemon.get()));
return r;
}
if (f) {
f->close_section();
- f->open_object_section("image_deleter");
}
-
- m_image_deleter->print_status(f, ss);
}
void Mirror::start()
} else {
dout(20) << "starting pool replayer for " << peer << dendl;
unique_ptr<PoolReplayer> pool_replayer(new PoolReplayer(
- m_threads, m_service_daemon.get(), m_image_deleter.get(), kv.first,
- peer, m_args));
+ m_threads, m_service_daemon.get(), kv.first, peer, m_args));
// TODO: make async
pool_replayer->init();
#include "include/rados/librados.hpp"
#include "ClusterWatcher.h"
#include "PoolReplayer.h"
-#include "ImageDeleter.h"
#include "types.h"
#include <set>
// monitor local cluster for config changes in peers
std::unique_ptr<ClusterWatcher> m_local_cluster_watcher;
- std::unique_ptr<ImageDeleter<>> m_image_deleter;
std::map<PoolPeer, std::unique_ptr<PoolReplayer> > m_pool_replayers;
std::atomic<bool> m_stopping = { false };
bool m_manual_stop = false;
PoolReplayer::PoolReplayer(Threads<librbd::ImageCtx> *threads,
ServiceDaemon<librbd::ImageCtx>* service_daemon,
- ImageDeleter<>* image_deleter,
int64_t local_pool_id, const peer_t &peer,
const std::vector<const char*> &args) :
m_threads(threads),
m_service_daemon(service_daemon),
- m_image_deleter(image_deleter),
m_local_pool_id(local_pool_id),
m_peer(peer),
m_args(args),
dout(20) << "connected to " << m_peer << dendl;
+ // TODO
+ C_SaferCond image_deleter_ctx;
+ m_image_deleter.reset(new ImageDeleter<>(m_local_io_ctx, m_threads,
+ m_service_daemon));
+ m_image_deleter->init(&image_deleter_ctx);
+ image_deleter_ctx.wait();
+
m_instance_replayer.reset(InstanceReplayer<>::create(
- m_threads, m_service_daemon, m_image_deleter, m_local_rados,
+ m_threads, m_service_daemon, m_image_deleter.get(), m_local_rados,
local_mirror_uuid, m_local_pool_id));
m_instance_replayer->init();
m_instance_replayer->add_peer(m_peer.uuid, m_remote_io_ctx);
m_instance_replayer.reset();
}
+ // TODO
+ if (m_image_deleter) {
+ C_SaferCond image_deleter_ctx;
+ m_image_deleter->shut_down(&image_deleter_ctx);
+ image_deleter_ctx.wait();
+ }
+
assert(!m_local_pool_watcher);
assert(!m_remote_pool_watcher);
m_local_rados.reset();
m_instance_replayer->print_status(f, ss);
+ f->open_object_section("image_deleter");
+ m_image_deleter->print_status(f, ss);
+ f->close_section();
+
f->close_section();
f->flush(*ss);
}
public:
PoolReplayer(Threads<librbd::ImageCtx> *threads,
ServiceDaemon<librbd::ImageCtx>* service_daemon,
- ImageDeleter<>* image_deleter,
int64_t local_pool_id, const peer_t &peer,
const std::vector<const char*> &args);
~PoolReplayer();
Threads<librbd::ImageCtx> *m_threads;
ServiceDaemon<librbd::ImageCtx>* m_service_daemon;
- ImageDeleter<>* m_image_deleter;
int64_t m_local_pool_id = -1;
peer_t m_peer;
std::vector<const char*> m_args;
std::unique_ptr<PoolWatcher<> > m_remote_pool_watcher;
std::unique_ptr<InstanceReplayer<librbd::ImageCtx>> m_instance_replayer;
+ std::unique_ptr<ImageDeleter<>> m_image_deleter;
std::string m_asok_hook_name;
AdminSocketHook *m_asok_hook = nullptr;