[asterisk-commits] rmudgett: branch rmudgett/ao2_red_black r371628 - /team/rmudgett/ao2_red_blac...
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list