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/Threads.h"
11 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
12 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
13 #include "tools/rbd_mirror/image_replayer/EventPreprocessor.h"
14 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
15 #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
16 #include "test/rbd_mirror/test_mock_fixture.h"
17 #include "test/journal/mock/MockJournaler.h"
18 #include "test/librbd/mock/MockImageCtx.h"
19 #include "test/librbd/mock/MockJournal.h"
20 #include "test/rbd_mirror/mock/MockContextWQ.h"
21 #include "test/rbd_mirror/mock/MockSafeTimer.h"
27 struct MockTestJournal
;
29 struct MockTestImageCtx
: public MockImageCtx
{
30 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
31 : librbd::MockImageCtx(image_ctx
) {
33 MockTestJournal
*journal
= nullptr;
36 struct MockTestJournal
: public MockJournal
{
37 MOCK_METHOD2(start_external_replay
, void(journal::Replay
<MockTestImageCtx
> **,
39 MOCK_METHOD0(stop_external_replay
, void());
42 } // anonymous namespace
47 struct Replay
<MockTestImageCtx
> {
48 MOCK_METHOD2(decode
, int(bufferlist::iterator
*, EventEntry
*));
49 MOCK_METHOD3(process
, void(const EventEntry
&, Context
*, Context
*));
50 MOCK_METHOD1(flush
, void(Context
*));
51 MOCK_METHOD2(shut_down
, void(bool, Context
*));
55 struct TypeTraits
<MockTestImageCtx
> {
56 typedef ::journal::MockJournalerProxy Journaler
;
57 typedef ::journal::MockReplayEntryProxy ReplayEntry
;
60 struct MirrorPeerClientMeta
;
62 } // namespace journal
69 struct Threads
<librbd::MockTestImageCtx
> {
73 MockContextWQ
*work_queue
;
75 Threads(Threads
<librbd::ImageCtx
> *threads
)
76 : timer(new MockSafeTimer()),
77 timer_lock(threads
->timer_lock
),
78 work_queue(new MockContextWQ()) {
87 struct ImageDeleter
<librbd::MockTestImageCtx
> {
88 MOCK_METHOD4(schedule_image_delete
, void(RadosRef
, int64_t,
89 const std::string
&, bool));
90 MOCK_METHOD4(wait_for_scheduled_deletion
,
91 void(int64_t, const std::string
&, Context
*, bool));
92 MOCK_METHOD2(cancel_waiter
, void(int64_t, const std::string
&));
96 class InstanceWatcher
<librbd::MockTestImageCtx
> {
99 namespace image_replayer
{
102 using ::testing::AtLeast
;
103 using ::testing::DoAll
;
104 using ::testing::InSequence
;
105 using ::testing::Invoke
;
106 using ::testing::MatcherCast
;
107 using ::testing::Return
;
108 using ::testing::ReturnArg
;
109 using ::testing::SetArgPointee
;
110 using ::testing::WithArg
;
113 struct PrepareLocalImageRequest
<librbd::MockTestImageCtx
> {
114 static PrepareLocalImageRequest
* s_instance
;
115 std::string
*local_image_id
= nullptr;
116 std::string
*tag_owner
= nullptr;
117 Context
*on_finish
= nullptr;
119 static PrepareLocalImageRequest
* create(librados::IoCtx
&,
120 const std::string
&global_image_id
,
121 std::string
*local_image_id
,
122 std::string
*tag_owner
,
123 MockContextWQ
*work_queue
,
124 Context
*on_finish
) {
125 assert(s_instance
!= nullptr);
126 s_instance
->local_image_id
= local_image_id
;
127 s_instance
->tag_owner
= tag_owner
;
128 s_instance
->on_finish
= on_finish
;
132 PrepareLocalImageRequest() {
136 MOCK_METHOD0(send
, void());
140 struct PrepareRemoteImageRequest
<librbd::MockTestImageCtx
> {
141 static PrepareRemoteImageRequest
* s_instance
;
142 std::string
*remote_mirror_uuid
= nullptr;
143 std::string
*remote_image_id
= nullptr;
144 Context
*on_finish
= nullptr;
146 static PrepareRemoteImageRequest
* create(librados::IoCtx
&,
147 const std::string
&global_image_id
,
148 std::string
*remote_mirror_uuid
,
149 std::string
*remote_image_id
,
150 Context
*on_finish
) {
151 assert(s_instance
!= nullptr);
152 s_instance
->remote_mirror_uuid
= remote_mirror_uuid
;
153 s_instance
->remote_image_id
= remote_image_id
;
154 s_instance
->on_finish
= on_finish
;
158 PrepareRemoteImageRequest() {
162 MOCK_METHOD0(send
, void());
166 struct BootstrapRequest
<librbd::MockTestImageCtx
> {
167 static BootstrapRequest
* s_instance
;
168 librbd::MockTestImageCtx
**image_ctx
= nullptr;
169 Context
*on_finish
= nullptr;
170 bool *do_resync
= nullptr;
172 static BootstrapRequest
* create(
173 librados::IoCtx
&local_io_ctx
, librados::IoCtx
&remote_io_ctx
,
174 rbd::mirror::InstanceWatcher
<librbd::MockTestImageCtx
> *instance_watcher
,
175 librbd::MockTestImageCtx
**local_image_ctx
,
176 const std::string
&local_image_name
, const std::string
&remote_image_id
,
177 const std::string
&global_image_id
, MockContextWQ
*work_queue
,
178 MockSafeTimer
*timer
, Mutex
*timer_lock
,
179 const std::string
&local_mirror_uuid
,
180 const std::string
&remote_mirror_uuid
,
181 ::journal::MockJournalerProxy
*journaler
,
182 librbd::journal::MirrorPeerClientMeta
*client_meta
,
183 Context
*on_finish
, bool *do_resync
,
184 rbd::mirror::ProgressContext
*progress_ctx
= nullptr) {
185 assert(s_instance
!= nullptr);
186 s_instance
->image_ctx
= local_image_ctx
;
187 s_instance
->on_finish
= on_finish
;
188 s_instance
->do_resync
= do_resync
;
193 assert(s_instance
== nullptr);
197 ~BootstrapRequest() {
198 assert(s_instance
== this);
199 s_instance
= nullptr;
208 inline bool is_syncing() const {
212 MOCK_METHOD0(send
, void());
213 MOCK_METHOD0(cancel
, void());
217 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
218 static CloseImageRequest
* s_instance
;
219 librbd::MockTestImageCtx
**image_ctx
= nullptr;
220 Context
*on_finish
= nullptr;
222 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
223 Context
*on_finish
) {
224 assert(s_instance
!= nullptr);
225 s_instance
->image_ctx
= image_ctx
;
226 s_instance
->on_finish
= on_finish
;
230 CloseImageRequest() {
231 assert(s_instance
== nullptr);
235 ~CloseImageRequest() {
236 assert(s_instance
== this);
237 s_instance
= nullptr;
240 MOCK_METHOD0(send
, void());
244 struct EventPreprocessor
<librbd::MockTestImageCtx
> {
245 static EventPreprocessor
*s_instance
;
247 static EventPreprocessor
*create(librbd::MockTestImageCtx
&local_image_ctx
,
248 ::journal::MockJournalerProxy
&remote_journaler
,
249 const std::string
&local_mirror_uuid
,
250 librbd::journal::MirrorPeerClientMeta
*client_meta
,
251 MockContextWQ
*work_queue
) {
252 assert(s_instance
!= nullptr);
256 static void destroy(EventPreprocessor
* processor
) {
259 EventPreprocessor() {
260 assert(s_instance
== nullptr);
264 ~EventPreprocessor() {
265 assert(s_instance
== this);
266 s_instance
= nullptr;
269 MOCK_METHOD1(is_required
, bool(const librbd::journal::EventEntry
&));
270 MOCK_METHOD2(preprocess
, void(librbd::journal::EventEntry
*, Context
*));
274 struct ReplayStatusFormatter
<librbd::MockTestImageCtx
> {
275 static ReplayStatusFormatter
* s_instance
;
277 static ReplayStatusFormatter
* create(::journal::MockJournalerProxy
*journaler
,
278 const std::string
&mirror_uuid
) {
279 assert(s_instance
!= nullptr);
283 static void destroy(ReplayStatusFormatter
* formatter
) {
286 ReplayStatusFormatter() {
287 assert(s_instance
== nullptr);
291 ~ReplayStatusFormatter() {
292 assert(s_instance
== this);
293 s_instance
= nullptr;
296 MOCK_METHOD2(get_or_send_update
, bool(std::string
*description
, Context
*on_finish
));
299 BootstrapRequest
<librbd::MockTestImageCtx
>* BootstrapRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
300 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
301 EventPreprocessor
<librbd::MockTestImageCtx
>* EventPreprocessor
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
302 PrepareLocalImageRequest
<librbd::MockTestImageCtx
>* PrepareLocalImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
303 PrepareRemoteImageRequest
<librbd::MockTestImageCtx
>* PrepareRemoteImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
304 ReplayStatusFormatter
<librbd::MockTestImageCtx
>* ReplayStatusFormatter
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
306 } // namespace image_replayer
307 } // namespace mirror
310 // template definitions
311 #include "tools/rbd_mirror/ImageReplayer.cc"
316 class TestMockImageReplayer
: public TestMockFixture
{
318 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
319 typedef ImageDeleter
<librbd::MockTestImageCtx
> MockImageDeleter
;
320 typedef BootstrapRequest
<librbd::MockTestImageCtx
> MockBootstrapRequest
;
321 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
322 typedef EventPreprocessor
<librbd::MockTestImageCtx
> MockEventPreprocessor
;
323 typedef PrepareLocalImageRequest
<librbd::MockTestImageCtx
> MockPrepareLocalImageRequest
;
324 typedef PrepareRemoteImageRequest
<librbd::MockTestImageCtx
> MockPrepareRemoteImageRequest
;
325 typedef ReplayStatusFormatter
<librbd::MockTestImageCtx
> MockReplayStatusFormatter
;
326 typedef librbd::journal::Replay
<librbd::MockTestImageCtx
> MockReplay
;
327 typedef ImageReplayer
<librbd::MockTestImageCtx
> MockImageReplayer
;
328 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
330 void SetUp() override
{
331 TestMockFixture::SetUp();
334 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
, m_image_size
));
335 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
, &m_remote_image_ctx
));
338 void TearDown() override
{
339 delete m_image_replayer
;
341 TestMockFixture::TearDown();
344 void create_local_image() {
346 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
347 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
350 void expect_work_queue_repeatedly(MockThreads
&mock_threads
) {
351 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
352 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
353 m_threads
->work_queue
->queue(ctx
, r
);
357 void expect_add_event_after_repeatedly(MockThreads
&mock_threads
) {
358 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
360 DoAll(Invoke([this](double seconds
, Context
*ctx
) {
361 m_threads
->timer
->add_event_after(seconds
, ctx
);
364 EXPECT_CALL(*mock_threads
.timer
, cancel_event(_
))
366 Invoke([this](Context
*ctx
) {
367 return m_threads
->timer
->cancel_event(ctx
);
371 void expect_wait_for_scheduled_deletion(MockImageDeleter
& mock_image_deleter
,
372 const std::string
& global_image_id
,
374 EXPECT_CALL(mock_image_deleter
,
375 wait_for_scheduled_deletion(_
, global_image_id
, _
, false))
376 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
*ctx
) {
377 m_threads
->work_queue
->queue(ctx
, r
);
381 void expect_cancel_waiter(MockImageDeleter
& mock_image_deleter
) {
382 EXPECT_CALL(mock_image_deleter
, cancel_waiter(m_local_io_ctx
.get_id(),
386 void expect_schedule_image_delete(MockImageDeleter
& mock_image_deleter
,
387 const std::string
& global_image_id
,
388 bool ignore_orphan
) {
389 EXPECT_CALL(mock_image_deleter
,
390 schedule_image_delete(_
, _
, global_image_id
, ignore_orphan
));
393 bufferlist
encode_tag_data(const librbd::journal::TagData
&tag_data
) {
395 ::encode(tag_data
, bl
);
399 void expect_get_or_send_update(
400 MockReplayStatusFormatter
&mock_replay_status_formatter
) {
401 EXPECT_CALL(mock_replay_status_formatter
, get_or_send_update(_
, _
))
402 .WillRepeatedly(DoAll(WithArg
<1>(CompleteContext(-EEXIST
)),
406 void expect_send(MockPrepareLocalImageRequest
&mock_request
,
407 const std::string
&local_image_id
,
408 const std::string
&tag_owner
,
410 EXPECT_CALL(mock_request
, send())
411 .WillOnce(Invoke([&mock_request
, local_image_id
, tag_owner
, r
]() {
413 *mock_request
.local_image_id
= local_image_id
;
414 *mock_request
.tag_owner
= tag_owner
;
416 mock_request
.on_finish
->complete(r
);
420 void expect_send(MockPrepareRemoteImageRequest
& mock_request
,
421 const std::string
& mirror_uuid
, const std::string
& image_id
,
423 EXPECT_CALL(mock_request
, send())
424 .WillOnce(Invoke([&mock_request
, image_id
, mirror_uuid
, r
]() {
425 *mock_request
.remote_mirror_uuid
= mirror_uuid
;
426 *mock_request
.remote_image_id
= image_id
;
427 mock_request
.on_finish
->complete(r
);
431 void expect_send(MockBootstrapRequest
&mock_bootstrap_request
,
432 librbd::MockTestImageCtx
&mock_local_image_ctx
,
433 bool do_resync
, int r
) {
434 EXPECT_CALL(mock_bootstrap_request
, send())
435 .WillOnce(Invoke([&mock_bootstrap_request
, &mock_local_image_ctx
,
438 *mock_bootstrap_request
.image_ctx
= &mock_local_image_ctx
;
439 *mock_bootstrap_request
.do_resync
= do_resync
;
441 mock_bootstrap_request
.on_finish
->complete(r
);
445 void expect_start_external_replay(librbd::MockTestJournal
&mock_journal
,
446 MockReplay
*mock_replay
, int r
) {
447 EXPECT_CALL(mock_journal
, start_external_replay(_
, _
))
448 .WillOnce(DoAll(SetArgPointee
<0>(mock_replay
),
449 WithArg
<1>(CompleteContext(r
))));
452 void expect_init(::journal::MockJournaler
&mock_journaler
, int r
) {
453 EXPECT_CALL(mock_journaler
, init(_
))
454 .WillOnce(CompleteContext(r
));
457 void expect_get_cached_client(::journal::MockJournaler
&mock_journaler
,
459 librbd::journal::ImageClientMeta image_client_meta
;
460 image_client_meta
.tag_class
= 0;
462 librbd::journal::ClientData client_data
;
463 client_data
.client_meta
= image_client_meta
;
465 cls::journal::Client client
;
466 ::encode(client_data
, client
.data
);
468 EXPECT_CALL(mock_journaler
, get_cached_client("local_mirror_uuid", _
))
469 .WillOnce(DoAll(SetArgPointee
<1>(client
),
473 void expect_stop_replay(::journal::MockJournaler
&mock_journaler
, int r
) {
474 EXPECT_CALL(mock_journaler
, stop_replay(_
))
475 .WillOnce(CompleteContext(r
));
478 void expect_flush(MockReplay
&mock_replay
, int r
) {
479 EXPECT_CALL(mock_replay
, flush(_
)).WillOnce(CompleteContext(r
));
482 void expect_shut_down(MockReplay
&mock_replay
, bool cancel_ops
, int r
) {
483 EXPECT_CALL(mock_replay
, shut_down(cancel_ops
, _
))
484 .WillOnce(WithArg
<1>(CompleteContext(r
)));
487 void expect_shut_down(journal::MockJournaler
&mock_journaler
, int r
) {
488 EXPECT_CALL(mock_journaler
, shut_down(_
))
489 .WillOnce(CompleteContext(r
));
492 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
493 EXPECT_CALL(mock_close_image_request
, send())
494 .WillOnce(Invoke([&mock_close_image_request
, r
]() {
495 *mock_close_image_request
.image_ctx
= nullptr;
496 mock_close_image_request
.on_finish
->complete(r
);
500 void expect_get_commit_tid_in_debug(
501 ::journal::MockReplayEntry
&mock_replay_entry
) {
502 // It is used in debug messages and depends on debug level
503 EXPECT_CALL(mock_replay_entry
, get_commit_tid())
505 .WillRepeatedly(Return(0));
508 void expect_committed(::journal::MockJournaler
&mock_journaler
, int times
) {
509 EXPECT_CALL(mock_journaler
, committed(
510 MatcherCast
<const ::journal::MockReplayEntryProxy
&>(_
)))
514 void expect_try_pop_front(::journal::MockJournaler
&mock_journaler
,
515 uint64_t replay_tag_tid
, bool entries_available
) {
516 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
517 .WillOnce(DoAll(SetArgPointee
<0>(::journal::MockReplayEntryProxy()),
518 SetArgPointee
<1>(replay_tag_tid
),
519 Return(entries_available
)));
522 void expect_try_pop_front_return_no_entries(
523 ::journal::MockJournaler
&mock_journaler
, Context
*on_finish
) {
524 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
525 .WillOnce(DoAll(Invoke([on_finish
](::journal::MockReplayEntryProxy
*e
,
527 on_finish
->complete(0);
532 void expect_get_tag(::journal::MockJournaler
&mock_journaler
,
533 const cls::journal::Tag
&tag
, int r
) {
534 EXPECT_CALL(mock_journaler
, get_tag(_
, _
, _
))
535 .WillOnce(DoAll(SetArgPointee
<1>(tag
),
536 WithArg
<2>(CompleteContext(r
))));
539 void expect_allocate_tag(librbd::MockTestJournal
&mock_journal
, int r
) {
540 EXPECT_CALL(mock_journal
, allocate_tag(_
, _
, _
))
541 .WillOnce(WithArg
<2>(CompleteContext(r
)));
544 void expect_preprocess(MockEventPreprocessor
&mock_event_preprocessor
,
545 bool required
, int r
) {
546 EXPECT_CALL(mock_event_preprocessor
, is_required(_
))
547 .WillOnce(Return(required
));
549 EXPECT_CALL(mock_event_preprocessor
, preprocess(_
, _
))
550 .WillOnce(WithArg
<1>(CompleteContext(r
)));
554 void expect_process(MockReplay
&mock_replay
,
555 int on_ready_r
, int on_commit_r
) {
556 EXPECT_CALL(mock_replay
, process(_
, _
, _
))
557 .WillOnce(DoAll(WithArg
<1>(CompleteContext(on_ready_r
)),
558 WithArg
<2>(CompleteContext(on_commit_r
))));
561 void create_image_replayer(MockThreads
&mock_threads
,
562 MockImageDeleter
&mock_image_deleter
) {
563 m_image_replayer
= new MockImageReplayer(
564 &mock_threads
, &mock_image_deleter
, &m_instance_watcher
,
565 rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx
)),
566 "local_mirror_uuid", m_local_io_ctx
.get_id(), "global image id");
567 m_image_replayer
->add_peer("peer_uuid", m_remote_io_ctx
);
570 librbd::ImageCtx
*m_remote_image_ctx
;
571 librbd::ImageCtx
*m_local_image_ctx
= nullptr;
572 MockInstanceWatcher m_instance_watcher
;
573 MockImageReplayer
*m_image_replayer
= nullptr;
576 TEST_F(TestMockImageReplayer
, StartStop
) {
579 create_local_image();
580 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
582 librbd::MockTestJournal mock_local_journal
;
583 mock_local_image_ctx
.journal
= &mock_local_journal
;
585 journal::MockJournaler mock_remote_journaler
;
586 MockThreads
mock_threads(m_threads
);
587 expect_work_queue_repeatedly(mock_threads
);
588 expect_add_event_after_repeatedly(mock_threads
);
590 MockImageDeleter mock_image_deleter
;
591 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
592 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
593 MockBootstrapRequest mock_bootstrap_request
;
594 MockReplay mock_local_replay
;
595 MockEventPreprocessor mock_event_preprocessor
;
596 MockReplayStatusFormatter mock_replay_status_formatter
;
598 expect_get_or_send_update(mock_replay_status_formatter
);
601 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
602 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
603 "remote mirror uuid", 0);
604 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
605 m_remote_image_ctx
->id
, 0);
606 EXPECT_CALL(mock_remote_journaler
, construct());
607 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
609 EXPECT_CALL(mock_local_journal
, add_listener(_
));
611 expect_init(mock_remote_journaler
, 0);
613 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
614 expect_get_cached_client(mock_remote_journaler
, 0);
616 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
618 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
620 create_image_replayer(mock_threads
, mock_image_deleter
);
622 C_SaferCond start_ctx
;
623 m_image_replayer
->start(&start_ctx
);
624 ASSERT_EQ(0, start_ctx
.wait());
625 ASSERT_EQ(image_replayer::HEALTH_STATE_OK
,
626 m_image_replayer
->get_health_state());
630 MockCloseImageRequest mock_close_local_image_request
;
632 expect_cancel_waiter(mock_image_deleter
);
633 expect_shut_down(mock_local_replay
, true, 0);
634 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
635 EXPECT_CALL(mock_local_journal
, stop_external_replay());
636 expect_send(mock_close_local_image_request
, 0);
638 expect_stop_replay(mock_remote_journaler
, 0);
639 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
640 expect_shut_down(mock_remote_journaler
, 0);
642 C_SaferCond stop_ctx
;
643 m_image_replayer
->stop(&stop_ctx
);
644 ASSERT_EQ(0, stop_ctx
.wait());
645 ASSERT_EQ(image_replayer::HEALTH_STATE_OK
,
646 m_image_replayer
->get_health_state());
649 TEST_F(TestMockImageReplayer
, LocalImagePrimary
) {
650 create_local_image();
651 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
653 MockThreads
mock_threads(m_threads
);
654 expect_work_queue_repeatedly(mock_threads
);
655 expect_add_event_after_repeatedly(mock_threads
);
657 MockImageDeleter mock_image_deleter
;
658 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
659 MockReplayStatusFormatter mock_replay_status_formatter
;
661 expect_get_or_send_update(mock_replay_status_formatter
);
664 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
665 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
668 create_image_replayer(mock_threads
, mock_image_deleter
);
670 C_SaferCond start_ctx
;
671 m_image_replayer
->start(&start_ctx
);
672 ASSERT_EQ(0, start_ctx
.wait());
675 TEST_F(TestMockImageReplayer
, LocalImageDNE
) {
676 create_local_image();
677 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
679 journal::MockJournaler mock_remote_journaler
;
680 MockThreads
mock_threads(m_threads
);
681 expect_work_queue_repeatedly(mock_threads
);
682 expect_add_event_after_repeatedly(mock_threads
);
684 MockImageDeleter mock_image_deleter
;
685 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
686 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
687 MockBootstrapRequest mock_bootstrap_request
;
688 MockReplayStatusFormatter mock_replay_status_formatter
;
690 expect_get_or_send_update(mock_replay_status_formatter
);
693 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
694 expect_send(mock_prepare_local_image_request
, "", "", -ENOENT
);
695 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
696 m_remote_image_ctx
->id
, 0);
697 EXPECT_CALL(mock_remote_journaler
, construct());
698 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EREMOTEIO
);
700 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
701 expect_shut_down(mock_remote_journaler
, 0);
703 create_image_replayer(mock_threads
, mock_image_deleter
);
705 C_SaferCond start_ctx
;
706 m_image_replayer
->start(&start_ctx
);
707 ASSERT_EQ(-EREMOTEIO
, start_ctx
.wait());
710 TEST_F(TestMockImageReplayer
, PrepareLocalImageError
) {
711 create_local_image();
712 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
714 MockThreads
mock_threads(m_threads
);
715 expect_work_queue_repeatedly(mock_threads
);
716 expect_add_event_after_repeatedly(mock_threads
);
718 MockImageDeleter mock_image_deleter
;
719 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
720 MockReplayStatusFormatter mock_replay_status_formatter
;
722 expect_get_or_send_update(mock_replay_status_formatter
);
725 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
726 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
727 "remote mirror uuid", -EINVAL
);
729 create_image_replayer(mock_threads
, mock_image_deleter
);
731 C_SaferCond start_ctx
;
732 m_image_replayer
->start(&start_ctx
);
733 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
736 TEST_F(TestMockImageReplayer
, GetRemoteImageIdDNE
) {
737 create_local_image();
738 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
740 MockThreads
mock_threads(m_threads
);
741 expect_work_queue_repeatedly(mock_threads
);
742 expect_add_event_after_repeatedly(mock_threads
);
744 MockImageDeleter mock_image_deleter
;
745 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
746 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
747 MockReplayStatusFormatter mock_replay_status_formatter
;
749 expect_get_or_send_update(mock_replay_status_formatter
);
752 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
753 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
754 "remote mirror uuid", 0);
755 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
757 expect_schedule_image_delete(mock_image_deleter
, "global image id", false);
759 create_image_replayer(mock_threads
, mock_image_deleter
);
761 C_SaferCond start_ctx
;
762 m_image_replayer
->start(&start_ctx
);
763 ASSERT_EQ(0, start_ctx
.wait());
766 TEST_F(TestMockImageReplayer
, GetRemoteImageIdNonLinkedDNE
) {
767 create_local_image();
768 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
770 MockThreads
mock_threads(m_threads
);
771 expect_work_queue_repeatedly(mock_threads
);
772 expect_add_event_after_repeatedly(mock_threads
);
774 MockImageDeleter mock_image_deleter
;
775 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
776 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
777 MockReplayStatusFormatter mock_replay_status_formatter
;
779 expect_get_or_send_update(mock_replay_status_formatter
);
782 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
783 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
784 "some other mirror uuid", 0);
785 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
788 create_image_replayer(mock_threads
, mock_image_deleter
);
790 C_SaferCond start_ctx
;
791 m_image_replayer
->start(&start_ctx
);
792 ASSERT_EQ(-ENOENT
, start_ctx
.wait());
795 TEST_F(TestMockImageReplayer
, GetRemoteImageIdError
) {
796 create_local_image();
797 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
799 MockThreads
mock_threads(m_threads
);
800 expect_work_queue_repeatedly(mock_threads
);
801 expect_add_event_after_repeatedly(mock_threads
);
803 MockImageDeleter mock_image_deleter
;
804 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
805 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
806 MockReplayStatusFormatter mock_replay_status_formatter
;
808 expect_get_or_send_update(mock_replay_status_formatter
);
811 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
812 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
813 "remote mirror uuid", 0);
814 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
815 m_remote_image_ctx
->id
, -EINVAL
);
817 create_image_replayer(mock_threads
, mock_image_deleter
);
819 C_SaferCond start_ctx
;
820 m_image_replayer
->start(&start_ctx
);
821 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
824 TEST_F(TestMockImageReplayer
, BootstrapError
) {
826 create_local_image();
827 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
829 journal::MockJournaler mock_remote_journaler
;
830 MockThreads
mock_threads(m_threads
);
831 expect_work_queue_repeatedly(mock_threads
);
832 expect_add_event_after_repeatedly(mock_threads
);
834 MockImageDeleter mock_image_deleter
;
835 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
836 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
837 MockBootstrapRequest mock_bootstrap_request
;
838 MockReplayStatusFormatter mock_replay_status_formatter
;
840 expect_get_or_send_update(mock_replay_status_formatter
);
843 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
844 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
845 "remote mirror uuid", 0);
846 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
847 m_remote_image_ctx
->id
, 0);
848 EXPECT_CALL(mock_remote_journaler
, construct());
849 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EINVAL
);
851 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
852 expect_shut_down(mock_remote_journaler
, 0);
854 create_image_replayer(mock_threads
, mock_image_deleter
);
856 C_SaferCond start_ctx
;
857 m_image_replayer
->start(&start_ctx
);
858 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
861 TEST_F(TestMockImageReplayer
, StartExternalReplayError
) {
864 create_local_image();
865 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
867 librbd::MockTestJournal mock_local_journal
;
868 mock_local_image_ctx
.journal
= &mock_local_journal
;
870 journal::MockJournaler mock_remote_journaler
;
871 MockThreads
mock_threads(m_threads
);
872 expect_work_queue_repeatedly(mock_threads
);
873 expect_add_event_after_repeatedly(mock_threads
);
875 MockImageDeleter mock_image_deleter
;
876 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
877 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
878 MockBootstrapRequest mock_bootstrap_request
;
879 MockReplay mock_local_replay
;
880 MockEventPreprocessor mock_event_preprocessor
;
881 MockReplayStatusFormatter mock_replay_status_formatter
;
883 expect_get_or_send_update(mock_replay_status_formatter
);
886 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
887 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
888 "remote mirror uuid", 0);
889 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
890 m_remote_image_ctx
->id
, 0);
891 EXPECT_CALL(mock_remote_journaler
, construct());
892 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
894 EXPECT_CALL(mock_local_journal
, add_listener(_
));
896 expect_init(mock_remote_journaler
, 0);
898 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
899 expect_get_cached_client(mock_remote_journaler
, 0);
901 expect_start_external_replay(mock_local_journal
, nullptr, -EINVAL
);
903 MockCloseImageRequest mock_close_local_image_request
;
904 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
905 expect_send(mock_close_local_image_request
, 0);
907 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
908 expect_shut_down(mock_remote_journaler
, 0);
910 create_image_replayer(mock_threads
, mock_image_deleter
);
912 C_SaferCond start_ctx
;
913 m_image_replayer
->start(&start_ctx
);
914 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
915 ASSERT_EQ(image_replayer::HEALTH_STATE_ERROR
,
916 m_image_replayer
->get_health_state());
919 TEST_F(TestMockImageReplayer
, StopError
) {
922 create_local_image();
923 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
925 librbd::MockTestJournal mock_local_journal
;
926 mock_local_image_ctx
.journal
= &mock_local_journal
;
928 journal::MockJournaler mock_remote_journaler
;
929 MockThreads
mock_threads(m_threads
);
930 expect_work_queue_repeatedly(mock_threads
);
931 expect_add_event_after_repeatedly(mock_threads
);
933 MockImageDeleter mock_image_deleter
;
934 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
935 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
936 MockBootstrapRequest mock_bootstrap_request
;
937 MockReplay mock_local_replay
;
938 MockEventPreprocessor mock_event_preprocessor
;
939 MockReplayStatusFormatter mock_replay_status_formatter
;
941 expect_get_or_send_update(mock_replay_status_formatter
);
944 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
945 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
946 "remote mirror uuid", 0);
947 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
948 m_remote_image_ctx
->id
, 0);
949 EXPECT_CALL(mock_remote_journaler
, construct());
950 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
952 EXPECT_CALL(mock_local_journal
, add_listener(_
));
954 expect_init(mock_remote_journaler
, 0);
956 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
957 expect_get_cached_client(mock_remote_journaler
, 0);
959 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
961 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
963 create_image_replayer(mock_threads
, mock_image_deleter
);
965 C_SaferCond start_ctx
;
966 m_image_replayer
->start(&start_ctx
);
967 ASSERT_EQ(0, start_ctx
.wait());
969 // STOP (errors are ignored)
971 MockCloseImageRequest mock_close_local_image_request
;
973 expect_cancel_waiter(mock_image_deleter
);
974 expect_shut_down(mock_local_replay
, true, -EINVAL
);
975 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
976 EXPECT_CALL(mock_local_journal
, stop_external_replay());
977 expect_send(mock_close_local_image_request
, -EINVAL
);
979 expect_stop_replay(mock_remote_journaler
, -EINVAL
);
980 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
981 expect_shut_down(mock_remote_journaler
, -EINVAL
);
983 C_SaferCond stop_ctx
;
984 m_image_replayer
->stop(&stop_ctx
);
985 ASSERT_EQ(0, stop_ctx
.wait());
988 TEST_F(TestMockImageReplayer
, Replay
) {
991 create_local_image();
992 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
994 librbd::MockTestJournal mock_local_journal
;
995 mock_local_image_ctx
.journal
= &mock_local_journal
;
997 journal::MockJournaler mock_remote_journaler
;
998 MockThreads
mock_threads(m_threads
);
999 expect_work_queue_repeatedly(mock_threads
);
1000 expect_add_event_after_repeatedly(mock_threads
);
1002 MockImageDeleter mock_image_deleter
;
1003 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
1004 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
1005 MockBootstrapRequest mock_bootstrap_request
;
1006 MockReplay mock_local_replay
;
1007 MockEventPreprocessor mock_event_preprocessor
;
1008 MockReplayStatusFormatter mock_replay_status_formatter
;
1009 ::journal::MockReplayEntry mock_replay_entry
;
1011 expect_get_or_send_update(mock_replay_status_formatter
);
1012 expect_get_commit_tid_in_debug(mock_replay_entry
);
1013 expect_committed(mock_remote_journaler
, 2);
1016 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
1017 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
1018 "remote mirror uuid", 0);
1019 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
1020 m_remote_image_ctx
->id
, 0);
1021 EXPECT_CALL(mock_remote_journaler
, construct());
1022 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
1024 EXPECT_CALL(mock_local_journal
, add_listener(_
));
1026 expect_init(mock_remote_journaler
, 0);
1028 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
1029 expect_get_cached_client(mock_remote_journaler
, 0);
1031 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1033 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
1035 create_image_replayer(mock_threads
, mock_image_deleter
);
1037 C_SaferCond start_ctx
;
1038 m_image_replayer
->start(&start_ctx
);
1039 ASSERT_EQ(0, start_ctx
.wait());
1043 cls::journal::Tag tag
=
1044 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1045 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1048 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1051 expect_shut_down(mock_local_replay
, false, 0);
1052 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1053 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1054 expect_get_tag(mock_remote_journaler
, tag
, 0);
1055 expect_allocate_tag(mock_local_journal
, 0);
1058 EXPECT_CALL(mock_replay_entry
, get_data());
1059 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1060 .WillOnce(Return(0));
1061 expect_preprocess(mock_event_preprocessor
, false, 0);
1062 expect_process(mock_local_replay
, 0, 0);
1064 // the next event with preprocess
1065 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1066 EXPECT_CALL(mock_replay_entry
, get_data());
1067 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1068 .WillOnce(Return(0));
1069 expect_preprocess(mock_event_preprocessor
, true, 0);
1070 expect_process(mock_local_replay
, 0, 0);
1072 // attempt to process the next event
1073 C_SaferCond replay_ctx
;
1074 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1077 m_image_replayer
->handle_replay_ready();
1078 ASSERT_EQ(0, replay_ctx
.wait());
1082 MockCloseImageRequest mock_close_local_image_request
;
1083 expect_cancel_waiter(mock_image_deleter
);
1084 expect_shut_down(mock_local_replay
, true, 0);
1085 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1086 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1087 expect_send(mock_close_local_image_request
, 0);
1089 expect_stop_replay(mock_remote_journaler
, 0);
1090 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1091 expect_shut_down(mock_remote_journaler
, 0);
1093 C_SaferCond stop_ctx
;
1094 m_image_replayer
->stop(&stop_ctx
);
1095 ASSERT_EQ(0, stop_ctx
.wait());
1098 TEST_F(TestMockImageReplayer
, DecodeError
) {
1101 create_local_image();
1102 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
1104 librbd::MockTestJournal mock_local_journal
;
1105 mock_local_image_ctx
.journal
= &mock_local_journal
;
1107 journal::MockJournaler mock_remote_journaler
;
1108 MockThreads
mock_threads(m_threads
);
1109 expect_work_queue_repeatedly(mock_threads
);
1110 expect_add_event_after_repeatedly(mock_threads
);
1112 MockImageDeleter mock_image_deleter
;
1113 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
1114 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
1115 MockBootstrapRequest mock_bootstrap_request
;
1116 MockReplay mock_local_replay
;
1117 MockEventPreprocessor mock_event_preprocessor
;
1118 MockReplayStatusFormatter mock_replay_status_formatter
;
1119 ::journal::MockReplayEntry mock_replay_entry
;
1121 expect_get_or_send_update(mock_replay_status_formatter
);
1122 expect_get_commit_tid_in_debug(mock_replay_entry
);
1125 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
1126 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
1127 "remote mirror uuid", 0);
1128 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
1129 m_remote_image_ctx
->id
, 0);
1130 EXPECT_CALL(mock_remote_journaler
, construct());
1131 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
1133 EXPECT_CALL(mock_local_journal
, add_listener(_
));
1135 expect_init(mock_remote_journaler
, 0);
1137 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
1138 expect_get_cached_client(mock_remote_journaler
, 0);
1140 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1142 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
1144 create_image_replayer(mock_threads
, mock_image_deleter
);
1146 C_SaferCond start_ctx
;
1147 m_image_replayer
->start(&start_ctx
);
1148 ASSERT_EQ(0, start_ctx
.wait());
1152 cls::journal::Tag tag
=
1153 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1154 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1157 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1160 expect_shut_down(mock_local_replay
, false, 0);
1161 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1162 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1163 expect_get_tag(mock_remote_journaler
, tag
, 0);
1164 expect_allocate_tag(mock_local_journal
, 0);
1167 EXPECT_CALL(mock_replay_entry
, get_data());
1168 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1169 .WillOnce(Return(-EINVAL
));
1172 expect_shut_down(mock_local_replay
, true, 0);
1173 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1174 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1176 MockCloseImageRequest mock_close_local_image_request
;
1177 C_SaferCond close_ctx
;
1178 EXPECT_CALL(mock_close_local_image_request
, send())
1179 .WillOnce(Invoke([&mock_close_local_image_request
, &close_ctx
]() {
1180 *mock_close_local_image_request
.image_ctx
= nullptr;
1181 mock_close_local_image_request
.on_finish
->complete(0);
1182 close_ctx
.complete(0);
1185 expect_stop_replay(mock_remote_journaler
, 0);
1186 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1187 expect_shut_down(mock_remote_journaler
, 0);
1190 m_image_replayer
->handle_replay_ready();
1191 ASSERT_EQ(0, close_ctx
.wait());
1193 while (!m_image_replayer
->is_stopped()) {
1198 TEST_F(TestMockImageReplayer
, DelayedReplay
) {
1202 create_local_image();
1203 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
1205 librbd::MockTestJournal mock_local_journal
;
1206 mock_local_image_ctx
.journal
= &mock_local_journal
;
1208 journal::MockJournaler mock_remote_journaler
;
1209 MockThreads
mock_threads(m_threads
);
1210 expect_work_queue_repeatedly(mock_threads
);
1211 expect_add_event_after_repeatedly(mock_threads
);
1213 MockImageDeleter mock_image_deleter
;
1214 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
1215 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
1216 MockBootstrapRequest mock_bootstrap_request
;
1217 MockReplay mock_local_replay
;
1218 MockEventPreprocessor mock_event_preprocessor
;
1219 MockReplayStatusFormatter mock_replay_status_formatter
;
1220 ::journal::MockReplayEntry mock_replay_entry
;
1222 expect_get_or_send_update(mock_replay_status_formatter
);
1223 expect_get_commit_tid_in_debug(mock_replay_entry
);
1224 expect_committed(mock_remote_journaler
, 1);
1227 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
1228 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
1229 "remote mirror uuid", 0);
1230 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
1231 m_remote_image_ctx
->id
, 0);
1232 EXPECT_CALL(mock_remote_journaler
, construct());
1233 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
1235 EXPECT_CALL(mock_local_journal
, add_listener(_
));
1237 expect_init(mock_remote_journaler
, 0);
1239 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
1240 expect_get_cached_client(mock_remote_journaler
, 0);
1242 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1244 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
1246 create_image_replayer(mock_threads
, mock_image_deleter
);
1248 C_SaferCond start_ctx
;
1249 m_image_replayer
->start(&start_ctx
);
1250 ASSERT_EQ(0, start_ctx
.wait());
1254 cls::journal::Tag tag
=
1255 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1256 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1259 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1262 expect_shut_down(mock_local_replay
, false, 0);
1263 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1264 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1265 expect_get_tag(mock_remote_journaler
, tag
, 0);
1266 expect_allocate_tag(mock_local_journal
, 0);
1268 // process with delay
1269 EXPECT_CALL(mock_replay_entry
, get_data());
1270 librbd::journal::EventEntry
event_entry(
1271 librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
1272 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1273 .WillOnce(DoAll(SetArgPointee
<1>(event_entry
),
1275 expect_preprocess(mock_event_preprocessor
, false, 0);
1276 expect_process(mock_local_replay
, 0, 0);
1278 // attempt to process the next event
1279 C_SaferCond replay_ctx
;
1280 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1283 mock_local_image_ctx
.mirroring_replay_delay
= 2;
1284 m_image_replayer
->handle_replay_ready();
1285 ASSERT_EQ(0, replay_ctx
.wait());
1287 // add a pending (delayed) entry before stop
1288 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1289 EXPECT_CALL(mock_replay_entry
, get_data());
1290 C_SaferCond decode_ctx
;
1291 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1292 .WillOnce(DoAll(Invoke([&decode_ctx
](bufferlist::iterator
* it
,
1293 librbd::journal::EventEntry
*e
) {
1294 decode_ctx
.complete(0);
1298 mock_local_image_ctx
.mirroring_replay_delay
= 10;
1299 m_image_replayer
->handle_replay_ready();
1300 ASSERT_EQ(0, decode_ctx
.wait());
1304 MockCloseImageRequest mock_close_local_image_request
;
1306 expect_cancel_waiter(mock_image_deleter
);
1307 expect_shut_down(mock_local_replay
, true, 0);
1308 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1309 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1310 expect_send(mock_close_local_image_request
, 0);
1312 expect_stop_replay(mock_remote_journaler
, 0);
1313 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1314 expect_shut_down(mock_remote_journaler
, 0);
1316 C_SaferCond stop_ctx
;
1317 m_image_replayer
->stop(&stop_ctx
);
1318 ASSERT_EQ(0, stop_ctx
.wait());
1322 } // namespace mirror