This is an automated email from the ASF dual-hosted git repository.

gfphoenix78 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git


The following commit(s) were added to refs/heads/main by this push:
     new 43e26c79fb1 Fix memory leak for bitmap in PAX
43e26c79fb1 is described below

commit 43e26c79fb10296fa313e92f23046e70b42efae2
Author: Hao Wu <gfphoeni...@gmail.com>
AuthorDate: Sun Aug 17 16:26:03 2025 +0800

    Fix memory leak for bitmap in PAX
    
    Bitmap should free memory if the memory is allocated by itself.
---
 contrib/pax_storage/src/cpp/access/pax_visimap.cc  |  3 +-
 contrib/pax_storage/src/cpp/comm/bitmap.h          | 45 +++++++++-------------
 .../src/cpp/storage/orc/orc_format_reader.cc       |  3 +-
 contrib/pax_storage/src/cpp/storage/pax.cc         |  6 +--
 .../src/cpp/storage/vec/pax_porc_adpater.cc        |  3 +-
 .../src/cpp/storage/vec_parallel_pax.cc            |  2 +-
 6 files changed, 25 insertions(+), 37 deletions(-)

diff --git a/contrib/pax_storage/src/cpp/access/pax_visimap.cc 
b/contrib/pax_storage/src/cpp/access/pax_visimap.cc
index b96752d31ba..cdc7dfe763e 100644
--- a/contrib/pax_storage/src/cpp/access/pax_visimap.cc
+++ b/contrib/pax_storage/src/cpp/access/pax_visimap.cc
@@ -143,8 +143,7 @@ bool TestVisimap(Relation rel, const char *visimap_name, 
int offset) {
   fs = Singleton<LocalFileSystem>::GetInstance();
 
   auto visimap = LoadVisimap(fs, options, file_path);
-  auto bm = Bitmap8(BitmapRaw<uint8>(visimap->data(), visimap->size()),
-                    Bitmap8::ReadOnlyOwnBitmap);
+  auto bm = Bitmap8(BitmapRaw<uint8>(visimap->data(), visimap->size()));
   auto is_set = bm.Test(offset);
   return !is_set;
 }
diff --git a/contrib/pax_storage/src/cpp/comm/bitmap.h 
b/contrib/pax_storage/src/cpp/comm/bitmap.h
index 1fc831f1787..793f85d668c 100644
--- a/contrib/pax_storage/src/cpp/comm/bitmap.h
+++ b/contrib/pax_storage/src/cpp/comm/bitmap.h
@@ -147,19 +147,9 @@ struct BitmapRaw final {
     raw.bitmap = nullptr;
     raw.size = 0;
   }
-  BitmapRaw &operator=(BitmapRaw) = delete;
   BitmapRaw &operator=(BitmapRaw &) = delete;
   BitmapRaw &operator=(const BitmapRaw &) = delete;
-  BitmapRaw &operator=(BitmapRaw &&raw) {
-    if (this != &raw) {
-      PAX_DELETE_ARRAY(bitmap);
-      bitmap = raw.bitmap;
-      size = raw.size;
-      raw.bitmap = nullptr;
-      raw.size = 0;
-    }
-    return *this;
-  }
+  BitmapRaw &operator=(BitmapRaw &&raw) = delete;
 
   ~BitmapRaw() = default;
 
