1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "cls/journal/cls_journal_types.h"
5 #include "librbd/journal/Replay.h"
6 #include "librbd/journal/Types.h"
7 #include "tools/rbd_mirror/ImageReplayer.h"
8 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
9 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
10 #include "tools/rbd_mirror/image_replayer/EventPreprocessor.h"
11 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
12 #include "tools/rbd_mirror/ImageSyncThrottler.h"
13 #include "test/rbd_mirror/test_mock_fixture.h"
14 #include "test/journal/mock/MockJournaler.h"
15 #include "test/librbd/mock/MockImageCtx.h"
16 #include "test/librbd/mock/MockJournal.h"
22 struct MockTestJournal
;
24 struct MockTestImageCtx
: public MockImageCtx
{
25 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
26 : librbd::MockImageCtx(image_ctx
) {
28 MockTestJournal
*journal
= nullptr;
31 struct MockTestJournal
: public MockJournal
{
32 MOCK_METHOD2(start_external_replay
, void(journal::Replay
<MockTestImageCtx
> **,
34 MOCK_METHOD0(stop_external_replay
, void());
37 } // anonymous namespace
42 struct Replay
<MockTestImageCtx
> {
43 MOCK_METHOD2(decode
, int(bufferlist::iterator
*, EventEntry
*));
44 MOCK_METHOD3(process
, void(const EventEntry
&, Context
*, Context
*));
45 MOCK_METHOD1(flush
, void(Context
*));
46 MOCK_METHOD2(shut_down
, void(bool, Context
*));
50 struct TypeTraits
<MockTestImageCtx
> {
51 typedef ::journal::MockJournalerProxy Journaler
;
52 typedef ::journal::MockReplayEntryProxy ReplayEntry
;
55 struct MirrorPeerClientMeta
;
57 } // namespace journal
64 class ImageSync
<librbd::MockTestImageCtx
> {
66 static ImageSync
* create(librbd::MockTestImageCtx
*local_image_ctx
,
67 librbd::MockTestImageCtx
*remote_image_ctx
,
68 SafeTimer
*timer
, Mutex
*timer_lock
,
69 const std::string
&mirror_uuid
,
70 journal::MockJournaler
*journaler
,
71 librbd::journal::MirrorPeerClientMeta
*client_meta
,
72 ContextWQ
*work_queue
, Context
*on_finish
,
73 ProgressContext
*progress_ctx
= nullptr) {
74 assert(0 == "unexpected call");
82 namespace image_replayer
{
85 using ::testing::AtLeast
;
86 using ::testing::DoAll
;
87 using ::testing::InSequence
;
88 using ::testing::Invoke
;
89 using ::testing::MatcherCast
;
90 using ::testing::Return
;
91 using ::testing::SetArgPointee
;
92 using ::testing::WithArg
;
95 struct PrepareLocalImageRequest
<librbd::MockTestImageCtx
> {
96 static PrepareLocalImageRequest
* s_instance
;
97 std::string
*local_image_id
= nullptr;
98 std::string
*tag_owner
= nullptr;
99 Context
*on_finish
= nullptr;
101 static PrepareLocalImageRequest
* create(librados::IoCtx
&,
102 const std::string
&global_image_id
,
103 std::string
*local_image_id
,
104 std::string
*tag_owner
,
105 ContextWQ
*work_queue
,
106 Context
*on_finish
) {
107 assert(s_instance
!= nullptr);
108 s_instance
->local_image_id
= local_image_id
;
109 s_instance
->tag_owner
= tag_owner
;
110 s_instance
->on_finish
= on_finish
;
114 PrepareLocalImageRequest() {
118 MOCK_METHOD0(send
, void());
122 struct BootstrapRequest
<librbd::MockTestImageCtx
> {
123 static BootstrapRequest
* s_instance
;
124 librbd::MockTestImageCtx
**image_ctx
= nullptr;
125 Context
*on_finish
= nullptr;
126 bool *do_resync
= nullptr;
128 static BootstrapRequest
* create(librados::IoCtx
&local_io_ctx
,
129 librados::IoCtx
&remote_io_ctx
,
130 rbd::mirror::ImageSyncThrottlerRef
<librbd::MockTestImageCtx
> image_sync_throttler
,
131 librbd::MockTestImageCtx
**local_image_ctx
,
132 const std::string
&local_image_name
,
133 const std::string
&remote_image_id
,
134 const std::string
&global_image_id
,
135 ContextWQ
*work_queue
, SafeTimer
*timer
,
137 const std::string
&local_mirror_uuid
,
138 const std::string
&remote_mirror_uuid
,
139 ::journal::MockJournalerProxy
*journaler
,
140 librbd::journal::MirrorPeerClientMeta
*client_meta
,
143 rbd::mirror::ProgressContext
*progress_ctx
= nullptr) {
144 assert(s_instance
!= nullptr);
145 s_instance
->image_ctx
= local_image_ctx
;
146 s_instance
->on_finish
= on_finish
;
147 s_instance
->do_resync
= do_resync
;
152 assert(s_instance
== nullptr);
156 ~BootstrapRequest() {
157 assert(s_instance
== this);
158 s_instance
= nullptr;
167 MOCK_METHOD0(send
, void());
168 MOCK_METHOD0(cancel
, void());
172 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
173 static CloseImageRequest
* s_instance
;
174 librbd::MockTestImageCtx
**image_ctx
= nullptr;
175 Context
*on_finish
= nullptr;
177 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
178 Context
*on_finish
) {
179 assert(s_instance
!= nullptr);
180 s_instance
->image_ctx
= image_ctx
;
181 s_instance
->on_finish
= on_finish
;
185 CloseImageRequest() {
186 assert(s_instance
== nullptr);
190 ~CloseImageRequest() {
191 assert(s_instance
== this);
192 s_instance
= nullptr;
195 MOCK_METHOD0(send
, void());
199 struct EventPreprocessor
<librbd::MockTestImageCtx
> {
200 static EventPreprocessor
*s_instance
;
202 static EventPreprocessor
*create(librbd::MockTestImageCtx
&local_image_ctx
,
203 ::journal::MockJournalerProxy
&remote_journaler
,
204 const std::string
&local_mirror_uuid
,
205 librbd::journal::MirrorPeerClientMeta
*client_meta
,
206 ContextWQ
*work_queue
) {
207 assert(s_instance
!= nullptr);
211 static void destroy(EventPreprocessor
* processor
) {
214 EventPreprocessor() {
215 assert(s_instance
== nullptr);
219 ~EventPreprocessor() {
220 assert(s_instance
== this);
221 s_instance
= nullptr;
224 MOCK_METHOD1(is_required
, bool(const librbd::journal::EventEntry
&));
225 MOCK_METHOD2(preprocess
, void(librbd::journal::EventEntry
*, Context
*));
229 struct ReplayStatusFormatter
<librbd::MockTestImageCtx
> {
230 static ReplayStatusFormatter
* s_instance
;
232 static ReplayStatusFormatter
* create(::journal::MockJournalerProxy
*journaler
,
233 const std::string
&mirror_uuid
) {
234 assert(s_instance
!= nullptr);
238 static void destroy(ReplayStatusFormatter
* formatter
) {
241 ReplayStatusFormatter() {
242 assert(s_instance
== nullptr);
246 ~ReplayStatusFormatter() {
247 assert(s_instance
== this);
248 s_instance
= nullptr;
251 MOCK_METHOD2(get_or_send_update
, bool(std::string
*description
, Context
*on_finish
));
254 BootstrapRequest
<librbd::MockTestImageCtx
>* BootstrapRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
255 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
256 EventPreprocessor
<librbd::MockTestImageCtx
>* EventPreprocessor
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
257 PrepareLocalImageRequest
<librbd::MockTestImageCtx
>* PrepareLocalImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
258 ReplayStatusFormatter
<librbd::MockTestImageCtx
>* ReplayStatusFormatter
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
260 } // namespace image_replayer
261 } // namespace mirror
264 // template definitions
265 #include "tools/rbd_mirror/ImageReplayer.cc"
266 #include "tools/rbd_mirror/ImageSyncThrottler.cc"
271 class TestMockImageReplayer
: public TestMockFixture
{
273 typedef BootstrapRequest
<librbd::MockTestImageCtx
> MockBootstrapRequest
;
274 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
275 typedef EventPreprocessor
<librbd::MockTestImageCtx
> MockEventPreprocessor
;
276 typedef PrepareLocalImageRequest
<librbd::MockTestImageCtx
> MockPrepareLocalImageRequest
;
277 typedef ReplayStatusFormatter
<librbd::MockTestImageCtx
> MockReplayStatusFormatter
;
278 typedef librbd::journal::Replay
<librbd::MockTestImageCtx
> MockReplay
;
279 typedef ImageReplayer
<librbd::MockTestImageCtx
> MockImageReplayer
;
281 void SetUp() override
{
282 TestMockFixture::SetUp();
285 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
, m_image_size
));
286 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
, &m_remote_image_ctx
));
288 m_image_deleter
.reset(new rbd::mirror::ImageDeleter(m_threads
->work_queue
,
290 &m_threads
->timer_lock
));
291 m_image_sync_throttler
.reset(
292 new rbd::mirror::ImageSyncThrottler
<librbd::MockTestImageCtx
>());
294 m_image_replayer
= new MockImageReplayer(
295 m_threads
, m_image_deleter
, m_image_sync_throttler
,
296 rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx
)),
297 "local_mirror_uuid", m_local_io_ctx
.get_id(), "global image id");
298 m_image_replayer
->add_remote_image(
299 "remote_mirror_uuid", m_remote_image_ctx
->id
, m_remote_io_ctx
);
302 void TearDown() override
{
303 delete m_image_replayer
;
305 TestMockFixture::TearDown();
308 void create_local_image() {
310 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
311 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
314 bufferlist
encode_tag_data(const librbd::journal::TagData
&tag_data
) {
316 ::encode(tag_data
, bl
);
320 void expect_get_or_send_update(
321 MockReplayStatusFormatter
&mock_replay_status_formatter
) {
322 EXPECT_CALL(mock_replay_status_formatter
, get_or_send_update(_
, _
))
323 .WillRepeatedly(DoAll(WithArg
<1>(CompleteContext(-EEXIST
)),
327 void expect_send(MockPrepareLocalImageRequest
&mock_request
,
328 const std::string
&local_image_id
,
329 const std::string
&tag_owner
,
331 EXPECT_CALL(mock_request
, send())
332 .WillOnce(Invoke([&mock_request
, local_image_id
, tag_owner
, r
]() {
334 *mock_request
.local_image_id
= local_image_id
;
335 *mock_request
.tag_owner
= tag_owner
;
337 mock_request
.on_finish
->complete(r
);
341 void expect_send(MockBootstrapRequest
&mock_bootstrap_request
,
342 librbd::MockTestImageCtx
&mock_local_image_ctx
,
343 bool do_resync
, int r
) {
344 EXPECT_CALL(mock_bootstrap_request
, send())
345 .WillOnce(Invoke([&mock_bootstrap_request
, &mock_local_image_ctx
,
348 *mock_bootstrap_request
.image_ctx
= &mock_local_image_ctx
;
349 *mock_bootstrap_request
.do_resync
= do_resync
;
351 mock_bootstrap_request
.on_finish
->complete(r
);
355 void expect_start_external_replay(librbd::MockTestJournal
&mock_journal
,
356 MockReplay
*mock_replay
, int r
) {
357 EXPECT_CALL(mock_journal
, start_external_replay(_
, _
))
358 .WillOnce(DoAll(SetArgPointee
<0>(mock_replay
),
359 WithArg
<1>(CompleteContext(r
))));
362 void expect_init(::journal::MockJournaler
&mock_journaler
, int r
) {
363 EXPECT_CALL(mock_journaler
, init(_
))
364 .WillOnce(CompleteContext(r
));
367 void expect_get_cached_client(::journal::MockJournaler
&mock_journaler
,
369 librbd::journal::ImageClientMeta image_client_meta
;
370 image_client_meta
.tag_class
= 0;
372 librbd::journal::ClientData client_data
;
373 client_data
.client_meta
= image_client_meta
;
375 cls::journal::Client client
;
376 ::encode(client_data
, client
.data
);
378 EXPECT_CALL(mock_journaler
, get_cached_client("local_mirror_uuid", _
))
379 .WillOnce(DoAll(SetArgPointee
<1>(client
),
383 void expect_stop_replay(::journal::MockJournaler
&mock_journaler
, int r
) {
384 EXPECT_CALL(mock_journaler
, stop_replay(_
))
385 .WillOnce(CompleteContext(r
));
388 void expect_shut_down(MockReplay
&mock_replay
, bool cancel_ops
, int r
) {
389 EXPECT_CALL(mock_replay
, shut_down(cancel_ops
, _
))
390 .WillOnce(WithArg
<1>(CompleteContext(r
)));
393 void expect_shut_down(journal::MockJournaler
&mock_journaler
, int r
) {
394 EXPECT_CALL(mock_journaler
, shut_down(_
))
395 .WillOnce(CompleteContext(r
));
398 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
399 EXPECT_CALL(mock_close_image_request
, send())
400 .WillOnce(Invoke([&mock_close_image_request
, r
]() {
401 *mock_close_image_request
.image_ctx
= nullptr;
402 mock_close_image_request
.on_finish
->complete(r
);
406 void expect_get_commit_tid_in_debug(
407 ::journal::MockReplayEntry
&mock_replay_entry
) {
408 // It is used in debug messages and depends on debug level
409 EXPECT_CALL(mock_replay_entry
, get_commit_tid())
411 .WillRepeatedly(Return(0));
414 void expect_committed(::journal::MockJournaler
&mock_journaler
, int times
) {
415 EXPECT_CALL(mock_journaler
, committed(
416 MatcherCast
<const ::journal::MockReplayEntryProxy
&>(_
)))
420 void expect_try_pop_front(::journal::MockJournaler
&mock_journaler
,
421 uint64_t replay_tag_tid
, bool entries_available
) {
422 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
423 .WillOnce(DoAll(SetArgPointee
<0>(::journal::MockReplayEntryProxy()),
424 SetArgPointee
<1>(replay_tag_tid
),
425 Return(entries_available
)));
428 void expect_try_pop_front_return_no_entries(
429 ::journal::MockJournaler
&mock_journaler
, Context
*on_finish
) {
430 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
431 .WillOnce(DoAll(Invoke([on_finish
](::journal::MockReplayEntryProxy
*e
,
433 on_finish
->complete(0);
438 void expect_get_tag(::journal::MockJournaler
&mock_journaler
,
439 const cls::journal::Tag
&tag
, int r
) {
440 EXPECT_CALL(mock_journaler
, get_tag(_
, _
, _
))
441 .WillOnce(DoAll(SetArgPointee
<1>(tag
),
442 WithArg
<2>(CompleteContext(r
))));
445 void expect_allocate_tag(librbd::MockTestJournal
&mock_journal
, int r
) {
446 EXPECT_CALL(mock_journal
, allocate_tag(_
, _
, _
))
447 .WillOnce(WithArg
<2>(CompleteContext(r
)));
450 void expect_preprocess(MockEventPreprocessor
&mock_event_preprocessor
,
451 bool required
, int r
) {
452 EXPECT_CALL(mock_event_preprocessor
, is_required(_
))
453 .WillOnce(Return(required
));
455 EXPECT_CALL(mock_event_preprocessor
, preprocess(_
, _
))
456 .WillOnce(WithArg
<1>(CompleteContext(r
)));
460 void expect_process(MockReplay
&mock_replay
,
461 int on_ready_r
, int on_commit_r
) {
462 EXPECT_CALL(mock_replay
, process(_
, _
, _
))
463 .WillOnce(DoAll(WithArg
<1>(CompleteContext(on_ready_r
)),
464 WithArg
<2>(CompleteContext(on_commit_r
))));
467 librbd::ImageCtx
*m_remote_image_ctx
;
468 librbd::ImageCtx
*m_local_image_ctx
= nullptr;
469 std::shared_ptr
<rbd::mirror::ImageDeleter
> m_image_deleter
;
470 std::shared_ptr
<rbd::mirror::ImageSyncThrottler
<librbd::MockTestImageCtx
>> m_image_sync_throttler
;
471 MockImageReplayer
*m_image_replayer
;
474 TEST_F(TestMockImageReplayer
, StartStop
) {
477 create_local_image();
478 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
480 librbd::MockTestJournal mock_local_journal
;
481 mock_local_image_ctx
.journal
= &mock_local_journal
;
483 journal::MockJournaler mock_remote_journaler
;
484 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
485 MockBootstrapRequest mock_bootstrap_request
;
486 MockReplay mock_local_replay
;
487 MockEventPreprocessor mock_event_preprocessor
;
488 MockReplayStatusFormatter mock_replay_status_formatter
;
490 expect_get_or_send_update(mock_replay_status_formatter
);
493 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
494 "remote mirror uuid", 0);
495 EXPECT_CALL(mock_remote_journaler
, construct());
496 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
498 EXPECT_CALL(mock_local_journal
, add_listener(_
));
500 expect_init(mock_remote_journaler
, 0);
502 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
503 expect_get_cached_client(mock_remote_journaler
, 0);
505 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
507 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
509 C_SaferCond start_ctx
;
510 m_image_replayer
->start(&start_ctx
);
511 ASSERT_EQ(0, start_ctx
.wait());
515 MockCloseImageRequest mock_close_local_image_request
;
517 expect_stop_replay(mock_remote_journaler
, 0);
518 expect_shut_down(mock_local_replay
, true, 0);
520 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
521 EXPECT_CALL(mock_local_journal
, stop_external_replay());
523 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
524 expect_shut_down(mock_remote_journaler
, 0);
526 expect_send(mock_close_local_image_request
, 0);
528 C_SaferCond stop_ctx
;
529 m_image_replayer
->stop(&stop_ctx
);
530 ASSERT_EQ(0, stop_ctx
.wait());
533 TEST_F(TestMockImageReplayer
, LocalImagePrimary
) {
534 create_local_image();
535 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
537 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
538 MockReplayStatusFormatter mock_replay_status_formatter
;
540 expect_get_or_send_update(mock_replay_status_formatter
);
543 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
546 C_SaferCond start_ctx
;
547 m_image_replayer
->start(&start_ctx
);
548 ASSERT_EQ(0, start_ctx
.wait());
551 TEST_F(TestMockImageReplayer
, LocalImageDNE
) {
552 create_local_image();
553 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
555 journal::MockJournaler mock_remote_journaler
;
556 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
557 MockBootstrapRequest mock_bootstrap_request
;
558 MockReplayStatusFormatter mock_replay_status_formatter
;
560 expect_get_or_send_update(mock_replay_status_formatter
);
563 expect_send(mock_prepare_local_image_request
, "", "", -ENOENT
);
564 EXPECT_CALL(mock_remote_journaler
, construct());
565 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EREMOTEIO
);
567 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
568 expect_shut_down(mock_remote_journaler
, 0);
570 C_SaferCond start_ctx
;
571 m_image_replayer
->start(&start_ctx
);
572 ASSERT_EQ(0, start_ctx
.wait());
575 TEST_F(TestMockImageReplayer
, PrepareLocalImageError
) {
576 create_local_image();
577 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
579 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
580 MockReplayStatusFormatter mock_replay_status_formatter
;
582 expect_get_or_send_update(mock_replay_status_formatter
);
585 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
586 "remote mirror uuid", -EINVAL
);
588 C_SaferCond start_ctx
;
589 m_image_replayer
->start(&start_ctx
);
590 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
593 TEST_F(TestMockImageReplayer
, BootstrapError
) {
595 create_local_image();
596 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
598 journal::MockJournaler mock_remote_journaler
;
599 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
600 MockBootstrapRequest mock_bootstrap_request
;
601 MockReplayStatusFormatter mock_replay_status_formatter
;
603 expect_get_or_send_update(mock_replay_status_formatter
);
606 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
607 "remote mirror uuid", 0);
608 EXPECT_CALL(mock_remote_journaler
, construct());
609 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EINVAL
);
611 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
612 expect_shut_down(mock_remote_journaler
, 0);
614 C_SaferCond start_ctx
;
615 m_image_replayer
->start(&start_ctx
);
616 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
619 TEST_F(TestMockImageReplayer
, StartExternalReplayError
) {
622 create_local_image();
623 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
625 librbd::MockTestJournal mock_local_journal
;
626 mock_local_image_ctx
.journal
= &mock_local_journal
;
628 journal::MockJournaler mock_remote_journaler
;
629 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
630 MockBootstrapRequest mock_bootstrap_request
;
631 MockReplay mock_local_replay
;
632 MockEventPreprocessor mock_event_preprocessor
;
633 MockReplayStatusFormatter mock_replay_status_formatter
;
635 expect_get_or_send_update(mock_replay_status_formatter
);
638 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
639 "remote mirror uuid", 0);
640 EXPECT_CALL(mock_remote_journaler
, construct());
641 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
643 EXPECT_CALL(mock_local_journal
, add_listener(_
));
645 expect_init(mock_remote_journaler
, 0);
647 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
648 expect_get_cached_client(mock_remote_journaler
, 0);
650 expect_start_external_replay(mock_local_journal
, nullptr, -EINVAL
);
652 MockCloseImageRequest mock_close_local_image_request
;
654 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
656 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
657 expect_shut_down(mock_remote_journaler
, 0);
659 expect_send(mock_close_local_image_request
, 0);
661 C_SaferCond start_ctx
;
662 m_image_replayer
->start(&start_ctx
);
663 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
666 TEST_F(TestMockImageReplayer
, StopError
) {
669 create_local_image();
670 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
672 librbd::MockTestJournal mock_local_journal
;
673 mock_local_image_ctx
.journal
= &mock_local_journal
;
675 journal::MockJournaler mock_remote_journaler
;
676 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
677 MockBootstrapRequest mock_bootstrap_request
;
678 MockReplay mock_local_replay
;
679 MockEventPreprocessor mock_event_preprocessor
;
680 MockReplayStatusFormatter mock_replay_status_formatter
;
682 expect_get_or_send_update(mock_replay_status_formatter
);
685 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
686 "remote mirror uuid", 0);
687 EXPECT_CALL(mock_remote_journaler
, construct());
688 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
690 EXPECT_CALL(mock_local_journal
, add_listener(_
));
692 expect_init(mock_remote_journaler
, 0);
694 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
695 expect_get_cached_client(mock_remote_journaler
, 0);
697 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
699 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
701 C_SaferCond start_ctx
;
702 m_image_replayer
->start(&start_ctx
);
703 ASSERT_EQ(0, start_ctx
.wait());
705 // STOP (errors are ignored)
707 MockCloseImageRequest mock_close_local_image_request
;
709 expect_stop_replay(mock_remote_journaler
, -EINVAL
);
710 expect_shut_down(mock_local_replay
, true, -EINVAL
);
712 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
713 EXPECT_CALL(mock_local_journal
, stop_external_replay());
715 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
716 expect_shut_down(mock_remote_journaler
, -EINVAL
);
718 expect_send(mock_close_local_image_request
, -EINVAL
);
720 C_SaferCond stop_ctx
;
721 m_image_replayer
->stop(&stop_ctx
);
722 ASSERT_EQ(0, stop_ctx
.wait());
725 TEST_F(TestMockImageReplayer
, Replay
) {
728 create_local_image();
729 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
731 librbd::MockTestJournal mock_local_journal
;
732 mock_local_image_ctx
.journal
= &mock_local_journal
;
734 journal::MockJournaler mock_remote_journaler
;
735 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
736 MockBootstrapRequest mock_bootstrap_request
;
737 MockReplay mock_local_replay
;
738 MockEventPreprocessor mock_event_preprocessor
;
739 MockReplayStatusFormatter mock_replay_status_formatter
;
740 ::journal::MockReplayEntry mock_replay_entry
;
742 expect_get_or_send_update(mock_replay_status_formatter
);
743 expect_get_commit_tid_in_debug(mock_replay_entry
);
744 expect_committed(mock_remote_journaler
, 2);
747 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
748 "remote mirror uuid", 0);
749 EXPECT_CALL(mock_remote_journaler
, construct());
750 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
752 EXPECT_CALL(mock_local_journal
, add_listener(_
));
754 expect_init(mock_remote_journaler
, 0);
756 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
757 expect_get_cached_client(mock_remote_journaler
, 0);
759 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
761 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
763 C_SaferCond start_ctx
;
764 m_image_replayer
->start(&start_ctx
);
765 ASSERT_EQ(0, start_ctx
.wait());
769 cls::journal::Tag tag
=
770 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
771 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
774 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
777 expect_shut_down(mock_local_replay
, false, 0);
778 EXPECT_CALL(mock_local_journal
, stop_external_replay());
779 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
780 expect_get_tag(mock_remote_journaler
, tag
, 0);
781 expect_allocate_tag(mock_local_journal
, 0);
784 EXPECT_CALL(mock_replay_entry
, get_data());
785 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
786 .WillOnce(Return(0));
787 expect_preprocess(mock_event_preprocessor
, false, 0);
788 expect_process(mock_local_replay
, 0, 0);
790 // the next event with preprocess
791 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
792 EXPECT_CALL(mock_replay_entry
, get_data());
793 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
794 .WillOnce(Return(0));
795 expect_preprocess(mock_event_preprocessor
, true, 0);
796 expect_process(mock_local_replay
, 0, 0);
798 // attempt to process the next event
799 C_SaferCond replay_ctx
;
800 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
803 m_image_replayer
->handle_replay_ready();
804 ASSERT_EQ(0, replay_ctx
.wait());
808 MockCloseImageRequest mock_close_local_image_request
;
810 expect_stop_replay(mock_remote_journaler
, 0);
811 expect_shut_down(mock_local_replay
, true, 0);
813 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
814 EXPECT_CALL(mock_local_journal
, stop_external_replay());
816 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
817 expect_shut_down(mock_remote_journaler
, 0);
819 expect_send(mock_close_local_image_request
, 0);
821 C_SaferCond stop_ctx
;
822 m_image_replayer
->stop(&stop_ctx
);
823 ASSERT_EQ(0, stop_ctx
.wait());
826 TEST_F(TestMockImageReplayer
, DecodeError
) {
829 create_local_image();
830 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
832 librbd::MockTestJournal mock_local_journal
;
833 mock_local_image_ctx
.journal
= &mock_local_journal
;
835 journal::MockJournaler mock_remote_journaler
;
836 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
837 MockBootstrapRequest mock_bootstrap_request
;
838 MockReplay mock_local_replay
;
839 MockEventPreprocessor mock_event_preprocessor
;
840 MockReplayStatusFormatter mock_replay_status_formatter
;
841 ::journal::MockReplayEntry mock_replay_entry
;
843 expect_get_or_send_update(mock_replay_status_formatter
);
844 expect_get_commit_tid_in_debug(mock_replay_entry
);
847 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
848 "remote mirror uuid", 0);
849 EXPECT_CALL(mock_remote_journaler
, construct());
850 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
852 EXPECT_CALL(mock_local_journal
, add_listener(_
));
854 expect_init(mock_remote_journaler
, 0);
856 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
857 expect_get_cached_client(mock_remote_journaler
, 0);
859 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
861 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
863 C_SaferCond start_ctx
;
864 m_image_replayer
->start(&start_ctx
);
865 ASSERT_EQ(0, start_ctx
.wait());
869 cls::journal::Tag tag
=
870 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
871 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
874 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
877 expect_shut_down(mock_local_replay
, false, 0);
878 EXPECT_CALL(mock_local_journal
, stop_external_replay());
879 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
880 expect_get_tag(mock_remote_journaler
, tag
, 0);
881 expect_allocate_tag(mock_local_journal
, 0);
884 EXPECT_CALL(mock_replay_entry
, get_data());
885 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
886 .WillOnce(Return(-EINVAL
));
889 expect_stop_replay(mock_remote_journaler
, 0);
890 expect_shut_down(mock_local_replay
, true, 0);
892 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
893 EXPECT_CALL(mock_local_journal
, stop_external_replay());
895 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
896 expect_shut_down(mock_remote_journaler
, 0);
898 MockCloseImageRequest mock_close_local_image_request
;
899 C_SaferCond close_ctx
;
900 EXPECT_CALL(mock_close_local_image_request
, send())
901 .WillOnce(Invoke([&mock_close_local_image_request
, &close_ctx
]() {
902 *mock_close_local_image_request
.image_ctx
= nullptr;
903 mock_close_local_image_request
.on_finish
->complete(0);
904 close_ctx
.complete(0);
908 m_image_replayer
->handle_replay_ready();
909 ASSERT_EQ(0, close_ctx
.wait());
911 while (!m_image_replayer
->is_stopped()) {
916 TEST_F(TestMockImageReplayer
, DelayedReplay
) {
920 create_local_image();
921 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
923 librbd::MockTestJournal mock_local_journal
;
924 mock_local_image_ctx
.journal
= &mock_local_journal
;
926 journal::MockJournaler mock_remote_journaler
;
927 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
928 MockBootstrapRequest mock_bootstrap_request
;
929 MockReplay mock_local_replay
;
930 MockEventPreprocessor mock_event_preprocessor
;
931 MockReplayStatusFormatter mock_replay_status_formatter
;
932 ::journal::MockReplayEntry mock_replay_entry
;
934 expect_get_or_send_update(mock_replay_status_formatter
);
935 expect_get_commit_tid_in_debug(mock_replay_entry
);
936 expect_committed(mock_remote_journaler
, 1);
939 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
940 "remote mirror uuid", 0);
941 EXPECT_CALL(mock_remote_journaler
, construct());
942 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
944 EXPECT_CALL(mock_local_journal
, add_listener(_
));
946 expect_init(mock_remote_journaler
, 0);
948 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
949 expect_get_cached_client(mock_remote_journaler
, 0);
951 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
953 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
955 C_SaferCond start_ctx
;
956 m_image_replayer
->start(&start_ctx
);
957 ASSERT_EQ(0, start_ctx
.wait());
961 cls::journal::Tag tag
=
962 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
963 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
966 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
969 expect_shut_down(mock_local_replay
, false, 0);
970 EXPECT_CALL(mock_local_journal
, stop_external_replay());
971 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
972 expect_get_tag(mock_remote_journaler
, tag
, 0);
973 expect_allocate_tag(mock_local_journal
, 0);
975 // process with delay
976 EXPECT_CALL(mock_replay_entry
, get_data());
977 librbd::journal::EventEntry
event_entry(
978 librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
979 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
980 .WillOnce(DoAll(SetArgPointee
<1>(event_entry
),
982 expect_preprocess(mock_event_preprocessor
, false, 0);
983 expect_process(mock_local_replay
, 0, 0);
985 // attempt to process the next event
986 C_SaferCond replay_ctx
;
987 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
990 mock_local_image_ctx
.mirroring_replay_delay
= 2;
991 m_image_replayer
->handle_replay_ready();
992 ASSERT_EQ(0, replay_ctx
.wait());
994 // add a pending (delayed) entry before stop
995 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
996 EXPECT_CALL(mock_replay_entry
, get_data());
997 C_SaferCond decode_ctx
;
998 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
999 .WillOnce(DoAll(Invoke([&decode_ctx
](bufferlist::iterator
* it
,
1000 librbd::journal::EventEntry
*e
) {
1001 decode_ctx
.complete(0);
1005 mock_local_image_ctx
.mirroring_replay_delay
= 10;
1006 m_image_replayer
->handle_replay_ready();
1007 ASSERT_EQ(0, decode_ctx
.wait());
1011 MockCloseImageRequest mock_close_local_image_request
;
1013 expect_stop_replay(mock_remote_journaler
, 0);
1014 expect_shut_down(mock_local_replay
, true, 0);
1016 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1017 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1019 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1020 expect_shut_down(mock_remote_journaler
, 0);
1022 expect_send(mock_close_local_image_request
, 0);
1024 C_SaferCond stop_ctx
;
1025 m_image_replayer
->stop(&stop_ctx
);
1026 ASSERT_EQ(0, stop_ctx
.wait());
1029 } // namespace mirror