#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/CreateImageRequest.h"
#include "tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include "test/journal/mock/MockJournaler.h"
#include "test/librbd/mock/MockImageCtx.h"
#include "test/rbd_mirror/mock/MockContextWQ.h"
CreateImageRequest<librbd::MockTestImageCtx>*
CreateImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+namespace journal {
+
+template<>
+struct StateBuilder<librbd::MockTestImageCtx> {
+ std::string local_image_id;
+
+ std::string remote_mirror_uuid;
+ ::journal::MockJournalerProxy* remote_journaler = nullptr;
+ cls::journal::ClientState remote_client_state;
+ librbd::journal::MirrorPeerClientMeta remote_client_meta;
+};
+
+} // namespace journal
} // namespace image_replayer
} // namespace mirror
} // namespace rbd
typedef CreateLocalImageRequest<librbd::MockTestImageCtx> MockCreateLocalImageRequest;
typedef Threads<librbd::MockTestImageCtx> MockThreads;
typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
+ typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
void SetUp() override {
TestMockFixture::SetUp();
MockCreateLocalImageRequest* create_request(
MockThreads& mock_threads,
- ::journal::MockJournaler& mock_journaler,
+ MockStateBuilder& mock_state_builder,
const std::string& global_image_id,
- const std::string& remote_mirror_uuid,
- librbd::journal::MirrorPeerClientMeta* mirror_peer_client_meta,
- std::string* local_image_id, Context* on_finish) {
+ Context* on_finish) {
return new MockCreateLocalImageRequest(
&mock_threads, m_local_io_ctx, m_mock_remote_image_ctx,
- &mock_journaler, global_image_id, remote_mirror_uuid,
- mirror_peer_client_meta, nullptr, local_image_id, on_finish);
+ global_image_id, nullptr, &mock_state_builder, on_finish);
}
librbd::ImageCtx *m_remote_image_ctx;
C_SaferCond ctx;
MockThreads mock_threads;
- std::string local_image_id;
+ MockStateBuilder mock_state_builder;
auto request = create_request(
- mock_threads, mock_journaler, "global image id", "remote mirror uuid",
- &mirror_peer_client_meta, &local_image_id, &ctx);
+ mock_threads, mock_state_builder, "global image id", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_EQ("local image id", local_image_id);
- ASSERT_EQ("local image id", mirror_peer_client_meta.image_id);
+ ASSERT_EQ("local image id", mock_state_builder.local_image_id);
+ ASSERT_EQ("local image id", mock_state_builder.remote_client_meta.image_id);
ASSERT_EQ(librbd::journal::MIRROR_PEER_STATE_SYNCING,
- mirror_peer_client_meta.state);
+ mock_state_builder.remote_client_meta.state);
}
TEST_F(TestMockImageReplayerJournalCreateLocalImageRequest, UnregisterError) {
C_SaferCond ctx;
MockThreads mock_threads;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
- std::string local_image_id;
+ MockStateBuilder mock_state_builder;
auto request = create_request(
- mock_threads, mock_journaler, "global image id", "remote mirror uuid",
- &mirror_peer_client_meta, &local_image_id, &ctx);
+ mock_threads, mock_state_builder, "global image id", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
C_SaferCond ctx;
MockThreads mock_threads;
- std::string local_image_id;
+ MockStateBuilder mock_state_builder;
auto request = create_request(
- mock_threads, mock_journaler, "global image id", "remote mirror uuid",
- &mirror_peer_client_meta, &local_image_id, &ctx);
+ mock_threads, mock_state_builder, "global image id", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
C_SaferCond ctx;
MockThreads mock_threads;
- std::string local_image_id;
+ MockStateBuilder mock_state_builder;
auto request = create_request(
- mock_threads, mock_journaler, "global image id", "remote mirror uuid",
- &mirror_peer_client_meta, &local_image_id, &ctx);
+ mock_threads, mock_state_builder, "global image id", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
C_SaferCond ctx;
MockThreads mock_threads;
- std::string local_image_id;
+ MockStateBuilder mock_state_builder;
auto request = create_request(
- mock_threads, mock_journaler, "global image id", "remote mirror uuid",
- &mirror_peer_client_meta, &local_image_id, &ctx);
+ mock_threads, mock_state_builder, "global image id", &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
C_SaferCond ctx;
MockThreads mock_threads;
- std::string local_image_id;
+ MockStateBuilder mock_state_builder;
auto request = create_request(
- mock_threads, mock_journaler, "global image id", "remote mirror uuid",
- &mirror_peer_client_meta, &local_image_id, &ctx);
+ mock_threads, mock_state_builder, "global image id", &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
#include "librbd/journal/TypeTraits.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include "test/journal/mock/MockJournaler.h"
#include "test/librbd/mock/MockImageCtx.h"
#include "test/librbd/mock/MockJournal.h"
} // namespace journal
} // namespace rbd
+namespace rbd {
+namespace mirror {
+namespace image_replayer {
+namespace journal {
+
+template<>
+struct StateBuilder<librbd::MockTestImageCtx> {
+ StateBuilder(librbd::MockTestImageCtx& local_image_ctx,
+ ::journal::MockJournaler& remote_journaler,
+ const librbd::journal::MirrorPeerClientMeta& remote_client_meta)
+ : local_image_ctx(&local_image_ctx),
+ local_image_id(local_image_ctx.id),
+ remote_journaler(&remote_journaler),
+ remote_client_meta(remote_client_meta) {
+ }
+
+ librbd::MockTestImageCtx* local_image_ctx;
+ std::string local_image_id;
+
+ std::string remote_mirror_uuid = "remote mirror uuid";
+ ::journal::MockJournaler* remote_journaler = nullptr;
+ librbd::journal::MirrorPeerClientMeta remote_client_meta;
+};
+
+} // namespace journal
+} // namespace image_replayer
+} // namespace mirror
+} // namespace rbd
+
// template definitions
#include "tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.cc"
class TestMockImageReplayerJournalPrepareReplayRequest : public TestMockFixture {
public:
typedef PrepareReplayRequest<librbd::MockTestImageCtx> MockPrepareReplayRequest;
+ typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
typedef std::list<cls::journal::Tag> Tags;
void SetUp() override {
}
MockPrepareReplayRequest* create_request(
- librbd::MockTestImageCtx& mock_local_image_ctx,
- ::journal::MockJournaler& mock_remote_journaler,
+ MockStateBuilder& mock_state_builder,
librbd::mirror::PromotionState remote_promotion_state,
const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- librbd::journal::MirrorPeerClientMeta* client_meta,
bool* resync_requested, bool* syncing, Context* on_finish) {
return new MockPrepareReplayRequest(
- &mock_local_image_ctx, &mock_remote_journaler, remote_promotion_state,
- local_mirror_uuid, remote_mirror_uuid, client_meta, nullptr,
+ local_mirror_uuid, remote_promotion_state, nullptr, &mock_state_builder,
resync_requested, syncing, on_finish);
}
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
::journal::MockJournaler mock_remote_journaler;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
::journal::MockJournaler mock_remote_journaler;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_TRUE(resync_requested);
::journal::MockJournaler mock_remote_journaler;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
::journal::MockJournaler mock_remote_journaler;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_NON_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
::journal::MockJournaler mock_remote_journaler;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
C_SaferCond ctx;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
::journal::MockJournaler mock_remote_journaler;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_NON_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_FALSE(resync_requested);
C_SaferCond ctx;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ mirror_peer_client_meta);
bool resync_requested;
bool syncing;
auto request = create_request(
- mock_local_image_ctx, mock_remote_journaler,
- librbd::mirror::PROMOTION_STATE_PRIMARY, "local mirror uuid",
- "remote mirror uuid", &mirror_peer_client_meta, &resync_requested,
- &syncing, &ctx);
+ mock_state_builder, librbd::mirror::PROMOTION_STATE_PRIMARY,
+ "local mirror uuid", &resync_requested, &syncing, &ctx);
request->send();
ASSERT_EQ(-EEXIST, ctx.wait());
}
#include "tools/rbd_mirror/image_replayer/journal/Replayer.h"
#include "tools/rbd_mirror/image_replayer/journal/EventPreprocessor.h"
#include "tools/rbd_mirror/image_replayer/journal/ReplayStatusFormatter.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include "test/journal/mock/MockJournaler.h"
#include "test/librbd/mock/MockImageCtx.h"
#include "test/rbd_mirror/mock/MockContextWQ.h"
MOCK_METHOD2(get_or_send_update, bool(std::string *description, Context *on_finish));
};
+template<>
+struct StateBuilder<librbd::MockTestImageCtx> {
+ StateBuilder(librbd::MockTestImageCtx& local_image_ctx,
+ ::journal::MockJournaler& remote_journaler,
+ const librbd::journal::MirrorPeerClientMeta& remote_client_meta)
+ : local_image_ctx(&local_image_ctx),
+ remote_journaler(&remote_journaler),
+ remote_client_meta(remote_client_meta) {
+ }
+
+ librbd::MockTestImageCtx* local_image_ctx;
+ std::string remote_mirror_uuid = "remote mirror uuid";
+ ::journal::MockJournaler* remote_journaler = nullptr;
+ librbd::journal::MirrorPeerClientMeta remote_client_meta;
+};
+
EventPreprocessor<librbd::MockTestImageCtx>* EventPreprocessor<librbd::MockTestImageCtx>::s_instance = nullptr;
ReplayStatusFormatter<librbd::MockTestImageCtx>* ReplayStatusFormatter<librbd::MockTestImageCtx>::s_instance = nullptr;
typedef Replayer<librbd::MockTestImageCtx> MockReplayer;
typedef EventPreprocessor<librbd::MockTestImageCtx> MockEventPreprocessor;
typedef ReplayStatusFormatter<librbd::MockTestImageCtx> MockReplayStatusFormatter;
+ typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
typedef Threads<librbd::MockTestImageCtx> MockThreads;
typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
typedef librbd::journal::Replay<librbd::MockTestImageCtx> MockReplay;
.WillOnce(CompleteContext(r));
}
- void expect_shut_down(::journal::MockJournaler &mock_journaler, int r) {
- EXPECT_CALL(mock_journaler, shut_down(_))
- .WillOnce(CompleteContext(m_threads->work_queue, r));
- }
-
void expect_shut_down(MockReplay &mock_replay, bool cancel_ops, int r) {
EXPECT_CALL(mock_replay, shut_down(cancel_ops, _))
.WillOnce(WithArg<1>(CompleteContext(m_threads->work_queue, r)));
expect_send(mock_close_image_request, 0);
expect_stop_replay(mock_remote_journaler, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
mock_local_journal,
mock_remote_journaler,
mock_local_journal_replay));
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitNoLocalJournal) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
mock_local_image_ctx.journal = nullptr;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
C_SaferCond init_ctx;
mock_replayer.init(&init_ctx);
ASSERT_EQ(-EINVAL, init_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitRemoteJournalerError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
expect_init(mock_remote_journaler, -EINVAL);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond init_ctx;
mock_replayer.init(&init_ctx);
ASSERT_EQ(-EINVAL, init_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitRemoteJournalerGetClientError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond init_ctx;
mock_replayer.init(&init_ctx);
ASSERT_EQ(-EINVAL, init_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitLocalJournalStartExternalReplayError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond init_ctx;
mock_replayer.init(&init_ctx);
ASSERT_EQ(-EINVAL, init_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitIsPromoted) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
ASSERT_EQ(0, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitDisconnected) {
mock_local_image_ctx.config.set_val("rbd_mirroring_resync_after_disconnect",
"false");
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond init_ctx;
mock_replayer.init(&init_ctx);
ASSERT_EQ(-ENOTCONN, init_ctx.wait());
ASSERT_FALSE(mock_replayer.is_resync_requested());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitDisconnectedResync) {
mock_local_image_ctx.config.set_val("rbd_mirroring_resync_after_disconnect",
"true");
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond init_ctx;
mock_replayer.init(&init_ctx);
ASSERT_EQ(-ENOTCONN, init_ctx.wait());
ASSERT_TRUE(mock_replayer.is_resync_requested());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitResyncRequested) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
ASSERT_EQ(0, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, InitResyncRequestedError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
MockCloseImageRequest mock_close_image_request;
expect_send(mock_close_image_request, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
ASSERT_EQ(0, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, ShutDownLocalJournalReplayError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
expect_send(mock_close_image_request, 0);
expect_stop_replay(mock_remote_journaler, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, -EPERM);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
ASSERT_EQ(-EINVAL, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, CloseLocalImageError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
expect_send(mock_close_image_request, -EINVAL);
expect_stop_replay(mock_remote_journaler, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, -EPERM);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
ASSERT_EQ(-EINVAL, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, StopRemoteJournalerError) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
expect_send(mock_close_image_request, 0);
expect_stop_replay(mock_remote_journaler, -EPERM);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
ASSERT_EQ(-EPERM, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
-}
-
-TEST_F(TestMockImageReplayerJournalReplayer, ShutDownRemoteJournalerError) {
- librbd::MockTestJournal mock_local_journal;
- librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
- mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
- ::journal::MockJournaler mock_remote_journaler;
- MockReplayerListener mock_replayer_listener;
- MockThreads mock_threads{m_threads};
- MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
-
- expect_work_queue_repeatedly(mock_threads);
-
- InSequence seq;
-
- MockReplay mock_local_journal_replay;
- MockEventPreprocessor mock_event_preprocessor;
- MockReplayStatusFormatter mock_replay_status_formatter;
- librbd::journal::Listener* local_journal_listener = nullptr;
- ::journal::ReplayHandler* remote_replay_handler = nullptr;
- ::journal::JournalMetadataListener* remote_journaler_listener = nullptr;
- ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
- mock_replayer_listener, mock_local_journal,
- mock_remote_journaler,
- mock_local_journal_replay,
- &local_journal_listener,
- &remote_replay_handler,
- &remote_journaler_listener));
-
- expect_shut_down(mock_local_journal_replay, true, 0);
- EXPECT_CALL(mock_local_journal, remove_listener(_));
- EXPECT_CALL(mock_local_journal, stop_external_replay());
- MockCloseImageRequest mock_close_image_request;
- expect_send(mock_close_image_request, 0);
- expect_stop_replay(mock_remote_journaler, 0);
- EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, -EPERM);
-
- C_SaferCond shutdown_ctx;
- mock_replayer.shut_down(&shutdown_ctx);
- ASSERT_EQ(-EPERM, shutdown_ctx.wait());
- ASSERT_EQ(nullptr, mock_local_image_ctx_ptr);
}
TEST_F(TestMockImageReplayerJournalReplayer, Replay) {
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
mock_local_image_ctx.config.set_val("rbd_mirroring_resync_after_disconnect",
"true");
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
+ ::journal::MockReplayEntry mock_replay_entry;
+ expect_get_commit_tid_in_debug(mock_replay_entry);
expect_work_queue_repeatedly(mock_threads);
InSequence seq;
&remote_replay_handler,
&remote_journaler_listener));
- ::journal::MockReplayEntry mock_replay_entry;
expect_try_pop_front(mock_remote_journaler, 1, true);
expect_shut_down(mock_local_journal_replay, false, -EINVAL);
EXPECT_CALL(mock_local_journal, stop_external_replay());
expect_send(mock_close_image_request, 0);
expect_stop_replay(mock_remote_journaler, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
+ ::journal::MockReplayEntry mock_replay_entry;
+ expect_get_commit_tid_in_debug(mock_replay_entry);
expect_work_queue_repeatedly(mock_threads);
InSequence seq;
&remote_replay_handler,
&remote_journaler_listener));
- ::journal::MockReplayEntry mock_replay_entry;
expect_try_pop_front(mock_remote_journaler, 1, true);
expect_shut_down(mock_local_journal_replay, false, 0);
EXPECT_CALL(mock_local_journal, stop_external_replay());
expect_send(mock_close_image_request, 0);
expect_stop_replay(mock_remote_journaler, 0);
EXPECT_CALL(mock_remote_journaler, remove_listener(_));
- expect_shut_down(mock_remote_journaler, 0);
C_SaferCond shutdown_ctx;
mock_replayer.shut_down(&shutdown_ctx);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
+ ::journal::MockReplayEntry mock_replay_entry;
+ expect_get_commit_tid_in_debug(mock_replay_entry);
expect_work_queue_repeatedly(mock_threads);
InSequence seq;
{1, 0, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
librbd::Journal<>::LOCAL_MIRROR_UUID,
true, 0, 0})};
- ::journal::MockReplayEntry mock_replay_entry;
expect_try_pop_front(mock_remote_journaler, tag.tid, true);
expect_shut_down(mock_local_journal_replay, false, 0);
EXPECT_CALL(mock_local_journal, stop_external_replay());
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
+ expect_get_commit_tid_in_debug(mock_replay_entry);
expect_get_tag_tid_in_debug(mock_local_journal);
InSequence seq;
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
librbd::MockTestJournal mock_local_journal;
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx,
mock_local_journal};
- librbd::MockTestImageCtx* mock_local_image_ctx_ptr = &mock_local_image_ctx;
::journal::MockJournaler mock_remote_journaler;
MockReplayerListener mock_replayer_listener;
MockThreads mock_threads{m_threads};
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_journaler,
+ {});
MockReplayer mock_replayer{
- &mock_local_image_ctx_ptr, &mock_remote_journaler, "local mirror uuid",
- "remote mirror uuid", &mock_replayer_listener, &mock_threads};
+ &mock_threads, "local mirror uuid", &mock_state_builder,
+ &mock_replayer_listener};
::journal::MockReplayEntry mock_replay_entry;
expect_work_queue_repeatedly(mock_threads);
#include "test/rbd_mirror/test_mock_fixture.h"
#include "librbd/journal/TypeTraits.h"
#include "librbd/mirror/GetInfoRequest.h"
+#include "tools/rbd_mirror/BaseRequest.h"
#include "tools/rbd_mirror/InstanceWatcher.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
#include "tools/rbd_mirror/image_replayer/StateBuilder.h"
-#include "tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h"
-#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
-#include "test/journal/mock/MockJournaler.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librbd/mock/MockImageCtx.h"
-#include "test/librbd/mock/MockJournal.h"
#include "test/rbd_mirror/mock/image_sync/MockSyncPointHandler.h"
+#include "test/rbd_mirror/mock/MockBaseRequest.h"
namespace librbd {
} // anonymous namespace
-namespace journal {
-
-template <>
-struct TypeTraits<librbd::MockTestImageCtx> {
- typedef ::journal::MockJournaler Journaler;
-};
-
-} // namespace journal
-
namespace mirror {
template<>
template<>
struct PrepareLocalImageRequest<librbd::MockTestImageCtx> {
static PrepareLocalImageRequest* s_instance;
- std::string *local_image_id = nullptr;
std::string *local_image_name = nullptr;
- std::string *tag_owner = nullptr;
+ StateBuilder<librbd::MockTestImageCtx>** state_builder = nullptr;
Context *on_finish = nullptr;
static PrepareLocalImageRequest* create(librados::IoCtx &,
const std::string &global_image_id,
- std::string *local_image_id,
std::string *local_image_name,
- std::string *tag_owner,
+ StateBuilder<librbd::MockTestImageCtx>** state_builder,
ContextWQ *work_queue,
Context *on_finish) {
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;
+ s_instance->state_builder = state_builder;
s_instance->on_finish = on_finish;
return s_instance;
}
template<>
struct PrepareRemoteImageRequest<librbd::MockTestImageCtx> {
static PrepareRemoteImageRequest* s_instance;
- std::string *remote_mirror_uuid = nullptr;
- std::string *remote_image_id = nullptr;
- ::journal::MockJournaler **remote_journaler = nullptr;
- cls::journal::ClientState *client_state;
- librbd::journal::MirrorPeerClientMeta *client_meta = nullptr;
+ StateBuilder<librbd::MockTestImageCtx>** state_builder = nullptr;
Context *on_finish = nullptr;
static PrepareRemoteImageRequest* create(Threads<librbd::MockTestImageCtx> *threads,
librados::IoCtx &,
const std::string &global_image_id,
const std::string &local_mirror_uuid,
- const std::string &local_image_id,
::journal::CacheManagerHandler *cache_manager_handler,
- std::string *remote_mirror_uuid,
- std::string *remote_image_id,
- ::journal::MockJournaler **remote_journaler,
- cls::journal::ClientState *client_state,
- librbd::journal::MirrorPeerClientMeta *client_meta,
+ StateBuilder<librbd::MockTestImageCtx>** state_builder,
Context *on_finish) {
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;
- s_instance->client_state = client_state;
- s_instance->client_meta = client_meta;
+ s_instance->state_builder = state_builder;
s_instance->on_finish = on_finish;
return s_instance;
}
template<>
struct StateBuilder<librbd::MockTestImageCtx> {
- virtual ~StateBuilder() {}
-
- void destroy_sync_point_handler() {
- }
- void destroy() {
- }
-};
-
-CloseImageRequest<librbd::MockTestImageCtx>*
- CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-OpenImageRequest<librbd::MockTestImageCtx>*
- OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-OpenLocalImageRequest<librbd::MockTestImageCtx>*
- OpenLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-PrepareLocalImageRequest<librbd::MockTestImageCtx>*
- PrepareLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-PrepareRemoteImageRequest<librbd::MockTestImageCtx>*
- PrepareRemoteImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-namespace journal {
-
-template<>
-struct CreateLocalImageRequest<librbd::MockTestImageCtx> {
- static CreateLocalImageRequest* s_instance;
-
- librbd::journal::MirrorPeerClientMeta* client_meta = nullptr;
- std::string* local_image_id;
- Context *on_finish = nullptr;
-
- static CreateLocalImageRequest* create(
- Threads<librbd::MockTestImageCtx>* mock_threads,
- librados::IoCtx &local_io_ctx,
- librbd::MockTestImageCtx* mock_remote_image_ctx,
- ::journal::MockJournaler *mock_remote_journaler,
- const std::string &global_image_id,
- const std::string &remote_mirror_uuid,
- librbd::journal::MirrorPeerClientMeta* client_meta,
- ProgressContext* progress_ctx,
- std::string* local_image_id, Context *on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->client_meta = client_meta;
- s_instance->local_image_id = local_image_id;
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- CreateLocalImageRequest() {
- ceph_assert(s_instance == nullptr);
- s_instance = this;
- }
- ~CreateLocalImageRequest() {
- s_instance = nullptr;
- }
-
- MOCK_METHOD0(send, void());
-};
-
-template<>
-struct PrepareReplayRequest<librbd::MockTestImageCtx> {
- static PrepareReplayRequest* s_instance;
-
- bool* resync_requested = nullptr;
- bool* syncing = nullptr;
- Context *on_finish = nullptr;
-
- static PrepareReplayRequest* create(
- librbd::MockTestImageCtx* local_image_ctx,
- ::journal::MockJournaler* remote_journaler,
- librbd::mirror::PromotionState remote_promotion_state,
- const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- librbd::journal::MirrorPeerClientMeta* client_meta,
- ProgressContext* progress_ctx,
- bool* resync_requested, bool* syncing, Context* on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->resync_requested = resync_requested;
- s_instance->syncing = syncing;
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- PrepareReplayRequest() {
- ceph_assert(s_instance == nullptr);
- s_instance = this;
- }
- ~PrepareReplayRequest() {
- s_instance = nullptr;
- }
-
- MOCK_METHOD0(send, void());
-};
-
-template<>
-struct StateBuilder<librbd::MockTestImageCtx>
- : image_replayer::StateBuilder<librbd::MockTestImageCtx>{
static StateBuilder* s_instance;
- ::journal::MockJournaler* remote_journaler = nullptr;
- librbd::journal::MirrorPeerClientMeta remote_client_meta;
-
image_sync::MockSyncPointHandler mock_sync_point_handler;
+ MockBaseRequest mock_base_request;
+
+ librbd::MockTestImageCtx* local_image_ctx = nullptr;
+ std::string local_image_id;
+ std::string remote_mirror_uuid;
+ std::string remote_image_id;
static StateBuilder* create(const std::string&) {
ceph_assert(s_instance != nullptr);
StateBuilder() {
s_instance = this;
}
+
+ MOCK_CONST_METHOD0(is_disconnected, bool());
+ MOCK_CONST_METHOD0(is_local_primary, bool());
+ MOCK_CONST_METHOD0(is_linked, bool());
+
+ MOCK_METHOD6(create_local_image_request,
+ BaseRequest*(Threads<librbd::MockTestImageCtx>*,
+ librados::IoCtx&,
+ librbd::MockTestImageCtx*,
+ const std::string&,
+ ProgressContext*,
+ Context*));
+ MOCK_METHOD6(create_prepare_replay_request,
+ BaseRequest*(const std::string&,
+ librbd::mirror::PromotionState,
+ ProgressContext*,
+ bool*, bool*, Context*));
+
+ void destroy_sync_point_handler() {
+ }
+ void destroy() {
+ }
};
-CreateLocalImageRequest<librbd::MockTestImageCtx>*
- CreateLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-PrepareReplayRequest<librbd::MockTestImageCtx>*
- PrepareReplayRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+CloseImageRequest<librbd::MockTestImageCtx>*
+ CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+OpenImageRequest<librbd::MockTestImageCtx>*
+ OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+OpenLocalImageRequest<librbd::MockTestImageCtx>*
+ OpenLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+PrepareLocalImageRequest<librbd::MockTestImageCtx>*
+ PrepareLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+PrepareRemoteImageRequest<librbd::MockTestImageCtx>*
+ PrepareRemoteImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
StateBuilder<librbd::MockTestImageCtx>*
StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr;
-} // namespace journal
} // namespace image_replayer
} // namespace mirror
} // namespace rbd
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::WithArg;
+using ::testing::WithArgs;
MATCHER_P(IsSameIoCtx, io_ctx, "") {
return &get_mock_io_ctx(arg) == &get_mock_io_ctx(*io_ctx);
typedef OpenLocalImageRequest<librbd::MockTestImageCtx> MockOpenLocalImageRequest;
typedef PrepareLocalImageRequest<librbd::MockTestImageCtx> MockPrepareLocalImageRequest;
typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
- typedef journal::CreateLocalImageRequest<librbd::MockTestImageCtx> MockCreateLocalImageRequest;
- typedef journal::PrepareReplayRequest<librbd::MockTestImageCtx> MockPrepareReplayRequest;
- typedef journal::StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
+ typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
typedef librbd::mirror::GetInfoRequest<librbd::MockTestImageCtx> MockGetMirrorInfoRequest;
typedef std::list<cls::journal::Tag> Tags;
}
void expect_send(MockPrepareLocalImageRequest &mock_request,
- const std::string &local_image_id,
- const std::string &local_image_name,
- const std::string &tag_owner,
- int r) {
+ MockStateBuilder& mock_state_builder,
+ const std::string& local_image_id,
+ const std::string& local_image_name, int r) {
EXPECT_CALL(mock_request, send())
- .WillOnce(Invoke([&mock_request, local_image_id, local_image_name,
- tag_owner, r]() {
+ .WillOnce(Invoke([&mock_request, &mock_state_builder, local_image_id,
+ local_image_name, r]() {
if (r == 0) {
- *mock_request.local_image_id = local_image_id;
+ *mock_request.state_builder = &mock_state_builder;
+ mock_state_builder.local_image_id = local_image_id;
*mock_request.local_image_name = local_image_name;
- *mock_request.tag_owner = tag_owner;
}
mock_request.on_finish->complete(r);
}));
}
void expect_send(MockPrepareRemoteImageRequest& mock_request,
- ::journal::MockJournaler& mock_remote_journaler,
- const std::string& mirror_uuid, const std::string& image_id,
- cls::journal::ClientState client_state,
- const librbd::journal::MirrorPeerClientMeta& mirror_peer_client_meta,
+ MockStateBuilder& mock_state_builder,
+ const std::string& remote_mirror_uuid,
+ const std::string& remote_image_id,
int r) {
EXPECT_CALL(mock_request, send())
- .WillOnce(Invoke([&mock_request, &mock_remote_journaler, image_id,
- mirror_uuid, client_state, mirror_peer_client_meta,
- r]() {
+ .WillOnce(Invoke([&mock_request, &mock_state_builder, remote_mirror_uuid,
+ remote_image_id, r]() {
if (r >= 0) {
- *mock_request.remote_journaler = &mock_remote_journaler;
- *mock_request.client_state = client_state;
- *mock_request.client_meta = mirror_peer_client_meta;
+ *mock_request.state_builder = &mock_state_builder;
+ mock_state_builder.remote_image_id = remote_image_id;
}
- *mock_request.remote_mirror_uuid = mirror_uuid;
- *mock_request.remote_image_id = image_id;
+ mock_state_builder.remote_mirror_uuid = remote_mirror_uuid;
mock_request.on_finish->complete(r);
}));
}
+ void expect_is_local_primary(MockStateBuilder& mock_state_builder,
+ bool is_primary) {
+ EXPECT_CALL(mock_state_builder, is_local_primary())
+ .WillOnce(Return(is_primary));
+ }
+
+ void expect_is_disconnected(MockStateBuilder& mock_state_builder,
+ bool is_disconnected) {
+ EXPECT_CALL(mock_state_builder, is_disconnected())
+ .WillOnce(Return(is_disconnected));
+ }
+
void expect_open_image(MockOpenImageRequest &mock_open_image_request,
librados::IoCtx &io_ctx, const std::string &image_id,
librbd::MockTestImageCtx &mock_image_ctx, int r) {
}));
}
- void expect_create_local_image(
- MockCreateLocalImageRequest &mock_create_local_image_request,
- const std::string& local_image_id, int r) {
- EXPECT_CALL(mock_create_local_image_request, send())
- .WillOnce(Invoke([this, &mock_create_local_image_request, local_image_id,
- r]() {
+ void expect_create_local_image(MockStateBuilder& mock_state_builder,
+ const std::string& local_image_id, int r) {
+ EXPECT_CALL(mock_state_builder,
+ create_local_image_request(_, _, _, _, _, _))
+ .WillOnce(WithArg<5>(
+ Invoke([this, &mock_state_builder, local_image_id, r](Context* ctx) {
if (r >= 0) {
- mock_create_local_image_request.client_meta->state =
- librbd::journal::MIRROR_PEER_STATE_SYNCING;
- mock_create_local_image_request.client_meta->image_id =
- local_image_id;
- *mock_create_local_image_request.local_image_id = local_image_id;
+ mock_state_builder.local_image_id = local_image_id;
}
+ mock_state_builder.mock_base_request.on_finish = ctx;
+ return &mock_state_builder.mock_base_request;
+ })));
+ EXPECT_CALL(mock_state_builder.mock_base_request, send())
+ .WillOnce(Invoke([this, &mock_state_builder, r]() {
m_threads->work_queue->queue(
- mock_create_local_image_request.on_finish, r);
+ mock_state_builder.mock_base_request.on_finish, r);
}));
}
- void expect_prepare_replay(
- MockPrepareReplayRequest& mock_prepare_replay_request,
- bool resync_requested, bool syncing, int r) {
- EXPECT_CALL(mock_prepare_replay_request, send())
- .WillOnce(Invoke([this, &mock_prepare_replay_request, resync_requested,
- syncing, r]() {
+ void expect_prepare_replay(MockStateBuilder& mock_state_builder,
+ bool resync_requested, bool syncing, int r) {
+ EXPECT_CALL(mock_state_builder,
+ create_prepare_replay_request(_, _, _, _, _, _))
+ .WillOnce(WithArgs<3, 4, 5>(
+ Invoke([this, &mock_state_builder, resync_requested, syncing, r]
+ (bool* resync, bool* sync, Context* ctx) {
if (r >= 0) {
- *mock_prepare_replay_request.resync_requested = resync_requested;
- *mock_prepare_replay_request.syncing = syncing;
+ *resync = resync_requested;
+ *sync = syncing;
}
- m_threads->work_queue->queue(mock_prepare_replay_request.on_finish,
- r);
+ mock_state_builder.mock_base_request.on_finish = ctx;
+ return &mock_state_builder.mock_base_request;
+ })));
+ EXPECT_CALL(mock_state_builder.mock_base_request, send())
+ .WillOnce(Invoke([this, &mock_state_builder, r]() {
+ m_threads->work_queue->queue(
+ mock_state_builder.mock_base_request.on_finish, r);
}));
}
global_image_id,
local_mirror_uuid,
nullptr, nullptr,
- &m_local_test_image_ctx,
- &m_local_image_id,
- &m_remote_image_id,
- &m_remote_mirror_uuid,
- &m_mock_remote_journaler,
+ &m_mock_state_builder,
&m_do_resync, on_finish);
}
librbd::ImageCtx *m_remote_image_ctx;
librbd::ImageCtx *m_local_image_ctx = nullptr;
- librbd::MockTestImageCtx *m_local_test_image_ctx = nullptr;
- std::string m_local_image_id;
- std::string m_remote_image_id;
- std::string m_remote_mirror_uuid;
- ::journal::MockJournaler *m_mock_remote_journaler = nullptr;
+ MockStateBuilder* m_mock_state_builder = nullptr;
bool m_do_resync = false;
};
InSequence seq;
// prepare local image
+ MockStateBuilder mock_state_builder;
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, false, 0);
+ expect_prepare_replay(mock_state_builder, false, false, 0);
+ expect_is_disconnected(mock_state_builder, false);
// close remote image
MockCloseImageRequest mock_close_image_request;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx,
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx,
-ENOENT);
// create local image
- MockCreateLocalImageRequest mock_create_local_image_request;
- expect_create_local_image(mock_create_local_image_request, "local image id",
- 0);
+ expect_create_local_image(mock_state_builder, "local image id", 0);
// re-open the local image
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
"local image id", &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, false, 0);
+ expect_prepare_replay(mock_state_builder, false, false, 0);
+ expect_is_disconnected(mock_state_builder, false);
// close remote image
MockCloseImageRequest mock_close_image_request;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx,
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, "", "", "", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder, "", "",
+ -ENOENT);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
librbd::mirror::PROMOTION_STATE_PRIMARY, 0);
// create local image
- MockCreateLocalImageRequest mock_create_local_image_request;
- expect_create_local_image(mock_create_local_image_request, "local image id",
- -EINVAL);
+ expect_create_local_image(mock_state_builder, "local image id", -EINVAL);
// close remote image
MockCloseImageRequest mock_close_image_request;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, false, -EINVAL);
-
- // close local image
- MockCloseImageRequest mock_close_image_request;
- expect_close_image(mock_close_image_request, mock_local_image_ctx, 0);
+ expect_prepare_replay(mock_state_builder, false, false, -EINVAL);
// close remote image
+ MockCloseImageRequest mock_close_image_request;
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, true, false, 0);
+ expect_prepare_replay(mock_state_builder, true, false, 0);
// close remote image
MockCloseImageRequest mock_close_image_request;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, true, 0);
+ expect_prepare_replay(mock_state_builder, false, true, 0);
+ expect_is_disconnected(mock_state_builder, false);
// image sync
- MockStateBuilder mock_state_builder;
MockImageSync mock_image_sync;
expect_image_sync(mock_image_sync, 0);
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, false, 0);
+ expect_prepare_replay(mock_state_builder, false, false, 0);
+ expect_is_disconnected(mock_state_builder, false);
// close remote image
MockCloseImageRequest mock_close_image_request;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, true, 0);
+ expect_prepare_replay(mock_state_builder, false, true, 0);
+ expect_is_disconnected(mock_state_builder, false);
// image sync
- MockStateBuilder mock_state_builder;
MockImageSync mock_image_sync;
expect_image_sync(mock_image_sync, -EINVAL);
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, true, 0);
+ expect_prepare_replay(mock_state_builder, false, true, 0);
+ expect_is_disconnected(mock_state_builder, false);
// close remote image
MockCloseImageRequest mock_close_image_request;
ASSERT_EQ(-ECANCELED, ctx.wait());
}
-TEST_F(TestMockImageReplayerBootstrapRequest, CloseLocalImageError) {
- InSequence seq;
-
- // prepare local image
- MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
-
- // prepare remote image
- MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 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
- MockGetMirrorInfoRequest mock_get_mirror_info_request;
- expect_get_remote_mirror_info(mock_get_mirror_info_request,
- {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "uuid",
- cls::rbd::MIRROR_IMAGE_STATE_ENABLED},
- librbd::mirror::PROMOTION_STATE_PRIMARY, 0);
-
- // open the local image
- librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
- MockOpenLocalImageRequest mock_open_local_image_request;
- expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
- mock_local_image_ctx.id, &mock_local_image_ctx, 0);
-
- // prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, false, -EREMOTEIO);
-
- // close local image
- MockCloseImageRequest mock_close_image_request;
- expect_close_image(mock_close_image_request, mock_local_image_ctx, -EINVAL);
-
- // close remote image
- expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
-
- C_SaferCond ctx;
- MockThreads mock_threads(m_threads);
- MockInstanceWatcher mock_instance_watcher;
- MockBootstrapRequest *request = create_request(
- &mock_threads, &mock_instance_watcher, "global image id",
- "local mirror uuid", &ctx);
- request->send();
- ASSERT_EQ(-EREMOTEIO, ctx.wait());
-}
-
TEST_F(TestMockImageReplayerBootstrapRequest, CloseRemoteImageError) {
InSequence seq;
// prepare local image
MockPrepareLocalImageRequest mock_prepare_local_image_request;
- expect_send(mock_prepare_local_image_request, m_local_image_ctx->id,
- m_local_image_ctx->name, "remote mirror uuid", 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_prepare_local_image_request, mock_state_builder,
+ m_local_image_ctx->id, m_local_image_ctx->name, 0);
// prepare remote image
MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
- ::journal::MockJournaler mock_remote_journaler;
- cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_ctx->id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- expect_send(mock_prepare_remote_image_request, mock_remote_journaler,
- "remote mirror uuid", m_remote_image_ctx->id, client_state,
- mirror_peer_client_meta, 0);
+ expect_send(mock_prepare_remote_image_request, mock_state_builder,
+ "remote mirror uuid", m_remote_image_ctx->id, 0);
+ expect_is_local_primary(mock_state_builder, false);
// 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,
// open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
- mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// prepare replay
- MockPrepareReplayRequest mock_prepare_replay_request;
- expect_prepare_replay(mock_prepare_replay_request, false, false, 0);
+ expect_prepare_replay(mock_state_builder, false, false, 0);
+ expect_is_disconnected(mock_state_builder, false);
MockCloseImageRequest mock_close_image_request;
expect_close_image(mock_close_image_request, mock_remote_image_ctx, -EINVAL);
#include "librbd/journal/TypeTraits.h"
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/StateBuilder.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include "test/journal/mock/MockJournaler.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librbd/mock/MockImageCtx.h"
MOCK_METHOD0(send, void());
};
+template<>
+struct StateBuilder<librbd::MockTestImageCtx> {
+ virtual ~StateBuilder() {}
+};
+
GetMirrorImageIdRequest<librbd::MockTestImageCtx>* GetMirrorImageIdRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+namespace journal {
+
+template<>
+struct StateBuilder<librbd::MockTestImageCtx>
+ : public image_replayer::StateBuilder<librbd::MockTestImageCtx> {
+ static StateBuilder* s_instance;
+
+ std::string local_image_id;
+ std::string local_tag_owner;
+
+ static StateBuilder* create(const std::string&) {
+ ceph_assert(s_instance != nullptr);
+ return s_instance;
+ }
+
+ StateBuilder() {
+ s_instance = this;
+ }
+};
+
+StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr;
+
+} // namespace journal
} // namespace image_replayer
} // namespace mirror
} // namespace rbd
public:
typedef PrepareLocalImageRequest<librbd::MockTestImageCtx> MockPrepareLocalImageRequest;
typedef GetMirrorImageIdRequest<librbd::MockTestImageCtx> MockGetMirrorImageIdRequest;
+ typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
+ typedef journal::StateBuilder<librbd::MockTestImageCtx> MockJournalStateBuilder;
void expect_get_mirror_image_id(MockGetMirrorImageIdRequest& mock_get_mirror_image_id_request,
const std::string& image_id, int r) {
librbd::MockJournal mock_journal;
expect_get_tag_owner(mock_journal, "local image id", "remote mirror uuid", 0);
- std::string local_image_id;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
std::string local_image_name;
- std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
- &local_image_id,
&local_image_name,
- &tag_owner,
+ &mock_state_builder,
m_threads->work_queue,
&ctx);
req->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_EQ(std::string("local image id"), local_image_id);
+ ASSERT_TRUE(mock_state_builder != nullptr);
ASSERT_EQ(std::string("local image name"), local_image_name);
- ASSERT_EQ(std::string("remote mirror uuid"), tag_owner);
+ ASSERT_EQ(std::string("local image id"),
+ mock_journal_state_builder.local_image_id);
+ ASSERT_EQ(std::string("remote mirror uuid"),
+ mock_journal_state_builder.local_tag_owner);
}
TEST_F(TestMockImageReplayerPrepareLocalImageRequest, MirrorImageIdError) {
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -EINVAL);
- std::string local_image_id;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
std::string local_image_name;
- std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
- &local_image_id,
&local_image_name,
- &tag_owner,
+ &mock_state_builder,
m_threads->work_queue,
&ctx);
req->send();
0);
expect_dir_get_name(m_local_io_ctx, "", -ENOENT);
- std::string local_image_id;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
std::string local_image_name;
- std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
- &local_image_id,
&local_image_name,
- &tag_owner,
+ &mock_state_builder,
m_threads->work_queue,
&ctx);
req->send();
cls::rbd::MIRROR_IMAGE_STATE_DISABLED,
"", -EINVAL);
- std::string local_image_id;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
std::string local_image_name;
- std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
- &local_image_id,
&local_image_name,
- &tag_owner,
+ &mock_state_builder,
m_threads->work_queue,
&ctx);
req->send();
expect_get_tag_owner(mock_journal, "local image id", "remote mirror uuid",
-ENOENT);
- std::string local_image_id;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
std::string local_image_name;
- std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
- &local_image_id,
&local_image_name,
- &tag_owner,
+ &mock_state_builder,
m_threads->work_queue,
&ctx);
req->send();
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/StateBuilder.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include "test/journal/mock/MockJournaler.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librbd/mock/MockImageCtx.h"
MOCK_METHOD0(send, void());
};
+template<>
+struct StateBuilder<librbd::MockTestImageCtx> {
+ std::string local_image_id;
+ std::string remote_mirror_uuid;
+ std::string remote_image_id;
+
+ virtual ~StateBuilder() {}
+
+ MOCK_CONST_METHOD0(get_mirror_image_mode, cls::rbd::MirrorImageMode());
+};
+
GetMirrorImageIdRequest<librbd::MockTestImageCtx>* GetMirrorImageIdRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+namespace journal {
+
+template<>
+struct StateBuilder<librbd::MockTestImageCtx>
+ : public image_replayer::StateBuilder<librbd::MockTestImageCtx> {
+ static StateBuilder* s_instance;
+
+ ::journal::MockJournalerProxy* remote_journaler = nullptr;
+ cls::journal::ClientState remote_client_state;
+ librbd::journal::MirrorPeerClientMeta remote_client_meta;
+
+ static StateBuilder* create(const std::string&) {
+ ceph_assert(s_instance != nullptr);
+ return s_instance;
+ }
+
+ StateBuilder() {
+ s_instance = this;
+ }
+};
+
+StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr;
+
+} // namespace journal
} // namespace image_replayer
} // namespace mirror
} // namespace rbd
typedef Threads<librbd::MockTestImageCtx> MockThreads;
typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
typedef GetMirrorImageIdRequest<librbd::MockTestImageCtx> MockGetMirrorImageIdRequest;
+ typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
+ typedef journal::StateBuilder<librbd::MockTestImageCtx> MockJournalStateBuilder;
+
+ void expect_get_mirror_image_mode(MockStateBuilder& mock_state_builder,
+ cls::rbd::MirrorImageMode mirror_image_mode) {
+ EXPECT_CALL(mock_state_builder, get_mirror_image_mode())
+ .WillOnce(Return(mirror_image_mode));
+ }
void expect_get_mirror_image_id(MockGetMirrorImageIdRequest& mock_get_mirror_image_id_request,
const std::string& image_id, int r) {
Return(r)));
}
- void expect_get_mirror_mode(librados::IoCtx &io_ctx,
- cls::rbd::MirrorImageMode mode, int r) {
+ void expect_get_mirror_image(librados::IoCtx &io_ctx,
+ cls::rbd::MirrorImageMode mode, int r) {
cls::rbd::MirrorImage mirror_image;
mirror_image.mode = mode;
};
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
"remote image id", 0);
- expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
- 0);
+ expect_get_mirror_image(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+ 0);
EXPECT_CALL(mock_remote_journaler, construct());
expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
client, 0);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "local image id",
- nullptr, &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
- ASSERT_EQ(std::string("remote image id"), remote_image_id);
- ASSERT_TRUE(remote_journaler != nullptr);
- ASSERT_EQ(cls::journal::CLIENT_STATE_DISCONNECTED, client_state);
- delete remote_journaler;
+ ASSERT_TRUE(mock_state_builder != nullptr);
+ ASSERT_EQ(std::string("remote mirror uuid"),
+ mock_journal_state_builder.remote_mirror_uuid);
+ ASSERT_EQ(std::string("remote image id"),
+ mock_journal_state_builder.remote_image_id);
+ ASSERT_TRUE(mock_journal_state_builder.remote_journaler != nullptr);
+ ASSERT_EQ(cls::journal::CLIENT_STATE_DISCONNECTED,
+ mock_journal_state_builder.remote_client_state);
}
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
"remote image id", 0);
- expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
- 0);
+ expect_get_mirror_image(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+ 0);
+ MockJournalStateBuilder mock_journal_state_builder;
+ expect_get_mirror_image_mode(mock_journal_state_builder,
+ cls::rbd::MIRROR_IMAGE_MODE_JOURNAL);
EXPECT_CALL(mock_remote_journaler, construct());
librbd::journal::ClientData client_data{mirror_peer_client_meta};
expect_journaler_register_client(mock_remote_journaler, client_data, 0);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ mock_journal_state_builder.local_image_id = "local image id";
+ MockStateBuilder* mock_state_builder = &mock_journal_state_builder;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "local image id",
- nullptr, &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
- ASSERT_EQ(std::string("remote image id"), remote_image_id);
- ASSERT_TRUE(remote_journaler != nullptr);
- ASSERT_EQ(cls::journal::CLIENT_STATE_CONNECTED, client_state);
- delete remote_journaler;
+ ASSERT_TRUE(mock_state_builder != nullptr);
+ ASSERT_EQ(std::string("remote mirror uuid"),
+ mock_journal_state_builder.remote_mirror_uuid);
+ ASSERT_EQ(std::string("remote image id"),
+ mock_journal_state_builder.remote_image_id);
+ ASSERT_TRUE(mock_journal_state_builder.remote_journaler != nullptr);
+ ASSERT_EQ(cls::journal::CLIENT_STATE_CONNECTED,
+ mock_journal_state_builder.remote_client_state);
}
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorUuidError) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
expect_mirror_uuid_get(m_remote_io_ctx, "", -EINVAL);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "", nullptr,
- &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(-EINVAL, ctx.wait());
- ASSERT_EQ(std::string(""), remote_mirror_uuid);
- ASSERT_TRUE(remote_journaler == nullptr);
+ ASSERT_EQ(std::string(""), mock_journal_state_builder.remote_mirror_uuid);
+ ASSERT_TRUE(mock_journal_state_builder.remote_journaler == nullptr);
}
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -EINVAL);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = &mock_journal_state_builder;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "", nullptr,
- &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(-EINVAL, ctx.wait());
- ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
- ASSERT_TRUE(remote_journaler == nullptr);
+ ASSERT_EQ(std::string("remote mirror uuid"),
+ mock_journal_state_builder.remote_mirror_uuid);
+ ASSERT_TRUE(mock_journal_state_builder.remote_journaler == nullptr);
}
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorModeError) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
"remote image id", 0);
- expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
- -EINVAL);
+ expect_get_mirror_image(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+ -EINVAL);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "", nullptr,
- &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(-EINVAL, ctx.wait());
- ASSERT_TRUE(remote_journaler == nullptr);
+ ASSERT_TRUE(mock_state_builder == nullptr);
}
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
"remote image id", 0);
- expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
- 0);
+ expect_get_mirror_image(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+ 0);
EXPECT_CALL(mock_remote_journaler, construct());
expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
client, -EINVAL);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ MockJournalStateBuilder mock_journal_state_builder;
+ MockStateBuilder* mock_state_builder = nullptr;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "local image id",
- nullptr, &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(-EINVAL, ctx.wait());
- ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
- ASSERT_EQ(std::string("remote image id"), remote_image_id);
- ASSERT_TRUE(remote_journaler == nullptr);
+ ASSERT_TRUE(mock_state_builder == nullptr);
}
TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) {
- journal::MockJournaler mock_remote_journaler;
+ ::journal::MockJournaler mock_remote_journaler;
MockThreads mock_threads(m_threads);
InSequence seq;
expect_get_mirror_image_id(mock_get_mirror_image_id_request,
"remote image id", 0);
- expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
- 0);
+ expect_get_mirror_image(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+ 0);
+ MockJournalStateBuilder mock_journal_state_builder;
+ expect_get_mirror_image_mode(mock_journal_state_builder,
+ cls::rbd::MIRROR_IMAGE_MODE_JOURNAL);
EXPECT_CALL(mock_remote_journaler, construct());
librbd::journal::ClientData client_data{mirror_peer_client_meta};
expect_journaler_register_client(mock_remote_journaler, client_data, -EINVAL);
- std::string remote_mirror_uuid;
- std::string remote_image_id;
- journal::MockJournalerProxy *remote_journaler = nullptr;
- cls::journal::ClientState client_state;
- librbd::journal::MirrorPeerClientMeta client_meta;
+ mock_journal_state_builder.local_image_id = "local image id";
+ MockStateBuilder* mock_state_builder = &mock_journal_state_builder;
C_SaferCond ctx;
auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
m_local_io_ctx,
m_remote_io_ctx,
"global image id",
"local mirror uuid",
- "local image id",
- nullptr, &remote_mirror_uuid,
- &remote_image_id,
- &remote_journaler,
- &client_state, &client_meta,
+ nullptr,
+ &mock_state_builder,
&ctx);
req->send();
ASSERT_EQ(-EINVAL, ctx.wait());
- ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
- ASSERT_EQ(std::string("remote image id"), remote_image_id);
- ASSERT_TRUE(remote_journaler == nullptr);
}
} // namespace image_replayer
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_MOCK_BASE_REQUEST_H
+#define CEPH_MOCK_BASE_REQUEST_H
+
+#include "tools/rbd_mirror/BaseRequest.h"
+#include <gmock/gmock.h>
+
+struct Context;
+
+namespace rbd {
+namespace mirror {
+
+struct MockBaseRequest : public BaseRequest {
+ MockBaseRequest() : BaseRequest(nullptr) {}
+
+ Context* on_finish = nullptr;
+
+ MOCK_METHOD0(send, void());
+};
+
+} // namespace mirror
+} // namepace rbd
+
+#endif // CEPH_MOCK_BASE_REQUEST_H
#include "tools/rbd_mirror/MirrorStatusUpdater.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
-#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
#include "tools/rbd_mirror/image_replayer/Replayer.h"
#include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
+#include "tools/rbd_mirror/image_replayer/StateBuilder.h"
#include "tools/rbd_mirror/image_replayer/Utils.h"
-#include "tools/rbd_mirror/image_replayer/journal/Replayer.h"
#include "test/rbd_mirror/test_mock_fixture.h"
-#include "test/journal/mock/MockJournaler.h"
#include "test/librbd/mock/MockImageCtx.h"
#include "test/rbd_mirror/mock/MockContextWQ.h"
#include "test/rbd_mirror/mock/MockSafeTimer.h"
} // anonymous namespace
-namespace journal {
-
-template <>
-struct TypeTraits<MockTestImageCtx> {
- typedef ::journal::MockJournalerProxy Journaler;
-};
-
-} // namespace journal
} // namespace librbd
namespace rbd {
template<>
struct BootstrapRequest<librbd::MockTestImageCtx> {
static BootstrapRequest* s_instance;
- librbd::MockTestImageCtx **image_ctx = nullptr;
- std::string* local_image_id = nullptr;
+
+ StateBuilder<librbd::MockTestImageCtx>** state_builder = nullptr;
bool *do_resync = nullptr;
Context *on_finish = nullptr;
const std::string &local_mirror_uuid,
::journal::CacheManagerHandler *cache_manager_handler,
rbd::mirror::ProgressContext *progress_ctx,
- librbd::MockTestImageCtx **local_image_ctx,
- std::string* local_image_id,
- std::string* remote_image_id,
- std::string* remote_mirror_uuid,
- ::journal::MockJournalerProxy** remote_journaler,
+ StateBuilder<librbd::MockTestImageCtx>** state_builder,
bool *do_resync, Context *on_finish) {
ceph_assert(s_instance != nullptr);
- s_instance->image_ctx = local_image_ctx;
- s_instance->local_image_id = local_image_id;
+ s_instance->state_builder = state_builder;
s_instance->do_resync = do_resync;
s_instance->on_finish = on_finish;
return s_instance;
MOCK_METHOD0(cancel, void());
};
-template<>
-struct CloseImageRequest<librbd::MockTestImageCtx> {
- static CloseImageRequest* s_instance;
- librbd::MockTestImageCtx **image_ctx = nullptr;
- Context *on_finish = nullptr;
-
- static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
- Context *on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->image_ctx = image_ctx;
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- CloseImageRequest() {
- ceph_assert(s_instance == nullptr);
- s_instance = this;
- }
-
- ~CloseImageRequest() {
- ceph_assert(s_instance == this);
- s_instance = nullptr;
- }
-
- MOCK_METHOD0(send, void());
-};
-
-BootstrapRequest<librbd::MockTestImageCtx>* BootstrapRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-CloseImageRequest<librbd::MockTestImageCtx>* CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-namespace journal {
-
-template <>
-struct Replayer<librbd::MockTestImageCtx> : public image_replayer::Replayer {
- static Replayer* s_instance;
- librbd::MockTestImageCtx** local_image_ctx;
+struct MockReplayer : public Replayer {
image_replayer::ReplayerListener* replayer_listener;
- static Replayer* create(librbd::MockTestImageCtx** local_image_ctx,
- ::journal::MockJournalerProxy* remote_journaler,
- const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- image_replayer::ReplayerListener* replayer_listener,
- Threads<librbd::MockTestImageCtx>* threads) {
- ceph_assert(s_instance != nullptr);
- ceph_assert(local_image_ctx != nullptr);
- s_instance->local_image_ctx = local_image_ctx;
- s_instance->replayer_listener = replayer_listener;
- return s_instance;
- }
-
- Replayer() {
- s_instance = this;
- }
-
MOCK_METHOD0(destroy, void());
MOCK_METHOD1(init, void(Context*));
MOCK_CONST_METHOD0(get_error_description, std::string());
};
-Replayer<librbd::MockTestImageCtx>* Replayer<librbd::MockTestImageCtx>::s_instance = nullptr;
+template <>
+struct StateBuilder<librbd::MockTestImageCtx> {
+ static StateBuilder* s_instance;
+
+ librbd::MockTestImageCtx* local_image_ctx = nullptr;
+ std::string local_image_id;
+ std::string remote_image_id;
+
+ void destroy() {
+ }
+
+ MOCK_METHOD1(close, void(Context*));
+ MOCK_METHOD3(create_replayer, Replayer*(Threads<librbd::MockTestImageCtx>*,
+ const std::string&,
+ ReplayerListener*));
+
+ StateBuilder() {
+ s_instance = this;
+ }
+};
+
+BootstrapRequest<librbd::MockTestImageCtx>* BootstrapRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr;
-} // namespace journal
} // namespace image_replayer
} // namespace mirror
} // namespace rbd
typedef ImageDeleter<librbd::MockTestImageCtx> MockImageDeleter;
typedef MirrorStatusUpdater<librbd::MockTestImageCtx> MockMirrorStatusUpdater;
typedef image_replayer::BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
- typedef image_replayer::CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
- typedef image_replayer::journal::Replayer<librbd::MockTestImageCtx> MockJournalReplayer;
+ typedef image_replayer::StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
+ typedef image_replayer::MockReplayer MockReplayer;
typedef ImageReplayer<librbd::MockTestImageCtx> MockImageReplayer;
typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
return bl;
}
- void expect_send(MockBootstrapRequest &mock_bootstrap_request,
- librbd::MockTestImageCtx &mock_local_image_ctx,
+ void expect_send(MockBootstrapRequest& mock_bootstrap_request,
+ MockStateBuilder& mock_state_builder,
+ librbd::MockTestImageCtx& mock_local_image_ctx,
bool do_resync, int r) {
EXPECT_CALL(mock_bootstrap_request, send())
- .WillOnce(Invoke([&mock_bootstrap_request, &mock_local_image_ctx,
- do_resync, r]() {
+ .WillOnce(Invoke([this, &mock_bootstrap_request, &mock_state_builder,
+ &mock_local_image_ctx, do_resync, r]() {
+ if (r == 0 || r == -ENOLINK) {
+ mock_state_builder.local_image_id = mock_local_image_ctx.id;
+ mock_state_builder.remote_image_id = m_remote_image_ctx->id;
+ *mock_bootstrap_request.state_builder = &mock_state_builder;
+ }
if (r == 0) {
- *mock_bootstrap_request.image_ctx = &mock_local_image_ctx;
+ mock_state_builder.local_image_ctx = &mock_local_image_ctx;
*mock_bootstrap_request.do_resync = do_resync;
- } else if (r == -ENOLINK) {
- *mock_bootstrap_request.local_image_id = mock_local_image_ctx.id;
+ }
+ if (r < 0) {
+ mock_state_builder.remote_image_id = "";
}
mock_bootstrap_request.on_finish->complete(r);
}));
}
- void expect_init(MockJournalReplayer& mock_journal_replayer, int r) {
- EXPECT_CALL(mock_journal_replayer, init(_))
- .WillOnce(Invoke([this, &mock_journal_replayer, r](Context* ctx) {
- if (r < 0) {
- *mock_journal_replayer.local_image_ctx = nullptr;
- }
+ void expect_create_replayer(MockStateBuilder& mock_state_builder,
+ MockReplayer& mock_replayer) {
+ EXPECT_CALL(mock_state_builder, create_replayer(_, _, _))
+ .WillOnce(WithArg<2>(
+ Invoke([this, &mock_replayer]
+ (image_replayer::ReplayerListener* replayer_listener) {
+ mock_replayer.replayer_listener = replayer_listener;
+ return &mock_replayer;
+ })));
+ }
+
+ void expect_close(MockStateBuilder& mock_state_builder, int r) {
+ EXPECT_CALL(mock_state_builder, close(_))
+ .WillOnce(Invoke([this, r](Context* ctx) {
m_threads->work_queue->queue(ctx, r);
}));
}
- void expect_shut_down(MockJournalReplayer& mock_journal_replayer, int r) {
- EXPECT_CALL(mock_journal_replayer, shut_down(_))
- .WillOnce(Invoke([this, &mock_journal_replayer, r](Context* ctx) {
- *mock_journal_replayer.local_image_ctx = nullptr;
+ void expect_init(MockReplayer& mock_replayer, int r) {
+ EXPECT_CALL(mock_replayer, init(_))
+ .WillOnce(Invoke([this, &mock_replayer, r](Context* ctx) {
m_threads->work_queue->queue(ctx, r);
}));
- EXPECT_CALL(mock_journal_replayer, destroy());
}
- void expect_get_replay_status(MockJournalReplayer& mock_journal_replayer) {
- EXPECT_CALL(mock_journal_replayer, get_replay_status(_, _))
- .WillRepeatedly(DoAll(WithArg<1>(CompleteContext(-EEXIST)),
- Return(true)));
+ void expect_shut_down(MockReplayer& mock_replayer, int r) {
+ EXPECT_CALL(mock_replayer, shut_down(_))
+ .WillOnce(Invoke([this, &mock_replayer, r](Context* ctx) {
+ m_threads->work_queue->queue(ctx, r);
+ }));
+ EXPECT_CALL(mock_replayer, destroy());
}
- void expect_send(MockCloseImageRequest &mock_close_image_request, int r) {
- EXPECT_CALL(mock_close_image_request, send())
- .WillOnce(Invoke([&mock_close_image_request, r]() {
- *mock_close_image_request.image_ctx = nullptr;
- mock_close_image_request.on_finish->complete(r);
- }));
+ void expect_get_replay_status(MockReplayer& mock_replayer) {
+ EXPECT_CALL(mock_replayer, get_replay_status(_, _))
+ .WillRepeatedly(DoAll(WithArg<1>(CompleteContext(-EEXIST)),
+ Return(true)));
}
void expect_set_mirror_image_status_repeatedly() {
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;
- MockBootstrapRequest mock_bootstrap_request;
- MockJournalReplayer mock_journal_replayer;
+ MockReplayer mock_replayer;
- expect_get_replay_status(mock_journal_replayer);
+ expect_get_replay_status(mock_replayer);
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
- expect_init(mock_journal_replayer, 0);
+ MockBootstrapRequest mock_bootstrap_request;
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, 0);
+
+ expect_create_replayer(mock_state_builder, mock_replayer);
+ expect_init(mock_replayer, 0);
create_image_replayer(mock_threads);
m_image_replayer->get_health_state());
// STOP
- expect_shut_down(mock_journal_replayer, 0);
+ expect_shut_down(mock_replayer, 0);
+ expect_close(mock_state_builder, 0);
expect_mirror_image_status_exists(false);
C_SaferCond stop_ctx;
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;
+ MockBootstrapRequest mock_bootstrap_request;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- MockBootstrapRequest mock_bootstrap_request;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -ENOMSG);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, -ENOMSG);
expect_mirror_image_status_exists(false);
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);
InSequence seq;
MockBootstrapRequest mock_bootstrap_request;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -ENOLINK);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, -ENOLINK);
+
+ expect_close(mock_state_builder, 0);
expect_trash_move(mock_image_deleter, "global image id", false, 0);
expect_mirror_image_status_exists(false);
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);
InSequence seq;
MockBootstrapRequest mock_bootstrap_request;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, true, 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ true, 0);
- MockCloseImageRequest mock_close_image_request;
- expect_send(mock_close_image_request, 0);
+ expect_close(mock_state_builder, 0);
expect_trash_move(mock_image_deleter, "global image id", true, 0);
expect_mirror_image_status_exists(false);
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);
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -EINVAL);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, -EINVAL);
expect_mirror_image_status_exists(false);
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);
create_image_replayer(mock_threads);
MockBootstrapRequest mock_bootstrap_request;
+ MockStateBuilder mock_state_builder;
EXPECT_CALL(mock_bootstrap_request, send())
.WillOnce(Invoke([this, &mock_bootstrap_request]() {
m_image_replayer->stop();
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;
MockBootstrapRequest mock_bootstrap_request;
- MockJournalReplayer mock_journal_replayer;
+ MockReplayer mock_replayer;
- expect_get_replay_status(mock_journal_replayer);
+ expect_get_replay_status(mock_replayer);
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
- expect_init(mock_journal_replayer, 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, 0);
+
+ expect_create_replayer(mock_state_builder, mock_replayer);
+ expect_init(mock_replayer, 0);
create_image_replayer(mock_threads);
// STOP (errors are ignored)
- expect_shut_down(mock_journal_replayer, -EINVAL);
+ expect_shut_down(mock_replayer, -EINVAL);
+ expect_close(mock_state_builder, -EINVAL);
expect_mirror_image_status_exists(false);
C_SaferCond stop_ctx;
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;
MockBootstrapRequest mock_bootstrap_request;
- MockJournalReplayer mock_journal_replayer;
+ MockReplayer mock_replayer;
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
- expect_init(mock_journal_replayer, -EINVAL);
- EXPECT_CALL(mock_journal_replayer, get_error_description())
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, 0);
+
+ expect_create_replayer(mock_state_builder, mock_replayer);
+ expect_init(mock_replayer, -EINVAL);
+ EXPECT_CALL(mock_replayer, get_error_description())
.WillOnce(Return("FAIL"));
- EXPECT_CALL(mock_journal_replayer, destroy());
+
+ EXPECT_CALL(mock_replayer, destroy());
+ expect_close(mock_state_builder, -EINVAL);
expect_mirror_image_status_exists(false);
create_image_replayer(mock_threads);
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;
MockBootstrapRequest mock_bootstrap_request;
- MockJournalReplayer mock_journal_replayer;
+ MockReplayer mock_replayer;
- expect_get_replay_status(mock_journal_replayer);
+ expect_get_replay_status(mock_replayer);
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
- expect_init(mock_journal_replayer, 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, 0);
+
+ expect_create_replayer(mock_state_builder, mock_replayer);
+ expect_init(mock_replayer, 0);
create_image_replayer(mock_threads);
ASSERT_EQ(0, start_ctx.wait());
// NOTIFY
- EXPECT_CALL(mock_journal_replayer, is_resync_requested())
+ EXPECT_CALL(mock_replayer, is_resync_requested())
.WillOnce(Return(true));
- expect_shut_down(mock_journal_replayer, 0);
+ expect_shut_down(mock_replayer, 0);
+ expect_close(mock_state_builder, 0);
expect_trash_move(mock_image_deleter, "global image id", true, 0);
expect_mirror_image_status_exists(false);
- mock_journal_replayer.replayer_listener->handle_notification();
+ mock_replayer.replayer_listener->handle_notification();
ASSERT_FALSE(m_image_replayer->is_running());
wait_for_stopped();
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;
MockBootstrapRequest mock_bootstrap_request;
- MockJournalReplayer mock_journal_replayer;
+ MockReplayer mock_replayer;
- expect_get_replay_status(mock_journal_replayer);
+ expect_get_replay_status(mock_replayer);
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
- expect_init(mock_journal_replayer, 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, 0);
+
+ expect_create_replayer(mock_state_builder, mock_replayer);
+ expect_init(mock_replayer, 0);
create_image_replayer(mock_threads);
ASSERT_EQ(0, start_ctx.wait());
// NOTIFY
- EXPECT_CALL(mock_journal_replayer, is_resync_requested())
+ EXPECT_CALL(mock_replayer, is_resync_requested())
.WillOnce(Return(false));
- EXPECT_CALL(mock_journal_replayer, is_replaying())
+ EXPECT_CALL(mock_replayer, is_replaying())
.WillOnce(Return(false));
- EXPECT_CALL(mock_journal_replayer, get_error_code())
+ EXPECT_CALL(mock_replayer, get_error_code())
.WillOnce(Return(-EINVAL));
- EXPECT_CALL(mock_journal_replayer, get_error_description())
+ EXPECT_CALL(mock_replayer, get_error_description())
.WillOnce(Return("INVALID"));
- expect_shut_down(mock_journal_replayer, 0);
+ expect_shut_down(mock_replayer, 0);
+ expect_close(mock_state_builder, 0);
expect_mirror_image_status_exists(false);
- mock_journal_replayer.replayer_listener->handle_notification();
+ mock_replayer.replayer_listener->handle_notification();
ASSERT_FALSE(m_image_replayer->is_running());
wait_for_stopped();
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;
MockBootstrapRequest mock_bootstrap_request;
- MockJournalReplayer mock_journal_replayer;
+ MockReplayer mock_replayer;
- expect_get_replay_status(mock_journal_replayer);
+ expect_get_replay_status(mock_replayer);
expect_set_mirror_image_status_repeatedly();
InSequence seq;
- expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
- expect_init(mock_journal_replayer, 0);
+ MockStateBuilder mock_state_builder;
+ expect_send(mock_bootstrap_request, mock_state_builder, mock_local_image_ctx,
+ false, 0);
+
+ expect_create_replayer(mock_state_builder, mock_replayer);
+ expect_init(mock_replayer, 0);
create_image_replayer(mock_threads);
ASSERT_EQ(0, start_ctx.wait());
// NOTIFY
- EXPECT_CALL(mock_journal_replayer, is_resync_requested())
+ EXPECT_CALL(mock_replayer, is_resync_requested())
.WillOnce(Return(false));
- EXPECT_CALL(mock_journal_replayer, is_replaying())
+ EXPECT_CALL(mock_replayer, is_replaying())
.WillOnce(Return(true));
mock_local_image_ctx.name = "NEW NAME";
- mock_journal_replayer.replayer_listener->handle_notification();
+ mock_replayer.replayer_listener->handle_notification();
// STOP
- expect_shut_down(mock_journal_replayer, 0);
+ expect_shut_down(mock_replayer, 0);
+ expect_close(mock_state_builder, 0);
expect_mirror_image_status_exists(false);
C_SaferCond stop_ctx;
#include "MirrorStatusUpdater.h"
#include "Threads.h"
#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
-#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
#include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
+#include "tools/rbd_mirror/image_replayer/StateBuilder.h"
#include "tools/rbd_mirror/image_replayer/Utils.h"
#include "tools/rbd_mirror/image_replayer/journal/Replayer.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include <map>
#define dout_context g_ceph_context
ImageReplayer<I>::~ImageReplayer()
{
unregister_admin_socket_hook();
- ceph_assert(m_local_image_ctx == nullptr);
+ ceph_assert(m_state_builder == nullptr);
ceph_assert(m_on_start_finish == nullptr);
ceph_assert(m_on_stop_finish == nullptr);
ceph_assert(m_bootstrap_request == nullptr);
return;
}
- m_local_image_id = "";
+ ceph_assert(m_state_builder == nullptr);
auto ctx = create_context_callback<
ImageReplayer, &ImageReplayer<I>::handle_bootstrap>(this);
auto request = image_replayer::BootstrapRequest<I>::create(
m_threads, m_local_io_ctx, m_remote_image.io_ctx, m_instance_watcher,
m_global_image_id, m_local_mirror_uuid, m_cache_manager_handler,
- &m_progress_cxt, &m_local_image_ctx, &m_local_image_id,
- &m_remote_image.image_id, &m_remote_image.mirror_uuid,
- &m_remote_journaler, &m_resync_requested, ctx);
+ &m_progress_cxt, &m_state_builder, &m_resync_requested, ctx);
request->get();
m_bootstrap_request = request;
std::lock_guard locker{m_lock};
m_bootstrap_request->put();
m_bootstrap_request = nullptr;
- if (m_local_image_ctx) {
- m_local_image_id = m_local_image_ctx->id;
- }
}
if (on_start_interrupted()) {
void ImageReplayer<I>::start_replay() {
dout(10) << dendl;
- // TODO support journal + snapshot replay
std::unique_lock locker{m_lock};
ceph_assert(m_replayer == nullptr);
- m_replayer = image_replayer::journal::Replayer<I>::create(
- &m_local_image_ctx, m_remote_journaler, m_local_mirror_uuid,
- m_remote_image.mirror_uuid, m_replayer_listener, m_threads);
+ m_replayer = m_state_builder->create_replayer(m_threads, m_local_mirror_uuid,
+ m_replayer_listener);
auto ctx = create_context_callback<
ImageReplayer<I>, &ImageReplayer<I>::handle_start_replay>(this);
m_replayer->destroy();
m_replayer = nullptr;
- derr << "error starting external replay on local image "
- << m_local_image_id << ": " << cpp_strerror(r) << dendl;
+ derr << "error starting replay: " << cpp_strerror(r) << dendl;
on_start_fail(r, error_description);
return;
}
state_desc = m_state_desc;
mirror_image_status_state = m_mirror_image_status_state;
last_r = m_last_r;
- stopping_replay = (m_local_image_ctx != nullptr);
+ stopping_replay = (m_replayer != nullptr);
if (m_bootstrap_request != nullptr) {
bootstrap_request = m_bootstrap_request;
handle_shut_down(r);
});
- // destruct the remote journaler created in prepare remote
- if (m_remote_journaler != nullptr) {
- ctx = new LambdaContext([this, ctx](int r) {
- delete m_remote_journaler;
- m_remote_journaler = nullptr;
- ctx->complete(0);
- });
- }
-
- // close the local image (if we aborted after a successful bootstrap)
- if (m_local_image_ctx != nullptr) {
- ctx = new LambdaContext([this, ctx](int r) {
- ceph_assert(m_local_image_ctx == nullptr);
- ctx->complete(0);
- });
+ // destruct the state builder
+ if (m_state_builder != nullptr) {
ctx = new LambdaContext([this, ctx](int r) {
- if (m_local_image_ctx == nullptr) {
- // never opened or closed via the replayer shutdown
- ctx->complete(0);
- return;
- }
-
- auto request = image_replayer::CloseImageRequest<I>::create(
- &m_local_image_ctx, ctx);
- request->send();
+ m_state_builder->close(ctx);
});
}
{
std::lock_guard locker{m_lock};
- if (m_delete_requested && !m_local_image_id.empty()) {
- ceph_assert(m_remote_image.image_id.empty());
+ if (m_delete_requested && m_state_builder != nullptr &&
+ !m_state_builder->local_image_id.empty()) {
+ ceph_assert(m_state_builder->remote_image_id.empty());
dout(0) << "remote image no longer exists: scheduling deletion" << dendl;
unregister_asok_hook = true;
std::swap(delete_requested, m_delete_requested);
}
std::swap(resync_requested, m_resync_requested);
- if (delete_requested || resync_requested) {
- m_local_image_id = "";
- } else if (m_last_r == -ENOENT &&
- m_local_image_id.empty() && m_remote_image.image_id.empty()) {
+ if (!delete_requested && !resync_requested && m_last_r == -ENOENT &&
+ ((m_state_builder == nullptr) ||
+ (m_state_builder->local_image_id.empty() &&
+ m_state_builder->remote_image_id.empty()))) {
dout(0) << "mirror image no longer exists" << dendl;
unregister_asok_hook = true;
m_finished = true;
return;
}
+ if (m_state_builder != nullptr) {
+ m_state_builder->destroy();
+ m_state_builder = nullptr;
+ }
+
dout(10) << "stop complete" << dendl;
Context *on_start = nullptr;
Context *on_stop = nullptr;
{
// detect a rename of the local image
- ceph_assert(m_local_image_ctx != nullptr);
- std::shared_lock image_locker{m_local_image_ctx->image_lock};
- if (m_local_image_name != m_local_image_ctx->name) {
+ ceph_assert(m_state_builder != nullptr &&
+ m_state_builder->local_image_ctx != nullptr);
+ std::shared_lock image_locker{m_state_builder->local_image_ctx->image_lock};
+ if (m_local_image_name != m_state_builder->local_image_ctx->name) {
// will re-register with new name after next status update
dout(10) << "image renamed" << dendl;
- m_local_image_name = m_local_image_ctx->name;
+ m_local_image_name = m_state_builder->local_image_ctx->name;
}
}
#include "common/AsyncOpTracker.h"
#include "common/ceph_mutex.h"
-#include "common/WorkQueue.h"
#include "include/rados/librados.hpp"
-#include "cls/journal/cls_journal_types.h"
#include "cls/rbd/cls_rbd_types.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/journal/Types.h"
-#include "librbd/journal/TypeTraits.h"
#include "ProgressContext.h"
#include "tools/rbd_mirror/Types.h"
#include "tools/rbd_mirror/image_replayer/Types.h"
class AdminSocketHook;
-namespace journal {
-
-struct CacheManagerHandler;
-class Journaler;
-
-} // namespace journal
-
-namespace librbd {
-
-class ImageCtx;
-
-} // namespace librbd
+namespace journal { struct CacheManagerHandler; }
+namespace librbd { class ImageCtx; }
namespace rbd {
namespace mirror {
class Replayer;
template <typename> class BootstrapRequest;
+template <typename> class StateBuilder;
} // namespace image_replayer
};
struct RemoteImage {
- std::string mirror_uuid;
- std::string image_id;
librados::IoCtx io_ctx;
MirrorStatusUpdater<ImageCtxT>* mirror_status_updater = nullptr;
};
struct ReplayerListener;
- typedef typename librbd::journal::TypeTraits<ImageCtxT>::Journaler Journaler;
typedef boost::optional<State> OptionalState;
typedef boost::optional<cls::rbd::MirrorImageStatusState>
OptionalMirrorImageStatusState;
Peers m_peers;
RemoteImage m_remote_image;
- std::string m_local_image_id;
std::string m_local_image_name;
std::string m_image_spec;
bool m_delete_requested = false;
bool m_resync_requested = false;
- ImageCtxT *m_local_image_ctx = nullptr;
-
- decltype(ImageCtxT::journal) m_local_journal = nullptr;
- Journaler* m_remote_journaler = nullptr;
-
+ image_replayer::StateBuilder<ImageCtxT>* m_state_builder = nullptr;
image_replayer::Replayer* m_replayer = nullptr;
ReplayerListener* m_replayer_listener = nullptr;
#include "common/Timer.h"
#include "common/debug.h"
#include "common/errno.h"
+#include "common/WorkQueue.h"
#include "librbd/Utils.h"
#include "ImageReplayer.h"
#include "InstanceReplayer.h"
#include "librbd/Utils.h"
#include "librbd/journal/Types.h"
#include "librbd/mirror/GetInfoRequest.h"
-#include "tools/rbd_mirror/ProgressContext.h"
+#include "tools/rbd_mirror/BaseRequest.h"
#include "tools/rbd_mirror/ImageSync.h"
+#include "tools/rbd_mirror/ProgressContext.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h"
-#include "tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h"
#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include "tools/rbd_mirror/image_replayer/journal/SyncPointHandler.h"
const std::string& local_mirror_uuid,
::journal::CacheManagerHandler* cache_manager_handler,
ProgressContext* progress_ctx,
- I** local_image_ctx,
- std::string* local_image_id,
- std::string* remote_image_id,
- std::string* remote_mirror_uuid,
- Journaler** remote_journaler,
+ StateBuilder<I>** state_builder,
bool* do_resync,
Context* on_finish)
: CancelableRequest("rbd::mirror::image_replayer::BootstrapRequest",
m_local_mirror_uuid(local_mirror_uuid),
m_cache_manager_handler(cache_manager_handler),
m_progress_ctx(progress_ctx),
- m_local_image_ctx(local_image_ctx),
- m_local_image_id(local_image_id),
- m_remote_image_id(remote_image_id),
- m_remote_mirror_uuid(remote_mirror_uuid),
- m_remote_journaler(remote_journaler),
+ m_state_builder(state_builder),
m_do_resync(do_resync),
m_lock(ceph::make_mutex(unique_lock_name("BootstrapRequest::m_lock",
this))) {
dout(10) << dendl;
update_progress("PREPARE_LOCAL_IMAGE");
- *m_local_image_id = "";
+ ceph_assert(*m_state_builder == nullptr);
m_local_image_name = m_global_image_id;
auto ctx = create_context_callback<
BootstrapRequest, &BootstrapRequest<I>::handle_prepare_local_image>(this);
auto req = image_replayer::PrepareLocalImageRequest<I>::create(
- m_local_io_ctx, m_global_image_id, m_local_image_id,
- &m_prepare_local_image_name, &m_local_image_tag_owner,
- m_threads->work_queue, ctx);
+ m_local_io_ctx, m_global_image_id, &m_prepare_local_image_name,
+ m_state_builder, m_threads->work_queue, ctx);
req->send();
}
void BootstrapRequest<I>::handle_prepare_local_image(int r) {
dout(10) << "r=" << r << dendl;
+ ceph_assert(r < 0 || *m_state_builder != nullptr);
if (r == -ENOENT) {
dout(10) << "local image does not exist" << dendl;
} else if (r < 0) {
dout(10) << dendl;
update_progress("PREPARE_REMOTE_IMAGE");
- ceph_assert(*m_remote_journaler == nullptr);
-
Context *ctx = create_context_callback<
BootstrapRequest, &BootstrapRequest<I>::handle_prepare_remote_image>(this);
auto req = image_replayer::PrepareRemoteImageRequest<I>::create(
m_threads, m_local_io_ctx, m_remote_io_ctx, m_global_image_id,
- m_local_mirror_uuid, *m_local_image_id, m_cache_manager_handler,
- m_remote_mirror_uuid, m_remote_image_id, m_remote_journaler,
- &m_client_state, &m_client_meta, ctx);
+ m_local_mirror_uuid, m_cache_manager_handler, m_state_builder, ctx);
req->send();
}
void BootstrapRequest<I>::handle_prepare_remote_image(int r) {
dout(10) << "r=" << r << dendl;
- ceph_assert(r < 0 ? *m_remote_journaler == nullptr :
- *m_remote_journaler != nullptr);
- if (r < 0 && !m_local_image_id->empty() &&
- m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
- // local image is primary -- fall-through
- } else if (r == -ENOENT) {
+ auto state_builder = *m_state_builder;
+ if (state_builder != nullptr && state_builder->is_local_primary()) {
+ dout(5) << "local image is primary" << dendl;
+ finish(-ENOMSG);
+ return;
+ } else if (r == -ENOENT || state_builder == nullptr) {
dout(10) << "remote image does not exist" << dendl;
// TODO need to support multiple remote images
- if (m_remote_image_id->empty() && !m_local_image_id->empty() &&
- m_local_image_tag_owner == *m_remote_mirror_uuid) {
+ if (state_builder != nullptr &&
+ state_builder->remote_image_id.empty() &&
+ !state_builder->local_image_id.empty() &&
+ state_builder->is_linked()) {
// local image exists and is non-primary and linked to the missing
// remote image
finish(-ENOLINK);
} else {
- dout(10) << "remote image does not exist" << dendl;
finish(-ENOENT);
}
return;
return;
}
- if (!m_local_image_id->empty() &&
- m_local_image_tag_owner == librbd::Journal<>::LOCAL_MIRROR_UUID) {
- dout(5) << "local image is primary" << dendl;
- finish(-ENOMSG);
- return;
- }
-
open_remote_image();
}
template <typename I>
void BootstrapRequest<I>::open_remote_image() {
- dout(15) << "remote_image_id=" << *m_remote_image_id << dendl;
+ ceph_assert(*m_state_builder != nullptr);
+ auto remote_image_id = (*m_state_builder)->remote_image_id;
+ dout(15) << "remote_image_id=" << remote_image_id << dendl;
update_progress("OPEN_REMOTE_IMAGE");
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,
+ m_remote_io_ctx, &m_remote_image_ctx, remote_image_id, false,
ctx);
request->send();
}
return;
}
+ ceph_assert(*m_state_builder != nullptr);
if (m_promotion_state != librbd::mirror::PROMOTION_STATE_PRIMARY &&
- m_local_image_id->empty()) {
+ (*m_state_builder)->local_image_id.empty()) {
// no local image and remote isn't primary -- don't sync it
- dout(5) << "remote image is not primary -- not syncing"
- << dendl;
+ dout(5) << "remote image is not primary -- not syncing" << dendl;
m_ret_val = -EREMOTEIO;
close_remote_image();
return;
}
- if (!m_client_meta.image_id.empty()) {
- // have an image id -- use that to open the image since a deletion (resync)
- // will leave the old image id registered in the peer
- *m_local_image_id = m_client_meta.image_id;
- }
- if (m_local_image_id->empty()) {
+ if ((*m_state_builder)->local_image_id.empty()) {
create_local_image();
return;
}
template <typename I>
void BootstrapRequest<I>::open_local_image() {
- dout(15) << "local_image_id=" << *m_local_image_id << dendl;
+ ceph_assert(*m_state_builder != nullptr);
+ auto local_image_id = (*m_state_builder)->local_image_id;
+
+ dout(15) << "local_image_id=" << local_image_id << dendl;
update_progress("OPEN_LOCAL_IMAGE");
BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_local_image>(
this);
OpenLocalImageRequest<I> *request = OpenLocalImageRequest<I>::create(
- m_local_io_ctx, m_local_image_ctx, *m_local_image_id, m_threads->work_queue,
- ctx);
+ m_local_io_ctx, &(*m_state_builder)->local_image_ctx, local_image_id,
+ m_threads->work_queue, ctx);
request->send();
}
void BootstrapRequest<I>::handle_open_local_image(int r) {
dout(15) << "r=" << r << dendl;
+ ceph_assert(*m_state_builder != nullptr);
+ auto local_image_ctx = (*m_state_builder)->local_image_ctx;
+ ceph_assert((r >= 0 && local_image_ctx != nullptr) ||
+ (r < 0 && local_image_ctx == nullptr));
+
if (r == -ENOENT) {
- ceph_assert(*m_local_image_ctx == nullptr);
dout(10) << "local image missing" << dendl;
create_local_image();
return;
} else if (r == -EREMOTEIO) {
- ceph_assert(*m_local_image_ctx == nullptr);
dout(10) << "local image is primary -- skipping image replay" << dendl;
m_ret_val = r;
close_remote_image();
return;
} else if (r < 0) {
- ceph_assert(*m_local_image_ctx == nullptr);
derr << "failed to open local image: " << cpp_strerror(r) << dendl;
m_ret_val = r;
close_remote_image();
dout(10) << dendl;
update_progress("PREPARE_REPLAY");
- // TODO support snapshot-based mirroring
+ ceph_assert(*m_state_builder != nullptr);
auto ctx = create_context_callback<
- BootstrapRequest<I>,
- &BootstrapRequest<I>::handle_prepare_replay>(this);
- auto request = journal::PrepareReplayRequest<I>::create(
- *m_local_image_ctx, *m_remote_journaler, m_promotion_state,
- m_local_mirror_uuid, *m_remote_mirror_uuid, &m_client_meta,
- m_progress_ctx, m_do_resync, &m_syncing, ctx);
+ BootstrapRequest<I>, &BootstrapRequest<I>::handle_prepare_replay>(this);
+ auto request = (*m_state_builder)->create_prepare_replay_request(
+ m_local_mirror_uuid, m_promotion_state, m_progress_ctx, m_do_resync,
+ &m_syncing, ctx);
request->send();
}
derr << "failed to prepare local replay: " << cpp_strerror(r) << dendl;
}
m_ret_val = r;
- close_local_image();
+ close_remote_image();
return;
} else if (*m_do_resync) {
dout(10) << "local image resync requested" << dendl;
close_remote_image();
return;
- } else if (m_client_state == cls::journal::CLIENT_STATE_DISCONNECTED) {
+ } else if ((*m_state_builder)->is_disconnected()) {
dout(10) << "client flagged disconnected -- skipping bootstrap" << dendl;
// The caller is expected to detect disconnect initializing remote journal.
m_ret_val = 0;
dout(10) << dendl;
update_progress("CREATE_LOCAL_IMAGE");
- // TODO support snapshot-based mirroring
+ ceph_assert(*m_state_builder != nullptr);
auto ctx = create_context_callback<
BootstrapRequest<I>,
&BootstrapRequest<I>::handle_create_local_image>(this);
- auto request = journal::CreateLocalImageRequest<I>::create(
- m_threads, m_local_io_ctx, m_remote_image_ctx, *m_remote_journaler,
- m_global_image_id, *m_remote_mirror_uuid, &m_client_meta, m_progress_ctx,
- m_local_image_id, ctx);
+ auto request = (*m_state_builder)->create_local_image_request(
+ m_threads, m_local_io_ctx, m_remote_image_ctx, m_global_image_id,
+ m_progress_ctx, ctx);
request->send();
}
return;
}
- m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
-
open_local_image();
}
dout(15) << dendl;
ceph_assert(m_image_sync == nullptr);
- // TODO temporary
- m_state_builder = journal::StateBuilder<I>::create(m_global_image_id);
- m_state_builder->remote_journaler = *m_remote_journaler;
- m_state_builder->remote_client_meta = m_client_meta;
- auto sync_point_handler = m_state_builder->create_sync_point_handler();
+ auto state_builder = *m_state_builder;
+ auto sync_point_handler = state_builder->create_sync_point_handler();
Context *ctx = create_context_callback<
BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(this);
m_image_sync = ImageSync<I>::create(
- m_threads, *m_local_image_ctx, m_remote_image_ctx, m_local_mirror_uuid,
- sync_point_handler, m_instance_watcher, m_progress_ctx, ctx);
+ m_threads, state_builder->local_image_ctx, m_remote_image_ctx,
+ m_local_mirror_uuid, sync_point_handler, m_instance_watcher,
+ m_progress_ctx, ctx);
m_image_sync->get();
locker.unlock();
m_image_sync->put();
m_image_sync = nullptr;
- m_state_builder->destroy_sync_point_handler();
-
- // TODO
- m_state_builder->remote_journaler = nullptr;
- m_state_builder->destroy();
- m_state_builder = nullptr;
+ (*m_state_builder)->destroy_sync_point_handler();
}
if (r < 0) {
close_remote_image();
}
-template <typename I>
-void BootstrapRequest<I>::close_local_image() {
- dout(15) << dendl;
-
- update_progress("CLOSE_LOCAL_IMAGE");
-
- Context *ctx = create_context_callback<
- BootstrapRequest<I>, &BootstrapRequest<I>::handle_close_local_image>(
- this);
- CloseImageRequest<I> *request = CloseImageRequest<I>::create(
- m_local_image_ctx, ctx);
- request->send();
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_close_local_image(int r) {
- dout(15) << "r=" << r << dendl;
-
- if (r < 0) {
- derr << "error encountered closing local image: " << cpp_strerror(r)
- << dendl;
- }
-
- close_remote_image();
-}
-
template <typename I>
void BootstrapRequest<I>::close_remote_image() {
dout(15) << dendl;
#include "include/int_types.h"
#include "include/rados/librados.hpp"
#include "common/ceph_mutex.h"
-#include "cls/journal/cls_journal_types.h"
#include "cls/rbd/cls_rbd_types.h"
-#include "librbd/journal/Types.h"
-#include "librbd/journal/TypeTraits.h"
#include "librbd/mirror/Types.h"
#include "tools/rbd_mirror/CancelableRequest.h"
#include "tools/rbd_mirror/Types.h"
-#include <list>
#include <string>
class Context;
namespace image_replayer {
-// TODO
-namespace journal { template <typename> class StateBuilder; }
+template <typename> class StateBuilder;
template <typename ImageCtxT = librbd::ImageCtx>
class BootstrapRequest : public CancelableRequest {
public:
- typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
- typedef typename TypeTraits::Journaler Journaler;
- typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
typedef rbd::mirror::ProgressContext ProgressContext;
static BootstrapRequest* create(
const std::string& local_mirror_uuid,
::journal::CacheManagerHandler* cache_manager_handler,
ProgressContext* progress_ctx,
- ImageCtxT** local_image_ctx,
- std::string* local_image_id,
- std::string* remote_image_id,
- std::string* remote_mirror_uuid,
- Journaler** remote_journaler,
+ StateBuilder<ImageCtxT>** state_builder,
bool* do_resync,
Context* on_finish) {
return new BootstrapRequest(
threads, local_io_ctx, remote_io_ctx, instance_watcher, global_image_id,
- local_mirror_uuid, cache_manager_handler, progress_ctx, local_image_ctx,
- local_image_id, remote_image_id, remote_mirror_uuid, remote_journaler,
+ local_mirror_uuid, cache_manager_handler, progress_ctx, state_builder,
do_resync, on_finish);
}
const std::string& local_mirror_uuid,
::journal::CacheManagerHandler* cache_manager_handler,
ProgressContext* progress_ctx,
- ImageCtxT** local_image_ctx,
- std::string* local_image_id,
- std::string* remote_image_id,
- std::string* remote_mirror_uuid,
- Journaler** remote_journaler,
+ StateBuilder<ImageCtxT>** state_builder,
bool* do_resync,
Context* on_finish);
~BootstrapRequest() override;
* | * *
* | * *
* v * *
- * PREPARE_REPLAY * * * * * * * * * *
- * | * * *
- * | * * *
- * v (skip if not needed) v * *
- * IMAGE_SYNC * * * * > CLOSE_LOCAL_IMAGE * *
- * | | * *
- * | | * *
- * \-----------------\ /-----/ * *
- * | * *
- * | * *
- * /----------------------------/ * *
+ * PREPARE_REPLAY * * * * * * * * * * * * * * *
+ * | * *
+ * | * *
+ * v (skip if not needed) * *
+ * IMAGE_SYNC * * * * * * * * * * * * * * * * *
+ * | * *
+ * | * *
+ * /---------/ * *
* | * *
* v * *
* CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * * *
*
* @endverbatim
*/
- typedef std::list<cls::journal::Tag> Tags;
-
Threads<ImageCtxT>* m_threads;
librados::IoCtx &m_local_io_ctx;
librados::IoCtx &m_remote_io_ctx;
std::string m_local_mirror_uuid;
::journal::CacheManagerHandler *m_cache_manager_handler;
ProgressContext *m_progress_ctx;
- ImageCtxT **m_local_image_ctx;
- std::string* m_local_image_id;
- std::string* m_remote_image_id;
- std::string* m_remote_mirror_uuid;
- Journaler** m_remote_journaler;
+ StateBuilder<ImageCtxT>** m_state_builder;
bool *m_do_resync;
mutable ceph::mutex m_lock;
int m_ret_val = 0;
std::string m_local_image_name;
- std::string m_local_image_tag_owner;
std::string m_prepare_local_image_name;
- cls::journal::ClientState m_client_state =
- cls::journal::CLIENT_STATE_DISCONNECTED;
- librbd::journal::MirrorPeerClientMeta m_client_meta;
-
bool m_syncing = false;
ImageSync<ImageCtxT> *m_image_sync = nullptr;
- // TODO temporary
- journal::StateBuilder<ImageCtxT>* m_state_builder = nullptr;
-
void prepare_local_image();
void handle_prepare_local_image(int r);
void image_sync();
void handle_image_sync(int r);
- void close_local_image();
- void handle_close_local_image(int r);
-
void close_remote_image();
void handle_close_remote_image(int r);
#include "librbd/Utils.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#include <type_traits>
#define dout_context g_ceph_context
PrepareLocalImageRequest<I>,
&PrepareLocalImageRequest<I>::handle_get_local_image_id>(this);
auto req = GetMirrorImageIdRequest<I>::create(m_io_ctx, m_global_image_id,
- m_local_image_id, ctx);
+ &m_local_image_id, ctx);
req->send();
}
template <typename I>
void PrepareLocalImageRequest<I>::handle_get_local_image_id(int r) {
dout(10) << "r=" << r << ", "
- << "local_image_id=" << *m_local_image_id << dendl;
+ << "local_image_id=" << m_local_image_id << dendl;
if (r < 0) {
finish(r);
dout(10) << dendl;
librados::ObjectReadOperation op;
- librbd::cls_client::dir_get_name_start(&op, *m_local_image_id);
+ librbd::cls_client::dir_get_name_start(&op, m_local_image_id);
m_out_bl.clear();
librados::AioCompletion *aio_comp = create_rados_callback<
dout(10) << dendl;
librados::ObjectReadOperation op;
- librbd::cls_client::mirror_image_get_start(&op, *m_local_image_id);
+ librbd::cls_client::mirror_image_get_start(&op, m_local_image_id);
m_out_bl.clear();
auto aio_comp = create_rados_callback<
Context *ctx = create_context_callback<
PrepareLocalImageRequest<I>,
&PrepareLocalImageRequest<I>::handle_get_tag_owner>(this);
- Journal::get_tag_owner(m_io_ctx, *m_local_image_id, m_tag_owner,
+ Journal::get_tag_owner(m_io_ctx, m_local_image_id, &m_local_tag_owner,
m_work_queue, ctx);
}
template <typename I>
void PrepareLocalImageRequest<I>::handle_get_tag_owner(int r) {
dout(10) << "r=" << r << ", "
- << "tag_owner=" << *m_tag_owner << dendl;
+ << "tag_owner=" << m_local_tag_owner << dendl;
if (r < 0) {
derr << "failed to retrieve journal tag owner: " << cpp_strerror(r)
return;
}
+ // journal-based local image exists
+ auto state_builder = journal::StateBuilder<I>::create(m_global_image_id);
+ state_builder->local_image_id = m_local_image_id;
+ state_builder->local_tag_owner = m_local_tag_owner;
+ *m_state_builder = state_builder;
+
finish(0);
}
namespace mirror {
namespace image_replayer {
+template <typename> class StateBuilder;
+
template <typename ImageCtxT = librbd::ImageCtx>
class PrepareLocalImageRequest {
public:
- static PrepareLocalImageRequest *create(librados::IoCtx &io_ctx,
- const std::string &global_image_id,
- std::string *local_image_id,
- std::string *local_image_name,
- std::string *tag_owner,
- ContextWQ *work_queue,
- Context *on_finish) {
- return new PrepareLocalImageRequest(io_ctx, global_image_id, local_image_id,
- local_image_name, tag_owner, work_queue,
- on_finish);
+ static PrepareLocalImageRequest *create(
+ librados::IoCtx &io_ctx,
+ const std::string &global_image_id,
+ std::string *local_image_name,
+ StateBuilder<ImageCtxT>** state_builder,
+ ContextWQ *work_queue,
+ Context *on_finish) {
+ return new PrepareLocalImageRequest(io_ctx, global_image_id,
+ local_image_name, state_builder,
+ work_queue, on_finish);
}
- PrepareLocalImageRequest(librados::IoCtx &io_ctx,
- const std::string &global_image_id,
- std::string *local_image_id,
- std::string *local_image_name,
- std::string *tag_owner,
- ContextWQ *work_queue,
- Context *on_finish)
+ PrepareLocalImageRequest(
+ librados::IoCtx &io_ctx,
+ const std::string &global_image_id,
+ std::string *local_image_name,
+ StateBuilder<ImageCtxT>** state_builder,
+ ContextWQ *work_queue,
+ Context *on_finish)
: m_io_ctx(io_ctx), m_global_image_id(global_image_id),
- m_local_image_id(local_image_id), m_local_image_name(local_image_name),
- m_tag_owner(tag_owner), m_work_queue(work_queue), m_on_finish(on_finish) {
+ m_local_image_name(local_image_name), m_state_builder(state_builder),
+ m_work_queue(work_queue), m_on_finish(on_finish) {
}
void send();
librados::IoCtx &m_io_ctx;
std::string m_global_image_id;
- std::string *m_local_image_id;
std::string *m_local_image_name;
- std::string *m_tag_owner;
+ StateBuilder<ImageCtxT>** m_state_builder;
ContextWQ *m_work_queue;
Context *m_on_finish;
bufferlist m_out_bl;
+ std::string m_local_image_id;
+
+ // journal-based mirroring
+ std::string m_local_tag_owner;
void get_local_image_id();
void handle_get_local_image_id(int r);
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
#include "tools/rbd_mirror/image_replayer/Utils.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
void PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid(int r) {
if (r >= 0) {
auto it = m_out_bl.cbegin();
- r = librbd::cls_client::mirror_uuid_get_finish(&it, m_remote_mirror_uuid);
- if (r >= 0 && m_remote_mirror_uuid->empty()) {
+ r = librbd::cls_client::mirror_uuid_get_finish(&it, &m_remote_mirror_uuid);
+ if (r >= 0 && m_remote_mirror_uuid.empty()) {
r = -ENOENT;
}
}
return;
}
+ auto state_builder = *m_state_builder;
+ if (state_builder != nullptr) {
+ // if the local image exists but the remote image doesn't, we still
+ // want to populate the remote mirror uuid that we've looked up
+ state_builder->remote_mirror_uuid = m_remote_mirror_uuid;
+ }
+
get_remote_image_id();
}
&PrepareRemoteImageRequest<I>::handle_get_remote_image_id>(this);
auto req = GetMirrorImageIdRequest<I>::create(m_remote_io_ctx,
m_global_image_id,
- m_remote_image_id, ctx);
+ &m_remote_image_id, ctx);
req->send();
}
template <typename I>
void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
dout(10) << "r=" << r << ", "
- << "remote_image_id=" << *m_remote_image_id << dendl;
+ << "remote_image_id=" << m_remote_image_id << dendl;
if (r < 0) {
finish(r);
dout(10) << dendl;
librados::ObjectReadOperation op;
- librbd::cls_client::mirror_image_get_start(&op, *m_remote_image_id);
+ librbd::cls_client::mirror_image_get_start(&op, m_remote_image_id);
auto aio_comp = create_rados_callback<
PrepareRemoteImageRequest<I>,
return;
}
+ if (*m_state_builder != nullptr &&
+ (*m_state_builder)->get_mirror_image_mode() != mirror_image.mode) {
+ derr << "local and remote mirror image using different mirroring modes "
+ << "for image " << m_global_image_id << ": split-brain" << dendl;
+ finish(-EEXIST);
+ return;
+ }
+
switch (mirror_image.mode) {
case cls::rbd::MIRROR_IMAGE_MODE_JOURNAL:
get_client();
journal_settings.commit_interval = cct->_conf.get_val<double>(
"rbd_mirror_journal_commit_age");
- ceph_assert(*m_remote_journaler == nullptr);
- *m_remote_journaler = new Journaler(m_threads->work_queue, m_threads->timer,
- &m_threads->timer_lock, m_remote_io_ctx,
- *m_remote_image_id, m_local_mirror_uuid,
- journal_settings,
- m_cache_manager_handler);
+ ceph_assert(m_remote_journaler == nullptr);
+ m_remote_journaler = new Journaler(m_threads->work_queue, m_threads->timer,
+ &m_threads->timer_lock, m_remote_io_ctx,
+ m_remote_image_id, m_local_mirror_uuid,
+ journal_settings, m_cache_manager_handler);
Context *ctx = create_async_context_callback(
m_threads->work_queue, create_context_callback<
PrepareRemoteImageRequest<I>,
&PrepareRemoteImageRequest<I>::handle_get_client>(this));
- (*m_remote_journaler)->get_client(m_local_mirror_uuid, &m_client, ctx);
+ m_remote_journaler->get_client(m_local_mirror_uuid, &m_client, ctx);
}
template <typename I>
void PrepareRemoteImageRequest<I>::handle_get_client(int r) {
dout(10) << "r=" << r << dendl;
+ MirrorPeerClientMeta client_meta;
if (r == -ENOENT) {
dout(10) << "client not registered" << dendl;
register_client();
} else if (r < 0) {
derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
finish(r);
- } else if (!util::decode_client_meta(m_client, m_client_meta)) {
+ } else if (!util::decode_client_meta(m_client, &client_meta)) {
// require operator intervention since the data is corrupt
finish(-EBADMSG);
} else {
// skip registration if it already exists
- *m_client_state = m_client.state;
+ finalize_journal_state_builder(m_client.state, client_meta);
finish(0);
}
}
void PrepareRemoteImageRequest<I>::register_client() {
dout(10) << dendl;
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ auto state_builder = *m_state_builder;
+ librbd::journal::MirrorPeerClientMeta client_meta{
+ (state_builder == nullptr ? "" : state_builder->local_image_id)};
+ client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- librbd::journal::ClientData client_data{mirror_peer_client_meta};
+ librbd::journal::ClientData client_data{client_meta};
bufferlist client_data_bl;
encode(client_data, client_data_bl);
m_threads->work_queue, create_context_callback<
PrepareRemoteImageRequest<I>,
&PrepareRemoteImageRequest<I>::handle_register_client>(this));
- (*m_remote_journaler)->register_client(client_data_bl, ctx);
+ m_remote_journaler->register_client(client_data_bl, ctx);
}
template <typename I>
return;
}
- *m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
- *m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
-
+ auto state_builder = *m_state_builder;
+ librbd::journal::MirrorPeerClientMeta client_meta{
+ (state_builder == nullptr ? "" : state_builder->local_image_id)};
+ client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ finalize_journal_state_builder(cls::journal::CLIENT_STATE_CONNECTED,
+ client_meta);
finish(0);
}
+template <typename I>
+void PrepareRemoteImageRequest<I>::finalize_journal_state_builder(
+ cls::journal::ClientState client_state,
+ const MirrorPeerClientMeta& client_meta) {
+ journal::StateBuilder<I>* state_builder = nullptr;
+ if (*m_state_builder != nullptr) {
+ // already verified that it's a matching builder in
+ // 'handle_get_mirror_image'
+ state_builder = dynamic_cast<journal::StateBuilder<I>*>(*m_state_builder);
+ ceph_assert(state_builder != nullptr);
+ } else {
+ state_builder = journal::StateBuilder<I>::create(m_global_image_id);
+ *m_state_builder = state_builder;
+ }
+
+ state_builder->remote_mirror_uuid = m_remote_mirror_uuid;
+ state_builder->remote_image_id = m_remote_image_id;
+ state_builder->remote_journaler = m_remote_journaler;
+ state_builder->remote_client_state = client_state;
+ state_builder->remote_client_meta = client_meta;
+}
+
template <typename I>
void PrepareRemoteImageRequest<I>::finish(int r) {
dout(10) << "r=" << r << dendl;
if (r < 0) {
- delete *m_remote_journaler;
- *m_remote_journaler = nullptr;
+ delete m_remote_journaler;
+ m_remote_journaler = nullptr;
}
m_on_finish->complete(r);
#include "include/rados/librados_fwd.hpp"
#include "cls/journal/cls_journal_types.h"
#include "journal/Settings.h"
+#include "librbd/journal/Types.h"
#include "librbd/journal/TypeTraits.h"
#include <string>
namespace image_replayer {
+template <typename> class StateBuilder;
+
template <typename ImageCtxT = librbd::ImageCtx>
class PrepareRemoteImageRequest {
public:
typedef typename TypeTraits::Journaler Journaler;
typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
- static PrepareRemoteImageRequest *create(Threads<ImageCtxT> *threads,
- librados::IoCtx &local_io_ctx,
- librados::IoCtx &remote_io_ctx,
- const std::string &global_image_id,
- const std::string &local_mirror_uuid,
- const std::string &local_image_id,
- ::journal::CacheManagerHandler *cache_manager_handler,
- std::string *remote_mirror_uuid,
- std::string *remote_image_id,
- Journaler **remote_journaler,
- cls::journal::ClientState *client_state,
- MirrorPeerClientMeta *client_meta,
- Context *on_finish) {
+ static PrepareRemoteImageRequest *create(
+ Threads<ImageCtxT> *threads,
+ librados::IoCtx &local_io_ctx,
+ librados::IoCtx &remote_io_ctx,
+ const std::string &global_image_id,
+ const std::string &local_mirror_uuid,
+ ::journal::CacheManagerHandler *cache_manager_handler,
+ StateBuilder<ImageCtxT>** state_builder,
+ Context *on_finish) {
return new PrepareRemoteImageRequest(threads, local_io_ctx, remote_io_ctx,
global_image_id, local_mirror_uuid,
- local_image_id, cache_manager_handler,
- remote_mirror_uuid, remote_image_id,
- remote_journaler, client_state,
- client_meta, on_finish);
+ cache_manager_handler, state_builder,
+ on_finish);
}
- PrepareRemoteImageRequest(Threads<ImageCtxT> *threads,
- librados::IoCtx &local_io_ctx,
- librados::IoCtx &remote_io_ctx,
- const std::string &global_image_id,
- const std::string &local_mirror_uuid,
- const std::string &local_image_id,
- ::journal::CacheManagerHandler *cache_manager_handler,
- std::string *remote_mirror_uuid,
- std::string *remote_image_id,
- Journaler **remote_journaler,
- cls::journal::ClientState *client_state,
- MirrorPeerClientMeta *client_meta,
- Context *on_finish)
+ PrepareRemoteImageRequest(
+ Threads<ImageCtxT> *threads,
+ librados::IoCtx &local_io_ctx,
+ librados::IoCtx &remote_io_ctx,
+ const std::string &global_image_id,
+ const std::string &local_mirror_uuid,
+ ::journal::CacheManagerHandler *cache_manager_handler,
+ StateBuilder<ImageCtxT>** state_builder,
+ Context *on_finish)
: m_threads(threads),
m_local_io_ctx(local_io_ctx),
m_remote_io_ctx(remote_io_ctx),
m_global_image_id(global_image_id),
- m_local_mirror_uuid(local_mirror_uuid), m_local_image_id(local_image_id),
+ m_local_mirror_uuid(local_mirror_uuid),
m_cache_manager_handler(cache_manager_handler),
- m_remote_mirror_uuid(remote_mirror_uuid),
- m_remote_image_id(remote_image_id),
- m_remote_journaler(remote_journaler), m_client_state(client_state),
- m_client_meta(client_meta), m_on_finish(on_finish) {
+ m_state_builder(state_builder),
+ m_on_finish(on_finish) {
}
void send();
librados::IoCtx &m_remote_io_ctx;
std::string m_global_image_id;
std::string m_local_mirror_uuid;
- std::string m_local_image_id;
::journal::CacheManagerHandler *m_cache_manager_handler;
- std::string *m_remote_mirror_uuid;
- std::string *m_remote_image_id;
- Journaler **m_remote_journaler;
- cls::journal::ClientState *m_client_state;
- MirrorPeerClientMeta *m_client_meta;
+ StateBuilder<ImageCtxT>** m_state_builder;
Context *m_on_finish;
bufferlist m_out_bl;
+ std::string m_remote_mirror_uuid;
+ std::string m_remote_image_id;
+
+ // journal-based mirroring
+ Journaler *m_remote_journaler = nullptr;
cls::journal::Client m_client;
void get_remote_mirror_uuid();
void register_client();
void handle_register_client(int r);
+ void finalize_journal_state_builder(cls::journal::ClientState client_state,
+ const MirrorPeerClientMeta& client_meta);
void finish(int r);
};
#include "journal/Journaler.h"
#include "librbd/ImageCtx.h"
#include "librbd/Utils.h"
+#include "librbd/journal/Types.h"
#include "tools/rbd_mirror/ProgressContext.h"
#include "tools/rbd_mirror/image_replayer/CreateImageRequest.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
template <typename I>
void CreateLocalImageRequest<I>::send() {
- *m_local_image_id = "";
+ m_state_builder->local_image_id = "";
unregister_client();
}
auto ctx = create_context_callback<
CreateLocalImageRequest<I>,
&CreateLocalImageRequest<I>::handle_unregister_client>(this);
- m_remote_journaler->unregister_client(ctx);
+ m_state_builder->remote_journaler->unregister_client(ctx);
}
template <typename I>
return;
}
- *m_client_meta = librbd::journal::MirrorPeerClientMeta{""};
+ m_state_builder->remote_client_meta = {};
register_client();
}
template <typename I>
void CreateLocalImageRequest<I>::register_client() {
- ceph_assert(m_local_image_id->empty());
- *m_local_image_id = librbd::util::generate_image_id<I>(m_local_io_ctx);
- dout(10) << "local_image_id=" << *m_local_image_id << dendl;
+ ceph_assert(m_state_builder->local_image_id.empty());
+ m_state_builder->local_image_id =
+ librbd::util::generate_image_id<I>(m_local_io_ctx);
+ dout(10) << "local_image_id=" << m_state_builder->local_image_id << dendl;
update_progress("REGISTER_CLIENT");
- librbd::journal::MirrorPeerClientMeta client_meta{*m_local_image_id};
+ librbd::journal::MirrorPeerClientMeta client_meta{
+ m_state_builder->local_image_id};
client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
librbd::journal::ClientData client_data{client_meta};
auto ctx = create_context_callback<
CreateLocalImageRequest<I>,
&CreateLocalImageRequest<I>::handle_register_client>(this);
- m_remote_journaler->register_client(client_data_bl, ctx);
+ m_state_builder->remote_journaler->register_client(client_data_bl, ctx);
}
template <typename I>
return;
}
- *m_client_meta = librbd::journal::MirrorPeerClientMeta{*m_local_image_id};
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ m_state_builder->remote_client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ m_state_builder->remote_client_meta = {m_state_builder->local_image_id};
+ m_state_builder->remote_client_meta.state =
+ librbd::journal::MIRROR_PEER_STATE_SYNCING;
create_local_image();
}
template <typename I>
void CreateLocalImageRequest<I>::create_local_image() {
- dout(10) << "local_image_id=" << *m_local_image_id << dendl;
+ dout(10) << "local_image_id=" << m_state_builder->local_image_id << dendl;
update_progress("CREATE_LOCAL_IMAGE");
m_remote_image_ctx->image_lock.lock_shared();
CreateLocalImageRequest<I>,
&CreateLocalImageRequest<I>::handle_create_local_image>(this);
auto request = CreateImageRequest<I>::create(
- m_threads, m_local_io_ctx, m_global_image_id, m_remote_mirror_uuid,
- image_name, *m_local_image_id, m_remote_image_ctx, ctx);
+ m_threads, m_local_io_ctx, m_global_image_id,
+ m_state_builder->remote_mirror_uuid, image_name,
+ m_state_builder->local_image_id, m_remote_image_ctx, ctx);
request->send();
}
template <typename I>
dout(10) << "r=" << r << dendl;
if (r == -EBADF) {
- dout(5) << "image id " << *m_local_image_id << " already in-use" << dendl;
- *m_local_image_id = "";
+ dout(5) << "image id " << m_state_builder->local_image_id << " "
+ << "already in-use" << dendl;
+ m_state_builder->local_image_id = "";
update_client_image();
return;
} else if (r < 0) {
template <typename I>
void CreateLocalImageRequest<I>::update_client_image() {
- ceph_assert(m_local_image_id->empty());
- *m_local_image_id = librbd::util::generate_image_id<I>(m_local_io_ctx);
+ ceph_assert(m_state_builder->local_image_id.empty());
+ m_state_builder->local_image_id =
+ librbd::util::generate_image_id<I>(m_local_io_ctx);
- dout(10) << "local_image_id=" << *m_local_image_id << dendl;
+ dout(10) << "local_image_id=" << m_state_builder->local_image_id << dendl;
update_progress("UPDATE_CLIENT_IMAGE");
- librbd::journal::MirrorPeerClientMeta client_meta{*m_local_image_id};
+ librbd::journal::MirrorPeerClientMeta client_meta{
+ m_state_builder->local_image_id};
client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
librbd::journal::ClientData client_data(client_meta);
auto ctx = create_context_callback<
CreateLocalImageRequest<I>,
&CreateLocalImageRequest<I>::handle_update_client_image>(this);
- m_remote_journaler->update_client(data_bl, ctx);
+ m_state_builder->remote_journaler->update_client(data_bl, ctx);
}
template <typename I>
return;
}
- *m_client_meta = librbd::journal::MirrorPeerClientMeta{*m_local_image_id};
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ m_state_builder->remote_client_meta = {m_state_builder->local_image_id};
+ m_state_builder->remote_client_meta.state =
+ librbd::journal::MIRROR_PEER_STATE_SYNCING;
create_local_image();
}
#define RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_CREATE_LOCAL_IMAGE_REQUEST_H
#include "include/rados/librados_fwd.hpp"
-#include "librbd/journal/Types.h"
-#include "librbd/journal/TypeTraits.h"
#include "tools/rbd_mirror/BaseRequest.h"
#include <string>
namespace image_replayer {
namespace journal {
+template <typename> class StateBuilder;
+
template <typename ImageCtxT>
class CreateLocalImageRequest : public BaseRequest {
public:
- typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
- typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
- typedef typename TypeTraits::Journaler Journaler;
typedef rbd::mirror::ProgressContext ProgressContext;
static CreateLocalImageRequest* create(
- Threads<ImageCtxT>* threads, librados::IoCtx& local_io_ctx,
- ImageCtxT* remote_image_ctx, Journaler* remote_journaler,
+ Threads<ImageCtxT>* threads,
+ librados::IoCtx& local_io_ctx,
+ ImageCtxT* remote_image_ctx,
const std::string& global_image_id,
- const std::string& remote_mirror_uuid,
- MirrorPeerClientMeta* client_meta, ProgressContext* progress_ctx,
- std::string* local_image_id, Context* on_finish) {
+ ProgressContext* progress_ctx,
+ StateBuilder<ImageCtxT>* state_builder,
+ Context* on_finish) {
return new CreateLocalImageRequest(threads, local_io_ctx, remote_image_ctx,
- remote_journaler, global_image_id,
- remote_mirror_uuid, client_meta,
- progress_ctx, local_image_id, on_finish);
+ global_image_id, progress_ctx,
+ state_builder, on_finish);
}
CreateLocalImageRequest(
- Threads<ImageCtxT>* threads, librados::IoCtx& local_io_ctx,
- ImageCtxT* remote_image_ctx, Journaler* remote_journaler,
+ Threads<ImageCtxT>* threads,
+ librados::IoCtx& local_io_ctx,
+ ImageCtxT* remote_image_ctx,
const std::string& global_image_id,
- const std::string& remote_mirror_uuid,
- MirrorPeerClientMeta* client_meta, ProgressContext* progress_ctx,
- std::string* local_image_id, Context* on_finish)
+ ProgressContext* progress_ctx,
+ StateBuilder<ImageCtxT>* state_builder,
+ Context* on_finish)
: BaseRequest(on_finish),
- m_threads(threads), m_local_io_ctx(local_io_ctx),
+ m_threads(threads),
+ m_local_io_ctx(local_io_ctx),
m_remote_image_ctx(remote_image_ctx),
- m_remote_journaler(remote_journaler),
m_global_image_id(global_image_id),
- m_remote_mirror_uuid(remote_mirror_uuid), m_client_meta(client_meta),
- m_progress_ctx(progress_ctx), m_local_image_id(local_image_id) {
+ m_progress_ctx(progress_ctx),
+ m_state_builder(state_builder) {
}
void send();
Threads<ImageCtxT>* m_threads;
librados::IoCtx& m_local_io_ctx;
ImageCtxT* m_remote_image_ctx;
- Journaler* m_remote_journaler;
std::string m_global_image_id;
- std::string m_remote_mirror_uuid;
- MirrorPeerClientMeta* m_client_meta;
ProgressContext* m_progress_ctx;
- std::string* m_local_image_id;
+ StateBuilder<ImageCtxT>* m_state_builder;
void unregister_client();
void handle_unregister_client(int r);
#include "librbd/Journal.h"
#include "librbd/Utils.h"
#include "tools/rbd_mirror/ProgressContext.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
*m_resync_requested = false;
*m_syncing = false;
- std::shared_lock image_locker(m_local_image_ctx->image_lock);
- if (m_local_image_ctx->journal == nullptr) {
+ if (m_state_builder->local_image_id !=
+ m_state_builder->remote_client_meta.image_id) {
+ // somehow our local image has a different image id than the image id
+ // registered in the remote image
+ derr << "split-brain detected: local_image_id="
+ << m_state_builder->local_image_id << ", "
+ << "registered local_image_id="
+ << m_state_builder->remote_client_meta.image_id << dendl;
+ finish(-EEXIST);
+ return;
+ }
+
+ std::shared_lock image_locker(m_state_builder->local_image_ctx->image_lock);
+ if (m_state_builder->local_image_ctx->journal == nullptr) {
image_locker.unlock();
derr << "local image does not support journaling" << dendl;
return;
}
- int r = m_local_image_ctx->journal->is_resync_requested(m_resync_requested);
+ int r = m_state_builder->local_image_ctx->journal->is_resync_requested(
+ m_resync_requested);
if (r < 0) {
image_locker.unlock();
return;
}
- m_local_tag_tid = m_local_image_ctx->journal->get_tag_tid();
- m_local_tag_data = m_local_image_ctx->journal->get_tag_data();
+ m_local_tag_tid = m_state_builder->local_image_ctx->journal->get_tag_tid();
+ m_local_tag_data = m_state_builder->local_image_ctx->journal->get_tag_data();
dout(10) << "local tag=" << m_local_tag_tid << ", "
<< "local tag data=" << m_local_tag_data << dendl;
image_locker.unlock();
- if (m_local_tag_data.mirror_uuid != m_remote_mirror_uuid &&
+ if (m_local_tag_data.mirror_uuid != m_state_builder->remote_mirror_uuid &&
m_remote_promotion_state != librbd::mirror::PROMOTION_STATE_PRIMARY) {
// if the local mirror is not linked to the (now) non-primary image,
// stop the replay. Otherwise, we ignore that the remote is non-primary
if (*m_resync_requested) {
finish(0);
return;
- } else if (m_client_meta->state ==
+ } else if (m_state_builder->remote_client_meta.state ==
librbd::journal::MIRROR_PEER_STATE_SYNCING &&
- m_local_tag_data.mirror_uuid == m_remote_mirror_uuid) {
+ m_local_tag_data.mirror_uuid ==
+ m_state_builder->remote_mirror_uuid) {
// if the initial sync hasn't completed, we cannot replay
*m_syncing = true;
finish(0);
template <typename I>
void PrepareReplayRequest<I>::update_client_state() {
- if (m_client_meta->state != librbd::journal::MIRROR_PEER_STATE_SYNCING ||
- m_local_tag_data.mirror_uuid == m_remote_mirror_uuid) {
+ if (m_state_builder->remote_client_meta.state !=
+ librbd::journal::MIRROR_PEER_STATE_SYNCING ||
+ m_local_tag_data.mirror_uuid == m_state_builder->remote_mirror_uuid) {
get_remote_tag_class();
return;
}
dout(15) << dendl;
update_progress("UPDATE_CLIENT_STATE");
- librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta);
+ auto client_meta = m_state_builder->remote_client_meta;
client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
librbd::journal::ClientData client_data(client_meta);
auto ctx = create_context_callback<
PrepareReplayRequest<I>,
&PrepareReplayRequest<I>::handle_update_client_state>(this);
- m_remote_journaler->update_client(data_bl, ctx);
+ m_state_builder->remote_journaler->update_client(data_bl, ctx);
}
template <typename I>
return;
}
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ m_state_builder->remote_client_meta.state =
+ librbd::journal::MIRROR_PEER_STATE_REPLAYING;
get_remote_tag_class();
}
auto ctx = create_context_callback<
PrepareReplayRequest<I>,
&PrepareReplayRequest<I>::handle_get_remote_tag_class>(this);
- m_remote_journaler->get_client(librbd::Journal<>::IMAGE_CLIENT_ID, &m_client,
- ctx);
+ m_state_builder->remote_journaler->get_client(
+ librbd::Journal<>::IMAGE_CLIENT_ID, &m_client, ctx);
}
template <typename I>
auto ctx = create_context_callback<
PrepareReplayRequest<I>,
&PrepareReplayRequest<I>::handle_get_remote_tags>(this);
- m_remote_journaler->get_tags(m_remote_tag_class, &m_remote_tags, ctx);
+ m_state_builder->remote_journaler->get_tags(m_remote_tag_class,
+ &m_remote_tags, ctx);
}
template <typename I>
// decode the remote tags
for (auto &remote_tag : m_remote_tags) {
if (m_local_tag_data.predecessor.commit_valid &&
- m_local_tag_data.predecessor.mirror_uuid == m_remote_mirror_uuid &&
+ m_local_tag_data.predecessor.mirror_uuid ==
+ m_state_builder->remote_mirror_uuid &&
m_local_tag_data.predecessor.tag_tid > remote_tag.tid) {
dout(10) << "skipping processed predecessor remote tag "
<< remote_tag.tid << dendl;
continue;
}
- if (m_local_tag_data.predecessor.mirror_uuid == m_remote_mirror_uuid &&
+ if (m_local_tag_data.predecessor.mirror_uuid ==
+ m_state_builder->remote_mirror_uuid &&
remote_tag_data.predecessor.mirror_uuid ==
librbd::Journal<>::LOCAL_MIRROR_UUID) {
// remote demoted and local has matching event
}
if (remote_tag_data_valid &&
- m_local_tag_data.mirror_uuid == m_remote_mirror_uuid) {
+ m_local_tag_data.mirror_uuid == m_state_builder->remote_mirror_uuid) {
dout(10) << "local image is in clean replay state" << dendl;
} else if (reconnect_orphan) {
dout(10) << "remote image was demoted/promoted" << dendl;
#include "include/int_types.h"
#include "cls/journal/cls_journal_types.h"
#include "librbd/journal/Types.h"
-#include "librbd/journal/TypeTraits.h"
#include "librbd/mirror/Types.h"
#include "tools/rbd_mirror/BaseRequest.h"
#include <list>
namespace image_replayer {
namespace journal {
+template <typename> class StateBuilder;
+
template <typename ImageCtxT>
class PrepareReplayRequest : public BaseRequest {
public:
- typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
- typedef typename TypeTraits::Journaler Journaler;
- typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
-
static PrepareReplayRequest* create(
- ImageCtxT* local_image_ctx, Journaler* remote_journaler,
- librbd::mirror::PromotionState remote_promotion_state,
const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- MirrorPeerClientMeta* client_meta, ProgressContext* progress_ctx,
- bool* resync_requested, bool* syncing, Context* on_finish) {
+ librbd::mirror::PromotionState remote_promotion_state,
+ ProgressContext* progress_ctx,
+ StateBuilder<ImageCtxT>* state_builder,
+ bool* resync_requested,
+ bool* syncing,
+ Context* on_finish) {
return new PrepareReplayRequest(
- local_image_ctx, remote_journaler, remote_promotion_state,
- local_mirror_uuid, remote_mirror_uuid, client_meta, progress_ctx,
+ local_mirror_uuid, remote_promotion_state, progress_ctx, state_builder,
resync_requested, syncing, on_finish);
}
PrepareReplayRequest(
- ImageCtxT* local_image_ctx, Journaler* remote_journaler,
- librbd::mirror::PromotionState remote_promotion_state,
const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- MirrorPeerClientMeta* client_meta, ProgressContext* progress_ctx,
- bool* resync_requested, bool* syncing, Context* on_finish)
+ librbd::mirror::PromotionState remote_promotion_state,
+ ProgressContext* progress_ctx,
+ StateBuilder<ImageCtxT>* state_builder,
+ bool* resync_requested,
+ bool* syncing,
+ Context* on_finish)
: BaseRequest(on_finish),
- m_local_image_ctx(local_image_ctx), m_remote_journaler(remote_journaler),
- m_remote_promotion_state(remote_promotion_state),
m_local_mirror_uuid(local_mirror_uuid),
- m_remote_mirror_uuid(remote_mirror_uuid), m_client_meta(client_meta),
- m_progress_ctx(progress_ctx), m_resync_requested(resync_requested),
+ m_remote_promotion_state(remote_promotion_state),
+ m_progress_ctx(progress_ctx),
+ m_state_builder(state_builder),
+ m_resync_requested(resync_requested),
m_syncing(syncing) {
}
*/
typedef std::list<cls::journal::Tag> Tags;
- ImageCtxT* m_local_image_ctx;
- Journaler* m_remote_journaler;
- librbd::mirror::PromotionState m_remote_promotion_state;
std::string m_local_mirror_uuid;
- std::string m_remote_mirror_uuid;
- MirrorPeerClientMeta* m_client_meta;
+ librbd::mirror::PromotionState m_remote_promotion_state;
ProgressContext* m_progress_ctx;
+ StateBuilder<ImageCtxT>* m_state_builder;
bool* m_resync_requested;
bool* m_syncing;
#include "tools/rbd_mirror/image_replayer/Utils.h"
#include "tools/rbd_mirror/image_replayer/journal/EventPreprocessor.h"
#include "tools/rbd_mirror/image_replayer/journal/ReplayStatusFormatter.h"
+#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
template <typename I>
Replayer<I>::Replayer(
- I** local_image_ctx, Journaler* remote_journaler,
- const std::string& local_mirror_uuid, const std::string& remote_mirror_uuid,
- ReplayerListener* replayer_listener, Threads<I>* threads)
- : m_local_image_ctx(local_image_ctx),
- m_remote_journaler(remote_journaler),
+ Threads<I>* threads,
+ const std::string& local_mirror_uuid,
+ StateBuilder<I>* state_builder,
+ ReplayerListener* replayer_listener)
+ : m_threads(threads),
m_local_mirror_uuid(local_mirror_uuid),
- m_remote_mirror_uuid(remote_mirror_uuid),
+ m_state_builder(state_builder),
m_replayer_listener(replayer_listener),
- m_threads(threads),
m_lock(ceph::make_mutex(librbd::util::unique_lock_name(
"rbd::mirror::image_replayer::journal::Replayer", this))) {
dout(10) << dendl;
ceph_assert(m_replay_status_formatter == nullptr);
ceph_assert(m_delayed_preprocess_task == nullptr);
ceph_assert(m_flush_local_replay_task == nullptr);
- ceph_assert(*m_local_image_ctx == nullptr);
+ ceph_assert(m_state_builder->local_image_ctx == nullptr);
}
template <typename I>
ceph_assert(m_local_journal == nullptr);
{
- auto local_image_ctx = *m_local_image_ctx;
+ auto local_image_ctx = m_state_builder->local_image_ctx;
std::shared_lock image_locker{local_image_ctx->image_lock};
m_image_spec = util::compute_image_spec(local_image_ctx->md_ctx,
local_image_ctx->name);
if (m_local_journal == nullptr) {
std::unique_lock locker{m_lock};
m_state = STATE_COMPLETE;
- m_remote_journaler = nullptr;
+ m_state_builder->remote_journaler = nullptr;
handle_replay_complete(locker, -EINVAL, "error accessing local journal");
close_local_image();
Context *ctx = create_context_callback<
Replayer, &Replayer<I>::handle_init_remote_journaler>(this);
- m_remote_journaler->init(ctx);
+ m_state_builder->remote_journaler->init(ctx);
}
template <typename I>
// listen for metadata updates to check for disconnect events
ceph_assert(m_remote_listener == nullptr);
m_remote_listener = new RemoteJournalerListener(this);
- m_remote_journaler->add_listener(m_remote_listener);
+ m_state_builder->remote_journaler->add_listener(m_remote_listener);
cls::journal::Client remote_client;
- r = m_remote_journaler->get_cached_client(m_local_mirror_uuid,
- &remote_client);
+ r = m_state_builder->remote_journaler->get_cached_client(m_local_mirror_uuid,
+ &remote_client);
if (r < 0) {
derr << "error retrieving remote journal client: " << cpp_strerror(r)
<< dendl;
}
std::string error;
- r = validate_remote_client_state(remote_client, &m_remote_client_meta,
+ r = validate_remote_client_state(remote_client,
+ &m_state_builder->remote_client_meta,
&m_resync_requested, &error);
if (r < 0) {
handle_replay_complete(locker, r, error);
if (r < 0) {
ceph_assert(m_local_journal_replay == nullptr);
derr << "error starting external replay on local image "
- << (*m_local_image_ctx)->id << ": " << cpp_strerror(r) << dendl;
+ << m_state_builder->local_image_ctx->id << ": "
+ << cpp_strerror(r) << dendl;
handle_replay_complete(locker, r, "error starting replay on local image");
close_local_image();
// start remote journal replay
m_event_preprocessor = EventPreprocessor<I>::create(
- **m_local_image_ctx, *m_remote_journaler, m_local_mirror_uuid,
- &m_remote_client_meta, m_threads->work_queue);
+ *m_state_builder->local_image_ctx, *m_state_builder->remote_journaler,
+ m_local_mirror_uuid, &m_state_builder->remote_client_meta,
+ m_threads->work_queue);
m_replay_status_formatter = ReplayStatusFormatter<I>::create(
- m_remote_journaler, m_local_mirror_uuid);
+ m_state_builder->remote_journaler, m_local_mirror_uuid);
- auto cct = static_cast<CephContext *>((*m_local_image_ctx)->cct);
+ auto cct = static_cast<CephContext *>(m_state_builder->local_image_ctx->cct);
double poll_seconds = cct->_conf.get_val<double>(
"rbd_mirror_journal_poll_age");
m_remote_replay_handler = new RemoteReplayHandler(this);
- m_remote_journaler->start_live_replay(m_remote_replay_handler, poll_seconds);
+ m_state_builder->remote_journaler->start_live_replay(m_remote_replay_handler,
+ poll_seconds);
notify_status_updated();
}
// NOTE: it's important to ensure that the local image is fully
// closed before attempting to close the remote journal in
// case the remote cluster is unreachable
+ ceph_assert(m_state_builder->local_image_ctx != nullptr);
auto ctx = create_context_callback<
Replayer<I>, &Replayer<I>::handle_close_local_image>(this);
auto request = image_replayer::CloseImageRequest<I>::create(
- m_local_image_ctx, ctx);
+ &m_state_builder->local_image_ctx, ctx);
request->send();
}
handle_replay_error(r, "failed to close local image");
}
- ceph_assert(*m_local_image_ctx == nullptr);
+ ceph_assert(m_state_builder->local_image_ctx == nullptr);
stop_remote_journaler_replay();
}
void Replayer<I>::stop_remote_journaler_replay() {
ceph_assert(ceph_mutex_is_locked_by_me(m_lock));
- if (m_remote_journaler == nullptr) {
+ if (m_state_builder->remote_journaler == nullptr) {
wait_for_in_flight_ops();
return;
} else if (m_remote_replay_handler == nullptr) {
- shut_down_remote_journaler();
+ wait_for_in_flight_ops();
return;
}
auto ctx = create_async_context_callback(
m_threads->work_queue, create_context_callback<
Replayer<I>, &Replayer<I>::handle_stop_remote_journaler_replay>(this));
- m_remote_journaler->stop_replay(ctx);
+ m_state_builder->remote_journaler->stop_replay(ctx);
}
template <typename I>
delete m_remote_replay_handler;
m_remote_replay_handler = nullptr;
- shut_down_remote_journaler();
+ wait_for_in_flight_ops();
}
template <typename I>
-void Replayer<I>::shut_down_remote_journaler() {
- ceph_assert(ceph_mutex_is_locked_by_me(m_lock));
-
+void Replayer<I>::wait_for_in_flight_ops() {
dout(10) << dendl;
if (m_remote_listener != nullptr) {
- m_remote_journaler->remove_listener(m_remote_listener);
+ m_state_builder->remote_journaler->remove_listener(m_remote_listener);
delete m_remote_listener;
m_remote_listener = nullptr;
}
- auto ctx = create_context_callback<
- Replayer, &Replayer<I>::handle_shut_down_remote_journaler>(this);
- m_remote_journaler->shut_down(ctx);
-}
-
-template <typename I>
-void Replayer<I>::handle_shut_down_remote_journaler(int r) {
- dout(10) << "r=" << r << dendl;
- if (r < 0) {
- derr << "failed to shut down remote journaler: " << cpp_strerror(r)
- << dendl;
-
- std::unique_lock locker{m_lock};
- handle_replay_error(r, "failed to shut down remote journaler");
- }
-
- m_remote_journaler = nullptr;
-
- wait_for_in_flight_ops();
-}
-
-template <typename I>
-void Replayer<I>::wait_for_in_flight_ops() {
- dout(10) << dendl;
-
auto ctx = create_async_context_callback(
m_threads->work_queue, create_context_callback<
Replayer<I>, &Replayer<I>::handle_wait_for_in_flight_ops>(this));
}
cls::journal::Client remote_client;
- int r = m_remote_journaler->get_cached_client(m_local_mirror_uuid,
- &remote_client);
+ int r = m_state_builder->remote_journaler->get_cached_client(
+ m_local_mirror_uuid, &remote_client);
if (r < 0) {
derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
return;
[this, on_flush](int r) {
handle_flush_commit_position(on_flush, r);
});
- m_remote_journaler->flush_commit_position(ctx);
+ m_state_builder->remote_journaler->flush_commit_position(ctx);
}
template <typename I>
return;
}
- if (!m_remote_journaler->try_pop_front(&m_replay_entry, &m_replay_tag_tid)) {
+ if (!m_state_builder->remote_journaler->try_pop_front(&m_replay_entry,
+ &m_replay_tag_tid)) {
dout(20) << "no entries ready for replay" << dendl;
return;
}
Context *ctx = create_context_callback<
Replayer, &Replayer<I>::handle_get_remote_tag>(this);
- m_remote_journaler->get_tag(m_replay_tag_tid, &m_replay_tag, ctx);
+ m_state_builder->remote_journaler->get_tag(m_replay_tag_tid, &m_replay_tag,
+ ctx);
}
template <typename I>
std::string mirror_uuid = m_replay_tag_data.mirror_uuid;
if (mirror_uuid == librbd::Journal<>::LOCAL_MIRROR_UUID) {
- mirror_uuid = m_remote_mirror_uuid;
+ mirror_uuid = m_state_builder->remote_mirror_uuid;
} else if (mirror_uuid == m_local_mirror_uuid) {
mirror_uuid = librbd::Journal<>::LOCAL_MIRROR_UUID;
} else if (mirror_uuid == librbd::Journal<>::ORPHAN_MIRROR_UUID) {
librbd::journal::TagPredecessor predecessor(m_replay_tag_data.predecessor);
if (predecessor.mirror_uuid == librbd::Journal<>::LOCAL_MIRROR_UUID) {
- predecessor.mirror_uuid = m_remote_mirror_uuid;
+ predecessor.mirror_uuid = m_state_builder->remote_mirror_uuid;
} else if (predecessor.mirror_uuid == m_local_mirror_uuid) {
predecessor.mirror_uuid = librbd::Journal<>::LOCAL_MIRROR_UUID;
}
m_replay_bytes = data.length();
uint32_t delay = calculate_replay_delay(
- m_event_entry.timestamp, (*m_local_image_ctx)->mirroring_replay_delay);
+ m_event_entry.timestamp,
+ m_state_builder->local_image_ctx->mirroring_replay_delay);
if (delay == 0) {
handle_preprocess_entry_ready(0);
return;
bool update_status = false;
{
- auto local_image_ctx = *m_local_image_ctx;
+ auto local_image_ctx = m_state_builder->local_image_ctx;
std::shared_lock image_locker{local_image_ctx->image_lock};
auto image_spec = util::compute_image_spec(local_image_ctx->md_ctx,
local_image_ctx->name);
derr << "failed to commit journal event: " << cpp_strerror(r) << dendl;
handle_replay_complete(r, "failed to commit journal event");
} else {
- ceph_assert(m_remote_journaler != nullptr);
- m_remote_journaler->committed(replay_entry);
+ ceph_assert(m_state_builder->remote_journaler != nullptr);
+ m_state_builder->remote_journaler->committed(replay_entry);
}
auto latency = ceph_clock_now() - replay_start_time;
return -EBADMSG;
}
- auto local_image_ctx = *m_local_image_ctx;
+ auto local_image_ctx = m_state_builder->local_image_ctx;
dout(5) << "image_id=" << local_image_ctx->id << ", "
<< "remote_client_meta.image_id="
<< remote_client_meta->image_id << ", "
ceph_assert(ceph_mutex_is_locked_by_me(m_lock));
ceph_assert(m_perf_counters == nullptr);
- auto cct = static_cast<CephContext *>((*m_local_image_ctx)->cct);
+ auto cct = static_cast<CephContext *>(m_state_builder->local_image_ctx->cct);
auto prio = cct->_conf.get_val<int64_t>("rbd_mirror_image_perf_stats_prio");
PerfCountersBuilder plb(g_ceph_context, "rbd_mirror_image_" + m_image_spec,
l_rbd_mirror_first, l_rbd_mirror_last);
namespace journal {
-template <typename I> class EventPreprocessor;
-template <typename I> class ReplayStatusFormatter;
+template <typename> class EventPreprocessor;
+template <typename> class ReplayStatusFormatter;
+template <typename> class StateBuilder;
template <typename ImageCtxT>
class Replayer : public image_replayer::Replayer {
public:
typedef typename librbd::journal::TypeTraits<ImageCtxT>::Journaler Journaler;
- static Replayer* create(ImageCtxT** local_image_ctx,
- Journaler* remote_journaler,
- const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- ReplayerListener* replayer_listener,
- Threads<ImageCtxT>* threads) {
- return new Replayer(local_image_ctx, remote_journaler, local_mirror_uuid,
- remote_mirror_uuid, replayer_listener, threads);
+ static Replayer* create(
+ Threads<ImageCtxT>* threads,
+ const std::string& local_mirror_uuid,
+ StateBuilder<ImageCtxT>* state_builder,
+ ReplayerListener* replayer_listener) {
+ return new Replayer(threads, local_mirror_uuid, state_builder,
+ replayer_listener);
}
Replayer(
- ImageCtxT** local_image_ctx, Journaler* remote_journaler,
+ Threads<ImageCtxT>* threads,
const std::string& local_mirror_uuid,
- const std::string& remote_mirror_uuid,
- ReplayerListener* replayer_listener, Threads<ImageCtxT>* threads);
+ StateBuilder<ImageCtxT>* state_builder,
+ ReplayerListener* replayer_listener);
~Replayer();
void destroy() override {
* v (skip if not started)
* STOP_REMOTE_JOURNALER_REPLAY
* |
- * v (skip if not initialized)
- * SHUT_DOWN_REMOTE_JOURNALER
- * |
* v
* WAIT_FOR_IN_FLIGHT_OPS
* |
struct RemoteReplayHandler;
struct LocalJournalListener;
- ImageCtxT** m_local_image_ctx;
- Journaler* m_remote_journaler;
+ Threads<ImageCtxT>* m_threads;
std::string m_local_mirror_uuid;
- std::string m_remote_mirror_uuid;
+ StateBuilder<ImageCtxT>* m_state_builder;
ReplayerListener* m_replayer_listener;
- Threads<ImageCtxT>* m_threads;
mutable ceph::mutex m_lock;
ceph::ref_t<typename std::remove_pointer<decltype(ImageCtxT::journal)>::type>
m_local_journal;
RemoteJournalerListener* m_remote_listener = nullptr;
- librbd::journal::MirrorPeerClientMeta m_remote_client_meta;
librbd::journal::Replay<ImageCtxT>* m_local_journal_replay = nullptr;
EventPreprocessor<ImageCtxT>* m_event_preprocessor = nullptr;
void stop_remote_journaler_replay();
void handle_stop_remote_journaler_replay(int r);
- void shut_down_remote_journaler();
- void handle_shut_down_remote_journaler(int r);
-
void wait_for_in_flight_ops();
void handle_wait_for_in_flight_ops(int r);
ProgressContext* progress_ctx,
Context* on_finish) {
return CreateLocalImageRequest<I>::create(
- threads, local_io_ctx, remote_image_ctx, remote_journaler,
- this->global_image_id, this->remote_mirror_uuid, &remote_client_meta,
- progress_ctx, &this->local_image_id, on_finish);
+ threads, local_io_ctx, remote_image_ctx, this->global_image_id,
+ progress_ctx, this, on_finish);
}
template <typename I>
bool* syncing,
Context* on_finish) {
return PrepareReplayRequest<I>::create(
- this->local_image_ctx,
- remote_journaler,
- remote_promotion_state,
- local_mirror_uuid,
- this->remote_mirror_uuid,
- &remote_client_meta,
- progress_ctx,
- resync_requested,
- syncing,
- on_finish);
+ local_mirror_uuid, remote_promotion_state, progress_ctx, this,
+ resync_requested, syncing, on_finish);
}
template <typename I>
const std::string& local_mirror_uuid,
ReplayerListener* replayer_listener) {
return Replayer<I>::create(
- &this->local_image_ctx,
- remote_journaler,
- local_mirror_uuid,
- this->remote_mirror_uuid,
- replayer_listener,
- threads);
+ threads, local_mirror_uuid, this, replayer_listener);
}
template <typename I>
bool* syncing,
Context* on_finish) override;
- Replayer* create_replayer(
+ image_replayer::Replayer* create_replayer(
Threads<ImageCtxT>* threads,
const std::string& local_mirror_uuid,
ReplayerListener* replayer_listener) override;