From: Jason Dillaman Date: Mon, 25 Apr 2016 19:11:28 +0000 (-0400) Subject: rbd-mirror: refactor snapshot create into its own state machine X-Git-Tag: v10.2.1~14^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a140753b6b01215f832cc9524e3532e825e4c2f2;p=ceph.git rbd-mirror: refactor snapshot create into its own state machine Initial implementation will resize the image (if needed) and create the snapshot. It is stubbed out for future state machines for handling object map and clones. Signed-off-by: Jason Dillaman (cherry picked from commit 8adc47fbf8efa3991bd247be43b786676fe5fff9) --- diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index 66ab55f87f6..f71f8242f5f 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -477,6 +477,7 @@ unittest_rbd_mirror_SOURCES = \ test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc \ test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc \ test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc \ + test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc \ test/rbd_mirror/image_sync/test_mock_SyncPointCreateRequest.cc \ test/rbd_mirror/image_sync/test_mock_SyncPointPruneRequest.cc unittest_rbd_mirror_CXXFLAGS = $(UNITTEST_CXXFLAGS) diff --git a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc index 15768a68d65..b3e4a120ab1 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc @@ -11,6 +11,7 @@ #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "test/librbd/mock/MockImageCtx.h" #include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.h" +#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h" #include "tools/rbd_mirror/Threads.h" namespace librbd { @@ -24,6 +25,36 @@ struct TypeTraits { } // namespace journal } // namespace librbd +namespace rbd { +namespace mirror { +namespace image_sync { + +template <> +struct SnapshotCreateRequest { + static SnapshotCreateRequest* s_instance; + static SnapshotCreateRequest* create(librbd::MockImageCtx* image_ctx, + const std::string &snap_name, + uint64_t size, Context *on_finish) { + assert(s_instance != nullptr); + s_instance->on_finish = on_finish; + return s_instance; + } + + Context *on_finish = nullptr; + + SnapshotCreateRequest() { + s_instance = this; + } + + MOCK_METHOD0(send, void()); +}; + +SnapshotCreateRequest* SnapshotCreateRequest::s_instance = nullptr; + +} // namespace image_sync +} // namespace mirror +} // namespace rbd + // template definitions #include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc" template class rbd::mirror::image_sync::SnapshotCopyRequest; @@ -46,6 +77,7 @@ using ::testing::WithArg; class TestMockImageSyncSnapshotCopyRequest : public TestMockFixture { public: typedef SnapshotCopyRequest MockSnapshotCopyRequest; + typedef SnapshotCreateRequest MockSnapshotCreateRequest; virtual void SetUp() { TestMockFixture::SetUp(); @@ -59,14 +91,15 @@ public: } void expect_snap_create(librbd::MockImageCtx &mock_image_ctx, + MockSnapshotCreateRequest &mock_snapshot_create_request, const std::string &snap_name, uint64_t snap_id, int r) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, 0)) - .WillOnce(DoAll(InvokeWithoutArgs([&mock_image_ctx, snap_id, snap_name]() { - inject_snap(mock_image_ctx, snap_id, snap_name); - }), - WithArg<1>(Invoke([this, r](Context *ctx) { - m_threads->work_queue->queue(ctx, r); - })))); + EXPECT_CALL(mock_snapshot_create_request, send()) + .WillOnce(DoAll(Invoke([&mock_image_ctx, snap_id, snap_name]() { + inject_snap(mock_image_ctx, snap_id, snap_name); + }), + Invoke([this, &mock_snapshot_create_request, r]() { + m_threads->work_queue->queue(mock_snapshot_create_request.on_finish, r); + }))); } void expect_snap_remove(librbd::MockImageCtx &mock_image_ctx, @@ -207,11 +240,12 @@ TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreate) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + MockSnapshotCreateRequest mock_snapshot_create_request; journal::MockJournaler mock_journaler; InSequence seq; - expect_snap_create(mock_local_image_ctx, "snap1", 12, 0); - expect_snap_create(mock_local_image_ctx, "snap2", 14, 0); + expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0); + expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap2", 14, 0); expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0); expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id2, false, 0); expect_update_client(mock_journaler, 0); @@ -232,10 +266,11 @@ TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateError) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + MockSnapshotCreateRequest mock_snapshot_create_request; journal::MockJournaler mock_journaler; InSequence seq; - expect_snap_create(mock_local_image_ctx, "snap1", 12, -EINVAL); + expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, -EINVAL); C_SaferCond ctx; MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx, @@ -253,13 +288,14 @@ TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapRemoveAndCreate) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + MockSnapshotCreateRequest mock_snapshot_create_request; journal::MockJournaler mock_journaler; InSequence seq; expect_snap_is_unprotected(mock_local_image_ctx, m_local_image_ctx->snap_ids["snap1"], true, 0); expect_snap_remove(mock_local_image_ctx, "snap1", 0); - expect_snap_create(mock_local_image_ctx, "snap1", 12, 0); + expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0); expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0); expect_update_client(mock_journaler, 0); @@ -357,6 +393,7 @@ TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapUnprotectRemove) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + MockSnapshotCreateRequest mock_snapshot_create_request; journal::MockJournaler mock_journaler; InSequence seq; @@ -364,7 +401,7 @@ TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapUnprotectRemove) { m_local_image_ctx->snap_ids["snap1"], false, 0); expect_snap_unprotect(mock_local_image_ctx, "snap1", 0); expect_snap_remove(mock_local_image_ctx, "snap1", 0); - expect_snap_create(mock_local_image_ctx, "snap1", 12, 0); + expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0); expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0); expect_update_client(mock_journaler, 0); @@ -386,10 +423,11 @@ TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateProtect) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + MockSnapshotCreateRequest mock_snapshot_create_request; journal::MockJournaler mock_journaler; InSequence seq; - expect_snap_create(mock_local_image_ctx, "snap1", 12, 0); + expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0); expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0); expect_snap_is_protected(mock_local_image_ctx, 12, false, 0); expect_snap_protect(mock_local_image_ctx, "snap1", 0); diff --git a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc new file mode 100644 index 00000000000..f8778212053 --- /dev/null +++ b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc @@ -0,0 +1,137 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/rbd_mirror/test_mock_fixture.h" +#include "test/librados_test_stub/LibradosTestStub.h" +#include "include/rbd/librbd.hpp" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Operations.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h" +#include "tools/rbd_mirror/Threads.h" + +// template definitions +#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc" +template class rbd::mirror::image_sync::SnapshotCreateRequest; + +namespace rbd { +namespace mirror { +namespace image_sync { + +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::InvokeWithoutArgs; +using ::testing::Return; +using ::testing::StrEq; +using ::testing::WithArg; + +class TestMockImageSyncSnapshotCreateRequest : public TestMockFixture { +public: + typedef SnapshotCreateRequest MockSnapshotCreateRequest; + + virtual void SetUp() { + TestMockFixture::SetUp(); + + librbd::RBD rbd; + ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); + ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx)); + } + + void expect_set_size(librbd::MockImageCtx &mock_image_ctx, int r) { + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_size"), _, _, _)) + .WillOnce(Return(r)); + } + + void expect_snap_create(librbd::MockImageCtx &mock_image_ctx, + const std::string &snap_name, uint64_t snap_id, int r) { + EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, 0)) + .WillOnce(DoAll(InvokeWithoutArgs([&mock_image_ctx, snap_id, snap_name]() { + inject_snap(mock_image_ctx, snap_id, snap_name); + }), + WithArg<1>(Invoke([this, r](Context *ctx) { + m_threads->work_queue->queue(ctx, r); + })))); + } + + static void inject_snap(librbd::MockImageCtx &mock_image_ctx, + uint64_t snap_id, const std::string &snap_name) { + mock_image_ctx.snap_ids[snap_name] = snap_id; + } + + MockSnapshotCreateRequest *create_request(librbd::MockImageCtx &mock_local_image_ctx, + const std::string &snap_name, + uint64_t size, Context *on_finish) { + return new MockSnapshotCreateRequest(&mock_local_image_ctx, snap_name, size, + on_finish); + } + + librbd::ImageCtx *m_local_image_ctx; +}; + +TEST_F(TestMockImageSyncSnapshotCreateRequest, Resize) { + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + InSequence seq; + expect_set_size(mock_local_image_ctx, 0); + expect_snap_create(mock_local_image_ctx, "snap1", 10, 0); + + C_SaferCond ctx; + MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx, + "snap1", 123, + &ctx); + request->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeError) { + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + InSequence seq; + expect_set_size(mock_local_image_ctx, -EINVAL); + + C_SaferCond ctx; + MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx, + "snap1", 123, + &ctx); + request->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + +TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreate) { + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + InSequence seq; + expect_snap_create(mock_local_image_ctx, "snap1", 10, 0); + + C_SaferCond ctx; + MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx, + "snap1", + m_local_image_ctx->size, + &ctx); + request->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreateError) { + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + InSequence seq; + expect_snap_create(mock_local_image_ctx, "snap1", 10, -EINVAL); + + C_SaferCond ctx; + MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx, + "snap1", + m_local_image_ctx->size, + &ctx); + request->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + +} // namespace image_sync +} // namespace mirror +} // namespace rbd diff --git a/src/tools/Makefile-client.am b/src/tools/Makefile-client.am index a1b2e95675d..7b80aac1e8e 100644 --- a/src/tools/Makefile-client.am +++ b/src/tools/Makefile-client.am @@ -104,6 +104,7 @@ librbd_mirror_internal_la_SOURCES = \ tools/rbd_mirror/image_sync/ImageCopyRequest.cc \ tools/rbd_mirror/image_sync/ObjectCopyRequest.cc \ tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc \ + tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc \ tools/rbd_mirror/image_sync/SyncPointCreateRequest.cc \ tools/rbd_mirror/image_sync/SyncPointPruneRequest.cc noinst_LTLIBRARIES += librbd_mirror_internal.la @@ -124,6 +125,7 @@ noinst_HEADERS += \ tools/rbd_mirror/image_sync/ImageCopyRequest.h \ tools/rbd_mirror/image_sync/ObjectCopyRequest.h \ tools/rbd_mirror/image_sync/SnapshotCopyRequest.h \ + tools/rbd_mirror/image_sync/SnapshotCreateRequest.h \ tools/rbd_mirror/image_sync/SyncPointCreateRequest.h \ tools/rbd_mirror/image_sync/SyncPointPruneRequest.h diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc index ca687c99a7c..9d90bc9a37d 100644 --- a/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc +++ b/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "SnapshotCopyRequest.h" +#include "SnapshotCreateRequest.h" #include "common/errno.h" #include "journal/Journaler.h" #include "librbd/Operations.h" @@ -35,8 +36,6 @@ const std::string &get_snapshot_name(I *image_ctx, librados::snap_t snap_id) { using librbd::util::create_context_callback; - - template SnapshotCopyRequest::SnapshotCopyRequest(I *local_image_ctx, I *remote_image_ctx, @@ -237,6 +236,8 @@ void SnapshotCopyRequest::handle_snap_remove(int r) { template void SnapshotCopyRequest::send_snap_create() { + CephContext *cct = m_local_image_ctx->cct; + SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin(); if (m_prev_snap_id != CEPH_NOSNAP) { snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id); @@ -261,7 +262,18 @@ void SnapshotCopyRequest::send_snap_create() { m_prev_snap_id = *snap_id_it; m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id); - CephContext *cct = m_local_image_ctx->cct; + m_remote_image_ctx->snap_lock.get_read(); + auto snap_info_it = m_remote_image_ctx->snap_info.find(m_prev_snap_id); + if (snap_info_it == m_remote_image_ctx->snap_info.end()) { + m_remote_image_ctx->snap_lock.put_read(); + lderr(cct) << "failed to retrieve remote snap info: " << m_snap_name + << dendl; + finish(-ENOENT); + return; + } + uint64_t size = snap_info_it->second.size; + m_remote_image_ctx->snap_lock.put_read(); + ldout(cct, 20) << ": " << "snap_name=" << m_snap_name << ", " << "snap_id=" << m_prev_snap_id << dendl; @@ -269,9 +281,9 @@ void SnapshotCopyRequest::send_snap_create() { Context *ctx = create_context_callback< SnapshotCopyRequest, &SnapshotCopyRequest::handle_snap_create>( this); - RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); - m_local_image_ctx->operations->execute_snap_create(m_snap_name.c_str(), ctx, - 0U); + SnapshotCreateRequest *req = SnapshotCreateRequest::create( + m_local_image_ctx, m_snap_name, size, ctx); + req->send(); } template diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc new file mode 100644 index 00000000000..7b5ce250cb9 --- /dev/null +++ b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc @@ -0,0 +1,191 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "SnapshotCreateRequest.h" +#include "common/errno.h" +#include "cls/rbd/cls_rbd_client.h" +#include "librbd/Operations.h" +#include "librbd/Utils.h" + +#define dout_subsys ceph_subsys_rbd_mirror +#undef dout_prefix +#define dout_prefix *_dout << "rbd::mirror::image_sync::SnapshotCreateRequest: " \ + << this << " " << __func__ + +namespace rbd { +namespace mirror { +namespace image_sync { + +using librbd::util::create_context_callback; +using librbd::util::create_rados_safe_callback; + +template +SnapshotCreateRequest::SnapshotCreateRequest(I *local_image_ctx, + const std::string &snap_name, + uint64_t size, + Context *on_finish) + : m_local_image_ctx(local_image_ctx), m_snap_name(snap_name), m_size(size), + m_on_finish(on_finish) { +} + +template +void SnapshotCreateRequest::send() { + send_set_size(); +} + +template +void SnapshotCreateRequest::send_set_size() { + m_local_image_ctx->snap_lock.get_read(); + if (m_local_image_ctx->size == m_size) { + m_local_image_ctx->snap_lock.put_read(); + send_remove_parent(); + return; + } + m_local_image_ctx->snap_lock.put_read(); + + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << dendl; + + // Change the image size on disk so that the snapshot picks up + // the expected size. We can do this because the last snapshot + // we process is the sync snapshot which was created to match the + // image size. We also don't need to worry about trimming because + // we track the highest possible object number within the sync record + librados::ObjectWriteOperation op; + librbd::cls_client::set_size(&op, m_size); + + librados::AioCompletion *comp = create_rados_safe_callback< + SnapshotCreateRequest, &SnapshotCreateRequest::handle_set_size>(this); + int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid, + comp, &op); + assert(r == 0); + comp->release(); +} + +template +void SnapshotCreateRequest::handle_set_size(int r) { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": r=" << r << dendl; + + if (r < 0) { + lderr(cct) << ": failed to update image size '" << m_snap_name << "': " + << cpp_strerror(r) << dendl; + finish(r); + return; + } + + { + // adjust in-memory image size now that it's updated on disk + RWLock::WLocker snap_locker(m_local_image_ctx->snap_lock); + m_local_image_ctx->size = m_size; + } + + send_remove_parent(); +} + +template +void SnapshotCreateRequest::send_remove_parent() { + // TODO: issue #14937 needs to add support for cloned images + if (true) { + send_snap_create(); + return; + } + + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << dendl; + +} + +template +void SnapshotCreateRequest::handle_remove_parent(int r) { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": r=" << r << dendl; + + // TODO: issue #14937 needs to add support for cloned images +} + +template +void SnapshotCreateRequest::send_set_parent() { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << dendl; + + // TODO: issue #14937 needs to add support for cloned images +} + +template +void SnapshotCreateRequest::handle_set_parent(int r) { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": r=" << r << dendl; + + // TODO: issue #14937 needs to add support for cloned images +} + +template +void SnapshotCreateRequest::send_snap_create() { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": snap_name=" << m_snap_name << dendl; + + Context *ctx = create_context_callback< + SnapshotCreateRequest, &SnapshotCreateRequest::handle_snap_create>( + this); + RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); + m_local_image_ctx->operations->execute_snap_create(m_snap_name.c_str(), ctx, + 0U); +} + +template +void SnapshotCreateRequest::handle_snap_create(int r) { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": r=" << r << dendl; + + if (r < 0) { + lderr(cct) << ": failed to create snapshot '" << m_snap_name << "': " + << cpp_strerror(r) << dendl; + finish(r); + return; + } + + send_create_object_map(); +} +template +void SnapshotCreateRequest::send_create_object_map() { + // TODO + if (true) { + finish(0); + return; + } + + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << dendl; + +} + +template +void SnapshotCreateRequest::handle_create_object_map(int r) { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": r=" << r << dendl; + + if (r < 0) { + lderr(cct) << ": failed to create object map: " << cpp_strerror(r) + << dendl; + finish(r); + return; + } + + finish(0); +} + +template +void SnapshotCreateRequest::finish(int r) { + CephContext *cct = m_local_image_ctx->cct; + ldout(cct, 20) << ": r=" << r << dendl; + + m_on_finish->complete(r); + delete this; +} + +} // namespace image_sync +} // namespace mirror +} // namespace rbd + +template class rbd::mirror::image_sync::SnapshotCreateRequest; diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.h b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.h new file mode 100644 index 00000000000..897c7b9d8ac --- /dev/null +++ b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.h @@ -0,0 +1,95 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_CREATE_REQUEST_H +#define RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_CREATE_REQUEST_H + +#include "include/int_types.h" +#include "include/rados/librados.hpp" +#include "common/snap_types.h" +#include "librbd/ImageCtx.h" +#include "librbd/journal/TypeTraits.h" +#include +#include +#include +#include + +class Context; + +namespace rbd { +namespace mirror { +namespace image_sync { + +template +class SnapshotCreateRequest { +public: + static SnapshotCreateRequest* create(ImageCtxT *local_image_ctx, + const std::string &snap_name, + uint64_t size, Context *on_finish) { + return new SnapshotCreateRequest(local_image_ctx, snap_name, size, + on_finish); + } + + SnapshotCreateRequest(ImageCtxT *local_image_ctx, + const std::string &snap_name, uint64_t size, + Context *on_finish); + + void send(); + +private: + /** + * @verbatim + * + * + * | + * v (skip if not needed) + * SET_SIZE + * | + * v (skip if not needed) + * REMOVE_PARENT + * | + * v (skip if not needed) + * SET_PARENT + * | + * v + * CREATE_SNAP + * | + * v (skip if not needed) + * CREATE_OBJECT_MAP + * | + * v + * + * + * @endverbatim + */ + + ImageCtxT *m_local_image_ctx; + std::string m_snap_name; + uint64_t m_size; + Context *m_on_finish; + + void send_set_size(); + void handle_set_size(int r); + + void send_remove_parent(); + void handle_remove_parent(int r); + + void send_set_parent(); + void handle_set_parent(int r); + + void send_snap_create(); + void handle_snap_create(int r); + + void send_create_object_map(); + void handle_create_object_map(int r); + + void finish(int r); +}; + +} // namespace image_sync +} // namespace mirror +} // namespace rbd + +extern template class rbd::mirror::image_sync::SnapshotCreateRequest; + +#endif // RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_CREATE_REQUEST_H