From cee543bd96bc99f219024aedbfafc5dcd99abb5a Mon Sep 17 00:00:00 2001 From: Ricardo Dias Date: Tue, 14 Jun 2016 16:43:19 +0100 Subject: [PATCH] rbd-mirror: tests: Support for inflight image sync point update Signed-off-by: Ricardo Dias --- .../image_sync/test_mock_ImageCopyRequest.cc | 131 ++++++++++++++++-- 1 file changed, 119 insertions(+), 12 deletions(-) diff --git a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc index ca6326e2fd2b..3d0855f31af7 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc @@ -50,7 +50,7 @@ struct ObjectCopyRequest { Mutex lock; Cond cond; - const ImageCopyRequest::SnapMap *snap_map; + const ImageCopyRequest::SnapMap *snap_map = nullptr; std::map object_contexts; ObjectCopyRequest() : lock("lock") { @@ -119,7 +119,8 @@ public: } bool complete_object_copy(MockObjectCopyRequest &mock_object_copy_request, - uint64_t object_num, int r) { + uint64_t object_num, int r, + std::function fn = []() {}) { Mutex::Locker locker(mock_object_copy_request.lock); while (mock_object_copy_request.object_contexts.count(object_num) == 0) { if (mock_object_copy_request.cond.WaitInterval(m_local_image_ctx->cct, @@ -129,7 +130,12 @@ public: } } - m_threads->work_queue->queue(mock_object_copy_request.object_contexts[object_num], r); + FunctionContext *wrapper_ctx = new FunctionContext( + [&mock_object_copy_request, object_num, fn] (int r) { + fn(); + mock_object_copy_request.object_contexts[object_num]->complete(r); + }); + m_threads->work_queue->queue(wrapper_ctx, r); return true; } @@ -224,6 +230,20 @@ TEST_F(TestMockImageSyncImageCopyRequest, Throttled) { ASSERT_EQ(0, create_snap("snap1")); m_client_meta.sync_points = {{"snap1", boost::none}}; + std::string update_sync_age;; + ASSERT_EQ(0, _rados->conf_get("rbd_mirror_sync_point_update_age", update_sync_age)); + ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", "1")); + BOOST_SCOPE_EXIT( (update_sync_age) ) { + ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", update_sync_age.c_str())); + } BOOST_SCOPE_EXIT_END; + + + std::string max_ops_str; + ASSERT_EQ(0, _rados->conf_get("rbd_concurrent_management_ops", max_ops_str)); + int max_ops = std::stoi(max_ops_str); + + uint64_t object_count = 55; + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); journal::MockJournaler mock_journaler; @@ -231,14 +251,31 @@ TEST_F(TestMockImageSyncImageCopyRequest, Throttled) { expect_get_snap_id(mock_remote_image_ctx); - InSequence seq; - expect_get_object_count(mock_remote_image_ctx, 50); + expect_get_object_count(mock_remote_image_ctx, object_count); expect_get_object_count(mock_remote_image_ctx, 0); - expect_update_client(mock_journaler, 0); - for (int i = 0; i < 50; ++i) { - expect_object_copy_send(mock_object_copy_request); - } - expect_update_client(mock_journaler, 0); + + EXPECT_CALL(mock_object_copy_request, send()).Times(object_count); + + boost::optional expected_object_number(boost::none); + EXPECT_CALL(mock_journaler, update_client(_, _)) + .WillRepeatedly( + Invoke([&expected_object_number, max_ops, object_count, this] + (bufferlist data, Context *ctx) { + ASSERT_EQ(expected_object_number, + m_client_meta.sync_points.front().object_number); + if (!expected_object_number) { + expected_object_number = (max_ops - 1); + } else { + expected_object_number = expected_object_number.get() + max_ops; + } + + if (expected_object_number.get() > (object_count - 1)) { + expected_object_number = (object_count - 1); + } + + m_threads->work_queue->queue(ctx, 0); + })); + C_SaferCond ctx; MockImageCopyRequest *request = create_request(mock_remote_image_ctx, @@ -248,9 +285,17 @@ TEST_F(TestMockImageSyncImageCopyRequest, Throttled) { &ctx); request->send(); + std::function sleep_fn = [request]() { + sleep(2); + }; + ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request)); - for (uint64_t i = 0; i < 50; ++i) { - ASSERT_TRUE(complete_object_copy(mock_object_copy_request, i, 0)); + for (uint64_t i = 0; i < object_count; ++i) { + if (i % 10 == 0) { + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, i, 0, sleep_fn)); + } else { + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, i, 0)); + } } ASSERT_EQ(0, ctx.wait()); } @@ -396,6 +441,68 @@ TEST_F(TestMockImageSyncImageCopyRequest, Cancel) { ASSERT_EQ(-ECANCELED, ctx.wait()); } +TEST_F(TestMockImageSyncImageCopyRequest, Cancel_Inflight_Sync) { + std::string update_sync_age;; + ASSERT_EQ(0, _rados->conf_get("rbd_mirror_sync_point_update_age", update_sync_age)); + ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", "1")); + BOOST_SCOPE_EXIT( (update_sync_age) ) { + ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", update_sync_age.c_str())); + } BOOST_SCOPE_EXIT_END; + + std::string max_ops_str; + ASSERT_EQ(0, _rados->conf_get("rbd_concurrent_management_ops", max_ops_str)); + ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", "3")); + BOOST_SCOPE_EXIT( (max_ops_str) ) { + ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", max_ops_str.c_str())); + } BOOST_SCOPE_EXIT_END; + + ASSERT_EQ(0, create_snap("snap1")); + m_client_meta.sync_points = {{"snap1", boost::none}}; + + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + journal::MockJournaler mock_journaler; + MockObjectCopyRequest mock_object_copy_request; + + expect_get_snap_id(mock_remote_image_ctx); + + expect_get_object_count(mock_remote_image_ctx, 10); + expect_get_object_count(mock_remote_image_ctx, 0); + + EXPECT_CALL(mock_object_copy_request, send()).Times(6); + + EXPECT_CALL(mock_journaler, update_client(_, _)) + .WillRepeatedly(Invoke([this] (bufferlist data, Context *ctx) { + m_threads->work_queue->queue(ctx, 0); + })); + + + C_SaferCond ctx; + MockImageCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, + mock_journaler, + m_client_meta.sync_points.front(), + &ctx); + request->send(); + + ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request)); + + std::function cancel_fn = [request]() { + sleep(2); + request->cancel(); + }; + + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 0, 0)); + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 1, 0)); + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 2, 0)); + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 3, 0, cancel_fn)); + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 4, 0)); + ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 5, 0)); + + ASSERT_EQ(-ECANCELED, ctx.wait()); + ASSERT_EQ(5u, m_client_meta.sync_points.front().object_number.get()); +} + TEST_F(TestMockImageSyncImageCopyRequest, Cancel1) { ASSERT_EQ(0, create_snap("snap1")); m_client_meta.sync_points = {{"snap1", boost::none}}; -- 2.47.3