Browse Source

fix the rbtree search policy problem

hanfeng 14 years ago
parent
commit
bebfa15d50
2 changed files with 90 additions and 135 deletions
  1. 75 73
      src/lib/datasrc/rbtree.h
  2. 15 62
      src/lib/datasrc/tests/rbtree_unittest.cc

+ 75 - 73
src/lib/datasrc/rbtree.h

@@ -55,7 +55,7 @@ operator-(const isc::dns::Name& super_name, const isc::dns::Name& sub_name) {
 }
 }
 
-template <typename T, bool returnEmptyNode>
+template <typename T>
 class RBTree;
 
 /// \brief \c RBNode is used by RBTree to store any data related to one domain
@@ -83,7 +83,7 @@ class RBNode : public boost::noncopyable {
 private:
     /// The RBNode is meant for use from within RBTree, so it has access to
     /// it.
-    template <typename U, bool returnEmptyNode>
+    template <typename U>
     friend class RBTree;
 
     /// \name Constructors
@@ -289,10 +289,13 @@ RBNode<T>::successor()const {
  *      multiple times.
  *
  *  Depending on different usage, rbtree will support different search policy.
- *  Whether return empty node to end user is one policy among them. Search
- *  policy is as the last template parameter, the default policy will NOT
- *  return empty node to end user, pass ture will get empty node during find
- *  is needed
+ *  Whether return empty node to end user is one policy among them. the default
+ *  policy will NOT return empty node to end user, pass ture will get empty node
+ *  during find is needed.
+ *  \note The search policy only affect find behavior of rbtree, but when inserting
+ *  one name, if the node already exist not matter it's insert explictly by end user
+ *  or empty node created by the rbtree itself, insert will return ALREADYEXISTS
+ *  not matter we want expose empty node or not.
  *
  * \anchor diagram
  *
@@ -330,7 +333,7 @@ RBNode<T>::successor()const {
  *  - since \c RBNode only has down pointer without up pointer, the node path
  *    during finding should be recorded for later use
  */
-template <typename T, bool returnEmptyNode = false>
+template <typename T>
 class RBTree : public boost::noncopyable {
     friend class RBNode<T>;
 public:
@@ -353,7 +356,7 @@ public:
     /// The constructor.
     ///
     /// It never throws an exception.
-    explicit RBTree();
+    explicit RBTree(bool returnEmptyNode = false);
 
     /// \b Note: RBTree is not intended to be inherited so the destructor
     /// is not virtual
@@ -467,16 +470,16 @@ public:
     /// \param node The found node.
     template <typename CBARG>
     Result findEx(const isc::dns::Name& name, NodeChain &node_path,
-                      RBNode<T>** node,
-                      bool (*callback)(const RBNode<T>&, CBARG),
-                      CBARG callback_arg) const;
- 
+                  RBNode<T>** node,
+                  bool (*callback)(const RBNode<T>&, CBARG),
+                  CBARG callback_arg) const;
+
     template <typename CBARG>
     Result findEx(const isc::dns::Name& name, NodeChain &node_path,
-                      const RBNode<T>** node,
-                      bool (*callback)(const RBNode<T>&, CBARG),
-                      CBARG callback_arg) const;
- 
+                  const RBNode<T>** node,
+                  bool (*callback)(const RBNode<T>&, CBARG),
+                  CBARG callback_arg) const;
+
 
     /// \brief return the next node which is bigger than node
     /// \param node_path store the path from base to sub domains in reverse order
@@ -583,24 +586,27 @@ private:
     RBNode<T>*  NULLNODE;
     /// the node count of current tree
     unsigned int node_count_;
+    /// search policy for rbtree
+    bool needsReturnEmptyNode_;
 };
 
-template <typename T, bool S>
-RBTree<T,S>::RBTree() {
+template <typename T>
+RBTree<T>::RBTree(bool returnEmptyNode) {
     NULLNODE = RBNode<T>::NULL_NODE();
     root_ = NULLNODE;
     node_count_ = 0;
+    needsReturnEmptyNode_ = returnEmptyNode;
 }
 
-template <typename T, bool S>
-RBTree<T,S>::~RBTree() {
+template <typename T>
+RBTree<T>::~RBTree() {
     deleteHelper(root_);
     assert(node_count_ == 0);
 }
 
-template <typename T, bool S>
-void 
-RBTree<T,S>::deleteHelper(RBNode<T> *root) {
+template <typename T>
+void
+RBTree<T>::deleteHelper(RBNode<T> *root) {
     if (root == NULLNODE) {
         return;
     }
@@ -629,10 +635,10 @@ RBTree<T,S>::deleteHelper(RBNode<T> *root) {
     --node_count_;
 }
 
-template <typename T, bool S>
+template <typename T>
 template <typename CBARG>
-typename RBTree<T,S>::Result
-RBTree<T,S>::find(const isc::dns::Name& name, RBNode<T>** node,
+typename RBTree<T>::Result
+RBTree<T>::find(const isc::dns::Name& name, RBNode<T>** node,
                 bool (*callback)(const RBNode<T>&, CBARG),
                 CBARG callback_arg) const
 {
@@ -640,10 +646,10 @@ RBTree<T,S>::find(const isc::dns::Name& name, RBNode<T>** node,
     return (findEx(name, node_path, node, callback, callback_arg));
 }
 
-template <typename T, bool S>
+template <typename T>
 template <typename CBARG>
-typename RBTree<T,S>::Result
-RBTree<T,S>::find(const isc::dns::Name& name, const RBNode<T>** node,
+typename RBTree<T>::Result
+RBTree<T>::find(const isc::dns::Name& name, const RBNode<T>** node,
                 bool (*callback)(const RBNode<T>&, CBARG),
                 CBARG callback_arg) const
 {
@@ -657,14 +663,14 @@ RBTree<T,S>::find(const isc::dns::Name& name, const RBNode<T>** node,
     return (ret);
 }
 
-template <typename T, bool returnEmptyNode>
+template <typename T>
 template <typename CBARG>
-typename RBTree<T,returnEmptyNode>::Result
-RBTree<T,returnEmptyNode>::findEx(const isc::dns::Name& target_name,
-                                      NodeChain &node_path,
-                                      RBNode<T>** target,
-                                      bool (*callback)(const RBNode<T>&, CBARG),
-                                      CBARG callback_arg) const
+typename RBTree<T>::Result
+RBTree<T>::findEx(const isc::dns::Name& target_name,
+                  NodeChain &node_path,
+                  RBNode<T>** target,
+                  bool (*callback)(const RBNode<T>&, CBARG),
+                  CBARG callback_arg) const
 {
     using namespace helper;
 
@@ -678,7 +684,7 @@ RBTree<T,returnEmptyNode>::findEx(const isc::dns::Name& target_name,
         const isc::dns::NameComparisonResult::NameRelation relation =
             compare_result.getRelation();
         if (relation == isc::dns::NameComparisonResult::EQUAL) {
-            if (returnEmptyNode || !node->isEmpty()) {
+            if (needsReturnEmptyNode_ || !node->isEmpty()) {
                 *target = node;
                 ret = EXACTMATCH;
             }
@@ -691,7 +697,7 @@ RBTree<T,returnEmptyNode>::findEx(const isc::dns::Name& target_name,
                 node = (compare_result.getOrder() < 0) ?
                     node->left_ : node->right_;
             } else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
-                if (returnEmptyNode || !node->isEmpty()) {
+                if (needsReturnEmptyNode_ || !node->isEmpty()) {
                     ret = PARTIALMATCH;
                     *target = node;
                     if (callback != NULL && node->callback_required_) {
@@ -712,14 +718,14 @@ RBTree<T,returnEmptyNode>::findEx(const isc::dns::Name& target_name,
     return (ret);
 }
 
-template <typename T, bool S>
+template <typename T>
 template <typename CBARG>
-typename RBTree<T,S>::Result
-RBTree<T,S>::findEx(const isc::dns::Name& target_name,
-                                      NodeChain &node_path,
-                                      const RBNode<T>** target,
-                                      bool (*callback)(const RBNode<T>&, CBARG),
-                                      CBARG callback_arg) const
+typename RBTree<T>::Result
+RBTree<T>::findEx(const isc::dns::Name& target_name,
+                  NodeChain &node_path,
+                  const RBNode<T>** target,
+                  bool (*callback)(const RBNode<T>&, CBARG),
+                  CBARG callback_arg) const
 {
     RBNode<T> *node = NULLNODE;
     const Result ret =
@@ -730,10 +736,10 @@ RBTree<T,S>::findEx(const isc::dns::Name& target_name,
     return (ret);
 }
 
-template <typename T, bool S>    
+template <typename T>
 const RBNode<T> *
-RBTree<T, S>::nextNode(const RBNode<T> *node, const NodeChain &node_path,
-                                NodeChain &next_node_path) const
+RBTree<T>::nextNode(const RBNode<T> *node, const NodeChain &node_path,
+                    NodeChain &next_node_path) const
 {
     next_node_path = node_path;
     // if node has sub domain, the next domain is the samllest
@@ -754,7 +760,7 @@ RBTree<T, S>::nextNode(const RBNode<T> *node, const NodeChain &node_path,
     }
 
     // if no successor found move to up level, the next successor
-    // is the successor of up node in the up level tree, if 
+    // is the successor of up node in the up level tree, if
     // up node doesn't has successor we gonna keep moving to up
     // level
     while (!next_node_path.empty()) {
@@ -769,10 +775,11 @@ RBTree<T, S>::nextNode(const RBNode<T> *node, const NodeChain &node_path,
 }
 
 
-template <typename T, bool returnEmptyNode>
-typename RBTree<T,returnEmptyNode>::Result
-RBTree<T,returnEmptyNode>::insert(const isc::dns::Name& target_name,
-                                  RBNode<T>** new_node) {
+template <typename T>
+typename RBTree<T>::Result
+RBTree<T>::insert(const isc::dns::Name& target_name,
+                  RBNode<T>** new_node)
+{
     using namespace helper;
     RBNode<T>* parent = NULLNODE;
     RBNode<T>* current = root_;
@@ -789,12 +796,7 @@ RBTree<T,returnEmptyNode>::insert(const isc::dns::Name& target_name,
             if (new_node != NULL) {
                 *new_node = current;
             }
-
-            if (current->isEmpty() && !returnEmptyNode) {
-                return (SUCCESS);
-            } else {
-                return (ALREADYEXISTS);
-            }
+            return (ALREADYEXISTS);
         } else {
             const int common_label_count = compare_result.getCommonLabels();
             if (common_label_count == 1) {
@@ -851,9 +853,9 @@ RBTree<T,returnEmptyNode>::insert(const isc::dns::Name& target_name,
 }
 
 
-template <typename T, bool S>
+template <typename T>
 void
-RBTree<T,S>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
+RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
     using namespace helper;
     const isc::dns::Name sub_name = node.name_ - base_name;
     // using auto_ptr here is to avoid memory leak in case of exception raised
@@ -874,9 +876,9 @@ RBTree<T,S>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
 }
 
 
-template <typename T, bool S>
+template <typename T>
 void
-RBTree<T,S>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
+RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
 
     RBNode<T>* uncle;
     while (node != *root && node->parent_->color_ == RBNode<T>::RED) {
@@ -920,9 +922,9 @@ RBTree<T,S>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
 }
 
 
-template <typename T, bool S>
+template <typename T>
 RBNode<T>*
-RBTree<T,S>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
+RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
     RBNode<T>* right = node->right_;
     node->right_ = right->left_;
     if (right->left_ != NULLNODE)
@@ -945,9 +947,9 @@ RBTree<T,S>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
     return (node);
 }
 
-template <typename T, bool S>
+template <typename T>
 RBNode<T>*
-RBTree<T,S>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
+RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
     RBNode<T>* left = node->left_;
     node->left_ = left->right_;
     if (left->right_ != NULLNODE)
@@ -970,17 +972,17 @@ RBTree<T,S>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
 }
 
 
-template <typename T, bool S>
+template <typename T>
 void
-RBTree<T,S>::dumpTree(std::ostream& os, unsigned int depth) const {
+RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const {
     indent(os, depth);
     os << "tree has " << node_count_ << " node(s)\n";
     dumpTreeHelper(os, root_, depth);
 }
 
-template <typename T, bool S>
+template <typename T>
 void
-RBTree<T,S>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
+RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
                           unsigned int depth) const
 {
     if (node == NULLNODE) {
@@ -1005,9 +1007,9 @@ RBTree<T,S>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
     dumpTreeHelper(os, node->right_, depth + 1);
 }
 
-template <typename T, bool S>
+template <typename T>
 void
-RBTree<T,S>::indent(std::ostream& os, unsigned int depth) {
+RBTree<T>::indent(std::ostream& os, unsigned int depth) {
     static const unsigned int INDENT_FOR_EACH_DEPTH = 5;
     os << std::string(depth * INDENT_FOR_EACH_DEPTH, ' ');
 }

+ 15 - 62
src/lib/datasrc/tests/rbtree_unittest.cc

@@ -50,8 +50,8 @@ using namespace isc::datasrc;
 namespace {
 class RBTreeTest : public::testing::Test {
 protected:
-    RBTreeTest() : rbtree() {
-        const char * domain_names[] = {"c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", 
+    RBTreeTest() : rbtree_expose_empty_node(true) {
+        const char * domain_names[] = {"c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h",
             "o.w.y.d.e.f", "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f"};
         int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
         for (int i = 0; i < name_count; ++i) {
@@ -65,7 +65,7 @@ protected:
     }
 
     RBTree<int> rbtree;
-    RBTree<int, true> rbtree_expose_empty_node;
+    RBTree<int> rbtree_expose_empty_node;
     RBNode<int>* rbtnode;
     const RBNode<int>* crbtnode;
 };
@@ -81,41 +81,24 @@ TEST_F(RBTreeTest, setGetData) {
 }
 
 TEST_F(RBTreeTest, insertNames) {
-    //if don't expose empty node, even the node already exsit which is caused by node fission
-    //we will return succeed
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("d.e.f"), &rbtnode));
+    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("d.e.f"), &rbtnode));
     EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
     EXPECT_EQ(13, rbtree.getNodeCount());
 
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, 
-            rbtree_expose_empty_node.insert(Name("d.e.f"), &rbtnode));
-    EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
-    EXPECT_EQ(13, rbtree_expose_empty_node.getNodeCount());
-
-
     //insert not exist node
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("."), &rbtnode));
     EXPECT_EQ(Name("."), rbtnode->getName());
     EXPECT_EQ(14, rbtree.getNodeCount());
 
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("."), &rbtnode));
-    EXPECT_EQ(Name("."), rbtnode->getName());
-    EXPECT_EQ(14, rbtree_expose_empty_node.getNodeCount());
-    
+
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example.com"), &rbtnode));
     EXPECT_EQ(15, rbtree.getNodeCount());
     rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
 
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("example.com"), &rbtnode));
-    EXPECT_EQ(15, rbtree_expose_empty_node.getNodeCount());
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
-
 
     // return ALREADYEXISTS, since node "example.com" already has been explicitly inserted
     EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example.com"), &rbtnode));
     EXPECT_EQ(15, rbtree.getNodeCount());
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree_expose_empty_node.insert(Name("example.com"), &rbtnode));
-    EXPECT_EQ(15, rbtree_expose_empty_node.getNodeCount());
 
 
     // split the node "d.e.f"
@@ -123,21 +106,13 @@ TEST_F(RBTreeTest, insertNames) {
     EXPECT_EQ(Name("k"), rbtnode->getName());
     EXPECT_EQ(17, rbtree.getNodeCount());
 
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("k.e.f"), &rbtnode));
-    EXPECT_EQ(Name("k"), rbtnode->getName());
-    EXPECT_EQ(17, rbtree_expose_empty_node.getNodeCount());
 
 
     // split the node "g.h"
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h"), &rbtnode));
+    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("h"), &rbtnode));
     EXPECT_EQ(Name("h"), rbtnode->getName());
     EXPECT_EQ(18, rbtree.getNodeCount());
 
-    //node fission will create node "h"
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree_expose_empty_node.insert(Name("h"), &rbtnode));
-    EXPECT_EQ(Name("h"), rbtnode->getName());
-    EXPECT_EQ(18, rbtree_expose_empty_node.getNodeCount());
-
 
     // add child domain
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
@@ -147,35 +122,21 @@ TEST_F(RBTreeTest, insertNames) {
     EXPECT_EQ(Name("n"), rbtnode->getName());
     EXPECT_EQ(20, rbtree.getNodeCount());
 
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
-    EXPECT_EQ(Name("m"), rbtnode->getName());
-    EXPECT_EQ(19, rbtree_expose_empty_node.getNodeCount());
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("n.p.w.y.d.e.f"), &rbtnode));
-    EXPECT_EQ(Name("n"), rbtnode->getName());
-    EXPECT_EQ(20, rbtree_expose_empty_node.getNodeCount());
-
 
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l.a"), &rbtnode));
     EXPECT_EQ(Name("l"), rbtnode->getName());
     EXPECT_EQ(21, rbtree.getNodeCount());
 
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("l.a"), &rbtnode));
-    EXPECT_EQ(Name("l"), rbtnode->getName());
-    EXPECT_EQ(21, rbtree_expose_empty_node.getNodeCount());
 
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("r.d.e.f"), &rbtnode));
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("s.d.e.f"), &rbtnode));
     EXPECT_EQ(23, rbtree.getNodeCount());
 
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("r.d.e.f"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("s.d.e.f"), &rbtnode));
-    EXPECT_EQ(23, rbtree_expose_empty_node.getNodeCount());
 
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h.w.y.d.e.f"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("h.w.y.d.e.f"), &rbtnode));
 
     // add more nodes one by one to cover leftRotate and rightRotate
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("f"), &rbtnode));
+    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("f"), &rbtnode));
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m"), &rbtnode));
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("nm"), &rbtnode));
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("om"), &rbtnode));
@@ -186,21 +147,9 @@ TEST_F(RBTreeTest, insertNames) {
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("i"), &rbtnode));
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ae"), &rbtnode));
     EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n"), &rbtnode));
