static void traverse_elements(void) { struct ht_element *el; int c=0; struct ast_hashtab_iter *it = ast_hashtab_start_write_traversal(glob_hashtab); #ifdef DEBUG printf("Traverse hashtab\n"); #endif while ((el = ast_hashtab_next(it))) { c++; } ast_hashtab_end_traversal(it); els_traversals++; /* unprotected, sometimes off, but, not really important, either */ }
/*! Continuously iterate through all the entries in the hash */ static void *hash_test_count(void *d) { const struct hash_test *data = d; int count = 0; int last_count = 0; while (count < data->max_grow) { struct ast_hashtab_iter *it = ast_hashtab_start_write_traversal(data->to_be_thrashed); char *ht = ast_hashtab_next(it); last_count = count; count = 0; while (ht) { /* only count keys added by grow thread */ if (strncmp(ht, "key0", 4) == 0) { ++count; } ht = ast_hashtab_next(it); } ast_hashtab_end_traversal(it); if (last_count == count) { /* Give other threads ample chance to run, note that using sched_yield here does not * provide enough of a chance and can cause this thread to starve others. */ usleep(1); } else if (last_count > count) { /* Make sure the hashtable never shrinks */ return "hashtab unexpectedly shrank"; } if (is_timed_out(data)) { return "Count timed out"; } } /* Successfully iterated over all of the expected elements */ return NULL; }
int main(int argc,char **argv) { char linebuffer[300]; FILE *ifile = fopen("/tmp/refs", "r"); char *t; unsigned int un; struct rc_obj *curr_obj, *count1_obj; struct rc_obj lookup; struct ast_hashtab_iter *it; struct ast_hashtab *objhash; if (!ifile) { printf("Sorry, Cannot open /tmp/refs!\n"); exit(10); } objhash = ast_hashtab_create(9000, hashtab_compare_rc, ast_hashtab_resize_java, ast_hashtab_newsize_java, hashtab_hash_rc, 1); while (fgets(linebuffer, sizeof(linebuffer), ifile)) { /* collect data about the entry */ un = strtoul(linebuffer, &t, 16); lookup.addr = un; lookup.count = 1; count1_obj = ast_hashtab_lookup(objhash, &lookup); if (count1_obj) { /* there IS a count1 obj, so let's see which one we REALLY want */ if (*(t+1) == '=') { /* start a new object! */ curr_obj = alloc_obj(un, ++count1_obj->last_count); /* put it in the hashtable */ ast_hashtab_insert_safe(objhash, curr_obj); } else { if (count1_obj->last_count > 1) { lookup.count = count1_obj->last_count; curr_obj = ast_hashtab_lookup(objhash, &lookup); } else { curr_obj = count1_obj; } } } else { /* NO obj at ALL? -- better make one! */ if (*(t+1) != '=') { printf("BAD: object %x appears without previous allocation marker!\n", un); } curr_obj = count1_obj = alloc_obj(un, 1); /* put it in the hashtable */ ast_hashtab_insert_safe(objhash, curr_obj); } if (*(t+1) == '+' || *(t+1) == '-' ) { curr_obj->total_refcount += strtol(t+1, NULL, 10); } else if (*(t+1) == '*') { curr_obj->destroy_count++; } add_to_hist(linebuffer, curr_obj); } fclose(ifile); /* traverse the objects and check for problems */ it = ast_hashtab_start_traversal(objhash); while ((curr_obj = ast_hashtab_next(it))) { if (curr_obj->total_refcount != 0 || curr_obj->destroy_count != 1) { struct rc_hist *h; if (curr_obj->total_refcount != 0) printf("Problem: net Refcount not zero for object %x\n", curr_obj->addr); if (curr_obj->destroy_count > 1 ) printf("Problem: Object %x destroyed more than once!\n", curr_obj->addr); printf("Object %x history:\n", curr_obj->addr); for(h=curr_obj->hist;h;h=h->next) { printf(" %s", h->desc); } printf("==============\n"); } } ast_hashtab_end_traversal(it); return 0; }