AIX, and threaded hash table test.

git-svn-id: file:///svn/unbound/trunk@187 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-03-22 11:09:05 +00:00
parent 9f413c07e0
commit d39976b2e1
5 changed files with 122 additions and 17 deletions

View file

@ -90,7 +90,7 @@ CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT])
CHECK_COMPILER_FLAG_NEEDED(-std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600, CHECK_COMPILER_FLAG_NEEDED(-std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE,
[ [
#include "confdefs.h" #include "confdefs.h"
#include <stdlib.h> #include <stdlib.h>
@ -121,7 +121,7 @@ int test() {
str = gai_strerror(0); str = gai_strerror(0);
return a; return a;
} }
], [CFLAGS="$CFLAGS -std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"]) ], [CFLAGS="$CFLAGS -std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
CHECK_COMPILER_FLAG_NEEDED(-std=c99, CHECK_COMPILER_FLAG_NEEDED(-std=c99,
[ [

View file

@ -1,3 +1,10 @@
22 March 2007: Wouter
- AIX configure check.
- lock-verify can handle references to locks that are created
in files it has not yet read in.
- threaded hash table test.
- unit test runs lock-verify afterwards and checks result.
21 March 2007: Wouter 21 March 2007: Wouter
- unit test of hash table, fixup locking problem in table_grow(). - unit test of hash table, fixup locking problem in table_grow().
- fixup accounting of sizes for removing items from hashtable. - fixup accounting of sizes for removing items from hashtable.

View file

@ -155,7 +155,7 @@ read_header(FILE* in)
if( abs((int)(the_time - t)) > 3600) if( abs((int)(the_time - t)) > 3600)
fatal_exit("input files from different times: %u %u", fatal_exit("input files from different times: %u %u",
(unsigned)the_time, (unsigned)t); (unsigned)the_time, (unsigned)t);
printf(" trace of thread %d\n", thrno); printf(" trace of thread %u:%d\n", (unsigned)p, thrno);
} }
return 1; return 1;
} }
@ -194,9 +194,34 @@ static void read_create(rbtree_t* all, FILE* in)
fatal_exit("fread: %s", strerror(errno)); fatal_exit("fread: %s", strerror(errno));
o->smaller = rbtree_create(order_lock_cmp); o->smaller = rbtree_create(order_lock_cmp);
o->node.key = &o->id; o->node.key = &o->id;
if(!rbtree_insert(all, &o->node)) {
/* already inserted */
struct order_lock* a = (struct order_lock*)rbtree_search(all,
&o->id);
log_assert(a);
a->create_file = o->create_file;
a->create_line = o->create_line;
free(o->smaller);
free(o);
o = a;
}
if(verb) printf("read create %u %u %s %d\n",
(unsigned)o->id.thr, (unsigned)o->id.instance,
o->create_file, o->create_line);
}
/** insert lock entry (empty) into list */
static struct order_lock*
insert_lock(rbtree_t* all, struct order_id* id)
{
struct order_lock* o = calloc(1, sizeof(struct order_lock));
if(!o) fatal_exit("malloc failure");
o->smaller = rbtree_create(order_lock_cmp);
o->id = *id;
o->node.key = &o->id;
if(!rbtree_insert(all, &o->node)) if(!rbtree_insert(all, &o->node))
fatal_exit("lock created twice"); fatal_exit("insert fail should not happen");
if(verb) printf("read create %s %d\n", o->create_file, o->create_line); return o;
} }
/** read lock entry */ /** read lock entry */
@ -214,12 +239,16 @@ static void read_lock(rbtree_t* all, FILE* in, int val)
!readup_str(&ref->file, in) || !readup_str(&ref->file, in) ||
fread(&ref->line, sizeof(int), 1, in) != 1) fread(&ref->line, sizeof(int), 1, in) != 1)
fatal_exit("fread: %s", strerror(errno)); fatal_exit("fread: %s", strerror(errno));
if(verb) printf("read lock %s %d\n", ref->file, ref->line); if(verb) printf("read lock %u %u %u %u %s %d\n",
(unsigned)prev_id.thr, (unsigned)prev_id.instance,
(unsigned)now_id.thr, (unsigned)now_id.instance,
ref->file, ref->line);
/* find the two locks involved */ /* find the two locks involved */
prev = (struct order_lock*)rbtree_search(all, &prev_id); prev = (struct order_lock*)rbtree_search(all, &prev_id);
now = (struct order_lock*)rbtree_search(all, &now_id); now = (struct order_lock*)rbtree_search(all, &now_id);
if(!prev || !now) /* if not there - insert 'em */
fatal_exit("Could not find locks involved."); if(!prev) prev = insert_lock(all, &prev_id);
if(!now) now = insert_lock(all, &now_id);
ref->lock = prev; ref->lock = prev;
ref->node.key = &prev->id; ref->node.key = &prev->id;
if(!rbtree_insert(now->smaller, &ref->node)) { if(!rbtree_insert(now->smaller, &ref->node)) {
@ -326,6 +355,10 @@ static void check_order_lock(struct order_lock* lock)
start.file = lock->create_file; start.file = lock->create_file;
start.line = lock->create_line; start.line = lock->create_line;
if(!lock->create_file)
log_err("lock %u %u does not have create info",
(unsigned)lock->id.thr, (unsigned)lock->id.instance);
/* depth first search to find cycle with this lock at head */ /* depth first search to find cycle with this lock at head */
lock->dfs_next = NULL; lock->dfs_next = NULL;
search_cycle(&start, 0, &start); search_cycle(&start, 0, &start);
@ -343,7 +376,7 @@ static void check_order(rbtree_t* all_locks)
i, (int)all_locks->count, i, (int)all_locks->count,
lock->id.thr, lock->id.instance, lock->id.thr, lock->id.instance,
lock->create_file, lock->create_line); lock->create_file, lock->create_line);
else if (i % 100 == 0) else if (i % (all_locks->count/75) == 0)
fprintf(stderr, "."); fprintf(stderr, ".");
i++; i++;
check_order_lock(lock); check_order_lock(lock);

