mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
AIX, and threaded hash table test.
git-svn-id: file:///svn/unbound/trunk@187 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
9f413c07e0
commit
d39976b2e1
5 changed files with 122 additions and 17 deletions
|
|
@ -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,
|
||||||
[
|
[
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
if(ref)
|
||||||
ref[numtoadd] = data;
|
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);
|
||||||
|
if(ref)
|
||||||
ref[num] = NULL;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
BIN
testdata/02-unittest.tpkg
vendored
BIN
testdata/02-unittest.tpkg
vendored
Binary file not shown.
Loading…
Reference in a new issue