rbtree.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef _RBTREE_H
  15. #define _RBTREE_H 1
  16. //! \file datasrc/rbtree.h
  17. ///
  18. /// \note The purpose of the RBTree is to provide a generic map with
  19. /// domain names as the key that can be used by various BIND 10 modules or
  20. /// even by other applications. However, because of some unresolved design
  21. /// issue, the design and interface are not fixed, and RBTree isn't ready to
  22. /// be used as a base data structure by other modules.
  23. #include <dns/name.h>
  24. #include <boost/utility.hpp>
  25. #include <boost/shared_ptr.hpp>
  26. #include <exception>
  27. #include <ostream>
  28. #include <algorithm>
  29. namespace isc {
  30. namespace datasrc {
  31. namespace helper {
  32. /// Helper function to remove the base domain from super domain
  33. ///
  34. /// the precondition of this function is the super_name contains the
  35. /// sub_name so
  36. /// \code Name a("a.b.c");
  37. /// Name b("b.c");
  38. /// Name c = a - b;
  39. /// \endcode
  40. ///
  41. /// \note function in this namespace is not intended to be used outside.
  42. inline isc::dns::Name
  43. operator-(const isc::dns::Name& super_name, const isc::dns::Name& sub_name) {
  44. return (super_name.split(0, super_name.getLabelCount() -
  45. sub_name.getLabelCount()));
  46. }
  47. }
  48. template <typename T>
  49. class RBTree;
  50. /// \brief \c RBNode use by RBTree to store any data related to one domain name
  51. ///
  52. /// It has two roles, the first one is as one node in the \c RBTree,
  53. /// the second one is to store the data related to one domain name and maintain
  54. /// the domain name hierarchy struct in one domain name space.
  55. /// As for the first role, it has left, right, parent and color members
  56. /// which is used to keep the balance of the \c RBTree.
  57. /// As for the second role, \c RBNode use down pointer to refer to all its sub
  58. /// domains, so the name of current node always relative to the up node. since
  59. /// we only has down pointer without up pointer, so we can only walk down from
  60. /// top domain to sub domain.
  61. /// One special kind of node is non-terminal node
  62. /// which has subdomains with RRset but itself doesn't have any RRsets.
  63. ///
  64. /// \note \c RBNode basically used internally by RBTree, it is meaningless to
  65. /// inherited from it or create it without \c RBTree.
  66. template <typename T>
  67. class RBNode : public boost::noncopyable {
  68. public:
  69. /// only \c RBTree can create and destroy \c RBNode
  70. friend class RBTree<T>;
  71. typedef boost::shared_ptr<T> NodeDataPtr;
  72. /// \name Destructor
  73. /// \note it's seems a little strange that constructor is private
  74. /// but deconstructor left public, the reason is for some smart pointer
  75. /// like std::auto_ptr, they needs to delete RBNode in sometimes, but
  76. /// \code delete *pointer_to_node \endcode shouldn't be called directly
  77. //@{
  78. ~RBNode();
  79. //@}
  80. /// \name Test functions
  81. //@{
  82. /// \brief return the name of current node, it's relative to its top node
  83. ///
  84. /// To get the absolute name of one node, the node path from the top node
  85. /// to current node has to be recorded
  86. const isc::dns::Name& getName() const { return (name_); }
  87. /// \brief return the data store in this node
  88. /// \note, since the data is managed by RBNode, developer should not
  89. /// free the pointer
  90. NodeDataPtr& getData() { return (data_); }
  91. /// \brief return the data stored in this node, read-only version
  92. const NodeDataPtr& getData() const { return (data_); }
  93. /// \brief return whether the node has related data
  94. /// \note it's meaningless has empty \c RBNode in one RBTree, the only
  95. /// exception is for non-terminal node which has sub domain nodes who
  96. /// has data(rrset)
  97. bool isEmpty() const { return (data_.get() == NULL); }
  98. //@}
  99. /// \name Modify functions
  100. //@{
  101. /// \breif set the data stored in the node
  102. void setData(const NodeDataPtr& data) { data_ = data; }
  103. //@}
  104. /// \name Callback related methods
  105. ///
  106. /// See the description of \c RBTree<T>::find() about callbacks.
  107. ///
  108. /// These methods never throw an exception.
  109. //@{
  110. /// Return if callback is enabled at the node.
  111. ///
  112. /// This method never throws an exception.
  113. bool isCallbackEnabled() const { return (callback_required_); }
  114. /// Enable callback at the node.
  115. void enableCallback() { callback_required_ = true; }
  116. /// Disable callback at the node.
  117. void disableCallback() { callback_required_ = false; }
  118. //@}
  119. private:
  120. /// \brief Define rbnode color
  121. enum RBNodeColor {BLACK, RED};
  122. /// \name Constructors
  123. /// \note \c Single RBNode is meaningless without living inside one \c RBTree
  124. /// the creation and destroy of one \c RBNode is handle by host \c RBTree, so
  125. /// the constructors and destructor of \c RBNode is left private
  126. //@{
  127. /// \brief Default constructor.
  128. ///
  129. /// This constructor is provided specifically for generating a special
  130. /// "null" node, and is intended be used only internally.
  131. RBNode();
  132. /// \brief Constructor from the node name.
  133. ///
  134. /// \param name The domain name corresponding to the node.
  135. RBNode(const isc::dns::Name& name);
  136. //@}
  137. /// This is a factory class method of a special singleton null node.
  138. static RBNode<T>* NULL_NODE() {
  139. static RBNode<T> null_node;
  140. return (&null_node);
  141. }
  142. /// data to maintain the rbtree balance
  143. RBNode<T>* parent_;
  144. RBNode<T>* left_;
  145. RBNode<T>* right_;
  146. RBNodeColor color_;
  147. isc::dns::Name name_;
  148. NodeDataPtr data_;
  149. /// the down pointer points to the root node of sub domains of current
  150. /// domain
  151. /// \par Adding down pointer to \c RBNode is for two purpose:
  152. /// \li Accelerate the search process, with sub domain tree, it split the
  153. /// big flat tree into several hierarchy trees
  154. /// \li It save memory useage, so same label won't be saved several times
  155. RBNode<T>* down_;
  156. // If true, callback should be called at this node in search.
  157. // (This may have to become part of more general "attribute flags")
  158. bool callback_required_;
  159. };
  160. // typically each node should has a name associate with it
  161. // this construction is only used to create \c NULLNODE
  162. template <typename T>
  163. RBNode<T>::RBNode() :
  164. parent_(this),
  165. left_(this),
  166. right_(this),
  167. color_(BLACK),
  168. // dummy name, the value doesn't matter:
  169. name_(isc::dns::Name::ROOT_NAME()),
  170. down_(this),
  171. callback_required_(false)
  172. {
  173. }
  174. template <typename T>
  175. RBNode<T>::RBNode(const isc::dns::Name& name) :
  176. parent_(NULL_NODE()),
  177. left_(NULL_NODE()),
  178. right_(NULL_NODE()),
  179. color_(RED),
  180. name_(name),
  181. down_(NULL_NODE()),
  182. callback_required_(false)
  183. {
  184. }
  185. template <typename T>
  186. RBNode<T>::~RBNode() {
  187. }
  188. // note: the following class description is documented using C-style comments
  189. // because the verbatim diagram contain a backslash, which could be interpreted
  190. // as part of a multi-line comment with C++ style comments.
  191. /**
  192. * \brief \c RBTree class represents all the domains with the same suffix,
  193. * so it can be used to store the domains in one zone.
  194. *
  195. * \c RBTree is a generic red black tree, and contains all the nodes with
  196. * the same suffix, since each name may have sub domain names
  197. * so \c RBTree is a recursive data structure namely tree in tree.
  198. * So for one zone, several RBTrees may be involved. But from outside, the sub
  199. * tree is opaque for end users.
  200. *
  201. * \c RBTree split the domain space into hierarchy red black trees, nodes in one
  202. * tree has the same base name. The benefit of this struct is that:
  203. * - enhance the query performace compared with one big flat red black tree
  204. * - decrase the memory footprint to save common labels only once.
  205. *
  206. * \verbatim
  207. with the following names:
  208. a x.d.e.f o.w.y.d.e.f
  209. b z.d.e.f p.w.y.d.e.f
  210. c g.h q.w.y.d.e.f
  211. the tree will looks like:
  212. b
  213. / \
  214. a d.e.f
  215. /|\
  216. c | g.h
  217. |
  218. w.y
  219. /|\
  220. x | z
  221. |
  222. p
  223. / \
  224. o q
  225. * \endverbatim
  226. * \note open problems:
  227. * - current find funciton only return non-empty nodes, so there is no difference
  228. * between find one not exist name with empty non-terminal nodes, but in DNS query
  229. * logic, they are different
  230. * \todo
  231. * - add remove interface
  232. * - add iterator to iterate the whole rbtree while may needed by axfr
  233. * - since \c RBNode only has down pointer without up pointer, the node path during finding
  234. * should be recorded for later use
  235. */
  236. template <typename T>
  237. class RBTree : public boost::noncopyable {
  238. friend class RBNode<T>;
  239. public:
  240. /// \brief The return value for the \c find() insert() and erase() method
  241. enum Result {
  242. SUCCEED, //insert or erase succeed
  243. EXACTMATCH, //find the target name
  244. PARTIALMATCH, //find part of target name
  245. NOTFOUND, // for find function means no related name found
  246. // for erase function means erase not exist name
  247. ALREADYEXIST, //for insert operation, the name to insert already exist
  248. };
  249. /// \name Constructor and Destructor
  250. //@{
  251. explicit RBTree();
  252. /// \b Note: RBTree is not intended to be inherited so the destructor
  253. /// is not virtual
  254. ~RBTree();
  255. //@}
  256. /// \name Inquery methods
  257. //@{
  258. /// \brief Find the node that gives a longest match against the given name
  259. ///
  260. /// This method searches the \c RBTree for a node whose name is a longest
  261. /// match against \c name. The found node, if any, is returned via the
  262. /// \c node pointer.
  263. /// By default, nodes that don't have data will be ignored, and the result
  264. /// can be \c NOTFOUND even if there is a node whose name matches the
  265. /// given \c name.
  266. /// We'll soon introduce a "no data OK" mode in this method. It would
  267. /// match any node of the tree regardless of whether the node has data
  268. /// or not.
  269. /// Since the tree is "compressed", i.e., a node can contain multiple
  270. /// name labels, there are counter intuitive cases in the "no data OK"
  271. /// mode. For example, see the diagram of the class description.
  272. /// Name "y.d.e.f" is logically contained in the tree as part of the
  273. /// "compressed" node of "w.y". But the search logic of this method
  274. /// cannot find the logical match, and would return a \c PARTIALMATCH
  275. /// result pointing to node "d.e.f". To correctly identify the real
  276. /// longest match, "y.d.e.f" with empty data, the caller needs to
  277. /// perform additional steps.
  278. ///
  279. /// This version of \c find() method is templated to allow the caller
  280. /// to specify a "hook" at nodes that give a partial match.
  281. /// When the search encounters a node with data that partially matches
  282. /// \c name (i.e. node's name is a superdomain of \c name) and has
  283. /// enabled callback (via the \c RBNode::enableCallback() method), if
  284. /// \c callback is non \c NULL then the callback function is called
  285. /// with the argument of a reference to the node and the given
  286. /// callback argument (\c callback_arg). The template parameter specifies
  287. /// the type of the callback argument.
  288. /// The callback function returns either \c true or \c false, meaning
  289. /// the search should stop or continue, respectively.
  290. /// If the return value is \c true the search stops immediately at the
  291. /// node even if there could be a longer matching name below it.
  292. /// In reality, this convoluted callback rule is specifically intended
  293. /// to be used to handle a zone cut (delegation) at a name search inside
  294. /// a zone, and won't be used in any other cases.
  295. /// Other applications of the tree won't need callbacks, and they should
  296. /// use the non templated version of the \c find() method.
  297. ///
  298. /// Since the expected usage of callback is very limited, we do not
  299. /// generalize the interface so that it can be an arbitrary functions or
  300. /// functor objects in favor of simplicity and efficiency.
  301. ///
  302. /// This method involves operations on names that can throw an exception.
  303. /// If that happens the exception will be propagated to the caller.
  304. /// The callback function should generally not throw an exception, but
  305. /// if it throws, the exception will be propagated to the caller.
  306. ///
  307. /// \param name Target to be found
  308. /// \param node On success (either \c EXACTMATCH or \c PARTIALMATCH)
  309. /// it will store a pointer to the matching node
  310. /// \param callback If non \c NULL, a call back function to be called
  311. /// at "delegation" nodes (see above).
  312. /// \param callback_arg A caller supplied argument to be passed to
  313. /// \c callback.
  314. ///
  315. /// \return \c EXACTMATCH A node that whose name is equal to \c name is
  316. /// found. \c *node will be set to point to that node.
  317. /// \return \c PARTIALMATCH There is a no exact match, but a superdomain
  318. /// of \c name exists. \c node will be set to point to the node whose
  319. /// name is the longest among such superdomains.
  320. /// \return \c NOTFOUND There is no exact or partial match against \c name
  321. /// \c *node will be intact in this case.
  322. template <typename CBARG>
  323. Result find(const isc::dns::Name& name, RBNode<T>** node,
  324. bool (*callback)(const RBNode<T>&, CBARG),
  325. CBARG callback_arg) const;
  326. /// Same as the other version, but the returned \c node will be immutable.
  327. template <typename CBARG>
  328. Result find(const isc::dns::Name& name, const RBNode<T>** node,
  329. bool (*callback)(const RBNode<T>&, CBARG),
  330. CBARG callback_arg) const;
  331. /// Same as the templated version, but does not use callback.
  332. ///
  333. /// Applications except the zone implementation should generally use the
  334. /// non templated version.
  335. Result find(const isc::dns::Name& name, RBNode<T>** node) const {
  336. return (find<void*>(name, node, NULL, NULL));
  337. }
  338. /// Same as the templated version, but does not use callback, and the
  339. /// returned \c node will be immutable.
  340. ///
  341. /// In general, this version should be preferred over the other non
  342. /// templated version, unless the caller knows it should modify the
  343. /// returned node.
  344. Result find(const isc::dns::Name& name, const RBNode<T>** node) const {
  345. return (find<void*>(name, node, NULL, NULL));
  346. }
  347. /// \brief Get the total node count in the tree
  348. /// the node count including the node created common suffix node,
  349. /// this function will only be used for debuging
  350. int getNodeCount() const { return (node_count_);}
  351. //@}
  352. /// \name Debug function
  353. //@{
  354. /// \brief print the nodes in the trees
  355. void dumpTree(std::ostream& os, unsigned int depth = 0) const;
  356. //@}
  357. /// \name Modify function
  358. //@{
  359. /// \brief Insert the domain name into the tree
  360. /// \param name The name to be inserted into the tree
  361. /// \param inserted_node If no node with the name in the tree,
  362. /// new \c RBNode will be created, otherwise nothing will be done.
  363. /// Anyway the pointer point to the node with the name will be assigned to
  364. /// inserted_node
  365. /// \return
  366. // - SUCCEED means no node exists in the tree with the name before insert
  367. /// - ALREADYEXIST means already has the node with the given name
  368. //
  369. /// \node To modify the data related with one name but not sure the name has
  370. /// inserted or not, it is better to call \c insert,instead of
  371. /// \c find(), in case the name isn't exist and needs to insert again
  372. Result insert(const isc::dns::Name& name, RBNode<T>** inserted_node);
  373. //@}
  374. /// \brief Swaps two tree's contents.
  375. ///
  376. /// This acts the same as many std::*.swap functions, exchanges the
  377. /// contents. This doesn't throw anything.
  378. void swap(RBTree<T>& other) {
  379. std::swap(root_, other.root_);
  380. std::swap(NULLNODE, other.NULLNODE);
  381. std::swap(node_count_, other.node_count_);
  382. }
  383. private:
  384. /// \name RBTree balance functions
  385. //@{
  386. void insertRebalance(RBNode<T>** root, RBNode<T>* node);
  387. RBNode<T>* rightRotate(RBNode<T>** root, RBNode<T>* node);
  388. RBNode<T>* leftRotate(RBNode<T>** root, RBNode<T>* node);
  389. //@}
  390. /// \name Helper functions
  391. //@{
  392. /// \brief delete tree whose root is equal to node
  393. void deleteHelper(RBNode<T> *node);
  394. /// \brief find the node with name
  395. /// \param name is the target, up will points to the base domain of
  396. /// the tree which name resides, node will point to the target node
  397. /// if we has exact same name or partical name in current tree.
  398. /// so for example, in zone a, we has
  399. /// b.a, c.b.a and d.b.a search c.b.a, up will points to b.a.
  400. /// and node will points to c.b.a
  401. /// \note parameter up now is not used by any funciton, but we are gonna
  402. /// need it soon to implement function like remove
  403. template <typename CBARG>
  404. Result findHelper(const isc::dns::Name& name, const RBNode<T>** up,
  405. RBNode<T>** node,
  406. bool (*callback)(const RBNode<T>&, CBARG),
  407. CBARG callback_arg) const;
  408. void dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
  409. unsigned int depth) const;
  410. /// for indent purpose, add certian mount empty charachter to output stream
  411. /// according to the depth. This is a helper function which is only used when
  412. /// dump tree
  413. static void indent(std::ostream& os, unsigned int depth);
  414. /// Split one node into two nodes, keep the old node and create one new
  415. /// node, old node will hold the base name, new node will be the down node
  416. /// of old node, new node will hold the sub_name, the data
  417. /// of old node will be move into new node, and old node became non-terminal
  418. void nodeFission(RBNode<T>& node, const isc::dns::Name& sub_name);
  419. //@}
  420. RBNode<T>* root_;
  421. RBNode<T>* NULLNODE;
  422. /// the node count of current tree
  423. unsigned int node_count_;
  424. };
  425. template <typename T>
  426. RBTree<T>::RBTree() {
  427. NULLNODE = RBNode<T>::NULL_NODE();
  428. root_ = NULLNODE;
  429. node_count_ = 0;
  430. }
  431. template <typename T>
  432. RBTree<T>::~RBTree() {
  433. deleteHelper(root_);
  434. assert(node_count_ == 0);
  435. }
  436. template <typename T>
  437. void RBTree<T> ::deleteHelper(RBNode<T> *root) {
  438. if (root == NULLNODE) {
  439. return;
  440. }
  441. RBNode<T> *node = root;
  442. while (root->left_ != NULLNODE || root->right_ != NULLNODE) {
  443. while (node->left_ != NULLNODE || node->right_ != NULLNODE) {
  444. node = (node->left_ != NULLNODE) ? node->left_ : node->right_;
  445. }
  446. RBNode<T> *parent = node->parent_;
  447. if (parent->left_ == node) {
  448. parent->left_ = NULLNODE;
  449. } else {
  450. parent->right_ = NULLNODE;
  451. }
  452. deleteHelper(node->down_);
  453. delete node;
  454. --node_count_;
  455. node = parent;
  456. }
  457. deleteHelper(root->down_);
  458. delete root;
  459. --node_count_;
  460. }
  461. template <typename T> template <typename CBARG>
  462. typename RBTree<T>::Result
  463. RBTree<T>::find(const isc::dns::Name& name, RBNode<T>** node,
  464. bool (*callback)(const RBNode<T>&, CBARG),
  465. CBARG callback_arg) const
  466. {
  467. const RBNode<T>* up_node = NULLNODE;
  468. return (findHelper(name, &up_node, node, callback, callback_arg));
  469. }
  470. template <typename T> template <typename CBARG>
  471. typename RBTree<T>::Result
  472. RBTree<T>::find(const isc::dns::Name& name, const RBNode<T>** node,
  473. bool (*callback)(const RBNode<T>&, CBARG),
  474. CBARG callback_arg) const
  475. {
  476. const RBNode<T>* up_node;
  477. RBNode<T>* target_node;
  478. const typename RBTree<T>::Result ret =
  479. findHelper(name, &up_node, &target_node, callback, callback_arg);
  480. if (ret != NOTFOUND) {
  481. *node = target_node;
  482. }
  483. return (ret);
  484. }
  485. template <typename T> template <typename CBARG>
  486. typename RBTree<T>::Result
  487. RBTree<T>::findHelper(const isc::dns::Name& target_name,
  488. const RBNode<T>** up_node,
  489. RBNode<T>** target,
  490. bool (*callback)(const RBNode<T>&, CBARG),
  491. CBARG callback_arg) const
  492. {
  493. using namespace helper;
  494. RBNode<T>* node = root_;
  495. typename RBTree<T>::Result ret = NOTFOUND;
  496. *up_node = NULLNODE;
  497. isc::dns::Name name = target_name;
  498. while (node != NULLNODE) {
  499. const isc::dns::NameComparisonResult compare_result =
  500. name.compare(node->name_);
  501. const isc::dns::NameComparisonResult::NameRelation relation =
  502. compare_result.getRelation();
  503. if (relation == isc::dns::NameComparisonResult::EQUAL) {
  504. if (!node->isEmpty()) {
  505. *target = node;
  506. ret = EXACTMATCH;
  507. }
  508. break;
  509. } else {
  510. const int common_label_count = compare_result.getCommonLabels();
  511. // If the common label count is 1, there is no common label between
  512. // the two names, except the trailing "dot".
  513. if (common_label_count == 1) {
  514. node = (compare_result.getOrder() < 0) ?
  515. node->left_ : node->right_;
  516. } else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
  517. if (!node->isEmpty()) {
  518. ret = RBTree<T>::PARTIALMATCH;
  519. *target = node;
  520. if (callback != NULL && node->callback_required_) {
  521. if ((callback)(*node, callback_arg)) {
  522. break;
  523. }
  524. }
  525. }
  526. *up_node = node;
  527. name = name - node->name_;
  528. node = node->down_;
  529. } else {
  530. break;
  531. }
  532. }
  533. }
  534. return (ret);
  535. }
  536. template <typename T>
  537. typename RBTree<T>::Result
  538. RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
  539. using namespace helper;
  540. RBNode<T>* parent = NULLNODE;
  541. RBNode<T>* current = root_;
  542. RBNode<T>* up_node = NULLNODE;
  543. isc::dns::Name name = target_name;
  544. int order = -1;
  545. while (current != NULLNODE) {
  546. const isc::dns::NameComparisonResult compare_result =
  547. name.compare(current->name_);
  548. const isc::dns::NameComparisonResult::NameRelation relation =
  549. compare_result.getRelation();
  550. if (relation == isc::dns::NameComparisonResult::EQUAL) {
  551. if (new_node != NULL) {
  552. *new_node = current;
  553. }
  554. return (ALREADYEXIST);
  555. } else {
  556. const int common_label_count = compare_result.getCommonLabels();
  557. if (common_label_count == 1) {
  558. parent = current;
  559. order = compare_result.getOrder();
  560. current = order < 0 ? current->left_ : current->right_;
  561. } else {
  562. // insert sub domain to sub tree
  563. if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
  564. parent = NULLNODE;
  565. up_node = current;
  566. name = name - current->name_;
  567. current = current->down_;
  568. } else {
  569. // The number of labels in common is fewer
  570. // than the number of labels at the current
  571. // node, so the current node must be adjusted
  572. // to have just the common suffix, and a down
  573. // pointer made to a new tree.
  574. const isc::dns::Name common_ancestor = name.split(
  575. name.getLabelCount() - common_label_count,
  576. common_label_count);
  577. nodeFission(*current, common_ancestor);
  578. }
  579. }
  580. }
  581. }
  582. RBNode<T>** current_root = (up_node != NULLNODE) ?
  583. &(up_node->down_) : &root_;
  584. // using auto_ptr here is avoid memory leak in case of exceptoin raised
  585. // after the RBNode creation, if we can make sure no exception will be
  586. // raised until the end of the function, we can remove it for optimization
  587. std::auto_ptr<RBNode<T> > node(new RBNode<T>(name));
  588. node->parent_ = parent;
  589. if (parent == NULLNODE) {
  590. *current_root = node.get();
  591. //node is the new root of sub tree, so its init color
  592. // is BLACK
  593. node->color_ = RBNode<T>::BLACK;
  594. } else if (order < 0) {
  595. parent->left_ = node.get();
  596. } else {
  597. parent->right_ = node.get();
  598. }
  599. insertRebalance(current_root, node.get());
  600. if (new_node != NULL) {
  601. *new_node = node.get();
  602. }
  603. ++node_count_;
  604. node.release();
  605. return (SUCCEED);
  606. }
  607. template <typename T>
  608. void
  609. RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
  610. using namespace helper;
  611. const isc::dns::Name sub_name = node.name_ - base_name;
  612. // using auto_ptr here is to avoid memory leak in case of exceptoin raised
  613. // after the RBNode creation
  614. std::auto_ptr<RBNode<T> > down_node(new RBNode<T>(sub_name));
  615. std::swap(node.data_, down_node->data_);
  616. std::swap(node.callback_required_, down_node->callback_required_);
  617. down_node->down_ = node.down_;
  618. node.name_ = base_name;
  619. node.down_ = down_node.get();
  620. //root node of sub tree, the initial color is BLACK
  621. down_node->color_ = RBNode<T>::BLACK;
  622. ++node_count_;
  623. down_node.release();
  624. }
  625. template <typename T>
  626. void
  627. RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
  628. RBNode<T>* uncle;
  629. while (node != *root && node->parent_->color_ == RBNode<T>::RED) {
  630. if (node->parent_ == node->parent_->parent_->left_) {
  631. uncle = node->parent_->parent_->right_;
  632. if (uncle->color_ == RBNode<T>::RED) {
  633. node->parent_->color_ = RBNode<T>::BLACK;
  634. uncle->color_ = RBNode<T>::BLACK;
  635. node->parent_->parent_->color_ = RBNode<T>::RED;
  636. node = node->parent_->parent_;
  637. } else {
  638. if (node == node->parent_->right_) {
  639. node = node->parent_;
  640. leftRotate(root, node);
  641. }
  642. node->parent_->color_ = RBNode<T>::BLACK;
  643. node->parent_->parent_->color_ = RBNode<T>::RED;
  644. rightRotate(root, node->parent_->parent_);
  645. }
  646. } else {
  647. uncle = node->parent_->parent_->left_;
  648. if (uncle->color_ == RBNode<T>::RED) {
  649. node->parent_->color_ = RBNode<T>::BLACK;
  650. uncle->color_ = RBNode<T>::BLACK;
  651. node->parent_->parent_->color_ = RBNode<T>::RED;
  652. node = node->parent_->parent_;
  653. } else {
  654. if (node == node->parent_->left_) {
  655. node = node->parent_;
  656. rightRotate(root, node);
  657. }
  658. node->parent_->color_ = RBNode<T>::BLACK;
  659. node->parent_->parent_->color_ = RBNode<T>::RED;
  660. leftRotate(root, node->parent_->parent_);
  661. }
  662. }
  663. }
  664. (*root)->color_ = RBNode<T>::BLACK;
  665. }
  666. template <typename T>
  667. RBNode<T>*
  668. RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
  669. RBNode<T>* right = node->right_;
  670. node->right_ = right->left_;
  671. if (right->left_ != NULLNODE)
  672. right->left_->parent_ = node;
  673. right->parent_ = node->parent_;
  674. if (node->parent_ != NULLNODE) {
  675. if (node == node->parent_->left_) {
  676. node->parent_->left_ = right;
  677. } else {
  678. node->parent_->right_ = right;
  679. }
  680. } else {
  681. *root = right;
  682. }
  683. right->left_ = node;
  684. node->parent_ = right;
  685. return (node);
  686. }
  687. template <typename T>
  688. RBNode<T>*
  689. RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
  690. RBNode<T>* left = node->left_;
  691. node->left_ = left->right_;
  692. if (left->right_ != NULLNODE)
  693. left->right_->parent_ = node;
  694. left->parent_ = node->parent_;
  695. if (node->parent_ != NULLNODE) {
  696. if (node == node->parent_->right_) {
  697. node->parent_->right_ = left;
  698. } else {
  699. node->parent_->left_ = left;
  700. }
  701. } else {
  702. *root = left;
  703. }
  704. left->right_ = node;
  705. node->parent_ = left;
  706. return (node);
  707. }
  708. template <typename T>
  709. void
  710. RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const {
  711. indent(os, depth);
  712. os << "tree has " << node_count_ << " node(s)\n";
  713. dumpTreeHelper(os, root_, depth);
  714. }
  715. template <typename T>
  716. void
  717. RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
  718. unsigned int depth) const
  719. {
  720. if (node == NULLNODE) {
  721. indent(os, depth);
  722. os << "NULL\n";
  723. return;
  724. }
  725. indent(os, depth);
  726. os << node->name_.toText() << " ("
  727. << ((node->color_ == RBNode<T>::BLACK) ? "black" : "red") << ")";
  728. os << ((node->isEmpty()) ? "[invisible] \n" : "\n");
  729. if (node->down_ != NULLNODE) {
  730. indent(os, depth + 1);
  731. os << "begin down from " << node->name_.toText() << "\n";
  732. dumpTreeHelper(os, node->down_, depth + 1);
  733. indent(os, depth + 1);
  734. os << "end down from " << node->name_.toText() << "\n";
  735. }
  736. dumpTreeHelper(os, node->left_, depth + 1);
  737. dumpTreeHelper(os, node->right_, depth + 1);
  738. }
  739. template <typename T>
  740. void
  741. RBTree<T>::indent(std::ostream& os, unsigned int depth) {
  742. static const unsigned int INDENT_FOR_EACH_DEPTH = 5;
  743. os << std::string(depth * INDENT_FOR_EACH_DEPTH, ' ');
  744. }
  745. }
  746. }
  747. #endif // _RBTREE_H
  748. // Local Variables:
  749. // mode: c++
  750. // End: