From 0f8e65f03b35e507ac9d3b16c5ae7d9119942664 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 8 Jan 2020 09:21:30 -0500 Subject: [PATCH] rbd-mirror: bootstrap and related state machines now uses StateBuilder This removes all the journal-specific variables from the image replayer and bootstrap state machines. Instead, these details are hidden behind the abstract StateBuilder class and its derived journal class. Signed-off-by: Jason Dillaman --- .../test_mock_CreateLocalImageRequest.cc | 61 +- .../journal/test_mock_PrepareReplayRequest.cc | 189 ++++-- .../journal/test_mock_Replayer.cc | 353 +++++----- .../test_mock_BootstrapRequest.cc | 623 ++++++------------ .../test_mock_PrepareLocalImageRequest.cc | 74 ++- .../test_mock_PrepareRemoteImageRequest.cc | 231 +++---- src/test/rbd_mirror/mock/MockBaseRequest.h | 26 + .../rbd_mirror/test_mock_ImageReplayer.cc | 325 +++++---- src/tools/rbd_mirror/ImageReplayer.cc | 79 +-- src/tools/rbd_mirror/ImageReplayer.h | 30 +- src/tools/rbd_mirror/InstanceReplayer.cc | 1 + .../image_replayer/BootstrapRequest.cc | 165 ++--- .../image_replayer/BootstrapRequest.h | 63 +- .../PrepareLocalImageRequest.cc | 19 +- .../image_replayer/PrepareLocalImageRequest.h | 47 +- .../PrepareRemoteImageRequest.cc | 91 ++- .../PrepareRemoteImageRequest.h | 75 +-- .../journal/CreateLocalImageRequest.cc | 55 +- .../journal/CreateLocalImageRequest.h | 47 +- .../journal/PrepareReplayRequest.cc | 58 +- .../journal/PrepareReplayRequest.h | 47 +- .../image_replayer/journal/Replayer.cc | 119 ++-- .../image_replayer/journal/Replayer.h | 39 +- .../image_replayer/journal/StateBuilder.cc | 24 +- .../image_replayer/journal/StateBuilder.h | 2 +- 25 files changed, 1319 insertions(+), 1524 deletions(-) create mode 100644 src/test/rbd_mirror/mock/MockBaseRequest.h diff --git a/src/test/rbd_mirror/image_replayer/journal/test_mock_CreateLocalImageRequest.cc b/src/test/rbd_mirror/image_replayer/journal/test_mock_CreateLocalImageRequest.cc index 5c310cd5c01..6fc7580165e 100644 --- a/src/test/rbd_mirror/image_replayer/journal/test_mock_CreateLocalImageRequest.cc +++ b/src/test/rbd_mirror/image_replayer/journal/test_mock_CreateLocalImageRequest.cc @@ -7,6 +7,7 @@ #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" @@ -90,6 +91,19 @@ struct CreateImageRequest { CreateImageRequest* CreateImageRequest::s_instance = nullptr; +namespace journal { + +template<> +struct StateBuilder { + 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 @@ -111,6 +125,7 @@ public: typedef CreateLocalImageRequest MockCreateLocalImageRequest; typedef Threads MockThreads; typedef CreateImageRequest MockCreateImageRequest; + typedef StateBuilder MockStateBuilder; void SetUp() override { TestMockFixture::SetUp(); @@ -168,15 +183,12 @@ public: 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; @@ -204,17 +216,16 @@ TEST_F(TestMockImageReplayerJournalCreateLocalImageRequest, Success) { 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) { @@ -226,11 +237,9 @@ 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()); } @@ -252,10 +261,9 @@ TEST_F(TestMockImageReplayerJournalCreateLocalImageRequest, RegisterError) { 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()); } @@ -281,10 +289,9 @@ TEST_F(TestMockImageReplayerJournalCreateLocalImageRequest, CreateImageError) { 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()); } @@ -316,10 +323,9 @@ TEST_F(TestMockImageReplayerJournalCreateLocalImageRequest, CreateImageDuplicate 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()); } @@ -348,10 +354,9 @@ TEST_F(TestMockImageReplayerJournalCreateLocalImageRequest, UpdateClientImageErr 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()); } diff --git a/src/test/rbd_mirror/image_replayer/journal/test_mock_PrepareReplayRequest.cc b/src/test/rbd_mirror/image_replayer/journal/test_mock_PrepareReplayRequest.cc index a2dbc5a69d2..9f75e69e609 100644 --- a/src/test/rbd_mirror/image_replayer/journal/test_mock_PrepareReplayRequest.cc +++ b/src/test/rbd_mirror/image_replayer/journal/test_mock_PrepareReplayRequest.cc @@ -6,6 +6,7 @@ #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" @@ -32,6 +33,35 @@ struct TypeTraits { } // namespace journal } // namespace rbd +namespace rbd { +namespace mirror { +namespace image_replayer { +namespace journal { + +template<> +struct StateBuilder { + 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" @@ -52,6 +82,7 @@ using ::testing::WithArg; class TestMockImageReplayerJournalPrepareReplayRequest : public TestMockFixture { public: typedef PrepareReplayRequest MockPrepareReplayRequest; + typedef StateBuilder MockStateBuilder; typedef std::list Tags; void SetUp() override { @@ -122,16 +153,12 @@ public: } 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); } @@ -171,13 +198,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, Success) { 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); @@ -193,13 +222,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, NoLocalJournal) { ::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()); } @@ -220,13 +251,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, ResyncRequested) { ::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); @@ -247,13 +280,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, ResyncRequestedError) { ::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()); } @@ -274,13 +309,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, UnlinkedRemoteNonPrimar ::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()); } @@ -301,13 +338,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, Syncing) { ::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); @@ -339,13 +378,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, GetRemoteTagClassError) 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()); } @@ -383,13 +424,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, GetRemoteTagsError) { 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()); } @@ -452,13 +495,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, LocalDemotedRemoteSynci 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); @@ -498,13 +543,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, UpdateClientError) { 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); @@ -529,13 +576,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, NonPrimaryRemoteNotTagO ::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()); } @@ -582,13 +631,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, RemoteDemotePromote) { 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); @@ -647,13 +698,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, MultipleRemoteDemotePro 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); @@ -700,13 +753,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, LocalDemoteRemotePromot 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); @@ -751,13 +806,15 @@ TEST_F(TestMockImageReplayerJournalPrepareReplayRequest, SplitBrainForcePromote) 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()); } diff --git a/src/test/rbd_mirror/image_replayer/journal/test_mock_Replayer.cc b/src/test/rbd_mirror/image_replayer/journal/test_mock_Replayer.cc index f8df90aac9d..de1513f192b 100644 --- a/src/test/rbd_mirror/image_replayer/journal/test_mock_Replayer.cc +++ b/src/test/rbd_mirror/image_replayer/journal/test_mock_Replayer.cc @@ -11,6 +11,7 @@ #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" @@ -209,6 +210,22 @@ struct ReplayStatusFormatter { MOCK_METHOD2(get_or_send_update, bool(std::string *description, Context *on_finish)); }; +template<> +struct StateBuilder { + 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* EventPreprocessor::s_instance = nullptr; ReplayStatusFormatter* ReplayStatusFormatter::s_instance = nullptr; @@ -241,6 +258,7 @@ public: typedef Replayer MockReplayer; typedef EventPreprocessor MockEventPreprocessor; typedef ReplayStatusFormatter MockReplayStatusFormatter; + typedef StateBuilder MockStateBuilder; typedef Threads MockThreads; typedef CloseImageRequest MockCloseImageRequest; typedef librbd::journal::Replay MockReplay; @@ -290,11 +308,6 @@ public: .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))); @@ -496,7 +509,6 @@ public: 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); @@ -515,13 +527,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitShutDown) { 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); @@ -545,22 +559,23 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitShutDown) { 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); @@ -572,20 +587,21 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitNoLocalJournal) { 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); @@ -594,25 +610,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitRemoteJournalerError) { 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); @@ -625,25 +641,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitRemoteJournalerGetClientError) 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); @@ -657,25 +673,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitLocalJournalStartExternalReplay 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); @@ -703,12 +719,10 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitIsPromoted) { 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) { @@ -718,13 +732,15 @@ 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); @@ -740,13 +756,11 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitDisconnected) { 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) { @@ -756,13 +770,15 @@ 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); @@ -778,26 +794,26 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitDisconnectedResync) { 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); @@ -826,25 +842,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitResyncRequested) { 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); @@ -874,25 +890,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, InitResyncRequestedError) { 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); @@ -919,25 +935,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, ShutDownLocalJournalReplayError) { 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); @@ -964,25 +980,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, CloseLocalImageError) { 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); @@ -1009,70 +1025,25 @@ TEST_F(TestMockImageReplayerJournalReplayer, StopRemoteJournalerError) { 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); @@ -1141,13 +1112,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, DecodeError) { 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); @@ -1208,13 +1181,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, DelayedReplay) { 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); @@ -1319,13 +1294,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayNoMemoryError) { 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); @@ -1362,13 +1339,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, LocalJournalForcePromoted) { 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); @@ -1402,13 +1381,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, LocalJournalResyncRequested) { 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); @@ -1444,16 +1425,18 @@ TEST_F(TestMockImageReplayerJournalReplayer, RemoteJournalDisconnected) { 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); @@ -1497,13 +1480,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, Flush) { 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); @@ -1540,13 +1525,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, FlushError) { 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); @@ -1582,13 +1569,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, FlushCommitPositionError) { 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); @@ -1626,14 +1615,18 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayFlushShutDownError) { 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; @@ -1652,7 +1645,6 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayFlushShutDownError) { &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()); @@ -1667,7 +1659,6 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayFlushShutDownError) { 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); @@ -1678,14 +1669,18 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayFlushStartError) { 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; @@ -1704,7 +1699,6 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayFlushStartError) { &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()); @@ -1720,7 +1714,6 @@ TEST_F(TestMockImageReplayerJournalReplayer, ReplayFlushStartError) { 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); @@ -1731,14 +1724,18 @@ TEST_F(TestMockImageReplayerJournalReplayer, GetTagError) { 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; @@ -1761,7 +1758,6 @@ TEST_F(TestMockImageReplayerJournalReplayer, GetTagError) { {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()); @@ -1784,13 +1780,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, AllocateTagDemotion) { 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); @@ -1846,16 +1844,19 @@ TEST_F(TestMockImageReplayerJournalReplayer, AllocateTagError) { 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; @@ -1903,13 +1904,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, PreprocessError) { 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); @@ -1965,13 +1968,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, ProcessError) { 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); @@ -2033,13 +2038,15 @@ TEST_F(TestMockImageReplayerJournalReplayer, ImageNameUpdated) { 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); diff --git a/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc index ee83b6a5121..9770c61378b 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc @@ -4,6 +4,7 @@ #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" @@ -13,14 +14,10 @@ #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 { @@ -34,15 +31,6 @@ struct MockTestImageCtx : public librbd::MockImageCtx { } // anonymous namespace -namespace journal { - -template <> -struct TypeTraits { - typedef ::journal::MockJournaler Journaler; -}; - -} // namespace journal - namespace mirror { template<> @@ -228,22 +216,19 @@ struct OpenLocalImageRequest { template<> struct PrepareLocalImageRequest { static PrepareLocalImageRequest* s_instance; - std::string *local_image_id = nullptr; std::string *local_image_name = nullptr; - std::string *tag_owner = nullptr; + StateBuilder** 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** 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; } @@ -258,11 +243,7 @@ struct PrepareLocalImageRequest { template<> struct PrepareRemoteImageRequest { 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** state_builder = nullptr; Context *on_finish = nullptr; static PrepareRemoteImageRequest* create(Threads *threads, @@ -270,20 +251,11 @@ struct PrepareRemoteImageRequest { 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** 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; } @@ -297,107 +269,15 @@ struct PrepareRemoteImageRequest { template<> struct StateBuilder { - virtual ~StateBuilder() {} - - void destroy_sync_point_handler() { - } - void destroy() { - } -}; - -CloseImageRequest* - CloseImageRequest::s_instance = nullptr; -OpenImageRequest* - OpenImageRequest::s_instance = nullptr; -OpenLocalImageRequest* - OpenLocalImageRequest::s_instance = nullptr; -PrepareLocalImageRequest* - PrepareLocalImageRequest::s_instance = nullptr; -PrepareRemoteImageRequest* - PrepareRemoteImageRequest::s_instance = nullptr; - -namespace journal { - -template<> -struct CreateLocalImageRequest { - static CreateLocalImageRequest* s_instance; - - librbd::journal::MirrorPeerClientMeta* client_meta = nullptr; - std::string* local_image_id; - Context *on_finish = nullptr; - - static CreateLocalImageRequest* create( - Threads* 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 { - 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 - : image_replayer::StateBuilder{ 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); @@ -411,16 +291,43 @@ struct StateBuilder 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*, + 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* - CreateLocalImageRequest::s_instance = nullptr; -PrepareReplayRequest* - PrepareReplayRequest::s_instance = nullptr; +CloseImageRequest* + CloseImageRequest::s_instance = nullptr; +OpenImageRequest* + OpenImageRequest::s_instance = nullptr; +OpenLocalImageRequest* + OpenLocalImageRequest::s_instance = nullptr; +PrepareLocalImageRequest* + PrepareLocalImageRequest::s_instance = nullptr; +PrepareRemoteImageRequest* + PrepareRemoteImageRequest::s_instance = nullptr; StateBuilder* StateBuilder::s_instance = nullptr; -} // namespace journal } // namespace image_replayer } // namespace mirror } // namespace rbd @@ -440,6 +347,7 @@ using ::testing::Return; 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); @@ -456,9 +364,7 @@ public: typedef OpenLocalImageRequest MockOpenLocalImageRequest; typedef PrepareLocalImageRequest MockPrepareLocalImageRequest; typedef PrepareRemoteImageRequest MockPrepareRemoteImageRequest; - typedef journal::CreateLocalImageRequest MockCreateLocalImageRequest; - typedef journal::PrepareReplayRequest MockPrepareReplayRequest; - typedef journal::StateBuilder MockStateBuilder; + typedef StateBuilder MockStateBuilder; typedef librbd::mirror::GetInfoRequest MockGetMirrorInfoRequest; typedef std::list Tags; @@ -474,44 +380,51 @@ public: } 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) { @@ -563,36 +476,43 @@ public: })); } - 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); })); } @@ -617,22 +537,14 @@ public: 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; }; @@ -640,23 +552,18 @@ TEST_F(TestMockImageReplayerBootstrapRequest, Success) { 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, @@ -671,14 +578,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, Success) { // 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; @@ -699,22 +605,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageError) { // 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, @@ -729,7 +630,6 @@ TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageError) { // 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, @@ -754,22 +654,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageDNE) { // 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, @@ -784,24 +679,21 @@ TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageDNE) { // 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; @@ -822,22 +714,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImagePrimary) { // 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, @@ -852,7 +739,6 @@ TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImagePrimary) { // 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, @@ -877,20 +763,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, CreateLocalImageError) { // 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, @@ -904,9 +787,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, CreateLocalImageError) { 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; @@ -927,22 +808,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayError) { // 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, @@ -957,20 +833,15 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayError) { // 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; @@ -988,22 +859,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayResyncRequested) { // 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, @@ -1018,14 +884,12 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayResyncRequested) { // 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; @@ -1047,22 +911,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplaySyncing) { // 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, @@ -1077,17 +936,15 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplaySyncing) { // 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); @@ -1110,22 +967,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayDisconnected) { // 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, @@ -1140,14 +992,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayDisconnected) { // 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; @@ -1168,22 +1019,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncError) { // 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, @@ -1198,17 +1044,15 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncError) { // 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); @@ -1231,22 +1075,17 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncCanceled) { // 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, @@ -1261,14 +1100,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncCanceled) { // 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; @@ -1285,88 +1123,22 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncCanceled) { 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, @@ -1381,14 +1153,13 @@ TEST_F(TestMockImageReplayerBootstrapRequest, CloseRemoteImageError) { // 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); diff --git a/src/test/rbd_mirror/image_replayer/test_mock_PrepareLocalImageRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_PrepareLocalImageRequest.cc index 64843155123..de3fe6cafb3 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_PrepareLocalImageRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_PrepareLocalImageRequest.cc @@ -6,6 +6,8 @@ #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" @@ -51,8 +53,36 @@ struct GetMirrorImageIdRequest { MOCK_METHOD0(send, void()); }; +template<> +struct StateBuilder { + virtual ~StateBuilder() {} +}; + GetMirrorImageIdRequest* GetMirrorImageIdRequest::s_instance = nullptr; +namespace journal { + +template<> +struct StateBuilder + : public image_replayer::StateBuilder { + 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* StateBuilder::s_instance = nullptr; + +} // namespace journal } // namespace image_replayer } // namespace mirror } // namespace rbd @@ -77,6 +107,8 @@ class TestMockImageReplayerPrepareLocalImageRequest : public TestMockFixture { public: typedef PrepareLocalImageRequest MockPrepareLocalImageRequest; typedef GetMirrorImageIdRequest MockGetMirrorImageIdRequest; + typedef StateBuilder MockStateBuilder; + typedef journal::StateBuilder MockJournalStateBuilder; void expect_get_mirror_image_id(MockGetMirrorImageIdRequest& mock_get_mirror_image_id_request, const std::string& image_id, int r) { @@ -146,23 +178,25 @@ TEST_F(TestMockImageReplayerPrepareLocalImageRequest, Success) { 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) { @@ -170,15 +204,14 @@ 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(); @@ -193,15 +226,14 @@ TEST_F(TestMockImageReplayerPrepareLocalImageRequest, DirGetNameError) { 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(); @@ -220,15 +252,14 @@ TEST_F(TestMockImageReplayerPrepareLocalImageRequest, MirrorImageError) { 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(); @@ -251,15 +282,14 @@ TEST_F(TestMockImageReplayerPrepareLocalImageRequest, TagOwnerError) { 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(); diff --git a/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc index 6755e6f05b2..dd48bef3135 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc @@ -7,6 +7,8 @@ #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" @@ -73,8 +75,43 @@ struct GetMirrorImageIdRequest { MOCK_METHOD0(send, void()); }; +template<> +struct StateBuilder { + 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* GetMirrorImageIdRequest::s_instance = nullptr; +namespace journal { + +template<> +struct StateBuilder + : public image_replayer::StateBuilder { + 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* StateBuilder::s_instance = nullptr; + +} // namespace journal } // namespace image_replayer } // namespace mirror } // namespace rbd @@ -99,6 +136,14 @@ public: typedef Threads MockThreads; typedef PrepareRemoteImageRequest MockPrepareRemoteImageRequest; typedef GetMirrorImageIdRequest MockGetMirrorImageIdRequest; + typedef StateBuilder MockStateBuilder; + typedef journal::StateBuilder 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) { @@ -122,8 +167,8 @@ public: 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; @@ -165,7 +210,7 @@ public: }; TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) { - journal::MockJournaler mock_remote_journaler; + ::journal::MockJournaler mock_remote_journaler; MockThreads mock_threads(m_threads); InSequence seq; @@ -174,8 +219,8 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) { 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()); @@ -189,35 +234,32 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) { 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; @@ -226,8 +268,11 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) { 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()); @@ -241,66 +286,57 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) { 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; @@ -308,32 +344,27 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) { 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; @@ -342,34 +373,28 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorModeError) { 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; @@ -378,8 +403,8 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) { 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()); @@ -387,33 +412,25 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) { 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; @@ -422,8 +439,11 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) { 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()); @@ -437,29 +457,20 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) { 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 diff --git a/src/test/rbd_mirror/mock/MockBaseRequest.h b/src/test/rbd_mirror/mock/MockBaseRequest.h new file mode 100644 index 00000000000..c85eab43455 --- /dev/null +++ b/src/test/rbd_mirror/mock/MockBaseRequest.h @@ -0,0 +1,26 @@ +// -*- 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 + +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 diff --git a/src/test/rbd_mirror/test_mock_ImageReplayer.cc b/src/test/rbd_mirror/test_mock_ImageReplayer.cc index fb30f3b113b..183dca020f0 100644 --- a/src/test/rbd_mirror/test_mock_ImageReplayer.cc +++ b/src/test/rbd_mirror/test_mock_ImageReplayer.cc @@ -10,13 +10,11 @@ #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" @@ -33,14 +31,6 @@ struct MockTestImageCtx : public MockImageCtx { } // anonymous namespace -namespace journal { - -template <> -struct TypeTraits { - typedef ::journal::MockJournalerProxy Journaler; -}; - -} // namespace journal } // namespace librbd namespace rbd { @@ -103,8 +93,8 @@ namespace image_replayer { template<> struct BootstrapRequest { static BootstrapRequest* s_instance; - librbd::MockTestImageCtx **image_ctx = nullptr; - std::string* local_image_id = nullptr; + + StateBuilder** state_builder = nullptr; bool *do_resync = nullptr; Context *on_finish = nullptr; @@ -117,15 +107,10 @@ struct BootstrapRequest { 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** 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; @@ -159,61 +144,9 @@ struct BootstrapRequest { MOCK_METHOD0(cancel, void()); }; -template<> -struct CloseImageRequest { - 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* BootstrapRequest::s_instance = nullptr; -CloseImageRequest* CloseImageRequest::s_instance = nullptr; - -namespace journal { - -template <> -struct Replayer : 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* 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*)); @@ -228,9 +161,30 @@ struct Replayer : public image_replayer::Replayer { MOCK_CONST_METHOD0(get_error_description, std::string()); }; -Replayer* Replayer::s_instance = nullptr; +template <> +struct StateBuilder { + 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*, + const std::string&, + ReplayerListener*)); + + StateBuilder() { + s_instance = this; + } +}; + +BootstrapRequest* BootstrapRequest::s_instance = nullptr; +StateBuilder* StateBuilder::s_instance = nullptr; -} // namespace journal } // namespace image_replayer } // namespace mirror } // namespace rbd @@ -258,8 +212,8 @@ public: typedef ImageDeleter MockImageDeleter; typedef MirrorStatusUpdater MockMirrorStatusUpdater; typedef image_replayer::BootstrapRequest MockBootstrapRequest; - typedef image_replayer::CloseImageRequest MockCloseImageRequest; - typedef image_replayer::journal::Replayer MockJournalReplayer; + typedef image_replayer::StateBuilder MockStateBuilder; + typedef image_replayer::MockReplayer MockReplayer; typedef ImageReplayer MockImageReplayer; typedef InstanceWatcher MockInstanceWatcher; @@ -320,53 +274,66 @@ public: 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() { @@ -415,21 +382,24 @@ TEST_F(TestMockImageReplayer, StartStop) { 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); @@ -440,7 +410,8 @@ TEST_F(TestMockImageReplayer, StartStop) { 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; @@ -454,19 +425,20 @@ TEST_F(TestMockImageReplayer, LocalImagePrimary) { 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); @@ -481,7 +453,6 @@ TEST_F(TestMockImageReplayer, BootstrapRemoteDeleted) { 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); @@ -493,7 +464,11 @@ TEST_F(TestMockImageReplayer, BootstrapRemoteDeleted) { 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); @@ -509,7 +484,6 @@ TEST_F(TestMockImageReplayer, BootstrapResyncRequested) { 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); @@ -521,10 +495,11 @@ TEST_F(TestMockImageReplayer, BootstrapResyncRequested) { 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); @@ -540,7 +515,6 @@ TEST_F(TestMockImageReplayer, BootstrapError) { 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); @@ -551,7 +525,9 @@ TEST_F(TestMockImageReplayer, BootstrapError) { 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); @@ -566,7 +542,6 @@ TEST_F(TestMockImageReplayer, BootstrapCancel) { 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); @@ -580,6 +555,7 @@ TEST_F(TestMockImageReplayer, BootstrapCancel) { 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(); @@ -600,21 +576,24 @@ TEST_F(TestMockImageReplayer, StopError) { 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); @@ -624,7 +603,8 @@ TEST_F(TestMockImageReplayer, StopError) { // 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; @@ -636,23 +616,28 @@ TEST_F(TestMockImageReplayer, ReplayerError) { 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); @@ -667,21 +652,24 @@ TEST_F(TestMockImageReplayer, ReplayerResync) { 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); @@ -690,12 +678,13 @@ TEST_F(TestMockImageReplayer, ReplayerResync) { 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(); @@ -706,21 +695,24 @@ TEST_F(TestMockImageReplayer, ReplayerInterrupted) { 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); @@ -729,17 +721,18 @@ TEST_F(TestMockImageReplayer, ReplayerInterrupted) { 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(); @@ -750,21 +743,24 @@ TEST_F(TestMockImageReplayer, ReplayerRenamed) { 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); @@ -773,15 +769,16 @@ TEST_F(TestMockImageReplayer, ReplayerRenamed) { 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; diff --git a/src/tools/rbd_mirror/ImageReplayer.cc b/src/tools/rbd_mirror/ImageReplayer.cc index 766191c040e..eb030c664fd 100644 --- a/src/tools/rbd_mirror/ImageReplayer.cc +++ b/src/tools/rbd_mirror/ImageReplayer.cc @@ -23,10 +23,11 @@ #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 #define dout_context g_ceph_context @@ -241,7 +242,7 @@ template ImageReplayer::~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); @@ -347,15 +348,13 @@ void ImageReplayer::bootstrap() { return; } - m_local_image_id = ""; + ceph_assert(m_state_builder == nullptr); auto ctx = create_context_callback< ImageReplayer, &ImageReplayer::handle_bootstrap>(this); auto request = image_replayer::BootstrapRequest::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; @@ -372,9 +371,6 @@ void ImageReplayer::handle_bootstrap(int r) { 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()) { @@ -409,12 +405,10 @@ template void ImageReplayer::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::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, &ImageReplayer::handle_start_replay>(this); @@ -438,8 +432,7 @@ void ImageReplayer::handle_start_replay(int r) { 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; } @@ -694,7 +687,7 @@ void ImageReplayer::set_mirror_image_status_update( 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; @@ -823,31 +816,10 @@ void ImageReplayer::shut_down(int r) { 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::create( - &m_local_image_ctx, ctx); - request->send(); + m_state_builder->close(ctx); }); } @@ -874,18 +846,19 @@ void ImageReplayer::handle_shut_down(int r) { { 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; @@ -934,6 +907,11 @@ void ImageReplayer::handle_shut_down(int r) { 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; @@ -969,12 +947,13 @@ void ImageReplayer::handle_replayer_notification() { { // 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; } } diff --git a/src/tools/rbd_mirror/ImageReplayer.h b/src/tools/rbd_mirror/ImageReplayer.h index 3ac9d16548d..9b94d3d7f37 100644 --- a/src/tools/rbd_mirror/ImageReplayer.h +++ b/src/tools/rbd_mirror/ImageReplayer.h @@ -6,13 +6,8 @@ #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" @@ -21,18 +16,8 @@ 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 { @@ -45,6 +30,7 @@ namespace image_replayer { class Replayer; template class BootstrapRequest; +template class StateBuilder; } // namespace image_replayer @@ -171,8 +157,6 @@ private: }; struct RemoteImage { - std::string mirror_uuid; - std::string image_id; librados::IoCtx io_ctx; MirrorStatusUpdater* mirror_status_updater = nullptr; @@ -184,7 +168,6 @@ private: }; struct ReplayerListener; - typedef typename librbd::journal::TypeTraits::Journaler Journaler; typedef boost::optional OptionalState; typedef boost::optional OptionalMirrorImageStatusState; @@ -213,7 +196,6 @@ private: Peers m_peers; RemoteImage m_remote_image; - std::string m_local_image_id; std::string m_local_image_name; std::string m_image_spec; @@ -231,11 +213,7 @@ private: 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* m_state_builder = nullptr; image_replayer::Replayer* m_replayer = nullptr; ReplayerListener* m_replayer_listener = nullptr; diff --git a/src/tools/rbd_mirror/InstanceReplayer.cc b/src/tools/rbd_mirror/InstanceReplayer.cc index 5e6fc66366d..ebf38eff174 100644 --- a/src/tools/rbd_mirror/InstanceReplayer.cc +++ b/src/tools/rbd_mirror/InstanceReplayer.cc @@ -6,6 +6,7 @@ #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" diff --git a/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc b/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc index 6ebff843131..9a8c0966989 100644 --- a/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc @@ -21,13 +21,12 @@ #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" @@ -55,11 +54,7 @@ BootstrapRequest::BootstrapRequest( 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** state_builder, bool* do_resync, Context* on_finish) : CancelableRequest("rbd::mirror::image_replayer::BootstrapRequest", @@ -73,11 +68,7 @@ BootstrapRequest::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))) { @@ -125,14 +116,13 @@ void BootstrapRequest::prepare_local_image() { 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::handle_prepare_local_image>(this); auto req = image_replayer::PrepareLocalImageRequest::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(); } @@ -140,6 +130,7 @@ template void BootstrapRequest::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) { @@ -164,15 +155,11 @@ void BootstrapRequest::prepare_remote_image() { dout(10) << dendl; update_progress("PREPARE_REMOTE_IMAGE"); - ceph_assert(*m_remote_journaler == nullptr); - Context *ctx = create_context_callback< BootstrapRequest, &BootstrapRequest::handle_prepare_remote_image>(this); auto req = image_replayer::PrepareRemoteImageRequest::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(); } @@ -180,22 +167,23 @@ template void BootstrapRequest::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; @@ -205,19 +193,14 @@ void BootstrapRequest::handle_prepare_remote_image(int r) { 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 void BootstrapRequest::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"); @@ -225,7 +208,7 @@ void BootstrapRequest::open_remote_image() { BootstrapRequest, &BootstrapRequest::handle_open_remote_image>( this); OpenImageRequest *request = OpenImageRequest::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(); } @@ -290,23 +273,18 @@ void BootstrapRequest::handle_get_remote_mirror_info(int r) { 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; } @@ -316,7 +294,10 @@ void BootstrapRequest::handle_get_remote_mirror_info(int r) { template void BootstrapRequest::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"); @@ -324,8 +305,8 @@ void BootstrapRequest::open_local_image() { BootstrapRequest, &BootstrapRequest::handle_open_local_image>( this); OpenLocalImageRequest *request = OpenLocalImageRequest::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(); } @@ -333,19 +314,21 @@ template void BootstrapRequest::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(); @@ -360,14 +343,12 @@ void BootstrapRequest::prepare_replay() { dout(10) << dendl; update_progress("PREPARE_REPLAY"); - // TODO support snapshot-based mirroring + ceph_assert(*m_state_builder != nullptr); auto ctx = create_context_callback< - BootstrapRequest, - &BootstrapRequest::handle_prepare_replay>(this); - auto request = journal::PrepareReplayRequest::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, &BootstrapRequest::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(); } @@ -380,13 +361,13 @@ void BootstrapRequest::handle_prepare_replay(int r) { 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; @@ -406,14 +387,13 @@ void BootstrapRequest::create_local_image() { 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, &BootstrapRequest::handle_create_local_image>(this); - auto request = journal::CreateLocalImageRequest::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(); } @@ -432,8 +412,6 @@ void BootstrapRequest::handle_create_local_image(int r) { return; } - m_client_state = cls::journal::CLIENT_STATE_CONNECTED; - open_local_image(); } @@ -452,17 +430,15 @@ void BootstrapRequest::image_sync() { dout(15) << dendl; ceph_assert(m_image_sync == nullptr); - // TODO temporary - m_state_builder = journal::StateBuilder::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, &BootstrapRequest::handle_image_sync>(this); m_image_sync = ImageSync::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(); @@ -479,12 +455,7 @@ void BootstrapRequest::handle_image_sync(int r) { 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) { @@ -499,32 +470,6 @@ void BootstrapRequest::handle_image_sync(int r) { close_remote_image(); } -template -void BootstrapRequest::close_local_image() { - dout(15) << dendl; - - update_progress("CLOSE_LOCAL_IMAGE"); - - Context *ctx = create_context_callback< - BootstrapRequest, &BootstrapRequest::handle_close_local_image>( - this); - CloseImageRequest *request = CloseImageRequest::create( - m_local_image_ctx, ctx); - request->send(); -} - -template -void BootstrapRequest::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 void BootstrapRequest::close_remote_image() { dout(15) << dendl; diff --git a/src/tools/rbd_mirror/image_replayer/BootstrapRequest.h b/src/tools/rbd_mirror/image_replayer/BootstrapRequest.h index 91093df41b5..6561495bbfa 100644 --- a/src/tools/rbd_mirror/image_replayer/BootstrapRequest.h +++ b/src/tools/rbd_mirror/image_replayer/BootstrapRequest.h @@ -7,14 +7,10 @@ #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 #include class Context; @@ -35,15 +31,11 @@ template struct Threads; namespace image_replayer { -// TODO -namespace journal { template class StateBuilder; } +template class StateBuilder; template class BootstrapRequest : public CancelableRequest { public: - typedef librbd::journal::TypeTraits TypeTraits; - typedef typename TypeTraits::Journaler Journaler; - typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta; typedef rbd::mirror::ProgressContext ProgressContext; static BootstrapRequest* create( @@ -55,17 +47,12 @@ public: 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** 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); } @@ -78,11 +65,7 @@ public: 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** state_builder, bool* do_resync, Context* on_finish); ~BootstrapRequest() override; @@ -121,17 +104,14 @@ private: * | * * * | * * * 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 < * * * * * * * * * * * * * * * * * @@ -141,8 +121,6 @@ private: * * @endverbatim */ - typedef std::list Tags; - Threads* m_threads; librados::IoCtx &m_local_io_ctx; librados::IoCtx &m_remote_io_ctx; @@ -151,11 +129,7 @@ private: 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** m_state_builder; bool *m_do_resync; mutable ceph::mutex m_lock; @@ -168,19 +142,11 @@ private: 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 *m_image_sync = nullptr; - // TODO temporary - journal::StateBuilder* m_state_builder = nullptr; - void prepare_local_image(); void handle_prepare_local_image(int r); @@ -205,9 +171,6 @@ private: 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); diff --git a/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc b/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc index 52bbeb2cc87..a5bfb5a19d1 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc @@ -11,6 +11,7 @@ #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 #define dout_context g_ceph_context @@ -41,14 +42,14 @@ void PrepareLocalImageRequest::get_local_image_id() { PrepareLocalImageRequest, &PrepareLocalImageRequest::handle_get_local_image_id>(this); auto req = GetMirrorImageIdRequest::create(m_io_ctx, m_global_image_id, - m_local_image_id, ctx); + &m_local_image_id, ctx); req->send(); } template void PrepareLocalImageRequest::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); @@ -63,7 +64,7 @@ void PrepareLocalImageRequest::get_local_image_name() { 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< @@ -99,7 +100,7 @@ void PrepareLocalImageRequest::get_mirror_image() { 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< @@ -157,14 +158,14 @@ void PrepareLocalImageRequest::get_tag_owner() { Context *ctx = create_context_callback< PrepareLocalImageRequest, &PrepareLocalImageRequest::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 void PrepareLocalImageRequest::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) @@ -173,6 +174,12 @@ void PrepareLocalImageRequest::handle_get_tag_owner(int r) { return; } + // journal-based local image exists + auto state_builder = journal::StateBuilder::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); } diff --git a/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h b/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h index f279f1867dd..05c7eb4319c 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h +++ b/src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h @@ -17,31 +17,33 @@ namespace rbd { namespace mirror { namespace image_replayer { +template class StateBuilder; + template 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** 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** 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(); @@ -72,13 +74,16 @@ private: 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** 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); diff --git a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc index 9190d092825..462f8b69740 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc @@ -14,6 +14,7 @@ #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 @@ -54,8 +55,8 @@ template void PrepareRemoteImageRequest::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; } } @@ -72,6 +73,13 @@ void PrepareRemoteImageRequest::handle_get_remote_mirror_uuid(int r) { 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(); } @@ -84,14 +92,14 @@ void PrepareRemoteImageRequest::get_remote_image_id() { &PrepareRemoteImageRequest::handle_get_remote_image_id>(this); auto req = GetMirrorImageIdRequest::create(m_remote_io_ctx, m_global_image_id, - m_remote_image_id, ctx); + &m_remote_image_id, ctx); req->send(); } template void PrepareRemoteImageRequest::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); @@ -106,7 +114,7 @@ void PrepareRemoteImageRequest::get_mirror_image() { 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, @@ -137,6 +145,14 @@ void PrepareRemoteImageRequest::handle_get_mirror_image(int r) { 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(); @@ -160,36 +176,36 @@ void PrepareRemoteImageRequest::get_client() { journal_settings.commit_interval = cct->_conf.get_val( "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, &PrepareRemoteImageRequest::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 void PrepareRemoteImageRequest::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); } } @@ -198,11 +214,12 @@ template void PrepareRemoteImageRequest::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); @@ -210,7 +227,7 @@ void PrepareRemoteImageRequest::register_client() { m_threads->work_queue, create_context_callback< PrepareRemoteImageRequest, &PrepareRemoteImageRequest::handle_register_client>(this)); - (*m_remote_journaler)->register_client(client_data_bl, ctx); + m_remote_journaler->register_client(client_data_bl, ctx); } template @@ -224,20 +241,44 @@ void PrepareRemoteImageRequest::handle_register_client(int r) { 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 +void PrepareRemoteImageRequest::finalize_journal_state_builder( + cls::journal::ClientState client_state, + const MirrorPeerClientMeta& client_meta) { + journal::StateBuilder* 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*>(*m_state_builder); + ceph_assert(state_builder != nullptr); + } else { + state_builder = journal::StateBuilder::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 void PrepareRemoteImageRequest::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); diff --git a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h index 21dc5ecac80..616c18e13be 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h +++ b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h @@ -8,6 +8,7 @@ #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 @@ -26,6 +27,8 @@ template struct Threads; namespace image_replayer { +template class StateBuilder; + template class PrepareRemoteImageRequest { public: @@ -33,50 +36,38 @@ public: typedef typename TypeTraits::Journaler Journaler; typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta; - static PrepareRemoteImageRequest *create(Threads *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 *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** 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 *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 *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** 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(); @@ -113,16 +104,16 @@ private: 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** 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(); @@ -140,6 +131,8 @@ private: 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); }; diff --git a/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.cc b/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.cc index 01d837a2829..9403108020c 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.cc @@ -9,8 +9,10 @@ #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 @@ -28,7 +30,7 @@ using librbd::util::create_context_callback; template void CreateLocalImageRequest::send() { - *m_local_image_id = ""; + m_state_builder->local_image_id = ""; unregister_client(); } @@ -40,7 +42,7 @@ void CreateLocalImageRequest::unregister_client() { auto ctx = create_context_callback< CreateLocalImageRequest, &CreateLocalImageRequest::handle_unregister_client>(this); - m_remote_journaler->unregister_client(ctx); + m_state_builder->remote_journaler->unregister_client(ctx); } template @@ -53,18 +55,20 @@ void CreateLocalImageRequest::handle_unregister_client(int r) { return; } - *m_client_meta = librbd::journal::MirrorPeerClientMeta{""}; + m_state_builder->remote_client_meta = {}; register_client(); } template void CreateLocalImageRequest::register_client() { - ceph_assert(m_local_image_id->empty()); - *m_local_image_id = librbd::util::generate_image_id(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(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}; @@ -74,7 +78,7 @@ void CreateLocalImageRequest::register_client() { auto ctx = create_context_callback< CreateLocalImageRequest, &CreateLocalImageRequest::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 @@ -88,15 +92,17 @@ void CreateLocalImageRequest::handle_register_client(int r) { 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 void CreateLocalImageRequest::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(); @@ -107,8 +113,9 @@ void CreateLocalImageRequest::create_local_image() { CreateLocalImageRequest, &CreateLocalImageRequest::handle_create_local_image>(this); auto request = CreateImageRequest::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 @@ -116,8 +123,9 @@ void CreateLocalImageRequest::handle_create_local_image(int r) { 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) { @@ -135,13 +143,15 @@ void CreateLocalImageRequest::handle_create_local_image(int r) { template void CreateLocalImageRequest::update_client_image() { - ceph_assert(m_local_image_id->empty()); - *m_local_image_id = librbd::util::generate_image_id(m_local_io_ctx); + ceph_assert(m_state_builder->local_image_id.empty()); + m_state_builder->local_image_id = + librbd::util::generate_image_id(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); @@ -151,7 +161,7 @@ void CreateLocalImageRequest::update_client_image() { auto ctx = create_context_callback< CreateLocalImageRequest, &CreateLocalImageRequest::handle_update_client_image>(this); - m_remote_journaler->update_client(data_bl, ctx); + m_state_builder->remote_journaler->update_client(data_bl, ctx); } template @@ -164,8 +174,9 @@ void CreateLocalImageRequest::handle_update_client_image(int r) { 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(); } diff --git a/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h b/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h index ee96117ea93..1ea19aca269 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h +++ b/src/tools/rbd_mirror/image_replayer/journal/CreateLocalImageRequest.h @@ -5,8 +5,6 @@ #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 @@ -22,41 +20,41 @@ template struct Threads; namespace image_replayer { namespace journal { +template class StateBuilder; + template class CreateLocalImageRequest : public BaseRequest { public: - typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta; - typedef librbd::journal::TypeTraits TypeTraits; - typedef typename TypeTraits::Journaler Journaler; typedef rbd::mirror::ProgressContext ProgressContext; static CreateLocalImageRequest* create( - Threads* threads, librados::IoCtx& local_io_ctx, - ImageCtxT* remote_image_ctx, Journaler* remote_journaler, + Threads* 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* 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* threads, librados::IoCtx& local_io_ctx, - ImageCtxT* remote_image_ctx, Journaler* remote_journaler, + Threads* 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* 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(); @@ -87,12 +85,9 @@ private: Threads* 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* m_state_builder; void unregister_client(); void handle_unregister_client(int r); diff --git a/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.cc b/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.cc index 13a4b9a1383..69631f27587 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.cc @@ -10,6 +10,7 @@ #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 @@ -30,8 +31,20 @@ void PrepareReplayRequest::send() { *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; @@ -39,7 +52,8 @@ void PrepareReplayRequest::send() { 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(); @@ -48,13 +62,13 @@ void PrepareReplayRequest::send() { 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 @@ -68,9 +82,10 @@ void PrepareReplayRequest::send() { 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); @@ -82,8 +97,9 @@ void PrepareReplayRequest::send() { template void PrepareReplayRequest::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; } @@ -94,7 +110,7 @@ void PrepareReplayRequest::update_client_state() { 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); @@ -104,7 +120,7 @@ void PrepareReplayRequest::update_client_state() { auto ctx = create_context_callback< PrepareReplayRequest, &PrepareReplayRequest::handle_update_client_state>(this); - m_remote_journaler->update_client(data_bl, ctx); + m_state_builder->remote_journaler->update_client(data_bl, ctx); } template @@ -116,7 +132,8 @@ void PrepareReplayRequest::handle_update_client_state(int r) { 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(); } @@ -128,8 +145,8 @@ void PrepareReplayRequest::get_remote_tag_class() { auto ctx = create_context_callback< PrepareReplayRequest, &PrepareReplayRequest::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 @@ -175,7 +192,8 @@ void PrepareReplayRequest::get_remote_tags() { auto ctx = create_context_callback< PrepareReplayRequest, &PrepareReplayRequest::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 @@ -200,7 +218,8 @@ void PrepareReplayRequest::handle_get_remote_tags(int r) { // 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; @@ -250,7 +269,8 @@ void PrepareReplayRequest::handle_get_remote_tags(int r) { 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 @@ -277,7 +297,7 @@ void PrepareReplayRequest::handle_get_remote_tags(int r) { } 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; diff --git a/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h b/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h index dc38f8b4cb0..4538c94a4ad 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h +++ b/src/tools/rbd_mirror/image_replayer/journal/PrepareReplayRequest.h @@ -7,7 +7,6 @@ #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 @@ -24,39 +23,38 @@ class ProgressContext; namespace image_replayer { namespace journal { +template class StateBuilder; + template class PrepareReplayRequest : public BaseRequest { public: - typedef librbd::journal::TypeTraits 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* 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* 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) { } @@ -84,13 +82,10 @@ private: */ typedef std::list 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* m_state_builder; bool* m_resync_requested; bool* m_syncing; diff --git a/src/tools/rbd_mirror/image_replayer/journal/Replayer.cc b/src/tools/rbd_mirror/image_replayer/journal/Replayer.cc index 7b58b364040..87290b05501 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/Replayer.cc +++ b/src/tools/rbd_mirror/image_replayer/journal/Replayer.cc @@ -19,6 +19,7 @@ #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 @@ -150,15 +151,14 @@ struct Replayer::LocalJournalListener template Replayer::Replayer( - I** local_image_ctx, Journaler* remote_journaler, - const std::string& local_mirror_uuid, const std::string& remote_mirror_uuid, - ReplayerListener* replayer_listener, Threads* threads) - : m_local_image_ctx(local_image_ctx), - m_remote_journaler(remote_journaler), + Threads* threads, + const std::string& local_mirror_uuid, + StateBuilder* 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; @@ -186,7 +186,7 @@ Replayer::~Replayer() { 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 @@ -195,7 +195,7 @@ void Replayer::init(Context* on_finish) { 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); @@ -208,7 +208,7 @@ void Replayer::init(Context* on_finish) { 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(); @@ -275,7 +275,7 @@ void Replayer::init_remote_journaler() { Context *ctx = create_context_callback< Replayer, &Replayer::handle_init_remote_journaler>(this); - m_remote_journaler->init(ctx); + m_state_builder->remote_journaler->init(ctx); } template @@ -293,11 +293,11 @@ void Replayer::handle_init_remote_journaler(int r) { // 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; @@ -307,7 +307,8 @@ void Replayer::handle_init_remote_journaler(int r) { } 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); @@ -335,7 +336,8 @@ void Replayer::handle_start_external_replay(int r) { 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(); @@ -375,16 +377,18 @@ void Replayer::handle_start_external_replay(int r) { // start remote journal replay m_event_preprocessor = EventPreprocessor::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::create( - m_remote_journaler, m_local_mirror_uuid); + m_state_builder->remote_journaler, m_local_mirror_uuid); - auto cct = static_cast((*m_local_image_ctx)->cct); + auto cct = static_cast(m_state_builder->local_image_ctx->cct); double poll_seconds = cct->_conf.get_val( "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(); } @@ -489,10 +493,11 @@ void Replayer::close_local_image() { // 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, &Replayer::handle_close_local_image>(this); auto request = image_replayer::CloseImageRequest::create( - m_local_image_ctx, ctx); + &m_state_builder->local_image_ctx, ctx); request->send(); } @@ -507,7 +512,7 @@ void Replayer::handle_close_local_image(int r) { 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(); } @@ -515,11 +520,11 @@ template void Replayer::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; } @@ -527,7 +532,7 @@ void Replayer::stop_remote_journaler_replay() { auto ctx = create_async_context_callback( m_threads->work_queue, create_context_callback< Replayer, &Replayer::handle_stop_remote_journaler_replay>(this)); - m_remote_journaler->stop_replay(ctx); + m_state_builder->remote_journaler->stop_replay(ctx); } template @@ -544,45 +549,18 @@ void Replayer::handle_stop_remote_journaler_replay(int r) { delete m_remote_replay_handler; m_remote_replay_handler = nullptr; - shut_down_remote_journaler(); + wait_for_in_flight_ops(); } template -void Replayer::shut_down_remote_journaler() { - ceph_assert(ceph_mutex_is_locked_by_me(m_lock)); - +void Replayer::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::handle_shut_down_remote_journaler>(this); - m_remote_journaler->shut_down(ctx); -} - -template -void Replayer::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 -void Replayer::wait_for_in_flight_ops() { - dout(10) << dendl; - auto ctx = create_async_context_callback( m_threads->work_queue, create_context_callback< Replayer, &Replayer::handle_wait_for_in_flight_ops>(this)); @@ -616,8 +594,8 @@ void Replayer::handle_remote_journal_metadata_updated() { } 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; @@ -729,7 +707,7 @@ void Replayer::flush_commit_position(Context* on_flush) { [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 @@ -807,7 +785,8 @@ void Replayer::handle_replay_ready( 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; } @@ -881,7 +860,8 @@ void Replayer::get_remote_tag() { Context *ctx = create_context_callback< Replayer, &Replayer::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 @@ -918,7 +898,7 @@ void Replayer::allocate_local_tag() { 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) { @@ -942,7 +922,7 @@ void Replayer::allocate_local_tag() { 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; } @@ -986,7 +966,8 @@ void Replayer::preprocess_entry() { 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; @@ -1076,7 +1057,7 @@ void Replayer::handle_process_entry_ready(int r) { 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); @@ -1107,8 +1088,8 @@ void Replayer::handle_process_entry_safe( 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; @@ -1191,7 +1172,7 @@ int Replayer::validate_remote_client_state( 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 << ", " @@ -1222,7 +1203,7 @@ void Replayer::register_perf_counters() { ceph_assert(ceph_mutex_is_locked_by_me(m_lock)); ceph_assert(m_perf_counters == nullptr); - auto cct = static_cast((*m_local_image_ctx)->cct); + auto cct = static_cast(m_state_builder->local_image_ctx->cct); auto prio = cct->_conf.get_val("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); diff --git a/src/tools/rbd_mirror/image_replayer/journal/Replayer.h b/src/tools/rbd_mirror/image_replayer/journal/Replayer.h index af22b145c41..90ef6102233 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/Replayer.h +++ b/src/tools/rbd_mirror/image_replayer/journal/Replayer.h @@ -36,29 +36,29 @@ struct ReplayerListener; namespace journal { -template class EventPreprocessor; -template class ReplayStatusFormatter; +template class EventPreprocessor; +template class ReplayStatusFormatter; +template class StateBuilder; template class Replayer : public image_replayer::Replayer { public: typedef typename librbd::journal::TypeTraits::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* threads) { - return new Replayer(local_image_ctx, remote_journaler, local_mirror_uuid, - remote_mirror_uuid, replayer_listener, threads); + static Replayer* create( + Threads* threads, + const std::string& local_mirror_uuid, + StateBuilder* 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* threads, const std::string& local_mirror_uuid, - const std::string& remote_mirror_uuid, - ReplayerListener* replayer_listener, Threads* threads); + StateBuilder* state_builder, + ReplayerListener* replayer_listener); ~Replayer(); void destroy() override { @@ -156,9 +156,6 @@ private: * v (skip if not started) * STOP_REMOTE_JOURNALER_REPLAY * | - * v (skip if not initialized) - * SHUT_DOWN_REMOTE_JOURNALER - * | * v * WAIT_FOR_IN_FLIGHT_OPS * | @@ -182,12 +179,10 @@ private: struct RemoteReplayHandler; struct LocalJournalListener; - ImageCtxT** m_local_image_ctx; - Journaler* m_remote_journaler; + Threads* m_threads; std::string m_local_mirror_uuid; - std::string m_remote_mirror_uuid; + StateBuilder* m_state_builder; ReplayerListener* m_replayer_listener; - Threads* m_threads; mutable ceph::mutex m_lock; @@ -202,7 +197,6 @@ private: ceph::ref_t::type> m_local_journal; RemoteJournalerListener* m_remote_listener = nullptr; - librbd::journal::MirrorPeerClientMeta m_remote_client_meta; librbd::journal::Replay* m_local_journal_replay = nullptr; EventPreprocessor* m_event_preprocessor = nullptr; @@ -259,9 +253,6 @@ private: 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); diff --git a/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc index a0f85f0a116..ed1cf6911ed 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc +++ b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc @@ -87,9 +87,8 @@ BaseRequest* StateBuilder::create_local_image_request( ProgressContext* progress_ctx, Context* on_finish) { return CreateLocalImageRequest::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 @@ -101,16 +100,8 @@ BaseRequest* StateBuilder::create_prepare_replay_request( bool* syncing, Context* on_finish) { return PrepareReplayRequest::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 @@ -119,12 +110,7 @@ image_replayer::Replayer* StateBuilder::create_replayer( const std::string& local_mirror_uuid, ReplayerListener* replayer_listener) { return Replayer::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 diff --git a/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h index 274c2acbcb8..c760a66ce26 100644 --- a/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h +++ b/src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h @@ -61,7 +61,7 @@ public: bool* syncing, Context* on_finish) override; - Replayer* create_replayer( + image_replayer::Replayer* create_replayer( Threads* threads, const std::string& local_mirror_uuid, ReplayerListener* replayer_listener) override; -- 2.39.5