Browse Source

[2905] store an empty zone data in zone table as placeholder of broken zones.

JINMEI Tatuya 12 years ago
parent
commit
cfbf803bb4
2 changed files with 27 additions and 12 deletions
  1. 19 7
      src/lib/datasrc/memory/zone_table.cc
  2. 8 5
      src/lib/datasrc/memory/zone_table.h

+ 19 - 7
src/lib/datasrc/memory/zone_table.cc

@@ -40,7 +40,10 @@ void
 deleteZoneData(util::MemorySegment* mem_sgmt, ZoneData* zone_data,
                RRClass rrclass)
 {
-    if (zone_data != NULL) {
+    // We shouldn't delete empty zone data here; the only empty zone
+    // that can be passed here is the placeholder for broken zones maintained
+    // in the zone table.  It will stay there until the table is destroyed.
+    if (zone_data && !zone_data->isEmpty()) {
         ZoneData::destroy(*mem_sgmt, zone_data, rrclass);
     }
 }
@@ -49,21 +52,30 @@ typedef boost::function<void(ZoneData*)> ZoneDataDeleterType;
 
 ZoneTable*
 ZoneTable::create(util::MemorySegment& mem_sgmt, const RRClass& zone_class) {
-    SegmentObjectHolder<ZoneTableTree, ZoneDataDeleterType> holder(
+    // Create a placeholder "null" zone data
+    SegmentObjectHolder<ZoneData, RRClass> zdholder(mem_sgmt, zone_class);
+    zdholder.set(ZoneData::create(mem_sgmt));
+
+    // create and setup the tree for the table.
+    SegmentObjectHolder<ZoneTableTree, ZoneDataDeleterType> tree_holder(
         mem_sgmt, boost::bind(deleteZoneData, &mem_sgmt, _1, zone_class));
-    holder.set(ZoneTableTree::create(mem_sgmt));
+    tree_holder.set(ZoneTableTree::create(mem_sgmt));
     void* p = mem_sgmt.allocate(sizeof(ZoneTable));
-    ZoneTable* zone_table = new(p) ZoneTable(zone_class, holder.get());
-    holder.release();
+
+    // Build zone table with the created objects.  Its constructor doesn't
+    // throw, so we can release them from the holder at this point.
+    ZoneTable* zone_table = new(p) ZoneTable(zone_class, tree_holder.release(),
+                                             zdholder.release());
     return (zone_table);
 }
 
 void
-ZoneTable::destroy(util::MemorySegment& mem_sgmt, ZoneTable* ztable)
-{
+ZoneTable::destroy(util::MemorySegment& mem_sgmt, ZoneTable* ztable) {
     ZoneTableTree::destroy(mem_sgmt, ztable->zones_.get(),
                            boost::bind(deleteZoneData, &mem_sgmt, _1,
                                        ztable->rrclass_));
+    ZoneData::destroy(mem_sgmt, ztable->null_zone_data_.get(),
+                      ztable->rrclass_);
     mem_sgmt.deallocate(ztable, sizeof(ZoneTable));
 }
 

+ 8 - 5
src/lib/datasrc/memory/zone_table.h

@@ -99,13 +99,13 @@ private:
     /// An object of this class is always expected to be created by the
     /// allocator (\c create()), so the constructor is hidden as private.
     ///
-    /// This constructor internally involves resource allocation, and if
-    /// it fails, a corresponding standard exception will be thrown.
-    /// It never throws an exception otherwise.
-    ZoneTable(const dns::RRClass& rrclass, ZoneTableTree* zones) :
+    /// This constructor never throws.
+    ZoneTable(const dns::RRClass& rrclass, ZoneTableTree* zones,
+              ZoneData* null_zone_data) :
         rrclass_(rrclass),
         zone_count_(0),
-        zones_(zones)
+        zones_(zones),
+        null_zone_data_(null_zone_data)
     {}
 
 public:
@@ -213,6 +213,9 @@ private:
     const dns::RRClass rrclass_;
     size_t zone_count_;
     boost::interprocess::offset_ptr<ZoneTableTree> zones_;
+
+    // this is a shared placeholder for broken zones
+    boost::interprocess::offset_ptr<ZoneData> null_zone_data_;
 };
 }
 }