1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "librbd/journal/Types.h"
6 #include "librbd/journal/TypeTraits.h"
7 #include "tools/rbd_mirror/Threads.h"
8 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
9 #include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
10 #include "tools/rbd_mirror/image_replayer/Utils.h"
11 #include "tools/rbd_mirror/image_replayer/journal/Replayer.h"
12 #include "tools/rbd_mirror/image_replayer/journal/EventPreprocessor.h"
13 #include "tools/rbd_mirror/image_replayer/journal/ReplayStatusFormatter.h"
14 #include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
15 #include "test/journal/mock/MockJournaler.h"
16 #include "test/librbd/mock/MockImageCtx.h"
17 #include "test/rbd_mirror/mock/MockContextWQ.h"
18 #include "test/rbd_mirror/mock/MockSafeTimer.h"
19 #include <boost/intrusive_ptr.hpp>
25 struct MockTestJournal
;
27 struct MockTestImageCtx
: public librbd::MockImageCtx
{
28 explicit MockTestImageCtx(librbd::ImageCtx
&image_ctx
,
29 MockTestJournal
& mock_test_journal
)
30 : librbd::MockImageCtx(image_ctx
), journal(&mock_test_journal
) {
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 TypeTraits
<librbd::MockTestImageCtx
> {
48 typedef ::journal::MockJournaler Journaler
;
49 typedef ::journal::MockReplayEntryProxy ReplayEntry
;
53 struct Replay
<MockTestImageCtx
> {
54 MOCK_METHOD2(decode
, int(bufferlist::const_iterator
*, EventEntry
*));
55 MOCK_METHOD3(process
, void(const EventEntry
&, Context
*, Context
*));
56 MOCK_METHOD1(flush
, void(Context
*));
57 MOCK_METHOD2(shut_down
, void(bool, Context
*));
60 } // namespace journal
66 struct intrusive_ptr
<librbd::MockTestJournal
> {
69 intrusive_ptr(librbd::MockTestJournal
* mock_test_journal
)
70 : mock_test_journal(mock_test_journal
) {
73 librbd::MockTestJournal
* operator->() {
74 return mock_test_journal
;
78 mock_test_journal
= nullptr;
81 const librbd::MockTestJournal
* get() const {
82 return mock_test_journal
;
86 bool operator==(T
* t
) const {
87 return (mock_test_journal
== t
);
90 librbd::MockTestJournal
* mock_test_journal
= nullptr;
99 struct Threads
<librbd::MockTestImageCtx
> {
100 MockSafeTimer
*timer
;
101 ceph::mutex
&timer_lock
;
103 MockContextWQ
*work_queue
;
105 Threads(Threads
<librbd::ImageCtx
>* threads
)
106 : timer(new MockSafeTimer()),
107 timer_lock(threads
->timer_lock
),
108 work_queue(new MockContextWQ()) {
118 struct MockReplayerListener
: public image_replayer::ReplayerListener
{
119 MOCK_METHOD0(handle_notification
, void());
122 } // anonymous namespace
124 namespace image_replayer
{
127 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
128 static CloseImageRequest
* s_instance
;
129 librbd::MockTestImageCtx
**image_ctx
= nullptr;
130 Context
*on_finish
= nullptr;
132 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
133 Context
*on_finish
) {
134 ceph_assert(s_instance
!= nullptr);
135 s_instance
->image_ctx
= image_ctx
;
136 s_instance
->on_finish
= on_finish
;
140 CloseImageRequest() {
141 ceph_assert(s_instance
== nullptr);
145 ~CloseImageRequest() {
146 ceph_assert(s_instance
== this);
147 s_instance
= nullptr;
150 MOCK_METHOD0(send
, void());
153 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
158 struct EventPreprocessor
<librbd::MockTestImageCtx
> {
159 static EventPreprocessor
*s_instance
;
161 static EventPreprocessor
*create(librbd::MockTestImageCtx
&local_image_ctx
,
162 ::journal::MockJournaler
&remote_journaler
,
163 const std::string
&local_mirror_uuid
,
164 librbd::journal::MirrorPeerClientMeta
*client_meta
,
165 MockContextWQ
*work_queue
) {
166 ceph_assert(s_instance
!= nullptr);
170 static void destroy(EventPreprocessor
* processor
) {
173 EventPreprocessor() {
174 ceph_assert(s_instance
== nullptr);
178 ~EventPreprocessor() {
179 ceph_assert(s_instance
== this);
180 s_instance
= nullptr;
183 MOCK_METHOD1(is_required
, bool(const librbd::journal::EventEntry
&));
184 MOCK_METHOD2(preprocess
, void(librbd::journal::EventEntry
*, Context
*));
188 struct ReplayStatusFormatter
<librbd::MockTestImageCtx
> {
189 static ReplayStatusFormatter
* s_instance
;
191 static ReplayStatusFormatter
* create(::journal::MockJournaler
*journaler
,
192 const std::string
&mirror_uuid
) {
193 ceph_assert(s_instance
!= nullptr);
197 static void destroy(ReplayStatusFormatter
* formatter
) {
200 ReplayStatusFormatter() {
201 ceph_assert(s_instance
== nullptr);
205 ~ReplayStatusFormatter() {
206 ceph_assert(s_instance
== this);
207 s_instance
= nullptr;
210 MOCK_METHOD2(get_or_send_update
, bool(std::string
*description
, Context
*on_finish
));
214 struct StateBuilder
<librbd::MockTestImageCtx
> {
215 StateBuilder(librbd::MockTestImageCtx
& local_image_ctx
,
216 ::journal::MockJournaler
& remote_journaler
,
217 const librbd::journal::MirrorPeerClientMeta
& remote_client_meta
)
218 : local_image_ctx(&local_image_ctx
),
219 remote_journaler(&remote_journaler
),
220 remote_client_meta(remote_client_meta
) {
223 librbd::MockTestImageCtx
* local_image_ctx
;
224 std::string remote_mirror_uuid
= "remote mirror uuid";
225 ::journal::MockJournaler
* remote_journaler
= nullptr;
226 librbd::journal::MirrorPeerClientMeta remote_client_meta
;
229 EventPreprocessor
<librbd::MockTestImageCtx
>* EventPreprocessor
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
230 ReplayStatusFormatter
<librbd::MockTestImageCtx
>* ReplayStatusFormatter
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
232 } // namespace journal
233 } // namespace image_replayer
234 } // namespace mirror
237 #include "tools/rbd_mirror/image_replayer/journal/Replayer.cc"
241 namespace image_replayer
{
245 using ::testing::AtLeast
;
246 using ::testing::DoAll
;
247 using ::testing::InSequence
;
248 using ::testing::Invoke
;
249 using ::testing::MatcherCast
;
250 using ::testing::Return
;
251 using ::testing::ReturnArg
;
252 using ::testing::SaveArg
;
253 using ::testing::SetArgPointee
;
254 using ::testing::WithArg
;
256 class TestMockImageReplayerJournalReplayer
: public TestMockFixture
{
258 typedef Replayer
<librbd::MockTestImageCtx
> MockReplayer
;
259 typedef EventPreprocessor
<librbd::MockTestImageCtx
> MockEventPreprocessor
;
260 typedef ReplayStatusFormatter
<librbd::MockTestImageCtx
> MockReplayStatusFormatter
;
261 typedef StateBuilder
<librbd::MockTestImageCtx
> MockStateBuilder
;
262 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
263 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
264 typedef librbd::journal::Replay
<librbd::MockTestImageCtx
> MockReplay
;
266 void SetUp() override
{
267 TestMockFixture::SetUp();
270 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
271 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
274 bufferlist
encode_tag_data(const librbd::journal::TagData
&tag_data
) {
276 encode(tag_data
, bl
);
280 void expect_work_queue_repeatedly(MockThreads
&mock_threads
) {
281 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
282 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
283 m_threads
->work_queue
->queue(ctx
, r
);
287 void expect_add_event_after_repeatedly(MockThreads
&mock_threads
) {
288 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
290 DoAll(Invoke([this](double seconds
, Context
*ctx
) {
291 m_threads
->timer
->add_event_after(seconds
, ctx
);
294 EXPECT_CALL(*mock_threads
.timer
, cancel_event(_
))
296 Invoke([this](Context
*ctx
) {
297 return m_threads
->timer
->cancel_event(ctx
);
301 void expect_init(::journal::MockJournaler
&mock_journaler
, int r
) {
302 EXPECT_CALL(mock_journaler
, init(_
))
303 .WillOnce(CompleteContext(m_threads
->work_queue
, r
));
306 void expect_stop_replay(::journal::MockJournaler
&mock_journaler
, int r
) {
307 EXPECT_CALL(mock_journaler
, stop_replay(_
))
308 .WillOnce(CompleteContext(r
));
311 void expect_shut_down(MockReplay
&mock_replay
, bool cancel_ops
, int r
) {
312 EXPECT_CALL(mock_replay
, shut_down(cancel_ops
, _
))
313 .WillOnce(WithArg
<1>(CompleteContext(m_threads
->work_queue
, r
)));
316 void expect_get_cached_client(::journal::MockJournaler
&mock_journaler
,
317 const std::string
& client_id
,
318 const cls::journal::Client
& client
,
319 const librbd::journal::ClientMeta
& client_meta
,
321 librbd::journal::ClientData client_data
;
322 client_data
.client_meta
= client_meta
;
324 cls::journal::Client client_copy
{client
};
325 encode(client_data
, client_copy
.data
);
327 EXPECT_CALL(mock_journaler
, get_cached_client(client_id
, _
))
328 .WillOnce(DoAll(SetArgPointee
<1>(client_copy
),
332 void expect_start_external_replay(librbd::MockTestJournal
&mock_journal
,
333 MockReplay
*mock_replay
, int r
) {
334 EXPECT_CALL(mock_journal
, start_external_replay(_
, _
))
335 .WillOnce(DoAll(SetArgPointee
<0>(mock_replay
),
336 WithArg
<1>(CompleteContext(m_threads
->work_queue
, r
))));
339 void expect_is_tag_owner(librbd::MockTestJournal
&mock_journal
,
341 EXPECT_CALL(mock_journal
, is_tag_owner()).WillOnce(Return(is_owner
));
344 void expect_is_resync_requested(librbd::MockTestJournal
&mock_journal
,
345 int r
, bool resync_requested
) {
346 EXPECT_CALL(mock_journal
, is_resync_requested(_
)).WillOnce(
347 DoAll(SetArgPointee
<0>(resync_requested
),
351 void expect_get_commit_tid_in_debug(
352 ::journal::MockReplayEntry
&mock_replay_entry
) {
353 // It is used in debug messages and depends on debug level
354 EXPECT_CALL(mock_replay_entry
, get_commit_tid())
356 .WillRepeatedly(Return(0));
359 void expect_get_tag_tid_in_debug(librbd::MockTestJournal
&mock_journal
) {
360 // It is used in debug messages and depends on debug level
361 EXPECT_CALL(mock_journal
, get_tag_tid()).Times(AtLeast(0))
362 .WillRepeatedly(Return(0));
365 void expect_committed(::journal::MockReplayEntry
&mock_replay_entry
,
366 ::journal::MockJournaler
&mock_journaler
, int times
) {
367 EXPECT_CALL(mock_replay_entry
, get_data()).Times(times
);
368 EXPECT_CALL(mock_journaler
, committed(
369 MatcherCast
<const ::journal::MockReplayEntryProxy
&>(_
)))
373 void expect_try_pop_front(::journal::MockJournaler
&mock_journaler
,
374 uint64_t replay_tag_tid
, bool entries_available
) {
375 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
376 .WillOnce(DoAll(SetArgPointee
<0>(::journal::MockReplayEntryProxy()),
377 SetArgPointee
<1>(replay_tag_tid
),
378 Return(entries_available
)));
381 void expect_try_pop_front_return_no_entries(
382 ::journal::MockJournaler
&mock_journaler
, Context
*on_finish
) {
383 EXPECT_CALL(mock_journaler
, try_pop_front(_
, _
))
384 .WillOnce(DoAll(Invoke([on_finish
](::journal::MockReplayEntryProxy
*e
,
386 on_finish
->complete(0);
391 void expect_get_tag(::journal::MockJournaler
&mock_journaler
,
392 const cls::journal::Tag
&tag
, int r
) {
393 EXPECT_CALL(mock_journaler
, get_tag(_
, _
, _
))
394 .WillOnce(DoAll(SetArgPointee
<1>(tag
),
395 WithArg
<2>(CompleteContext(r
))));
398 void expect_allocate_tag(librbd::MockTestJournal
&mock_journal
, int r
) {
399 EXPECT_CALL(mock_journal
, allocate_tag(_
, _
, _
))
400 .WillOnce(WithArg
<2>(CompleteContext(r
)));
403 void expect_preprocess(MockEventPreprocessor
&mock_event_preprocessor
,
404 bool required
, int r
) {
405 EXPECT_CALL(mock_event_preprocessor
, is_required(_
))
406 .WillOnce(Return(required
));
408 EXPECT_CALL(mock_event_preprocessor
, preprocess(_
, _
))
409 .WillOnce(WithArg
<1>(CompleteContext(r
)));
413 void expect_process(MockReplay
&mock_replay
,
414 int on_ready_r
, int on_commit_r
) {
415 EXPECT_CALL(mock_replay
, process(_
, _
, _
))
416 .WillOnce(DoAll(WithArg
<1>(CompleteContext(on_ready_r
)),
417 WithArg
<2>(CompleteContext(on_commit_r
))));
420 void expect_flush(MockReplay
& mock_replay
, int r
) {
421 EXPECT_CALL(mock_replay
, flush(_
))
422 .WillOnce(CompleteContext(m_threads
->work_queue
, r
));
425 void expect_flush_commit_position(::journal::MockJournaler
& mock_journal
,
427 EXPECT_CALL(mock_journal
, flush_commit_position(_
))
428 .WillOnce(CompleteContext(m_threads
->work_queue
, r
));
431 void expect_get_tag_data(librbd::MockTestJournal
& mock_local_journal
,
432 const librbd::journal::TagData
& tag_data
) {
433 EXPECT_CALL(mock_local_journal
, get_tag_data())
434 .WillOnce(Return(tag_data
));
437 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
438 EXPECT_CALL(mock_close_image_request
, send())
439 .WillOnce(Invoke([this, &mock_close_image_request
, r
]() {
440 *mock_close_image_request
.image_ctx
= nullptr;
441 m_threads
->work_queue
->queue(mock_close_image_request
.on_finish
, r
);
445 void expect_notification(MockThreads
& mock_threads
,
446 MockReplayerListener
& mock_replayer_listener
) {
447 EXPECT_CALL(mock_replayer_listener
, handle_notification())
448 .WillOnce(Invoke([this]() {
449 std::unique_lock locker
{m_lock
};
455 int wait_for_notification() {
456 std::unique_lock locker
{m_lock
};
457 while (!m_notified
) {
458 if (m_cond
.wait_for(locker
, 10s
) == std::cv_status::timeout
) {
466 int init_entry_replayer(MockReplayer
& mock_replayer
,
467 MockThreads
& mock_threads
,
468 MockReplayerListener
& mock_replayer_listener
,
469 librbd::MockTestJournal
& mock_local_journal
,
470 ::journal::MockJournaler
& mock_remote_journaler
,
471 MockReplay
& mock_local_journal_replay
,
472 librbd::journal::Listener
** local_journal_listener
,
473 ::journal::ReplayHandler
** remote_replay_handler
,
474 ::journal::JournalMetadataListener
** remote_journal_listener
) {
475 expect_init(mock_remote_journaler
, 0);
476 EXPECT_CALL(mock_remote_journaler
, add_listener(_
))
477 .WillOnce(SaveArg
<0>(remote_journal_listener
));
478 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid", {},
479 {librbd::journal::MirrorPeerClientMeta
{}}, 0);
480 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
482 EXPECT_CALL(mock_local_journal
, add_listener(_
))
483 .WillOnce(SaveArg
<0>(local_journal_listener
));
484 expect_is_tag_owner(mock_local_journal
, false);
485 expect_is_resync_requested(mock_local_journal
, 0, false);
486 EXPECT_CALL(mock_remote_journaler
, start_live_replay(_
, _
))
487 .WillOnce(SaveArg
<0>(remote_replay_handler
));
488 expect_notification(mock_threads
, mock_replayer_listener
);
490 C_SaferCond init_ctx
;
491 mock_replayer
.init(&init_ctx
);
492 int r
= init_ctx
.wait();
497 return wait_for_notification();
500 int shut_down_entry_replayer(MockReplayer
& mock_replayer
,
501 MockThreads
& mock_threads
,
502 librbd::MockTestJournal
& mock_local_journal
,
503 ::journal::MockJournaler
& mock_remote_journaler
,
504 MockReplay
& mock_local_journal_replay
) {
505 expect_shut_down(mock_local_journal_replay
, true, 0);
506 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
507 EXPECT_CALL(mock_local_journal
, stop_external_replay());
508 MockCloseImageRequest mock_close_image_request
;
509 expect_send(mock_close_image_request
, 0);
510 expect_stop_replay(mock_remote_journaler
, 0);
511 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
513 C_SaferCond shutdown_ctx
;
514 mock_replayer
.shut_down(&shutdown_ctx
);
515 return shutdown_ctx
.wait();
518 librbd::ImageCtx
* m_local_image_ctx
= nullptr;
520 ceph::mutex m_lock
= ceph::make_mutex(
521 "TestMockImageReplayerJournalReplayer");
522 ceph::condition_variable m_cond
;
523 bool m_notified
= false;
526 TEST_F(TestMockImageReplayerJournalReplayer
, InitShutDown
) {
527 librbd::MockTestJournal mock_local_journal
;
528 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
530 ::journal::MockJournaler mock_remote_journaler
;
531 MockReplayerListener mock_replayer_listener
;
532 MockThreads mock_threads
{m_threads
};
533 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
534 mock_remote_journaler
,
536 MockReplayer mock_replayer
{
537 &mock_threads
, "local mirror uuid", &mock_state_builder
,
538 &mock_replayer_listener
};
540 expect_work_queue_repeatedly(mock_threads
);
544 MockReplay mock_local_journal_replay
;
545 MockEventPreprocessor mock_event_preprocessor
;
546 MockReplayStatusFormatter mock_replay_status_formatter
;
547 librbd::journal::Listener
* local_journal_listener
= nullptr;
548 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
549 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
550 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
551 mock_replayer_listener
, mock_local_journal
,
552 mock_remote_journaler
,
553 mock_local_journal_replay
,
554 &local_journal_listener
,
555 &remote_replay_handler
,
556 &remote_journaler_listener
));
558 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
560 mock_remote_journaler
,
561 mock_local_journal_replay
));
564 TEST_F(TestMockImageReplayerJournalReplayer
, InitNoLocalJournal
) {
565 librbd::MockTestJournal mock_local_journal
;
566 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
568 ::journal::MockJournaler mock_remote_journaler
;
569 MockReplayerListener mock_replayer_listener
;
570 MockThreads mock_threads
{m_threads
};
572 mock_local_image_ctx
.journal
= nullptr;
573 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
574 mock_remote_journaler
,
576 MockReplayer mock_replayer
{
577 &mock_threads
, "local mirror uuid", &mock_state_builder
,
578 &mock_replayer_listener
};
580 expect_work_queue_repeatedly(mock_threads
);
584 MockCloseImageRequest mock_close_image_request
;
585 expect_send(mock_close_image_request
, 0);
587 C_SaferCond init_ctx
;
588 mock_replayer
.init(&init_ctx
);
589 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
592 TEST_F(TestMockImageReplayerJournalReplayer
, InitRemoteJournalerError
) {
593 librbd::MockTestJournal mock_local_journal
;
594 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
596 ::journal::MockJournaler mock_remote_journaler
;
597 MockReplayerListener mock_replayer_listener
;
598 MockThreads mock_threads
{m_threads
};
599 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
600 mock_remote_journaler
,
602 MockReplayer mock_replayer
{
603 &mock_threads
, "local mirror uuid", &mock_state_builder
,
604 &mock_replayer_listener
};
606 expect_work_queue_repeatedly(mock_threads
);
610 expect_init(mock_remote_journaler
, -EINVAL
);
611 MockCloseImageRequest mock_close_image_request
;
612 expect_send(mock_close_image_request
, 0);
614 C_SaferCond init_ctx
;
615 mock_replayer
.init(&init_ctx
);
616 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
619 TEST_F(TestMockImageReplayerJournalReplayer
, InitRemoteJournalerGetClientError
) {
620 librbd::MockTestJournal mock_local_journal
;
621 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
623 ::journal::MockJournaler mock_remote_journaler
;
624 MockReplayerListener mock_replayer_listener
;
625 MockThreads mock_threads
{m_threads
};
626 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
627 mock_remote_journaler
,
629 MockReplayer mock_replayer
{
630 &mock_threads
, "local mirror uuid", &mock_state_builder
,
631 &mock_replayer_listener
};
633 expect_work_queue_repeatedly(mock_threads
);
637 expect_init(mock_remote_journaler
, 0);
638 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
639 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid", {},
640 {librbd::journal::MirrorPeerClientMeta
{}}, -EINVAL
);
641 MockCloseImageRequest mock_close_image_request
;
642 expect_send(mock_close_image_request
, 0);
643 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
645 C_SaferCond init_ctx
;
646 mock_replayer
.init(&init_ctx
);
647 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
650 TEST_F(TestMockImageReplayerJournalReplayer
, InitLocalJournalStartExternalReplayError
) {
651 librbd::MockTestJournal mock_local_journal
;
652 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
654 ::journal::MockJournaler mock_remote_journaler
;
655 MockReplayerListener mock_replayer_listener
;
656 MockThreads mock_threads
{m_threads
};
657 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
658 mock_remote_journaler
,
660 MockReplayer mock_replayer
{
661 &mock_threads
, "local mirror uuid", &mock_state_builder
,
662 &mock_replayer_listener
};
664 expect_work_queue_repeatedly(mock_threads
);
668 expect_init(mock_remote_journaler
, 0);
669 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
670 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid", {},
671 {librbd::journal::MirrorPeerClientMeta
{}}, 0);
672 expect_start_external_replay(mock_local_journal
, nullptr, -EINVAL
);
673 MockCloseImageRequest mock_close_image_request
;
674 expect_send(mock_close_image_request
, 0);
675 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
677 C_SaferCond init_ctx
;
678 mock_replayer
.init(&init_ctx
);
679 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
682 TEST_F(TestMockImageReplayerJournalReplayer
, InitIsPromoted
) {
683 librbd::MockTestJournal mock_local_journal
;
684 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
686 ::journal::MockJournaler mock_remote_journaler
;
687 MockReplayerListener mock_replayer_listener
;
688 MockThreads mock_threads
{m_threads
};
689 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
690 mock_remote_journaler
,
692 MockReplayer mock_replayer
{
693 &mock_threads
, "local mirror uuid", &mock_state_builder
,
694 &mock_replayer_listener
};
696 expect_work_queue_repeatedly(mock_threads
);
700 expect_init(mock_remote_journaler
, 0);
701 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
702 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid", {},
703 {librbd::journal::MirrorPeerClientMeta
{}}, 0);
704 MockReplay mock_local_journal_replay
;
705 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
707 EXPECT_CALL(mock_local_journal
, add_listener(_
));
708 expect_is_tag_owner(mock_local_journal
, true);
709 expect_notification(mock_threads
, mock_replayer_listener
);
711 C_SaferCond init_ctx
;
712 mock_replayer
.init(&init_ctx
);
713 ASSERT_EQ(0, init_ctx
.wait());
714 ASSERT_EQ(0, wait_for_notification());
716 expect_shut_down(mock_local_journal_replay
, true, 0);
717 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
718 EXPECT_CALL(mock_local_journal
, stop_external_replay());
719 MockCloseImageRequest mock_close_image_request
;
720 expect_send(mock_close_image_request
, 0);
721 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
723 C_SaferCond shutdown_ctx
;
724 mock_replayer
.shut_down(&shutdown_ctx
);
725 ASSERT_EQ(0, shutdown_ctx
.wait());
728 TEST_F(TestMockImageReplayerJournalReplayer
, InitDisconnected
) {
729 librbd::MockTestJournal mock_local_journal
;
730 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
732 mock_local_image_ctx
.config
.set_val("rbd_mirroring_resync_after_disconnect",
735 ::journal::MockJournaler mock_remote_journaler
;
736 MockReplayerListener mock_replayer_listener
;
737 MockThreads mock_threads
{m_threads
};
738 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
739 mock_remote_journaler
,
741 MockReplayer mock_replayer
{
742 &mock_threads
, "local mirror uuid", &mock_state_builder
,
743 &mock_replayer_listener
};
745 expect_work_queue_repeatedly(mock_threads
);
749 expect_init(mock_remote_journaler
, 0);
750 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
751 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid",
753 cls::journal::CLIENT_STATE_DISCONNECTED
},
754 {librbd::journal::MirrorPeerClientMeta
{
755 mock_local_image_ctx
.id
}}, 0);
756 MockCloseImageRequest mock_close_image_request
;
757 expect_send(mock_close_image_request
, 0);
758 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
760 C_SaferCond init_ctx
;
761 mock_replayer
.init(&init_ctx
);
762 ASSERT_EQ(-ENOTCONN
, init_ctx
.wait());
763 ASSERT_FALSE(mock_replayer
.is_resync_requested());
766 TEST_F(TestMockImageReplayerJournalReplayer
, InitDisconnectedResync
) {
767 librbd::MockTestJournal mock_local_journal
;
768 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
770 mock_local_image_ctx
.config
.set_val("rbd_mirroring_resync_after_disconnect",
773 ::journal::MockJournaler mock_remote_journaler
;
774 MockReplayerListener mock_replayer_listener
;
775 MockThreads mock_threads
{m_threads
};
776 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
777 mock_remote_journaler
,
779 MockReplayer mock_replayer
{
780 &mock_threads
, "local mirror uuid", &mock_state_builder
,
781 &mock_replayer_listener
};
783 expect_work_queue_repeatedly(mock_threads
);
787 expect_init(mock_remote_journaler
, 0);
788 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
789 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid",
791 cls::journal::CLIENT_STATE_DISCONNECTED
},
792 {librbd::journal::MirrorPeerClientMeta
{
793 mock_local_image_ctx
.id
}}, 0);
794 MockCloseImageRequest mock_close_image_request
;
795 expect_send(mock_close_image_request
, 0);
796 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
798 C_SaferCond init_ctx
;
799 mock_replayer
.init(&init_ctx
);
800 ASSERT_EQ(-ENOTCONN
, init_ctx
.wait());
801 ASSERT_TRUE(mock_replayer
.is_resync_requested());
804 TEST_F(TestMockImageReplayerJournalReplayer
, InitResyncRequested
) {
805 librbd::MockTestJournal mock_local_journal
;
806 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
808 ::journal::MockJournaler mock_remote_journaler
;
809 MockReplayerListener mock_replayer_listener
;
810 MockThreads mock_threads
{m_threads
};
811 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
812 mock_remote_journaler
,
814 MockReplayer mock_replayer
{
815 &mock_threads
, "local mirror uuid", &mock_state_builder
,
816 &mock_replayer_listener
};
818 expect_work_queue_repeatedly(mock_threads
);
822 expect_init(mock_remote_journaler
, 0);
823 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
824 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid", {},
825 {librbd::journal::MirrorPeerClientMeta
{}}, 0);
826 MockReplay mock_local_journal_replay
;
827 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
829 EXPECT_CALL(mock_local_journal
, add_listener(_
));
830 expect_is_tag_owner(mock_local_journal
, false);
831 expect_is_resync_requested(mock_local_journal
, 0, true);
832 expect_notification(mock_threads
, mock_replayer_listener
);
834 C_SaferCond init_ctx
;
835 mock_replayer
.init(&init_ctx
);
836 ASSERT_EQ(0, init_ctx
.wait());
837 ASSERT_EQ(0, wait_for_notification());
839 expect_shut_down(mock_local_journal_replay
, true, 0);
840 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
841 EXPECT_CALL(mock_local_journal
, stop_external_replay());
842 MockCloseImageRequest mock_close_image_request
;
843 expect_send(mock_close_image_request
, 0);
844 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
846 C_SaferCond shutdown_ctx
;
847 mock_replayer
.shut_down(&shutdown_ctx
);
848 ASSERT_EQ(0, shutdown_ctx
.wait());
851 TEST_F(TestMockImageReplayerJournalReplayer
, InitResyncRequestedError
) {
852 librbd::MockTestJournal mock_local_journal
;
853 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
855 ::journal::MockJournaler mock_remote_journaler
;
856 MockReplayerListener mock_replayer_listener
;
857 MockThreads mock_threads
{m_threads
};
858 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
859 mock_remote_journaler
,
861 MockReplayer mock_replayer
{
862 &mock_threads
, "local mirror uuid", &mock_state_builder
,
863 &mock_replayer_listener
};
865 expect_work_queue_repeatedly(mock_threads
);
869 expect_init(mock_remote_journaler
, 0);
870 EXPECT_CALL(mock_remote_journaler
, add_listener(_
));
871 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid", {},
872 {librbd::journal::MirrorPeerClientMeta
{}}, 0);
873 MockReplay mock_local_journal_replay
;
874 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
876 EXPECT_CALL(mock_local_journal
, add_listener(_
));
877 expect_is_tag_owner(mock_local_journal
, false);
878 expect_is_resync_requested(mock_local_journal
, -EINVAL
, false);
879 expect_notification(mock_threads
, mock_replayer_listener
);
881 C_SaferCond init_ctx
;
882 mock_replayer
.init(&init_ctx
);
883 ASSERT_EQ(0, init_ctx
.wait());
884 ASSERT_EQ(0, wait_for_notification());
885 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
887 expect_shut_down(mock_local_journal_replay
, true, 0);
888 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
889 EXPECT_CALL(mock_local_journal
, stop_external_replay());
890 MockCloseImageRequest mock_close_image_request
;
891 expect_send(mock_close_image_request
, 0);
892 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
894 C_SaferCond shutdown_ctx
;
895 mock_replayer
.shut_down(&shutdown_ctx
);
896 ASSERT_EQ(0, shutdown_ctx
.wait());
899 TEST_F(TestMockImageReplayerJournalReplayer
, ShutDownLocalJournalReplayError
) {
900 librbd::MockTestJournal mock_local_journal
;
901 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
903 ::journal::MockJournaler mock_remote_journaler
;
904 MockReplayerListener mock_replayer_listener
;
905 MockThreads mock_threads
{m_threads
};
906 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
907 mock_remote_journaler
,
909 MockReplayer mock_replayer
{
910 &mock_threads
, "local mirror uuid", &mock_state_builder
,
911 &mock_replayer_listener
};
913 expect_work_queue_repeatedly(mock_threads
);
917 MockReplay mock_local_journal_replay
;
918 MockEventPreprocessor mock_event_preprocessor
;
919 MockReplayStatusFormatter mock_replay_status_formatter
;
920 librbd::journal::Listener
* local_journal_listener
= nullptr;
921 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
922 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
923 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
924 mock_replayer_listener
, mock_local_journal
,
925 mock_remote_journaler
,
926 mock_local_journal_replay
,
927 &local_journal_listener
,
928 &remote_replay_handler
,
929 &remote_journaler_listener
));
931 expect_shut_down(mock_local_journal_replay
, true, -EINVAL
);
932 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
933 EXPECT_CALL(mock_local_journal
, stop_external_replay());
934 MockCloseImageRequest mock_close_image_request
;
935 expect_send(mock_close_image_request
, 0);
936 expect_stop_replay(mock_remote_journaler
, 0);
937 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
939 C_SaferCond shutdown_ctx
;
940 mock_replayer
.shut_down(&shutdown_ctx
);
941 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
944 TEST_F(TestMockImageReplayerJournalReplayer
, CloseLocalImageError
) {
945 librbd::MockTestJournal mock_local_journal
;
946 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
948 ::journal::MockJournaler mock_remote_journaler
;
949 MockReplayerListener mock_replayer_listener
;
950 MockThreads mock_threads
{m_threads
};
951 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
952 mock_remote_journaler
,
954 MockReplayer mock_replayer
{
955 &mock_threads
, "local mirror uuid", &mock_state_builder
,
956 &mock_replayer_listener
};
958 expect_work_queue_repeatedly(mock_threads
);
962 MockReplay mock_local_journal_replay
;
963 MockEventPreprocessor mock_event_preprocessor
;
964 MockReplayStatusFormatter mock_replay_status_formatter
;
965 librbd::journal::Listener
* local_journal_listener
= nullptr;
966 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
967 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
968 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
969 mock_replayer_listener
, mock_local_journal
,
970 mock_remote_journaler
,
971 mock_local_journal_replay
,
972 &local_journal_listener
,
973 &remote_replay_handler
,
974 &remote_journaler_listener
));
976 expect_shut_down(mock_local_journal_replay
, true, 0);
977 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
978 EXPECT_CALL(mock_local_journal
, stop_external_replay());
979 MockCloseImageRequest mock_close_image_request
;
980 expect_send(mock_close_image_request
, -EINVAL
);
981 expect_stop_replay(mock_remote_journaler
, 0);
982 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
984 C_SaferCond shutdown_ctx
;
985 mock_replayer
.shut_down(&shutdown_ctx
);
986 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
989 TEST_F(TestMockImageReplayerJournalReplayer
, StopRemoteJournalerError
) {
990 librbd::MockTestJournal mock_local_journal
;
991 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
993 ::journal::MockJournaler mock_remote_journaler
;
994 MockReplayerListener mock_replayer_listener
;
995 MockThreads mock_threads
{m_threads
};
996 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
997 mock_remote_journaler
,
999 MockReplayer mock_replayer
{
1000 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1001 &mock_replayer_listener
};
1003 expect_work_queue_repeatedly(mock_threads
);
1007 MockReplay mock_local_journal_replay
;
1008 MockEventPreprocessor mock_event_preprocessor
;
1009 MockReplayStatusFormatter mock_replay_status_formatter
;
1010 librbd::journal::Listener
* local_journal_listener
= nullptr;
1011 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1012 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1013 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1014 mock_replayer_listener
, mock_local_journal
,
1015 mock_remote_journaler
,
1016 mock_local_journal_replay
,
1017 &local_journal_listener
,
1018 &remote_replay_handler
,
1019 &remote_journaler_listener
));
1021 expect_shut_down(mock_local_journal_replay
, true, 0);
1022 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1023 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1024 MockCloseImageRequest mock_close_image_request
;
1025 expect_send(mock_close_image_request
, 0);
1026 expect_stop_replay(mock_remote_journaler
, -EPERM
);
1027 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1029 C_SaferCond shutdown_ctx
;
1030 mock_replayer
.shut_down(&shutdown_ctx
);
1031 ASSERT_EQ(-EPERM
, shutdown_ctx
.wait());
1034 TEST_F(TestMockImageReplayerJournalReplayer
, Replay
) {
1035 librbd::MockTestJournal mock_local_journal
;
1036 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1037 mock_local_journal
};
1038 ::journal::MockJournaler mock_remote_journaler
;
1039 MockReplayerListener mock_replayer_listener
;
1040 MockThreads mock_threads
{m_threads
};
1041 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1042 mock_remote_journaler
,
1044 MockReplayer mock_replayer
{
1045 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1046 &mock_replayer_listener
};
1048 ::journal::MockReplayEntry mock_replay_entry
;
1049 expect_work_queue_repeatedly(mock_threads
);
1050 expect_add_event_after_repeatedly(mock_threads
);
1051 expect_get_commit_tid_in_debug(mock_replay_entry
);
1052 expect_get_tag_tid_in_debug(mock_local_journal
);
1053 expect_committed(mock_replay_entry
, mock_remote_journaler
, 2);
1057 MockReplay mock_local_journal_replay
;
1058 MockEventPreprocessor mock_event_preprocessor
;
1059 MockReplayStatusFormatter mock_replay_status_formatter
;
1060 librbd::journal::Listener
* local_journal_listener
= nullptr;
1061 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1062 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1063 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1064 mock_replayer_listener
, mock_local_journal
,
1065 mock_remote_journaler
,
1066 mock_local_journal_replay
,
1067 &local_journal_listener
,
1068 &remote_replay_handler
,
1069 &remote_journaler_listener
));
1071 cls::journal::Tag tag
=
1072 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1073 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1076 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1079 expect_shut_down(mock_local_journal_replay
, false, 0);
1080 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1081 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1083 expect_get_tag(mock_remote_journaler
, tag
, 0);
1084 expect_allocate_tag(mock_local_journal
, 0);
1087 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
)).WillOnce(Return(0));
1088 expect_preprocess(mock_event_preprocessor
, false, 0);
1089 expect_process(mock_local_journal_replay
, 0, 0);
1091 // the next event with preprocess
1092 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1093 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
)).WillOnce(Return(0));
1094 expect_preprocess(mock_event_preprocessor
, true, 0);
1095 expect_process(mock_local_journal_replay
, 0, 0);
1097 // attempt to process the next event
1098 C_SaferCond replay_ctx
;
1099 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1102 remote_replay_handler
->handle_entries_available();
1103 ASSERT_EQ(0, replay_ctx
.wait());
1105 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1107 mock_remote_journaler
,
1108 mock_local_journal_replay
));
1111 TEST_F(TestMockImageReplayerJournalReplayer
, DecodeError
) {
1112 librbd::MockTestJournal mock_local_journal
;
1113 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1114 mock_local_journal
};
1115 ::journal::MockJournaler mock_remote_journaler
;
1116 MockReplayerListener mock_replayer_listener
;
1117 MockThreads mock_threads
{m_threads
};
1118 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1119 mock_remote_journaler
,
1121 MockReplayer mock_replayer
{
1122 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1123 &mock_replayer_listener
};
1125 ::journal::MockReplayEntry mock_replay_entry
;
1126 expect_work_queue_repeatedly(mock_threads
);
1127 expect_add_event_after_repeatedly(mock_threads
);
1128 expect_get_commit_tid_in_debug(mock_replay_entry
);
1129 expect_get_tag_tid_in_debug(mock_local_journal
);
1133 MockReplay mock_local_journal_replay
;
1134 MockEventPreprocessor mock_event_preprocessor
;
1135 MockReplayStatusFormatter mock_replay_status_formatter
;
1136 librbd::journal::Listener
* local_journal_listener
= nullptr;
1137 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1138 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1139 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1140 mock_replayer_listener
, mock_local_journal
,
1141 mock_remote_journaler
,
1142 mock_local_journal_replay
,
1143 &local_journal_listener
,
1144 &remote_replay_handler
,
1145 &remote_journaler_listener
));
1147 cls::journal::Tag tag
=
1148 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1149 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1152 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1155 expect_shut_down(mock_local_journal_replay
, false, 0);
1156 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1157 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1159 expect_get_tag(mock_remote_journaler
, tag
, 0);
1160 expect_allocate_tag(mock_local_journal
, 0);
1163 EXPECT_CALL(mock_replay_entry
, get_data());
1164 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
))
1165 .WillOnce(Return(-EINVAL
));
1166 expect_notification(mock_threads
, mock_replayer_listener
);
1169 remote_replay_handler
->handle_entries_available();
1170 wait_for_notification();
1172 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1174 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1176 mock_remote_journaler
,
1177 mock_local_journal_replay
));
1180 TEST_F(TestMockImageReplayerJournalReplayer
, DelayedReplay
) {
1181 librbd::MockTestJournal mock_local_journal
;
1182 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1183 mock_local_journal
};
1184 ::journal::MockJournaler mock_remote_journaler
;
1185 MockReplayerListener mock_replayer_listener
;
1186 MockThreads mock_threads
{m_threads
};
1187 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1188 mock_remote_journaler
,
1190 MockReplayer mock_replayer
{
1191 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1192 &mock_replayer_listener
};
1194 ::journal::MockReplayEntry mock_replay_entry
;
1195 expect_work_queue_repeatedly(mock_threads
);
1196 expect_add_event_after_repeatedly(mock_threads
);
1197 expect_get_commit_tid_in_debug(mock_replay_entry
);
1198 expect_get_tag_tid_in_debug(mock_local_journal
);
1199 expect_committed(mock_replay_entry
, mock_remote_journaler
, 1);
1203 MockReplay mock_local_journal_replay
;
1204 MockEventPreprocessor mock_event_preprocessor
;
1205 MockReplayStatusFormatter mock_replay_status_formatter
;
1206 librbd::journal::Listener
* local_journal_listener
= nullptr;
1207 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1208 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1209 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1210 mock_replayer_listener
, mock_local_journal
,
1211 mock_remote_journaler
,
1212 mock_local_journal_replay
,
1213 &local_journal_listener
,
1214 &remote_replay_handler
,
1215 &remote_journaler_listener
));
1217 cls::journal::Tag tag
=
1218 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1219 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1222 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1225 expect_shut_down(mock_local_journal_replay
, false, 0);
1226 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1227 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1229 expect_get_tag(mock_remote_journaler
, tag
, 0);
1230 expect_allocate_tag(mock_local_journal
, 0);
1232 // process with delay
1233 EXPECT_CALL(mock_replay_entry
, get_data());
1234 librbd::journal::EventEntry
event_entry(
1235 librbd::journal::AioDiscardEvent(123, 345, 0), ceph_clock_now());
1236 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
))
1237 .WillOnce(DoAll(SetArgPointee
<1>(event_entry
),
1240 Context
* delayed_task_ctx
= nullptr;
1241 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
1243 DoAll(Invoke([this, &delayed_task_ctx
](double seconds
, Context
*ctx
) {
1244 std::unique_lock locker
{m_lock
};
1245 delayed_task_ctx
= ctx
;
1246 m_cond
.notify_all();
1249 expect_preprocess(mock_event_preprocessor
, false, 0);
1250 expect_process(mock_local_journal_replay
, 0, 0);
1252 // attempt to process the next event
1253 C_SaferCond replay_ctx
;
1254 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
1257 mock_local_image_ctx
.mirroring_replay_delay
= 600;
1258 remote_replay_handler
->handle_entries_available();
1260 std::unique_lock locker
{m_lock
};
1261 while (delayed_task_ctx
== nullptr) {
1262 if (m_cond
.wait_for(locker
, 10s
) == std::cv_status::timeout
) {
1263 FAIL() << "timed out waiting for task";
1269 std::unique_lock timer_locker
{mock_threads
.timer_lock
};
1270 delayed_task_ctx
->complete(0);
1272 ASSERT_EQ(0, replay_ctx
.wait());
1274 // add a pending (delayed) entry before stop
1275 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1276 C_SaferCond decode_ctx
;
1277 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
))
1278 .WillOnce(DoAll(Invoke([&decode_ctx
](bufferlist::const_iterator
* it
,
1279 librbd::journal::EventEntry
*e
) {
1280 decode_ctx
.complete(0);
1284 remote_replay_handler
->handle_entries_available();
1285 ASSERT_EQ(0, decode_ctx
.wait());
1287 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1289 mock_remote_journaler
,
1290 mock_local_journal_replay
));
1293 TEST_F(TestMockImageReplayerJournalReplayer
, ReplayNoMemoryError
) {
1294 librbd::MockTestJournal mock_local_journal
;
1295 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1296 mock_local_journal
};
1297 ::journal::MockJournaler mock_remote_journaler
;
1298 MockReplayerListener mock_replayer_listener
;
1299 MockThreads mock_threads
{m_threads
};
1300 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1301 mock_remote_journaler
,
1303 MockReplayer mock_replayer
{
1304 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1305 &mock_replayer_listener
};
1307 expect_work_queue_repeatedly(mock_threads
);
1311 MockReplay mock_local_journal_replay
;
1312 MockEventPreprocessor mock_event_preprocessor
;
1313 MockReplayStatusFormatter mock_replay_status_formatter
;
1314 librbd::journal::Listener
* local_journal_listener
= nullptr;
1315 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1316 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1317 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1318 mock_replayer_listener
, mock_local_journal
,
1319 mock_remote_journaler
,
1320 mock_local_journal_replay
,
1321 &local_journal_listener
,
1322 &remote_replay_handler
,
1323 &remote_journaler_listener
));
1325 expect_notification(mock_threads
, mock_replayer_listener
);
1326 remote_replay_handler
->handle_complete(-ENOMEM
);
1328 wait_for_notification();
1329 ASSERT_EQ(false, mock_replayer
.is_replaying());
1330 ASSERT_EQ(-ENOMEM
, mock_replayer
.get_error_code());
1332 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1334 mock_remote_journaler
,
1335 mock_local_journal_replay
));
1338 TEST_F(TestMockImageReplayerJournalReplayer
, LocalJournalForcePromoted
) {
1339 librbd::MockTestJournal mock_local_journal
;
1340 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1341 mock_local_journal
};
1342 ::journal::MockJournaler mock_remote_journaler
;
1343 MockReplayerListener mock_replayer_listener
;
1344 MockThreads mock_threads
{m_threads
};
1345 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1346 mock_remote_journaler
,
1348 MockReplayer mock_replayer
{
1349 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1350 &mock_replayer_listener
};
1352 expect_work_queue_repeatedly(mock_threads
);
1356 MockReplay mock_local_journal_replay
;
1357 MockEventPreprocessor mock_event_preprocessor
;
1358 MockReplayStatusFormatter mock_replay_status_formatter
;
1359 librbd::journal::Listener
* local_journal_listener
= nullptr;
1360 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1361 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1362 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1363 mock_replayer_listener
, mock_local_journal
,
1364 mock_remote_journaler
,
1365 mock_local_journal_replay
,
1366 &local_journal_listener
,
1367 &remote_replay_handler
,
1368 &remote_journaler_listener
));
1370 expect_notification(mock_threads
, mock_replayer_listener
);
1371 local_journal_listener
->handle_promoted();
1372 wait_for_notification();
1374 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1376 mock_remote_journaler
,
1377 mock_local_journal_replay
));
1380 TEST_F(TestMockImageReplayerJournalReplayer
, LocalJournalResyncRequested
) {
1381 librbd::MockTestJournal mock_local_journal
;
1382 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1383 mock_local_journal
};
1384 ::journal::MockJournaler mock_remote_journaler
;
1385 MockReplayerListener mock_replayer_listener
;
1386 MockThreads mock_threads
{m_threads
};
1387 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1388 mock_remote_journaler
,
1390 MockReplayer mock_replayer
{
1391 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1392 &mock_replayer_listener
};
1394 expect_work_queue_repeatedly(mock_threads
);
1398 MockReplay mock_local_journal_replay
;
1399 MockEventPreprocessor mock_event_preprocessor
;
1400 MockReplayStatusFormatter mock_replay_status_formatter
;
1401 librbd::journal::Listener
* local_journal_listener
= nullptr;
1402 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1403 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1404 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1405 mock_replayer_listener
, mock_local_journal
,
1406 mock_remote_journaler
,
1407 mock_local_journal_replay
,
1408 &local_journal_listener
,
1409 &remote_replay_handler
,
1410 &remote_journaler_listener
));
1412 expect_notification(mock_threads
, mock_replayer_listener
);
1413 local_journal_listener
->handle_resync();
1414 wait_for_notification();
1416 ASSERT_TRUE(mock_replayer
.is_resync_requested());
1418 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1420 mock_remote_journaler
,
1421 mock_local_journal_replay
));
1424 TEST_F(TestMockImageReplayerJournalReplayer
, RemoteJournalDisconnected
) {
1425 librbd::MockTestJournal mock_local_journal
;
1426 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1427 mock_local_journal
};
1428 mock_local_image_ctx
.config
.set_val("rbd_mirroring_resync_after_disconnect",
1431 ::journal::MockJournaler mock_remote_journaler
;
1432 MockReplayerListener mock_replayer_listener
;
1433 MockThreads mock_threads
{m_threads
};
1434 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1435 mock_remote_journaler
,
1437 MockReplayer mock_replayer
{
1438 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1439 &mock_replayer_listener
};
1441 expect_work_queue_repeatedly(mock_threads
);
1445 MockReplay mock_local_journal_replay
;
1446 MockEventPreprocessor mock_event_preprocessor
;
1447 MockReplayStatusFormatter mock_replay_status_formatter
;
1448 librbd::journal::Listener
* local_journal_listener
= nullptr;
1449 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1450 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1451 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1452 mock_replayer_listener
, mock_local_journal
,
1453 mock_remote_journaler
,
1454 mock_local_journal_replay
,
1455 &local_journal_listener
,
1456 &remote_replay_handler
,
1457 &remote_journaler_listener
));
1459 expect_get_cached_client(mock_remote_journaler
, "local mirror uuid",
1461 cls::journal::CLIENT_STATE_DISCONNECTED
},
1462 {librbd::journal::MirrorPeerClientMeta
{
1463 mock_local_image_ctx
.id
}}, 0);
1464 expect_notification(mock_threads
, mock_replayer_listener
);
1466 remote_journaler_listener
->handle_update(nullptr);
1467 wait_for_notification();
1469 ASSERT_EQ(-ENOTCONN
, mock_replayer
.get_error_code());
1470 ASSERT_FALSE(mock_replayer
.is_replaying());
1471 ASSERT_TRUE(mock_replayer
.is_resync_requested());
1473 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1475 mock_remote_journaler
,
1476 mock_local_journal_replay
));
1479 TEST_F(TestMockImageReplayerJournalReplayer
, Flush
) {
1480 librbd::MockTestJournal mock_local_journal
;
1481 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1482 mock_local_journal
};
1483 ::journal::MockJournaler mock_remote_journaler
;
1484 MockReplayerListener mock_replayer_listener
;
1485 MockThreads mock_threads
{m_threads
};
1486 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1487 mock_remote_journaler
,
1489 MockReplayer mock_replayer
{
1490 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1491 &mock_replayer_listener
};
1493 expect_work_queue_repeatedly(mock_threads
);
1497 MockReplay mock_local_journal_replay
;
1498 MockEventPreprocessor mock_event_preprocessor
;
1499 MockReplayStatusFormatter mock_replay_status_formatter
;
1500 librbd::journal::Listener
* local_journal_listener
= nullptr;
1501 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1502 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1503 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1504 mock_replayer_listener
, mock_local_journal
,
1505 mock_remote_journaler
,
1506 mock_local_journal_replay
,
1507 &local_journal_listener
,
1508 &remote_replay_handler
,
1509 &remote_journaler_listener
));
1511 expect_flush(mock_local_journal_replay
, 0);
1512 expect_flush_commit_position(mock_remote_journaler
, 0);
1515 mock_replayer
.flush(&ctx
);
1516 ASSERT_EQ(0, ctx
.wait());
1518 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1520 mock_remote_journaler
,
1521 mock_local_journal_replay
));
1524 TEST_F(TestMockImageReplayerJournalReplayer
, FlushError
) {
1525 librbd::MockTestJournal mock_local_journal
;
1526 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1527 mock_local_journal
};
1528 ::journal::MockJournaler mock_remote_journaler
;
1529 MockReplayerListener mock_replayer_listener
;
1530 MockThreads mock_threads
{m_threads
};
1531 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1532 mock_remote_journaler
,
1534 MockReplayer mock_replayer
{
1535 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1536 &mock_replayer_listener
};
1538 expect_work_queue_repeatedly(mock_threads
);
1542 MockReplay mock_local_journal_replay
;
1543 MockEventPreprocessor mock_event_preprocessor
;
1544 MockReplayStatusFormatter mock_replay_status_formatter
;
1545 librbd::journal::Listener
* local_journal_listener
= nullptr;
1546 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1547 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1548 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1549 mock_replayer_listener
, mock_local_journal
,
1550 mock_remote_journaler
,
1551 mock_local_journal_replay
,
1552 &local_journal_listener
,
1553 &remote_replay_handler
,
1554 &remote_journaler_listener
));
1556 expect_flush(mock_local_journal_replay
, -EINVAL
);
1559 mock_replayer
.flush(&ctx
);
1560 ASSERT_EQ(-EINVAL
, ctx
.wait());
1562 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1564 mock_remote_journaler
,
1565 mock_local_journal_replay
));
1568 TEST_F(TestMockImageReplayerJournalReplayer
, FlushCommitPositionError
) {
1569 librbd::MockTestJournal mock_local_journal
;
1570 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1571 mock_local_journal
};
1572 ::journal::MockJournaler mock_remote_journaler
;
1573 MockReplayerListener mock_replayer_listener
;
1574 MockThreads mock_threads
{m_threads
};
1575 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1576 mock_remote_journaler
,
1578 MockReplayer mock_replayer
{
1579 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1580 &mock_replayer_listener
};
1582 expect_work_queue_repeatedly(mock_threads
);
1586 MockReplay mock_local_journal_replay
;
1587 MockEventPreprocessor mock_event_preprocessor
;
1588 MockReplayStatusFormatter mock_replay_status_formatter
;
1589 librbd::journal::Listener
* local_journal_listener
= nullptr;
1590 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1591 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1592 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1593 mock_replayer_listener
, mock_local_journal
,
1594 mock_remote_journaler
,
1595 mock_local_journal_replay
,
1596 &local_journal_listener
,
1597 &remote_replay_handler
,
1598 &remote_journaler_listener
));
1600 expect_flush(mock_local_journal_replay
, 0);
1601 expect_flush_commit_position(mock_remote_journaler
, -EINVAL
);
1604 mock_replayer
.flush(&ctx
);
1605 ASSERT_EQ(-EINVAL
, ctx
.wait());
1607 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1609 mock_remote_journaler
,
1610 mock_local_journal_replay
));
1614 TEST_F(TestMockImageReplayerJournalReplayer
, ReplayFlushShutDownError
) {
1615 librbd::MockTestJournal mock_local_journal
;
1616 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1617 mock_local_journal
};
1618 ::journal::MockJournaler mock_remote_journaler
;
1619 MockReplayerListener mock_replayer_listener
;
1620 MockThreads mock_threads
{m_threads
};
1621 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1622 mock_remote_journaler
,
1624 MockReplayer mock_replayer
{
1625 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1626 &mock_replayer_listener
};
1628 ::journal::MockReplayEntry mock_replay_entry
;
1629 expect_get_commit_tid_in_debug(mock_replay_entry
);
1630 expect_work_queue_repeatedly(mock_threads
);
1634 MockReplay mock_local_journal_replay
;
1635 MockEventPreprocessor mock_event_preprocessor
;
1636 MockReplayStatusFormatter mock_replay_status_formatter
;
1637 librbd::journal::Listener
* local_journal_listener
= nullptr;
1638 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1639 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1640 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1641 mock_replayer_listener
, mock_local_journal
,
1642 mock_remote_journaler
,
1643 mock_local_journal_replay
,
1644 &local_journal_listener
,
1645 &remote_replay_handler
,
1646 &remote_journaler_listener
));
1648 expect_try_pop_front(mock_remote_journaler
, 1, true);
1649 expect_shut_down(mock_local_journal_replay
, false, -EINVAL
);
1650 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1651 expect_notification(mock_threads
, mock_replayer_listener
);
1652 remote_replay_handler
->handle_entries_available();
1654 wait_for_notification();
1655 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1657 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1658 MockCloseImageRequest mock_close_image_request
;
1659 expect_send(mock_close_image_request
, 0);
1660 expect_stop_replay(mock_remote_journaler
, 0);
1661 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1663 C_SaferCond shutdown_ctx
;
1664 mock_replayer
.shut_down(&shutdown_ctx
);
1665 ASSERT_EQ(0, shutdown_ctx
.wait());
1668 TEST_F(TestMockImageReplayerJournalReplayer
, ReplayFlushStartError
) {
1669 librbd::MockTestJournal mock_local_journal
;
1670 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1671 mock_local_journal
};
1672 ::journal::MockJournaler mock_remote_journaler
;
1673 MockReplayerListener mock_replayer_listener
;
1674 MockThreads mock_threads
{m_threads
};
1675 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1676 mock_remote_journaler
,
1678 MockReplayer mock_replayer
{
1679 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1680 &mock_replayer_listener
};
1682 ::journal::MockReplayEntry mock_replay_entry
;
1683 expect_get_commit_tid_in_debug(mock_replay_entry
);
1684 expect_work_queue_repeatedly(mock_threads
);
1688 MockReplay mock_local_journal_replay
;
1689 MockEventPreprocessor mock_event_preprocessor
;
1690 MockReplayStatusFormatter mock_replay_status_formatter
;
1691 librbd::journal::Listener
* local_journal_listener
= nullptr;
1692 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1693 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1694 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1695 mock_replayer_listener
, mock_local_journal
,
1696 mock_remote_journaler
,
1697 mock_local_journal_replay
,
1698 &local_journal_listener
,
1699 &remote_replay_handler
,
1700 &remote_journaler_listener
));
1702 expect_try_pop_front(mock_remote_journaler
, 1, true);
1703 expect_shut_down(mock_local_journal_replay
, false, 0);
1704 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1705 expect_start_external_replay(mock_local_journal
, nullptr, -EINVAL
);
1706 expect_notification(mock_threads
, mock_replayer_listener
);
1707 remote_replay_handler
->handle_entries_available();
1709 wait_for_notification();
1710 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1712 EXPECT_CALL(mock_local_journal
, remove_listener(_
));
1713 MockCloseImageRequest mock_close_image_request
;
1714 expect_send(mock_close_image_request
, 0);
1715 expect_stop_replay(mock_remote_journaler
, 0);
1716 EXPECT_CALL(mock_remote_journaler
, remove_listener(_
));
1718 C_SaferCond shutdown_ctx
;
1719 mock_replayer
.shut_down(&shutdown_ctx
);
1720 ASSERT_EQ(0, shutdown_ctx
.wait());
1723 TEST_F(TestMockImageReplayerJournalReplayer
, GetTagError
) {
1724 librbd::MockTestJournal mock_local_journal
;
1725 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1726 mock_local_journal
};
1727 ::journal::MockJournaler mock_remote_journaler
;
1728 MockReplayerListener mock_replayer_listener
;
1729 MockThreads mock_threads
{m_threads
};
1730 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1731 mock_remote_journaler
,
1733 MockReplayer mock_replayer
{
1734 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1735 &mock_replayer_listener
};
1737 ::journal::MockReplayEntry mock_replay_entry
;
1738 expect_get_commit_tid_in_debug(mock_replay_entry
);
1739 expect_work_queue_repeatedly(mock_threads
);
1743 MockReplay mock_local_journal_replay
;
1744 MockEventPreprocessor mock_event_preprocessor
;
1745 MockReplayStatusFormatter mock_replay_status_formatter
;
1746 librbd::journal::Listener
* local_journal_listener
= nullptr;
1747 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1748 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1749 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1750 mock_replayer_listener
, mock_local_journal
,
1751 mock_remote_journaler
,
1752 mock_local_journal_replay
,
1753 &local_journal_listener
,
1754 &remote_replay_handler
,
1755 &remote_journaler_listener
));
1757 cls::journal::Tag tag
=
1758 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1759 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1761 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1762 expect_shut_down(mock_local_journal_replay
, false, 0);
1763 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1764 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1766 expect_get_tag(mock_remote_journaler
, tag
, -EINVAL
);
1767 expect_notification(mock_threads
, mock_replayer_listener
);
1768 remote_replay_handler
->handle_entries_available();
1770 wait_for_notification();
1771 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1773 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1775 mock_remote_journaler
,
1776 mock_local_journal_replay
));
1779 TEST_F(TestMockImageReplayerJournalReplayer
, AllocateTagDemotion
) {
1780 librbd::MockTestJournal mock_local_journal
;
1781 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1782 mock_local_journal
};
1783 ::journal::MockJournaler mock_remote_journaler
;
1784 MockReplayerListener mock_replayer_listener
;
1785 MockThreads mock_threads
{m_threads
};
1786 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1787 mock_remote_journaler
,
1789 MockReplayer mock_replayer
{
1790 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1791 &mock_replayer_listener
};
1793 ::journal::MockReplayEntry mock_replay_entry
;
1794 expect_work_queue_repeatedly(mock_threads
);
1795 expect_notification(mock_threads
, mock_replayer_listener
);
1796 expect_get_commit_tid_in_debug(mock_replay_entry
);
1797 expect_get_tag_tid_in_debug(mock_local_journal
);
1798 expect_committed(mock_replay_entry
, mock_remote_journaler
, 1);
1802 MockReplay mock_local_journal_replay
;
1803 MockEventPreprocessor mock_event_preprocessor
;
1804 MockReplayStatusFormatter mock_replay_status_formatter
;
1805 librbd::journal::Listener
* local_journal_listener
= nullptr;
1806 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1807 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1808 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1809 mock_replayer_listener
, mock_local_journal
,
1810 mock_remote_journaler
,
1811 mock_local_journal_replay
,
1812 &local_journal_listener
,
1813 &remote_replay_handler
,
1814 &remote_journaler_listener
));
1816 cls::journal::Tag tag
=
1817 {1, 0, encode_tag_data({librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
1818 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1821 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1822 expect_shut_down(mock_local_journal_replay
, false, 0);
1823 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1824 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1826 expect_get_tag(mock_remote_journaler
, tag
, 0);
1827 expect_get_tag_data(mock_local_journal
, {});
1828 expect_allocate_tag(mock_local_journal
, 0);
1829 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
)).WillOnce(Return(0));
1830 expect_preprocess(mock_event_preprocessor
, false, 0);
1831 expect_process(mock_local_journal_replay
, 0, 0);
1833 remote_replay_handler
->handle_entries_available();
1834 wait_for_notification();
1835 ASSERT_FALSE(mock_replayer
.is_replaying());
1837 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1839 mock_remote_journaler
,
1840 mock_local_journal_replay
));
1843 TEST_F(TestMockImageReplayerJournalReplayer
, AllocateTagError
) {
1844 librbd::MockTestJournal mock_local_journal
;
1845 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1846 mock_local_journal
};
1847 ::journal::MockJournaler mock_remote_journaler
;
1848 MockReplayerListener mock_replayer_listener
;
1849 MockThreads mock_threads
{m_threads
};
1850 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1851 mock_remote_journaler
,
1853 MockReplayer mock_replayer
{
1854 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1855 &mock_replayer_listener
};
1857 ::journal::MockReplayEntry mock_replay_entry
;
1858 expect_work_queue_repeatedly(mock_threads
);
1859 expect_get_commit_tid_in_debug(mock_replay_entry
);
1860 expect_get_tag_tid_in_debug(mock_local_journal
);
1864 MockReplay mock_local_journal_replay
;
1865 MockEventPreprocessor mock_event_preprocessor
;
1866 MockReplayStatusFormatter mock_replay_status_formatter
;
1867 librbd::journal::Listener
* local_journal_listener
= nullptr;
1868 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1869 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1870 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1871 mock_replayer_listener
, mock_local_journal
,
1872 mock_remote_journaler
,
1873 mock_local_journal_replay
,
1874 &local_journal_listener
,
1875 &remote_replay_handler
,
1876 &remote_journaler_listener
));
1878 cls::journal::Tag tag
=
1879 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1880 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1883 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1884 expect_shut_down(mock_local_journal_replay
, false, 0);
1885 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1886 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1888 expect_get_tag(mock_remote_journaler
, tag
, 0);
1889 expect_allocate_tag(mock_local_journal
, -EINVAL
);
1890 expect_notification(mock_threads
, mock_replayer_listener
);
1891 remote_replay_handler
->handle_entries_available();
1893 wait_for_notification();
1894 ASSERT_FALSE(mock_replayer
.is_replaying());
1895 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1897 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1899 mock_remote_journaler
,
1900 mock_local_journal_replay
));
1903 TEST_F(TestMockImageReplayerJournalReplayer
, PreprocessError
) {
1904 librbd::MockTestJournal mock_local_journal
;
1905 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1906 mock_local_journal
};
1907 ::journal::MockJournaler mock_remote_journaler
;
1908 MockReplayerListener mock_replayer_listener
;
1909 MockThreads mock_threads
{m_threads
};
1910 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1911 mock_remote_journaler
,
1913 MockReplayer mock_replayer
{
1914 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1915 &mock_replayer_listener
};
1917 ::journal::MockReplayEntry mock_replay_entry
;
1918 expect_work_queue_repeatedly(mock_threads
);
1919 expect_get_commit_tid_in_debug(mock_replay_entry
);
1920 expect_get_tag_tid_in_debug(mock_local_journal
);
1924 MockReplay mock_local_journal_replay
;
1925 MockEventPreprocessor mock_event_preprocessor
;
1926 MockReplayStatusFormatter mock_replay_status_formatter
;
1927 librbd::journal::Listener
* local_journal_listener
= nullptr;
1928 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1929 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1930 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1931 mock_replayer_listener
, mock_local_journal
,
1932 mock_remote_journaler
,
1933 mock_local_journal_replay
,
1934 &local_journal_listener
,
1935 &remote_replay_handler
,
1936 &remote_journaler_listener
));
1938 cls::journal::Tag tag
=
1939 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1940 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
1943 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
1944 expect_shut_down(mock_local_journal_replay
, false, 0);
1945 EXPECT_CALL(mock_local_journal
, stop_external_replay());
1946 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
1948 expect_get_tag(mock_remote_journaler
, tag
, 0);
1949 expect_allocate_tag(mock_local_journal
, 0);
1950 EXPECT_CALL(mock_replay_entry
, get_data());
1951 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
)).WillOnce(Return(0));
1952 expect_preprocess(mock_event_preprocessor
, true, -EINVAL
);
1954 expect_notification(mock_threads
, mock_replayer_listener
);
1955 remote_replay_handler
->handle_entries_available();
1957 wait_for_notification();
1958 ASSERT_FALSE(mock_replayer
.is_replaying());
1959 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1961 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1963 mock_remote_journaler
,
1964 mock_local_journal_replay
));
1967 TEST_F(TestMockImageReplayerJournalReplayer
, ProcessError
) {
1968 librbd::MockTestJournal mock_local_journal
;
1969 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
1970 mock_local_journal
};
1971 ::journal::MockJournaler mock_remote_journaler
;
1972 MockReplayerListener mock_replayer_listener
;
1973 MockThreads mock_threads
{m_threads
};
1974 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1975 mock_remote_journaler
,
1977 MockReplayer mock_replayer
{
1978 &mock_threads
, "local mirror uuid", &mock_state_builder
,
1979 &mock_replayer_listener
};
1981 ::journal::MockReplayEntry mock_replay_entry
;
1982 expect_work_queue_repeatedly(mock_threads
);
1983 expect_get_commit_tid_in_debug(mock_replay_entry
);
1984 expect_get_tag_tid_in_debug(mock_local_journal
);
1985 expect_notification(mock_threads
, mock_replayer_listener
);
1989 MockReplay mock_local_journal_replay
;
1990 MockEventPreprocessor mock_event_preprocessor
;
1991 MockReplayStatusFormatter mock_replay_status_formatter
;
1992 librbd::journal::Listener
* local_journal_listener
= nullptr;
1993 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
1994 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
1995 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1996 mock_replayer_listener
, mock_local_journal
,
1997 mock_remote_journaler
,
1998 mock_local_journal_replay
,
1999 &local_journal_listener
,
2000 &remote_replay_handler
,
2001 &remote_journaler_listener
));
2003 cls::journal::Tag tag
=
2004 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
2005 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
2008 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
2009 expect_shut_down(mock_local_journal_replay
, false, 0);
2010 EXPECT_CALL(mock_local_journal
, stop_external_replay());
2011 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
2013 expect_get_tag(mock_remote_journaler
, tag
, 0);
2014 expect_allocate_tag(mock_local_journal
, 0);
2015 EXPECT_CALL(mock_replay_entry
, get_data());
2016 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
)).WillOnce(Return(0));
2017 expect_preprocess(mock_event_preprocessor
, false, 0);
2018 expect_process(mock_local_journal_replay
, 0, -EINVAL
);
2020 // attempt to process the next event
2021 C_SaferCond replay_ctx
;
2022 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
2023 remote_replay_handler
->handle_entries_available();
2025 wait_for_notification();
2026 ASSERT_FALSE(mock_replayer
.is_replaying());
2027 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
2029 ASSERT_EQ(0, replay_ctx
.wait());
2031 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2033 mock_remote_journaler
,
2034 mock_local_journal_replay
));
2037 TEST_F(TestMockImageReplayerJournalReplayer
, ImageNameUpdated
) {
2038 librbd::MockTestJournal mock_local_journal
;
2039 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
,
2040 mock_local_journal
};
2041 ::journal::MockJournaler mock_remote_journaler
;
2042 MockReplayerListener mock_replayer_listener
;
2043 MockThreads mock_threads
{m_threads
};
2044 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2045 mock_remote_journaler
,
2047 MockReplayer mock_replayer
{
2048 &mock_threads
, "local mirror uuid", &mock_state_builder
,
2049 &mock_replayer_listener
};
2051 ::journal::MockReplayEntry mock_replay_entry
;
2052 expect_work_queue_repeatedly(mock_threads
);
2053 expect_add_event_after_repeatedly(mock_threads
);
2054 expect_get_commit_tid_in_debug(mock_replay_entry
);
2055 expect_get_tag_tid_in_debug(mock_local_journal
);
2056 expect_committed(mock_replay_entry
, mock_remote_journaler
, 1);
2057 expect_notification(mock_threads
, mock_replayer_listener
);
2061 MockReplay mock_local_journal_replay
;
2062 MockEventPreprocessor mock_event_preprocessor
;
2063 MockReplayStatusFormatter mock_replay_status_formatter
;
2064 librbd::journal::Listener
* local_journal_listener
= nullptr;
2065 ::journal::ReplayHandler
* remote_replay_handler
= nullptr;
2066 ::journal::JournalMetadataListener
* remote_journaler_listener
= nullptr;
2067 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2068 mock_replayer_listener
, mock_local_journal
,
2069 mock_remote_journaler
,
2070 mock_local_journal_replay
,
2071 &local_journal_listener
,
2072 &remote_replay_handler
,
2073 &remote_journaler_listener
));
2075 mock_local_image_ctx
.name
= "NEW NAME";
2076 cls::journal::Tag tag
=
2077 {1, 0, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
2078 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
2081 expect_try_pop_front(mock_remote_journaler
, tag
.tid
, true);
2082 expect_shut_down(mock_local_journal_replay
, false, 0);
2083 EXPECT_CALL(mock_local_journal
, stop_external_replay());
2084 expect_start_external_replay(mock_local_journal
, &mock_local_journal_replay
,
2086 expect_get_tag(mock_remote_journaler
, tag
, 0);
2087 expect_allocate_tag(mock_local_journal
, 0);
2088 EXPECT_CALL(mock_local_journal_replay
, decode(_
, _
)).WillOnce(Return(0));
2089 expect_preprocess(mock_event_preprocessor
, false, 0);
2090 expect_process(mock_local_journal_replay
, 0, 0);
2092 // attempt to process the next event
2093 C_SaferCond replay_ctx
;
2094 expect_try_pop_front_return_no_entries(mock_remote_journaler
, &replay_ctx
);
2096 remote_replay_handler
->handle_entries_available();
2097 wait_for_notification();
2099 auto image_spec
= util::compute_image_spec(m_local_io_ctx
, "NEW NAME");
2100 ASSERT_EQ(image_spec
, mock_replayer
.get_image_spec());
2102 ASSERT_EQ(0, replay_ctx
.wait());
2103 ASSERT_TRUE(mock_replayer
.is_replaying());
2105 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2107 mock_remote_journaler
,
2108 mock_local_journal_replay
));
2111 } // namespace journal
2112 } // namespace image_replayer
2113 } // namespace mirror