mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 07:35:26 +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:
@@ -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))
|
||||||
|
Reference in New Issue
Block a user