Browse Source

[2107] test the case of adding some RdataSets as node data

also now make sure all linked RdataSets are released.
JINMEI Tatuya 12 years ago
parent
commit
e50a2637c7

+ 11 - 0
src/lib/datasrc/memory/rdataset.h

@@ -228,6 +228,17 @@ private:
     static const size_t MANY_RRSIG_COUNT = (1 << 3) - 1;
     static const size_t MANY_RRSIG_COUNT = (1 << 3) - 1;
 
 
 public:
 public:
+    /// \brief Return the bare pointer to the next node.
+    ///
+    /// In such an operation as iterating over a linked list of \c RdataSet
+    /// object, using this method is generally more efficient than using
+    /// the \c next member directly because it prevents unintentional
+    /// creation of offset pointer objects.  While the application can
+    /// get the same result by directly calling get() on \c next, it would
+    /// help encourage the use of more efficient usage if we provide an
+    /// explicit accessor.
+    RdataSet* getNext() const { return (next.get()); }
+
     /// \brief Return the number of RDATAs stored in the \c RdataSet.
     /// \brief Return the number of RDATAs stored in the \c RdataSet.
     size_t getRdataCount() const { return (rdata_count_); }
     size_t getRdataCount() const { return (rdata_count_); }
 
 

+ 32 - 1
src/lib/datasrc/memory/tests/zone_data_unittest.cc

@@ -18,15 +18,19 @@
 
 
 #include <dns/name.h>
 #include <dns/name.h>
 #include <dns/labelsequence.h>
 #include <dns/labelsequence.h>
+#include <dns/rrclass.h>
 
 
 #include <datasrc/memory/rdata_encoder.h>
 #include <datasrc/memory/rdata_encoder.h>
 #include <datasrc/memory/rdataset.h>
 #include <datasrc/memory/rdataset.h>
 #include <datasrc/memory/zone_data.h>
 #include <datasrc/memory/zone_data.h>
 
 
+#include <testutils/dnsmessage_test.h>
+
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
 using namespace isc::dns;
 using namespace isc::dns;
 using namespace isc::datasrc::memory;
 using namespace isc::datasrc::memory;
+using namespace isc::testutils;
 
 
 namespace {
 namespace {
 
 
@@ -37,7 +41,7 @@ protected:
     {}
     {}
     void TearDown() {
     void TearDown() {
         if (zone_data_ != NULL) {
         if (zone_data_ != NULL) {
-            ZoneData::destroy(mem_sgmt_, zone_data_);
+            ZoneData::destroy(RRClass::IN(), mem_sgmt_, zone_data_);
         }
         }
         // detect any memory leak in the test memory segment
         // detect any memory leak in the test memory segment
         EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
         EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
@@ -52,4 +56,31 @@ protected:
 TEST_F(ZoneDataTest, getOriginNode) {
 TEST_F(ZoneDataTest, getOriginNode) {
     EXPECT_EQ(LabelSequence(zname_), zone_data_->getOriginNode()->getLabels());
     EXPECT_EQ(LabelSequence(zname_), zone_data_->getOriginNode()->getLabels());
 }
 }
+
+TEST_F(ZoneDataTest, addRdataSets) {
+    // Insert a name to the zone, and add a couple the data (RdataSet) objects
+    // to the corresponding node.
+
+    ConstRRsetPtr a_rrset_ =
+        textToRRset("www.example.com. 3600 IN A 192.0.2.1");
+
+    ZoneData::ZoneNode* node = NULL;
+    zone_data_->insertName(mem_sgmt_, a_rrset_->getName(), &node);
+    ASSERT_NE(static_cast<ZoneData::ZoneNode*>(NULL), node);
+    EXPECT_TRUE(node->isEmpty()); // initially it should be empty
+
+    RdataSet* rdataset_a =
+        RdataSet::create(mem_sgmt_, encoder_, a_rrset_, ConstRRsetPtr());
+    node->setData(rdataset_a);
+
+    ConstRRsetPtr aaaa_rrset_ =
+        textToRRset("www.example.com. 3600 IN AAAA 2001:db8::1");
+    RdataSet* rdataset_aaaa =
+        RdataSet::create(mem_sgmt_, encoder_, aaaa_rrset_, ConstRRsetPtr());
+    // make a linked list and replace the list head
+    rdataset_aaaa->next = rdataset_a;
+    node->setData(rdataset_aaaa);
+
+    // TearDown() will confirm there's no leak on destroy
+}
 }
 }

+ 33 - 2
src/lib/datasrc/memory/zone_data.cc

@@ -15,11 +15,14 @@
 #include <util/memory_segment.h>
 #include <util/memory_segment.h>
 
 
 #include <dns/name.h>
 #include <dns/name.h>
+#include <dns/rrclass.h>
 
 
 #include "rdataset.h"
 #include "rdataset.h"
 #include "rdata_encoder.h"
 #include "rdata_encoder.h"
 #include "zone_data.h"
 #include "zone_data.h"
 
 
+#include <boost/bind.hpp>
+
 #include <cassert>
 #include <cassert>
 #include <new>                  // for the placement new
 #include <new>                  // for the placement new
 
 
@@ -42,12 +45,40 @@ ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
     return (zone_data);
     return (zone_data);
 }
 }
 
 
