2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 07:35:26 +00:00
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:
David Lawrence
1999-10-16 19:44:54 +00:00
parent 80bd254851
commit 401fc772b1

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * 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 */ /* Principal Authors: DCL */
@@ -147,6 +147,8 @@ Name(dns_rbtnode_t *node) {
return (name); return (name);
} }
static void dns_rbt_printnodename(dns_rbtnode_t *node);
#endif #endif
#if defined(ISC_MEM_DEBUG) || defined(RBT_MEM_TEST) #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. * Found an exact match.
*/ */
chain->end = current; chain->end = current;
chain->level_matches = chain->level_count == 0 ? 0 : chain->level_matches = chain->level_count;
chain->level_count - 1;
if (foundname != NULL) if (foundname != NULL)
result = chain_name(chain, foundname, ISC_TRUE); 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(node != NULL);
REQUIRE(rootp != NULL); REQUIRE(rootp != NULL);
REQUIRE(parent == NULL ||
RIGHT(parent) == node || LEFT(parent) == node);
child = RIGHT(node); child = RIGHT(node);
REQUIRE(child != NULL); 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(node != NULL);
REQUIRE(rootp != NULL); REQUIRE(rootp != NULL);
REQUIRE(parent == NULL ||
RIGHT(parent) == node || LEFT(parent) == node);
child = LEFT(node); child = LEFT(node);
REQUIRE(child != NULL); 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; * The successor cannot possibly have a left child;
* if there is any child, it is on the right. * if there is any child, it is on the right.
*/ */
if (RIGHT(successor)) if (RIGHT(successor) != NULL)
child = RIGHT(successor); child = RIGHT(successor);
/* Swap the two nodes; it would be simpler to just replace /* 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 * but this rigamarole is done so the caller has complete
* control over the pointers (and memory allocation) of * control over the pointers (and memory allocation) of
* all of nodes. If just the key value were removed from * all of nodes. If just the key value were removed from
* the tree, the pointer to the node would would be * the tree, the pointer to the node would be unchanged.
* unchanged.
*/ */
/* /*
* First, put the successor in the tree location of the * First, put the successor in the tree location of the
* node to be deleted. * node to be deleted.
*/ */
memcpy(tmp, successor, sizeof(dns_rbtnode_t)); memcpy(tmp, successor, sizeof(dns_rbtnode_t));
chain->ancestors[depth] = successor; 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. * Original location of successor node has no left.
*/ */
LEFT(delete) = NULL; LEFT(delete) = NULL;
RIGHT(delete) = RIGHT(tmp); RIGHT(delete) = RIGHT(tmp);
COLOR(delete) = COLOR(tmp); COLOR(delete) = COLOR(tmp);
@@ -1671,26 +1673,37 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
if (LEFT(parent) == child) { if (LEFT(parent) == child) {
sibling = RIGHT(parent); sibling = RIGHT(parent);
if (IS_RED(sibling)) { if (IS_RED(sibling)) {
MAKE_BLACK(sibling); MAKE_BLACK(sibling);
MAKE_RED(parent); MAKE_RED(parent);
rotate_left(parent, grandparent, rotate_left(parent, grandparent,
rootp); 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); sibling = RIGHT(parent);
} }
if (IS_BLACK(LEFT(sibling)) && if (IS_BLACK(LEFT(sibling)) &&
IS_BLACK(RIGHT(sibling))) { IS_BLACK(RIGHT(sibling))) {
MAKE_RED(sibling); MAKE_RED(sibling);
child = parent; child = parent;
} else { } else {
if (IS_BLACK(RIGHT(sibling))) { if (IS_BLACK(RIGHT(sibling))) {
MAKE_BLACK(LEFT(sibling)); MAKE_BLACK(LEFT(sibling));
MAKE_RED(sibling); MAKE_RED(sibling);
rotate_right(sibling, rotate_right(sibling, parent,
grandparent,
rootp); rootp);
sibling = RIGHT(parent); sibling = RIGHT(parent);
} }
COLOR(sibling) = COLOR(parent); COLOR(sibling) = COLOR(parent);
MAKE_BLACK(parent); MAKE_BLACK(parent);
MAKE_BLACK(RIGHT(sibling)); MAKE_BLACK(RIGHT(sibling));
@@ -1698,28 +1711,44 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
rootp); rootp);
child = *rootp; child = *rootp;
} }
} else { } else {
/*
* Child is parent's right child.
* Everything is doen the same as above,
* except mirrored.
*/
sibling = LEFT(parent); sibling = LEFT(parent);
if (IS_RED(sibling)) { if (IS_RED(sibling)) {
MAKE_BLACK(sibling); MAKE_BLACK(sibling);
MAKE_RED(parent); MAKE_RED(parent);
rotate_right(parent, grandparent, rotate_right(parent, grandparent,
rootp); 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); sibling = LEFT(parent);
} }
if (IS_BLACK(LEFT(sibling)) && if (IS_BLACK(LEFT(sibling)) &&
IS_BLACK(RIGHT(sibling))) { IS_BLACK(RIGHT(sibling))) {
MAKE_RED(sibling); MAKE_RED(sibling);
child = parent; child = parent;
} else { } else {
if (IS_BLACK(LEFT(sibling))) { if (IS_BLACK(LEFT(sibling))) {
MAKE_BLACK(RIGHT(sibling)); MAKE_BLACK(RIGHT(sibling));
MAKE_RED(sibling); MAKE_RED(sibling);
rotate_left(sibling, rotate_left(sibling, parent,
grandparent,
rootp); rootp);
sibling = LEFT(parent); sibling = LEFT(parent);
} }
COLOR(sibling) = COLOR(parent); COLOR(sibling) = COLOR(parent);
MAKE_BLACK(parent); MAKE_BLACK(parent);
MAKE_BLACK(LEFT(sibling)); MAKE_BLACK(LEFT(sibling));
@@ -1728,7 +1757,6 @@ dns_rbt_deletefromlevel(dns_rbt_t *rbt, dns_rbtnode_t *delete,
child = *rootp; child = *rootp;
} }
} }
} }
if (IS_RED(child)) if (IS_RED(child))