[asterisk-commits] rmudgett: branch rmudgett/ao2_red_black r371818 - /team/rmudgett/ao2_red_blac...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Aug 28 02:20:49 CDT 2012
Author: rmudgett
Date: Tue Aug 28 02:20:45 2012
New Revision: 371818
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=371818
Log:
Fix rbtree deletion. Added debug code.
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=371818&r1=371817&r2=371818
==============================================================================
--- team/rmudgett/ao2_red_black/main/astobj2.c (original)
+++ team/rmudgett/ao2_red_black/main/astobj2.c Tue Aug 28 02:20:45 2012
@@ -1039,6 +1039,9 @@
res = 0;
node = self->v_table->new_node(self, obj_new, tag, file, line, func);
if (node) {
+ if (ao2_container_check(self, OBJ_NOLOCK)) {/* BUGBUG */
+ ast_log(LOG_NOTICE, "BUGBUG integrity failed before insert.\n");
+ }
/* Insert the new node. */
switch (self->v_table->insert(self, node)) {
case AO2_CONTAINER_INSERT_NODE_INSERTED:
@@ -1063,6 +1066,9 @@
case AO2_CONTAINER_INSERT_NODE_REJECTED:
__ao2_ref(node, -1);
break;
+ }
+ if (ao2_container_check(self, OBJ_NOLOCK)) {/* BUGBUG */
+ ast_log(LOG_NOTICE, "BUGBUG integrity failed after insert.\n");
}
}
@@ -3482,6 +3488,30 @@
child->right = node;
}
+#if 0
+/*!
+ * \internal
+ * \brief Dump the tree structure.
+ * \since 12.0.0
+ *
+ * \param self Container to operate upon.
+ * \param header What is being dumped.
+ *
+ * \return Nothing
+ */
+static void rb_dump(struct ao2_container_rbtree *self, const char *header)
+{
+ struct rbtree_node *node;
+
+ printf("%s\n", header);
+ printf("%16s, %16s, %16s, %16s, %c, %16s\n", "Node", "Parent", "Left", "Right", 'T', "Obj");
+ for (node = self->root; node; node = rb_node_pre(node)) {
+ printf("%16p, %16p, %16p, %16p, %c, %16p\n",
+ node, node->parent, node->left, node->right, node->is_red ? 'R' : 'B', node->common.obj);
+ }
+}
+#endif
+
/*!
* \internal
* \brief Create an empty copy of this container.
@@ -3579,12 +3609,11 @@
sibling->is_red = 1;
child = child->parent;
} else {
- if (!sibling->right || !sibling->right->is_red) {
+ if ((sibling->left && sibling->left->is_red)
+ && (!sibling->right || !sibling->right->is_red)) {
/* Case 3: The sibling is black, its left child is red, and its right child is black. */
AO2_DEVMODE_STAT(++self->stats.fixup_delete_left[2]);
- if (sibling->left) {
- sibling->left->is_red = 0;
- }
+ sibling->left->is_red = 0;
sibling->is_red = 1;
rb_rotate_right(self, sibling);
sibling = child->parent->right;
@@ -3620,12 +3649,11 @@
sibling->is_red = 1;
child = child->parent;
} else {
- if (!sibling->left || !sibling->left->is_red) {
+ if ((sibling->right && sibling->right->is_red)
+ && (!sibling->left || !sibling->left->is_red)) {
/* Case 3: The sibling is black, its right child is red, and its left child is black. */
AO2_DEVMODE_STAT(++self->stats.fixup_delete_right[2]);
- if (sibling->right) {
- sibling->right->is_red = 0;
- }
+ sibling->right->is_red = 0;
sibling->is_red = 1;
rb_rotate_left(self, sibling);
sibling = child->parent->left;
@@ -3643,6 +3671,11 @@
}
}
}
+
+ /*
+ * Case 2 could leave the child node red and it needs to leave
+ * with it black.
+ */
child->is_red = 0;
}
@@ -3692,25 +3725,30 @@
next->parent->right = next;
}
next->left->parent = next;
- next->right->parent = next;
-
- /* Link back in the doomed node. (It has no left child) */
- if (doomed->parent->left == next) {
- /* The next node was not the right child of doomed. */
+ if (next->right == next) {
+ /* The next node was the right child of doomed. */
+ next->right = doomed;
+ doomed->parent = next;
+ } else {
+ next->right->parent = next;
doomed->parent->left = doomed;
}
/*
+ * The doomed node has no left child now.
+ *
* We don't have to link the right child back in with doomed
* since we are going to link it with doomed's parent anyway.
*/
child = doomed->right;
+ ast_assert(doomed->parent != doomed);/* BUGBUG */
} else {
/* Doomed has at most one child. */
child = doomed->left;
if (!child) {
child = doomed->right;
}
+ ast_assert(doomed->parent != doomed);/* BUGBUG */
}
if (child) {
AO2_DEVMODE_STAT(++self->stats.delete_children[1]);
@@ -3793,7 +3831,17 @@
my_container = (struct ao2_container_rbtree *) doomed->common.my_container;
adjust_lock(my_container, AO2_LOCK_REQ_WRLOCK, 1);
+ if (!my_container->common.destroying
+ && ao2_container_check(doomed->common.my_container, OBJ_NOLOCK)) {/* BUGBUG */
+ ast_log(LOG_NOTICE, "BUGBUG integrity failed before delete.\n");
+ }
+// rb_dump(my_container, "Pre deletion");
+// printf("%16p Deleting node\n", doomed);
rb_delete_node(my_container, doomed);
+ if (!my_container->common.destroying
+ && ao2_container_check(doomed->common.my_container, OBJ_NOLOCK)) {/* BUGBUG */
+ ast_log(LOG_NOTICE, "BUGBUG integrity failed after delete.\n");
+ }
}
/*
More information about the asterisk-commits
mailing list