std::string generate_image_id(librados::IoCtx &ioctx);
+template <typename T>
+inline std::string generate_image_id(librados::IoCtx &ioctx) {
+ return generate_image_id(ioctx);
+}
+
const std::string group_header_name(const std::string &group_id);
const std::string id_obj_name(const std::string &name);
const std::string header_name(const std::string &image_id);
};
} // namespace journal
+
+namespace util {
+
+static std::string s_image_id;
+
+template <>
+std::string generate_image_id<MockTestImageCtx>(librados::IoCtx&) {
+ assert(!s_image_id.empty());
+ return s_image_id;
+}
+
+} // namespace util
} // namespace librbd
namespace rbd {
template<>
struct CreateImageRequest<librbd::MockTestImageCtx> {
static CreateImageRequest* s_instance;
- std::string *local_image_id = nullptr;
Context *on_finish = nullptr;
static CreateImageRequest* create(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,
- std::string *local_image_id,
Context *on_finish) {
assert(s_instance != nullptr);
- s_instance->local_image_id = local_image_id;
s_instance->on_finish = on_finish;
+ s_instance->construct(local_image_id);
return s_instance;
}
s_instance = nullptr;
}
+ MOCK_METHOD1(construct, void(const std::string&));
MOCK_METHOD0(send, void());
};
void expect_create_image(MockCreateImageRequest &mock_create_image_request,
const std::string &image_id, int r) {
+ EXPECT_CALL(mock_create_image_request, construct(image_id));
EXPECT_CALL(mock_create_image_request, send())
- .WillOnce(Invoke([this, &mock_create_image_request, image_id, r]() {
- *mock_create_image_request.local_image_id = image_id;
+ .WillOnce(Invoke([this, &mock_create_image_request, r]() {
m_threads->work_queue->queue(mock_create_image_request.on_finish, r);
}));
}
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
- // create the local image
+ // 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;
+ mirror_peer_client_meta = {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, 0);
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
expect_is_resync_requested(mock_journal, false, 0);
- // update client state back to syncing
- mirror_peer_client_meta = {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);
-
// sync the remote image to the local image
MockImageSync mock_image_sync;
expect_image_sync(mock_image_sync, 0);
// test if remote image is primary
expect_is_primary(mock_is_primary_request, true, 0);
- // create the missing local image
+ // 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;
+ mirror_peer_client_meta = {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 missing local image
MockCreateImageRequest mock_create_image_request;
expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
mock_local_image_ctx.id, &mock_local_image_ctx, 0);
expect_is_resync_requested(mock_journal, false, 0);
- // update client state back to syncing
- mirror_peer_client_meta = {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);
-
// sync the remote image to the local image
MockImageSync mock_image_sync;
expect_image_sync(mock_image_sync, 0);
MockCreateImageRequest *create_request(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 &mock_remote_image_ctx,
- std::string *local_image_id,
Context *on_finish) {
return new MockCreateImageRequest(m_local_io_ctx, m_threads->work_queue,
global_image_id, remote_mirror_uuid,
- local_image_name, &mock_remote_image_ctx,
- local_image_id, on_finish);
+ local_image_name, local_image_id,
+ &mock_remote_image_ctx, on_finish);
}
librbd::ImageCtx *m_remote_image_ctx;
expect_create_image(mock_create_request, m_local_io_ctx, 0);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
- mock_remote_image_ctx,
- &local_image_id, &ctx);
+ "image name", "101241a7c4c9",
+ mock_remote_image_ctx, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_FALSE(local_image_id.empty());
}
TEST_F(TestMockImageReplayerCreateImageRequest, CreateError) {
expect_create_image(mock_create_request, m_local_io_ctx, -EINVAL);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
- mock_remote_image_ctx,
- &local_image_id, &ctx);
+ "image name", "101241a7c4c9",
+ mock_remote_image_ctx, &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_FALSE(local_image_id.empty());
}
TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) {
expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", -ENOENT);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(-ENOENT, ctx.wait());
}
expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", -ENOENT);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(-ENOENT, ctx.wait());
}
m_remote_image_ctx->id, mock_remote_parent_image_ctx, -ENOENT);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(-ENOENT, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(-ENOENT, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(-ENOENT, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(-EINVAL, ctx.wait());
}
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_FALSE(local_image_id.empty());
}
TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) {
expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, -EINVAL);
C_SaferCond ctx;
- std::string local_image_id;
MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
- "image name",
+ "image name", "101241a7c4c9",
mock_remote_clone_image_ctx,
- &local_image_id, &ctx);
+ &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
- ASSERT_FALSE(local_image_id.empty());
}
} // namespace image_replayer
return;
}
+ m_client = {};
*m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
is_primary();
}
}
if (m_local_image_id.empty()) {
- create_local_image();
+ update_client_image();
return;
}
return;
}
- update_client_image();
+ get_remote_tags();
}
template <typename I>
register_client();
}
-template <typename I>
-void BootstrapRequest<I>::create_local_image() {
- dout(20) << dendl;
-
- m_local_image_id = "";
- update_progress("CREATE_LOCAL_IMAGE");
-
- m_remote_image_ctx->snap_lock.get_read();
- std::string image_name = m_remote_image_ctx->name;
- m_remote_image_ctx->snap_lock.put_read();
-
- Context *ctx = create_context_callback<
- BootstrapRequest<I>, &BootstrapRequest<I>::handle_create_local_image>(
- this);
- CreateImageRequest<I> *request = CreateImageRequest<I>::create(
- m_local_io_ctx, m_work_queue, m_global_image_id, m_remote_mirror_uuid,
- image_name, m_remote_image_ctx, &m_local_image_id, ctx);
- request->send();
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_create_local_image(int r) {
- dout(20) << ": r=" << r << dendl;
-
- if (r < 0) {
- derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
- m_ret_val = r;
- close_remote_image();
- return;
- }
-
- open_local_image();
-}
-
template <typename I>
void BootstrapRequest<I>::update_client_image() {
- if (m_client_meta->image_id == (*m_local_image_ctx)->id) {
- // already registered local image with remote journal
- get_remote_tags();
- return;
- }
- m_local_image_id = (*m_local_image_ctx)->id;
-
dout(20) << dendl;
update_progress("UPDATE_CLIENT_IMAGE");
+ assert(m_local_image_id.empty());
+ m_local_image_id = librbd::util::generate_image_id<I>(m_local_io_ctx);
+
librbd::journal::MirrorPeerClientMeta client_meta{m_local_image_id};
client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
*m_client_meta = {m_local_image_id};
m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
- get_remote_tags();
+ create_local_image();
+}
+
+template <typename I>
+void BootstrapRequest<I>::create_local_image() {
+ dout(20) << dendl;
+ update_progress("CREATE_LOCAL_IMAGE");
+
+ m_remote_image_ctx->snap_lock.get_read();
+ std::string image_name = m_remote_image_ctx->name;
+ m_remote_image_ctx->snap_lock.put_read();
+
+ Context *ctx = create_context_callback<
+ BootstrapRequest<I>, &BootstrapRequest<I>::handle_create_local_image>(
+ this);
+ CreateImageRequest<I> *request = CreateImageRequest<I>::create(
+ m_local_io_ctx, m_work_queue, m_global_image_id, m_remote_mirror_uuid,
+ image_name, m_local_image_id, m_remote_image_ctx, ctx);
+ request->send();
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_create_local_image(int r) {
+ dout(20) << ": r=" << r << dendl;
+
+ if (r < 0) {
+ derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
+ m_ret_val = r;
+ close_remote_image();
+ return;
+ }
+
+ open_local_image();
}
template <typename I>
* IS_PRIMARY * * * * * * * * * * * * * * * * * * * * * * |
* | * * |
* | (remote image primary, no local image id) * * |
+ * \----> UPDATE_CLIENT_IMAGE * * * * * * * * * * * * |
+ * | | * * |
+ * | v * * |
* \----> CREATE_LOCAL_IMAGE * * * * * * * * * * * * * |
* | | * * |
* | v * * |
* | | \-----------------------*---*---/
* | | * *
* | v (skip if not needed) * *
- * | UPDATE_CLIENT_IMAGE * * * * * * *
- * | | * * *
- * | v (skip if not needed) * * *
* | GET_REMOTE_TAGS * * * * * * * * *
* | | * * *
* | v (skip if not needed) v * *
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
+ const std::string &local_image_id,
I *remote_image_ctx,
- std::string *local_image_id,
Context *on_finish)
: m_local_io_ctx(local_io_ctx), m_work_queue(work_queue),
m_global_image_id(global_image_id),
m_remote_mirror_uuid(remote_mirror_uuid),
- m_local_image_name(local_image_name), m_remote_image_ctx(remote_image_ctx),
- m_local_image_id(local_image_id), m_on_finish(on_finish) {
+ m_local_image_name(local_image_name), m_local_image_id(local_image_id),
+ m_remote_image_ctx(remote_image_ctx), m_on_finish(on_finish) {
}
template <typename I>
image_options.set(RBD_IMAGE_OPTION_STRIPE_COUNT,
m_remote_image_ctx->stripe_count);
- *m_local_image_id = librbd::util::generate_image_id(m_local_io_ctx);;
-
librbd::image::CreateRequest<I> *req = librbd::image::CreateRequest<I>::create(
- m_local_io_ctx, m_local_image_name, *m_local_image_id,
+ m_local_io_ctx, m_local_image_name, m_local_image_id,
m_remote_image_ctx->size, image_options, m_global_image_id,
m_remote_mirror_uuid, false, m_remote_image_ctx->op_work_queue, ctx);
req->send();
opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, m_remote_image_ctx->stripe_unit);
opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, m_remote_image_ctx->stripe_count);
- *m_local_image_id = librbd::util::generate_image_id(m_local_io_ctx);;
-
using klass = CreateImageRequest<I>;
Context *ctx = create_context_callback<klass, &klass::handle_clone_image>(this);
librbd::image::CloneRequest<I> *req = librbd::image::CloneRequest<I>::create(
m_local_parent_image_ctx, m_local_io_ctx, m_local_image_name,
- *m_local_image_id, opts, m_global_image_id, m_remote_mirror_uuid,
+ m_local_image_id, opts, m_global_image_id, m_remote_mirror_uuid,
m_remote_image_ctx->op_work_queue, ctx);
req->send();
}
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
+ const std::string &local_image_id,
ImageCtxT *remote_image_ctx,
- std::string *local_image_id,
Context *on_finish) {
return new CreateImageRequest(local_io_ctx, work_queue, global_image_id,
remote_mirror_uuid, local_image_name,
- remote_image_ctx, local_image_id, on_finish);
+ local_image_id, remote_image_ctx, on_finish);
}
CreateImageRequest(librados::IoCtx &local_io_ctx, ContextWQ *work_queue,
const std::string &global_image_id,
const std::string &remote_mirror_uuid,
const std::string &local_image_name,
+ const std::string &local_image_id,
ImageCtxT *remote_image_ctx,
- std::string *local_image_id,
Context *on_finish);
void send();
std::string m_global_image_id;
std::string m_remote_mirror_uuid;
std::string m_local_image_name;
+ std::string m_local_image_id;
ImageCtxT *m_remote_image_ctx;
- std::string *m_local_image_id;
Context *m_on_finish;
librados::IoCtx m_remote_parent_io_ctx;