})));
}
+ void expect_journaler_unregister_client(::journal::MockJournaler &mock_journaler,
+ int r) {
+ EXPECT_CALL(mock_journaler, unregister_client(_))
+ .WillOnce(Invoke([this, r](Context *on_finish) {
+ m_threads->work_queue->queue(on_finish, r);
+ }));
+ }
+
void expect_journaler_update_client(::journal::MockJournaler &mock_journaler,
const librbd::journal::ClientData &client_data,
int r) {
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);
+
// lookup local peer in remote journal
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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, false, 0);
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);
+
// lookup local peer in remote journal
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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);
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);
+
// lookup local peer in remote journal
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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);
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);
+
// lookup local peer in remote journal
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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);
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);
+
// lookup local peer in remote journal
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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);
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);
+
// lookup local peer in remote journal
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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);
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);
+
// lookup local peer in remote journal
client = {};
expect_journaler_get_client(mock_journaler, "local mirror uuid",
client_data.client_meta = mirror_peer_client_meta;
expect_journaler_register_client(mock_journaler, client_data, 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);
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);
+
// lookup local peer in remote journal
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
"missing image id"};
expect_journaler_get_client(mock_journaler, "local mirror uuid",
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);
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
"missing image id", nullptr, -ENOENT);
+ // re-register the client
+ expect_journaler_unregister_client(mock_journaler, 0);
+ mirror_peer_client_meta = {};
+ client_data.client_meta = mirror_peer_client_meta;
+ expect_journaler_register_client(mock_journaler, client_data, 0);
+
+ // test if remote image is primary
+ expect_is_primary(mock_is_primary_request, true, 0);
+
// create the missing local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
mock_local_image_ctx.journal = &mock_journal;
m_remote_tag_class = client_meta->tag_class;
dout(10) << ": remote tag class=" << m_remote_tag_class << dendl;
+ open_remote_image();
+}
+
+template <typename I>
+void BootstrapRequest<I>::open_remote_image() {
+ dout(20) << dendl;
+
+ update_progress("OPEN_REMOTE_IMAGE");
+
+ Context *ctx = create_context_callback<
+ BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_remote_image>(
+ this);
+ OpenImageRequest<I> *request = OpenImageRequest<I>::create(
+ m_remote_io_ctx, &m_remote_image_ctx, m_remote_image_id, false,
+ ctx);
+ request->send();
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_open_remote_image(int r) {
+ dout(20) << ": r=" << r << dendl;
+
+ if (r < 0) {
+ derr << ": failed to open remote image: " << cpp_strerror(r) << dendl;
+ assert(m_remote_image_ctx == nullptr);
+ finish(r);
+ return;
+ }
+
get_client();
}
dout(10) << ": client not registered" << dendl;
} else if (r < 0) {
derr << ": failed to retrieve client: " << cpp_strerror(r) << dendl;
- finish(r);
+ m_ret_val = r;
+ close_remote_image();
return;
} else if (decode_client_meta()) {
// skip registration if it already exists
- open_remote_image();
+ is_primary();
return;
}
if (r < 0) {
derr << ": failed to register with remote journal: " << cpp_strerror(r)
<< dendl;
- finish(r);
+ m_ret_val = r;
+ close_remote_image();
return;
}
*m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
- open_remote_image();
-}
-
-template <typename I>
-void BootstrapRequest<I>::open_remote_image() {
- dout(20) << dendl;
-
- update_progress("OPEN_REMOTE_IMAGE");
-
- Context *ctx = create_context_callback<
- BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_remote_image>(
- this);
- OpenImageRequest<I> *request = OpenImageRequest<I>::create(
- m_remote_io_ctx, &m_remote_image_ctx, m_remote_image_id, false,
- ctx);
- request->send();
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_open_remote_image(int r) {
- dout(20) << ": r=" << r << dendl;
-
- if (r < 0) {
- derr << ": failed to open remote image: " << cpp_strerror(r) << dendl;
- assert(m_remote_image_ctx == nullptr);
- finish(r);
- return;
- }
-
is_primary();
}
if (r < 0) {
derr << ": failed to update client: " << cpp_strerror(r) << dendl;
} else {
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;;
+ m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
}
close_remote_image();
if (r == -ENOENT) {
assert(*m_local_image_ctx == nullptr);
dout(10) << ": local image missing" << dendl;
- create_local_image();
+ unregister_client();
return;
} else if (r == -EREMOTEIO) {
assert(*m_local_image_ctx == nullptr);
update_client_image();
}
+template <typename I>
+void BootstrapRequest<I>::unregister_client() {
+ dout(20) << dendl;
+ update_progress("UNREGISTER_CLIENT");
+
+ m_local_image_id = "";
+ Context *ctx = create_context_callback<
+ BootstrapRequest<I>, &BootstrapRequest<I>::handle_unregister_client>(
+ this);
+ m_journaler->unregister_client(ctx);
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_unregister_client(int r) {
+ dout(20) << ": r=" << r << dendl;
+ if (r < 0) {
+ derr << ": failed to unregister with remote journal: " << cpp_strerror(r)
+ << dendl;
+ m_ret_val = r;
+ close_remote_image();
+ return;
+ }
+
+ *m_client_meta = librbd::journal::MirrorPeerClientMeta("");
+ register_client();
+}
+
template <typename I>
void BootstrapRequest<I>::create_local_image() {
dout(20) << dendl;
template <typename I>
void BootstrapRequest<I>::update_client_image() {
- dout(20) << dendl;
-
- update_progress("UPDATE_CLIENT_IMAGE");
-
if (m_client_meta->image_id == (*m_local_image_ctx)->id) {
// already registered local image with remote journal
get_remote_tags();
m_local_image_id = (*m_local_image_ctx)->id;
dout(20) << dendl;
+ update_progress("UPDATE_CLIENT_IMAGE");
librbd::journal::MirrorPeerClientMeta client_meta{m_local_image_id};
client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
if (r < 0) {
derr << ": failed to update client: " << cpp_strerror(r) << dendl;
m_ret_val = r;
- close_local_image();
+ close_remote_image();
return;
}
if (m_canceled) {
dout(10) << ": request canceled" << dendl;
m_ret_val = -ECANCELED;
- close_local_image();
+ close_remote_image();
return;
}
* <start>
* |
* v
- * GET_REMOTE_TAG_CLASS * * * * * * * * * * * * * * * *
- * | *
- * v *
- * GET_CLIENT * * * * * * * * * * * * * * * * * * * * *
- * | *
- * v (skip if not needed) * (error)
- * REGISTER_CLIENT * * * * * * * * * * * * * * * * * *
- * | *
- * v *
- * OPEN_REMOTE_IMAGE * * * * * * * * * * * * * * * * *
- * | *
- * v *
- * IS_PRIMARY * * * * * * * * * * * * * * * * * * * * *
- * | *
- * | (remote image primary) *
- * \----> OPEN_LOCAL_IMAGE * * * * * * * * * * * * *
- * | | . ^ *
- * | | . | *
- * | | . \-----------------------\ *
- * | | . | *
- * | | . (image sync requested) | *
- * | | . . > REMOVE_LOCAL_IMAGE * * * * *
- * | | . | | *
- * | | . (image doesn't | | *
- * | | . exist) v | *
- * | | . . > CREATE_LOCAL_IMAGE * * * * *
- * | | | | *
- * | | \-----------------/ *
- * | | *
- * | v (skip if not needed) *
- * | UPDATE_CLIENT_IMAGE * * * * * *
- * | | * *
- * | v (skip if not needed) * *
- * | GET_REMOTE_TAGS * * * * * * * *
- * | | * *
- * | v (skip if not needed) v *
- * | IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE *
- * | | | *
- * | \-----------------\ /-----/ *
- * | | *
- * | | *
- * | (skip if not needed) | *
- * \----> UPDATE_CLIENT_STATE *|* * * * * * * * * *
- * | | *
- * /-----------/----------------/ *
- * | *
- * v *
- * CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * *
- * |
- * v
- * <finish>
+ * GET_REMOTE_TAG_CLASS * * * * * * * * * * * * * * * * * *
+ * | * (error)
+ * v *
+ * OPEN_REMOTE_IMAGE * * * * * * * * * * * * * * * * * * *
+ * | *
+ * v *
+ * GET_CLIENT * * * * * * * * * * * * * * * * * * * * * *
+ * | * *
+ * |/----------------------------------------------*---*---\
+ * v (skip if not needed) * * |
+ * REGISTER_CLIENT * * * * * * * * * * * * * * * * * * * |
+ * | * * |
+ * v * * |
+ * IS_PRIMARY * * * * * * * * * * * * * * * * * * * * * * |
+ * | * * |
+ * | (remote image primary, no local image id) * * |
+ * \----> CREATE_LOCAL_IMAGE * * * * * * * * * * * * * |
+ * | | * * |
+ * | v * * |
+ * | (remote image primary) * * |
+ * \----> OPEN_LOCAL_IMAGE * * * * * * * * * * * * * * |
+ * | | . * * |
+ * | | . (image doesn't exist) * * |
+ * | | . . > UNREGISTER_CLIENT * * * * * * * |
+ * | | | * * |
+ * | | \-----------------------*---*---/
+ * | | * *
+ * | v (skip if not needed) * *
+ * | UPDATE_CLIENT_IMAGE * * * * * * *
+ * | | * * *
+ * | v (skip if not needed) * * *
+ * | GET_REMOTE_TAGS * * * * * * * * *
+ * | | * * *
+ * | v (skip if not needed) v * *
+ * | IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE * *
+ * | | | * *
+ * | \-----------------\ /-----/ * *
+ * | | * *
+ * | | * *
+ * | (skip if not needed) | * *
+ * \----> UPDATE_CLIENT_STATE *|* * * * * * * * * * *
+ * | | * *
+ * /-----------/----------------/ * *
+ * | * *
+ * v * *
+ * CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * * *
+ * | *
+ * v *
+ * <finish> < * * * * * * * * * * * * * * * * * * * * * * *
*
* @endverbatim
*/
void open_local_image();
void handle_open_local_image(int r);
- void remove_local_image();
- void handle_remove_local_image(int r);
+ void unregister_client();
+ void handle_unregister_client(int r);
void create_local_image();
void handle_create_local_image(int r);