BIND 10 trac2836, updated. 2f220f9ff1a51348ea225d72a75d58d5d81031aa [2836] Make segment holder survive relocation

BIND 10 source code commits bind10-changes at lists.isc.org
Fri May 10 11:39:06 UTC 2013


The branch, trac2836 has been updated
       via  2f220f9ff1a51348ea225d72a75d58d5d81031aa (commit)
       via  a87cf3103eb903132064550a8e75715d9b644620 (commit)
      from  427bc05eee647c9c5afb013f07c0cc73ff17aecc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2f220f9ff1a51348ea225d72a75d58d5d81031aa
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Fri May 10 13:37:12 2013 +0200

    [2836] Make segment holder survive relocation
    
    Let the SegmentObjectHolder store the object's address in the segment's
    named addresses, so it moves correctly when the segment is relocated.

commit a87cf3103eb903132064550a8e75715d9b644620
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Fri May 10 10:23:06 2013 +0200

    [2836] Test that segment holder survives relocation
    
    Test that the SegmentObjectHolder survives when the segment relocates
    itself and correctly releases all its memory.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/datasrc/memory/Makefile.am                 |    1 +
 .../memory/{logger.cc => segment_object_holder.cc} |   15 ++++--
 src/lib/datasrc/memory/segment_object_holder.h     |   48 ++++++++++++++++----
 .../tests/memory/segment_object_holder_unittest.cc |   43 ++++++++++++++++++
 4 files changed, 94 insertions(+), 13 deletions(-)
 copy src/lib/datasrc/memory/{logger.cc => segment_object_holder.cc} (70%)

-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory/Makefile.am b/src/lib/datasrc/memory/Makefile.am
index c0ee688..27c2de3 100644
--- a/src/lib/datasrc/memory/Makefile.am
+++ b/src/lib/datasrc/memory/Makefile.am
@@ -17,6 +17,7 @@ libdatasrc_memory_la_SOURCES += rdata_serialization.h rdata_serialization.cc
 libdatasrc_memory_la_SOURCES += zone_data.h zone_data.cc
 libdatasrc_memory_la_SOURCES += rrset_collection.h rrset_collection.cc
 libdatasrc_memory_la_SOURCES += segment_object_holder.h
+libdatasrc_memory_la_SOURCES += segment_object_holder.cc
 libdatasrc_memory_la_SOURCES += logger.h logger.cc
 libdatasrc_memory_la_SOURCES += zone_table.h zone_table.cc
 libdatasrc_memory_la_SOURCES += zone_finder.h zone_finder.cc
diff --git a/src/lib/datasrc/memory/segment_object_holder.cc b/src/lib/datasrc/memory/segment_object_holder.cc
new file mode 100644
index 0000000..9ca9d3c
--- /dev/null
+++ b/src/lib/datasrc/memory/segment_object_holder.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "segment_object_holder.h"
+
+#include <boost/lexical_cast.hpp>
+
+namespace isc {
+namespace datasrc {
+namespace memory {
+namespace detail {
+
+std::string
+getNextHolderName() {
+    static size_t index = 0;
+    return ("Segment object holder auto name " +
+            boost::lexical_cast<std::string>(index ++));
+}
+
+}
+}
+}
+}
diff --git a/src/lib/datasrc/memory/segment_object_holder.h b/src/lib/datasrc/memory/segment_object_holder.h
index 384f4ef..e1629d0 100644
--- a/src/lib/datasrc/memory/segment_object_holder.h
+++ b/src/lib/datasrc/memory/segment_object_holder.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -16,12 +16,22 @@
 #define DATASRC_MEMORY_SEGMENT_OBJECT_HOLDER_H 1
 
 #include <util/memory_segment.h>
