Browse Source

[trac507] supported empty node matching, easy case.

 - construct the backend rbtree with the 'empty okay' mode
 - return NXRRSET if the found node is empty
JINMEI Tatuya 14 years ago
parent
commit
dc5d961adf

+ 9 - 3
src/lib/datasrc/memory_datasrc.cc

@@ -34,7 +34,7 @@ namespace datasrc {
 struct MemoryZone::MemoryZoneImpl {
     // Constructor
     MemoryZoneImpl(const RRClass& zone_class, const Name& origin) :
-        zone_class_(zone_class), origin_(origin)
+        zone_class_(zone_class), origin_(origin), domains_(true)
     {}
 
     // Information about the zone
@@ -193,7 +193,8 @@ struct MemoryZone::MemoryZoneImpl {
         DomainNode* node(NULL);
         FindState state(options);
         RBTreeNodeChain<Domain> node_path;
-        switch (domains_.find(name, &node, node_path, zonecutCallback, &state)) {
+        switch (domains_.find(name, &node, node_path, zonecutCallback,
+                              &state)) {
             case DomainTree::PARTIALMATCH:
                 if (state.zonecut_node_ != NULL) {
                     return (FindResult(DELEGATION, state.rrset_));
@@ -210,7 +211,12 @@ struct MemoryZone::MemoryZoneImpl {
                 assert(0);
         }
         assert(node);
-        assert(!node->isEmpty());
+
+        // If there is an exact match but the node is empty, it's equivalent
+        // to NXRRSET.
+        if (node->isEmpty()) {
+            return (FindResult(NXRRSET, ConstRRsetPtr()));
+        }
 
         Domain::const_iterator found;
 

+ 28 - 0
src/lib/datasrc/tests/memory_datasrc_unittest.cc

@@ -375,6 +375,34 @@ TEST_F(MemoryZoneTest, find) {
     findTest(Name("example.net"), RRType::A(), Zone::NXDOMAIN);
 }
 
+TEST_F(MemoryZoneTest, emptyNode) {
+    /*
+     * The backend RBTree for this test should look like as follows:
+     *          example.org
+     *               |
+     *              baz (empty; easy case)
+     *            /  |  \
+     *          bar  |  x.foo ('foo' part is empty; a bit trickier) 
+     *              bbb
+     *             /
+     *           aaa
+     */
+
+    // Construct the test zone
+    const char* const names[] = {
+        "bar.example.org", "x.foo.example.org", "aaa.baz.example.org",
+        "bbb.baz.example.org.", NULL};
+    for (int i = 0; names[i] != NULL; ++i) {
+        ConstRRsetPtr rrset(new RRset(Name(names[i]), class_, RRType::A(),
+                                      RRTTL(300)));
+        EXPECT_EQ(SUCCESS, zone_.add(rrset));
+    }
+
+    // empty node matching, easy case: the node for 'baz' exists with
+    // no data.
+    findTest(Name("baz.example.org"), RRType::A(), Zone::NXRRSET);
+}
+
 TEST_F(MemoryZoneTest, load) {
     // Put some data inside the zone
     EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_.add(rr_ns_)));