Parcourir la source

make the rbtree more generic

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac397@3530 e5f2f494-b856-4b98-b285-d166d9295462
Han Feng il y a 14 ans
Parent
commit
5ebb4759f7
3 fichiers modifiés avec 633 ajouts et 653 suppressions
  1. 1 1
      src/bin/auth/Makefile.am
  2. 0 596
      src/bin/auth/rbt_datasrc.cc
  3. 632 56
      src/bin/auth/rbt_datasrc.h

+ 1 - 1
src/bin/auth/Makefile.am

@@ -51,7 +51,7 @@ libasio_link_a_CPPFLAGS = $(AM_CPPFLAGS)
 BUILT_SOURCES = spec_config.h 
 pkglibexec_PROGRAMS = b10-auth
 b10_auth_SOURCES = auth_srv.cc auth_srv.h
-b10_auth_SOURCES += rbt_datasrc.h rbt_datasrc.cc
+b10_auth_SOURCES += rbt_datasrc.h 
 b10_auth_SOURCES += change_user.cc change_user.h
 b10_auth_SOURCES += common.h
 b10_auth_SOURCES += main.cc

+ 0 - 596
src/bin/auth/rbt_datasrc.cc

@@ -1,596 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-
-#include <cstdio>
-#include <iostream>
-#include <cassert>
-#include "rbt_datasrc.h"
-
-using namespace isc::dns;
-namespace {
-/// helper function to remove the base domain from super domain
-/// the precondition of this function is the super_name contains the
-/// sub_name
-Name
-operator-(const Name& super_name, const Name& sub_name) {
-    return (super_name.split(0, super_name.getLabelCount() -
-                             sub_name.getLabelCount()));
-}
-}
-
-namespace isc {
-namespace datasrc {
-RBNode::RBNode(const Name& name, RRsetListPtr rrsets, RBNode* nullnode) :
-    parent_(nullnode),
-    left_(nullnode),
-    right_(nullnode),
-    color_(RED),
-    name_(name),
-    rrsets_(rrsets),
-    down_(NULL),
-    is_delegate_(false),
-    is_nonterminal_(false)
-{
-}
-
-RBNode::~RBNode() {
-    delete down_;
-}
-
-RBNode*
-RBNode::successor() {
-    RBNode* current = this;
-
-    // if it has right node, the successor is the left-most node
-    if (right_ != right_->right_) {
-        current = right_;
-        while (current->left_ != current->left_->left_) {
-            current = current->left_;
-        }
-        return (current);
-    }
-
-    // otherwise return the parent without left child or
-    // current node is not its right child
-    RBNode* s = current->parent_;
-    while (s != s->left_ && current == s->right_) {
-        current = s;
-        s = s->parent_;
-    }
-    return (s);
-}
-
-int
-RBNode::addRRset(RRsetPtr rrset) {
-    if (rrset->getType() == RRType::NS()) {
-        is_delegate_ = true;
-    }
-    if (rrsets_.get() == NULL) {
-        rrsets_.reset(new RRsetList());
-    }
-    rrsets_->addRRset(rrset);
-    is_nonterminal_ = false;
-    return (0);
-}
-
-void
-RBNode::cloneDNSData(RBNode& node) {
-    node.name_ = name_;
-    node.rrsets_ = rrsets_;
-    node.is_delegate_ = is_delegate_;
-    node.is_nonterminal_ = is_nonterminal_;
-}
-
-void
-RBNode::setDownTree(RBTree* down) {
-    down_ = down;
-    if (down) {
-        down->up_ = this;
-    }
-}
-
-/*
- with the following names:
-     a       x.d.e.f     o.w.y.d.e.f
-     b       z.d.e.f     p.w.y.d.e.f
-     c       g.h         q.w.y.d.e.f
-     the tree will looks like:
-                                  b
-                                /   \
-                               a    d.e.f
-                                      /|\
-                                     c | g.h
-                                       |
-                                      w.y
-                                      /|\
-                                     x | z
-                                       |
-                                       p
-                                      / \
-                                     o   q
-*/
-RBTree::RBTree() {
-    NULLNODE = new RBNode(Name(" "));
-    NULLNODE->parent_  = NULLNODE->left_ = NULLNODE->right_ = NULLNODE;
-    NULLNODE->color_ = BLACK;
-    root_ = NULLNODE;
-    node_count_ = 0;
-    up_ = NULL;
-}
-
-
-RBTree::~RBTree() {
-    assert(root_ != NULL);
-
-    delete NULLNODE;
-    if (root_ == NULLNODE) {
-        return;
-    }
-
-    RBNode* node = root_;
-    while (root_->left_ != NULLNODE || root_->right_ != NULLNODE) {
-        while (node->left_ != NULLNODE || node->right_ != NULLNODE) {
-            node = (node->left_ != NULLNODE) ? node->left_ : node->right_;
-        }
-
-        RBNode* parent = node->parent_;
-        if (parent->left_ == node) {
-            parent->left_ = NULLNODE;
-        } else {
-            parent->right_ = NULLNODE;
-        }
-        delete node;
-        node = parent;
-    }
-
-    delete root_;
-    root_ = NULL;
-}
-
-RBTree::FindResult
-RBTree::find(const Name& name, RBNode** node) const {
-    RBTree* tree;
-    return (findHelper(name, &tree, node));
-}
-
-
-RBTree::FindResult
-RBTree::findHelper(const Name& name, RBTree** tree, RBNode** ret) const {
-    RBNode* node = root_;
-    while (node != NULLNODE) {
-        NameComparisonResult compare_result = name.compare(node->name_);
-        NameComparisonResult::NameRelation relation =
-            compare_result.getRelation();
-        if (relation == NameComparisonResult::EQUAL) {
-            *tree = (RBTree*)this;
-            *ret = node;
-            return (RBTree::EXACTMATCH);
-        } else {
-            int common_label_count = compare_result.getCommonLabels();
-            // common label count equal one means, there is no common between
-            // two names
-            if (common_label_count == 1) {
-                node = (compare_result.getOrder() < 0) ?
-                    node->left_ : node->right_;
-            } else if (NameComparisonResult::SUBDOMAIN == relation) {
-                if (node->isDelegate()) {
-                    *tree = (RBTree*)this;
-                    *ret = node;
-                    return (RBTree::FINDREFERRAL);
-                } else if (node->down_) {
-                    // the node all save the relative name, so we need to
-                    // remove the suffix
-                    return (node->down_->findHelper(name - node->name_, tree,
-                                                    ret));
-                } else {
-                    return (RBTree::NOTFOUND);
-                }
-            } else {
-                return (RBTree::NOTFOUND);
-            }
-        }
-    }
-
-    return (RBTree::NOTFOUND);
-}
-
-int
-RBTree::getNodeCount() const {
-    return (getNodeCountHelper(root_));
-}
-
-int
-RBTree::getNodeCountHelper(const RBNode *node) const {
-    if (NULLNODE == node) {
-        return (0);
-    }
-
-    int sub_tree_node_count = node->down_ ? node->down_->getNodeCount() : 0;
-    return (1 + sub_tree_node_count + getNodeCountHelper(node->left_) +
-            getNodeCountHelper(node->right_));
-}
-
-int
-RBTree::insert(const Name& name, RBNode** new_node) {
-    RBNode* parent = NULLNODE;
-    RBNode* current = root_;
-
-    int order = -1;
-    while (current != NULLNODE) {
-        parent = current;
-
-        NameComparisonResult compare_result = name.compare(current->name_);
-        NameComparisonResult::NameRelation relation =
-            compare_result.getRelation();
-        if (relation == NameComparisonResult::EQUAL) {
-            if (new_node) {
-                *new_node = current;
-            }
-            // if the node is non-ternimal, it does not exist, so we return 0
-            return (current->rrsets_.get() ? 1 : 0);
-        } else {
-            int common_label_count = compare_result.getCommonLabels();
-            if (common_label_count == 1) {
-                order = compare_result.getOrder();
-                current = order < 0 ? current->left_ : current->right_;
-            } else {
-                // insert sub domain to sub tree
-                if (relation == NameComparisonResult::SUBDOMAIN) {
-                    if (NULL == current->down_) {
-                        current->setDownTree(new RBTree());
-                    }
-                    return (current->down_->insert(name - current->name_,
-                                                   new_node));
-                } else {
-                    // for super domain or has common label domain, create
-                    // common node first then insert current name and new name
-                    // into the sub tree
-                    Name common_ancestor = name.split(
-                        name.getLabelCount() - common_label_count,
-                        common_label_count);
-                    Name sub_name = current->name_ - common_ancestor;
-                    current->name_ = common_ancestor;
-                    RBTree* down_old = current->down_;
-                    current->setDownTree(new RBTree());
-                    RBNode* sub_root;
-                    current->down_->insert(sub_name, &sub_root);
-
-                    current->cloneDNSData(*sub_root);
-                    sub_root->setDownTree(down_old);
-                    sub_root->name_ = sub_name;
-
-                    current->rrsets_.reset();
-                    // if insert name is the super domain of current node, no
-                    // need insert again otherwise insert it into the down
-                    // tree.
-                    if (name.getLabelCount() == common_label_count) {
-                        *new_node = current;
-                        return (0);
-                    } else {
-                        current->is_nonterminal_ = true;
-                        return (current->down_->insert(name - common_ancestor,
-                                                       new_node));
-                    }
-                }
-            }
-        }
-    }
-
-    RBNode* node = new RBNode(name, RBNode::RRsetListPtr(), NULLNODE);
-    node->parent_ = parent;
-    if (parent == NULLNODE) {
-        root_ = node;
-    } else if (order < 0) {
-        parent->left_ = node;
-    } else {
-        parent->right_ = node;
-    }
-
-    insertRebalance(node);
-    if (new_node) {
-        *new_node = node;
-    }
-    ++node_count_;
-    return (0);
-}
-
-void
-RBTree::insertRebalance(RBNode* node) {
-    RBNode* uncle;
-
-    while (node->parent_->color_ == RED) {
-        if (node->parent_ == node->parent_->parent_->left_) {
-            uncle = node->parent_->parent_->right_;
-
-            if (uncle->color_ == RED) {
-                node->parent_->color_ = BLACK;
-                uncle->color_ = BLACK;
-                node->parent_->parent_->color_ = RED;
-                node = node->parent_->parent_;
-            } else {
-                if (node == node->parent_->right_) {
-                    node = node->parent_;
-                    leftRotate(node);
-                }
-
-                node->parent_->color_ = BLACK;
-                node->parent_->parent_->color_ = RED;
-
-                rightRotate(node->parent_->parent_);
-            }
-        } else {
-            uncle = node->parent_->parent_->left_;
-
-            if (uncle->color_ == RED) {
-                node->parent_->color_ = BLACK;
-                uncle->color_ = BLACK;
-                node->parent_->parent_->color_ = RED;
-                node = node->parent_->parent_;
-            } else {
-                if (node == node->parent_->left_) {
-                    node = node->parent_;
-                    rightRotate(node);
-                }
-
-                node->parent_->color_ = BLACK;
-                node->parent_->parent_->color_ = RED;
-
-                leftRotate(node->parent_->parent_);
-            }
-        }
-    }
-
-    root_->color_ = BLACK;
-}
-
-
-RBNode*
-RBTree::leftRotate(RBNode* p) {
-    RBNode* c = p->right_;
-
-    p->right_ = c->left_;
-
-    if (c->left_ != NULLNODE) {
-        c->left_->parent_ = p;
-    }
-
-    c->parent_ = p->parent_;
-
-    if (p->parent_ == NULLNODE) {
-        root_ = c;
-    } else if (p == p->parent_->left_) {
-        p->parent_->left_ = c;
-    } else {
-        p->parent_->right_ = c;
-    }
-
-    c->left_ = p;
-    p->parent_ = c;
-
-    return (c);
-}
-
-RBNode*
-RBTree::rightRotate(RBNode* p) {
-    RBNode* c = p->left_;
-
-    p->left_ = c->right_;
-
-    if (c->right_ != NULLNODE) {
-        c->right_->parent_ = p;
-    }
-
-    c->parent_ = p->parent_;
-
-    if (p->parent_ == NULLNODE) {
-        root_ = c;
-    } else if (p == p->parent_->left_) {
-        p->parent_->left_ = c;
-    } else {
-        p->parent_->right_ = c;
-    }
-
-    c->right_ = p;
-    p->parent_ = c;
-
-    return (c);
-}
-
-
-int
-RBTree::erase(const Name& name) {
-    RBNode* node;
-    RBTree* tree;
-    if (findHelper(name, &tree, &node) != RBTree::EXACTMATCH) {
-        return (1);
-    }
-
-    // cannot delete non terminal
-    if (node->down_ != NULL) {
-        return (1);
-    }
-
-    tree->eraseNode(node);
-    // merge down to up
-    if (tree->node_count_ == 1 && tree->up_ != NULL &&
-        tree->up_->isNonterminal()) {
-        RBNode* up = tree->up_;
-        Name merged_name = tree->root_->name_.concatenate(up->name_);
-        tree->root_->cloneDNSData(*up);
-        up->setDownTree(tree->root_->down_);
-        tree->root_->setDownTree(NULL);
-        up->name_ = merged_name;
-        up->is_nonterminal_ = false;
-        delete tree;
-    } else if (tree->node_count_ == 0 && tree->up_) { // delete empty tree
-        tree->up_->setDownTree(NULL);
-        delete tree;
-    }
-
-    return (0);
-}
-
-
-void
-RBTree::eraseNode(RBNode *node) {
-    RBNode* y = NULLNODE;
-    RBNode* x = NULLNODE;
-
-    if (node->left_ == NULLNODE || node->right_ == NULLNODE) {
-        y = node;
-    } else {
-        y = node->successor();
-    }
-
-    if (y->left_ != NULLNODE) {
-        x = y->left_;
-    } else {
-        x = y->right_;
-    }
-
-    x->parent_ = y->parent_;
-
-    if (y->parent_ == NULLNODE) {
-        root_ = x;
-    } else if (y == y->parent_->left_) {
-        y->parent_->left_ = x;
-    } else {
-        y->parent_->right_ = x;
-    }
-
-    if (y != node) {
-        y->cloneDNSData(*node);
-        node->setDownTree(y->down_);
-        y->down_ = NULL;
-    }
-
-    if (y->color_ == BLACK) {
-        deleteRebalance(x);
-    }
-
-    y->left_ = NULL;
-    y->right_ = NULL;
-    delete y;
-    --node_count_;
-}
-
-void
-RBTree::deleteRebalance(RBNode* node) {
-    RBNode* w = NULLNODE;
-
-    while (node != root_ && node->color_ == BLACK) {
-        if (node == node->parent_->left_) {
-            w = node->parent_->right_;
-
-            if (w->color_ == RED) {
-                w->color_ = BLACK;
-                node->parent_->color_ = RED;
-                leftRotate(node->parent_);
-                w = node->parent_->right_;
-            }
-
-            if (w->left_->color_ == BLACK && w->right_->color_ == BLACK) {
-                w->color_ = RED;
-                node = node->parent_;
-            } else {
-                if (w->right_->color_ == BLACK) {
-                    w->left_->color_ = BLACK;
-                    w->color_ = RED;
-                    rightRotate(w);
-                    w = node->parent_->right_;
-                }
-
-                w->color_ = node->parent_->color_;
-                node->parent_->color_ = BLACK;
-                w->right_->color_ = BLACK;
-                leftRotate(node->parent_);
-                node = root_;
-            }
-        } else {
-            w = node->parent_->left_;
-            if (w->color_ == RED) {
-                w->color_ = BLACK;
-                node->parent_->color_ = RED;
-                rightRotate(node->parent_);
-                w = node->parent_->left_;
-            }
-
-            if (w->right_->color_ == BLACK && w->left_->color_ == BLACK) {
-                w->color_ = RED;
-                node = node->parent_;
-            } else {
-                if (w->left_->color_ == BLACK) {
-                    w->right_->color_ = BLACK;
-                    w->color_ = RED;
-                    leftRotate(w);
-                    w = node->parent_->left_;
-                }
-                w->color_ = node->parent_->color_;
-                node->parent_->color_ = BLACK;
-                w->left_->color_ = BLACK;
-                rightRotate(node->parent_);
-                node = root_;
-            }
-        }
-    }
-
-    node->color_ = BLACK;
-}
-
-#define INDNET(depth) do { \
-    int i = 0; \
-    for (; i < (depth) * 5; ++i) { \
-        std::cout << " "; \
-    } \
-} while(0)
-
-void
-RBTree::printTree(int depth) const {
-    INDNET(depth);
-    std::cout << "tree has node " << node_count_ << "\n";
-    printTreeHelper(root_, depth);
-}
-
-void
-RBTree::printTreeHelper(RBNode* node, int depth) const {
-    INDNET(depth);
-    std::cout << node->name_.toText() << " ("
-              << ((node->color_ == BLACK) ? "black" : "red") << ")\n";
-    std::cout << ((node->isNonterminal()) ? "[non-terminal] \n" : "\n");
-    if (node->down_) {
-        assert(node->down_->up_ == node);
-        INDNET(depth + 1);
-        std::cout << "begin down from "<< node->name_.toText() << "\n";
-        node->down_->printTree(depth + 1);
-        INDNET(depth + 1);
-        std::cout << "end down from" << node->name_.toText() <<"\n";
-    }
-
-    if (node->left_ != NULLNODE) {
-        printTreeHelper(node->left_, depth + 1);
-    } else {
-        INDNET(depth + 1);
-        std::cout << "NULL\n";
-    }
-
-    if (node->right_ != NULLNODE) {
-        printTreeHelper(node->right_, depth + 1);
-    } else {
-        INDNET(depth + 1);
-        std::cout << "NULL\n";
-    }
-}
-}
-}

