]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: tests: Support for inflight image sync point update 9699/head
authorRicardo Dias <rdias@suse.com>
Tue, 14 Jun 2016 15:43:19 +0000 (16:43 +0100)
committerRicardo Dias <rdias@suse.com>
Mon, 27 Jun 2016 13:51:34 +0000 (14:51 +0100)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc

index ca6326e2fd2b016f98c9dd0bd3a790e076bff407..3d0855f31af72d0bf3b79848c8e521561d862ff2 100644 (file)
@@ -50,7 +50,7 @@ struct ObjectCopyRequest<librbd::MockImageCtx> {
   Mutex lock;
   Cond cond;
 
-  const ImageCopyRequest<librbd::MockImageCtx>::SnapMap *snap_map;
+  const ImageCopyRequest<librbd::MockImageCtx>::SnapMap *snap_map = nullptr;
   std::map<uint64_t, Context *> 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<void()> 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<uint64_t> 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<void()> 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<void()> 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}};