📄 rbt.c
字号:
}static voiddns_rbt_deletetreeflat(dns_rbt_t *rbt, dns_rbtnode_t **nodep) { dns_rbtnode_t *parent; dns_rbtnode_t *node = *nodep; REQUIRE(VALID_RBT(rbt)); again: if (node == NULL) { *nodep = NULL; return; } traverse: if (LEFT(node) != NULL) { node = LEFT(node); goto traverse; } if (RIGHT(node) != NULL) { node = RIGHT(node); goto traverse; } if (DOWN(node) != NULL) { node = DOWN(node); goto traverse; } if (DATA(node) != NULL && rbt->data_deleter != NULL) rbt->data_deleter(DATA(node), rbt->deleter_arg); unhash_node(rbt, node);#if DNS_RBT_USEMAGIC node->magic = 0;#endif parent = PARENT(node); if (parent != NULL) { if (LEFT(parent) == node) LEFT(parent) = NULL; else if (DOWN(parent) == node) DOWN(parent) = NULL; else if (RIGHT(parent) == node) RIGHT(parent) = NULL; } isc_mem_put(rbt->mctx, node, NODE_SIZE(node)); rbt->nodecount--; node = parent; if (rbt->quantum != 0 && --rbt->quantum == 0) { *nodep = node; return; } goto again;}static voiddns_rbt_indent(int depth) { int i; for (i = 0; i < depth; i++) putchar('\t');}static voiddns_rbt_printnodename(dns_rbtnode_t *node) { isc_region_t r; dns_name_t name; char buffer[DNS_NAME_FORMATSIZE]; dns_offsets_t offsets; r.length = NAMELEN(node); r.base = NAME(node); dns_name_init(&name, offsets); dns_name_fromregion(&name, &r); dns_name_format(&name, buffer, sizeof(buffer)); printf("%s", buffer);}static voiddns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent, int depth) { dns_rbt_indent(depth); if (root != NULL) { dns_rbt_printnodename(root); printf(" (%s", IS_RED(root) ? "RED" : "black"); if (parent) { printf(" from "); dns_rbt_printnodename(parent); } if ((! IS_ROOT(root) && PARENT(root) != parent) || ( IS_ROOT(root) && depth > 0 && DOWN(PARENT(root)) != root)) { printf(" (BAD parent pointer! -> "); if (PARENT(root) != NULL) dns_rbt_printnodename(PARENT(root)); else printf("NULL"); printf(")"); } printf(")\n"); depth++; if (DOWN(root)) { dns_rbt_indent(depth); printf("++ BEG down from "); dns_rbt_printnodename(root); printf("\n"); dns_rbt_printtree(DOWN(root), NULL, depth); dns_rbt_indent(depth); printf("-- END down from "); dns_rbt_printnodename(root); printf("\n"); } if (IS_RED(root) && IS_RED(LEFT(root))) printf("** Red/Red color violation on left\n"); dns_rbt_printtree(LEFT(root), root, depth); if (IS_RED(root) && IS_RED(RIGHT(root))) printf("** Red/Red color violation on right\n"); dns_rbt_printtree(RIGHT(root), root, depth); } else printf("NULL\n");}voiddns_rbt_printall(dns_rbt_t *rbt) { REQUIRE(VALID_RBT(rbt)); dns_rbt_printtree(rbt->root, NULL, 0);}/* * Chain Functions */voiddns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) { /* * Initialize 'chain'. */ REQUIRE(chain != NULL); chain->mctx = mctx; chain->end = NULL; chain->level_count = 0; chain->level_matches = 0; chain->magic = CHAIN_MAGIC;}isc_result_tdns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name, dns_name_t *origin, dns_rbtnode_t **node){ isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_CHAIN(chain)); if (node != NULL) *node = chain->end; if (chain->end == NULL) return (ISC_R_NOTFOUND); if (name != NULL) { NODENAME(chain->end, name); if (chain->level_count == 0) { /* * Names in the top level tree are all absolute. * Always make 'name' relative. */ INSIST(dns_name_isabsolute(name)); /* * This is cheaper than dns_name_getlabelsequence(). */ name->labels--; name->length--; name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; } } if (origin != NULL) { if (chain->level_count > 0) result = chain_name(chain, origin, ISC_FALSE); else result = dns_name_copy(dns_rootname, origin, NULL); } return (result);}isc_result_tdns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name, dns_name_t *origin){ dns_rbtnode_t *current, *previous, *predecessor; isc_result_t result = ISC_R_SUCCESS; isc_boolean_t new_origin = ISC_FALSE; REQUIRE(VALID_CHAIN(chain) && chain->end != NULL); predecessor = NULL; current = chain->end; if (LEFT(current) != NULL) { /* * Moving left one then right as far as possible is the * previous node, at least for this level. */ current = LEFT(current); while (RIGHT(current) != NULL) current = RIGHT(current); predecessor = current; } else { /* * No left links, so move toward the root. If at any point on * the way there the link from parent to child is a right * link, then the parent is the previous node, at least * for this level. */ while (! IS_ROOT(current)) { previous = current; current = PARENT(current); if (RIGHT(current) == previous) { predecessor = current; break; } } } if (predecessor != NULL) { /* * Found a predecessor node in this level. It might not * really be the predecessor, however. */ if (DOWN(predecessor) != NULL) { /* * The predecessor is really down at least one level. * Go down and as far right as possible, and repeat * as long as the rightmost node has a down pointer. */ do { /* * XXX DCL Need to do something about origins * here. See whether to go down, and if so * whether it is truly what Bob calls a * new origin. */ ADD_LEVEL(chain, predecessor); predecessor = DOWN(predecessor); /* XXX DCL duplicated from above; clever * way to unduplicate? */ while (RIGHT(predecessor) != NULL) predecessor = RIGHT(predecessor); } while (DOWN(predecessor) != NULL); /* XXX DCL probably needs work on the concept */ if (origin != NULL) new_origin = ISC_TRUE; } } else if (chain->level_count > 0) { /* * Dang, didn't find a predecessor in this level. * Got to the root of this level without having traversed * any right links. Ascend the tree one level; the * node that points to this tree is the predecessor. */ INSIST(chain->level_count > 0 && IS_ROOT(current)); predecessor = chain->levels[--chain->level_count]; /* XXX DCL probably needs work on the concept */ /* * Don't declare an origin change when the new origin is "." * at the top level tree, because "." is declared as the origin * for the second level tree. */ if (origin != NULL && (chain->level_count > 0 || OFFSETLEN(predecessor) > 1)) new_origin = ISC_TRUE; } if (predecessor != NULL) { chain->end = predecessor; if (new_origin) { result = dns_rbtnodechain_current(chain, name, origin, NULL); if (result == ISC_R_SUCCESS) result = DNS_R_NEWORIGIN; } else result = dns_rbtnodechain_current(chain, name, NULL, NULL); } else result = ISC_R_NOMORE; return (result);}isc_result_tdns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name, dns_name_t *origin){ dns_rbtnode_t *current, *previous, *successor; isc_result_t result = ISC_R_SUCCESS; isc_boolean_t new_origin = ISC_FALSE; REQUIRE(VALID_CHAIN(chain) && chain->end != NULL); successor = NULL; current = chain->end; /* * If there is a level below this node, the next node is the leftmost * node of the next level. */ if (DOWN(current) != NULL) { /* * Don't declare an origin change when the new origin is "." * at the second level tree, because "." is already declared * as the origin for the top level tree. */ if (chain->level_count > 0 || OFFSETLEN(current) > 1) new_origin = ISC_TRUE; ADD_LEVEL(chain, current); current = DOWN(current); while (LEFT(current) != NULL) current = LEFT(current); successor = current; } else if (RIGHT(current) == NULL) { /* * The successor is up, either in this level or a previous one. * Head back toward the root of the tree, looking for any path * that was via a left link; the successor is the node that has * that left link. In the event the root of the level is * reached without having traversed any left links, ascend one * level and look for either a right link off the point of * ascent, or search for a left link upward again, repeating * ascents until either case is true. */ do { while (! IS_ROOT(current)) { previous = current; current = PARENT(current); if (LEFT(current) == previous) { successor = current; break; } } if (successor == NULL) { /* * Reached the root without having traversed * any left pointers, so this level is done. */ if (chain->level_count == 0) break; current = chain->levels[--chain->level_count]; new_origin = ISC_TRUE; if (RIGHT(current) != NULL) break; } } while (successor == NULL); } if (successor == NULL && RIGHT(current) != NULL) { current = RIGHT(current); while (LEFT(current) != NULL) current = LEFT(current); successor = current; } if (successor != NULL) { chain->end = successor; /* * It is not necessary to use dns_rbtnodechain_current like * the other functions because this function will never * find a node in the topmost level. This is because the * root level will never be more than one name, and everything * in the megatree is a successor to that node, down at * the second level or below. */ if (name != NULL) NODENAME(chain->end, name); if (new_origin) { if (origin != NULL) result = chain_name(chain, origin, ISC_FALSE); if (result == ISC_R_SUCCESS) result = DNS_R_NEWORIGIN; } else result = ISC_R_SUCCESS; } else result = ISC_R_NOMORE; return (result);}isc_result_tdns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt, dns_name_t *name, dns_name_t *origin){ isc_result_t result; REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_CHAIN(chain)); dns_rbtnodechain_reset(chain); chain->end = rbt->root; result = dns_rbtnodechain_current(chain, name, origin, NULL); if (result == ISC_R_SUCCESS) result = DNS_R_NEWORIGIN; return (result);}isc_result_tdns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt, dns_name_t *name, dns_name_t *origin){ isc_result_t result; REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_CHAIN(chain)); dns_rbtnodechain_reset(chain); result = move_chain_to_last(chain, rbt->root); if (result != ISC_R_SUCCESS) return (result); result = dns_rbtnodechain_current(chain, name, origin, NULL); if (result == ISC_R_SUCCESS) result = DNS_R_NEWORIGIN; return (result);}voiddns_rbtnodechain_reset(dns_rbtnodechain_t *chain) { /* * Free any dynamic storage associated with 'chain', and then * reinitialize 'chain'. */ REQUIRE(VALID_CHAIN(chain)); chain->end = NULL; chain->level_count = 0; chain->level_matches = 0;}voiddns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) { /* * Free any dynamic storage associated with 'chain', and then * invalidate 'chain'. */ dns_rbtnodechain_reset(chain); chain->magic = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -