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