This is an automated email from the ASF dual-hosted git repository.
liaoxin01 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new d7ec4abd781 [fix](cloud) Decrement delete bitmap packed file ref
counts when recycling tablets (#66919)
d7ec4abd781 is described below
commit d7ec4abd78153f88eea4aa18c379bc3d0637b653
Author: Yixuan Wang <[email protected]>
AuthorDate: Tue Aug 25 17:24:56 2026 +0800
[fix](cloud) Decrement delete bitmap packed file ref counts when recycling
tablets (#66919)
### What problem does this PR solve?
Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
When recycling a dropped tablet, recycle_tablet decremented packed file
reference counts for rowset data but omitted packed delete bitmap files.
As a result, delete bitmap packed file metadata and objects could remain
after all referenced rowsets had been recycled.
Call decrement_delete_bitmap_packed_file_ref_counts for both regular
rowsets and restore-job rowsets before deleting the tablet metadata.
Add a unit test that constructs a blob-backed delete bitmap referencing
a packed file. The test failed before the fix because the packed file KV
and object remained, and passes after the fix.
---
cloud/src/recycler/recycler.cpp | 16 ++++++++++++++++
cloud/test/recycler_test.cpp | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/cloud/src/recycler/recycler.cpp b/cloud/src/recycler/recycler.cpp
index 4efbf55004e..d191c7eb3ce 100644
--- a/cloud/src/recycler/recycler.cpp
+++ b/cloud/src/recycler/recycler.cpp
@@ -5070,6 +5070,14 @@ int InstanceRecycler::recycle_tablet(int64_t tablet_id,
RecyclerMetricsContext&
.tag("rowset_id", rs_meta.rowset_id_v2());
return -1;
}
+ if (decrement_delete_bitmap_packed_file_ref_counts(tablet_id,
rs_meta.rowset_id_v2(),
+ nullptr) != 0) {
+ LOG_WARNING("failed to decrement delete bitmap packed file ref
count")
+ .tag("instance_id", instance_id_)
+ .tag("tablet_id", tablet_id)
+ .tag("rowset_id", rs_meta.rowset_id_v2());
+ return -1;
+ }
recycle_rowsets_number += 1;
recycle_segments_number += rs_meta.num_segments();
recycle_rowsets_data_size += rs_meta.data_disk_size();
@@ -5122,6 +5130,14 @@ int InstanceRecycler::recycle_tablet(int64_t tablet_id,
RecyclerMetricsContext&
.tag("rowset_id", rs_meta.rowset_id_v2());
return -1;
}
+ if (decrement_delete_bitmap_packed_file_ref_counts(tablet_id,
rs_meta.rowset_id_v2(),
+ nullptr) != 0) {
+ LOG_WARNING("failed to decrement delete bitmap packed file ref
count")
+ .tag("instance_id", instance_id_)
+ .tag("tablet_id", tablet_id)
+ .tag("rowset_id", rs_meta.rowset_id_v2());
+ return -1;
+ }
recycle_restore_job_rowsets_number += 1;
recycle_restore_job_segments_number += rs_meta.num_segments();
recycle_restore_job_rowsets_data_size += rs_meta.data_disk_size();
diff --git a/cloud/test/recycler_test.cpp b/cloud/test/recycler_test.cpp
index c5a0a150b95..f84af017a6b 100644
--- a/cloud/test/recycler_test.cpp
+++ b/cloud/test/recycler_test.cpp
@@ -3617,10 +3617,41 @@ TEST(RecyclerTest,
recycle_tablet_packed_file_ref_count) {
}
std::string merged_key = packed_file_key({instance_id, packed_file_path});
txn->put(merged_key, merged_info.SerializeAsString());
+
+ // Delete bitmap metadata is stored as a blob and its packed-file slice
must be
+ // decremented when the tablet is recycled as well.
+ const std::string delete_bitmap_packed_file_path =
+ fmt::format("data/merge_file/{}/delete_bitmap.dat", tablet_id);
+ const std::string delete_bitmap_key = versioned::meta_delete_bitmap_key(
+ {instance_id, tablet_id, merged_rowset.rowset_id_v2()});
+ DeleteBitmapStoragePB delete_bitmap_storage;
+ delete_bitmap_storage.set_store_in_fdb(false);
+ auto* delete_bitmap_location =
delete_bitmap_storage.mutable_packed_slice_location();
+
delete_bitmap_location->set_packed_file_path(delete_bitmap_packed_file_path);
+ delete_bitmap_location->set_offset(0);
+ delete_bitmap_location->set_size(kSmallFileSize);
+ cloud::blob_put(txn.get(), delete_bitmap_key, delete_bitmap_storage, 0);
+
+ PackedFileInfoPB delete_bitmap_info;
+ delete_bitmap_info.set_ref_cnt(1);
+ delete_bitmap_info.set_total_slice_num(1);
+ delete_bitmap_info.set_total_slice_bytes(kSmallFileSize);
+ delete_bitmap_info.set_remaining_slice_bytes(kSmallFileSize);
+ delete_bitmap_info.set_state(PackedFileInfoPB::NORMAL);
+ delete_bitmap_info.set_resource_id(std::string(kResourceId));
+ auto* delete_bitmap_slice = delete_bitmap_info.add_slices();
+ delete_bitmap_slice->set_path(delete_bitmap_path(tablet_id,
merged_rowset.rowset_id_v2()));
+ delete_bitmap_slice->set_offset(0);
+ delete_bitmap_slice->set_size(kSmallFileSize);
+ delete_bitmap_slice->set_rowset_id(merged_rowset.rowset_id_v2());
+ delete_bitmap_slice->set_tablet_id(tablet_id);
+ txn->put(packed_file_key({instance_id, delete_bitmap_packed_file_path}),
+ delete_bitmap_info.SerializeAsString());
ASSERT_EQ(TxnErrorCode::TXN_OK, txn->commit());
// Prepare object storage files.
ASSERT_EQ(0, accessor->put_file(packed_file_path, "payload"));
+ ASSERT_EQ(0, accessor->put_file(delete_bitmap_packed_file_path, "delete
bitmap payload"));
for (int i = 0; i < merged_rowset.num_segments(); ++i) {
auto path = segment_path(tablet_id, merged_rowset.rowset_id_v2(), i);
ASSERT_EQ(0, accessor->put_file(path, "segment"));
@@ -3637,6 +3668,11 @@ TEST(RecyclerTest, recycle_tablet_packed_file_ref_count)
{
std::string merged_val;
EXPECT_EQ(TxnErrorCode::TXN_KEY_NOT_FOUND, txn->get(merged_key,
&merged_val));
EXPECT_EQ(1, accessor->exists(packed_file_path));
+ std::string delete_bitmap_packed_file_val;
+ EXPECT_EQ(TxnErrorCode::TXN_KEY_NOT_FOUND,
+ txn->get(packed_file_key({instance_id,
delete_bitmap_packed_file_path}),
+ &delete_bitmap_packed_file_val));
+ EXPECT_EQ(1, accessor->exists(delete_bitmap_packed_file_path));
// tablet directory should be cleaned.
std::unique_ptr<ListIterator> list_iter;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]