-    
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree_expose_empty_node.insert(Name("f"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("m"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("nm"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("om"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("k"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("l"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("fe"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("ge"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("i"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("ae"), &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree_expose_empty_node.insert(Name("n"), &rbtnode));
 }
 
-   
+
 TEST_F(RBTreeTest, findName) {
     // find const rbtnode
     // exact match
@@ -213,6 +162,10 @@ TEST_F(RBTreeTest, findName) {
     EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("x"), &crbtnode));
     EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("m.n"), &crbtnode));
 
+    //if we expose empty node, we can get the empty node created during insert
+    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree_expose_empty_node.find(Name("d.e.f"), &crbtnode));
+    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree_expose_empty_node.find(Name("w.y.d.e.f"), &crbtnode));
+
     // partial match
     EXPECT_EQ(RBTree<int>::PARTIALMATCH, rbtree.find(Name("m.b"), &crbtnode));
     EXPECT_EQ(Name("b"), crbtnode->getName());
@@ -249,7 +202,7 @@ TEST_F(RBTreeTest, callback) {
                                                   &subrbtnode));
     subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
     RBNode<int>* parentrbtnode;
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example"),
+    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example"),
                                                        &parentrbtnode));
     //  the chilld/parent nodes shouldn't "inherit" the callback flag.
     // "rbtnode" may be invalid due to the insertion, so we need to re-find
@@ -302,11 +255,11 @@ Name nodeAbsoluteName(const RBNode<int> *node, const RBTree<int>::NodeChain &nod
     while (!node_path_copy.empty()) {
         absoluteName = absoluteName.concatenate(node_path_copy.top()->getName());
         node_path_copy.pop();
-    }   
+    }
     return (absoluteName);
 }
 
-void testNodeAdjacentHelper(const RBTree<int, true> &tree, const Name &currentDomain, const Name &nextDomain) {
+void testNodeAdjacentHelper(const RBTree<int> &tree, const Name &currentDomain, const Name &nextDomain) {
     RBTree<int>::NodeChain node_path;
     RBTree<int>::NodeChain next_node_path;
     const RBNode<int> *node;