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/ImageDeleter.h"
8 #include "tools/rbd_mirror/ImageReplayer.h"
9 #include "tools/rbd_mirror/InstanceWatcher.h"
10 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
11 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
12 #include "tools/rbd_mirror/image_replayer/EventPreprocessor.h"
13 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
14 #include "test/rbd_mirror/test_mock_fixture.h"
15 #include "test/journal/mock/MockJournaler.h"
16 #include "test/librbd/mock/MockImageCtx.h"
17 #include "test/librbd/mock/MockJournal.h"
23 struct MockTestJournal
;
25 struct MockTestImageCtx
: public MockImageCtx
{
26 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
27 : librbd::MockImageCtx(image_ctx
) {
29 MockTestJournal
*journal
= nullptr;
32 struct MockTestJournal
: public MockJournal
{
33 MOCK_METHOD2(start_external_replay
, void(journal::Replay
<MockTestImageCtx
> **,
35 MOCK_METHOD0(stop_external_replay
, void());
38 } // anonymous namespace
43 struct Replay
<MockTestImageCtx
> {
44 MOCK_METHOD2(decode
, int(bufferlist::iterator
*, EventEntry
*));
45 MOCK_METHOD3(process
, void(const EventEntry
&, Context
*, Context
*));
46 MOCK_METHOD1(flush
, void(Context
*));
47 MOCK_METHOD2(shut_down
, void(bool, Context
*));
51 struct TypeTraits
<MockTestImageCtx
> {
52 typedef ::journal::MockJournalerProxy Journaler
;
53 typedef ::journal::MockReplayEntryProxy ReplayEntry
;
56 struct MirrorPeerClientMeta
;
58 } // namespace journal
65 struct ImageDeleter
<librbd::MockTestImageCtx
> {
66 MOCK_METHOD4(schedule_image_delete
, void(RadosRef
, int64_t,
67 const std::string
&, bool));
71 class InstanceWatcher
<librbd::MockTestImageCtx
> {
74 namespace image_replayer
{
77 using ::testing::AtLeast
;
78 using ::testing::DoAll
;
79 using ::testing::InSequence
;
80 using ::testing::Invoke
;
81 using ::testing::MatcherCast
;
82 using ::testing::Return
;
83 using ::testing::SetArgPointee
;
84 using ::testing::WithArg
;
87 struct PrepareLocalImageRequest
<librbd::MockTestImageCtx
> {
88 static PrepareLocalImageRequest
* s_instance
;
89 std::string
*local_image_id
= nullptr;
90 std::string
*tag_owner
= nullptr;
91 Context
*on_finish
= nullptr;
93 static PrepareLocalImageRequest
* create(librados::IoCtx
&,
94 const std::string
&global_image_id
,
95 std::string
*local_image_id
,
96 std::string
*tag_owner
,
97 ContextWQ
*work_queue
,
99 assert(s_instance
!= nullptr);
100 s_instance
->local_image_id
= local_image_id
;
101 s_instance
->tag_owner
= tag_owner
;
102 s_instance
->on_finish
= on_finish
;
106 PrepareLocalImageRequest() {
110 MOCK_METHOD0(send
, void());
114 struct BootstrapRequest
<librbd::MockTestImageCtx
> {
115 static BootstrapRequest
* s_instance
;
116 librbd::MockTestImageCtx
**image_ctx
= nullptr;
117 Context
*on_finish
= nullptr;
118 bool *do_resync
= nullptr;
120 static BootstrapRequest
* create(
121 librados::IoCtx
&local_io_ctx
, librados::IoCtx
&remote_io_ctx
,
122 rbd::mirror::InstanceWatcher
<librbd::MockTestImageCtx
> *instance_watcher
,
123 librbd::MockTestImageCtx
**local_image_ctx
,
124 const std::string
&local_image_name
, const std::string
&remote_image_id
,
125 const std::string
&global_image_id
, ContextWQ
*work_queue
,
126 SafeTimer
*timer
, Mutex
*timer_lock
, const std::string
&local_mirror_uuid
,
127 const std::string
&remote_mirror_uuid
,
128 ::journal::MockJournalerProxy
*journaler
,
129 librbd::journal::MirrorPeerClientMeta
*client_meta
,
130 Context
*on_finish
, bool *do_resync
,
131 rbd::mirror::ProgressContext
*progress_ctx
= nullptr) {
132 assert(s_instance
!= nullptr);
133 s_instance
->image_ctx
= local_image_ctx
;
134 s_instance
->on_finish
= on_finish
;
135 s_instance
->do_resync
= do_resync
;
140 assert(s_instance
== nullptr);
144 ~BootstrapRequest() {
145 assert(s_instance
== this);
146 s_instance
= nullptr;
155 inline bool is_syncing() const {
159 MOCK_METHOD0(send
, void());
160 MOCK_METHOD0(cancel
, void());
164 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
165 static CloseImageRequest
* s_instance
;
166 librbd::MockTestImageCtx
**image_ctx
= nullptr;
167 Context
*on_finish
= nullptr;
169 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
170 Context
*on_finish
) {
171 assert(s_instance
!= nullptr);
172 s_instance
->image_ctx
= image_ctx
;
173 s_instance
->on_finish
= on_finish
;
177 CloseImageRequest() {
178 assert(s_instance
== nullptr);
182 ~CloseImageRequest() {
183 assert(s_instance
== this);
184 s_instance
= nullptr;
187 MOCK_METHOD0(send
, void());
191 struct EventPreprocessor
<librbd::MockTestImageCtx
> {
192 static EventPreprocessor
*s_instance
;
194 static EventPreprocessor
*create(librbd::MockTestImageCtx
&local_image_ctx
,
195 ::journal::MockJournalerProxy
&remote_journaler
,
196 const std::string
&local_mirror_uuid
,
197 librbd::journal::MirrorPeerClientMeta
*client_meta
,
198 ContextWQ
*work_queue
) {
199 assert(s_instance
!= nullptr);
203 static void destroy(EventPreprocessor
* processor
) {
206 EventPreprocessor() {
207 assert(s_instance
== nullptr);
211 ~EventPreprocessor() {
212 assert(s_instance
== this);
213 s_instance
= nullptr;
216 MOCK_METHOD1(is_required
, bool(const librbd::journal::EventEntry
&));
217 MOCK_METHOD2(preprocess
, void(librbd::journal::EventEntry
*, Context
*));
221 struct ReplayStatusFormatter
<librbd::MockTestImageCtx
> {
222 static ReplayStatusFormatter
* s_instance
;
224 static ReplayStatusFormatter
* create(::journal::MockJournalerProxy
*journaler
,
225 const std::string
&mirror_uuid
) {
226 assert(s_instance
!= nullptr);
230 static void destroy(ReplayStatusFormatter
* formatter
) {
233 ReplayStatusFormatter() {
234 assert(s_instance
== nullptr);
238 ~ReplayStatusFormatter() {
239 assert(s_instance
== this);
240 s_instance
= nullptr;
243 MOCK_METHOD2(get_or_send_update
, bool(std::string
*description
, Context
*on_finish
));
246 BootstrapRequest
<librbd::MockTestImageCtx
>* BootstrapRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
247 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
248 EventPreprocessor
<librbd::MockTestImageCtx
>* EventPreprocessor
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
249 PrepareLocalImageRequest
<librbd::MockTestImageCtx
>* PrepareLocalImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
250 ReplayStatusFormatter
<librbd::MockTestImageCtx
>* ReplayStatusFormatter
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
252 } // namespace image_replayer
253 } // namespace mirror
256 // template definitions
257 #include "tools/rbd_mirror/ImageReplayer.cc"
262 class TestMockImageReplayer
: public TestMockFixture
{
264 typedef ImageDeleter
<librbd::MockTestImageCtx
> MockImageDeleter
;
265 typedef BootstrapRequest
<librbd::MockTestImageCtx
> MockBootstrapRequest
;
266 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
267 typedef EventPreprocessor
<librbd::MockTestImageCtx
> MockEventPreprocessor
;
268 typedef PrepareLocalImageRequest
<librbd::MockTestImageCtx
> MockPrepareLocalImageRequest
;
269 typedef ReplayStatusFormatter
<librbd::MockTestImageCtx
> MockReplayStatusFormatter
;
270 typedef librbd::journal::Replay
<librbd::MockTestImageCtx
> MockReplay
;
271 typedef ImageReplayer
<librbd::MockTestImageCtx
> MockImageReplayer
;
272 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
274 void SetUp() override
{
275 TestMockFixture::SetUp();
278 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
, m_image_size
));
279 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
, &m_remote_image_ctx
));
282 void TearDown() override
{
283 delete m_image_replayer
;
285 TestMockFixture::TearDown();
288 void create_local_image() {
290 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
291 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
294 bufferlist
encode_tag_data(const librbd::journal::TagData
&tag_data
) {
296 ::encode(tag_data
, bl
);
300 void expect_get_or_send_update(
301 MockReplayStatusFormatter
&mock_replay_status_formatter
) {
302 EXPECT_CALL(mock_replay_status_formatter
, get_or_send_update(_
, _
))
303 .WillRepeatedly(DoAll(WithArg
<1>(CompleteContext(-EEXIST
)),
307 void expect_send(MockPrepareLocalImageRequest
&mock_request
,
308 const std::string
&local_image_id
,
309 const std::string
&tag_owner
,
311 EXPECT_CALL(mock_request
, send())
312 .WillOnce(Invoke([&mock_request
, local_image_id
, tag_owner
, r
]() {
314 *mock_request
.local_image_id
= local_image_id
;
315 *mock_request
.tag_owner
= tag_owner
;
317 mock_request
.on_finish
->complete(r
);
321 void expect_send(MockBootstrapRequest
&mock_bootstrap_request
,
322 librbd::MockTestImageCtx
&mock_local_image_ctx
,
323 bool do_resync
, int r
) {
324 EXPECT_CALL(mock_bootstrap_request
, send())
325 .WillOnce(Invoke([&mock_bootstrap_request
, &mock_local_image_ctx
,
328 *mock_bootstrap_request
.image_ctx
= &mock_local_image_ctx
;
329 *mock_bootstrap_request
.do_resync
= do_resync
;
331 mock_bootstrap_request
.on_finish
->complete(r
);
335 void expect_start_external_replay(librbd::MockTestJournal
&mock_journal
,
336 MockReplay
*mock_replay
, int r
) {
337 EXPECT_CALL(mock_journal
, start_external_replay(_
, _
))
338 .WillOnce(DoAll(SetArgPointee
<0>(mock_replay
),
339 WithArg
<1>(CompleteContext(r
))));
342 void expect_init(::journal::MockJournaler
&mock_journaler
, int r
) {
343 EXPECT_CALL(mock_journaler
, init(_
))
344 .WillOnce(CompleteContext(r
));
347 void expect_get_cached_client(::journal::MockJournaler
&mock_journaler
,
349 librbd::journal::ImageClientMeta image_client_meta
;
350 image_client_meta
.tag_class
= 0;
352 librbd::journal::ClientData client_data
;
353 client_data
.client_meta
= image_client_meta
;
355 cls::journal::Client client
;
356 ::encode(client_data
, client
.data
);
358 EXPECT_CALL(mock_journaler
, get_cached_client("local_mirror_uuid", _
))
359 .WillOnce(DoAll(SetArgPointee
<1>(client
),
363 void expect_stop_replay(::journal::MockJournaler
&mock_journaler
, int r
) {
364 EXPECT_CALL(mock_journaler
, stop_replay(_
))
365 .WillOnce(CompleteContext(r
));
368 void expect_flush(MockReplay
&mock_replay
, int r
) {
369 EXPECT_CALL(mock_replay
, flush(_
)).WillOnce(CompleteContext(r
));
372 void expect_shut_down(MockReplay
&mock_replay
, bool cancel_ops
, int r
) {
373 EXPECT_CALL(mock_replay
, shut_down(cancel_ops
, _
))
374 .WillOnce(WithArg
<1>(CompleteContext(r
)));
377 void expect_shut_down(journal::MockJournaler
&mock_journaler
, int r
) {
378 EXPECT_CALL(mock_journaler
, shut_down(_
))
379 .WillOnce(CompleteContext(r
));
382 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
383 EXPECT_CALL(mock_close_image_request
, send())
384 .WillOnce(Invoke([&mock_close_image_request
, r
]() {
385 *mock_close_image_request
.image_ctx
= nullptr;
386 mock_close_image_request
.on_finish
->complete(r
);
390 void expect_get_commit_tid_in_debug(
391 ::journal::MockReplayEntry
&mock_replay_entry
) {
392 // It is used in debug messages and depends on debug level
393 EXPECT_CALL(mock_replay_entry
, get_commit_tid())
395 .WillRepeatedly(Return(0));
398 void expect_committed(::journal::MockJournaler
&mock_journaler
, int times
) {
399 EXPECT_CALL(mock_journaler
, committed(
400 MatcherCast
<const ::journal::MockReplayEntryProxy
&>(_
)))
404 void expect_try_pop_front(::journal::MockJournaler
&mock_journaler
,
405 uint64_t replay_tag_tid
, bool entries_available
) {
406 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
407 .WillOnce(DoAll(SetArgPointee
<0>(::journal::MockReplayEntryProxy()),
408 SetArgPointee
<1>(replay_tag_tid
),
409 Return(entries_available
)));
412 void expect_try_pop_front_return_no_entries(
413 ::journal::MockJournaler
&mock_journaler
, Context
*on_finish
) {
414 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
415 .WillOnce(DoAll(Invoke([on_finish
](::journal::MockReplayEntryProxy
*e
,
417 on_finish
->complete(0);
422 void expect_get_tag(::journal::MockJournaler
&mock_journaler
,
423 const cls::journal::Tag
&tag
, int r
) {
424 EXPECT_CALL(mock_journaler
, get_tag(_
, _
, _
))
425 .WillOnce(DoAll(SetArgPointee
<1>(tag
),
426 WithArg
<2>(CompleteContext(r
))));
429 void expect_allocate_tag(librbd::MockTestJournal
&mock_journal
, int r
) {
430 EXPECT_CALL(mock_journal
, allocate_tag(_
, _
, _
))
431 .WillOnce(WithArg
<2>(CompleteContext(r
)));
434 void expect_preprocess(MockEventPreprocessor
&mock_event_preprocessor
,
435 bool required
, int r
) {
436 EXPECT_CALL(mock_event_preprocessor
, is_required(_
))
437 .WillOnce(Return(required
));
439 EXPECT_CALL(mock_event_preprocessor
, preprocess(_
, _
))
440 .WillOnce(WithArg
<1>(CompleteContext(r
)));
444 void expect_process(MockReplay
&mock_replay
,
445 int on_ready_r
, int on_commit_r
) {
446 EXPECT_CALL(mock_replay
, process(_
, _
, _
))
447 .WillOnce(DoAll(WithArg
<1>(CompleteContext(on_ready_r
)),
448 WithArg
<2>(CompleteContext(on_commit_r
))));
451 void create_image_replayer(MockImageDeleter
&mock_image_deleter
) {
452 m_image_replayer
= new MockImageReplayer(
453 m_threads
, &mock_image_deleter
, &m_instance_watcher
,
454 rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx
)),
455 "local_mirror_uuid", m_local_io_ctx
.get_id(), "global image id");
456 m_image_replayer
->add_remote_image(
457 "remote_mirror_uuid", m_remote_image_ctx
->id
, m_remote_io_ctx
);
460 librbd::ImageCtx
*m_remote_image_ctx
;
461 librbd::ImageCtx
*m_local_image_ctx
= nullptr;
462 MockInstanceWatcher m_instance_watcher
;
463 MockImageReplayer
*m_image_replayer
= nullptr;
466 TEST_F(TestMockImageReplayer
, StartStop
) {
469 create_local_image();
470 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
472 librbd::MockTestJournal mock_local_journal
;
473 mock_local_image_ctx
.journal
= &mock_local_journal
;
475 journal::MockJournaler mock_remote_journaler
;
476 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
477 MockBootstrapRequest mock_bootstrap_request
;
478 MockReplay mock_local_replay
;
479 MockEventPreprocessor mock_event_preprocessor
;
480 MockReplayStatusFormatter mock_replay_status_formatter
;
482 expect_get_or_send_update(mock_replay_status_formatter
);
485 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
486 "remote mirror uuid", 0);
487 EXPECT_CALL(mock_remote_journaler
, construct());
488 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
490 EXPECT_CALL(mock_local_journal
, add_listener(_
));
492 expect_init(mock_remote_journaler
, 0);
494 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
495 expect_get_cached_client(mock_remote_journaler
, 0);
497 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
499 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
501 MockImageDeleter mock_image_deleter
;
502 create_image_replayer(mock_image_deleter
);
504 C_SaferCond start_ctx
;
505 m_image_replayer
->start(&start_ctx
);
506 ASSERT_EQ(0, start_ctx
.wait());
507 ASSERT_EQ(image_replayer::HEALTH_STATE_OK
,
508 m_image_replayer
->get_health_state());
512 MockCloseImageRequest mock_close_local_image_request
;
514 expect_shut_down(mock_local_replay
, true, 0);
515 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
516 EXPECT_CALL(mock_local_journal
, stop_external_replay());
517 expect_send(mock_close_local_image_request
, 0);
519 expect_stop_replay(mock_remote_journaler
, 0);
520 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
521 expect_shut_down(mock_remote_journaler
, 0);
523 C_SaferCond stop_ctx
;
524 m_image_replayer
->stop(&stop_ctx
);
525 ASSERT_EQ(0, stop_ctx
.wait());
526 ASSERT_EQ(image_replayer::HEALTH_STATE_OK
,
527 m_image_replayer
->get_health_state());
530 TEST_F(TestMockImageReplayer
, LocalImagePrimary
) {
531 create_local_image();
532 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
534 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
535 MockReplayStatusFormatter mock_replay_status_formatter
;
537 expect_get_or_send_update(mock_replay_status_formatter
);
540 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
543 MockImageDeleter mock_image_deleter
;
544 create_image_replayer(mock_image_deleter
);
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 MockImageDeleter mock_image_deleter
;
571 create_image_replayer(mock_image_deleter
);
573 C_SaferCond start_ctx
;
574 m_image_replayer
->start(&start_ctx
);
575 ASSERT_EQ(-EREMOTEIO
, start_ctx
.wait());
578 TEST_F(TestMockImageReplayer
, PrepareLocalImageError
) {
579 create_local_image();
580 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
582 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
583 MockReplayStatusFormatter mock_replay_status_formatter
;
585 expect_get_or_send_update(mock_replay_status_formatter
);
588 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
589 "remote mirror uuid", -EINVAL
);
591 MockImageDeleter mock_image_deleter
;
592 create_image_replayer(mock_image_deleter
);
594 C_SaferCond start_ctx
;
595 m_image_replayer
->start(&start_ctx
);
596 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
599 TEST_F(TestMockImageReplayer
, BootstrapError
) {
601 create_local_image();
602 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
604 journal::MockJournaler mock_remote_journaler
;
605 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
606 MockBootstrapRequest mock_bootstrap_request
;
607 MockReplayStatusFormatter mock_replay_status_formatter
;
609 expect_get_or_send_update(mock_replay_status_formatter
);
612 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
613 "remote mirror uuid", 0);
614 EXPECT_CALL(mock_remote_journaler
, construct());
615 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EINVAL
);
617 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
618 expect_shut_down(mock_remote_journaler
, 0);
620 MockImageDeleter mock_image_deleter
;
621 create_image_replayer(mock_image_deleter
);
623 C_SaferCond start_ctx
;
624 m_image_replayer
->start(&start_ctx
);
625 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
628 TEST_F(TestMockImageReplayer
, StartExternalReplayError
) {
631 create_local_image();
632 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
634 librbd::MockTestJournal mock_local_journal
;
635 mock_local_image_ctx
.journal
= &mock_local_journal
;
637 journal::MockJournaler mock_remote_journaler
;
638 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
639 MockBootstrapRequest mock_bootstrap_request
;
640 MockReplay mock_local_replay
;
641 MockEventPreprocessor mock_event_preprocessor
;
642 MockReplayStatusFormatter mock_replay_status_formatter
;
644 expect_get_or_send_update(mock_replay_status_formatter
);
647 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
648 "remote mirror uuid", 0);
649 EXPECT_CALL(mock_remote_journaler
, construct());
650 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
652 EXPECT_CALL(mock_local_journal
, add_listener(_
));
654 expect_init(mock_remote_journaler
, 0);
656 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
657 expect_get_cached_client(mock_remote_journaler
, 0);
659 expect_start_external_replay(mock_local_journal
, nullptr, -EINVAL
);
661 MockCloseImageRequest mock_close_local_image_request
;
662 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
663 expect_send(mock_close_local_image_request
, 0);
665 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
666 expect_shut_down(mock_remote_journaler
, 0);
668 MockImageDeleter mock_image_deleter
;
669 create_image_replayer(mock_image_deleter
);
671 C_SaferCond start_ctx
;
672 m_image_replayer
->start(&start_ctx
);
673 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
674 ASSERT_EQ(image_replayer::HEALTH_STATE_ERROR
,
675 m_image_replayer
->get_health_state());
678 TEST_F(TestMockImageReplayer
, StopError
) {
681 create_local_image();
682 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
684 librbd::MockTestJournal mock_local_journal
;
685 mock_local_image_ctx
.journal
= &mock_local_journal
;
687 journal::MockJournaler mock_remote_journaler
;
688 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
689 MockBootstrapRequest mock_bootstrap_request
;
690 MockReplay mock_local_replay
;
691 MockEventPreprocessor mock_event_preprocessor
;
692 MockReplayStatusFormatter mock_replay_status_formatter
;
694 expect_get_or_send_update(mock_replay_status_formatter
);
697 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
698 "remote mirror uuid", 0);
699 EXPECT_CALL(mock_remote_journaler
, construct());
700 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
702 EXPECT_CALL(mock_local_journal
, add_listener(_
));
704 expect_init(mock_remote_journaler
, 0);
706 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
707 expect_get_cached_client(mock_remote_journaler
, 0);
709 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
711 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
713 MockImageDeleter mock_image_deleter
;
714 create_image_replayer(mock_image_deleter
);
716 C_SaferCond start_ctx
;
717 m_image_replayer
->start(&start_ctx
);
718 ASSERT_EQ(0, start_ctx
.wait());
720 // STOP (errors are ignored)
722 MockCloseImageRequest mock_close_local_image_request
;
724 expect_shut_down(mock_local_replay
, true, -EINVAL
);
725 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
726 EXPECT_CALL(mock_local_journal
, stop_external_replay());
727 expect_send(mock_close_local_image_request
, -EINVAL
);
729 expect_stop_replay(mock_remote_journaler
, -EINVAL
);
730 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
731 expect_shut_down(mock_remote_journaler
, -EINVAL
);
733 C_SaferCond stop_ctx
;
734 m_image_replayer
->stop(&stop_ctx
);
735 ASSERT_EQ(0, stop_ctx
.wait());
738 TEST_F(TestMockImageReplayer
, Replay
) {
741 create_local_image();
742 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
744 librbd::MockTestJournal mock_local_journal
;
745 mock_local_image_ctx
.journal
= &mock_local_journal
;
747 journal::MockJournaler mock_remote_journaler
;
748 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
749 MockBootstrapRequest mock_bootstrap_request
;
750 MockReplay mock_local_replay
;
751 MockEventPreprocessor mock_event_preprocessor
;
752 MockReplayStatusFormatter mock_replay_status_formatter
;
753 ::journal::MockReplayEntry mock_replay_entry
;
755 expect_get_or_send_update(mock_replay_status_formatter
);
756 expect_get_commit_tid_in_debug(mock_replay_entry
);
757 expect_committed(mock_remote_journaler
, 2);
760 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
761 "remote mirror uuid", 0);
762 EXPECT_CALL(mock_remote_journaler
, construct());
763 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
765 EXPECT_CALL(mock_local_journal
, add_listener(_
));
767 expect_init(mock_remote_journaler
, 0);
769 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
770 expect_get_cached_client(mock_remote_journaler
, 0);
772 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
774 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
776 MockImageDeleter mock_image_deleter
;
777 create_image_replayer(mock_image_deleter
);
779 C_SaferCond start_ctx
;
780 m_image_replayer
->start(&start_ctx
);
781 ASSERT_EQ(0, start_ctx
.wait());
785 cls::journal::Tag tag
=
786 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
787 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
790 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
793 expect_shut_down(mock_local_replay
, false, 0);
794 EXPECT_CALL(mock_local_journal
, stop_external_replay());
795 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
796 expect_get_tag(mock_remote_journaler
, tag
, 0);
797 expect_allocate_tag(mock_local_journal
, 0);
800 EXPECT_CALL(mock_replay_entry
, get_data());
801 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
802 .WillOnce(Return(0));
803 expect_preprocess(mock_event_preprocessor
, false, 0);
804 expect_process(mock_local_replay
, 0, 0);
806 // the next event with preprocess
807 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
808 EXPECT_CALL(mock_replay_entry
, get_data());
809 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
810 .WillOnce(Return(0));
811 expect_preprocess(mock_event_preprocessor
, true, 0);
812 expect_process(mock_local_replay
, 0, 0);
814 // attempt to process the next event
815 C_SaferCond replay_ctx
;
816 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
819 m_image_replayer
->handle_replay_ready();
820 ASSERT_EQ(0, replay_ctx
.wait());
824 MockCloseImageRequest mock_close_local_image_request
;
825 expect_shut_down(mock_local_replay
, true, 0);
826 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
827 EXPECT_CALL(mock_local_journal
, stop_external_replay());
828 expect_send(mock_close_local_image_request
, 0);
830 expect_stop_replay(mock_remote_journaler
, 0);
831 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
832 expect_shut_down(mock_remote_journaler
, 0);
834 C_SaferCond stop_ctx
;
835 m_image_replayer
->stop(&stop_ctx
);
836 ASSERT_EQ(0, stop_ctx
.wait());
839 TEST_F(TestMockImageReplayer
, DecodeError
) {
842 create_local_image();
843 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
845 librbd::MockTestJournal mock_local_journal
;
846 mock_local_image_ctx
.journal
= &mock_local_journal
;
848 journal::MockJournaler mock_remote_journaler
;
849 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
850 MockBootstrapRequest mock_bootstrap_request
;
851 MockReplay mock_local_replay
;
852 MockEventPreprocessor mock_event_preprocessor
;
853 MockReplayStatusFormatter mock_replay_status_formatter
;
854 ::journal::MockReplayEntry mock_replay_entry
;
856 expect_get_or_send_update(mock_replay_status_formatter
);
857 expect_get_commit_tid_in_debug(mock_replay_entry
);
860 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
861 "remote mirror uuid", 0);
862 EXPECT_CALL(mock_remote_journaler
, construct());
863 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
865 EXPECT_CALL(mock_local_journal
, add_listener(_
));
867 expect_init(mock_remote_journaler
, 0);
869 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
870 expect_get_cached_client(mock_remote_journaler
, 0);
872 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
874 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
876 MockImageDeleter mock_image_deleter
;
877 create_image_replayer(mock_image_deleter
);
879 C_SaferCond start_ctx
;
880 m_image_replayer
->start(&start_ctx
);
881 ASSERT_EQ(0, start_ctx
.wait());
885 cls::journal::Tag tag
=
886 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
887 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
890 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
893 expect_shut_down(mock_local_replay
, false, 0);
894 EXPECT_CALL(mock_local_journal
, stop_external_replay());
895 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
896 expect_get_tag(mock_remote_journaler
, tag
, 0);
897 expect_allocate_tag(mock_local_journal
, 0);
900 EXPECT_CALL(mock_replay_entry
, get_data());
901 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
902 .WillOnce(Return(-EINVAL
));
905 expect_shut_down(mock_local_replay
, true, 0);
906 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
907 EXPECT_CALL(mock_local_journal
, stop_external_replay());
909 MockCloseImageRequest mock_close_local_image_request
;
910 C_SaferCond close_ctx
;
911 EXPECT_CALL(mock_close_local_image_request
, send())
912 .WillOnce(Invoke([&mock_close_local_image_request
, &close_ctx
]() {
913 *mock_close_local_image_request
.image_ctx
= nullptr;
914 mock_close_local_image_request
.on_finish
->complete(0);
915 close_ctx
.complete(0);
918 expect_stop_replay(mock_remote_journaler
, 0);
919 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
920 expect_shut_down(mock_remote_journaler
, 0);
923 m_image_replayer
->handle_replay_ready();
924 ASSERT_EQ(0, close_ctx
.wait());
926 while (!m_image_replayer
->is_stopped()) {
931 TEST_F(TestMockImageReplayer
, DelayedReplay
) {
935 create_local_image();
936 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
938 librbd::MockTestJournal mock_local_journal
;
939 mock_local_image_ctx
.journal
= &mock_local_journal
;
941 journal::MockJournaler mock_remote_journaler
;
942 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
943 MockBootstrapRequest mock_bootstrap_request
;
944 MockReplay mock_local_replay
;
945 MockEventPreprocessor mock_event_preprocessor
;
946 MockReplayStatusFormatter mock_replay_status_formatter
;
947 ::journal::MockReplayEntry mock_replay_entry
;
949 expect_get_or_send_update(mock_replay_status_formatter
);
950 expect_get_commit_tid_in_debug(mock_replay_entry
);
951 expect_committed(mock_remote_journaler
, 1);
954 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
955 "remote mirror uuid", 0);
956 EXPECT_CALL(mock_remote_journaler
, construct());
957 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
959 EXPECT_CALL(mock_local_journal
, add_listener(_
));
961 expect_init(mock_remote_journaler
, 0);
963 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
964 expect_get_cached_client(mock_remote_journaler
, 0);
966 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
968 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
970 MockImageDeleter mock_image_deleter
;
971 create_image_replayer(mock_image_deleter
);
973 C_SaferCond start_ctx
;
974 m_image_replayer
->start(&start_ctx
);
975 ASSERT_EQ(0, start_ctx
.wait());
979 cls::journal::Tag tag
=
980 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
981 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
984 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
987 expect_shut_down(mock_local_replay
, false, 0);
988 EXPECT_CALL(mock_local_journal
, stop_external_replay());
989 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
990 expect_get_tag(mock_remote_journaler
, tag
, 0);
991 expect_allocate_tag(mock_local_journal
, 0);
993 // process with delay
994 EXPECT_CALL(mock_replay_entry
, get_data());
995 librbd::journal::EventEntry
event_entry(
996 librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
997 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
998 .WillOnce(DoAll(SetArgPointee
<1>(event_entry
),
1000 expect_preprocess(mock_event_preprocessor
, false, 0);
1001 expect_process(mock_local_replay
, 0, 0);
1003 // attempt to process the next event
1004 C_SaferCond replay_ctx
;
1005 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1008 mock_local_image_ctx
.mirroring_replay_delay
= 2;
1009 m_image_replayer
->handle_replay_ready();
1010 ASSERT_EQ(0, replay_ctx
.wait());
1012 // add a pending (delayed) entry before stop
1013 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1014 EXPECT_CALL(mock_replay_entry
, get_data());
1015 C_SaferCond decode_ctx
;
1016 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1017 .WillOnce(DoAll(Invoke([&decode_ctx
](bufferlist::iterator
* it
,
1018 librbd::journal::EventEntry
*e
) {
1019 decode_ctx
.complete(0);
1023 mock_local_image_ctx
.mirroring_replay_delay
= 10;
1024 m_image_replayer
->handle_replay_ready();
1025 ASSERT_EQ(0, decode_ctx
.wait());
1029 MockCloseImageRequest mock_close_local_image_request
;
1031 expect_shut_down(mock_local_replay
, true, 0);
1032 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1033 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1034 expect_send(mock_close_local_image_request
, 0);
1036 expect_stop_replay(mock_remote_journaler
, 0);
1037 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1038 expect_shut_down(mock_remote_journaler
, 0);
1040 C_SaferCond stop_ctx
;
1041 m_image_replayer
->stop(&stop_ctx
);
1042 ASSERT_EQ(0, stop_ctx
.wait());
1045 } // namespace mirror