PageRenderTime 57ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/bind9/lib/dns/rbt.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2674 lines | 1520 code | 455 blank | 699 comment | 530 complexity | 81ad892c3e11df5bfea01cab4e611246 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /*
  2. * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id$ */
  18. /*! \file */
  19. /* Principal Authors: DCL */
  20. #include <config.h>
  21. #include <isc/mem.h>
  22. #include <isc/platform.h>
  23. #include <isc/print.h>
  24. #include <isc/refcount.h>
  25. #include <isc/string.h>
  26. #include <isc/util.h>
  27. /*%
  28. * This define is so dns/name.h (included by dns/fixedname.h) uses more
  29. * efficient macro calls instead of functions for a few operations.
  30. */
  31. #define DNS_NAME_USEINLINE 1
  32. #include <dns/fixedname.h>
  33. #include <dns/log.h>
  34. #include <dns/rbt.h>
  35. #include <dns/result.h>
  36. #define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
  37. #define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
  38. /*
  39. * XXXDCL Since parent pointers were added in again, I could remove all of the
  40. * chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
  41. * _lastnode. This would involve pretty major change to the API.
  42. */
  43. #define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
  44. #define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
  45. #define RBT_HASH_SIZE 64
  46. #ifdef RBT_MEM_TEST
  47. #undef RBT_HASH_SIZE
  48. #define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
  49. #endif
  50. struct dns_rbt {
  51. unsigned int magic;
  52. isc_mem_t * mctx;
  53. dns_rbtnode_t * root;
  54. void (*data_deleter)(void *, void *);
  55. void * deleter_arg;
  56. unsigned int nodecount;
  57. unsigned int hashsize;
  58. dns_rbtnode_t ** hashtable;
  59. };
  60. #define RED 0
  61. #define BLACK 1
  62. /*%
  63. * Elements of the rbtnode structure.
  64. */
  65. #define PARENT(node) ((node)->parent)
  66. #define LEFT(node) ((node)->left)
  67. #define RIGHT(node) ((node)->right)
  68. #define DOWN(node) ((node)->down)
  69. #define DATA(node) ((node)->data)
  70. #define HASHNEXT(node) ((node)->hashnext)
  71. #define HASHVAL(node) ((node)->hashval)
  72. #define COLOR(node) ((node)->color)
  73. #define NAMELEN(node) ((node)->namelen)
  74. #define OLDNAMELEN(node) ((node)->oldnamelen)
  75. #define OFFSETLEN(node) ((node)->offsetlen)
  76. #define ATTRS(node) ((node)->attributes)
  77. #define IS_ROOT(node) ISC_TF((node)->is_root == 1)
  78. #define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
  79. /*%
  80. * Structure elements from the rbtdb.c, not
  81. * used as part of the rbt.c algorithms.
  82. */
  83. #define DIRTY(node) ((node)->dirty)
  84. #define WILD(node) ((node)->wild)
  85. #define LOCKNUM(node) ((node)->locknum)
  86. /*%
  87. * The variable length stuff stored after the node has the following
  88. * structure.
  89. *
  90. * <name_data>{1..255}<oldoffsetlen>{1}<offsets>{1..128}
  91. *
  92. * <name_data> contains the name of the node when it was created.
  93. * <oldoffsetlen> contains the length of <offsets> when the node was created.
  94. * <offsets> contains the offets into name for each label when the node was
  95. * created.
  96. */
  97. #define NAME(node) ((unsigned char *)((node) + 1))
  98. #define OFFSETS(node) (NAME(node) + OLDNAMELEN(node) + 1)
  99. #define OLDOFFSETLEN(node) (OFFSETS(node)[-1])
  100. #define NODE_SIZE(node) (sizeof(*node) + \
  101. OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1)
  102. /*%
  103. * Color management.
  104. */
  105. #define IS_RED(node) ((node) != NULL && (node)->color == RED)
  106. #define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
  107. #define MAKE_RED(node) ((node)->color = RED)
  108. #define MAKE_BLACK(node) ((node)->color = BLACK)
  109. /*%
  110. * Chain management.
  111. *
  112. * The "ancestors" member of chains were removed, with their job now
  113. * being wholly handled by parent pointers (which didn't exist, because
  114. * of memory concerns, when chains were first implemented).
  115. */
  116. #define ADD_LEVEL(chain, node) \
  117. (chain)->levels[(chain)->level_count++] = (node)
  118. /*%
  119. * The following macros directly access normally private name variables.
  120. * These macros are used to avoid a lot of function calls in the critical
  121. * path of the tree traversal code.
  122. */
  123. #define NODENAME(node, name) \
  124. do { \
  125. (name)->length = NAMELEN(node); \
  126. (name)->labels = OFFSETLEN(node); \
  127. (name)->ndata = NAME(node); \
  128. (name)->offsets = OFFSETS(node); \
  129. (name)->attributes = ATTRS(node); \
  130. (name)->attributes |= DNS_NAMEATTR_READONLY; \
  131. } while (0)
  132. #ifdef DNS_RBT_USEHASH
  133. static isc_result_t
  134. inithash(dns_rbt_t *rbt);
  135. #endif
  136. #ifdef DEBUG
  137. #define inline
  138. /*
  139. * A little something to help out in GDB.
  140. */
  141. dns_name_t Name(dns_rbtnode_t *node);
  142. dns_name_t
  143. Name(dns_rbtnode_t *node) {
  144. dns_name_t name;
  145. dns_name_init(&name, NULL);
  146. if (node != NULL)
  147. NODENAME(node, &name);
  148. return (name);
  149. }
  150. static void dns_rbt_printnodename(dns_rbtnode_t *node);
  151. #endif
  152. static inline dns_rbtnode_t *
  153. find_up(dns_rbtnode_t *node) {
  154. dns_rbtnode_t *root;
  155. /*
  156. * Return the node in the level above the argument node that points
  157. * to the level the argument node is in. If the argument node is in
  158. * the top level, the return value is NULL.
  159. */
  160. for (root = node; ! IS_ROOT(root); root = PARENT(root))
  161. ; /* Nothing. */
  162. return (PARENT(root));
  163. }
  164. /*
  165. * Forward declarations.
  166. */
  167. static isc_result_t
  168. create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
  169. #ifdef DNS_RBT_USEHASH
  170. static inline void
  171. hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
  172. static inline void
  173. unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
  174. #else
  175. #define hash_node(rbt, node, name) (ISC_R_SUCCESS)
  176. #define unhash_node(rbt, node)
  177. #endif
  178. static inline void
  179. rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
  180. static inline void
  181. rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
  182. static void
  183. dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
  184. dns_rbtnode_t **rootp);
  185. static void
  186. dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
  187. static isc_result_t
  188. dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
  189. static void
  190. dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
  191. dns_rbtnode_t **nodep);
  192. /*
  193. * Initialize a red/black tree of trees.
  194. */
  195. isc_result_t
  196. dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
  197. void *deleter_arg, dns_rbt_t **rbtp)
  198. {
  199. #ifdef DNS_RBT_USEHASH
  200. isc_result_t result;
  201. #endif
  202. dns_rbt_t *rbt;
  203. REQUIRE(mctx != NULL);
  204. REQUIRE(rbtp != NULL && *rbtp == NULL);
  205. REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
  206. rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
  207. if (rbt == NULL)
  208. return (ISC_R_NOMEMORY);
  209. rbt->mctx = mctx;
  210. rbt->data_deleter = deleter;
  211. rbt->deleter_arg = deleter_arg;
  212. rbt->root = NULL;
  213. rbt->nodecount = 0;
  214. rbt->hashtable = NULL;
  215. rbt->hashsize = 0;
  216. #ifdef DNS_RBT_USEHASH
  217. result = inithash(rbt);
  218. if (result != ISC_R_SUCCESS) {
  219. isc_mem_put(mctx, rbt, sizeof(*rbt));
  220. return (result);
  221. }
  222. #endif
  223. rbt->magic = RBT_MAGIC;
  224. *rbtp = rbt;
  225. return (ISC_R_SUCCESS);
  226. }
  227. /*
  228. * Deallocate a red/black tree of trees.
  229. */
  230. void
  231. dns_rbt_destroy(dns_rbt_t **rbtp) {
  232. RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
  233. }
  234. isc_result_t
  235. dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
  236. dns_rbt_t *rbt;
  237. REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
  238. rbt = *rbtp;
  239. dns_rbt_deletetreeflat(rbt, quantum, &rbt->root);
  240. if (rbt->root != NULL)
  241. return (ISC_R_QUOTA);
  242. INSIST(rbt->nodecount == 0);
  243. if (rbt->hashtable != NULL)
  244. isc_mem_put(rbt->mctx, rbt->hashtable,
  245. rbt->hashsize * sizeof(dns_rbtnode_t *));
  246. rbt->magic = 0;
  247. isc_mem_put(rbt->mctx, rbt, sizeof(*rbt));
  248. *rbtp = NULL;
  249. return (ISC_R_SUCCESS);
  250. }
  251. unsigned int
  252. dns_rbt_nodecount(dns_rbt_t *rbt) {
  253. REQUIRE(VALID_RBT(rbt));
  254. return (rbt->nodecount);
  255. }
  256. static inline isc_result_t
  257. chain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
  258. isc_boolean_t include_chain_end)
  259. {
  260. dns_name_t nodename;
  261. isc_result_t result = ISC_R_SUCCESS;
  262. int i;
  263. dns_name_init(&nodename, NULL);
  264. if (include_chain_end && chain->end != NULL) {
  265. NODENAME(chain->end, &nodename);
  266. result = dns_name_copy(&nodename, name, NULL);
  267. if (result != ISC_R_SUCCESS)
  268. return (result);
  269. } else
  270. dns_name_reset(name);
  271. for (i = (int)chain->level_count - 1; i >= 0; i--) {
  272. NODENAME(chain->levels[i], &nodename);
  273. result = dns_name_concatenate(name, &nodename, name, NULL);
  274. if (result != ISC_R_SUCCESS)
  275. return (result);
  276. }
  277. return (result);
  278. }
  279. static inline isc_result_t
  280. move_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
  281. do {
  282. /*
  283. * Go as far right and then down as much as possible,
  284. * as long as the rightmost node has a down pointer.
  285. */
  286. while (RIGHT(node) != NULL)
  287. node = RIGHT(node);
  288. if (DOWN(node) == NULL)
  289. break;
  290. ADD_LEVEL(chain, node);
  291. node = DOWN(node);
  292. } while (1);
  293. chain->end = node;
  294. return (ISC_R_SUCCESS);
  295. }
  296. /*
  297. * Add 'name' to tree, initializing its data pointer with 'data'.
  298. */
  299. isc_result_t
  300. dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
  301. /*
  302. * Does this thing have too many variables or what?
  303. */
  304. dns_rbtnode_t **root, *parent, *child, *current, *new_current;
  305. dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
  306. dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
  307. dns_offsets_t current_offsets;
  308. dns_namereln_t compared;
  309. isc_result_t result = ISC_R_SUCCESS;
  310. dns_rbtnodechain_t chain;
  311. unsigned int common_labels;
  312. unsigned int nlabels, hlabels;
  313. int order;
  314. REQUIRE(VALID_RBT(rbt));
  315. REQUIRE(dns_name_isabsolute(name));
  316. REQUIRE(nodep != NULL && *nodep == NULL);
  317. /*
  318. * Create a copy of the name so the original name structure is
  319. * not modified.
  320. */
  321. dns_fixedname_init(&fixedcopy);
  322. add_name = dns_fixedname_name(&fixedcopy);
  323. dns_name_clone(name, add_name);
  324. if (rbt->root == NULL) {
  325. result = create_node(rbt->mctx, add_name, &new_current);
  326. if (result == ISC_R_SUCCESS) {
  327. rbt->nodecount++;
  328. new_current->is_root = 1;
  329. rbt->root = new_current;
  330. *nodep = new_current;
  331. hash_node(rbt, new_current, name);
  332. }
  333. return (result);
  334. }
  335. dns_rbtnodechain_init(&chain, rbt->mctx);
  336. dns_fixedname_init(&fixedprefix);
  337. dns_fixedname_init(&fixedsuffix);
  338. prefix = dns_fixedname_name(&fixedprefix);
  339. suffix = dns_fixedname_name(&fixedsuffix);
  340. root = &rbt->root;
  341. INSIST(IS_ROOT(*root));
  342. parent = NULL;
  343. current = NULL;
  344. child = *root;
  345. dns_name_init(&current_name, current_offsets);
  346. dns_fixedname_init(&fnewname);
  347. new_name = dns_fixedname_name(&fnewname);
  348. nlabels = dns_name_countlabels(name);
  349. hlabels = 0;
  350. do {
  351. current = child;
  352. NODENAME(current, &current_name);
  353. compared = dns_name_fullcompare(add_name, &current_name,
  354. &order, &common_labels);
  355. if (compared == dns_namereln_equal) {
  356. *nodep = current;
  357. result = ISC_R_EXISTS;
  358. break;
  359. }
  360. if (compared == dns_namereln_none) {
  361. if (order < 0) {
  362. parent = current;
  363. child = LEFT(current);
  364. } else if (order > 0) {
  365. parent = current;
  366. child = RIGHT(current);
  367. }
  368. } else {
  369. /*
  370. * This name has some suffix in common with the
  371. * name at the current node. If the name at
  372. * the current node is shorter, that means the
  373. * new name should be in a subtree. If the
  374. * name at the current node is longer, that means
  375. * the down pointer to this tree should point
  376. * to a new tree that has the common suffix, and
  377. * the non-common parts of these two names should
  378. * start a new tree.
  379. */
  380. hlabels += common_labels;
  381. if (compared == dns_namereln_subdomain) {
  382. /*
  383. * All of the existing labels are in common,
  384. * so the new name is in a subtree.
  385. * Whack off the common labels for the
  386. * not-in-common part to be searched for
  387. * in the next level.
  388. */
  389. dns_name_split(add_name, common_labels,
  390. add_name, NULL);
  391. /*
  392. * Follow the down pointer (possibly NULL).
  393. */
  394. root = &DOWN(current);
  395. INSIST(*root == NULL ||
  396. (IS_ROOT(*root) &&
  397. PARENT(*root) == current));
  398. parent = NULL;
  399. child = DOWN(current);
  400. ADD_LEVEL(&chain, current);
  401. } else {
  402. /*
  403. * The number of labels in common is fewer
  404. * than the number of labels at the current
  405. * node, so the current node must be adjusted
  406. * to have just the common suffix, and a down
  407. * pointer made to a new tree.
  408. */
  409. INSIST(compared == dns_namereln_commonancestor
  410. || compared == dns_namereln_contains);
  411. /*
  412. * Ensure the number of levels in the tree
  413. * does not exceed the number of logical
  414. * levels allowed by DNSSEC.
  415. *
  416. * XXXDCL need a better error result?
  417. *
  418. * XXXDCL Since chain ancestors were removed,
  419. * no longer used by dns_rbt_addonlevel(),
  420. * this is the only real use of chains in the
  421. * function. It could be done instead with
  422. * a simple integer variable, but I am pressed
  423. * for time.
  424. */
  425. if (chain.level_count ==
  426. (sizeof(chain.levels) /
  427. sizeof(*chain.levels))) {
  428. result = ISC_R_NOSPACE;
  429. break;
  430. }
  431. /*
  432. * Split the name into two parts, a prefix
  433. * which is the not-in-common parts of the
  434. * two names and a suffix that is the common
  435. * parts of them.
  436. */
  437. dns_name_split(&current_name, common_labels,
  438. prefix, suffix);
  439. result = create_node(rbt->mctx, suffix,
  440. &new_current);
  441. if (result != ISC_R_SUCCESS)
  442. break;
  443. /*
  444. * Reproduce the tree attributes of the
  445. * current node.
  446. */
  447. new_current->is_root = current->is_root;
  448. if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
  449. new_current->nsec = DNS_RBT_NSEC_NORMAL;
  450. else
  451. new_current->nsec = current->nsec;
  452. PARENT(new_current) = PARENT(current);
  453. LEFT(new_current) = LEFT(current);
  454. RIGHT(new_current) = RIGHT(current);
  455. COLOR(new_current) = COLOR(current);
  456. /*
  457. * Fix pointers that were to the current node.
  458. */
  459. if (parent != NULL) {
  460. if (LEFT(parent) == current)
  461. LEFT(parent) = new_current;
  462. else
  463. RIGHT(parent) = new_current;
  464. }
  465. if (LEFT(new_current) != NULL)
  466. PARENT(LEFT(new_current)) =
  467. new_current;
  468. if (RIGHT(new_current) != NULL)
  469. PARENT(RIGHT(new_current)) =
  470. new_current;
  471. if (*root == current)
  472. *root = new_current;
  473. NAMELEN(current) = prefix->length;
  474. OFFSETLEN(current) = prefix->labels;
  475. /*
  476. * Set up the new root of the next level.
  477. * By definition it will not be the top
  478. * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
  479. */
  480. current->is_root = 1;
  481. PARENT(current) = new_current;
  482. DOWN(new_current) = current;
  483. root = &DOWN(new_current);
  484. ADD_LEVEL(&chain, new_current);
  485. LEFT(current) = NULL;
  486. RIGHT(current) = NULL;
  487. MAKE_BLACK(current);
  488. ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
  489. rbt->nodecount++;
  490. dns_name_getlabelsequence(name,
  491. nlabels - hlabels,
  492. hlabels, new_name);
  493. hash_node(rbt, new_current, new_name);
  494. if (common_labels ==
  495. dns_name_countlabels(add_name)) {
  496. /*
  497. * The name has been added by pushing
  498. * the not-in-common parts down to
  499. * a new level.
  500. */
  501. *nodep = new_current;
  502. return (ISC_R_SUCCESS);
  503. } else {
  504. /*
  505. * The current node has no data,
  506. * because it is just a placeholder.
  507. * Its data pointer is already NULL
  508. * from create_node()), so there's
  509. * nothing more to do to it.
  510. */
  511. /*
  512. * The not-in-common parts of the new
  513. * name will be inserted into the new
  514. * level following this loop (unless
  515. * result != ISC_R_SUCCESS, which
  516. * is tested after the loop ends).
  517. */
  518. dns_name_split(add_name, common_labels,
  519. add_name, NULL);
  520. break;
  521. }
  522. }
  523. }
  524. } while (child != NULL);
  525. if (result == ISC_R_SUCCESS)
  526. result = create_node(rbt->mctx, add_name, &new_current);
  527. if (result == ISC_R_SUCCESS) {
  528. dns_rbt_addonlevel(new_current, current, order, root);
  529. rbt->nodecount++;
  530. *nodep = new_current;
  531. hash_node(rbt, new_current, name);
  532. }
  533. return (result);
  534. }
  535. /*
  536. * Add a name to the tree of trees, associating it with some data.
  537. */
  538. isc_result_t
  539. dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
  540. isc_result_t result;
  541. dns_rbtnode_t *node;
  542. REQUIRE(VALID_RBT(rbt));
  543. REQUIRE(dns_name_isabsolute(name));
  544. node = NULL;
  545. result = dns_rbt_addnode(rbt, name, &node);
  546. /*
  547. * dns_rbt_addnode will report the node exists even when
  548. * it does not have data associated with it, but the
  549. * dns_rbt_*name functions all behave depending on whether
  550. * there is data associated with a node.
  551. */
  552. if (result == ISC_R_SUCCESS ||
  553. (result == ISC_R_EXISTS && DATA(node) == NULL)) {
  554. DATA(node) = data;
  555. result = ISC_R_SUCCESS;
  556. }
  557. return (result);
  558. }
  559. /*
  560. * Find the node for "name" in the tree of trees.
  561. */
  562. isc_result_t
  563. dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
  564. dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
  565. unsigned int options, dns_rbtfindcallback_t callback,
  566. void *callback_arg)
  567. {
  568. dns_rbtnode_t *current, *last_compared, *current_root;
  569. dns_rbtnodechain_t localchain;
  570. dns_name_t *search_name, current_name, *callback_name;
  571. dns_fixedname_t fixedcallbackname, fixedsearchname;
  572. dns_namereln_t compared;
  573. isc_result_t result, saved_result;
  574. unsigned int common_labels;
  575. unsigned int hlabels = 0;
  576. int order;
  577. REQUIRE(VALID_RBT(rbt));
  578. REQUIRE(dns_name_isabsolute(name));
  579. REQUIRE(node != NULL && *node == NULL);
  580. REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
  581. != (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
  582. /*
  583. * If there is a chain it needs to appear to be in a sane state,
  584. * otherwise a chain is still needed to generate foundname and
  585. * callback_name.
  586. */
  587. if (chain == NULL) {
  588. options |= DNS_RBTFIND_NOPREDECESSOR;
  589. chain = &localchain;
  590. dns_rbtnodechain_init(chain, rbt->mctx);
  591. } else
  592. dns_rbtnodechain_reset(chain);
  593. if (rbt->root == NULL)
  594. return (ISC_R_NOTFOUND);
  595. else {
  596. /*
  597. * Appease GCC about variables it incorrectly thinks are
  598. * possibly used uninitialized.
  599. */
  600. compared = dns_namereln_none;
  601. last_compared = NULL;
  602. order = 0;
  603. }
  604. dns_fixedname_init(&fixedcallbackname);
  605. callback_name = dns_fixedname_name(&fixedcallbackname);
  606. /*
  607. * search_name is the name segment being sought in each tree level.
  608. * By using a fixedname, the search_name will definitely have offsets
  609. * for use by any splitting.
  610. * By using dns_name_clone, no name data should be copied thanks to
  611. * the lack of bitstring labels.
  612. */
  613. dns_fixedname_init(&fixedsearchname);
  614. search_name = dns_fixedname_name(&fixedsearchname);
  615. dns_name_clone(name, search_name);
  616. dns_name_init(&current_name, NULL);
  617. saved_result = ISC_R_SUCCESS;
  618. current = rbt->root;
  619. current_root = rbt->root;
  620. while (current != NULL) {
  621. NODENAME(current, &current_name);
  622. compared = dns_name_fullcompare(search_name, &current_name,
  623. &order, &common_labels);
  624. last_compared = current;
  625. if (compared == dns_namereln_equal)
  626. break;
  627. if (compared == dns_namereln_none) {
  628. #ifdef DNS_RBT_USEHASH
  629. dns_name_t hash_name;
  630. dns_rbtnode_t *hnode;
  631. dns_rbtnode_t *up_current;
  632. unsigned int nlabels;
  633. unsigned int tlabels = 1;
  634. unsigned int hash;
  635. /*
  636. * If there is no hash table, hashing can't be done.
  637. */
  638. if (rbt->hashtable == NULL)
  639. goto nohash;
  640. /*
  641. * The case of current != current_root, that
  642. * means a left or right pointer was followed,
  643. * only happens when the algorithm fell through to
  644. * the traditional binary search because of a
  645. * bitstring label. Since we dropped the bitstring
  646. * support, this should not happen.
  647. */
  648. INSIST(current == current_root);
  649. nlabels = dns_name_countlabels(search_name);
  650. /*
  651. * current_root is the root of the current level, so
  652. * it's parent is the same as it's "up" pointer.
  653. */
  654. up_current = PARENT(current_root);
  655. dns_name_init(&hash_name, NULL);
  656. hashagain:
  657. /*
  658. * Hash includes tail.
  659. */
  660. dns_name_getlabelsequence(name,
  661. nlabels - tlabels,
  662. hlabels + tlabels,
  663. &hash_name);
  664. hash = dns_name_fullhash(&hash_name, ISC_FALSE);
  665. dns_name_getlabelsequence(search_name,
  666. nlabels - tlabels,
  667. tlabels, &hash_name);
  668. for (hnode = rbt->hashtable[hash % rbt->hashsize];
  669. hnode != NULL;
  670. hnode = hnode->hashnext)
  671. {
  672. dns_name_t hnode_name;
  673. if (hash != HASHVAL(hnode))
  674. continue;
  675. if (find_up(hnode) != up_current)
  676. continue;
  677. dns_name_init(&hnode_name, NULL);
  678. NODENAME(hnode, &hnode_name);
  679. if (dns_name_equal(&hnode_name, &hash_name))
  680. break;
  681. }
  682. if (hnode != NULL) {
  683. current = hnode;
  684. /*
  685. * This is an optimization. If hashing found
  686. * the right node, the next call to
  687. * dns_name_fullcompare() would obviously
  688. * return _equal or _subdomain. Determine
  689. * which of those would be the case by
  690. * checking if the full name was hashed. Then
  691. * make it look like dns_name_fullcompare
  692. * was called and jump to the right place.
  693. */
  694. if (tlabels == nlabels) {
  695. compared = dns_namereln_equal;
  696. break;
  697. } else {
  698. common_labels = tlabels;
  699. compared = dns_namereln_subdomain;
  700. goto subdomain;
  701. }
  702. }
  703. if (tlabels++ < nlabels)
  704. goto hashagain;
  705. /*
  706. * All of the labels have been tried against the hash
  707. * table. Since we dropped the support of bitstring
  708. * labels, the name isn't in the table.
  709. */
  710. current = NULL;
  711. continue;
  712. nohash:
  713. #endif /* DNS_RBT_USEHASH */
  714. /*
  715. * Standard binary search tree movement.
  716. */
  717. if (order < 0)
  718. current = LEFT(current);
  719. else
  720. current = RIGHT(current);
  721. } else {
  722. /*
  723. * The names have some common suffix labels.
  724. *
  725. * If the number in common are equal in length to
  726. * the current node's name length, then follow the
  727. * down pointer and search in the new tree.
  728. */
  729. if (compared == dns_namereln_subdomain) {
  730. subdomain:
  731. /*
  732. * Whack off the current node's common parts
  733. * for the name to search in the next level.
  734. */
  735. dns_name_split(search_name, common_labels,
  736. search_name, NULL);
  737. hlabels += common_labels;
  738. /*
  739. * This might be the closest enclosing name.
  740. */
  741. if (DATA(current) != NULL ||
  742. (options & DNS_RBTFIND_EMPTYDATA) != 0)
  743. *node = current;
  744. /*
  745. * Point the chain to the next level. This
  746. * needs to be done before 'current' is pointed
  747. * there because the callback in the next
  748. * block of code needs the current 'current',
  749. * but in the event the callback requests that
  750. * the search be stopped then the
  751. * DNS_R_PARTIALMATCH code at the end of this
  752. * function needs the chain pointed to the
  753. * next level.
  754. */
  755. ADD_LEVEL(chain, current);
  756. /*
  757. * The caller may want to interrupt the
  758. * downward search when certain special nodes
  759. * are traversed. If this is a special node,
  760. * the callback is used to learn what the
  761. * caller wants to do.
  762. */
  763. if (callback != NULL &&
  764. FINDCALLBACK(current)) {
  765. result = chain_name(chain,
  766. callback_name,
  767. ISC_FALSE);
  768. if (result != ISC_R_SUCCESS) {
  769. dns_rbtnodechain_reset(chain);
  770. return (result);
  771. }
  772. result = (callback)(current,
  773. callback_name,
  774. callback_arg);
  775. if (result != DNS_R_CONTINUE) {
  776. saved_result = result;
  777. /*
  778. * Treat this node as if it
  779. * had no down pointer.
  780. */
  781. current = NULL;
  782. break;
  783. }
  784. }
  785. /*
  786. * Finally, head to the next tree level.
  787. */
  788. current = DOWN(current);
  789. current_root = current;
  790. } else {
  791. /*
  792. * Though there are labels in common, the
  793. * entire name at this node is not common
  794. * with the search name so the search
  795. * name does not exist in the tree.
  796. */
  797. INSIST(compared == dns_namereln_commonancestor
  798. || compared == dns_namereln_contains);
  799. current = NULL;
  800. }
  801. }
  802. }
  803. /*
  804. * If current is not NULL, NOEXACT is not disallowing exact matches,
  805. * and either the node has data or an empty node is ok, return
  806. * ISC_R_SUCCESS to indicate an exact match.
  807. */
  808. if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
  809. (DATA(current) != NULL ||
  810. (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
  811. /*
  812. * Found an exact match.
  813. */
  814. chain->end = current;
  815. chain->level_matches = chain->level_count;
  816. if (foundname != NULL)
  817. result = chain_name(chain, foundname, ISC_TRUE);
  818. else
  819. result = ISC_R_SUCCESS;
  820. if (result == ISC_R_SUCCESS) {
  821. *node = current;
  822. result = saved_result;
  823. } else
  824. *node = NULL;
  825. } else {
  826. /*
  827. * Did not find an exact match (or did not want one).
  828. */
  829. if (*node != NULL) {
  830. /*
  831. * ... but found a partially matching superdomain.
  832. * Unwind the chain to the partial match node
  833. * to set level_matches to the level above the node,
  834. * and then to derive the name.
  835. *
  836. * chain->level_count is guaranteed to be at least 1
  837. * here because by definition of finding a superdomain,
  838. * the chain is pointed to at least the first subtree.
  839. */
  840. chain->level_matches = chain->level_count - 1;
  841. while (chain->levels[chain->level_matches] != *node) {
  842. INSIST(chain->level_matches > 0);
  843. chain->level_matches--;
  844. }
  845. if (foundname != NULL) {
  846. unsigned int saved_count = chain->level_count;
  847. chain->level_count = chain->level_matches + 1;
  848. result = chain_name(chain, foundname,
  849. ISC_FALSE);
  850. chain->level_count = saved_count;
  851. } else
  852. result = ISC_R_SUCCESS;
  853. if (result == ISC_R_SUCCESS)
  854. result = DNS_R_PARTIALMATCH;
  855. } else
  856. result = ISC_R_NOTFOUND;
  857. if (current != NULL) {
  858. /*
  859. * There was an exact match but either
  860. * DNS_RBTFIND_NOEXACT was set, or
  861. * DNS_RBTFIND_EMPTYDATA was set and the node had no
  862. * data. A policy decision was made to set the
  863. * chain to the exact match, but this is subject
  864. * to change if it becomes apparent that something
  865. * else would be more useful. It is important that
  866. * this case is handled here, because the predecessor
  867. * setting code below assumes the match was not exact.
  868. */
  869. INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
  870. ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
  871. DATA(current) == NULL));
  872. chain->end = current;
  873. } else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
  874. /*
  875. * Ensure the chain points nowhere.
  876. */
  877. chain->end = NULL;
  878. } else {
  879. /*
  880. * Since there was no exact match, the chain argument
  881. * needs to be pointed at the DNSSEC predecessor of
  882. * the search name.
  883. */
  884. if (compared == dns_namereln_subdomain) {
  885. /*
  886. * Attempted to follow a down pointer that was
  887. * NULL, which means the searched for name was
  888. * a subdomain of a terminal name in the tree.
  889. * Since there are no existing subdomains to
  890. * order against, the terminal name is the
  891. * predecessor.
  892. */
  893. INSIST(chain->level_count > 0);
  894. INSIST(chain->level_matches <
  895. chain->level_count);
  896. chain->end =
  897. chain->levels[--chain->level_count];
  898. } else {
  899. isc_result_t result2;
  900. /*
  901. * Point current to the node that stopped
  902. * the search.
  903. *
  904. * With the hashing modification that has been
  905. * added to the algorithm, the stop node of a
  906. * standard binary search is not known. So it
  907. * has to be found. There is probably a more
  908. * clever way of doing this.
  909. *
  910. * The assignment of current to NULL when
  911. * the relationship is *not* dns_namereln_none,
  912. * even though it later gets set to the same
  913. * last_compared anyway, is simply to not push
  914. * the while loop in one more level of
  915. * indentation.
  916. */
  917. if (compared == dns_namereln_none)
  918. current = last_compared;
  919. else
  920. current = NULL;
  921. while (current != NULL) {
  922. NODENAME(current, &current_name);
  923. compared = dns_name_fullcompare(
  924. search_name,
  925. &current_name,
  926. &order,
  927. &common_labels);
  928. POST(compared);
  929. last_compared = current;
  930. /*
  931. * Standard binary search movement.
  932. */
  933. if (order < 0)
  934. current = LEFT(current);
  935. else
  936. current = RIGHT(current);
  937. }
  938. current = last_compared;
  939. /*
  940. * Reached a point within a level tree that
  941. * positively indicates the name is not
  942. * present, but the stop node could be either
  943. * less than the desired name (order > 0) or
  944. * greater than the desired name (order < 0).
  945. *
  946. * If the stop node is less, it is not
  947. * necessarily the predecessor. If the stop
  948. * node has a down pointer, then the real
  949. * predecessor is at the end of a level below
  950. * (not necessarily the next level).
  951. * Move down levels until the rightmost node
  952. * does not have a down pointer.
  953. *
  954. * When the stop node is greater, it is
  955. * the successor. All the logic for finding
  956. * the predecessor is handily encapsulated
  957. * in dns_rbtnodechain_prev. In the event
  958. * that the search name is less than anything
  959. * else in the tree, the chain is reset.
  960. * XXX DCL What is the best way for the caller
  961. * to know that the search name has
  962. * no predecessor?
  963. */
  964. if (order > 0) {
  965. if (DOWN(current) != NULL) {
  966. ADD_LEVEL(chain, current);
  967. result2 =
  968. move_chain_to_last(chain,
  969. DOWN(current));
  970. if (result2 != ISC_R_SUCCESS)
  971. result = result2;
  972. } else
  973. /*
  974. * Ah, the pure and simple
  975. * case. The stop node is the
  976. * predecessor.
  977. */
  978. chain->end = current;
  979. } else {
  980. INSIST(order < 0);
  981. chain->end = current;
  982. result2 = dns_rbtnodechain_prev(chain,
  983. NULL,
  984. NULL);
  985. if (result2 == ISC_R_SUCCESS ||
  986. result2 == DNS_R_NEWORIGIN)
  987. ; /* Nothing. */
  988. else if (result2 == ISC_R_NOMORE)
  989. /*
  990. * There is no predecessor.
  991. */
  992. dns_rbtnodechain_reset(chain);
  993. else
  994. result = result2;
  995. }
  996. }
  997. }
  998. }
  999. ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
  1000. return (result);
  1001. }
  1002. /*
  1003. * Get the data pointer associated with 'name'.
  1004. */
  1005. isc_result_t
  1006. dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
  1007. dns_name_t *foundname, void **data) {
  1008. dns_rbtnode_t *node = NULL;
  1009. isc_result_t result;
  1010. REQUIRE(data != NULL && *data == NULL);
  1011. result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
  1012. options, NULL, NULL);
  1013. if (node != NULL &&
  1014. (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
  1015. *data = DATA(node);
  1016. else
  1017. result = ISC_R_NOTFOUND;
  1018. return (result);
  1019. }
  1020. /*
  1021. * Delete a name from the tree of trees.
  1022. */
  1023. isc_result_t
  1024. dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
  1025. dns_rbtnode_t *node = NULL;
  1026. isc_result_t result;
  1027. REQUIRE(VALID_RBT(rbt));
  1028. REQUIRE(dns_name_isabsolute(name));
  1029. /*
  1030. * First, find the node.
  1031. *
  1032. * When searching, the name might not have an exact match:
  1033. * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
  1034. * elements of a tree, which would make layer 1 a single
  1035. * node tree of "b.a.com" and layer 2 a three node tree of
  1036. * a, b, and c. Deleting a.com would find only a partial depth
  1037. * match in the first layer. Should it be a requirement that
  1038. * that the name to be deleted have data? For now, it is.
  1039. *
  1040. * ->dirty, ->locknum and ->references are ignored; they are
  1041. * solely the province of rbtdb.c.
  1042. */
  1043. result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
  1044. DNS_RBTFIND_NOOPTIONS, NULL, NULL);
  1045. if (result == ISC_R_SUCCESS) {
  1046. if (DATA(node) != NULL)
  1047. result = dns_rbt_deletenode(rbt, node, recurse);
  1048. else
  1049. result = ISC_R_NOTFOUND;
  1050. } else if (result == DNS_R_PARTIALMATCH)
  1051. result = ISC_R_NOTFOUND;
  1052. return (result);
  1053. }
  1054. /*
  1055. * Remove a node from the tree of trees.
  1056. *
  1057. * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
  1058. * a sequence of additions to be deletions will not generally get the
  1059. * tree back to the state it started in. For example, if the addition
  1060. * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
  1061. * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
  1062. * restoring "a.b.c". The RBT *used* to do this kind of rejoining, but it
  1063. * turned out to be a bad idea because it could corrupt an active nodechain
  1064. * that had "b.c" as one of its levels -- and the RBT has no idea what
  1065. * nodechains are in use by callers, so it can't even *try* to helpfully
  1066. * fix them up (which would probably be doomed to failure anyway).
  1067. *
  1068. * Similarly, it is possible to leave the tree in a state where a supposedly
  1069. * deleted node still exists. The first case of this is obvious; take
  1070. * the tree which has "b.c" on one level, pointing to "a". Now deleted "b.c".
  1071. * It was just established in the previous paragraph why we can't pull "a"
  1072. * back up to its parent level. But what happens when "a" then gets deleted?
  1073. * "b.c" is left hanging around without data or children. This condition
  1074. * is actually pretty easy to detect, but ... should it really be removed?
  1075. * Is a chain pointing to it? An iterator? Who knows! (Note that the
  1076. * references structure member cannot be looked at because it is private to
  1077. * rbtdb.) This is ugly and makes me unhappy, but after hours of trying to
  1078. * make it more aesthetically proper and getting nowhere, this is the way it
  1079. * is going to stay until such time as it proves to be a *real* problem.
  1080. *
  1081. * Finally, for reference, note that the original routine that did node
  1082. * joining was called join_nodes(). It has been excised, living now only
  1083. * in the CVS history, but comments have been left behind that point to it just
  1084. * in case someone wants to muck with this some more.
  1085. *
  1086. * The one positive aspect of all of this is that joining used to have a
  1087. * case where it might fail. Without trying to join, now this function always
  1088. * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
  1089. */
  1090. isc_result_t
  1091. dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
  1092. {
  1093. dns_rbtnode_t *parent;
  1094. REQUIRE(VALID_RBT(rbt));
  1095. REQUIRE(DNS_RBTNODE_VALID(node));
  1096. if (DOWN(node) != NULL) {
  1097. if (recurse)
  1098. RUNTIME_CHECK(dns_rbt_deletetree(rbt, DOWN(node))
  1099. == ISC_R_SUCCESS);
  1100. else {
  1101. if (DATA(node) != NULL && rbt->data_deleter != NULL)
  1102. rbt->data_deleter(DATA(node), rbt->deleter_arg);
  1103. DATA(node) = NULL;
  1104. /*
  1105. * Since there is at least one node below this one and
  1106. * no recursion was requested, the deletion is
  1107. * complete. The down node from this node might be all
  1108. * by itself on a single level, so join_nodes() could
  1109. * be used to collapse the tree (with all the caveats
  1110. * of the comment at the start of this function).
  1111. */
  1112. return (ISC_R_SUCCESS);
  1113. }
  1114. }
  1115. /*
  1116. * Note the node that points to the level of the node that is being
  1117. * deleted. If the deleted node is the top level, parent will be set
  1118. * to NULL.
  1119. */
  1120. parent = find_up(node);
  1121. /*
  1122. * This node now has no down pointer (either because it didn't
  1123. * have one to start, or because it was recursively removed).
  1124. * So now the node needs to be removed from this level.
  1125. */
  1126. dns_rbt_deletefromlevel(node, parent == NULL ? &rbt->root :
  1127. &DOWN(parent));
  1128. if (DATA(node) != NULL && rbt->data_deleter != NULL)
  1129. rbt->data_deleter(DATA(node), rbt->deleter_arg);
  1130. unhash_node(rbt, node);
  1131. #if DNS_RBT_USEMAGIC
  1132. node->magic = 0;
  1133. #endif
  1134. dns_rbtnode_refdestroy(node);
  1135. isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
  1136. rbt->nodecount--;
  1137. /*
  1138. * There are now two special cases that can exist that would
  1139. * not have existed if the tree had been created using only
  1140. * the names that now exist in it. (This is all related to
  1141. * join_nodes() as described in this function's introductory comment.)
  1142. * Both cases exist when the deleted node's parent (the node
  1143. * that pointed to the deleted node's level) is not null but
  1144. * it has no data: parent != NULL && DATA(parent) == NULL.
  1145. *
  1146. * The first case is that the deleted node was the last on its level:
  1147. * DOWN(parent) == NULL. This case can only exist if the parent was
  1148. * previously deleted -- and so now, apparently, the parent should go
  1149. * away. That can't be done though because there might be external
  1150. * references to it, such as through a nodechain.
  1151. *
  1152. * The other case also involves a parent with no data, but with the
  1153. * deleted node being the next-to-last node instead of the last:
  1154. * LEFT(DOWN(parent)) == NULL && RIGHT(DOWN(parent)) == NULL.
  1155. * Presumably now the remaining node on the level should be joined
  1156. * with the parent, but it's already been described why that can't be
  1157. * done.
  1158. */
  1159. /*
  1160. * This function never fails.
  1161. */
  1162. return (ISC_R_SUCCESS);
  1163. }
  1164. void
  1165. dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
  1166. REQUIRE(DNS_RBTNODE_VALID(node));
  1167. REQUIRE(name != NULL);
  1168. REQUIRE(name->offsets == NULL);
  1169. NODENAME(node, name);
  1170. }
  1171. isc_result_t
  1172. dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
  1173. dns_name_t current;
  1174. isc_result_t result;
  1175. REQUIRE(DNS_RBTNODE_VALID(node));
  1176. REQUIRE(name != NULL);
  1177. REQUIRE(name->buffer != NULL);
  1178. dns_name_init(&current, NULL);
  1179. dns_name_reset(name);
  1180. do {
  1181. INSIST(node != NULL);
  1182. NODENAME(node, &current);
  1183. result = dns_name_concatenate(name, &current, name, NULL);
  1184. if (result != ISC_R_SUCCESS)
  1185. break;
  1186. node = find_up(node);
  1187. } while (! dns_name_isabsolute(name));
  1188. return (result);
  1189. }
  1190. char *
  1191. dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
  1192. {
  1193. dns_fixedname_t fixedname;
  1194. dns_name_t *name;
  1195. isc_result_t result;
  1196. REQUIRE(DNS_RBTNODE_VALID(node));
  1197. REQUIRE(printname != NULL);
  1198. dns_fixedname_init(&fixedname);
  1199. name = dns_fixedname_name(&fixedname);
  1200. result = dns_rbt_fullnamefromnode(node, name);
  1201. if (result == ISC_R_SUCCESS)
  1202. dns_name_format(name, printname, size);
  1203. else
  1204. snprintf(printname, size, "<error building name: %s>",
  1205. dns_result_totext(result));
  1206. return (printname);
  1207. }
  1208. static isc_result_t
  1209. create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
  1210. dns_rbtnode_t *node;
  1211. isc_region_t region;
  1212. unsigned int labels;
  1213. REQUIRE(name->offsets != NULL);
  1214. dns_name_toregion(name, &region);
  1215. labels = dns_name_countlabels(name);
  1216. ENSURE(labels > 0);
  1217. /*
  1218. * Allocate space for the node structure, the name, and the offsets.
  1219. */
  1220. node = (dns_rbtnode_t *)isc_mem_get(mctx, sizeof(*node) +
  1221. region.length + labels + 1);
  1222. if (node == NULL)
  1223. return (ISC_R_NOMEMORY);
  1224. node->is_root = 0;
  1225. PARENT(node) = NULL;
  1226. RIGHT(node) = NULL;
  1227. LEFT(node) = NULL;
  1228. DOWN(node) = NULL;
  1229. DATA(node) = NULL;
  1230. #ifdef DNS_RBT_USEHASH
  1231. HASHNEXT(node) = NULL;
  1232. HASHVAL(node) = 0;
  1233. #endif
  1234. ISC_LINK_INIT(node, deadlink);
  1235. LOCKNUM(node) = 0;
  1236. WILD(node) = 0;
  1237. DIRTY(node) = 0;
  1238. dns_rbtnode_refinit(node, 0);
  1239. node->find_callback = 0;
  1240. node->nsec = DNS_RBT_NSEC_NORMAL;
  1241. MAKE_BLACK(node);
  1242. /*
  1243. * The following is stored to make reconstructing a name from the
  1244. * stored value in the node easy: the length of the name, the number
  1245. * of labels, whether the name is absolute or not, the name itself,
  1246. * and the name's offsets table.
  1247. *
  1248. * XXX RTH
  1249. * The offsets table could be made smaller by eliminating the
  1250. * first offset, which is always 0. This requires changes to
  1251. * lib/dns/name.c.
  1252. *
  1253. * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned
  1254. * as it uses OLDNAMELEN.
  1255. */
  1256. OLDNAMELEN(node) = NAMELEN(node) = region.length;
  1257. OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
  1258. ATTRS(node) = name->attributes;
  1259. memcpy(NAME(node), region.base, region.length);
  1260. memcpy(OFFSETS(node), name->offsets, labels);
  1261. #if DNS_RBT_USEMAGIC
  1262. node->magic = DNS_RBTNODE_MAGIC;
  1263. #endif
  1264. *nodep = node;
  1265. return (ISC_R_SUCCESS);
  1266. }
  1267. #ifdef DNS_RBT_USEHASH
  1268. static inline void
  1269. hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
  1270. unsigned int hash;
  1271. HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
  1272. hash = HASHVAL(node) % rbt->hashsize;
  1273. HASHNEXT(node) = rbt->hashtable[hash];
  1274. rbt->hashtable[hash] = node;
  1275. }
  1276. static isc_result_t
  1277. inithash(dns_rbt_t *rbt) {
  1278. unsigned int bytes;
  1279. rbt->hashsize = RBT_HASH_SIZE;
  1280. bytes = rbt->hashsize * sizeof(dns_rbtnode_t *);
  1281. rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
  1282. if (rbt->hashtable == NULL)
  1283. return (ISC_R_NOMEMORY);
  1284. memset(rbt->hashtable, 0, bytes);
  1285. return (ISC_R_SUCCESS);
  1286. }
  1287. static void
  1288. rehash(dns_rbt_t *rbt) {
  1289. unsigned int oldsize;
  1290. dns_rbtnode_t **oldtable;
  1291. dns_rbtnode_t *node;
  1292. unsigned int hash;
  1293. unsigned int i;
  1294. oldsize = rbt->hashsize;
  1295. oldtable = rbt->hashtable;
  1296. rbt->hashsize = rbt->hashsize * 2 + 1;
  1297. rbt->hashtable = isc_mem_get(rbt->mctx,
  1298. rbt->hashsize * sizeof(dns_rbtnode_t *));
  1299. if (rbt->hashtable == NULL) {
  1300. rbt->hashtable = oldtable;
  1301. rbt->hashsize = oldsize;
  1302. return;
  1303. }
  1304. for (i = 0; i < rbt->hashsize; i++)
  1305. rbt->hashtable[i] = NULL;
  1306. for (i = 0; i < oldsize; i++) {
  1307. node = oldtable[i];
  1308. while (node != NULL) {
  1309. hash = HASHVAL(node) % rbt->hashsize;
  1310. oldtable[i] = HASHNEXT(node);
  1311. HASHNEXT(node) = rbt->hashtable[hash];
  1312. rbt->hashtable[hash] = node;
  1313. node = oldtable[i];
  1314. }
  1315. }
  1316. isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
  1317. }
  1318. static inline void
  1319. hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
  1320. REQUIRE(DNS_RBTNODE_VALID(node));
  1321. if (rbt->nodecount >= (rbt->hashsize *3))
  1322. rehash(rbt);
  1323. hash_add_node(rbt, node, name);
  1324. }
  1325. static inline void
  1326. unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
  1327. unsigned int bucket;
  1328. dns_rbtnode_t *bucket_node;
  1329. REQUIRE(DNS_RBTNODE_VALID(node));
  1330. if (rbt->hashtable != NULL) {
  1331. bucket = HASHVAL(node) % rbt->hashsize;
  1332. bucket_node = rbt->hashtable[bucket];
  1333. if (bucket_node == node)
  1334. rbt->hashtable[bucket] = HASHNEXT(node);
  1335. else {
  1336. while (HASHNEXT(bucket_node) != node) {
  1337. INSIST(HASHNEXT(bucket_node) != NULL);
  1338. bucket_node = HASHNEXT(bucket_node);
  1339. }
  1340. HASHNEXT(bucket_node) = HASHNEXT(node);
  1341. }
  1342. }
  1343. }
  1344. #endif /* DNS_RBT_USEHASH */
  1345. static inline void
  1346. rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
  1347. dns_rbtnode_t *child;
  1348. REQUIRE(DNS_RBTNODE_VALID(node));
  1349. REQUIRE(rootp != NULL);
  1350. child = RIGHT(node);
  1351. INSIST(child != NULL);
  1352. RIGHT(node) = LEFT(child);
  1353. if (LEFT(child) != NULL)
  1354. PARENT(LEFT(child)) = node;
  1355. LEFT(child) = node;
  1356. if (child != NULL)
  1357. PARENT(child) = PARENT(node);
  1358. if (IS_ROOT(node)) {
  1359. *rootp = child;
  1360. child->is_root = 1;
  1361. node->is_root = 0;
  1362. } else {
  1363. if (LEFT(PARENT(node)) == node)
  1364. LEFT(PARENT(node)) = child;
  1365. else
  1366. RIGHT(PARENT(node)) = child;
  1367. }
  1368. PARENT(node) = child;
  1369. }
  1370. static inline void
  1371. rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
  1372. dns_rbtnode_t *child;
  1373. REQUIRE(DNS_RBTNODE_VALID(node));
  1374. REQUIRE(rootp != NULL);
  1375. child = LEFT(node);
  1376. INSIST(child != NULL);
  1377. LEFT(node) = RIGHT(child);
  1378. if (RIGHT(child) != NULL)
  1379. PARENT(RIGHT(child)) = node;
  1380. RIGHT(child) = node;
  1381. if (child != NULL)
  1382. PARENT(child) = PARENT(node);
  1383. if (IS_ROOT(node)) {
  1384. *rootp = child;
  1385. child->is_root = 1;
  1386. node->is_root = 0;
  1387. } else {
  1388. if (LEFT(PARENT(node)) == node)
  1389. LEFT(PARENT(node)) = child;
  1390. else
  1391. RIGHT(PARENT(node)) = child;
  1392. }
  1393. PARENT(node) = child;
  1394. }
  1395. /*
  1396. * This is the real workhorse of the insertion code, because it does the
  1397. * true red/black tree on a single level.
  1398. */
  1399. static void
  1400. dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
  1401. dns_rbtnode_t **rootp)
  1402. {
  1403. dns_rbtnode_t *child, *root, *parent, *grandparent;
  1404. dns_name_t add_name, current_name;
  1405. dns_offsets_t add_offsets, current_offsets;
  1406. REQUIRE(rootp != NULL);
  1407. REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
  1408. RIGHT(node) == NULL);
  1409. REQUIRE(current != NULL);
  1410. root = *rootp;
  1411. if (root == NULL) {
  1412. /*
  1413. * First node of a level.
  1414. */
  1415. MAKE_BLACK(node);
  1416. node->is_root = 1;
  1417. PARENT(node) = current;
  1418. *rootp = node;
  1419. return;
  1420. }
  1421. child = root;
  1422. POST(child);
  1423. dns_name_init(&add_name, add_offsets);
  1424. NODENAME(node, &add_name);
  1425. dns_name_init(&current_name, current_offsets);
  1426. NODENAME(current, &current_name);
  1427. if (order < 0) {
  1428. INSIST(LEFT(current) == NULL);
  1429. LEFT(current) = node;
  1430. } else {
  1431. INSIST(RIGHT(current) == NULL);
  1432. RIGHT(current) = node;
  1433. }
  1434. INSIST(PARENT(node) == NULL);
  1435. PARENT(node) = current;
  1436. MAKE_RED(node);
  1437. while (node != root && IS_RED(PARENT(node))) {
  1438. /*
  1439. * XXXDCL could do away with separate parent and grandparent
  1440. * variables. They are vestiges of the days before parent
  1441. * pointers. However, they make the code a little clearer.
  1442. */
  1443. parent = PARENT(node);
  1444. grandparent = PARENT(parent);
  1445. if (parent == LEFT(grandparent)) {
  1446. child = RIGHT(grandparent);
  1447. if (child != NULL && IS_RED(child)) {
  1448. MAKE_BLACK(parent);
  1449. MAKE_BLACK(child);
  1450. MAKE_RED(grandparent);
  1451. node = grandparent;
  1452. } else {
  1453. if (node == RIGHT(parent)) {
  1454. rotate_left(parent, &root);
  1455. node = parent;
  1456. parent = PARENT(node);
  1457. grandparent = PARENT(parent);
  1458. }
  1459. MAKE_BLACK(parent);
  1460. MAKE_RED(grandparent);
  1461. rotate_right(grandparent, &root);
  1462. }
  1463. } else {
  1464. child = LEFT(grandparent);
  1465. if (child != NULL && IS_RED(child)) {
  1466. MAKE_BLACK(parent);
  1467. MAKE_BLACK(child);
  1468. MAKE_RED(grandparent);
  1469. node = grandparent;
  1470. } else {
  1471. if (node == LEFT(parent)) {
  1472. rotate_right(parent, &root);
  1473. node = parent;
  1474. parent = PARENT(node);
  1475. grandparent = PARENT(parent);
  1476. }
  1477. MAKE_BLACK(parent);
  1478. MAKE_RED(grandparent);
  1479. rotate_left(grandparent, &root);
  1480. }
  1481. }
  1482. }
  1483. MAKE_BLACK(root);
  1484. ENSURE(IS_ROOT(root));
  1485. *rootp = root;
  1486. return;
  1487. }
  1488. /*
  1489. * This is the real workhorse of the deletion code, because it does the
  1490. * true red/black tree on a single level.
  1491. */
  1492. static void
  1493. dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
  1494. dns_rbtnode_t *child, *sibling, *parent;
  1495. dns_rbtnode_t *successor;
  1496. REQUIRE(delete != NULL);
  1497. /*
  1498. * Verify that the parent history is (apparently) correct.
  1499. */
  1500. INSIST((IS_ROOT(delete) && *rootp == delete) ||
  1501. (! IS_ROOT(delete) &&
  1502. (LEFT(PARENT(delete)) == delete ||
  1503. RIGHT(PARENT(delete)) == delete)));
  1504. child = NULL;
  1505. if (LEFT(delete) == NULL) {
  1506. if (RIGHT(delete) == NULL) {
  1507. if (IS_ROOT(delete)) {
  1508. /*
  1509. * This is the only item in the tree.
  1510. */
  1511. *rootp = NULL;
  1512. return;
  1513. }
  1514. } else
  1515. /*
  1516. * This node has one child, on the right.
  1517. */
  1518. child = RIGHT(delete);
  1519. } else if (RIGHT(delete) == NULL)
  1520. /*
  1521. * This node has one child, on the left.
  1522. */
  1523. child = LEFT(delete);
  1524. else {
  1525. dns_rbtnode_t holder, *tmp = &holder;
  1526. /*
  1527. * This node has two children, so it cannot be directly
  1528. * deleted. Find its immediate in-order successor and
  1529. * move it to this location, then do the deletion at the
  1530. * old site of the successor.
  1531. */
  1532. successor = RIGHT(delete);
  1533. while (LEFT(successor) != NULL)
  1534. successor = LEFT(successor);
  1535. /*
  1536. * The successor cannot possibly have a left child;
  1537. * if there is any child, it is on the right.
  1538. */
  1539. if (RIGHT(successor) != NULL)
  1540. child = RIGHT(successor);
  1541. /*
  1542. * Swap the two nodes; it would be simpler to just replace
  1543. * the value being deleted with that of the successor,
  1544. * but this rigamarole is done so the caller has complete
  1545. * control over the pointers (and memory allocation) of
  1546. * all of nodes. If just the key value were removed from
  1547. * the tree, the pointer to the node would be unchanged.
  1548. */
  1549. /*
  1550. * First, put the successor in the tree location of the
  1551. * node to be deleted. Save its existing tree pointer
  1552. * information, which will be needed when linking up
  1553. * delete to the successor's old location.
  1554. */
  1555. memcpy(tmp, successor, sizeof(dns_rbtnode_t));
  1556. if (IS_ROOT(delete)) {
  1557. *rootp = successor;
  1558. successor->is_root = ISC_TRUE;
  1559. delete->is_root = ISC_FALSE;
  1560. } else
  1561. if (LEFT(PARENT(delete)) == delete)
  1562. LEFT(PARENT(delete)) = successor;
  1563. else
  1564. RIGHT(PARENT(delete)) = successor;
  1565. PARENT(successor) = PARENT(delete);
  1566. LEFT(successor) = LEFT(delete);
  1567. RIGHT(successor) = RIGHT(delete);
  1568. COLOR(successor) = COLOR(delete);
  1569. if (LEFT(successor) != NULL)
  1570. PARENT(LEFT(successor)) = successor;
  1571. if (RIGHT(successor) != successor)
  1572. PARENT(RIGHT(successor)) = successor;
  1573. /*
  1574. * Now relink the node to be deleted into the
  1575. * successor's previous tree location. PARENT(tmp)
  1576. * is the successor's original parent.
  1577. */
  1578. INSIST(! IS_ROOT(delete));
  1579. if (PARENT(tmp) == delete) {
  1580. /*
  1581. * Node being deleted was successor's parent.
  1582. */
  1583. RIGHT(successor) = delete;
  1584. PARENT(delete) = successor;
  1585. } else {
  1586. LEFT(PARENT(tmp)) = delete;
  1587. PARENT(delete) = PARENT(tmp);
  1588. }
  1589. /*
  1590. * Original location of successor node has no left.
  1591. */
  1592. LEFT(delete) = NULL;
  1593. RIGHT(delete) = RIGHT(tmp);
  1594. COLOR(delete) = COLOR(tmp);
  1595. }
  1596. /*
  1597. * Remove the node by removing the links from its parent.
  1598. */
  1599. if (! IS_ROOT(delete)) {
  1600. if (LEFT(PARENT(delete)) == delete)
  1601. LEFT(PARENT(delete)) = child;
  1602. else
  1603. RIGHT(PARENT(delete)) = child;
  1604. if (child != NULL)
  1605. PARENT(child) = PARENT(delete);
  1606. } else {
  1607. /*
  1608. * This is the root being deleted, and at this point
  1609. * it is known to have just one child.
  1610. */
  1611. *rootp = child;
  1612. child->is_root = 1;
  1613. PARENT(child) = PARENT(delete);
  1614. }
  1615. /*
  1616. * Fix color violations.
  1617. */
  1618. if (IS_BLACK(delete)) {
  1619. parent = PARENT(delete);
  1620. while (child != *rootp && IS_BLACK(child)) {
  1621. INSIST(child == NULL || ! IS_ROOT(child));
  1622. if (LEFT(parent) == child) {
  1623. sibling = RIGHT(parent);
  1624. if (IS_RED(sibling)) {
  1625. MAKE_BLACK(sibling);
  1626. MAKE_RED(parent);
  1627. rotate_left(parent, rootp);
  1628. sibling = RIGHT(parent);
  1629. }
  1630. INSIST(sibling != NULL);
  1631. if (IS_BLACK(LEFT(sibling)) &&
  1632. IS_BLACK(RIGHT(sibling))) {
  1633. MAKE_RED(sibling);
  1634. child = parent;
  1635. } else {
  1636. if (IS_BLACK(RIGHT(sibling))) {
  1637. MAKE_BLACK(LEFT(sibling));
  1638. MAKE_RED(sibling);
  1639. rotate_right(sibling, rootp);
  1640. sibling = RIGHT(parent);
  1641. }
  1642. COLOR(sibling) = COLOR(parent);
  1643. MAKE_BLACK(parent);
  1644. MAKE_BLACK(RIGHT(sibling));
  1645. rotate_left(parent, rootp);
  1646. child = *rootp;
  1647. }
  1648. } else {
  1649. /*
  1650. * Child is parent's right child.
  1651. * Everything is done the same as above,
  1652. * except mirrored.
  1653. */
  1654. sibling = LEFT(parent);
  1655. if (IS_RED(sibling)) {
  1656. MAKE_BLACK(sibling);
  1657. MAKE_RED(parent);
  1658. rotate_right(parent, rootp);
  1659. sibling = LEFT(parent);
  1660. }
  1661. INSIST(sibling != NULL);
  1662. if (IS_BLACK(LEFT(sibling)) &&
  1663. IS_BLACK(RIGHT(sibling))) {
  1664. MAKE_RED(sibling);
  1665. child = parent;
  1666. } else {
  1667. if (IS_BLACK(LEFT(sibling))) {
  1668. MAKE_BLACK(RIGHT(sibling));
  1669. MAKE_RED(sibling);
  1670. rotate_left(sibling, rootp);
  1671. sibling = LEFT(parent);
  1672. }
  1673. COLOR(sibling) = COLOR(parent);
  1674. MAKE_BLACK(parent);
  1675. MAKE_BLACK(LEFT(sibling));
  1676. rotate_right(parent, rootp);
  1677. child = *rootp;
  1678. }
  1679. }
  1680. parent = PARENT(child);
  1681. }
  1682. if (IS_RED(child))
  1683. MAKE_BLACK(child);
  1684. }
  1685. }
  1686. /*
  1687. * This should only be used on the root of a tree, because no color fixup
  1688. * is done at all.
  1689. *
  1690. * NOTE: No root pointer maintenance is done, because the function is only
  1691. * used for two cases:
  1692. * + deleting everything DOWN from a node that is itself being deleted, and
  1693. * + deleting the entire tree of trees from dns_rbt_destroy.
  1694. * In each case, the root pointer is no longer relevant, so there
  1695. * is no need for a root parameter to this function.
  1696. *
  1697. * If the function is ever intended to be used to delete something where
  1698. * a pointer needs to be told that this tree no longer exists,
  1699. * this function would need to adjusted accordingly.
  1700. */
  1701. static isc_result_t
  1702. dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
  1703. isc_result_t result = ISC_R_SUCCESS;
  1704. REQUIRE(VALID_RBT(rbt));
  1705. if (node == NULL)
  1706. return (result);
  1707. if (LEFT(node) != NULL) {
  1708. result = dns_rbt_deletetree(rbt, LEFT(node));
  1709. if (result != ISC_R_SUCCESS)
  1710. goto done;
  1711. LEFT(node) = NULL;
  1712. }
  1713. if (RIGHT(node) != NULL) {
  1714. result = dns_rbt_deletetree(rbt, RIGHT(node));
  1715. if (result != ISC_R_SUCCESS)
  1716. goto done;
  1717. RIGHT(node) = NULL;
  1718. }
  1719. if (DOWN(node) != NULL) {
  1720. result = dns_rbt_deletetree(rbt, DOWN(node));
  1721. if (result != ISC_R_SUCCESS)
  1722. goto done;
  1723. DOWN(node) = NULL;
  1724. }
  1725. done:
  1726. if (result != ISC_R_SUCCESS)
  1727. return (result);
  1728. if (DATA(node) != NULL && rbt->data_deleter != NULL)
  1729. rbt->data_deleter(DATA(node), rbt->deleter_arg);
  1730. unhash_node(rbt, node);
  1731. #if DNS_RBT_USEMAGIC
  1732. node->magic = 0;
  1733. #endif
  1734. isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
  1735. rbt->nodecount--;
  1736. return (result);
  1737. }
  1738. static void
  1739. dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
  1740. dns_rbtnode_t **nodep)
  1741. {
  1742. dns_rbtnode_t *parent;
  1743. dns_rbtnode_t *node = *nodep;
  1744. REQUIRE(VALID_RBT(rbt));
  1745. again:
  1746. if (node == NULL) {
  1747. *nodep = NULL;
  1748. return;
  1749. }
  1750. traverse:
  1751. if (LEFT(node) != NULL) {
  1752. node = LEFT(node);
  1753. goto traverse;
  1754. }
  1755. if (DOWN(node) != NULL) {
  1756. node = DOWN(node);
  1757. goto traverse;
  1758. }
  1759. if (DATA(node) != NULL && rbt->data_deleter != NULL)
  1760. rbt->data_deleter(DATA(node), rbt->deleter_arg);
  1761. /*
  1762. * Note: we don't call unhash_node() here as we are destroying
  1763. * the complete rbt tree.
  1764. */
  1765. #if DNS_RBT_USEMAGIC
  1766. node->magic = 0;
  1767. #endif
  1768. parent = PARENT(node);
  1769. if (RIGHT(node) != NULL)
  1770. PARENT(RIGHT(node)) = parent;
  1771. if (parent != NULL) {
  1772. if (LEFT(parent) == node)
  1773. LEFT(parent) = RIGHT(node);
  1774. else if (DOWN(parent) == node)
  1775. DOWN(parent) = RIGHT(node);
  1776. } else
  1777. parent = RIGHT(node);
  1778. isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
  1779. rbt->nodecount--;
  1780. node = parent;
  1781. if (quantum != 0 && --quantum == 0) {
  1782. *nodep = node;
  1783. return;
  1784. }
  1785. goto again;
  1786. }
  1787. static void
  1788. dns_rbt_indent(int depth) {
  1789. int i;
  1790. for (i = 0; i < depth; i++)
  1791. putchar('\t');
  1792. }
  1793. static void
  1794. dns_rbt_printnodename(dns_rbtnode_t *node) {
  1795. isc_region_t r;
  1796. dns_name_t name;
  1797. char buffer[DNS_NAME_FORMATSIZE];
  1798. dns_offsets_t offsets;
  1799. r.length = NAMELEN(node);
  1800. r.base = NAME(node);
  1801. dns_name_init(&name, offsets);
  1802. dns_name_fromregion(&name, &r);
  1803. dns_name_format(&name, buffer, sizeof(buffer));
  1804. printf("%s", buffer);
  1805. }
  1806. static void
  1807. dns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent, int depth) {
  1808. dns_rbt_indent(depth);
  1809. if (root != NULL) {
  1810. dns_rbt_printnodename(root);
  1811. printf(" (%s", IS_RED(root) ? "RED" : "black");
  1812. if (parent) {
  1813. printf(" from ");
  1814. dns_rbt_printnodename(parent);
  1815. }
  1816. if ((! IS_ROOT(root) && PARENT(root) != parent) ||
  1817. ( IS_ROOT(root) && depth > 0 &&
  1818. DOWN(PARENT(root)) != root)) {
  1819. printf(" (BAD parent pointer! -> ");
  1820. if (PARENT(root) != NULL)
  1821. dns_rbt_printnodename(PARENT(root));
  1822. else
  1823. printf("NULL");
  1824. printf(")");
  1825. }
  1826. printf(")\n");
  1827. depth++;
  1828. if (DOWN(root)) {
  1829. dns_rbt_indent(depth);
  1830. printf("++ BEG down from ");
  1831. dns_rbt_printnodename(root);
  1832. printf("\n");
  1833. dns_rbt_printtree(DOWN(root), NULL, depth);
  1834. dns_rbt_indent(depth);
  1835. printf("-- END down from ");
  1836. dns_rbt_printnodename(root);
  1837. printf("\n");
  1838. }
  1839. if (IS_RED(root) && IS_RED(LEFT(root)))
  1840. printf("** Red/Red color violation on left\n");
  1841. dns_rbt_printtree(LEFT(root), root, depth);
  1842. if (IS_RED(root) && IS_RED(RIGHT(root)))
  1843. printf("** Red/Red color violation on right\n");
  1844. dns_rbt_printtree(RIGHT(root), root, depth);
  1845. } else
  1846. printf("NULL\n");
  1847. }
  1848. void
  1849. dns_rbt_printall(dns_rbt_t *rbt) {
  1850. REQUIRE(VALID_RBT(rbt));
  1851. dns_rbt_printtree(rbt->root, NULL, 0);
  1852. }
  1853. /*
  1854. * Chain Functions
  1855. */
  1856. void
  1857. dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
  1858. /*
  1859. * Initialize 'chain'.
  1860. */
  1861. REQUIRE(chain != NULL);
  1862. chain->mctx = mctx;
  1863. chain->end = NULL;
  1864. chain->level_count = 0;
  1865. chain->level_matches = 0;
  1866. memset(chain->levels, 0, sizeof(chain->levels));
  1867. chain->magic = CHAIN_MAGIC;
  1868. }
  1869. isc_result_t
  1870. dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
  1871. dns_name_t *origin, dns_rbtnode_t **node)
  1872. {
  1873. isc_result_t result = ISC_R_SUCCESS;
  1874. REQUIRE(VALID_CHAIN(chain));
  1875. if (node != NULL)
  1876. *node = chain->end;
  1877. if (chain->end == NULL)
  1878. return (ISC_R_NOTFOUND);
  1879. if (name != NULL) {
  1880. NODENAME(chain->end, name);
  1881. if (chain->level_count == 0) {
  1882. /*
  1883. * Names in the top level tree are all absolute.
  1884. * Always make 'name' relative.
  1885. */
  1886. INSIST(dns_name_isabsolute(name));
  1887. /*
  1888. * This is cheaper than dns_name_getlabelsequence().
  1889. */
  1890. name->labels--;
  1891. name->length--;
  1892. name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
  1893. }
  1894. }
  1895. if (origin != NULL) {
  1896. if (chain->level_count > 0)
  1897. result = chain_name(chain, origin, ISC_FALSE);
  1898. else
  1899. result = dns_name_copy(dns_rootname, origin, NULL);
  1900. }
  1901. return (result);
  1902. }
  1903. isc_result_t
  1904. dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
  1905. dns_name_t *origin)
  1906. {
  1907. dns_rbtnode_t *current, *previous, *predecessor;
  1908. isc_result_t result = ISC_R_SUCCESS;
  1909. isc_boolean_t new_origin = ISC_FALSE;
  1910. REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
  1911. predecessor = NULL;
  1912. current = chain->end;
  1913. if (LEFT(current) != NULL) {
  1914. /*
  1915. * Moving left one then right as far as possible is the
  1916. * previous node, at least for this level.
  1917. */
  1918. current = LEFT(current);
  1919. while (RIGHT(current) != NULL)
  1920. current = RIGHT(current);
  1921. predecessor = current;
  1922. } else {
  1923. /*
  1924. * No left links, so move toward the root. If at any point on
  1925. * the way there the link from parent to child is a right
  1926. * link, then the parent is the previous node, at least
  1927. * for this level.
  1928. */
  1929. while (! IS_ROOT(current)) {
  1930. previous = current;
  1931. current = PARENT(current);
  1932. if (RIGHT(current) == previous) {
  1933. predecessor = current;
  1934. break;
  1935. }
  1936. }
  1937. }
  1938. if (predecessor != NULL) {
  1939. /*
  1940. * Found a predecessor node in this level. It might not
  1941. * really be the predecessor, however.
  1942. */
  1943. if (DOWN(predecessor) != NULL) {
  1944. /*
  1945. * The predecessor is really down at least one level.
  1946. * Go down and as far right as possible, and repeat
  1947. * as long as the rightmost node has a down pointer.
  1948. */
  1949. do {
  1950. /*
  1951. * XXX DCL Need to do something about origins
  1952. * here. See whether to go down, and if so
  1953. * whether it is truly what Bob calls a
  1954. * new origin.
  1955. */
  1956. ADD_LEVEL(chain, predecessor);
  1957. predecessor = DOWN(predecessor);
  1958. /* XXX DCL duplicated from above; clever
  1959. * way to unduplicate? */
  1960. while (RIGHT(predecessor) != NULL)
  1961. predecessor = RIGHT(predecessor);
  1962. } while (DOWN(predecessor) != NULL);
  1963. /* XXX DCL probably needs work on the concept */
  1964. if (origin != NULL)
  1965. new_origin = ISC_TRUE;
  1966. }
  1967. } else if (chain->level_count > 0) {
  1968. /*
  1969. * Dang, didn't find a predecessor in this level.
  1970. * Got to the root of this level without having traversed
  1971. * any right links. Ascend the tree one level; the
  1972. * node that points to this tree is the predecessor.
  1973. */
  1974. INSIST(chain->level_count > 0 && IS_ROOT(current));
  1975. predecessor = chain->levels[--chain->level_count];
  1976. /* XXX DCL probably needs work on the concept */
  1977. /*
  1978. * Don't declare an origin change when the new origin is "."
  1979. * at the top level tree, because "." is declared as the origin
  1980. * for the second level tree.
  1981. */
  1982. if (origin != NULL &&
  1983. (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
  1984. new_origin = ISC_TRUE;
  1985. }
  1986. if (predecessor != NULL) {
  1987. chain->end = predecessor;
  1988. if (new_origin) {
  1989. result = dns_rbtnodechain_current(chain, name, origin,
  1990. NULL);
  1991. if (result == ISC_R_SUCCESS)
  1992. result = DNS_R_NEWORIGIN;
  1993. } else
  1994. result = dns_rbtnodechain_current(chain, name, NULL,
  1995. NULL);
  1996. } else
  1997. result = ISC_R_NOMORE;
  1998. return (result);
  1999. }
  2000. isc_result_t
  2001. dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
  2002. dns_name_t *origin)
  2003. {
  2004. dns_rbtnode_t *current, *successor;
  2005. isc_result_t result = ISC_R_SUCCESS;
  2006. isc_boolean_t new_origin = ISC_FALSE;
  2007. REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
  2008. successor = NULL;
  2009. current = chain->end;
  2010. if (DOWN(current) != NULL) {
  2011. /*
  2012. * Don't declare an origin change when the new origin is "."
  2013. * at the second level tree, because "." is already declared
  2014. * as the origin for the top level tree.
  2015. */
  2016. if (chain->level_count > 0 ||
  2017. OFFSETLEN(current) > 1)
  2018. new_origin = ISC_TRUE;
  2019. ADD_LEVEL(chain, current);
  2020. current = DOWN(current);
  2021. while (LEFT(current) != NULL)
  2022. current = LEFT(current);
  2023. successor = current;
  2024. }
  2025. if (successor != NULL) {
  2026. chain->end = successor;
  2027. /*
  2028. * It is not necessary to use dns_rbtnodechain_current like
  2029. * the other functions because this function will never
  2030. * find a node in the topmost level. This is because the
  2031. * root level will never be more than one name, and everything
  2032. * in the megatree is a successor to that node, down at
  2033. * the second level or below.
  2034. */
  2035. if (name != NULL)
  2036. NODENAME(chain->end, name);
  2037. if (new_origin) {
  2038. if (origin != NULL)
  2039. result = chain_name(chain, origin, ISC_FALSE);
  2040. if (result == ISC_R_SUCCESS)
  2041. result = DNS_R_NEWORIGIN;
  2042. } else
  2043. result = ISC_R_SUCCESS;
  2044. } else
  2045. result = ISC_R_NOMORE;
  2046. return (result);
  2047. }
  2048. isc_result_t
  2049. dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
  2050. dns_rbtnode_t *current, *previous, *successor;
  2051. isc_result_t result = ISC_R_SUCCESS;
  2052. REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
  2053. successor = NULL;
  2054. current = chain->end;
  2055. if (RIGHT(current) == NULL) {
  2056. while (! IS_ROOT(current)) {
  2057. previous = current;
  2058. current = PARENT(current);
  2059. if (LEFT(current) == previous) {
  2060. successor = current;
  2061. break;
  2062. }
  2063. }
  2064. } else {
  2065. current = RIGHT(current);
  2066. while (LEFT(current) != NULL)
  2067. current = LEFT(current);
  2068. successor = current;
  2069. }
  2070. if (successor != NULL) {
  2071. chain->end = successor;
  2072. if (name != NULL)
  2073. NODENAME(chain->end, name);
  2074. result = ISC_R_SUCCESS;
  2075. } else
  2076. result = ISC_R_NOMORE;
  2077. return (result);
  2078. }
  2079. isc_result_t
  2080. dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
  2081. dns_name_t *origin)
  2082. {
  2083. dns_rbtnode_t *current, *previous, *successor;
  2084. isc_result_t result = ISC_R_SUCCESS;
  2085. isc_boolean_t new_origin = ISC_FALSE;
  2086. REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
  2087. successor = NULL;
  2088. current = chain->end;
  2089. /*
  2090. * If there is a level below this node, the next node is the leftmost
  2091. * node of the next level.
  2092. */
  2093. if (DOWN(current) != NULL) {
  2094. /*
  2095. * Don't declare an origin change when the new origin is "."
  2096. * at the second level tree, because "." is already declared
  2097. * as the origin for the top level tree.
  2098. */
  2099. if (chain->level_count > 0 ||
  2100. OFFSETLEN(current) > 1)
  2101. new_origin = ISC_TRUE;
  2102. ADD_LEVEL(chain, current);
  2103. current = DOWN(current);
  2104. while (LEFT(current) != NULL)
  2105. current = LEFT(current);
  2106. successor = current;
  2107. } else if (RIGHT(current) == NULL) {
  2108. /*
  2109. * The successor is up, either in this level or a previous one.
  2110. * Head back toward the root of the tree, looking for any path
  2111. * that was via a left link; the successor is the node that has
  2112. * that left link. In the event the root of the level is
  2113. * reached without having traversed any left links, ascend one
  2114. * level and look for either a right link off the point of
  2115. * ascent, or search for a left link upward again, repeating
  2116. * ascends until either case is true.
  2117. */
  2118. do {
  2119. while (! IS_ROOT(current)) {
  2120. previous = current;
  2121. current = PARENT(current);
  2122. if (LEFT(current) == previous) {
  2123. successor = current;
  2124. break;
  2125. }
  2126. }
  2127. if (successor == NULL) {
  2128. /*
  2129. * Reached the root without having traversed
  2130. * any left pointers, so this level is done.
  2131. */
  2132. if (chain->level_count == 0)
  2133. break;
  2134. current = chain->levels[--chain->level_count];
  2135. new_origin = ISC_TRUE;
  2136. if (RIGHT(current) != NULL)
  2137. break;
  2138. }
  2139. } while (successor == NULL);
  2140. }
  2141. if (successor == NULL && RIGHT(current) != NULL) {
  2142. current = RIGHT(current);
  2143. while (LEFT(current) != NULL)
  2144. current = LEFT(current);
  2145. successor = current;
  2146. }
  2147. if (successor != NULL) {
  2148. chain->end = successor;
  2149. /*
  2150. * It is not necessary to use dns_rbtnodechain_current like
  2151. * the other functions because this function will never
  2152. * find a node in the topmost level. This is because the
  2153. * root level will never be more than one name, and everything
  2154. * in the megatree is a successor to that node, down at
  2155. * the second level or below.
  2156. */
  2157. if (name != NULL)
  2158. NODENAME(chain->end, name);
  2159. if (new_origin) {
  2160. if (origin != NULL)
  2161. result = chain_name(chain, origin, ISC_FALSE);
  2162. if (result == ISC_R_SUCCESS)
  2163. result = DNS_R_NEWORIGIN;
  2164. } else
  2165. result = ISC_R_SUCCESS;
  2166. } else
  2167. result = ISC_R_NOMORE;
  2168. return (result);
  2169. }
  2170. isc_result_t
  2171. dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
  2172. dns_name_t *name, dns_name_t *origin)
  2173. {
  2174. isc_result_t result;
  2175. REQUIRE(VALID_RBT(rbt));
  2176. REQUIRE(VALID_CHAIN(chain));
  2177. dns_rbtnodechain_reset(chain);
  2178. chain->end = rbt->root;
  2179. result = dns_rbtnodechain_current(chain, name, origin, NULL);
  2180. if (result == ISC_R_SUCCESS)
  2181. result = DNS_R_NEWORIGIN;
  2182. return (result);
  2183. }
  2184. isc_result_t
  2185. dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
  2186. dns_name_t *name, dns_name_t *origin)
  2187. {
  2188. isc_result_t result;
  2189. REQUIRE(VALID_RBT(rbt));
  2190. REQUIRE(VALID_CHAIN(chain));
  2191. dns_rbtnodechain_reset(chain);
  2192. result = move_chain_to_last(chain, rbt->root);
  2193. if (result != ISC_R_SUCCESS)
  2194. return (result);
  2195. result = dns_rbtnodechain_current(chain, name, origin, NULL);
  2196. if (result == ISC_R_SUCCESS)
  2197. result = DNS_R_NEWORIGIN;
  2198. return (result);
  2199. }
  2200. void
  2201. dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
  2202. /*
  2203. * Free any dynamic storage associated with 'chain', and then
  2204. * reinitialize 'chain'.
  2205. */
  2206. REQUIRE(VALID_CHAIN(chain));
  2207. chain->end = NULL;
  2208. chain->level_count = 0;
  2209. chain->level_matches = 0;
  2210. }
  2211. void
  2212. dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
  2213. /*
  2214. * Free any dynamic storage associated with 'chain', and then
  2215. * invalidate 'chain'.
  2216. */
  2217. dns_rbtnodechain_reset(chain);
  2218. chain->magic = 0;
  2219. }