test/cls/rgw: test that index entry is removed after racing deletes

Signed-off-by: Casey Bodley <cbodley@redhat.com>
This commit is contained in:
Casey Bodley 2023-02-09 13:45:10 -05:00
parent 08efcc2536
commit 5ddde6eb3d

View 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);
}