+#include <string>
 
 namespace isc {
 namespace datasrc {
 namespace memory {
 namespace detail {
 
+// Internal function to get next yet unused name of segment holder.
+// We need the names of holders to be unique per segment at any given
+// momemnt. This just keeps incrementing number after a prefix with
+// each call, it should be enough (the holder should no longer be
+// alive when the counter wraps around, if that ever happens with
+// presumably 64bit counters).
+std::string
+getNextHolderName();
+
 // A simple holder to create and use some objects in this implementation
 // in an exception safe manner.   It works like std::auto_ptr but much
 // more simplified.
@@ -32,23 +42,41 @@ template <typename T, typename ARG_T>
 class SegmentObjectHolder {
 public:
     SegmentObjectHolder(util::MemorySegment& mem_sgmt, T* obj, ARG_T arg) :
-        mem_sgmt_(mem_sgmt), obj_(obj), arg_(arg)
-    {}
+        mem_sgmt_(mem_sgmt), arg_(arg),
+        holder_name_(getNextHolderName()), holding_(true)
+    {
+        mem_sgmt_.setNamedAddress(holder_name_.c_str(), obj);
+    }
     ~SegmentObjectHolder() {
-        if (obj_ != NULL) {
-            T::destroy(mem_sgmt_, obj_, arg_);
+        if (holding_) {
+            // Use release, as it removes the stored address from segment
+            T* obj = release();
+            T::destroy(mem_sgmt_, obj, arg_);
+        }
+    }
+    T* get() {
+        if (holding_) {
+            return (static_cast<T*>(
+                mem_sgmt_.getNamedAddress(holder_name_.c_str())));
+        } else {
+            return (NULL);
         }
     }
-    T* get() { return (obj_); }
     T* release() {
-        T* ret = obj_;
-        obj_ = NULL;
-        return (ret);
+        if (holding_) {
+            T* obj = get();
+            mem_sgmt_.clearNamedAddress(holder_name_.c_str());
+            holding_ = false;
+            return (obj);
+        } else {
+            return (NULL);
+        }
     }
 private:
     util::MemorySegment& mem_sgmt_;
-    T* obj_;
     ARG_T arg_;
+    const std::string holder_name_;
+    bool holding_;
 };
 
 } // detail
diff --git a/src/lib/datasrc/tests/memory/segment_object_holder_unittest.cc b/src/lib/datasrc/tests/memory/segment_object_holder_unittest.cc
index d27e364..77a36e9 100644
--- a/src/lib/datasrc/tests/memory/segment_object_holder_unittest.cc
+++ b/src/lib/datasrc/tests/memory/segment_object_holder_unittest.cc
@@ -13,6 +13,7 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <util/memory_segment_local.h>
+#include <util/memory_segment_mapped.h>
 
 #include <datasrc/memory/segment_object_holder.h>
 
@@ -24,6 +25,7 @@ using namespace isc::datasrc::memory::detail;
 
 namespace {
 const int TEST_ARG_VAL = 42;    // arbitrary chosen magic number
+const char* const mapped_file = TEST_DATA_BUILDDIR "/test.mapped";
 
 class TestObject {
 public:
@@ -64,4 +66,45 @@ TEST(SegmentObjectHolderTest, foo) {
     useHolder(sgmt, obj, false);
     EXPECT_TRUE(sgmt.allMemoryDeallocated());
 }
+
+// Keep allocating bigger and bigger chunks of data until the allocation
+// fails with growing the segment.
+void
+allocateUntilGrows(MemorySegment& segment, size_t& current_size) {
+    // Create an object that will not be explicitly deallocated.
+    // It must be deallocated by the segment holder and even in case
+    // the position moved.
+    void *object_memory = segment.allocate(sizeof(TestObject));
+    TestObject* object = new(object_memory) TestObject;
+    SegmentObjectHolder<TestObject, int> holder(segment, object, TEST_ARG_VAL);
+    while (true) {
+        void* data = segment.allocate(current_size);
+        segment.deallocate(data, current_size);
+        current_size *= 2;
+    }
+}
+
+// Check that the segment thing releases stuff even in case it throws
+// SegmentGrown exception and the thing moves address
+TEST(SegmentObjectHolderTest, grow) {
+    MemorySegmentMapped segment(mapped_file,
+                                isc::util::MemorySegmentMapped::CREATE_ONLY);
+    // Allocate a bit of memory, to get a unique address
+    void* mark = segment.allocate(1);
+    segment.setNamedAddress("mark", mark);
+    // Try allocating bigger and bigger chunks of data until the segment
+    // actually relocates
+    size_t alloc_size = 1024;
+    while (mark == segment.getNamedAddress("mark")) {
+        EXPECT_THROW(allocateUntilGrows(segment, alloc_size),
+                     MemorySegmentGrown);
+    }
+    mark = segment.getNamedAddress("mark");
+    segment.clearNamedAddress("mark");
+    segment.deallocate(mark, 1);
+    EXPECT_TRUE(segment.allMemoryDeallocated());
+    // Remove the file
+    EXPECT_EQ(0, unlink(mapped_file));
+}
+
 }



More information about the bind10-changes mailing list