@@ -171,40 +161,46 @@ template <typename T>
 class BitmapTpl final {
  public:
   using BitmapMemoryPolicy = void (*)(BitmapRaw<T> &, uint32);
-  explicit BitmapTpl(uint32 initial_size = 16,
-                     BitmapMemoryPolicy policy = DefaultBitmapMemoryPolicy) {
+  explicit BitmapTpl(uint32 initial_size = 16) {
     static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 ||
                   sizeof(T) == 8);
     static_assert(BM_WORD_BITS == (1 << BM_WORD_SHIFTS));
-    policy_ = policy;
-    policy(raw_, Max(initial_size, 16));
+    policy_ = DefaultBitmapMemoryPolicy;
+    policy_(raw_, Max(initial_size, 16));
   }
-  explicit BitmapTpl(const BitmapRaw<T> &raw, BitmapMemoryPolicy policy) {
+  explicit BitmapTpl(const BitmapRaw<T> &raw) {
     static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 ||
                   sizeof(T) == 8);
     static_assert(BM_WORD_BITS == (1 << BM_WORD_SHIFTS));
-    Assert(policy == ReadOnlyRefBitmap || policy == ReadOnlyOwnBitmap);
-    policy_ = policy;
+    policy_ = ReadOnlyRefBitmap;
     raw_.bitmap = raw.bitmap;
     raw_.size = raw.size;
   }
   BitmapTpl(const BitmapTpl &tpl) = delete;
   BitmapTpl(BitmapTpl &&tpl)
-      : raw_(std::move(tpl.raw_)), policy_(tpl.policy_) {}
+      : raw_(std::move(tpl.raw_)), policy_(tpl.policy_) {
+    tpl.raw_.bitmap = nullptr;
+    tpl.policy_ = ReadOnlyRefBitmap;
+  }
   BitmapTpl(BitmapRaw<T> &&raw)
-      : raw_(std::move(raw)), policy_(DefaultBitmapMemoryPolicy) {}
+      : raw_(std::move(raw)), policy_(ReadOnlyRefBitmap) {}
   BitmapTpl &operator=(const BitmapTpl &tpl) = delete;
   BitmapTpl &operator=(BitmapTpl &&tpl) = delete;
   ~BitmapTpl() {
     // Reference doesn't free the memory
-    if (policy_ == ReadOnlyRefBitmap) raw_.bitmap = nullptr;
+    if (policy_ == DefaultBitmapMemoryPolicy)
+      PAX_DELETE_ARRAY(raw_.bitmap);
+    raw_.bitmap = nullptr;
   }
 
   std::unique_ptr<BitmapTpl> Clone() const {
+    auto bm = std::make_unique<BitmapTpl>(raw_);
     auto p = PAX_NEW_ARRAY<T>(raw_.size);
     memcpy(p, raw_.bitmap, sizeof(T) * raw_.size);
-    BitmapRaw<T> bm_raw(p, raw_.size);
-    return std::make_unique<BitmapTpl>(std::move(bm_raw));
+    bm->raw_.bitmap = p;
+    bm->raw_.size = raw_.size;
+    bm->policy_ = DefaultBitmapMemoryPolicy;
+    return bm;
   }
 
   inline size_t WordBits() const { return BM_WORD_BITS; }
@@ -272,9 +268,6 @@ class BitmapTpl final {
     // raise
     CBDB_RAISE(cbdb::CException::kExTypeInvalidMemoryOperation);
   }
-  static void ReadOnlyOwnBitmap(BitmapRaw<T> & /*raw*/, uint32 /*index*/) {
-    CBDB_RAISE(cbdb::CException::kExTypeInvalidMemoryOperation);
-  }
 
   static inline size_t RequireWords(size_t nbits) {
     return nbits ? ((nbits - 1) >> BM_WORD_SHIFTS) + 1 : 0;
diff --git a/contrib/pax_storage/src/cpp/storage/orc/orc_format_reader.cc 
b/contrib/pax_storage/src/cpp/storage/orc/orc_format_reader.cc
index 94ac27bbf4c..2fa58790d97 100644
--- a/contrib/pax_storage/src/cpp/storage/orc/orc_format_reader.cc
+++ b/contrib/pax_storage/src/cpp/storage/orc/orc_format_reader.cc
@@ -909,8 +909,7 @@ std::unique_ptr<PaxColumns> OrcFormatReader::ReadStripe(
           reinterpret_cast<uint8 *>(data_buffer->GetAvailableBuffer());
 
       Assert(non_null_stream.kind() == pax::porc::proto::Stream_Kind_PRESENT);
-      non_null_bitmap = std::make_unique<Bitmap8>(BitmapRaw<uint8>(bm_bytes, 
bm_nbytes),
-                                         BitmapTpl<uint8>::ReadOnlyRefBitmap);
+      non_null_bitmap = std::make_unique<Bitmap8>(BitmapRaw<uint8>(bm_bytes, 
bm_nbytes));
       data_buffer->Brush(bm_nbytes);
     }
 
diff --git a/contrib/pax_storage/src/cpp/storage/pax.cc 
b/contrib/pax_storage/src/cpp/storage/pax.cc
index d1b2000009c..ab10387c76c 100644
--- a/contrib/pax_storage/src/cpp/storage/pax.cc
+++ b/contrib/pax_storage/src/cpp/storage/pax.cc
@@ -615,8 +615,7 @@ void TableDeleter::DeleteWithVisibilityMap(
         auto buffer = LoadVisimap(file_system_, file_system_options_,
                                   visibility_map_filename);
         auto visibility_file_bitmap =
-            Bitmap8(BitmapRaw<uint8>(buffer->data(), buffer->size()),
-                    Bitmap8::ReadOnlyOwnBitmap);
+            Bitmap8(BitmapRaw<uint8>(buffer->data(), buffer->size()));
         visi_bitmap =
             Bitmap8::Union(&visibility_file_bitmap, delete_visi_bitmap.get());
 
@@ -664,8 +663,7 @@ void TableDeleter::DeleteWithVisibilityMap(
     // Update the stats in pax aux table
     // Notice that: PAX won't update the stats in group
     UpdateStatsInAuxTable(catalog_update, micro_partition_metadata,
-                          std::make_shared<Bitmap8>(visi_bitmap->Raw(),
-                                                    
Bitmap8::ReadOnlyOwnBitmap),
+                          std::make_shared<Bitmap8>(visi_bitmap->Raw()),
                           min_max_col_idxs,
                           cbdb::GetBloomFilterColumnIndexes(rel_),
                           stats_updater_projection);
diff --git a/contrib/pax_storage/src/cpp/storage/vec/pax_porc_adpater.cc 
b/contrib/pax_storage/src/cpp/storage/vec/pax_porc_adpater.cc
index 9cfcc49b091..65eeb4e88ae 100644
--- a/contrib/pax_storage/src/cpp/storage/vec/pax_porc_adpater.cc
+++ b/contrib/pax_storage/src/cpp/storage/vec/pax_porc_adpater.cc
@@ -576,8 +576,7 @@ std::pair<size_t, size_t> 
VecAdapter::AppendPorcFormat(PaxColumns *columns,
         vec_buffer->Set(boolean_buffer, align_size);
 
         Bitmap8 vec_bool_bitmap(
-            BitmapRaw<uint8>((uint8 *)(boolean_buffer), align_size),
-            BitmapTpl<uint8>::ReadOnlyRefBitmap);
+            BitmapRaw<uint8>((uint8 *)(boolean_buffer), align_size));
 
         CopyBitPackedBuffer(column, micro_partition_visibility_bitmap_,
                             group_base_offset_, range_begin, range_lens,
diff --git a/contrib/pax_storage/src/cpp/storage/vec_parallel_pax.cc 
b/contrib/pax_storage/src/cpp/storage/vec_parallel_pax.cc
index a93d5d17646..632be28f827 100644
--- a/contrib/pax_storage/src/cpp/storage/vec_parallel_pax.cc
+++ b/contrib/pax_storage/src/cpp/storage/vec_parallel_pax.cc
@@ -60,7 +60,7 @@ class MicroPartitionInfo : public MicroPartitionInfoProvider {
     if (!visimap_name.empty()) {
       visimap = pax::LoadVisimap(file_system, nullptr, visimap_name);
       BitmapRaw<uint8_t> raw(visimap->data(), visimap->size());
-      bitmap = std::make_unique<Bitmap8>(raw, 
BitmapTpl<uint8>::ReadOnlyRefBitmap);
+      bitmap = std::make_unique<Bitmap8>(raw);
     }
     return {std::move(visimap), std::move(bitmap)};
   }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cloudberry.apache.org
For additional commands, e-mail: commits-h...@cloudberry.apache.org

Reply via email to