View file

@ -324,30 +324,32 @@ check_table(struct lruhash* table)
/** test adding a random element (unlimited range) */ /** test adding a random element (unlimited range) */
static void static void
testadd_unlim(struct lruhash* table, struct testdata* ref[]) testadd_unlim(struct lruhash* table, struct testdata** ref)
{ {
int numtoadd = random() % (HASHTESTMAX * 10); int numtoadd = random() % (HASHTESTMAX * 10);
struct testdata* data = newdata(numtoadd); struct testdata* data = newdata(numtoadd);
struct testkey* key = newkey(numtoadd); struct testkey* key = newkey(numtoadd);
key->entry.data = data; key->entry.data = data;
lruhash_insert(table, myhash(numtoadd), &key->entry, data); lruhash_insert(table, myhash(numtoadd), &key->entry, data);
ref[numtoadd] = data; if(ref)
ref[numtoadd] = data;
} }
/** test adding a random element (unlimited range) */ /** test adding a random element (unlimited range) */
static void static void
testremove_unlim(struct lruhash* table, struct testdata* ref[]) testremove_unlim(struct lruhash* table, struct testdata** ref)
{ {
int num = random() % (HASHTESTMAX*10); int num = random() % (HASHTESTMAX*10);
struct testkey* key = newkey(num); struct testkey* key = newkey(num);
lruhash_remove(table, myhash(num), key); lruhash_remove(table, myhash(num), key);
ref[num] = NULL; if(ref)
ref[num] = NULL;
delkey(key); delkey(key);
} }
/** test adding a random element (unlimited range) */ /** test adding a random element (unlimited range) */
static void static void
testlookup_unlim(struct lruhash* table, struct testdata* ref[]) testlookup_unlim(struct lruhash* table, struct testdata** ref)
{ {
int num = random() % (HASHTESTMAX*10); int num = random() % (HASHTESTMAX*10);
struct testkey* key = newkey(num); struct testkey* key = newkey(num);
@ -357,9 +359,9 @@ testlookup_unlim(struct lruhash* table, struct testdata* ref[])
unit_assert(en->key); unit_assert(en->key);
unit_assert(en->data); unit_assert(en->data);
} }
if(0) log_info("lookup unlim %d got %d, expect %d", num, en ? if(0 && ref) log_info("lookup unlim %d got %d, expect %d", num, en ?
data->data :-1, ref[num] ? ref[num]->data : -1); data->data :-1, ref[num] ? ref[num]->data : -1);
if(data) { if(data && ref) {
/* its okay for !data, it fell off the lru */ /* its okay for !data, it fell off the lru */
unit_assert( data == ref[num] ); unit_assert( data == ref[num] );
} }
@ -422,6 +424,66 @@ test_long_table(struct lruhash* table)
} }
} }
/** structure to threaded test the lru hash table */
struct test_thr {
/** thread num, first entry. */
int num;
/** id */
ub_thread_t id;
/** hash table */
struct lruhash* table;
};
/** main routine for threaded hash table test */
static void*
test_thr_main(void* arg)
{
struct test_thr* t = (struct test_thr*)arg;
int i;
log_thread_set(&t->num);
for(i=0; i<1000; i++) {
switch(random() % 4) {
case 0:
case 3:
testadd_unlim(t->table, NULL);
break;
case 1:
testremove_unlim(t->table, NULL);
break;
case 2:
testlookup_unlim(t->table, NULL);
break;
default:
unit_assert(0);
}
if(0) lruhash_status(t->table, "hashtest", 1);
if(i % 100 == 0) /* because of locking, not all the time */
check_table(t->table);
}
check_table(t->table);
return NULL;
}
/** test hash table access by multiple threads. */
static void
test_threaded_table(struct lruhash* table)
{
int numth = 10;
struct test_thr t[100];
int i;
for(i=1; i<numth; i++) {
t[i].num = i;
t[i].table = table;
ub_thread_create(&t[i].id, test_thr_main, &t[i]);
}
for(i=1; i<numth; i++) {
ub_thread_join(t[i].id);
}
if(0) lruhash_status(table, "hashtest", 1);
}
void lruhash_test() void lruhash_test()
{ {
/* start very very small array, so it can do lots of table_grow() */ /* start very very small array, so it can do lots of table_grow() */
@ -432,7 +494,10 @@ void lruhash_test()
test_lru(table); test_lru(table);
test_short_table(table); test_short_table(table);
test_long_table(table); test_long_table(table);
/* hashtable tests go here */ lruhash_delete(table);
table = lruhash_create(2, 4096,
test_sizefunc, test_compfunc, test_delkey, test_deldata, NULL);
test_threaded_table(table);
lruhash_delete(table); lruhash_delete(table);
} }

Binary file not shown.