[svn-commits] rmudgett: branch rmudgett/ao2_red_black r371780 - /team/rmudgett/ao2_red_blac...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Aug 27 14:32:38 CDT 2012


Author: rmudgett
Date: Mon Aug 27 14:32:34 2012
New Revision: 371780

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=371780
Log:
Fix property 5 quick check and add complete property 5 check.

Modified:
    team/rmudgett/ao2_red_black/main/astobj2.c

Modified: team/rmudgett/ao2_red_black/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_red_black/main/astobj2.c?view=diff&rev=371780&r1=371779&r2=371780
==============================================================================
--- team/rmudgett/ao2_red_black/main/astobj2.c (original)
+++ team/rmudgett/ao2_red_black/main/astobj2.c Mon Aug 27 14:32:34 2012
@@ -4656,6 +4656,50 @@
 #if defined(AST_DEVMODE)
 /*!
  * \internal
+ * \brief Check the black height of the given node.
+ * \since 12.0.0
+ *
+ * \param node Node to check black height.
+ *
+ * \retval black-height of node on success.
+ * \retval -1 on error.  Node black height did not balance.
+ */
+static int rb_check_black_height(struct rbtree_node *node)
+{
+	int height_left;
+	int height_right;
+
+	if (!node) {
+		/* A NULL child is a black node. */
+		return 0;
+	}
+
+	height_left = rb_check_black_height(node->left);
+	if (height_left < 0) {
+		return -1;
+	}
+	height_right = rb_check_black_height(node->right);
+	if (height_right < 0) {
+		return -1;
+	}
+	if (height_left != height_right) {
+		ast_log(LOG_ERROR,
+			"Tree node black height of children does not match! L:%d != R:%d\n",
+			height_left, height_right);
+		return -1;
+	}
+	if (!node->is_red) {
+		/* The node itself is black. */
+		++height_left;
+	}
+	return height_left;
+}
+
+#endif	/* defined(AST_DEVMODE) */
+
+#if defined(AST_DEVMODE)
+/*!
+ * \internal
  * \brief Perform an integrity check on the specified container.
  * \since 12.0.0
  *
@@ -4737,16 +4781,27 @@
 				}
 			} else {
 				/*
-				 * A black node must have two black children, or two red
-				 * children, or one red child, or no children.
+				 * A black node must have two children, or one red child, or no
+				 * children.  If the black node has two children and only one of
+				 * them is red, that red child must have two children.
 				 */
 				if (node->left && node->right) {
 					/* Node has two children. */
 					if (node->left->is_red != node->right->is_red) {
-						/* Violation rbtree property 5. */
-						ast_log(LOG_ERROR,
-							"Tree node is black and the left child's color doesn't match the right child!\n");
-						res = -1;
+						/* The children are not the same color. */
+						struct rbtree_node *red;
+
+						if (node->left->is_red) {
+							red = node->left;
+						} else {
+							red = node->right;
+						}
+						if (!red->left || !red->right) {
+							/* Violation rbtree property 5. */
+							ast_log(LOG_ERROR,
+								"Tree node is black and the red child does not have two children!\n");
+							res = -1;
+						}
 					}
 				} else if ((node->left && !node->left->is_red)
 					|| (node->right && !node->right->is_red)) {
@@ -4780,6 +4835,12 @@
 				}
 			}
 			obj_last = node->common.obj;
+		}
+
+		/* Completely check property 5 */
+		if (!res && rb_check_black_height(self->root) < 0) {
+			/* Violation rbtree property 5. */
+			res = -1;
 		}
 	}
 




More information about the svn-commits mailing list