template <>
std::string generate_image_id<MockTestImageCtx>(librados::IoCtx&) {
- assert(!s_image_id.empty());
+ ceph_assert(!s_image_id.empty());
return s_image_id;
}
class ProgressContext;
+template <>
+struct Threads<librbd::MockTestImageCtx> {
+ Mutex &timer_lock;
+ SafeTimer *timer;
+ ContextWQ *work_queue;
+
+ Threads(Threads<librbd::ImageCtx> *threads)
+ : timer_lock(threads->timer_lock), timer(threads->timer),
+ work_queue(threads->work_queue) {
+ }
+};
+
template<>
struct ImageSync<librbd::MockTestImageCtx> {
static ImageSync* s_instance;
static ImageSync* create(
librbd::MockTestImageCtx *local_image_ctx,
librbd::MockTestImageCtx *remote_image_ctx,
- SafeTimer *timer, Mutex *timer_lock, const std::string &mirror_uuid,
- ::journal::MockJournaler *journaler,
+ SafeTimer *timer, Mutex *timer_lock,
+ const std::string &mirror_uuid, ::journal::MockJournaler *journaler,
librbd::journal::MirrorPeerClientMeta *client_meta, ContextWQ *work_queue,
InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
Context *on_finish, ProgressContext *progress_ctx) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
return s_instance;
}
ImageSync() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~ImageSync() {
static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->image_ctx = image_ctx;
s_instance->on_finish = on_finish;
s_instance->construct(*image_ctx);
}
CloseImageRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~CloseImageRequest() {
static CreateImageRequest* s_instance;
Context *on_finish = nullptr;
- static CreateImageRequest* create(librados::IoCtx &local_io_ctx,
- ContextWQ *work_queue,
+ static CreateImageRequest* create(Threads<librbd::MockTestImageCtx>* threads,
+ librados::IoCtx &local_io_ctx,
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
const std::string &local_image_id,
librbd::MockTestImageCtx *remote_image_ctx,
Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
s_instance->construct(local_image_id);
return s_instance;
}
CreateImageRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~CreateImageRequest() {
static IsPrimaryRequest* create(librbd::MockTestImageCtx *image_ctx,
bool *primary, Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->primary = primary;
s_instance->on_finish = on_finish;
return s_instance;
}
IsPrimaryRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~IsPrimaryRequest() {
librbd::MockTestImageCtx **image_ctx,
const std::string &image_id,
bool read_only, Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->image_ctx = image_ctx;
s_instance->on_finish = on_finish;
s_instance->construct(io_ctx, image_id);
}
OpenImageRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~OpenImageRequest() {
const std::string &local_image_id,
ContextWQ *work_queue,
Context *on_finish) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
s_instance->image_ctx = local_image_ctx;
s_instance->on_finish = on_finish;
s_instance->construct(local_io_ctx, local_image_id);
}
OpenLocalImageRequest() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~OpenLocalImageRequest() {
class TestMockImageReplayerBootstrapRequest : public TestMockFixture {
public:
+ typedef Threads<librbd::MockTestImageCtx> MockThreads;
typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
const librbd::journal::ClientData &client_data,
int r) {
bufferlist bl;
- ::encode(client_data, bl);
+ encode(client_data, bl);
EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _))
.WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
const librbd::journal::ClientData &client_data,
int r) {
bufferlist bl;
- ::encode(client_data, bl);
+ encode(client_data, bl);
EXPECT_CALL(mock_journaler, update_client(ContentsEqual(bl), _))
.WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) {
bufferlist bl;
- ::encode(tag_data, bl);
+ encode(tag_data, bl);
return bl;
}
- MockBootstrapRequest *create_request(MockInstanceWatcher *mock_instance_watcher,
+ MockBootstrapRequest *create_request(MockThreads* mock_threads,
+ MockInstanceWatcher *mock_instance_watcher,
::journal::MockJournaler &mock_journaler,
const std::string &local_image_id,
const std::string &remote_image_id,
cls::journal::ClientState *client_state,
librbd::journal::MirrorPeerClientMeta *mirror_peer_client_meta,
Context *on_finish) {
- return new MockBootstrapRequest(m_local_io_ctx,
+ return new MockBootstrapRequest(mock_threads, m_local_io_ctx,
m_remote_io_ctx,
mock_instance_watcher,
&m_local_test_image_ctx,
local_image_id,
remote_image_id,
global_image_id,
- m_threads->work_queue,
- m_threads->timer,
- &m_threads->timer_lock,
local_mirror_uuid,
remote_mirror_uuid,
&mock_journaler,
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(-EEXIST, ctx.wait());
ASSERT_EQ(NULL, m_local_test_image_ctx);
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, mock_local_image_ctx.id,
- mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ &mock_threads, &mock_instance_watcher, mock_journaler,
+ mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
+ "local mirror uuid", "remote mirror uuid", &client_state,
+ &mirror_peer_client_meta, &ctx);
m_do_resync = false;
request->send();
ASSERT_EQ(0, ctx.wait());
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
client_data.client_meta = mirror_peer_client_meta;
client.data.clear();
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
expect_journaler_update_client(mock_journaler, client_data, 0);
// create the local image
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
mirror_peer_client_meta.image_id = "";
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, "",
+ &mock_threads, &mock_instance_watcher, mock_journaler, "",
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
cls::journal::Client client;
librbd::journal::ClientData client_data{
librbd::journal::ImageClientMeta{123}};
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
::journal::MockJournaler mock_journaler;
expect_journaler_get_client(mock_journaler,
librbd::Journal<>::IMAGE_CLIENT_ID,
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
client_data.client_meta = mirror_peer_client_meta;
client.data.clear();
- ::encode(client_data, client.data);
+ encode(client_data, client.data);
expect_journaler_update_client(mock_journaler, client_data, 0);
// create the missing local image
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
MockInstanceWatcher mock_instance_watcher;
cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
mirror_peer_client_meta.image_id = "missing image id";
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
MockBootstrapRequest *request = create_request(
- &mock_instance_watcher, mock_journaler, "missing image id",
+ &mock_threads, &mock_instance_watcher, mock_journaler, "missing image id",
+ mock_remote_image_ctx.id, "global image id", "local mirror uuid",
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+ request->send();
+ ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockImageReplayerBootstrapRequest, LocalImageIdCollision) {
+ create_local_image();
+
+ InSequence seq;
+
+ // lookup remote image tag class
+ cls::journal::Client client;
+ librbd::journal::ClientData client_data{
+ librbd::journal::ImageClientMeta{123}};
+ encode(client_data, client.data);
+ ::journal::MockJournaler mock_journaler;
+ expect_journaler_get_client(mock_journaler,
+ librbd::Journal<>::IMAGE_CLIENT_ID,
+ client, 0);
+
+ // open the remote image
+ librbd::MockJournal mock_journal;
+ librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+ MockOpenImageRequest mock_open_image_request;
+ expect_open_image(mock_open_image_request, m_remote_io_ctx,
+ mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
+ // test if remote image is primary
+ MockIsPrimaryRequest mock_is_primary_request;
+ expect_is_primary(mock_is_primary_request, true, 0);
+
+ // update client state back to syncing
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ mock_local_image_ctx.journal = &mock_journal;
+
+ librbd::util::s_image_id = mock_local_image_ctx.id;
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+ mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ client_data.client_meta = mirror_peer_client_meta;
+ client.data.clear();
+ encode(client_data, client.data);
+ expect_journaler_update_client(mock_journaler, client_data, 0);
+
+ // create the local image
+ MockCreateImageRequest mock_create_image_request;
+ expect_create_image(mock_create_image_request, mock_local_image_ctx.id,
+ -EBADF);
+
+ expect_journaler_update_client(mock_journaler, client_data, 0);
+ expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
+
+ // open the local image
+ MockOpenLocalImageRequest mock_open_local_image_request;
+ expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
+ expect_is_resync_requested(mock_journal, false, 0);
+
+ expect_journal_get_tag_tid(mock_journal, 345);
+ expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
+
+ // sync the remote image to the local image
+ MockImageSync mock_image_sync;
+ expect_image_sync(mock_image_sync, 0);
+
+ MockCloseImageRequest mock_close_image_request;
+ expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
+
+ C_SaferCond ctx;
+ MockThreads mock_threads(m_threads);
+ MockInstanceWatcher mock_instance_watcher;
+ cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ mirror_peer_client_meta.image_id = "";
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ MockBootstrapRequest *request = create_request(
+ &mock_threads, &mock_instance_watcher, mock_journaler, "",
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
"remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();