template<>
struct Replay<MockTestImageCtx> {
- MOCK_METHOD2(decode, int(bufferlist::iterator *, EventEntry *));
+ MOCK_METHOD2(decode, int(bufferlist::const_iterator *, EventEntry *));
MOCK_METHOD3(process, void(const EventEntry &, Context *, Context *));
MOCK_METHOD1(flush, void(Context*));
MOCK_METHOD2(shut_down, void(bool, Context*));
namespace rbd {
namespace mirror {
+template <>
+struct ImageDeleter<librbd::MockTestImageCtx> {
+ static ImageDeleter* s_instance;
+
+ static void trash_move(librados::IoCtx& local_io_ctx,
+ const std::string& global_image_id, bool resync,
+ MockContextWQ* work_queue, Context* on_finish) {
+ ceph_assert(s_instance != nullptr);
+ s_instance->trash_move(global_image_id, resync, on_finish);
+ }
+
+ MOCK_METHOD3(trash_move, void(const std::string&, bool, Context*));
+
+ ImageDeleter() {
+ s_instance = this;
+ }
+};
+
+ImageDeleter<librbd::MockTestImageCtx>* ImageDeleter<librbd::MockTestImageCtx>::s_instance = nullptr;
+
template <>
struct Threads<librbd::MockTestImageCtx> {
MockSafeTimer *timer;
}
};
-template <>
-struct ImageDeleter<librbd::MockTestImageCtx> {
- MOCK_METHOD4(schedule_image_delete, void(RadosRef, int64_t,
- const std::string&, bool));
- MOCK_METHOD4(wait_for_scheduled_deletion,
- void(int64_t, const std::string&, Context*, bool));
- MOCK_METHOD2(cancel_waiter, void(int64_t, const std::string&));
-};
-
template<>
class InstanceWatcher<librbd::MockTestImageCtx> {
};
std::string *tag_owner,
MockContextWQ *work_queue,
Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->local_image_id = local_image_id;
s_instance->local_image_name = local_image_name;
s_instance->tag_owner = tag_owner;
const std::string &global_image_id,
const std::string &local_mirror_uuid,
const std::string &local_image_id,
+ const journal::Settings &settings,
std::string *remote_mirror_uuid,
std::string *remote_image_id,
::journal::MockJournalerProxy **remote_journaler,
cls::journal::ClientState *client_state,
librbd::journal::MirrorPeerClientMeta *client_meta,
Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->remote_mirror_uuid = remote_mirror_uuid;
s_instance->remote_image_id = remote_image_id;
s_instance->remote_journaler = remote_journaler;
bool *do_resync = nullptr;
static BootstrapRequest* create(
+ Threads<librbd::MockTestImageCtx>* threads,
librados::IoCtx &local_io_ctx, librados::IoCtx &remote_io_ctx,
rbd::mirror::InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
librbd::MockTestImageCtx **local_image_ctx,
const std::string &local_image_name, const std::string &remote_image_id,
- const std::string &global_image_id, MockContextWQ *work_queue,
- MockSafeTimer *timer, Mutex *timer_lock,
+ const std::string &global_image_id,
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid,
::journal::MockJournalerProxy *journaler,
librbd::journal::MirrorPeerClientMeta *client_meta,
Context *on_finish, bool *do_resync,
rbd::mirror::ProgressContext *progress_ctx = nullptr) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->image_ctx = local_image_ctx;
s_instance->on_finish = on_finish;
s_instance->do_resync = do_resync;
}
BootstrapRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~BootstrapRequest() {
- assert(s_instance == this);
+ ceph_assert(s_instance == this);
s_instance = nullptr;
}
static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->image_ctx = image_ctx;
s_instance->on_finish = on_finish;
return s_instance;
}
CloseImageRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~CloseImageRequest() {
- assert(s_instance == this);
+ ceph_assert(s_instance == this);
s_instance = nullptr;
}
const std::string &local_mirror_uuid,
librbd::journal::MirrorPeerClientMeta *client_meta,
MockContextWQ *work_queue) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
return s_instance;
}
}
EventPreprocessor() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~EventPreprocessor() {
- assert(s_instance == this);
+ ceph_assert(s_instance == this);
s_instance = nullptr;
}
static ReplayStatusFormatter* create(::journal::MockJournalerProxy *journaler,
const std::string &mirror_uuid) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
return s_instance;
}
}
ReplayStatusFormatter() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~ReplayStatusFormatter() {
- assert(s_instance == this);
+ ceph_assert(s_instance == this);
s_instance = nullptr;
}
}));
}
- void expect_wait_for_scheduled_deletion(MockImageDeleter& mock_image_deleter,
- const std::string& global_image_id,
- int r) {
+ void expect_trash_move(MockImageDeleter& mock_image_deleter,
+ const std::string& global_image_id,
+ bool ignore_orphan, int r) {
EXPECT_CALL(mock_image_deleter,
- wait_for_scheduled_deletion(_, global_image_id, _, false))
- .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
+ trash_move(global_image_id, ignore_orphan, _))
+ .WillOnce(WithArg<2>(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"));
- }
-
- 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));
- }
-
bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) {
bufferlist bl;
- ::encode(tag_data, bl);
+ encode(tag_data, bl);
return bl;
}
client_data.client_meta = image_client_meta;
cls::journal::Client client;
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
EXPECT_CALL(mock_journaler, get_cached_client("local_mirror_uuid", _))
.WillOnce(DoAll(SetArgPointee<1>(client),
.WillRepeatedly(Return(0));
}
- void expect_committed(::journal::MockJournaler &mock_journaler, int times) {
+ void expect_get_tag_tid_in_debug(librbd::MockTestJournal &mock_journal) {
+ // It is used in debug messages and depends on debug level
+ EXPECT_CALL(mock_journal, get_tag_tid()).Times(AtLeast(0))
+ .WillRepeatedly(Return(0));
+ }
+
+ void expect_committed(::journal::MockReplayEntry &mock_replay_entry,
+ ::journal::MockJournaler &mock_journaler, int times) {
+ EXPECT_CALL(mock_replay_entry, get_data()).Times(times);
EXPECT_CALL(mock_journaler, committed(
MatcherCast<const ::journal::MockReplayEntryProxy&>(_)))
.Times(times);
WithArg<2>(CompleteContext(on_commit_r))));
}
- void create_image_replayer(MockThreads &mock_threads,
- MockImageDeleter &mock_image_deleter) {
+ void create_image_replayer(MockThreads &mock_threads) {
m_image_replayer = new MockImageReplayer(
- &mock_threads, &mock_image_deleter, &m_instance_watcher,
+ &mock_threads, &m_instance_watcher,
rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx)),
"local_mirror_uuid", m_local_io_ctx.get_id(), "global image id");
m_image_replayer->add_peer("peer_uuid", m_remote_io_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
MockCloseImageRequest mock_close_local_image_request;
- expect_cancel_waiter(mock_image_deleter);
expect_shut_down(mock_local_replay, true, 0);
EXPECT_CALL(mock_local_journal, remove_listener(_));
EXPECT_CALL(mock_local_journal, stop_external_replay());
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
expect_shut_down(mock_remote_journaler, 0);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, "", "", "", -ENOENT);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
expect_shut_down(mock_remote_journaler, 0);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", -EINVAL);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
"", -ENOENT);
- expect_schedule_image_delete(mock_image_deleter, "global image id", false);
+ expect_trash_move(mock_image_deleter, "global image id", false, 0);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "some other mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
"", -ENOENT);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, -EINVAL);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
}
TEST_F(TestMockImageReplayer, BootstrapError) {
-
create_local_image();
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
expect_shut_down(mock_remote_journaler, 0);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
ASSERT_EQ(-EINVAL, start_ctx.wait());
}
+TEST_F(TestMockImageReplayer, StopBeforeBootstrap) {
+ create_local_image();
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+
+ journal::MockJournaler mock_remote_journaler;
+ MockThreads mock_threads(m_threads);
+ expect_work_queue_repeatedly(mock_threads);
+ expect_add_event_after_repeatedly(mock_threads);
+
+ MockImageDeleter mock_image_deleter;
+ MockPrepareLocalImageRequest mock_prepare_local_image_request;
+ MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
+ MockReplayStatusFormatter mock_replay_status_formatter;
+
+ expect_get_or_send_update(mock_replay_status_formatter);
+
+ InSequence seq;
+ expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
+ expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
+ m_remote_image_ctx->id, 0);
+ EXPECT_CALL(mock_remote_journaler, construct())
+ .WillOnce(Invoke([this]() {
+ m_image_replayer->stop(nullptr, true);
+ }));
+
+ EXPECT_CALL(mock_remote_journaler, remove_listener(_));
+ expect_shut_down(mock_remote_journaler, 0);
+
+ create_image_replayer(mock_threads);
+
+ C_SaferCond start_ctx;
+ m_image_replayer->start(&start_ctx);
+ ASSERT_EQ(-ECANCELED, start_ctx.wait());
+}
+
TEST_F(TestMockImageReplayer, StartExternalReplayError) {
// START
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
expect_shut_down(mock_remote_journaler, 0);
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
MockCloseImageRequest mock_close_local_image_request;
- expect_cancel_waiter(mock_image_deleter);
expect_shut_down(mock_local_replay, true, -EINVAL);
EXPECT_CALL(mock_local_journal, remove_listener(_));
EXPECT_CALL(mock_local_journal, stop_external_replay());
expect_get_or_send_update(mock_replay_status_formatter);
expect_get_commit_tid_in_debug(mock_replay_entry);
- expect_committed(mock_remote_journaler, 2);
+ expect_get_tag_tid_in_debug(mock_local_journal);
+ expect_committed(mock_replay_entry, mock_remote_journaler, 2);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
// STOP
MockCloseImageRequest mock_close_local_image_request;
- expect_cancel_waiter(mock_image_deleter);
expect_shut_down(mock_local_replay, true, 0);
EXPECT_CALL(mock_local_journal, remove_listener(_));
EXPECT_CALL(mock_local_journal, stop_external_replay());
expect_get_or_send_update(mock_replay_status_formatter);
expect_get_commit_tid_in_debug(mock_replay_entry);
+ expect_get_tag_tid_in_debug(mock_local_journal);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
expect_get_or_send_update(mock_replay_status_formatter);
expect_get_commit_tid_in_debug(mock_replay_entry);
- expect_committed(mock_remote_journaler, 1);
+ expect_get_tag_tid_in_debug(mock_local_journal);
+ expect_committed(mock_replay_entry, mock_remote_journaler, 1);
InSequence seq;
- expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
- create_image_replayer(mock_threads, mock_image_deleter);
+ create_image_replayer(mock_threads);
C_SaferCond start_ctx;
m_image_replayer->start(&start_ctx);
// process with delay
EXPECT_CALL(mock_replay_entry, get_data());
librbd::journal::EventEntry event_entry(
- librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
+ librbd::journal::AioDiscardEvent(123, 345, 0), ceph_clock_now());
EXPECT_CALL(mock_local_replay, decode(_, _))
.WillOnce(DoAll(SetArgPointee<1>(event_entry),
Return(0)));
EXPECT_CALL(mock_replay_entry, get_data());
C_SaferCond decode_ctx;
EXPECT_CALL(mock_local_replay, decode(_, _))
- .WillOnce(DoAll(Invoke([&decode_ctx](bufferlist::iterator* it,
+ .WillOnce(DoAll(Invoke([&decode_ctx](bufferlist::const_iterator* it,
librbd::journal::EventEntry *e) {
decode_ctx.complete(0);
}),
MockCloseImageRequest mock_close_local_image_request;
- expect_cancel_waiter(mock_image_deleter);
expect_shut_down(mock_local_replay, true, 0);
EXPECT_CALL(mock_local_journal, remove_listener(_));
EXPECT_CALL(mock_local_journal, stop_external_replay());