const std::string &global_image_id,
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid,
+ cls::journal::ClientState *client_state,
+ librbd::journal::MirrorPeerClientMeta *mirror_peer_client_meta,
Context *on_finish) {
return new MockBootstrapRequest(m_local_io_ctx,
m_remote_io_ctx,
local_mirror_uuid,
remote_mirror_uuid,
&mock_journaler,
- &m_mirror_peer_client_meta,
+ client_state, mirror_peer_client_meta,
on_finish, &m_do_resync);
}
librbd::ImageCtx *m_remote_image_ctx;
librbd::ImageCtx *m_local_image_ctx = nullptr;
librbd::MockTestImageCtx *m_local_test_image_ctx = nullptr;
- librbd::journal::MirrorPeerClientMeta m_mirror_peer_client_meta;
bool m_do_resync;
};
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{
- 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_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, false, 0);
// switch the state to replaying
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
client_data.client_meta = mirror_peer_client_meta;
expect_journaler_update_client(mock_journaler, client_data, 0);
C_SaferCond ctx;
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", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(-EREMOTEIO, ctx.wait());
}
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{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- client.data.clear();
- ::encode(client_data, client.data);
- expect_journaler_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
// open the local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
C_SaferCond ctx;
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", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
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{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- client.data.clear();
- ::encode(client_data, client.data);
- expect_journaler_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
// open the local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
C_SaferCond ctx;
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", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
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{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- client.data.clear();
- ::encode(client_data, client.data);
- expect_journaler_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
// open the local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
C_SaferCond ctx;
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", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
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{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- client.data.clear();
- ::encode(client_data, client.data);
- expect_journaler_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
// open the local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
C_SaferCond ctx;
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", &ctx);
+ "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);
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{
- mock_local_image_ctx.id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- client.data.clear();
- ::encode(client_data, client.data);
- expect_journaler_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
// open the local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
C_SaferCond ctx;
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", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
m_do_resync = false;
request->send();
ASSERT_EQ(0, ctx.wait());
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, -ENOENT);
-
- // register missing client in remote journal
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- expect_journaler_register_client(mock_journaler, client_data, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
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};
+ 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();
C_SaferCond ctx;
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_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
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"};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- client_data.client_meta = mirror_peer_client_meta;
- client.data.clear();
- ::encode(client_data, client.data);
- expect_journaler_get_client(mock_journaler, "local mirror uuid",
- client, 0);
-
// test if remote image is primary
MockIsPrimaryRequest mock_is_primary_request;
expect_is_primary(mock_is_primary_request, true, 0);
// re-register the client
expect_journaler_unregister_client(mock_journaler, 0);
- mirror_peer_client_meta = {};
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+ mirror_peer_client_meta.image_id = "";
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
client_data.client_meta = mirror_peer_client_meta;
expect_journaler_register_client(mock_journaler, client_data, 0);
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.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();
C_SaferCond ctx;
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, "",
+ &mock_instance_watcher, mock_journaler, "missing image id",
mock_remote_image_ctx.id, "global image id", "local mirror uuid",
- "remote mirror uuid", &ctx);
+ "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
request->send();
ASSERT_EQ(0, ctx.wait());
}
const std::string &local_mirror_uuid,
const std::string &remote_mirror_uuid,
Journaler *journaler,
+ cls::journal::ClientState *client_state,
MirrorPeerClientMeta *client_meta,
Context *on_finish,
bool *do_resync,
m_timer(timer), m_timer_lock(timer_lock),
m_local_mirror_uuid(local_mirror_uuid),
m_remote_mirror_uuid(remote_mirror_uuid), m_journaler(journaler),
- m_client_meta(client_meta), m_progress_ctx(progress_ctx),
- m_do_resync(do_resync),
+ m_client_state(client_state), m_client_meta(client_meta),
+ m_progress_ctx(progress_ctx), m_do_resync(do_resync),
m_lock(unique_lock_name("BootstrapRequest::m_lock", this)) {
}
return;
}
- get_client();
-}
-
-template <typename I>
-void BootstrapRequest<I>::get_client() {
- dout(20) << dendl;
-
- update_progress("GET_CLIENT");
-
- Context *ctx = create_context_callback<
- BootstrapRequest<I>, &BootstrapRequest<I>::handle_get_client>(
- this);
- m_journaler->get_client(m_local_mirror_uuid, &m_client, ctx);
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_get_client(int r) {
- dout(20) << ": r=" << r << dendl;
-
- if (r == -ENOENT) {
- dout(10) << ": client not registered" << dendl;
- } else if (r < 0) {
- derr << ": failed to retrieve client: " << cpp_strerror(r) << dendl;
- m_ret_val = r;
- close_remote_image();
- return;
- } else if (decode_client_meta()) {
- // skip registration if it already exists
- is_primary();
- return;
- }
-
- register_client();
-}
-
-template <typename I>
-void BootstrapRequest<I>::register_client() {
- dout(20) << dendl;
-
- update_progress("REGISTER_CLIENT");
-
- librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
- m_local_image_id};
- mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
-
- librbd::journal::ClientData client_data{mirror_peer_client_meta};
- bufferlist client_data_bl;
- ::encode(client_data, client_data_bl);
-
- Context *ctx = create_context_callback<
- BootstrapRequest<I>, &BootstrapRequest<I>::handle_register_client>(
- this);
- m_journaler->register_client(client_data_bl, ctx);
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_register_client(int r) {
- dout(20) << ": r=" << r << dendl;
-
- if (r < 0) {
- derr << ": failed to register with remote journal: " << cpp_strerror(r)
- << dendl;
- m_ret_val = r;
- close_remote_image();
- return;
- }
-
- m_client = {};
- *m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
-
is_primary();
}
return;
}
+ if (!m_client_meta->image_id.empty()) {
+ // have an image id -- use that to open the image since a deletion (resync)
+ // will leave the old image id registered in the peer
+ m_local_image_id = m_client_meta->image_id;
+ }
+
if (m_local_image_id.empty()) {
update_client_image();
return;
return;
}
- if (m_client.state == cls::journal::CLIENT_STATE_DISCONNECTED) {
+ if (*m_client_state == cls::journal::CLIENT_STATE_DISCONNECTED) {
dout(10) << ": client flagged disconnected -- skipping bootstrap" << dendl;
// The caller is expected to detect disconnect initializing remote journal.
m_ret_val = 0;
register_client();
}
+template <typename I>
+void BootstrapRequest<I>::register_client() {
+ dout(20) << dendl;
+
+ update_progress("REGISTER_CLIENT");
+
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ m_local_image_id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+
+ librbd::journal::ClientData client_data{mirror_peer_client_meta};
+ bufferlist client_data_bl;
+ ::encode(client_data, client_data_bl);
+
+ Context *ctx = create_context_callback<
+ BootstrapRequest<I>, &BootstrapRequest<I>::handle_register_client>(
+ this);
+ m_journaler->register_client(client_data_bl, ctx);
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_register_client(int r) {
+ dout(20) << ": r=" << r << dendl;
+
+ if (r < 0) {
+ derr << ": failed to register with remote journal: " << cpp_strerror(r)
+ << dendl;
+ m_ret_val = r;
+ close_remote_image();
+ return;
+ }
+
+ *m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
+ *m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
+ m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+
+ is_primary();
+}
+
template <typename I>
void BootstrapRequest<I>::update_client_image() {
dout(20) << dendl;
finish(m_ret_val);
}
-template <typename I>
-bool BootstrapRequest<I>::decode_client_meta() {
- dout(20) << dendl;
-
- librbd::journal::ClientData client_data;
- bufferlist::iterator it = m_client.data.begin();
- try {
- ::decode(client_data, it);
- } catch (const buffer::error &err) {
- derr << ": failed to decode client meta data: " << err.what() << dendl;
- return false;
- }
-
- librbd::journal::MirrorPeerClientMeta *client_meta =
- boost::get<librbd::journal::MirrorPeerClientMeta>(&client_data.client_meta);
- if (client_meta == nullptr) {
- derr << ": unknown peer registration" << dendl;
- return false;
- } else if (!client_meta->image_id.empty()) {
- // have an image id -- use that to open the image
- m_local_image_id = client_meta->image_id;
- }
-
- *m_client_meta = *client_meta;
-
- dout(20) << ": client found: image_id=" << m_local_image_id
- << ", client_meta=" << *m_client_meta << dendl;
- return true;
-}
-
template <typename I>
void BootstrapRequest<I>::update_progress(const std::string &description) {
dout(20) << ": " << description << dendl;