mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 05:28:00 +00:00
Major:
deletion bug fixed that could orphan a large section of the tree. the "parent" argument to rotate_left or rotate_right was sometimes not really the parent of the rotation vertex, because the parent's parent was not correctly reidentified after a rotation done on the parent. Minor: forward static declaration of dns_rbt_printnodename, useful in debugging. level_matches set correctly for exact match in dns_rbt_findnode (it was one too few, but this was minor because as yet level_matches is only used by other code when a partial match was made. insist 'node' is a child of 'parent' in rotate_left and rotate_right compare a pointer explicitly to NULL that was just "if (pointer)" "would would" in a comment changed to just one "would".
This commit is contained in:
parent
80bd254851
commit
401fc772b1
@ -15,7 +15,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rbt.c,v 1.63 1999/10/15 01:35:23 halley Exp $ */
|
||||
/* $Id: rbt.c,v 1.64 1999/10/16 19:44:54 tale Exp $ */
|
||||
|
||||
/* Principal Authors: DCL */
|
||||
|
||||
@ -147,6 +147,8 @@ Name(dns_rbtnode_t *node) {
|
||||
|
||||
return (name);
|
||||
}
|
||||
|
||||
static void dns_rbt_printnodename(dns_rbtnode_t *node);
|
||||
#endif
|
||||
|
||||
#if defined(ISC_MEM_DEBUG) || defined(RBT_MEM_TEST)
|
||||
@ -870,8 +872,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
||||
* Found an exact match.
|
||||
*/
|
||||
chain->end = current;
|
||||
chain->level_matches = chain->level_count == 0 ? 0 :
|
||||
chain->level_count - 1;
|
||||
chain->level_matches = chain->level_count;
|
||||
|
||||
if (foundname != NULL)
|
||||
result = chain_name(chain, foundname, ISC_TRUE);
|
||||
@ -1362,6 +1363,8 @@ rotate_left(dns_rbtnode_t *node, dns_rbtnode_t *parent, dns_rbtnode_t **rootp) {
|
||||
|
||||
REQUIRE(node != NULL);
|
||||
REQUIRE(rootp != NULL);
|
||||
REQUIRE(parent == NULL ||
|
||||
RIGHT(parent) == node || LEFT(parent) == node);
|
||||
|
||||
child = RIGHT(node);
|
||||
REQUIRE(child != NULL);
|
||||
@ -1385,6 +1388,8 @@ rotate_right(dns_rbtnode_t *node, dns_rbtnode_t *parent, dns_rbtnode_t **rootp)
|
||||
|
||||
REQUIRE(node != NULL);
|
||||
REQUIRE(rootp != NULL);
|
||||
REQUIRE(parent == NULL ||
|
||||
RIGHT(parent) == node || LEFT(parent) == node);
|
||||
|
||||
child = LEFT(node);
|
||||
REQUIRE(child != NULL);
|
||||
@ -1582,7 +1587,7 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
|
||||
* The successor cannot possibly have a left child;
|
||||
* if there is any child, it is on the right.
|
||||
*/
|
||||
if (RIGHT(successor))
|
||||
if (RIGHT(successor) != NULL)
|
||||
child = RIGHT(successor);
|
||||
|
||||
/* Swap the two nodes; it would be simpler to just replace
|
||||
@ -1590,15 +1595,13 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
|
||||
* but this rigamarole is done so the caller has complete
|
||||
* control over the pointers (and memory allocation) of
|
||||
* all of nodes. If just the key value were removed from
|
||||
* the tree, the pointer to the node would would be
|
||||
* unchanged.
|
||||
* the tree, the pointer to the node would be unchanged.
|
||||
*/
|
||||
|
||||
/*
|
||||
* First, put the successor in the tree location of the
|
||||
* node to be deleted.
|
||||
*/
|
||||
|
||||
memcpy(tmp, successor, sizeof(dns_rbtnode_t));
|
||||
|
||||
chain->ancestors[depth] = successor;
|
||||
@ -1629,7 +1632,6 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
|
||||
/*
|
||||
* Original location of successor node has no left.
|
||||
*/
|
||||
|
||||
LEFT(delete) = NULL;
|
||||
RIGHT(delete) = RIGHT(tmp);
|
||||
COLOR(delete) = COLOR(tmp);
|
||||
@ -1671,26 +1673,37 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
|
||||
|
||||
if (LEFT(parent) == child) {
|
||||
sibling = RIGHT(parent);
|
||||
|
||||
if (IS_RED(sibling)) {
|
||||
MAKE_BLACK(sibling);
|
||||
MAKE_RED(parent);
|
||||
rotate_left(parent, grandparent,
|
||||
rootp);
|
||||
/*
|
||||
* Parent was reparented by the
|
||||
* rotation, so the new grandparent
|
||||
* needs to be noted. Grandpa is dead,
|
||||
* long live grandpa.
|
||||
*/
|
||||
grandparent = sibling;
|
||||
sibling = RIGHT(parent);
|
||||
}
|
||||
|
||||
if (IS_BLACK(LEFT(sibling)) &&
|
||||
IS_BLACK(RIGHT(sibling))) {
|
||||
MAKE_RED(sibling);
|
||||
child = parent;
|
||||
|
||||
} else {
|
||||
|
||||
if (IS_BLACK(RIGHT(sibling))) {
|
||||
MAKE_BLACK(LEFT(sibling));
|
||||
MAKE_RED(sibling);
|
||||
rotate_right(sibling,
|
||||
grandparent,
|
||||
rotate_right(sibling, parent,
|
||||
rootp);
|
||||
sibling = RIGHT(parent);
|
||||
}
|
||||
|
||||
COLOR(sibling) = COLOR(parent);
|
||||
MAKE_BLACK(parent);
|
||||
MAKE_BLACK(RIGHT(sibling));
|
||||
@ -1698,28 +1711,44 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
|
||||
rootp);
|
||||
child = *rootp;
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Child is parent's right child.
|
||||
* Everything is doen the same as above,
|
||||
* except mirrored.
|
||||
*/
|
||||
sibling = LEFT(parent);
|
||||
|
||||
if (IS_RED(sibling)) {
|
||||
MAKE_BLACK(sibling);
|
||||
MAKE_RED(parent);
|
||||
rotate_right(parent, grandparent,
|
||||
rootp);
|
||||
/*
|
||||
* Parent was reparented by the
|
||||
* rotation, so the new grandparent
|
||||
* needs to be noted. Grandma is dead,
|
||||
* long live grandma.
|
||||
*/
|
||||
grandparent = sibling;
|
||||
sibling = LEFT(parent);
|
||||
}
|
||||
|
||||
if (IS_BLACK(LEFT(sibling)) &&
|
||||
IS_BLACK(RIGHT(sibling))) {
|
||||
MAKE_RED(sibling);
|
||||
child = parent;
|
||||
|
||||
} else {
|
||||
if (IS_BLACK(LEFT(sibling))) {
|
||||
MAKE_BLACK(RIGHT(sibling));
|
||||
MAKE_RED(sibling);
|
||||
rotate_left(sibling,
|
||||
grandparent,
|
||||
rotate_left(sibling, parent,
|
||||
rootp);
|
||||
sibling = LEFT(parent);
|
||||
}
|
||||
|
||||
COLOR(sibling) = COLOR(parent);
|
||||
MAKE_BLACK(parent);
|
||||
MAKE_BLACK(LEFT(sibling));
|
||||
@ -1728,7 +1757,6 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
|
||||
child = *rootp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (IS_RED(child))
|
||||
|
Loading…
x
Reference in New Issue
Block a user