# Running the first probe as a single process is required to avoid "File exists" # errors. It seems that fresh database creation does not support concurrency. Index: test.sh --- test.sh 2007-07-29 21:07:10 +0200 +++ test.sh 2007-07-29 22:56:24 +0200 @@ -9,11 +9,11 @@ echo "---- probing linear run" rm /tmp/my.db; rm -rf /tmp/my.d; mkdir /tmp/my.d || exit 1 -for i in 0 1 2 3 4 5 6 7 8 9; do ./probe ; done +./probe; for i in 1 2 3 4 5 6 7 8 9; do ./probe ; done /openpkg-dev/bin/db_dump -p /tmp/my.db | egrep '^ key-' | wc -l echo "---- probing concurrent run" rm /tmp/my.db; rm -rf /tmp/my.d; mkdir /tmp/my.d || exit 1 -for i in 0 1 2 3 4 5 6 7 8 9; do ./probe & done; wait +./probe; for i in 1 2 3 4 5 6 7 8 9; do ./probe & done; wait /openpkg-dev/bin/db_dump -p /tmp/my.db | egrep '^ key-' | wc -l # Cosmetics Index: test.sh --- test.sh 2007-07-29 21:07:10 +0200 +++ test.sh 2007-07-29 22:56:24 +0200 @@ -5,7 +5,7 @@ echo "---- building probe" uname | grep SunOS && EXTRALIBS='-l rt' -/openpkg-dev/bin/gcc -I /openpkg-dev/include/ -L /openpkg-dev/lib/ -o probe probe.c -l db $EXTRALIBS || exit 1 +/openpkg-dev/bin/gcc -Wall -I /openpkg-dev/include/ -L /openpkg-dev/lib/ -o probe probe.c -l db $EXTRALIBS || exit 1 echo "---- probing linear run" rm /tmp/my.db; rm -rf /tmp/my.d; mkdir /tmp/my.d || exit 1 Index: probe.c --- probe.c 2007-07-29 20:56:27 +0200 +++ probe.c 2007-07-29 23:22:48 +0200 @@ -24,12 +24,10 @@ sprintf(key, "key-%05d-%05d-%05d", (int)getpid(), o, i); dbkey.data = &key; dbkey.size = strlen(key); sprintf(val, "val-%05d-%05d-%05d", (int)getpid(), o, i); dbval.data = &val; dbval.size = strlen(val); -#if 0 - printf("key=%s, val=%s\n", key, val); -#else rv = db->put(db, NULL, &dbkey, &dbval, DB_NOOVERWRITE); - if (rv != 0) die(rv); -#endif + if (rv != 0) { + fprintf(stderr, "WARNING: key=%s, val=%s error(%d)=%s\n", key, val, rv, db_strerror(rv)); + } } int main(void) @@ -55,7 +55,8 @@ flags |= DB_RECOVER; if ((rv = dbenv->open(dbenv, /* DB environment pointer */ "/tmp/my.d", /* Homedir */ - flags, 0) /* Open flags, File mode (using defaults) */ + flags, /* Open flags */ + 0) /* File mode (using defaults) */ ) != 0) die(rv); /* Initialize and open the database */ @@ -71,7 +69,8 @@ "/tmp/my.db", /* On-disk file that holds the database. */ "foo", /* Optional logical database name */ DB_BTREE, /* Database access method */ - flags, 0) /* Open flags, File mode (using defaults) */ + flags, /* Open flags */ + 0) /* File mode (using defaults) */ ) != 0) die(rv); /* Put content into database */ # reduce use of die() macro to the main function only and enhance to call proper cleanup sequence. Index: probe.c --- probe.c 2007-07-29 20:56:27 +0200 +++ probe.c 2007-07-29 23:22:48 +0200 @@ -7,9 +7,9 @@ #include #include -#define die(e) { fprintf(stderr, "ERROR file %s line %d pid=%d: %s (%d)\n", \ +#define die(e) { fprintf(stderr, "DIE: file %s line %d pid=%d: %s (%d)\n", \ __FILE__, __LINE__, (int)getpid(), db_strerror(e), e); \ - exit(e); } + goto CLEANUP; } void insert(DB *db, int o, int i) { @@ -77,6 +77,7 @@ /* Put content into database */ for (i=0; i<100; i++) insert(db, o, i); +CLEANUP: /* Flush, cleanup and close database and environment */ if (db != NULL) db->close(db, 0); if (dbenv != NULL) dbenv->close(dbenv, 0); # DB_INIT_LOCK is the wholly grail to enabling concurrency. # DB_INIT_MPOOL used to prevent error "environment did not include a memory pool". # DB_INIT_TXN used to prevent error "recovery requires transaction support". # DB_RECOVER used to prevent error "No recovery flag was specified, and recovery is needed" Index: probe.c --- probe.c 2007-07-29 20:56:27 +0200 +++ probe.c 2007-07-29 23:22:48 +0200 @@ -48,6 +48,8 @@ dbenv->set_errfile(dbenv, stderr); flags = 0; flags |= DB_CREATE; + flags |= DB_INIT_MPOOL; + flags |= DB_INIT_LOCK; flags |= DB_INIT_TXN; flags |= DB_REGISTER; flags |= DB_RECOVER; # the environment only helps if passed to db_create Index: probe.c --- probe.c 2007-07-29 20:56:27 +0200 +++ probe.c 2007-07-29 23:22:48 +0200 @@ -61,7 +61,7 @@ /* Initialize and open the database */ db = NULL; - rv = db_create(&db, NULL, 0); + rv = db_create(&db, dbenv, 0); if (rv != 0) die(rv); db->set_errfile(db, stderr);