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]

Reply via email to