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

jvanderzee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 3ea4d8ff63 Implement RAII for `PreservationTable` (#11825)
3ea4d8ff63 is described below

commit 3ea4d8ff639c354cc9090ff42368c3be367867af
Author: JosiahWI <[email protected]>
AuthorDate: Thu Nov 7 16:13:20 2024 -0600

    Implement RAII for `PreservationTable` (#11825)
    
    * Add a constructor to `PreservationTable`
    
    * Delete `PreservationTable` copy constructors
    
    * Implement moves for `PreservationTable`
    
    * Add destructor to `PreservationTable`
---
 src/iocore/cache/PreservationTable.cc      | 37 ++++++++++++++++++++++++++++++
 src/iocore/cache/PreservationTable.h       | 23 ++++++++++++++++++-
 src/iocore/cache/StripeSM.cc               | 11 ++++-----
 src/iocore/cache/unit_tests/test_Stripe.cc |  3 ---
 4 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/src/iocore/cache/PreservationTable.cc 
b/src/iocore/cache/PreservationTable.cc
index c45deb2d95..572e9af74f 100644
--- a/src/iocore/cache/PreservationTable.cc
+++ b/src/iocore/cache/PreservationTable.cc
@@ -31,7 +31,12 @@
 
 #include "tsutil/DbgCtl.h"
 
+#include "tscore/ink_assert.h"
+#include "tscore/ink_memory.h"
+#include "tscore/List.h"
+
 #include <cinttypes>
+#include <cstring>
 
 namespace
 {
@@ -40,6 +45,38 @@ DbgCtl dbg_ctl_cache_evac{"cache_evac"};
 
 } // namespace
 
+PreservationTable::PreservationTable(int size) : evacuate_size{(size / 
EVACUATION_BUCKET_SIZE) + 2}
+{
+  ink_assert(size > 0);
+  int evac_len   = this->evacuate_size * sizeof(DLL<EvacuationBlock>);
+  this->evacuate = static_cast<DLL<EvacuationBlock> *>(ats_malloc(evac_len));
+  memset(static_cast<void *>(this->evacuate), 0, evac_len);
+}
+
+PreservationTable::~PreservationTable()
+{
+  ats_free(this->evacuate);
+  this->evacuate = nullptr;
+}
+
+PreservationTable::PreservationTable(PreservationTable &&that)
+{
+  this->evacuate_size = that.evacuate_size;
+  this->evacuate      = that.evacuate;
+  that.evacuate_size  = 0;
+  that.evacuate       = nullptr;
+}
+
+PreservationTable &
+PreservationTable::operator=(PreservationTable &&that)
+{
+  this->evacuate_size = that.evacuate_size;
+  this->evacuate      = that.evacuate;
+  that.evacuate_size  = 0;
+  that.evacuate       = nullptr;
+  return *this;
+}
+
 EvacuationBlock *
 PreservationTable::find(Dir const &dir) const
 {
diff --git a/src/iocore/cache/PreservationTable.h 
b/src/iocore/cache/PreservationTable.h
index 7641456b45..acf762cce9 100644
--- a/src/iocore/cache/PreservationTable.h
+++ b/src/iocore/cache/PreservationTable.h
@@ -36,8 +36,8 @@
 #include "tscore/ink_platform.h"
 #include "tscore/List.h"
 
-#define EVACUATION_BUCKET_SIZE (2 * EVACUATION_SIZE) // 16MB
 #define EVACUATION_SIZE        (2 * AGG_SIZE)        // 8MB
+#define EVACUATION_BUCKET_SIZE (2 * EVACUATION_SIZE) // 16MB
 #define PIN_SCAN_EVERY         16                    // scan every 1/16 of disk
 
 #define dir_offset_evac_bucket(_o) (_o / (EVACUATION_BUCKET_SIZE / 
CACHE_BLOCK_SIZE))
@@ -85,6 +85,9 @@ struct EvacuationBlock {
  * This class is not safe for concurrent access. It should be protected
  * by a lock.
  *
+ * Destructing this object without first releasing all blocks and calling
+ * periodic_scan may result in memory leaks.
+ *
  * @see Stripe
  */
 class PreservationTable
@@ -99,6 +102,24 @@ public:
    */
   DLL<EvacuationBlock> *evacuate{nullptr};
 
+  /**
+   * PreservationTable constructor
+   *
+   * This will abort the program if it is unable to allocate memory.
+   *
+   * @param size The total number of directory entries the table must
+   * be able to store. The size must be a positive number.
+   */
+  PreservationTable(int size);
+
+  ~PreservationTable();
+
+  PreservationTable(PreservationTable const &that)            = delete;
+  PreservationTable &operator=(PreservationTable const &that) = delete;
+
+  PreservationTable(PreservationTable &&that);
+  PreservationTable &operator=(PreservationTable &&that);
+
   /**
    * Check whether the hash table may be indexed with the given offset.
    *
diff --git a/src/iocore/cache/StripeSM.cc b/src/iocore/cache/StripeSM.cc
index d3c901ec59..d5899dbe29 100644
--- a/src/iocore/cache/StripeSM.cc
+++ b/src/iocore/cache/StripeSM.cc
@@ -109,13 +109,12 @@ struct StripeInitInfo {
   }
 };
 
-StripeSM::StripeSM(CacheDisk *disk, off_t blocks, off_t dir_skip) : 
Continuation(new_ProxyMutex()), Stripe{disk, blocks, dir_skip}
+// This is weird: the len passed to the constructor for _preserved_dirs is
+// initialized in the superclasse's constructor. This is safe because the
+// superclass should always be initialized first.
+StripeSM::StripeSM(CacheDisk *disk, off_t blocks, off_t dir_skip)
+  : Continuation(new_ProxyMutex()), Stripe{disk, blocks, dir_skip}, 
_preserved_dirs{static_cast<int>(len)}
 {
-  this->_preserved_dirs.evacuate_size = static_cast<int>(len / 
EVACUATION_BUCKET_SIZE) + 2;
-  int evac_len                        = this->_preserved_dirs.evacuate_size * 
sizeof(DLL<EvacuationBlock>);
-  this->_preserved_dirs.evacuate      = static_cast<DLL<EvacuationBlock> 
*>(ats_malloc(evac_len));
-  memset(static_cast<void *>(this->_preserved_dirs.evacuate), 0, evac_len);
-
   open_dir.mutex = this->mutex;
   SET_HANDLER(&StripeSM::aggWrite);
 }
diff --git a/src/iocore/cache/unit_tests/test_Stripe.cc 
b/src/iocore/cache/unit_tests/test_Stripe.cc
index 6c09b1af00..dd81dcc8bb 100644
--- a/src/iocore/cache/unit_tests/test_Stripe.cc
+++ b/src/iocore/cache/unit_tests/test_Stripe.cc
@@ -193,7 +193,6 @@ TEST_CASE("The behavior of StripeSM::add_writer.")
   }
 
   ats_free(stripe.raw_dir);
-  ats_free(stripe.get_preserved_dirs().evacuate);
   ats_free(stripe.path);
 }
 
@@ -305,7 +304,6 @@ TEST_CASE("aggWrite behavior with f.evacuator unset")
   }
 
   ats_free(stripe.raw_dir);
-  ats_free(stripe.get_preserved_dirs().evacuate);
   ats_free(stripe.path);
 }
 
@@ -405,6 +403,5 @@ TEST_CASE("aggWrite behavior with f.evacuator set")
 
   delete[] source;
   ats_free(stripe.raw_dir);
-  ats_free(stripe.get_preserved_dirs().evacuate);
   ats_free(stripe.path);
 }

Reply via email to