.WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
}
+ void expect_close_journal(MockImageCtx &mock_image_ctx,
+ MockJournal &mock_journal) {
+ EXPECT_CALL(mock_journal, close(_))
+ .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+ }
+
+ void expect_is_journal_tag_owner(MockJournal &mock_journal, bool owner) {
+ EXPECT_CALL(mock_journal, is_tag_owner()).WillOnce(Return(owner));
+ }
+
+ void expect_allocate_journal_tag(MockImageCtx &mock_image_ctx,
+ MockJournal &mock_journal, int r) {
+ EXPECT_CALL(mock_journal, allocate_tag("", _))
+ .WillOnce(WithArg<1>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
+ }
+
void expect_get_lock_info(MockImageCtx &mock_image_ctx, int r,
const entity_name_t &locker_entity,
const std::string &locker_address,
expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
expect_create_journal(mock_image_ctx, &mock_journal);
expect_open_journal(mock_image_ctx, mock_journal, 0);
+ expect_is_journal_tag_owner(mock_journal, true);
+ expect_allocate_journal_tag(mock_image_ctx, mock_journal, 0);
C_SaferCond acquire_ctx;
C_SaferCond ctx;
expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
expect_create_journal(mock_image_ctx, &mock_journal);
expect_open_journal(mock_image_ctx, mock_journal, 0);
+ expect_is_journal_tag_owner(mock_journal, true);
+ expect_allocate_journal_tag(mock_image_ctx, mock_journal, 0);
C_SaferCond acquire_ctx;
C_SaferCond ctx;
expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
expect_create_journal(mock_image_ctx, mock_journal);
expect_open_journal(mock_image_ctx, *mock_journal, -EINVAL);
+ expect_close_journal(mock_image_ctx, *mock_journal);
expect_close_object_map(mock_image_ctx, *mock_object_map);
C_SaferCond acquire_ctx;
ASSERT_EQ(-EINVAL, ctx.wait());
}
+TEST_F(TestMockExclusiveLockAcquireRequest, NotJournalTagOwner) {
+ REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+ expect_op_work_queue(mock_image_ctx);
+
+ InSequence seq;
+ expect_flush_notifies(mock_image_ctx);
+ expect_lock(mock_image_ctx, 0);
+
+ MockObjectMap *mock_object_map = new MockObjectMap();
+ expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+ expect_create_object_map(mock_image_ctx, mock_object_map);
+ expect_open_object_map(mock_image_ctx, *mock_object_map);
+
+ MockJournal *mock_journal = new MockJournal();
+ expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
+ expect_create_journal(mock_image_ctx, mock_journal);
+ expect_open_journal(mock_image_ctx, *mock_journal, 0);
+ expect_is_journal_tag_owner(*mock_journal, false);
+ expect_close_journal(mock_image_ctx, *mock_journal);
+ expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+ C_SaferCond acquire_ctx;
+ C_SaferCond ctx;
+ MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
+ TEST_COOKIE,
+ &acquire_ctx, &ctx);
+ req->send();
+ ASSERT_EQ(-EPERM, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockAcquireRequest, AllocateJournalTagError) {
+ REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+ expect_op_work_queue(mock_image_ctx);
+
+ InSequence seq;
+ expect_flush_notifies(mock_image_ctx);
+ expect_lock(mock_image_ctx, 0);
+
+ MockObjectMap *mock_object_map = new MockObjectMap();
+ expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+ expect_create_object_map(mock_image_ctx, mock_object_map);
+ expect_open_object_map(mock_image_ctx, *mock_object_map);
+
+ MockJournal *mock_journal = new MockJournal();
+ expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
+ expect_create_journal(mock_image_ctx, mock_journal);
+ expect_open_journal(mock_image_ctx, *mock_journal, 0);
+ expect_is_journal_tag_owner(*mock_journal, true);
+ expect_allocate_journal_tag(mock_image_ctx, *mock_journal, -ESTALE);
+ expect_close_journal(mock_image_ctx, *mock_journal);
+ expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+ C_SaferCond acquire_ctx;
+ C_SaferCond ctx;
+ MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
+ TEST_COOKIE,
+ &acquire_ctx, &ctx);
+ req->send();
+ ASSERT_EQ(-ESTALE, ctx.wait());
+}
+
TEST_F(TestMockExclusiveLockAcquireRequest, LockBusy) {
REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
}
}
- void get_journal_commit_position(librbd::ImageCtx *ictx, int64_t *tid)
+ void get_journal_commit_position(librbd::ImageCtx *ictx, int64_t *tag,
+ int64_t *entry)
{
const std::string client_id = "";
std::string journal_id = ictx->id;
break;
}
}
- if (c == registered_clients.end()) {
- *tid = -1;
- return;
+ if (c == registered_clients.end() ||
+ c->commit_position.object_positions.empty()) {
+ *tag = 0;
+ *entry = -1;
+ } else {
+ const cls::journal::ObjectPosition &object_position =
+ *c->commit_position.object_positions.begin();
+ *tag = object_position.tag_tid;
+ *entry = object_position.entry_tid;
}
- cls::journal::ObjectPositions object_positions =
- c->commit_position.object_positions;
- cls::journal::ObjectPositions::const_iterator p;
- for (p = object_positions.begin(); p != object_positions.end(); p++) {
- if (p->tag_tid == 0) {
- break;
- }
- }
- *tid = p == object_positions.end() ? -1 : p->entry_tid;
C_SaferCond open_cond;
ictx->journal = new librbd::Journal<>(*ictx);
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject a discard operation into the journal
inject_into_journal(ictx,
ASSERT_EQ(std::string(read_payload.size(), '\0'), read_payload);
// check the commit position is properly updated
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 1);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(0, current_entry);
// replay several envents and check the commit position
inject_into_journal(ictx,
librbd::journal::AioDiscardEvent(0, payload.size()));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 3);
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 2, current_tag);
+ ASSERT_EQ(1, current_entry);
// verify lock ordering constraints
aio_comp = new librbd::AioCompletion();
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject a write operation into the journal
std::string payload(4096, '1');
ASSERT_EQ(payload, read_payload);
// check the commit position is properly updated
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 1);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(0, current_entry);
// replay several events and check the commit position
inject_into_journal(ictx,
librbd::journal::AioWriteEvent(0, payload.size(), payload_bl));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 3);
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 2, current_tag);
+ ASSERT_EQ(1, current_entry);
// verify lock ordering constraints
aio_comp = new librbd::AioCompletion();
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject a flush operation into the journal
inject_into_journal(ictx, librbd::journal::AioFlushEvent());
ASSERT_EQ(payload, read_payload);
// check the commit position is properly updated
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 1);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(0, current_entry);
// replay several events and check the commit position
inject_into_journal(ictx, librbd::journal::AioFlushEvent());
inject_into_journal(ictx, librbd::journal::AioFlushEvent());
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 3);
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 2, current_tag);
+ ASSERT_EQ(1, current_entry);
// verify lock ordering constraints
aio_comp = new librbd::AioCompletion();
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::SnapCreateEvent(1, "snap"));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(1, current_entry);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
ASSERT_EQ(0, ictx->operations->snap_create("snap"));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::SnapProtectEvent(1, "snap"));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag, current_tag);
+ ASSERT_EQ(initial_entry + 2, current_entry);
bool is_protected;
ASSERT_EQ(0, librbd::snap_is_protected(ictx, "snap", &is_protected));
ASSERT_EQ(0, ictx->operations->snap_protect("snap"));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::SnapUnprotectEvent(1, "snap"));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag, current_tag);
+ ASSERT_EQ(initial_entry + 2, current_entry);
bool is_protected;
ASSERT_EQ(0, librbd::snap_is_protected(ictx, "snap", &is_protected));
}
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::SnapRenameEvent(1, snap_id, "snap2"));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag, current_tag);
+ ASSERT_EQ(initial_entry + 2, current_entry);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
ASSERT_EQ(0, ictx->operations->snap_create("snap"));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::SnapRollbackEvent(1, "snap"));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag, current_tag);
+ ASSERT_EQ(initial_entry + 2, current_entry);
// verify lock ordering constraints
librbd::NoOpProgressContext no_op_progress;
ASSERT_EQ(0, ictx->operations->snap_create("snap"));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::SnapRemoveEvent(1, "snap"));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag, current_tag);
+ ASSERT_EQ(initial_entry + 2, current_entry);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
std::string new_image_name(get_temp_image_name());
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(1, current_entry);
// verify lock ordering constraints
librbd::RBD rbd;
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx, librbd::journal::ResizeEvent(1, 16));
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(1, current_entry);
// verify lock ordering constraints
librbd::NoOpProgressContext no_op_progress;
ASSERT_EQ(0, when_acquired_lock(ictx2));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx2, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx2, &initial_tag, &initial_entry);
// inject snapshot ops into journal
inject_into_journal(ictx2, librbd::journal::FlattenEvent(1));
ASSERT_EQ(0, open_image(clone_name, &ictx2));
ASSERT_EQ(0, when_acquired_lock(ictx2));
- int64_t current;
- get_journal_commit_position(ictx2, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx2, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(1, current_entry);
ASSERT_EQ(0, ictx->operations->snap_unprotect("snap"));
// verify lock ordering constraints
ASSERT_EQ(0, when_acquired_lock(ictx));
// get current commit position
- int64_t initial;
- get_journal_commit_position(ictx, &initial);
+ int64_t initial_tag;
+ int64_t initial_entry;
+ get_journal_commit_position(ictx, &initial_tag, &initial_entry);
std::string payload(4096, '1');
librbd::AioCompletion *aio_comp = new librbd::AioCompletion();
aio_comp->release();
// check the commit position updated
- int64_t current;
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 2);
+ int64_t current_tag;
+ int64_t current_entry;
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(1, current_entry);
// write again
aio_comp->release();
// check the commit position updated
- get_journal_commit_position(ictx, ¤t);
- ASSERT_EQ(current, initial + 4);
+ get_journal_commit_position(ictx, ¤t_tag, ¤t_entry);
+ ASSERT_EQ(initial_tag + 1, current_tag);
+ ASSERT_EQ(3, current_entry);
}
#include "common/Cond.h"
#include "common/Mutex.h"
#include "cls/journal/cls_journal_types.h"
+#include "journal/Journaler.h"
#include "librbd/Journal.h"
#include "librbd/Utils.h"
#include "librbd/journal/Replay.h"
MOCK_METHOD1(init, void(Context*));
MOCK_METHOD1(flush_commit_position, void(Context*));
+ MOCK_METHOD2(get_cached_client, int(const std::string&, cls::journal::Client*));
+ MOCK_METHOD3(get_tags, void(uint64_t, journal::Journaler::Tags*, Context*));
+
MOCK_METHOD1(start_replay, void(::journal::ReplayHandler *replay_handler));
MOCK_METHOD1(try_pop_front, bool(MockReplayEntryProxy *replay_entry));
MOCK_METHOD0(stop_replay, void());
MockJournaler::get_instance().init(on_finish);
}
+ int get_cached_client(const std::string& client_id,
+ cls::journal::Client* client) {
+ return MockJournaler::get_instance().get_cached_client(client_id, client);
+ }
+
+ void get_tags(uint64_t tag_class, journal::Journaler::Tags *tags,
+ Context *on_finish) {
+ MockJournaler::get_instance().get_tags(tag_class, tags, on_finish);
+ }
+
void flush_commit_position(Context *on_finish) {
MockJournaler::get_instance().flush_commit_position(on_finish);
}
void expect_init_journaler(::journal::MockJournaler &mock_journaler, int r) {
EXPECT_CALL(mock_journaler, init(_))
.WillOnce(CompleteContext(r, NULL));
+ }
+
+ void expect_get_journaler_cached_client(::journal::MockJournaler &mock_journaler, int r) {
+
+ journal::ImageClientMeta image_client_meta;
+ image_client_meta.tag_class = 0;
+
+ journal::ClientData client_data;
+ client_data.client_meta = image_client_meta;
+
+ cls::journal::Client client;
+ ::encode(client_data, client.data);
+
+ EXPECT_CALL(mock_journaler, get_cached_client("", _))
+ .WillOnce(DoAll(SetArgPointee<1>(client),
+ Return(r)));
+ }
+
+ void expect_get_journaler_tags(MockImageCtx &mock_image_ctx,
+ ::journal::MockJournaler &mock_journaler,
+ int r) {
+ journal::TagData tag_data;
+
+ bufferlist tag_data_bl;
+ ::encode(tag_data, tag_data_bl);
+ ::journal::Journaler::Tags tags = {{0, 0, {}}, {1, 0, tag_data_bl}};
+ EXPECT_CALL(mock_journaler, get_tags(0, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(tags),
+ WithArg<2>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue))));
}
void expect_start_replay(MockJournalImageCtx &mock_image_ctx,
InSequence seq;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, 0)
::journal::MockJournaler mock_journaler;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_ready, _1),
ASSERT_EQ(-EINVAL, when_open(mock_journal));
}
+TEST_F(TestMockJournal, GetCachedClientError) {
+ REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+ MockJournal mock_journal(mock_image_ctx);
+ expect_op_work_queue(mock_image_ctx);
+
+ InSequence seq;
+
+ ::journal::MockJournaler mock_journaler;
+ expect_construct_journaler(mock_journaler);
+ expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, -ENOENT);
+ ASSERT_EQ(-ENOENT, when_open(mock_journal));
+}
+
+TEST_F(TestMockJournal, GetTagsError) {
+ REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+ MockJournal mock_journal(mock_image_ctx);
+ expect_op_work_queue(mock_image_ctx);
+
+ InSequence seq;
+
+ ::journal::MockJournaler mock_journaler;
+ expect_construct_journaler(mock_journaler);
+ expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, -EBADMSG);
+ ASSERT_EQ(-EBADMSG, when_open(mock_journal));
+}
+
TEST_F(TestMockJournal, ReplayCompleteError) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
::journal::MockJournaler mock_journaler;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, -EINVAL)
// replay failure should result in replay-restart
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, 0)
::journal::MockJournaler mock_journaler;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_ready, _1),
// replay flush failure should result in replay-restart
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, 0)
::journal::MockJournaler mock_journaler;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, 0)
::journal::MockJournaler mock_journaler;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
::journal::ReplayHandler *replay_handler = nullptr;
expect_start_replay(
// replay write-to-disk failure should result in replay-restart
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, 0)
::journal::MockJournaler mock_journaler;
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_ready, _1),
// replay write-to-disk failure should result in replay-restart
expect_construct_journaler(mock_journaler);
expect_init_journaler(mock_journaler, 0);
+ expect_get_journaler_cached_client(mock_journaler, 0);
+ expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
expect_start_replay(
mock_image_ctx, mock_journaler, {
std::bind(&invoke_replay_complete, _1, 0)