]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test/cls/rgw: test that index entry is removed after racing deletes 50241/head
authorCasey Bodley <cbodley@redhat.com>
Thu, 9 Feb 2023 18:45:10 +0000 (13:45 -0500)
committerCasey Bodley <cbodley@redhat.com>
Thu, 23 Feb 2023 19:20:37 +0000 (14:20 -0500)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 5ddde6eb3d6a9e387b904fa4986bfb8e2ccbef7a)

src/test/cls_rgw/test_cls_rgw.cc

index c37521a248fd18a716187175d6f0f49410c09129..4b9d2d072b836e38b5ba46d57d74b844da8f360f 100644 (file)
@@ -1252,3 +1252,91 @@ TEST_F(cls_rgw, bi_log_trim)
     EXPECT_FALSE(truncated);
   }
 }
+
+TEST_F(cls_rgw, index_racing_removes)
+{
+  string bucket_oid = str_int("bucket", 8);
+
+  ObjectWriteOperation op;
+  cls_rgw_bucket_init_index(op);
+  ASSERT_EQ(0, ioctx.operate(bucket_oid, &op));
+
+  int epoch = 0;
+  rgw_bucket_dir_entry dirent;
+  rgw_bucket_dir_entry_meta meta;
+
+  // prepare/complete add for single object
+  const cls_rgw_obj_key obj{"obj"};
+  std::string loc = "loc";
+  {
+    std::string tag = "tag-add";
+    index_prepare(ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc);
+    index_complete(ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, ++epoch, obj, meta);
+    test_stats(ioctx, bucket_oid, RGWObjCategory::None, 1, 0);
+  }
+
+  // list to verify no pending ops
+  {
+    std::map<int, rgw_cls_list_ret> results;
+    list_entries(ioctx, bucket_oid, 1, results);
+    ASSERT_EQ(1, results.size());
+    const auto& entries = results.begin()->second.dir.m;
+    ASSERT_EQ(1, entries.size());
+    dirent = std::move(entries.begin()->second);
+    ASSERT_EQ(obj, dirent.key);
+    ASSERT_TRUE(dirent.exists);
+    ASSERT_TRUE(dirent.pending_map.empty());
+  }
+
+  // prepare three racing removals
+  std::string tag1 = "tag-rm1";
+  std::string tag2 = "tag-rm2";
+  std::string tag3 = "tag-rm3";
+  index_prepare(ioctx, bucket_oid, CLS_RGW_OP_DEL, tag1, obj, loc);
+  index_prepare(ioctx, bucket_oid, CLS_RGW_OP_DEL, tag2, obj, loc);
+  index_prepare(ioctx, bucket_oid, CLS_RGW_OP_DEL, tag3, obj, loc);
+
+  test_stats(ioctx, bucket_oid, RGWObjCategory::None, 1, 0);
+
+  // complete on tag2
+  index_complete(ioctx, bucket_oid, CLS_RGW_OP_DEL, tag2, ++epoch, obj, meta);
+  {
+    std::map<int, rgw_cls_list_ret> results;
+    list_entries(ioctx, bucket_oid, 1, results);
+    ASSERT_EQ(1, results.size());
+    const auto& entries = results.begin()->second.dir.m;
+    ASSERT_EQ(1, entries.size());
+    dirent = std::move(entries.begin()->second);
+    ASSERT_EQ(obj, dirent.key);
+    ASSERT_FALSE(dirent.exists);
+    ASSERT_FALSE(dirent.pending_map.empty());
+  }
+
+  // cancel on tag1
+  index_complete(ioctx, bucket_oid, CLS_RGW_OP_CANCEL, tag1, ++epoch, obj, meta);
+  {
+    std::map<int, rgw_cls_list_ret> results;
+    list_entries(ioctx, bucket_oid, 1, results);
+    ASSERT_EQ(1, results.size());
+    const auto& entries = results.begin()->second.dir.m;
+    ASSERT_EQ(1, entries.size());
+    dirent = std::move(entries.begin()->second);
+    ASSERT_EQ(obj, dirent.key);
+    ASSERT_FALSE(dirent.exists);
+    ASSERT_FALSE(dirent.pending_map.empty());
+  }
+
+  // final cancel on tag3
+  index_complete(ioctx, bucket_oid, CLS_RGW_OP_CANCEL, tag3, ++epoch, obj, meta);
+
+  // verify that the key was removed
+  {
+    std::map<int, rgw_cls_list_ret> results;
+    list_entries(ioctx, bucket_oid, 1, results);
+    EXPECT_EQ(1, results.size());
+    const auto& entries = results.begin()->second.dir.m;
+    ASSERT_EQ(0, entries.size());
+  }
+
+  test_stats(ioctx, bucket_oid, RGWObjCategory::None, 0, 0);
+}