+ 632 - 56
src/bin/auth/rbt_datasrc.h

@@ -25,8 +25,20 @@ using namespace isc::dns;
 namespace isc {
 namespace datasrc {
 
+namespace {
+/// helper function to remove the base domain from super domain
+/// the precondition of this function is the super_name contains the
+/// sub_name
+Name
+operator-(const Name& super_name, const Name& sub_name) {
+    return (super_name.split(0, super_name.getLabelCount() -
+                             sub_name.getLabelCount()));
+}
+}
+
 /// \brief Define rbtree color
 enum RBTreeColor {BLACK = 1, RED};
+template <typename T>
 class RBTree;
 
 /// \brief \c RBNode class represents one domain name in the domain space
@@ -43,45 +55,27 @@ class RBTree;
 ///
 /// \b Note: \c RBNode should be created or destroyed only by \c RBTree so
 /// constructor and destructor function aren't exposed.
-
+template <typename T>
 class RBNode : public boost::noncopyable {
 public:
     /// only /c RBTree can create and destroy \c RBNode
-    friend class RBTree;
-    typedef boost::shared_ptr<RRsetList> RRsetListPtr;
-
+    friend class RBTree<T>;
     /// \name Test functions
-    ///
     //@{
-    /// \brief return whether current domain name has NS records
-    bool isDelegate() const { return (is_delegate_); }
-
-    /// \brief return whether current domain name is non-terminal
-    /// A non-terminal domain has no RRsets but at least one of its descendant
-    /// domain has RRset
-    bool isNonterminal() const { return (is_nonterminal_); }
-
     /// \brief return the name of current node, it's relative to its parents
     //
     /// \todo Is it meaningful to return the absolute of the node?
     const Name& getName() const {return (name_); }
 
+    // \breif return the data 
+    T& getData() { return (data_);}
     // \brief return next node whose name is bigger than current node
-    RBNode* successor();
-    //@}
-
-
-    /// \name modify function
-    //@{
-
-    /// \brief add an RRset to the node
-    /// \Note: there is no check about whether the node already has the RRset
-    /// or not
-    /// and no check about whether the name of the RRset is the same with the
-    /// node or not.
-    /// It is the caller's responsibility to ensure these conditions.
-    int addRRset(RRsetPtr rrset);
+    RBNode<T>* successor();
     //@}
+    
+    /// \name Modify functions
+    // \brief return the data stored in the node
+    void setData(T& data) { data_ = data;}
 
 private:
     /// \name Constructors and destructor
@@ -90,8 +84,11 @@ private:
     /// use one specified
     /// default node singled as null node, this is intended to keep the code
     /// more unify
-    RBNode(const Name& name, RRsetListPtr rrsets = RRsetListPtr(),
-           RBNode* nullnode = NULL);
+
+    RBNode(const Name &name, RBNode<T> *nullnode = NULL);
+
+    RBNode(const Name& name, T& data,
+            RBNode<T>* nullnode = NULL);
 
     /// the class isn't left to be inherited
     ~RBNode();
@@ -99,28 +96,93 @@ private:
 
     /// \brief copy the DNS related data to another node except the sub domain
     /// tree
-    void cloneDNSData(RBNode& node);
+    void cloneDNSData(RBNode<T>& node);
 
     /// \brief when copy the DNS data from one node to another, except the
     /// RRsets, name etc,
     /// also needs to maintain the down and up relationship, which includes
     /// set the down point of current node and up point of sub domain tree
-    void setDownTree(RBTree* down);
+    void setDownTree(RBTree<T>* down);
 
     /// data to maintain the rbtree balance
-    RBNode*  parent_;
-    RBNode*  left_;
-    RBNode*  right_;
-    int       color_;
+    RBNode<T>*  parent_;
+    RBNode<T>*  left_;
+    RBNode<T>*  right_;
+    RBTreeColor color_;
 
     /// data to carry dns info
-    Name      name_;
-    RRsetListPtr rrsets_;
-    RBTree*  down_;
-    bool      is_delegate_;
-    bool      is_nonterminal_;
+    Name        name_;
+    T           data_;
+    RBTree<T>*  down_;
+    bool        is_shadow_; ///the node willn't return to end user, if the node is shadow
 };
 
+
+template <typename T>
+RBNode<T>::RBNode(const Name& name, T &data, RBNode* nullnode) :
+    parent_(nullnode),
+    left_(nullnode),
+    right_(nullnode),
+    color_(RED),
+    name_(name),
+    data_(data),
+    down_(NULL) {
+}
+
+template <typename T>
+RBNode<T>::RBNode(const Name& name, RBNode* nullnode) :
+    parent_(nullnode),
+    left_(nullnode),
+    right_(nullnode),
+    color_(RED),
+    name_(name),
+    down_(NULL) {
+}
+
+template <typename T>
+RBNode<T>::~RBNode() {
+    delete down_;
+}
+
+template <typename T>
+RBNode<T>*
+RBNode<T>::successor() {
+    RBNode<T>* current = this;
+
+    // if it has right node, the successor is the left-most node
+    if (right_ != right_->right_) {
+        current = right_;
+        while (current->left_ != current->left_->left_) {
+            current = current->left_;
+        }
+        return (current);
+    }
+
+    // otherwise return the parent without left child or
+    // current node is not its right child
+    RBNode<T>* s = current->parent_;
+    while (s != s->left_ && current == s->right_) {
+        current = s;
+        s = s->parent_;
+    }
+    return (s);
+}
+
+template <typename T>
+void
+RBNode<T>::cloneDNSData(RBNode<T>& node) {
+    node.name_ = name_;
+    node.data_ = data_;
+}
+
+template <typename T>
+void
+RBNode<T>::setDownTree(RBTree<T>* down) {
+    down_ = down;
+    if (down) {
+        down->up_ = this;
+    }
+}
 /// \brief \c RBTree class represents all the domains with the same suffix,
 /// so it can be used to store the domains in one zone.
 ///
@@ -130,15 +192,16 @@ private:
 /// or tree in tree.
 /// So for one zone, several RBTrees may be involved. But from outside, the sub
 /// tree is opaque for end users.
+template <typename T>
 class RBTree : public boost::noncopyable {
-    friend class RBNode;
+    friend class RBNode<T>;
 public:
     /// \brief The return value for the \c find() method
     /// - EXACTMATCH: return the node in the tree exactly same with the target
     /// - FINDREFERRAL: return the node which is an ancestor of the target
     ///   containing NS record
     /// - NOTFOUND: other conditions except EXACTMATCH & FINDREFERRAL
-    enum FindResult{EXACTMATCH, FINDREFERRAL, NOTFOUND};
+    enum FindResult{EXACTMATCH, PARTIALMATCH, NOTFOUND};
 
     /// \name Constructor and Destructor
     //@{
@@ -156,7 +219,7 @@ public:
     /// \param node Point to the node when the return vaule is \c not
     /// NOTFOUND, if the return value is NOTFOUND, the value of node is
     /// \c unknown
-    FindResult find(const Name& name, RBNode** node) const;
+    FindResult find(const Name& name, RBNode<T>** node) const;
 
     /// \brief Get the total node count in the tree
     int getNodeCount() const;
@@ -183,7 +246,7 @@ public:
     /// To add an RRset into one node when it's not known whether the node
     /// already exists, it is better to call \c insert and then call the
     /// RBNode interface instead of calling \c find().
-    int insert(const Name& name, RBNode** inserted_node);
+    int insert(const Name& name, RBNode<T>** inserted_node);
 
     /// \brief Erase the node with the domain name
     /// \return If no node with the name, return 1; otherwise return 0
@@ -193,28 +256,541 @@ public:
 private:
     /// \name RBTree balance functions
     //@{
-    void deleteRebalance(RBNode* node);
-    void insertRebalance(RBNode* node);
-    RBNode* rightRotate(RBNode* p);
-    RBNode* leftRotate(RBNode* p);
+    void deleteRebalance(RBNode<T>* node);
+    void insertRebalance(RBNode<T>* node);
+    RBNode<T>* rightRotate(RBNode<T>* p);
+    RBNode<T>* leftRotate(RBNode<T>* p);
     //@}
 
     /// \name Helper functions
     //@{
     /// Each public function has related recursive helper function
-    void eraseNode(RBNode* node);
-    FindResult findHelper(const Name& name, RBTree** tree,
-                          RBNode** node) const;
-    int getNodeCountHelper(const RBNode* node) const;
-    void printTreeHelper(RBNode* node, int depth) const;
+    void eraseNode(RBNode<T>* node);
+    FindResult findHelper(const Name& name, RBTree<T>** tree,
+                          RBNode<T>** node) const;
+    int getNodeCountHelper(const RBNode<T>* node) const;
+    void printTreeHelper(RBNode<T>* node, int depth) const;
     //@}
 
-    RBNode*  root_;
-    RBNode*  NULLNODE;
-    RBNode*  up_;
+    RBNode<T>*  root_;
+    RBNode<T>*  NULLNODE;
+    RBNode<T>*  up_;
     /// the node count of current tree except the sub domain trees
     unsigned int node_count_;
 };
+
+/*
+ with the following names:
+     a       x.d.e.f     o.w.y.d.e.f
+     b       z.d.e.f     p.w.y.d.e.f
+     c       g.h         q.w.y.d.e.f
+     the tree will looks like:
+                                  b
+                                /   \
+                               a    d.e.f
+                                      /|\
+                                     c | g.h
+                                       |
+                                      w.y
+                                      /|\
+                                     x | z
+                                       |
+                                       p
+                                      / \
+                                     o   q
+*/
+template <typename T>
+RBTree<T>::RBTree() {
+    NULLNODE = new RBNode<T>(Name(" "));
+    NULLNODE->parent_  = NULLNODE->left_ = NULLNODE->right_ = NULLNODE;
+    NULLNODE->color_ = BLACK;
+    root_ = NULLNODE;
+    node_count_ = 0;
+    up_ = NULL;
+}
+
+template <typename T>
+RBTree<T>::~RBTree() {
+    assert(root_ != NULL);
+
+    delete NULLNODE;
+    if (root_ == NULLNODE) {
+        return;
+    }
+
+    RBNode<T>* node = root_;
+    while (root_->left_ != NULLNODE || root_->right_ != NULLNODE) {
+        while (node->left_ != NULLNODE || node->right_ != NULLNODE) {
+            node = (node->left_ != NULLNODE) ? node->left_ : node->right_;
+        }
+
+        RBNode<T>* parent = node->parent_;
+        if (parent->left_ == node) {
+            parent->left_ = NULLNODE;
+        } else {
+            parent->right_ = NULLNODE;
+        }
+        delete node;
+        node = parent;
+    }
+
+    delete root_;
+    root_ = NULL;
+}
+
+template <typename T>
+typename RBTree<T>::FindResult
+RBTree<T>::find(const Name& name, RBNode<T>** node) const {
+    RBTree<T>* tree;
+    return (findHelper(name, &tree, node));
+}
+
+template <typename T>
+typename RBTree<T>::FindResult
+RBTree<T>::findHelper(const Name& name, RBTree<T>** tree, RBNode<T>** ret) const {
+    RBNode<T>* node = root_;
+    while (node != NULLNODE) {
+        NameComparisonResult compare_result = name.compare(node->name_);
+        NameComparisonResult::NameRelation relation =
+            compare_result.getRelation();
+        if (relation == NameComparisonResult::EQUAL) {
+            *tree = (RBTree*)this;
+            *ret = node;
+            return (RBTree<T>::EXACTMATCH);
+        } else {
+            int common_label_count = compare_result.getCommonLabels();
+            // common label count equal one means, there is no common between
+            // two names
+            if (common_label_count == 1) {
+                node = (compare_result.getOrder() < 0) ?
+                    node->left_ : node->right_;
+            } else if (NameComparisonResult::SUBDOMAIN == relation) {
+                if (node->is_shadow_) {
+                    assert(node->down_);
+                    return (node->down_->findHelper(name - node->name_, tree,
+                                    ret));
+                } else {
+                    RBTree<T>::FindResult result = RBTree<T>::NOTFOUND;
+                    if (node->down_) {
+                        result = node->down_->findHelper(name - node->name_, tree,
+                                ret);
+                    }
+                    // if not found in sub domain tree, so current node is the longest match
+                    // otherwise return the result in sub domin tree
+                    if (RBTree<T>::NOTFOUND == result) {
+                        *tree = (RBTree *)this;
+                        *ret = node;
+                        return RBTree<T>::PARTIALMATCH;
+                    } else {
+                        return result;
+                    }
+                }
+            } else {
+                return (RBTree<T>::NOTFOUND);
+            }
+        }
+    }
+
+    return (RBTree<T>::NOTFOUND);
+}
+
+template <typename T>
+int
+RBTree<T>::getNodeCount() const {
+    return (getNodeCountHelper(root_));
+}
+
+template <typename T>
+int
+RBTree<T>::getNodeCountHelper(const RBNode<T> *node) const {
+    if (NULLNODE == node) {
+        return (0);
+    }
+
+    int sub_tree_node_count = node->down_ ? node->down_->getNodeCount() : 0;
+    return (1 + sub_tree_node_count + getNodeCountHelper(node->left_) +
+            getNodeCountHelper(node->right_));
+}
+
+template <typename T>
+int
+RBTree<T>::insert(const Name& name, RBNode<T>** new_node) {
+    RBNode<T>* parent = NULLNODE;
+    RBNode<T>* current = root_;
+
+    int order = -1;
+    while (current != NULLNODE) {
+        parent = current;
+
+        NameComparisonResult compare_result = name.compare(current->name_);
+        NameComparisonResult::NameRelation relation =
+            compare_result.getRelation();
+        if (relation == NameComparisonResult::EQUAL) {
+            if (new_node) {
+                *new_node = current;
+            }
+            // if the node is non-ternimal, it does not exist, so we return 0
+            return (current->is_shadow_ ? 0 : 1);
+        } else {
+            int common_label_count = compare_result.getCommonLabels();
+            if (common_label_count == 1) {
+                order = compare_result.getOrder();
+                current = order < 0 ? current->left_ : current->right_;
+            } else {
+                // insert sub domain to sub tree
+                if (relation == NameComparisonResult::SUBDOMAIN) {
+                    if (NULL == current->down_) {
+                        current->setDownTree(new RBTree());
+                    }
+                    return (current->down_->insert(name - current->name_,
+                                                   new_node));
+                } else {
+                    // for super domain or has common label domain, create
+                    // common node first then insert current name and new name
+                    // into the sub tree
+                    Name common_ancestor = name.split(
+                        name.getLabelCount() - common_label_count,
+                        common_label_count);
+                    Name sub_name = current->name_ - common_ancestor;
+                    current->name_ = common_ancestor;
+                    RBTree<T>* down_old = current->down_;
+                    current->setDownTree(new RBTree<T>());
+                    RBNode<T>* sub_root;
+                    current->down_->insert(sub_name, &sub_root);
+
+                    current->cloneDNSData(*sub_root);
+                    sub_root->setDownTree(down_old);
+                    sub_root->name_ = sub_name;
+                    current->is_shadow_ = true;
+
+                    // if insert name is the super domain of current node, no
+                    // need insert again otherwise insert it into the down
+                    // tree.
+                    if (name.getLabelCount() == common_label_count) {
+                        *new_node = current;
+                        current->is_shadow_ = false;
+                        return (0);
+                    } else {
+                        return (current->down_->insert(name - common_ancestor,
+                                                       new_node));
+                    }
+                }
+            }
+        }
+    }
+
+    RBNode<T>* node = new RBNode<T>(name, NULLNODE);
+    node->parent_ = parent;
+    if (parent == NULLNODE) {
+        root_ = node;
+    } else if (order < 0) {
+        parent->left_ = node;
+    } else {
+        parent->right_ = node;
+    }
+
+    insertRebalance(node);
+    if (new_node) {
+        *new_node = node;
+    }
+    ++node_count_;
+    return (0);
+}
+
+template <typename T>
+void
+RBTree<T>::insertRebalance(RBNode<T>* node) {
+    RBNode<T>* uncle;
+
+    while (node->parent_->color_ == RED) {
+        if (node->parent_ == node->parent_->parent_->left_) {
+            uncle = node->parent_->parent_->right_;
+
+            if (uncle->color_ == RED) {
+                node->parent_->color_ = BLACK;
+                uncle->color_ = BLACK;
+                node->parent_->parent_->color_ = RED;
+                node = node->parent_->parent_;
+            } else {
+                if (node == node->parent_->right_) {
+                    node = node->parent_;
+                    leftRotate(node);
+                }
+
+                node->parent_->color_ = BLACK;
+                node->parent_->parent_->color_ = RED;
+
+                rightRotate(node->parent_->parent_);
+            }
+        } else {
+            uncle = node->parent_->parent_->left_;
+
+            if (uncle->color_ == RED) {
+                node->parent_->color_ = BLACK;
+                uncle->color_ = BLACK;
+                node->parent_->parent_->color_ = RED;
+                node = node->parent_->parent_;
+            } else {
+                if (node == node->parent_->left_) {
+                    node = node->parent_;
+                    rightRotate(node);
+                }
+
+                node->parent_->color_ = BLACK;
+                node->parent_->parent_->color_ = RED;
+
+                leftRotate(node->parent_->parent_);
+            }
+        }
+    }
+
+    root_->color_ = BLACK;
+}
+
+template <typename T>
+RBNode<T>*
+RBTree<T>::leftRotate(RBNode<T>* p) {
+    RBNode<T>* c = p->right_;
+
+    p->right_ = c->left_;
+
+    if (c->left_ != NULLNODE) {
+        c->left_->parent_ = p;
+    }
+
+    c->parent_ = p->parent_;
+
+    if (p->parent_ == NULLNODE) {
+        root_ = c;
+    } else if (p == p->parent_->left_) {
+        p->parent_->left_ = c;
+    } else {
+        p->parent_->right_ = c;
+    }
+
+    c->left_ = p;
+    p->parent_ = c;
+
+    return (c);
+}
+
+template <typename T>
+RBNode<T>*
+RBTree<T>::rightRotate(RBNode<T>* p) {
+    RBNode<T>* c = p->left_;
+
+    p->left_ = c->right_;
+
+    if (c->right_ != NULLNODE) {
+        c->right_->parent_ = p;
+    }
+
+    c->parent_ = p->parent_;
+
+    if (p->parent_ == NULLNODE) {
+        root_ = c;
+    } else if (p == p->parent_->left_) {
+        p->parent_->left_ = c;
+    } else {
+        p->parent_->right_ = c;
+    }
+
+    c->right_ = p;
+    p->parent_ = c;
+
+    return (c);
+}
+
+
+template <typename T>
+int
+RBTree<T>::erase(const Name& name) {
+    RBNode<T>* node;
+    RBTree<T>* tree;
+    if (findHelper(name, &tree, &node) != RBTree<T>::EXACTMATCH) {
+        return (1);
+    }
+
+    // cannot delete non terminal
+    if (node->down_ != NULL) {
+        return (1);
+    }
+
+    tree->eraseNode(node);
+    // merge down to up
+    if (tree->node_count_ == 1 && tree->up_ != NULL &&
+        tree->up_->is_shadow_) {
+        RBNode<T>* up = tree->up_;
+        Name merged_name = tree->root_->name_.concatenate(up->name_);
+        tree->root_->cloneDNSData(*up);
+        up->setDownTree(tree->root_->down_);
+        tree->root_->setDownTree(NULL);
+        up->name_ = merged_name;
+        up->is_shadow_ = false;
+        delete tree;
+    } else if (tree->node_count_ == 0 && tree->up_) { // delete empty tree
+        tree->up_->setDownTree(NULL);
+        delete tree;
+    }
+
+    return (0);
+}
+
+
+template <typename T>
+void
+RBTree<T>::eraseNode(RBNode<T> *node) {
+    RBNode<T>* y = NULLNODE;
+    RBNode<T>* x = NULLNODE;
+
+    if (node->left_ == NULLNODE || node->right_ == NULLNODE) {
+        y = node;
+    } else {
+        y = node->successor();
+    }
+
+    if (y->left_ != NULLNODE) {
+        x = y->left_;
+    } else {
+        x = y->right_;
+    }
+
+    x->parent_ = y->parent_;
+
+    if (y->parent_ == NULLNODE) {
+        root_ = x;
+    } else if (y == y->parent_->left_) {
+        y->parent_->left_ = x;
+    } else {
+        y->parent_->right_ = x;
+    }
+
+    if (y != node) {
+        y->cloneDNSData(*node);
+        node->setDownTree(y->down_);
+        y->down_ = NULL;
+    }
+
+    if (y->color_ == BLACK) {
+        deleteRebalance(x);
+    }
+
+    y->left_ = NULL;
+    y->right_ = NULL;
+    delete y;
+    --node_count_;
+}
+
+template <typename T>
+void
+RBTree<T>::deleteRebalance(RBNode<T>* node) {
+    RBNode<T>* w = NULLNODE;
+
+    while (node != root_ && node->color_ == BLACK) {
+        if (node == node->parent_->left_) {
+            w = node->parent_->right_;
+
+            if (w->color_ == RED) {
+                w->color_ = BLACK;
+                node->parent_->color_ = RED;
+                leftRotate(node->parent_);
+                w = node->parent_->right_;
+            }
+
+            if (w->left_->color_ == BLACK && w->right_->color_ == BLACK) {
+                w->color_ = RED;
+                node = node->parent_;
+            } else {
+                if (w->right_->color_ == BLACK) {
+                    w->left_->color_ = BLACK;
+                    w->color_ = RED;
+                    rightRotate(w);
+                    w = node->parent_->right_;
+                }
+
+                w->color_ = node->parent_->color_;
+                node->parent_->color_ = BLACK;
+                w->right_->color_ = BLACK;
+                leftRotate(node->parent_);
+                node = root_;
+            }
+        } else {
+            w = node->parent_->left_;
+            if (w->color_ == RED) {
+                w->color_ = BLACK;
+                node->parent_->color_ = RED;
+                rightRotate(node->parent_);
+                w = node->parent_->left_;
+            }
+
+            if (w->right_->color_ == BLACK && w->left_->color_ == BLACK) {
+                w->color_ = RED;
+                node = node->parent_;
+            } else {
+                if (w->left_->color_ == BLACK) {
+                    w->right_->color_ = BLACK;
+                    w->color_ = RED;
+                    leftRotate(w);
+                    w = node->parent_->left_;
+                }
+                w->color_ = node->parent_->color_;
+                node->parent_->color_ = BLACK;
+                w->left_->color_ = BLACK;
+                rightRotate(node->parent_);
+                node = root_;
+            }
+        }
+    }
+
+    node->color_ = BLACK;
+}
+
+#define INDNET(depth) do { \
+    int i = 0; \
+    for (; i < (depth) * 5; ++i) { \
+        std::cout << " "; \
+    } \
+} while(0)
+
+template <typename T>
+void
+RBTree<T>::printTree(int depth) const {
+    INDNET(depth);
+    std::cout << "tree has node " << node_count_ << "\n";
+    printTreeHelper(root_, depth);
+}
+
+template <typename T>
+void
+RBTree<T>::printTreeHelper(RBNode<T>* node, int depth) const {
+    INDNET(depth);
+    std::cout << node->name_.toText() << " ("
+              << ((node->color_ == BLACK) ? "black" : "red") << ")\n";
+    std::cout << ((node->isNonterminal()) ? "[non-terminal] \n" : "\n");
+    if (node->down_) {
+        assert(node->down_->up_ == node);
+        INDNET(depth + 1);
+        std::cout << "begin down from "<< node->name_.toText() << "\n";
+        node->down_->printTree(depth + 1);
+        INDNET(depth + 1);
+        std::cout << "end down from" << node->name_.toText() <<"\n";
+    }
+
+    if (node->left_ != NULLNODE) {
+        printTreeHelper(node->left_, depth + 1);
+    } else {
+        INDNET(depth + 1);
+        std::cout << "NULL\n";
+    }
+
+    if (node->right_ != NULLNODE) {
+        printTreeHelper(node->right_, depth + 1);
+    } else {
+        INDNET(depth + 1);
+        std::cout << "NULL\n";
+    }
+}
+
 }
 }