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

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Aug 22 12:24:42 CDT 2012


Author: rmudgett
Date: Wed Aug 22 12:24:38 2012
New Revision: 371628

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=371628
Log:
Check hash bucket list links and red-black tree links better.

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=371628&r1=371627&r2=371628
==============================================================================
--- team/rmudgett/ao2_red_black/main/astobj2.c (original)
+++ team/rmudgett/ao2_red_black/main/astobj2.c Wed Aug 22 12:24:38 2012
@@ -2703,130 +2703,129 @@
 {
 	int bucket_exp;
 	int bucket;
-	int count_node_forward;
-	int count_node_backward;
-	int count_obj_forward;
-	int count_obj_backward;
+	int count_node;
+	int count_obj;
 	int count_total_obj;
+	void *obj_last;
 	struct hash_bucket_node *node;
-	struct hash_bucket_node *last;
+	struct hash_bucket_node *prev;
+	struct hash_bucket_node *next;
 
 	count_total_obj = 0;
 
 	/* For each bucket in the container. */
 	for (bucket = 0; bucket < self->n_buckets; ++bucket) {
-		count_node_forward = 0;
-		count_node_backward = 0;
-		count_obj_forward = 0;
-		count_obj_backward = 0;
-
-		/* Check forward list. */
-		last = NULL;
-		for (node = AST_DLLIST_FIRST(&self->buckets[bucket].list);
-			node;
-			node = AST_DLLIST_NEXT(node, links)) {
-			++count_node_forward;
+		if (!AST_DLLIST_FIRST(&self->buckets[bucket].list)
+			&& !AST_DLLIST_LAST(&self->buckets[bucket].list)) {
+			/* The bucket list is empty. */
+			continue;
+		}
+
+		count_node = 0;
+		count_obj = 0;
+		obj_last = NULL;
+
+		/* Check bucket list links and nodes. */
+		node = AST_DLLIST_LAST(&self->buckets[bucket].list);
+		if (!node) {
+			ast_log(LOG_ERROR, "Bucket %d list tail is NULL when it should not be!\n",
+				bucket);
+			return -1;
+		}
+		if (AST_DLLIST_NEXT(node, links)) {
+			ast_log(LOG_ERROR, "Bucket %d list tail node is not the last node!\n",
+				bucket);
+			return -1;
+		}
+		node = AST_DLLIST_FIRST(&self->buckets[bucket].list);
+		if (!node) {
+			ast_log(LOG_ERROR, "Bucket %d list head is NULL when it should not be!\n",
+				bucket);
+			return -1;
+		}
+		if (AST_DLLIST_PREV(node, links)) {
+			ast_log(LOG_ERROR, "Bucket %d list head node is not the first node!\n",
+				bucket);
+			return -1;
+		}
+		for (; node; node = next) {
+			/* Check backward link. */
+			prev = AST_DLLIST_PREV(node, links);
+			if (prev) {
+				if (node != AST_DLLIST_NEXT(prev, links)) {
+					ast_log(LOG_ERROR, "Bucket %d list node's prev node does not link back!\n",
+						bucket);
+					return -1;
+				}
+			} else if (node != AST_DLLIST_FIRST(&self->buckets[bucket].list)) {
+				ast_log(LOG_ERROR, "Bucket %d backward list chain is broken!\n",
+					bucket);
+				return -1;
+			}
+
+			/* Check forward link. */
+			next = AST_DLLIST_NEXT(node, links);
+			if (next) {
+				if (node != AST_DLLIST_PREV(next, links)) {
+					ast_log(LOG_ERROR, "Bucket %d list node's next node does not link back!\n",
+						bucket);
+					return -1;
+				}
+			} else if (node != AST_DLLIST_LAST(&self->buckets[bucket].list)) {
+				ast_log(LOG_ERROR, "Bucket %d forward list chain is broken!\n",
+					bucket);
+				return -1;
+			}
 
 			if (bucket != node->my_bucket) {
-				ast_log(LOG_ERROR, "Node not in correct bucket! B:%d != N:%d (forward)\n",
+				ast_log(LOG_ERROR, "Bucket %d node claims to be in bucket %d!\n",
 					bucket, node->my_bucket);
 				return -1;
 			}
 
+			++count_node;
 			if (!node->common.obj) {
 				/* Node is empty. */
 				continue;
 			}
-			++count_obj_forward;
+			++count_obj;
 
 			/* Check container hash key for expected bucket. */
 			bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_POINTER));
 			bucket_exp %= self->n_buckets;
 			if (bucket != bucket_exp) {
-				ast_log(LOG_ERROR, "Hash does not match bucket! B:%d != H:%d (forward)\n",
+				ast_log(LOG_ERROR, "Bucket %d node hashes to bucket %d!\n",
 					bucket, bucket_exp);
 				return -1;
 			}
 
 			/* Check sort if configured. */
-			if (last && self->common.sort_fn) {
-				if (self->common.sort_fn(last->common.obj, node->common.obj, OBJ_POINTER) > 0) {
-					ast_log(LOG_ERROR, "Bucket nodes out of order in bucket %d! (forward)\n",
+			if (self->common.sort_fn) {
+				if (obj_last
+					&& self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
+					ast_log(LOG_ERROR, "Bucket %d nodes out of sorted order!\n",
 						bucket);
 					return -1;
 				}
-			}
-			last = node;
-		}
-
-		/* Check backward list. */
-		last = NULL;
-		for (node = AST_DLLIST_LAST(&self->buckets[bucket].list);
-			node;
-			node = AST_DLLIST_PREV(node, links)) {
-			++count_node_backward;
-
-			if (bucket != node->my_bucket) {
-				ast_log(LOG_ERROR, "Node not in correct bucket! B:%d != N:%d (backward)\n",
-					bucket, node->my_bucket);
-				return -1;
-			}
-
-			if (!node->common.obj) {
-				/* Node is empty. */
-				continue;
-			}
-			++count_obj_backward;
-
-			/* Check container hash key for expected bucket. */
-			bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_POINTER));
-			bucket_exp %= self->n_buckets;
-			if (bucket != bucket_exp) {
-				ast_log(LOG_ERROR, "Hash does not match bucket! B:%d != H:%d (backward)\n",
-					bucket, bucket_exp);
-				return -1;
-			}
-
-			/* Check sort if configured. */
-			if (last && self->common.sort_fn) {
-				if (self->common.sort_fn(node->common.obj, last->common.obj, OBJ_POINTER) > 0) {
-					ast_log(LOG_ERROR, "Bucket nodes out of order in bucket %d! (backward)\n",
-						bucket);
-					return -1;
-				}
-			}
-			last = node;
-		}
-
-		/* Check bucket forward/backward node count. */
-		if (count_node_forward != count_node_backward) {
-			ast_log(LOG_ERROR, "Forward/backward node count does not match! F:%d != B:%d\n",
-				count_node_forward, count_node_backward);
+				obj_last = node->common.obj;
+			}
+		}
+
+		/* Check bucket obj count statistic. */
+		if (count_obj != self->buckets[bucket].elements) {
+			ast_log(LOG_ERROR, "Bucket %d object count of %d does not match stat of %d!\n",
+				bucket, count_obj, self->buckets[bucket].elements);
 			return -1;
 		}
 
-		/* Check bucket forward/backward obj count. */
-		if (count_obj_forward != count_obj_backward) {
-			ast_log(LOG_ERROR, "Forward/backward object count does not match! F:%d != B:%d\n",
-				count_obj_forward, count_obj_backward);
-			return -1;
-		}
-
-		/* Check bucket obj count statistic. */
-		if (count_obj_forward != self->buckets[bucket].elements) {
-			ast_log(LOG_ERROR, "Bucket object count stat does not match! C:%d != S:%d\n",
-				count_obj_forward, self->buckets[bucket].elements);
-			return -1;
-		}
-
 		/* Accumulate found object counts. */
-		count_total_obj += count_obj_forward;
+		count_total_obj += count_obj;
 	}
 
 	/* Check total obj count. */
 	if (count_total_obj != ao2_container_count(&self->common)) {
 		ast_log(LOG_ERROR,
-			"Total object count does not match ao2_container_count()! T:%d != C:%d\n",
+			"Total object count of %d does not match ao2_container_count() of %d!\n",
 			count_total_obj, ao2_container_count(&self->common));
 		return -1;
 	}
@@ -4164,87 +4163,69 @@
 static int rb_ao2_integrity(struct ao2_container_rbtree *self)
 {
 /* BUGBUG rb_ao2_integrity not written */
+
+	int count_node;
+	int count_obj;
+	void *obj_last;
+	struct rbtree_node *node;
+
+	count_node = 0;
+	count_obj = 0;
+
+	if (self->root) {
+		/* Check tree links. */
+		if (self->root->parent) {
+			ast_log(LOG_ERROR, "Red-black tree root is not a root node!\n");
+			return -1;
+		}
+		node = self->root;
+		do {
+			if (node->left && node->left->parent != node) {
+				ast_log(LOG_ERROR, "Red-black tree node's left child does not link back!\n");
+				return -1;
+			}
+			if (node->right && node->right->parent != node) {
+				ast_log(LOG_ERROR, "Red-black tree node's right child does not link back!\n");
+				return -1;
+			}
+
+			/* Count nodes and objects. */
+			++count_node;
+			if (node->common.obj) {
+				++count_obj;
+			}
+
+			node = rb_node_pre(node);
+		} while (node);
+
+		/* Check forward list. */
+		obj_last = NULL;
+		for (node = rb_node_most_left(self->root); node; node = rb_node_next(node)) {
+			if (!node->common.obj) {
+				/* Node is empty. */
+				continue;
+			}
+
+			/* Check sort order. */
+			if (obj_last) {
+				if (self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
+					ast_log(LOG_ERROR, "Red-black tree nodes out of sorted order!\n");
+					return -1;
+				}
+			}
+			obj_last = node->common.obj;
+		}
+
 /* BUGBUG Check red/black node flags. */
-
-	int count_node_forward;
-	int count_node_backward;
-	int count_obj_forward;
-	int count_obj_backward;
-	struct rbtree_node *node;
-	struct rbtree_node *last;
-
-	count_node_forward = 0;
-	count_node_backward = 0;
-	count_obj_forward = 0;
-	count_obj_backward = 0;
-
-	if (self->root) {
+		/* Check red/black node flags. */
 		if (self->root->is_red) {
 			ast_log(LOG_ERROR, "Red-black tree root is red!\n");
 			return -1;
 		}
-
-		/* Check forward list. */
-		last = NULL;
-		for (node = rb_node_most_left(self->root);
-			node;
-			node = rb_node_next(node)) {
-			++count_node_forward;
-
-			if (!node->common.obj) {
-				/* Node is empty. */
-				continue;
-			}
-			++count_obj_forward;
-
-			/* Check sort order. */
-			if (last) {
-				if (self->common.sort_fn(last->common.obj, node->common.obj, OBJ_POINTER) > 0) {
-					ast_log(LOG_ERROR, "Red-black tree nodes out of order (forward)!\n");
-					return -1;
-				}
-			}
-			last = node;
-		}
-
-		/* Check backward list. */
-		last = NULL;
-		for (node = rb_node_most_right(self->root);
-			node;
-			node = rb_node_prev(node)) {
-			++count_node_backward;
-
-			if (!node->common.obj) {
-				/* Node is empty. */
-				continue;
-			}
-			++count_obj_backward;
-
-			/* Check sort order. */
-			if (last) {
-				if (self->common.sort_fn(node->common.obj, last->common.obj, OBJ_POINTER) > 0) {
-					ast_log(LOG_ERROR, "Red-black tree nodes out of order (backward)!\n");
-					return -1;
-				}
-			}
-			last = node;
-		}
-
-		/* Check forward/backward node count. */
-		if (count_node_forward != count_node_backward) {
-			ast_log(LOG_ERROR, "Forward/backward node count does not match!\n");
-			return -1;
-		}
-
-		/* Check forward/backward obj count. */
-		if (count_obj_forward != count_obj_backward) {
-			ast_log(LOG_ERROR, "Forward/backward object count does not match!\n");
-			return -1;
-		}
 	}
 
 	/* Check total obj count. */
-	if (count_obj_forward != ao2_container_count(&self->common)) {
+	if (count_obj != ao2_container_count(&self->common)) {
 		ast_log(LOG_ERROR, "Total object count does not match ao2_container_count()!\n");
 		return -1;
 	}




More information about the svn-commits mailing list