+namespace {
+void
+rdataSetDeleter(RRClass rrclass, util::MemorySegment* mem_sgmt,
+                RdataSet* rdataset_head)
+{
+    for (RdataSet* rdataset = rdataset_head;
+         rdataset != NULL;
+         rdataset = rdataset->getNext()) {
+        RdataSet::destroy(*mem_sgmt, rrclass, rdataset);
+    }
+}
+}
+
 void
 void
-ZoneData::destroy(util::MemorySegment& mem_sgmt, ZoneData* zone_data) {
-    ZoneTree::destroy(mem_sgmt, zone_data->zone_tree_.get());
+ZoneData::destroy(RRClass zone_class, util::MemorySegment& mem_sgmt,
+                  ZoneData* zone_data)
+{
+    ZoneTree::destroy(mem_sgmt, zone_data->zone_tree_.get(),
+                      boost::bind(rdataSetDeleter, zone_class, &mem_sgmt,
+                                  _1));
     mem_sgmt.deallocate(zone_data, sizeof(ZoneData));
     mem_sgmt.deallocate(zone_data, sizeof(ZoneData));
 }
 }
 
 
+void
+ZoneData::insertName(util::MemorySegment& mem_sgmt, const Name& name,
+                     ZoneNode** node)
+{
+    const ZoneTree::Result result = zone_tree_->insert(mem_sgmt, name, node);
+
+    // This should be ensured by the API:
+    assert((result == ZoneTree::SUCCESS ||
+            result == ZoneTree::ALREADYEXISTS) && node!= NULL);
+}
+
 } // namespace memory
 } // namespace memory
 } // namespace datasrc
 } // namespace datasrc
 } // datasrc isc
 } // datasrc isc

+ 14 - 6
src/lib/datasrc/memory/zone_data.h

@@ -18,6 +18,7 @@
 #include <util/memory_segment.h>
 #include <util/memory_segment.h>
 
 
 #include <dns/name.h>
 #include <dns/name.h>
+#include <dns/rrclass.h>
 
 
 #include <datasrc/memory/domaintree.h>
 #include <datasrc/memory/domaintree.h>
 #include <datasrc/memory/rdataset.h>
 #include <datasrc/memory/rdataset.h>
@@ -33,13 +34,14 @@ class ZoneData : boost::noncopyable {
     struct RdataSetDeleter {
     struct RdataSetDeleter {
     public:
     public:
         RdataSetDeleter() {}
         RdataSetDeleter() {}
-        void operator()(util::MemorySegment& /*mem_sgmt*/,
-                        RdataSet* /*rdataset_head*/) const
-        {}
+        void operator()(util::MemorySegment& mem_sgmt,
+                        RdataSet* rdataset_head) const;
     };
     };
-    typedef DomainTree<RdataSet, RdataSetDeleter> ZoneTree;
-    typedef DomainTreeNode<RdataSet, RdataSetDeleter> ZoneNode;
+public:
+    typedef DomainTree<RdataSet> ZoneTree;
+    typedef DomainTreeNode<RdataSet> ZoneNode;
 
 
+private:
     ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
     ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
         zone_tree_(zone_tree), origin_node_(origin_node)
         zone_tree_(zone_tree), origin_node_(origin_node)
     {}
     {}
@@ -47,7 +49,13 @@ class ZoneData : boost::noncopyable {
 public:
 public:
     static ZoneData* create(util::MemorySegment& mem_sgmt,
     static ZoneData* create(util::MemorySegment& mem_sgmt,
                             const dns::Name& zone_name);
                             const dns::Name& zone_name);
-    static void destroy(util::MemorySegment& mem_sgmt, ZoneData* zone_data);
+    static void destroy(dns::RRClass zone_class, util::MemorySegment& mem_sgmt,
+                        ZoneData* zone_data);
+
+    void insertName(util::MemorySegment& mem_sgmt, const dns::Name& name,
+                    ZoneNode** node);
+
+    // This is a shortcut.
     const ZoneNode* getOriginNode() const {
     const ZoneNode* getOriginNode() const {
         return (origin_node_.get());
         return (origin_node_.get());
     }
     }