123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- // 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 thant super_name contains 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() {
- if (down_)
- delete down_;
- }
- RBNode*
- RBNode::successor() {
- RBNode* current = this;
- if (right_ != right_->right_) {
- current = right_;
- while (current->left_ != current->left_->left_)
- current = current->left_;
- return (current);
- }
- RBNode* s = current->parent_;
- while (s != s->left_ && current == s->right_) {
- current = s;
- s = s->parent_;
- }
- return (s);
- }
- /// no duplication is checked now
- 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;
- }
- 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 doesn't 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
- //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);
- /// cann't 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);
- if ( y == root_)
- root_ = NULLNODE;
- 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";
- }
- }
- }
- }
|