Browse Source

[2089] store subtreerootness in node flags

Jelte Jansen 12 years ago
parent
commit
55dfd7fb67
2 changed files with 37 additions and 7 deletions
  1. 36 5
      src/lib/datasrc/rbtree.h
  2. 1 2
      src/lib/datasrc/tests/rbtree_unittest.cc

+ 36 - 5
src/lib/datasrc/rbtree.h

@@ -124,6 +124,7 @@ public:
     enum Flags {
     enum Flags {
         FLAG_CALLBACK = 1, ///< Callback enabled. See \ref callback
         FLAG_CALLBACK = 1, ///< Callback enabled. See \ref callback
         FLAG_RED = 2, ///< Node color; 1 if node is red, 0 if node is black.
         FLAG_RED = 2, ///< Node color; 1 if node is red, 0 if node is black.
+        FLAG_SUBTREE_ROOT = 4, ///< Set if the node is the root of a subtree
         FLAG_USER1 = 0x80000000U, ///< Application specific flag
         FLAG_USER1 = 0x80000000U, ///< Application specific flag
         FLAG_USER2 = 0x40000000U, ///< Application specific flag
         FLAG_USER2 = 0x40000000U, ///< Application specific flag
         FLAG_USER3 = 0x20000000U  ///< Application specific flag
         FLAG_USER3 = 0x20000000U  ///< Application specific flag
@@ -265,8 +266,16 @@ private:
         }
         }
     }
     }
 
 
+    void setSubTreeRoot(bool root) {
+        if (root) {
+            flags_ |= FLAG_SUBTREE_ROOT;
+        } else {
+            flags_ &= ~FLAG_SUBTREE_ROOT;
+        }
+    }
+
     bool isSubTreeRoot() const {
     bool isSubTreeRoot() const {
-        return (parent_ == NULL_NODE());
+        return ((flags_ & FLAG_SUBTREE_ROOT) != 0);
     }
     }
 
 
     /// \brief return the next node which is bigger than current node
     /// \brief return the next node which is bigger than current node
@@ -357,7 +366,7 @@ RBNode<T>::RBNode() :
     // dummy name, the value doesn't matter:
     // dummy name, the value doesn't matter:
     name_(isc::dns::Name::ROOT_NAME()),
     name_(isc::dns::Name::ROOT_NAME()),
     down_(NULL),
     down_(NULL),
-    flags_(0)
+    flags_(FLAG_SUBTREE_ROOT)
 {
 {
     // Some compilers object to use of "this" in initializer lists.
     // Some compilers object to use of "this" in initializer lists.
     parent_ = this;
     parent_ = this;
@@ -373,7 +382,7 @@ RBNode<T>::RBNode(const isc::dns::Name& name) :
     right_(NULL_NODE()),
     right_(NULL_NODE()),
     name_(name),
     name_(name),
     down_(NULL_NODE()),
     down_(NULL_NODE()),
-    flags_(FLAG_RED)
+    flags_(FLAG_RED | FLAG_SUBTREE_ROOT)
 {
 {
 }
 }
 
 
@@ -1395,9 +1404,12 @@ RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
         //node is the new root of sub tree, so its init color
         //node is the new root of sub tree, so its init color
         // is BLACK
         // is BLACK
         node->setColor(RBNode<T>::BLACK);
         node->setColor(RBNode<T>::BLACK);
+        node->setSubTreeRoot(true);
     } else if (order < 0) {
     } else if (order < 0) {
+        node->setSubTreeRoot(false);
         parent->left_ = node.get();
         parent->left_ = node.get();
     } else {
     } else {
+        node->setSubTreeRoot(false);
         parent->right_ = node.get();
         parent->right_ = node.get();
     }
     }
     insertRebalance(current_root, node.get());
     insertRebalance(current_root, node.get());
@@ -1438,6 +1450,10 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
 
 
     // root node of sub tree, the initial color is BLACK
     // root node of sub tree, the initial color is BLACK
     down_node->setColor(RBNode<T>::BLACK);
     down_node->setColor(RBNode<T>::BLACK);
