Parcourir la source

[2150] Allow DomainTree::find() to start at a lower level

Note that if a previous find() results in a PARTIALMATCH, the next
find() (when passed a populated node chain and a non-absolute label
sequence) starts at the down-node of the partial match's top of chain
(deepest matched node).  The caller must pass the correctly formed
non-absolute label sequence for that sub-tree-of-tree.
Mukund Sivaraman il y a 12 ans
Parent
commit
3c03d322a1

+ 19 - 6
src/lib/datasrc/memory/domaintree.h

@@ -1153,9 +1153,11 @@ public:
     /// Another special feature of this version is the ability to record
     /// more detailed information regarding the search result.
     ///
-    /// This information will be returned via the \c node_path parameter,
-    /// which is an object of class \c DomainTreeNodeChain.
-    /// The passed parameter must be empty.
+    /// This information will be returned via the \c node_path
+    /// parameter, which is an object of class \c DomainTreeNodeChain.
+    /// The passed parameter must be empty if the label sequence is
+    /// absolute. If the label sequence is not absolute, then find()
+    /// will begin from the top of the node chain.
     ///
     /// On success, the node sequence stored in \c node_path will contain all
     /// the ancestor nodes from the found node towards the root.
@@ -1462,12 +1464,23 @@ DomainTree<T>::find(const isc::dns::LabelSequence& target_labels_orig,
                     bool (*callback)(const DomainTreeNode<T>&, CBARG),
                     CBARG callback_arg) const
 {
-    if (!node_path.isEmpty()) {
+    if (node_path.isEmpty() ^ target_labels_orig.isAbsolute()) {
         isc_throw(isc::BadValue,
-                  "DomainTree::find is given a non empty chain");
+                  "DomainTree::find() is given mismatched node chain"
+                  " and label sequence");
+    }
+
+    DomainTreeNode<T>* node;
+
+    if (!node_path.isEmpty()) {
+        // Get the top node in the node chain
+        node = const_cast<DomainTreeNode<T>*>(node_path.top());
+        // Start searching from its down pointer
+        node = node->getDown();
+    } else {
+        node = root_.get();
     }
 
-    DomainTreeNode<T>* node = root_.get();
     Result ret = NOTFOUND;
     dns::LabelSequence target_labels(target_labels_orig);
 

+ 34 - 0
src/lib/datasrc/memory/tests/domaintree_unittest.cc

@@ -454,6 +454,40 @@ TEST_F(DomainTreeTest, callbackLabelSequence) {
     performCallbackTest(dtree, mem_sgmt_, ls1, ls2);
 }
 
+TEST_F(DomainTreeTest, findInSubTree) {
+    // For the version that takes a node chain, the chain must be empty.
+    DomainTreeNodeChain<int> chain;
+    bool flag;
+
+    // First, find a sub-tree node
+    const Name n1("w.y.d.e.f");
+    const LabelSequence ls1(n1);
+    DomainTree<int>::Result result =
+        dtree_expose_empty_node.find(ls1, &cdtnode, chain,
+                                     testCallback, &flag);
+    EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
+    EXPECT_EQ(n1, chain.getAbsoluteName());
+
+    // Searching for an absolute label sequence when chain is already
+    // populated should throw.
+    const Name n2a("o");
+    const LabelSequence ls2a(n2a);
+    EXPECT_THROW(dtree_expose_empty_node.find(ls2a, &cdtnode, chain,
+                                              testCallback, &flag),
+                 isc::BadValue);
+
+    // Now, find "o.w.y.d.e.f." by right-stripping the "w.y.d.e.f."
+    // suffix.
+    const Name n2("o.w.y.d.e.f");
+    LabelSequence ls2(n2);
+    ls2.stripRight(6);
+
+    result = dtree_expose_empty_node.find(ls2, &cdtnode, chain,
+                                          testCallback, &flag);
+    EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
+    EXPECT_EQ(n2, chain.getAbsoluteName());
+}
+
 TEST_F(DomainTreeTest, chainLevel) {
     TestDomainTreeNodeChain chain;