Browse Source

[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.
Michal 'vorner' Vaner 12 years ago
parent
commit
2f220f9ff1

+ 1 - 0
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

+ 34 - 0
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 ++));
+}
+
+}
+}
+}
+}

+ 38 - 10
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