+
+    // mark it as the root of a subtree
+    down_node->setSubTreeRoot(true);
+
     ++node_count_;
     ++node_count_;
     down_node.release();
     down_node.release();
 }
 }
@@ -1494,23 +1510,30 @@ RBNode<T>*
 RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
 RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
     RBNode<T>* right = node->right_;
     RBNode<T>* right = node->right_;
     node->right_ = right->left_;
     node->right_ = right->left_;
-    if (right->left_ != NULLNODE)
+    if (right->left_ != NULLNODE) {
         right->left_->parent_ = node;
         right->left_->parent_ = node;
+        right->left_->setSubTreeRoot(false);
+    } else {
+        right->left_->setSubTreeRoot(true);
+    }
 
 
     right->parent_ = node->parent_;
     right->parent_ = node->parent_;
 
 
     if (node->parent_ != NULLNODE) {
     if (node->parent_ != NULLNODE) {
+        right->setSubTreeRoot(false);
         if (node == node->parent_->left_) {
         if (node == node->parent_->left_) {
             node->parent_->left_ = right;
             node->parent_->left_ = right;
         } else  {
         } else  {
             node->parent_->right_ = right;
             node->parent_->right_ = right;
         }
         }
     } else {
     } else {
+        right->setSubTreeRoot(true);
         *root = right;
         *root = right;
     }
     }
 
 
     right->left_ = node;
     right->left_ = node;
     node->parent_ = right;
     node->parent_ = right;
+    node->setSubTreeRoot(false);
     return (node);
     return (node);
 }
 }
 
 
@@ -1519,22 +1542,30 @@ RBNode<T>*
 RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
 RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
     RBNode<T>* left = node->left_;
     RBNode<T>* left = node->left_;
     node->left_ = left->right_;
     node->left_ = left->right_;
-    if (left->right_ != NULLNODE)
+    if (left->right_ != NULLNODE) {
         left->right_->parent_ = node;
         left->right_->parent_ = node;
+        left->right_->setSubTreeRoot(false);
+    } else {
+        left->right_->setSubTreeRoot(true);
+    }
 
 
     left->parent_ = node->parent_;
     left->parent_ = node->parent_;
 
 
     if (node->parent_ != NULLNODE) {
     if (node->parent_ != NULLNODE) {
+        left->setSubTreeRoot(false);
         if (node == node->parent_->right_) {
         if (node == node->parent_->right_) {
             node->parent_->right_ = left;
             node->parent_->right_ = left;
         } else  {
         } else  {
             node->parent_->left_ = left;
             node->parent_->left_ = left;
         }
         }
     } else {
     } else {
+        left->setSubTreeRoot(true);
         *root = left;
         *root = left;
     }
     }
     left->right_ = node;
     left->right_ = node;
     node->parent_ = left;
     node->parent_ = left;
+    node->setSubTreeRoot(false);
+
     return (node);
     return (node);
 }
 }
 
 

+ 1 - 2
src/lib/datasrc/tests/rbtree_unittest.cc

@@ -77,7 +77,6 @@ protected:
     const RBNode<int>* crbtnode;
     const RBNode<int>* crbtnode;
 };
 };
 
 
-
 TEST_F(RBTreeTest, getNodeCount) {
 TEST_F(RBTreeTest, getNodeCount) {
     EXPECT_EQ(14, rbtree.getNodeCount());
     EXPECT_EQ(14, rbtree.getNodeCount());
 }
 }
@@ -722,7 +721,7 @@ TEST_F(RBTreeTest, dumpTree) {
             "               end down from g.h.\n" <<
             "               end down from g.h.\n" <<
             "               NULL\n" <<
             "               NULL\n" <<
             "               NULL\n";
             "               NULL\n";
-    EXPECT_EQ(str.str(), str2.str());
+    EXPECT_EQ(str2.str(), str.str());
 }
 }
 
 
 TEST_F(RBTreeTest, swap) {
 TEST_F(RBTreeTest, swap) {