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 cls::journal::ClientState
*client_state
;
145 ::journal::MockJournalerProxy
**remote_journaler
= nullptr;
146 librbd::journal::MirrorPeerClientMeta
*client_meta
= nullptr;
147 Context
*on_finish
= nullptr;
149 static PrepareRemoteImageRequest
* create(Threads
<librbd::MockTestImageCtx
> *threads
,
151 const std::string
&global_image_id
,
152 const std::string
&local_mirror_uuid
,
153 const std::string
&local_image_id
,
154 std::string
*remote_mirror_uuid
,
155 std::string
*remote_image_id
,
156 ::journal::MockJournalerProxy
**remote_journaler
,
157 cls::journal::ClientState
*client_state
,
158 librbd::journal::MirrorPeerClientMeta
*client_meta
,
159 Context
*on_finish
) {
160 assert(s_instance
!= nullptr);
161 s_instance
->remote_mirror_uuid
= remote_mirror_uuid
;
162 s_instance
->remote_image_id
= remote_image_id
;
163 s_instance
->remote_journaler
= remote_journaler
;
164 s_instance
->client_state
= client_state
;
165 s_instance
->client_meta
= client_meta
;
166 s_instance
->on_finish
= on_finish
;
170 PrepareRemoteImageRequest() {
174 MOCK_METHOD0(send
, void());
178 struct BootstrapRequest
<librbd::MockTestImageCtx
> {
179 static BootstrapRequest
* s_instance
;
180 librbd::MockTestImageCtx
**image_ctx
= nullptr;
181 Context
*on_finish
= nullptr;
182 bool *do_resync
= nullptr;
184 static BootstrapRequest
* create(
185 librados::IoCtx
&local_io_ctx
, librados::IoCtx
&remote_io_ctx
,
186 rbd::mirror::InstanceWatcher
<librbd::MockTestImageCtx
> *instance_watcher
,
187 librbd::MockTestImageCtx
**local_image_ctx
,
188 const std::string
&local_image_name
, const std::string
&remote_image_id
,
189 const std::string
&global_image_id
, MockContextWQ
*work_queue
,
190 MockSafeTimer
*timer
, Mutex
*timer_lock
,
191 const std::string
&local_mirror_uuid
,
192 const std::string
&remote_mirror_uuid
,
193 ::journal::MockJournalerProxy
*journaler
,
194 cls::journal::ClientState
*client_state
,
195 librbd::journal::MirrorPeerClientMeta
*client_meta
,
196 Context
*on_finish
, bool *do_resync
,
197 rbd::mirror::ProgressContext
*progress_ctx
= nullptr) {
198 assert(s_instance
!= nullptr);
199 s_instance
->image_ctx
= local_image_ctx
;
200 s_instance
->on_finish
= on_finish
;
201 s_instance
->do_resync
= do_resync
;
206 assert(s_instance
== nullptr);
210 ~BootstrapRequest() {
211 assert(s_instance
== this);
212 s_instance
= nullptr;
221 inline bool is_syncing() const {
225 MOCK_METHOD0(send
, void());
226 MOCK_METHOD0(cancel
, void());
230 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
231 static CloseImageRequest
* s_instance
;
232 librbd::MockTestImageCtx
**image_ctx
= nullptr;
233 Context
*on_finish
= nullptr;
235 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
236 Context
*on_finish
) {
237 assert(s_instance
!= nullptr);
238 s_instance
->image_ctx
= image_ctx
;
239 s_instance
->on_finish
= on_finish
;
243 CloseImageRequest() {
244 assert(s_instance
== nullptr);
248 ~CloseImageRequest() {
249 assert(s_instance
== this);
250 s_instance
= nullptr;
253 MOCK_METHOD0(send
, void());
257 struct EventPreprocessor
<librbd::MockTestImageCtx
> {
258 static EventPreprocessor
*s_instance
;
260 static EventPreprocessor
*create(librbd::MockTestImageCtx
&local_image_ctx
,
261 ::journal::MockJournalerProxy
&remote_journaler
,
262 const std::string
&local_mirror_uuid
,
263 librbd::journal::MirrorPeerClientMeta
*client_meta
,
264 MockContextWQ
*work_queue
) {
265 assert(s_instance
!= nullptr);
269 static void destroy(EventPreprocessor
* processor
) {
272 EventPreprocessor() {
273 assert(s_instance
== nullptr);
277 ~EventPreprocessor() {
278 assert(s_instance
== this);
279 s_instance
= nullptr;
282 MOCK_METHOD1(is_required
, bool(const librbd::journal::EventEntry
&));
283 MOCK_METHOD2(preprocess
, void(librbd::journal::EventEntry
*, Context
*));
287 struct ReplayStatusFormatter
<librbd::MockTestImageCtx
> {
288 static ReplayStatusFormatter
* s_instance
;
290 static ReplayStatusFormatter
* create(::journal::MockJournalerProxy
*journaler
,
291 const std::string
&mirror_uuid
) {
292 assert(s_instance
!= nullptr);
296 static void destroy(ReplayStatusFormatter
* formatter
) {
299 ReplayStatusFormatter() {
300 assert(s_instance
== nullptr);
304 ~ReplayStatusFormatter() {
305 assert(s_instance
== this);
306 s_instance
= nullptr;
309 MOCK_METHOD2(get_or_send_update
, bool(std::string
*description
, Context
*on_finish
));
312 BootstrapRequest
<librbd::MockTestImageCtx
>* BootstrapRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
313 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
314 EventPreprocessor
<librbd::MockTestImageCtx
>* EventPreprocessor
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
315 PrepareLocalImageRequest
<librbd::MockTestImageCtx
>* PrepareLocalImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
316 PrepareRemoteImageRequest
<librbd::MockTestImageCtx
>* PrepareRemoteImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
317 ReplayStatusFormatter
<librbd::MockTestImageCtx
>* ReplayStatusFormatter
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
319 } // namespace image_replayer
320 } // namespace mirror
323 // template definitions
324 #include "tools/rbd_mirror/ImageReplayer.cc"
329 class TestMockImageReplayer
: public TestMockFixture
{
331 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
332 typedef ImageDeleter
<librbd::MockTestImageCtx
> MockImageDeleter
;
333 typedef BootstrapRequest
<librbd::MockTestImageCtx
> MockBootstrapRequest
;
334 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
335 typedef EventPreprocessor
<librbd::MockTestImageCtx
> MockEventPreprocessor
;
336 typedef PrepareLocalImageRequest
<librbd::MockTestImageCtx
> MockPrepareLocalImageRequest
;
337 typedef PrepareRemoteImageRequest
<librbd::MockTestImageCtx
> MockPrepareRemoteImageRequest
;
338 typedef ReplayStatusFormatter
<librbd::MockTestImageCtx
> MockReplayStatusFormatter
;
339 typedef librbd::journal::Replay
<librbd::MockTestImageCtx
> MockReplay
;
340 typedef ImageReplayer
<librbd::MockTestImageCtx
> MockImageReplayer
;
341 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
343 void SetUp() override
{
344 TestMockFixture::SetUp();
347 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
, m_image_size
));
348 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
, &m_remote_image_ctx
));
351 void TearDown() override
{
352 delete m_image_replayer
;
354 TestMockFixture::TearDown();
357 void create_local_image() {
359 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
360 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
363 void expect_work_queue_repeatedly(MockThreads
&mock_threads
) {
364 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
365 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
366 m_threads
->work_queue
->queue(ctx
, r
);
370 void expect_add_event_after_repeatedly(MockThreads
&mock_threads
) {
371 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
373 DoAll(Invoke([this](double seconds
, Context
*ctx
) {
374 m_threads
->timer
->add_event_after(seconds
, ctx
);
377 EXPECT_CALL(*mock_threads
.timer
, cancel_event(_
))
379 Invoke([this](Context
*ctx
) {
380 return m_threads
->timer
->cancel_event(ctx
);
384 void expect_wait_for_scheduled_deletion(MockImageDeleter
& mock_image_deleter
,
385 const std::string
& global_image_id
,
387 EXPECT_CALL(mock_image_deleter
,
388 wait_for_scheduled_deletion(_
, global_image_id
, _
, false))
389 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
*ctx
) {
390 m_threads
->work_queue
->queue(ctx
, r
);
394 void expect_cancel_waiter(MockImageDeleter
& mock_image_deleter
) {
395 EXPECT_CALL(mock_image_deleter
, cancel_waiter(m_local_io_ctx
.get_id(),
399 void expect_schedule_image_delete(MockImageDeleter
& mock_image_deleter
,
400 const std::string
& global_image_id
,
401 bool ignore_orphan
) {
402 EXPECT_CALL(mock_image_deleter
,
403 schedule_image_delete(_
, _
, global_image_id
, ignore_orphan
));
406 bufferlist
encode_tag_data(const librbd::journal::TagData
&tag_data
) {
408 ::encode(tag_data
, bl
);
412 void expect_get_or_send_update(
413 MockReplayStatusFormatter
&mock_replay_status_formatter
) {
414 EXPECT_CALL(mock_replay_status_formatter
, get_or_send_update(_
, _
))
415 .WillRepeatedly(DoAll(WithArg
<1>(CompleteContext(-EEXIST
)),
419 void expect_send(MockPrepareLocalImageRequest
&mock_request
,
420 const std::string
&local_image_id
,
421 const std::string
&tag_owner
,
423 EXPECT_CALL(mock_request
, send())
424 .WillOnce(Invoke([&mock_request
, local_image_id
, tag_owner
, r
]() {
426 *mock_request
.local_image_id
= local_image_id
;
427 *mock_request
.tag_owner
= tag_owner
;
429 mock_request
.on_finish
->complete(r
);
433 void expect_send(MockPrepareRemoteImageRequest
& mock_request
,
434 const std::string
& mirror_uuid
, const std::string
& image_id
,
436 EXPECT_CALL(mock_request
, send())
437 .WillOnce(Invoke([&mock_request
, image_id
, mirror_uuid
, r
]() {
439 *mock_request
.remote_journaler
= new ::journal::MockJournalerProxy();
442 *mock_request
.remote_mirror_uuid
= mirror_uuid
;
443 *mock_request
.remote_image_id
= image_id
;
444 mock_request
.on_finish
->complete(r
);
448 void expect_send(MockBootstrapRequest
&mock_bootstrap_request
,
449 librbd::MockTestImageCtx
&mock_local_image_ctx
,
450 bool do_resync
, int r
) {
451 EXPECT_CALL(mock_bootstrap_request
, send())
452 .WillOnce(Invoke([&mock_bootstrap_request
, &mock_local_image_ctx
,
455 *mock_bootstrap_request
.image_ctx
= &mock_local_image_ctx
;
456 *mock_bootstrap_request
.do_resync
= do_resync
;
458 mock_bootstrap_request
.on_finish
->complete(r
);
462 void expect_start_external_replay(librbd::MockTestJournal
&mock_journal
,
463 MockReplay
*mock_replay
, int r
) {
464 EXPECT_CALL(mock_journal
, start_external_replay(_
, _
))
465 .WillOnce(DoAll(SetArgPointee
<0>(mock_replay
),
466 WithArg
<1>(CompleteContext(r
))));
469 void expect_init(::journal::MockJournaler
&mock_journaler
, int r
) {
470 EXPECT_CALL(mock_journaler
, init(_
))
471 .WillOnce(CompleteContext(r
));
474 void expect_get_cached_client(::journal::MockJournaler
&mock_journaler
,
476 librbd::journal::ImageClientMeta image_client_meta
;
477 image_client_meta
.tag_class
= 0;
479 librbd::journal::ClientData client_data
;
480 client_data
.client_meta
= image_client_meta
;
482 cls::journal::Client client
;
483 ::encode(client_data
, client
.data
);
485 EXPECT_CALL(mock_journaler
, get_cached_client("local_mirror_uuid", _
))
486 .WillOnce(DoAll(SetArgPointee
<1>(client
),
490 void expect_stop_replay(::journal::MockJournaler
&mock_journaler
, int r
) {
491 EXPECT_CALL(mock_journaler
, stop_replay(_
))
492 .WillOnce(CompleteContext(r
));
495 void expect_flush(MockReplay
&mock_replay
, int r
) {
496 EXPECT_CALL(mock_replay
, flush(_
)).WillOnce(CompleteContext(r
));
499 void expect_shut_down(MockReplay
&mock_replay
, bool cancel_ops
, int r
) {
500 EXPECT_CALL(mock_replay
, shut_down(cancel_ops
, _
))
501 .WillOnce(WithArg
<1>(CompleteContext(r
)));
504 void expect_shut_down(journal::MockJournaler
&mock_journaler
, int r
) {
505 EXPECT_CALL(mock_journaler
, shut_down(_
))
506 .WillOnce(CompleteContext(r
));
509 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
510 EXPECT_CALL(mock_close_image_request
, send())
511 .WillOnce(Invoke([&mock_close_image_request
, r
]() {
512 *mock_close_image_request
.image_ctx
= nullptr;
513 mock_close_image_request
.on_finish
->complete(r
);
517 void expect_get_commit_tid_in_debug(
518 ::journal::MockReplayEntry
&mock_replay_entry
) {
519 // It is used in debug messages and depends on debug level
520 EXPECT_CALL(mock_replay_entry
, get_commit_tid())
522 .WillRepeatedly(Return(0));
525 void expect_committed(::journal::MockJournaler
&mock_journaler
, int times
) {
526 EXPECT_CALL(mock_journaler
, committed(
527 MatcherCast
<const ::journal::MockReplayEntryProxy
&>(_
)))
531 void expect_try_pop_front(::journal::MockJournaler
&mock_journaler
,
532 uint64_t replay_tag_tid
, bool entries_available
) {
533 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
534 .WillOnce(DoAll(SetArgPointee
<0>(::journal::MockReplayEntryProxy()),
535 SetArgPointee
<1>(replay_tag_tid
),
536 Return(entries_available
)));
539 void expect_try_pop_front_return_no_entries(
540 ::journal::MockJournaler
&mock_journaler
, Context
*on_finish
) {
541 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
542 .WillOnce(DoAll(Invoke([on_finish
](::journal::MockReplayEntryProxy
*e
,
544 on_finish
->complete(0);
549 void expect_get_tag(::journal::MockJournaler
&mock_journaler
,
550 const cls::journal::Tag
&tag
, int r
) {
551 EXPECT_CALL(mock_journaler
, get_tag(_
, _
, _
))
552 .WillOnce(DoAll(SetArgPointee
<1>(tag
),
553 WithArg
<2>(CompleteContext(r
))));
556 void expect_allocate_tag(librbd::MockTestJournal
&mock_journal
, int r
) {
557 EXPECT_CALL(mock_journal
, allocate_tag(_
, _
, _
))
558 .WillOnce(WithArg
<2>(CompleteContext(r
)));
561 void expect_preprocess(MockEventPreprocessor
&mock_event_preprocessor
,
562 bool required
, int r
) {
563 EXPECT_CALL(mock_event_preprocessor
, is_required(_
))
564 .WillOnce(Return(required
));
566 EXPECT_CALL(mock_event_preprocessor
, preprocess(_
, _
))
567 .WillOnce(WithArg
<1>(CompleteContext(r
)));
571 void expect_process(MockReplay
&mock_replay
,
572 int on_ready_r
, int on_commit_r
) {
573 EXPECT_CALL(mock_replay
, process(_
, _
, _
))
574 .WillOnce(DoAll(WithArg
<1>(CompleteContext(on_ready_r
)),
575 WithArg
<2>(CompleteContext(on_commit_r
))));
578 void create_image_replayer(MockThreads
&mock_threads
,
579 MockImageDeleter
&mock_image_deleter
) {
580 m_image_replayer
= new MockImageReplayer(
581 &mock_threads
, &mock_image_deleter
, &m_instance_watcher
,
582 rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx
)),
583 "local_mirror_uuid", m_local_io_ctx
.get_id(), "global image id");
584 m_image_replayer
->add_peer("peer_uuid", m_remote_io_ctx
);
587 librbd::ImageCtx
*m_remote_image_ctx
;
588 librbd::ImageCtx
*m_local_image_ctx
= nullptr;
589 MockInstanceWatcher m_instance_watcher
;
590 MockImageReplayer
*m_image_replayer
= nullptr;
593 TEST_F(TestMockImageReplayer
, StartStop
) {
596 create_local_image();
597 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
599 librbd::MockTestJournal mock_local_journal
;
600 mock_local_image_ctx
.journal
= &mock_local_journal
;
602 journal::MockJournaler mock_remote_journaler
;
603 MockThreads
mock_threads(m_threads
);
604 expect_work_queue_repeatedly(mock_threads
);
605 expect_add_event_after_repeatedly(mock_threads
);
607 MockImageDeleter mock_image_deleter
;
608 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
609 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
610 MockBootstrapRequest mock_bootstrap_request
;
611 MockReplay mock_local_replay
;
612 MockEventPreprocessor mock_event_preprocessor
;
613 MockReplayStatusFormatter mock_replay_status_formatter
;
615 expect_get_or_send_update(mock_replay_status_formatter
);
618 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
619 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
620 "remote mirror uuid", 0);
621 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
622 m_remote_image_ctx
->id
, 0);
623 EXPECT_CALL(mock_remote_journaler
, construct());
624 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
626 EXPECT_CALL(mock_local_journal
, add_listener(_
));
628 expect_init(mock_remote_journaler
, 0);
630 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
631 expect_get_cached_client(mock_remote_journaler
, 0);
633 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
635 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
637 create_image_replayer(mock_threads
, mock_image_deleter
);
639 C_SaferCond start_ctx
;
640 m_image_replayer
->start(&start_ctx
);
641 ASSERT_EQ(0, start_ctx
.wait());
642 ASSERT_EQ(image_replayer::HEALTH_STATE_OK
,
643 m_image_replayer
->get_health_state());
647 MockCloseImageRequest mock_close_local_image_request
;
649 expect_cancel_waiter(mock_image_deleter
);
650 expect_shut_down(mock_local_replay
, true, 0);
651 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
652 EXPECT_CALL(mock_local_journal
, stop_external_replay());
653 expect_send(mock_close_local_image_request
, 0);
655 expect_stop_replay(mock_remote_journaler
, 0);
656 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
657 expect_shut_down(mock_remote_journaler
, 0);
659 C_SaferCond stop_ctx
;
660 m_image_replayer
->stop(&stop_ctx
);
661 ASSERT_EQ(0, stop_ctx
.wait());
662 ASSERT_EQ(image_replayer::HEALTH_STATE_OK
,
663 m_image_replayer
->get_health_state());
666 TEST_F(TestMockImageReplayer
, LocalImagePrimary
) {
667 create_local_image();
668 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
670 journal::MockJournaler mock_remote_journaler
;
671 MockThreads
mock_threads(m_threads
);
672 expect_work_queue_repeatedly(mock_threads
);
673 expect_add_event_after_repeatedly(mock_threads
);
675 MockImageDeleter mock_image_deleter
;
676 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
677 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
678 MockReplayStatusFormatter mock_replay_status_formatter
;
680 expect_get_or_send_update(mock_replay_status_formatter
);
683 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
684 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
686 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
687 "remote image id", 0);
688 EXPECT_CALL(mock_remote_journaler
, construct());
689 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
690 expect_shut_down(mock_remote_journaler
, 0);
692 create_image_replayer(mock_threads
, mock_image_deleter
);
694 C_SaferCond start_ctx
;
695 m_image_replayer
->start(&start_ctx
);
696 ASSERT_EQ(0, start_ctx
.wait());
699 TEST_F(TestMockImageReplayer
, LocalImageDNE
) {
700 create_local_image();
701 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
703 journal::MockJournaler mock_remote_journaler
;
704 MockThreads
mock_threads(m_threads
);
705 expect_work_queue_repeatedly(mock_threads
);
706 expect_add_event_after_repeatedly(mock_threads
);
708 MockImageDeleter mock_image_deleter
;
709 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
710 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
711 MockBootstrapRequest mock_bootstrap_request
;
712 MockReplayStatusFormatter mock_replay_status_formatter
;
714 expect_get_or_send_update(mock_replay_status_formatter
);
717 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
718 expect_send(mock_prepare_local_image_request
, "", "", -ENOENT
);
719 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
720 m_remote_image_ctx
->id
, 0);
721 EXPECT_CALL(mock_remote_journaler
, construct());
722 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EREMOTEIO
);
724 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
725 expect_shut_down(mock_remote_journaler
, 0);
727 create_image_replayer(mock_threads
, mock_image_deleter
);
729 C_SaferCond start_ctx
;
730 m_image_replayer
->start(&start_ctx
);
731 ASSERT_EQ(-EREMOTEIO
, start_ctx
.wait());
734 TEST_F(TestMockImageReplayer
, PrepareLocalImageError
) {
735 create_local_image();
736 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
738 MockThreads
mock_threads(m_threads
);
739 expect_work_queue_repeatedly(mock_threads
);
740 expect_add_event_after_repeatedly(mock_threads
);
742 MockImageDeleter mock_image_deleter
;
743 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
744 MockReplayStatusFormatter mock_replay_status_formatter
;
746 expect_get_or_send_update(mock_replay_status_formatter
);
749 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
750 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
751 "remote mirror uuid", -EINVAL
);
753 create_image_replayer(mock_threads
, mock_image_deleter
);
755 C_SaferCond start_ctx
;
756 m_image_replayer
->start(&start_ctx
);
757 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
760 TEST_F(TestMockImageReplayer
, GetRemoteImageIdDNE
) {
761 create_local_image();
762 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
764 MockThreads
mock_threads(m_threads
);
765 expect_work_queue_repeatedly(mock_threads
);
766 expect_add_event_after_repeatedly(mock_threads
);
768 MockImageDeleter mock_image_deleter
;
769 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
770 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
771 MockReplayStatusFormatter mock_replay_status_formatter
;
773 expect_get_or_send_update(mock_replay_status_formatter
);
776 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
777 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
778 "remote mirror uuid", 0);
779 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
781 expect_schedule_image_delete(mock_image_deleter
, "global image id", false);
783 create_image_replayer(mock_threads
, mock_image_deleter
);
785 C_SaferCond start_ctx
;
786 m_image_replayer
->start(&start_ctx
);
787 ASSERT_EQ(0, start_ctx
.wait());
790 TEST_F(TestMockImageReplayer
, GetRemoteImageIdNonLinkedDNE
) {
791 create_local_image();
792 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
794 MockThreads
mock_threads(m_threads
);
795 expect_work_queue_repeatedly(mock_threads
);
796 expect_add_event_after_repeatedly(mock_threads
);
798 MockImageDeleter mock_image_deleter
;
799 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
800 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
801 MockReplayStatusFormatter mock_replay_status_formatter
;
803 expect_get_or_send_update(mock_replay_status_formatter
);
806 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
807 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
808 "some other mirror uuid", 0);
809 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
812 create_image_replayer(mock_threads
, mock_image_deleter
);
814 C_SaferCond start_ctx
;
815 m_image_replayer
->start(&start_ctx
);
816 ASSERT_EQ(-ENOENT
, start_ctx
.wait());
819 TEST_F(TestMockImageReplayer
, GetRemoteImageIdError
) {
820 create_local_image();
821 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
823 MockThreads
mock_threads(m_threads
);
824 expect_work_queue_repeatedly(mock_threads
);
825 expect_add_event_after_repeatedly(mock_threads
);
827 MockImageDeleter mock_image_deleter
;
828 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
829 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
830 MockReplayStatusFormatter mock_replay_status_formatter
;
832 expect_get_or_send_update(mock_replay_status_formatter
);
835 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
836 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
837 "remote mirror uuid", 0);
838 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
839 m_remote_image_ctx
->id
, -EINVAL
);
841 create_image_replayer(mock_threads
, mock_image_deleter
);
843 C_SaferCond start_ctx
;
844 m_image_replayer
->start(&start_ctx
);
845 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
848 TEST_F(TestMockImageReplayer
, BootstrapError
) {
850 create_local_image();
851 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
853 journal::MockJournaler mock_remote_journaler
;
854 MockThreads
mock_threads(m_threads
);
855 expect_work_queue_repeatedly(mock_threads
);
856 expect_add_event_after_repeatedly(mock_threads
);
858 MockImageDeleter mock_image_deleter
;
859 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
860 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
861 MockBootstrapRequest mock_bootstrap_request
;
862 MockReplayStatusFormatter mock_replay_status_formatter
;
864 expect_get_or_send_update(mock_replay_status_formatter
);
867 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
868 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
869 "remote mirror uuid", 0);
870 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
871 m_remote_image_ctx
->id
, 0);
872 EXPECT_CALL(mock_remote_journaler
, construct());
873 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, -EINVAL
);
875 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
876 expect_shut_down(mock_remote_journaler
, 0);
878 create_image_replayer(mock_threads
, mock_image_deleter
);
880 C_SaferCond start_ctx
;
881 m_image_replayer
->start(&start_ctx
);
882 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
885 TEST_F(TestMockImageReplayer
, StartExternalReplayError
) {
888 create_local_image();
889 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
891 librbd::MockTestJournal mock_local_journal
;
892 mock_local_image_ctx
.journal
= &mock_local_journal
;
894 journal::MockJournaler mock_remote_journaler
;
895 MockThreads
mock_threads(m_threads
);
896 expect_work_queue_repeatedly(mock_threads
);
897 expect_add_event_after_repeatedly(mock_threads
);
899 MockImageDeleter mock_image_deleter
;
900 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
901 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
902 MockBootstrapRequest mock_bootstrap_request
;
903 MockReplay mock_local_replay
;
904 MockEventPreprocessor mock_event_preprocessor
;
905 MockReplayStatusFormatter mock_replay_status_formatter
;
907 expect_get_or_send_update(mock_replay_status_formatter
);
910 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
911 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
912 "remote mirror uuid", 0);
913 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
914 m_remote_image_ctx
->id
, 0);
915 EXPECT_CALL(mock_remote_journaler
, construct());
916 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
918 EXPECT_CALL(mock_local_journal
, add_listener(_
));
920 expect_init(mock_remote_journaler
, 0);
922 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
923 expect_get_cached_client(mock_remote_journaler
, 0);
925 expect_start_external_replay(mock_local_journal
, nullptr, -EINVAL
);
927 MockCloseImageRequest mock_close_local_image_request
;
928 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
929 expect_send(mock_close_local_image_request
, 0);
931 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
932 expect_shut_down(mock_remote_journaler
, 0);
934 create_image_replayer(mock_threads
, mock_image_deleter
);
936 C_SaferCond start_ctx
;
937 m_image_replayer
->start(&start_ctx
);
938 ASSERT_EQ(-EINVAL
, start_ctx
.wait());
939 ASSERT_EQ(image_replayer::HEALTH_STATE_ERROR
,
940 m_image_replayer
->get_health_state());
943 TEST_F(TestMockImageReplayer
, StopError
) {
946 create_local_image();
947 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
949 librbd::MockTestJournal mock_local_journal
;
950 mock_local_image_ctx
.journal
= &mock_local_journal
;
952 journal::MockJournaler mock_remote_journaler
;
953 MockThreads
mock_threads(m_threads
);
954 expect_work_queue_repeatedly(mock_threads
);
955 expect_add_event_after_repeatedly(mock_threads
);
957 MockImageDeleter mock_image_deleter
;
958 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
959 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
960 MockBootstrapRequest mock_bootstrap_request
;
961 MockReplay mock_local_replay
;
962 MockEventPreprocessor mock_event_preprocessor
;
963 MockReplayStatusFormatter mock_replay_status_formatter
;
965 expect_get_or_send_update(mock_replay_status_formatter
);
968 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
969 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
970 "remote mirror uuid", 0);
971 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
972 m_remote_image_ctx
->id
, 0);
973 EXPECT_CALL(mock_remote_journaler
, construct());
974 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
976 EXPECT_CALL(mock_local_journal
, add_listener(_
));
978 expect_init(mock_remote_journaler
, 0);
980 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
981 expect_get_cached_client(mock_remote_journaler
, 0);
983 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
985 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
987 create_image_replayer(mock_threads
, mock_image_deleter
);
989 C_SaferCond start_ctx
;
990 m_image_replayer
->start(&start_ctx
);
991 ASSERT_EQ(0, start_ctx
.wait());
993 // STOP (errors are ignored)
995 MockCloseImageRequest mock_close_local_image_request
;
997 expect_cancel_waiter(mock_image_deleter
);
998 expect_shut_down(mock_local_replay
, true, -EINVAL
);
999 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1000 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1001 expect_send(mock_close_local_image_request
, -EINVAL
);
1003 expect_stop_replay(mock_remote_journaler
, -EINVAL
);
1004 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1005 expect_shut_down(mock_remote_journaler
, -EINVAL
);
1007 C_SaferCond stop_ctx
;
1008 m_image_replayer
->stop(&stop_ctx
);
1009 ASSERT_EQ(0, stop_ctx
.wait());
1012 TEST_F(TestMockImageReplayer
, Replay
) {
1015 create_local_image();
1016 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
1018 librbd::MockTestJournal mock_local_journal
;
1019 mock_local_image_ctx
.journal
= &mock_local_journal
;
1021 journal::MockJournaler mock_remote_journaler
;
1022 MockThreads
mock_threads(m_threads
);
1023 expect_work_queue_repeatedly(mock_threads
);
1024 expect_add_event_after_repeatedly(mock_threads
);
1026 MockImageDeleter mock_image_deleter
;
1027 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
1028 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
1029 MockBootstrapRequest mock_bootstrap_request
;
1030 MockReplay mock_local_replay
;
1031 MockEventPreprocessor mock_event_preprocessor
;
1032 MockReplayStatusFormatter mock_replay_status_formatter
;
1033 ::journal::MockReplayEntry mock_replay_entry
;
1035 expect_get_or_send_update(mock_replay_status_formatter
);
1036 expect_get_commit_tid_in_debug(mock_replay_entry
);
1037 expect_committed(mock_remote_journaler
, 2);
1040 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
1041 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
1042 "remote mirror uuid", 0);
1043 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
1044 m_remote_image_ctx
->id
, 0);
1045 EXPECT_CALL(mock_remote_journaler
, construct());
1046 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
1048 EXPECT_CALL(mock_local_journal
, add_listener(_
));
1050 expect_init(mock_remote_journaler
, 0);
1052 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
1053 expect_get_cached_client(mock_remote_journaler
, 0);
1055 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1057 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
1059 create_image_replayer(mock_threads
, mock_image_deleter
);
1061 C_SaferCond start_ctx
;
1062 m_image_replayer
->start(&start_ctx
);
1063 ASSERT_EQ(0, start_ctx
.wait());
1067 cls::journal::Tag tag
=
1068 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1069 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1072 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1075 expect_shut_down(mock_local_replay
, false, 0);
1076 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1077 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1078 expect_get_tag(mock_remote_journaler
, tag
, 0);
1079 expect_allocate_tag(mock_local_journal
, 0);
1082 EXPECT_CALL(mock_replay_entry
, get_data());
1083 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1084 .WillOnce(Return(0));
1085 expect_preprocess(mock_event_preprocessor
, false, 0);
1086 expect_process(mock_local_replay
, 0, 0);
1088 // the next event with preprocess
1089 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1090 EXPECT_CALL(mock_replay_entry
, get_data());
1091 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1092 .WillOnce(Return(0));
1093 expect_preprocess(mock_event_preprocessor
, true, 0);
1094 expect_process(mock_local_replay
, 0, 0);
1096 // attempt to process the next event
1097 C_SaferCond replay_ctx
;
1098 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1101 m_image_replayer
->handle_replay_ready();
1102 ASSERT_EQ(0, replay_ctx
.wait());
1106 MockCloseImageRequest mock_close_local_image_request
;
1107 expect_cancel_waiter(mock_image_deleter
);
1108 expect_shut_down(mock_local_replay
, true, 0);
1109 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1110 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1111 expect_send(mock_close_local_image_request
, 0);
1113 expect_stop_replay(mock_remote_journaler
, 0);
1114 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1115 expect_shut_down(mock_remote_journaler
, 0);
1117 C_SaferCond stop_ctx
;
1118 m_image_replayer
->stop(&stop_ctx
);
1119 ASSERT_EQ(0, stop_ctx
.wait());
1122 TEST_F(TestMockImageReplayer
, DecodeError
) {
1125 create_local_image();
1126 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
1128 librbd::MockTestJournal mock_local_journal
;
1129 mock_local_image_ctx
.journal
= &mock_local_journal
;
1131 journal::MockJournaler mock_remote_journaler
;
1132 MockThreads
mock_threads(m_threads
);
1133 expect_work_queue_repeatedly(mock_threads
);
1134 expect_add_event_after_repeatedly(mock_threads
);
1136 MockImageDeleter mock_image_deleter
;
1137 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
1138 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
1139 MockBootstrapRequest mock_bootstrap_request
;
1140 MockReplay mock_local_replay
;
1141 MockEventPreprocessor mock_event_preprocessor
;
1142 MockReplayStatusFormatter mock_replay_status_formatter
;
1143 ::journal::MockReplayEntry mock_replay_entry
;
1145 expect_get_or_send_update(mock_replay_status_formatter
);
1146 expect_get_commit_tid_in_debug(mock_replay_entry
);
1149 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
1150 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
1151 "remote mirror uuid", 0);
1152 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
1153 m_remote_image_ctx
->id
, 0);
1154 EXPECT_CALL(mock_remote_journaler
, construct());
1155 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
1157 EXPECT_CALL(mock_local_journal
, add_listener(_
));
1159 expect_init(mock_remote_journaler
, 0);
1161 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
1162 expect_get_cached_client(mock_remote_journaler
, 0);
1164 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1166 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
1168 create_image_replayer(mock_threads
, mock_image_deleter
);
1170 C_SaferCond start_ctx
;
1171 m_image_replayer
->start(&start_ctx
);
1172 ASSERT_EQ(0, start_ctx
.wait());
1176 cls::journal::Tag tag
=
1177 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1178 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1181 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1184 expect_shut_down(mock_local_replay
, false, 0);
1185 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1186 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1187 expect_get_tag(mock_remote_journaler
, tag
, 0);
1188 expect_allocate_tag(mock_local_journal
, 0);
1191 EXPECT_CALL(mock_replay_entry
, get_data());
1192 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1193 .WillOnce(Return(-EINVAL
));
1196 expect_shut_down(mock_local_replay
, true, 0);
1197 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1198 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1200 MockCloseImageRequest mock_close_local_image_request
;
1201 C_SaferCond close_ctx
;
1202 EXPECT_CALL(mock_close_local_image_request
, send())
1203 .WillOnce(Invoke([&mock_close_local_image_request
, &close_ctx
]() {
1204 *mock_close_local_image_request
.image_ctx
= nullptr;
1205 mock_close_local_image_request
.on_finish
->complete(0);
1206 close_ctx
.complete(0);
1209 expect_stop_replay(mock_remote_journaler
, 0);
1210 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1211 expect_shut_down(mock_remote_journaler
, 0);
1214 m_image_replayer
->handle_replay_ready();
1215 ASSERT_EQ(0, close_ctx
.wait());
1217 while (!m_image_replayer
->is_stopped()) {
1222 TEST_F(TestMockImageReplayer
, DelayedReplay
) {
1226 create_local_image();
1227 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
1229 librbd::MockTestJournal mock_local_journal
;
1230 mock_local_image_ctx
.journal
= &mock_local_journal
;
1232 journal::MockJournaler mock_remote_journaler
;
1233 MockThreads
mock_threads(m_threads
);
1234 expect_work_queue_repeatedly(mock_threads
);
1235 expect_add_event_after_repeatedly(mock_threads
);
1237 MockImageDeleter mock_image_deleter
;
1238 MockPrepareLocalImageRequest mock_prepare_local_image_request
;
1239 MockPrepareRemoteImageRequest mock_prepare_remote_image_request
;
1240 MockBootstrapRequest mock_bootstrap_request
;
1241 MockReplay mock_local_replay
;
1242 MockEventPreprocessor mock_event_preprocessor
;
1243 MockReplayStatusFormatter mock_replay_status_formatter
;
1244 ::journal::MockReplayEntry mock_replay_entry
;
1246 expect_get_or_send_update(mock_replay_status_formatter
);
1247 expect_get_commit_tid_in_debug(mock_replay_entry
);
1248 expect_committed(mock_remote_journaler
, 1);
1251 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global image id", 0);
1252 expect_send(mock_prepare_local_image_request
, mock_local_image_ctx
.id
,
1253 "remote mirror uuid", 0);
1254 expect_send(mock_prepare_remote_image_request
, "remote mirror uuid",
1255 m_remote_image_ctx
->id
, 0);
1256 EXPECT_CALL(mock_remote_journaler
, construct());
1257 expect_send(mock_bootstrap_request
, mock_local_image_ctx
, false, 0);
1259 EXPECT_CALL(mock_local_journal
, add_listener(_
));
1261 expect_init(mock_remote_journaler
, 0);
1263 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
1264 expect_get_cached_client(mock_remote_journaler
, 0);
1266 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1268 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
));
1270 create_image_replayer(mock_threads
, mock_image_deleter
);
1272 C_SaferCond start_ctx
;
1273 m_image_replayer
->start(&start_ctx
);
1274 ASSERT_EQ(0, start_ctx
.wait());
1278 cls::journal::Tag tag
=
1279 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1280 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1283 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1286 expect_shut_down(mock_local_replay
, false, 0);
1287 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1288 expect_start_external_replay(mock_local_journal
, &mock_local_replay
, 0);
1289 expect_get_tag(mock_remote_journaler
, tag
, 0);
1290 expect_allocate_tag(mock_local_journal
, 0);
1292 // process with delay
1293 EXPECT_CALL(mock_replay_entry
, get_data());
1294 librbd::journal::EventEntry
event_entry(
1295 librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
1296 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1297 .WillOnce(DoAll(SetArgPointee
<1>(event_entry
),
1299 expect_preprocess(mock_event_preprocessor
, false, 0);
1300 expect_process(mock_local_replay
, 0, 0);
1302 // attempt to process the next event
1303 C_SaferCond replay_ctx
;
1304 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1307 mock_local_image_ctx
.mirroring_replay_delay
= 2;
1308 m_image_replayer
->handle_replay_ready();
1309 ASSERT_EQ(0, replay_ctx
.wait());
1311 // add a pending (delayed) entry before stop
1312 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1313 EXPECT_CALL(mock_replay_entry
, get_data());
1314 C_SaferCond decode_ctx
;
1315 EXPECT_CALL(mock_local_replay
, decode(_
, _
))
1316 .WillOnce(DoAll(Invoke([&decode_ctx
](bufferlist::iterator
* it
,
1317 librbd::journal::EventEntry
*e
) {
1318 decode_ctx
.complete(0);
1322 mock_local_image_ctx
.mirroring_replay_delay
= 10;
1323 m_image_replayer
->handle_replay_ready();
1324 ASSERT_EQ(0, decode_ctx
.wait());
1328 MockCloseImageRequest mock_close_local_image_request
;
1330 expect_cancel_waiter(mock_image_deleter
);
1331 expect_shut_down(mock_local_replay
, true, 0);
1332 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1333 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1334 expect_send(mock_close_local_image_request
, 0);
1336 expect_stop_replay(mock_remote_journaler
, 0);
1337 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1338 expect_shut_down(mock_remote_journaler
, 0);
1340 C_SaferCond stop_ctx
;
1341 m_image_replayer
->stop(&stop_ctx
);
1342 ASSERT_EQ(0, stop_ctx
.wait());
1346 } // namespace mirror