From baa45b21a285d22e206b809243c234aadc3becba Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 9 Feb 2023 13:45:10 -0500 Subject: [PATCH] test/cls/rgw: test that index entry is removed after racing deletes Signed-off-by: Casey Bodley (cherry picked from commit 5ddde6eb3d6a9e387b904fa4986bfb8e2ccbef7a) --- src/test/cls_rgw/test_cls_rgw.cc | 88 ++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/test/cls_rgw/test_cls_rgw.cc b/src/test/cls_rgw/test_cls_rgw.cc index c37521a248fd1..4b9d2d072b836 100644 --- a/src/test/cls_rgw/test_cls_rgw.cc +++ b/src/test/cls_rgw/test_cls_rgw.cc @@ -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 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 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 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 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); +} -- 2.39.5