Import BSDDB 4.7.25 (as of svn r89086)

This commit is contained in:
Zachary Ware
2017-09-04 13:40:25 -05:00
parent 4b29e0458f
commit 8f590873d0
4781 changed files with 2241032 additions and 6 deletions

101
test_micro/source/LIST Normal file
View File

@@ -0,0 +1,101 @@
Test list:
b_curalloc
Cursor allocation
usage: b_curalloc [-c count]
-c Cursor count
b_curwalk
Walk a cursor through N records
usage: b_curwalk [-pSs] [-C cachesz]
[-c cnt] [-d dupcnt] [-P pagesz] [-t type] [-w walkcnt]
-C Cache size
-c Record count
-d Duplicate record count
-P Page size
-p Walk backward instead of forward
-S Skip duplicates
-s Sort duplicates
-t Database type (B | H | Q | R)
b_del
Delete records
usage: b_del [-w] [-C cachesz] [-c count] [-t type]
-C Cache size
-c Record count
-t Database type (B | H | Q | R)
-w Delete through cursor
b_get
Read records
usage: b_get [-C cachesz] [-c count] [-t type]
-C Cache size
-c Record count
-t Database type (B | H | Q | R)
b_load
Insert records
usage: b_load [-d] [-C cachesz] [-c count] [-t type]
-C Cache size
-c Record count
-d Use duplicate records
-t Database type (B | H | Q | R)
b_open
Database open/close
usage: b_open [-df] [-c count] [-t type]
-d Open/close a subdatabase
-f Open/close a physical file
-c Open/close count
-t Database type (B | H | Q | R)
b_put
Overwrite record
usage: b_put [-C cachesz]
[-c count] [-d bytes] [-s secondaries] [-t type]
-C Cache size
-c Record count
-d Data size
-s Number of secondaries
-t Database type (B | H | Q | R)
b_recover
Run recovery
usage: b_recover [-C cachesz] [-c count]
-C Cache size
-c Transactions to recover
b_txn
Abort or commit a transaction containing no operations
usage: b_txn [-a] [-c count]
-a Abort rather than commit
-c Transaction count
b_txn_write
Write/commit transaction
usage: b_txn_write [-arw] [-c count]
-a nosync
-c Transaction count
-r Configure replication stub callback
-w write-nosync
b_workload

View File

@@ -0,0 +1,65 @@
/*
* $Id: b_curalloc.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_curalloc(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBC *curp;
int ch, i, count;
count = 100000;
while ((ch = getopt(argc, argv, "c:")) != EOF)
switch (ch) {
case 'c':
count = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
dbp->set_errfile(dbp, stderr);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif
/* Allocate a cursor count times. */
TIMER_START;
for (i = 0; i < count; ++i) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &curp, 0) == 0);
DB_BENCH_ASSERT(curp->c_close(curp) == 0);
}
TIMER_STOP;
printf("# %d cursor allocations\n", count);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_curalloc [-c count]\n");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,204 @@
/*
* $Id: b_curwalk.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_curwalk(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBTYPE type;
DBC *dbc;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize, pagesize, walkflags;
int ch, i, count, dupcount, j;
int prev, ret, skipdupwalk, sorted, walkcount;
char *ts, dbuf[32], kbuf[32];
type = DB_BTREE;
cachesize = 10 * MEGABYTE;
pagesize = 16 * 1024;
count = 100000;
dupcount = prev = skipdupwalk = sorted = 0;
walkcount = 1000;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:d:P:pSst:w:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 'd':
dupcount = atoi(optarg);
break;
case 'P':
pagesize = (u_int32_t)atoi(optarg);
break;
case 'p':
prev = 1;
break;
case 'S':
skipdupwalk = 1;
break;
case 's':
sorted = 1;
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case 'w':
walkcount = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/*
* Queue and Recno don't support duplicates.
*/
if (dupcount != 0 && (type == DB_QUEUE || type == DB_RECNO)) {
fprintf(stderr,
"b_curwalk: Queue and Recno don't support duplicates\n");
return (usage());
}
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
#define DB_PREV_NODUP 0
/*
* DB_PREV_NODUP wasn't available until after 3.0.55.
*
* For some reason, testing sorted duplicates doesn't work either.
* I don't really care about 3.0.55 any more, just ignore it.
*/
return (0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);
/* Set duplicates flag. */
if (dupcount != 0)
DB_BENCH_ASSERT(
dbp->set_flags(dbp, sorted ? DB_DUPSORT : DB_DUP) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* Insert count in-order key/data pairs. */
data.data = dbuf;
data.size = 20;
if (type == DB_BTREE || type == DB_HASH) {
key.size = 10;
key.data = kbuf;
for (i = 0; i < count; ++i) {
(void)snprintf(kbuf, sizeof(kbuf), "%010d", i);
for (j = 0; j <= dupcount; ++j) {
(void)snprintf(dbuf, sizeof(dbuf), "%020d", j);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
}
} else {
key.data = &recno;
key.size = sizeof(recno);
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
walkflags = prev ?
(skipdupwalk ? DB_PREV_NODUP : DB_PREV) :
(skipdupwalk ? DB_NEXT_NODUP : DB_NEXT);
/* Walk the cursor through the tree N times. */
TIMER_START;
for (i = 0; i < walkcount; ++i) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while ((ret = dbc->c_get(dbc, &key, &data, walkflags)) == 0)
;
DB_BENCH_ASSERT(ret == DB_NOTFOUND);
DB_BENCH_ASSERT(dbc->c_close(dbc) == 0);
}
TIMER_STOP;
printf("# %d %s %s cursor of %d 10/20 byte key/data items",
walkcount, ts, prev ?
(skipdupwalk ? "DB_PREV_NODUP" : "DB_PREV") :
(skipdupwalk ? "DB_NEXT_NODUP" : "DB_NEXT"),
count);
if (dupcount != 0)
printf(" with %d dups", dupcount);
printf("\n");
/*
* An "operation" is traversal of a single key/data pair -- not a
* return of the key/data pair, since some versions of this test
* skip duplicate key/data pairs.
*
* Use a "double" so we don't overflow.
*/
TIMER_DISPLAY((double)count * walkcount);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (EXIT_SUCCESS);
}
static int
usage()
{
(void)fprintf(stderr, "%s\n\t%s\n",
"usage: b_curwalk [-pSs] [-C cachesz]",
"[-c cnt] [-d dupcnt] [-P pagesz] [-t type] [-w walkcnt]");
return (EXIT_FAILURE);
}

162
test_micro/source/b_del.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* $Id: b_del.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_del(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBC *dbc;
DBT key, data;
DBTYPE type;
db_recno_t recno;
u_int32_t cachesize;
int ch, i, count, ret, use_cursor;
char *ts, buf[32];
type = DB_BTREE;
cachesize = MEGABYTE;
count = 100000;
use_cursor = 0;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:t:w")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case 'w':
use_cursor = 1;
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
data.data = "01234567890123456789";
data.size = 20;
/* Store a key/data pair. */
switch (type) {
case DB_BTREE:
case DB_HASH:
key.data = buf;
key.size = 10;
break;
case DB_QUEUE:
case DB_RECNO:
key.data = &recno;
key.size = sizeof(recno);
break;
case DB_UNKNOWN:
b_util_abort();
break;
}
/* Insert count in-order key/data pairs. */
if (type == DB_BTREE || type == DB_HASH)
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%010d", i);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
else
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
/* Delete the records. */
TIMER_START;
if (use_cursor) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0)
DB_BENCH_ASSERT(dbc->c_del(dbc, 0) == 0);
DB_BENCH_ASSERT (ret == DB_NOTFOUND);
} else
if (type == DB_BTREE || type == DB_HASH)
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%010d", i);
DB_BENCH_ASSERT(
dbp->del(dbp, NULL, &key, 0) == 0);
}
else
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->del(dbp, NULL, &key, 0) == 0);
TIMER_STOP;
printf(
"# %d %s database in-order delete of 10/20 byte key/data pairs using %s\n",
count, ts, use_cursor ? "a cursor" : "the key");
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_del [-w] [-C cachesz] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

129
test_micro/source/b_get.c Normal file
View File

@@ -0,0 +1,129 @@
/*
* $Id: b_get.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_get(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBTYPE type;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize;
int ch, i, count;
char *ts;
type = DB_BTREE;
cachesize = MEGABYTE;
count = 100000;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:t:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 10) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Store a key/data pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
switch (type) {
case DB_BTREE:
case DB_HASH:
key.data = "aaaaa";
key.size = 5;
break;
case DB_QUEUE:
case DB_RECNO:
recno = 1;
key.data = &recno;
key.size = sizeof(recno);
break;
case DB_UNKNOWN:
b_util_abort();
break;
}
data.data = "bbbbb";
data.size = 5;
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
/* Retrieve the key/data pair count times. */
TIMER_START;
for (i = 0; i < count; ++i)
DB_BENCH_ASSERT(dbp->get(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
printf("# %d %s database get of cached key/data item\n", count, ts);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_get [-C cachesz] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

423
test_micro/source/b_inmem.c Normal file
View File

@@ -0,0 +1,423 @@
/*
* $Id: b_inmem.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0
/*
* The in-memory tests don't run on early releases of Berkeley DB.
*/
#undef MEGABYTE
#define MEGABYTE (1024 * 1024)
u_int32_t bulkbufsize = 4 * MEGABYTE;
u_int32_t cachesize = 32 * MEGABYTE;
u_int32_t datasize = 32;
u_int32_t keysize = 8;
u_int32_t logbufsize = 8 * MEGABYTE;
u_int32_t numitems;
u_int32_t pagesize = 32 * 1024;
FILE *fp;
char *progname;
static void op_ds __P((u_int, int));
static void op_ds_bulk __P((u_int, u_int *));
static void op_tds __P((u_int, int, u_int32_t, u_int32_t));
static int usage __P((void));
static void
op_ds(u_int ops, int update)
{
DB_ENV *dbenv;
char *letters = "abcdefghijklmnopqrstuvwxuz";
DB *dbp;
DBT key, data;
char *keybuf, *databuf;
DB_MPOOL_STAT *gsp;
DB_BENCH_ASSERT((keybuf = malloc(keysize)) != NULL);
DB_BENCH_ASSERT((databuf = malloc(datasize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
memset(keybuf, 'a', keysize);
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
dbenv = dbp->dbenv;
dbp->set_errfile(dbp, stderr);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
if (update) {
TIMER_START;
for (; ops > 0; --ops) {
keybuf[(ops % keysize)] = letters[(ops % 26)];
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
TIMER_STOP;
} else {
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
TIMER_START;
for (; ops > 0; --ops)
DB_BENCH_ASSERT(
dbp->get(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
}
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_cache_miss == 0);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
}
static void
op_ds_bulk(u_int ops, u_int *totalp)
{
DB_ENV *dbenv;
DB *dbp;
DBC *dbc;
DBT key, data;
u_int32_t len, klen;
u_int i, total;
char *keybuf, *databuf;
void *pointer, *dp, *kp;
DB_MPOOL_STAT *gsp;
DB_BENCH_ASSERT((keybuf = malloc(keysize)) != NULL);
DB_BENCH_ASSERT((databuf = malloc(bulkbufsize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
dbenv = dbp->dbenv;
dbp->set_errfile(dbp, stderr);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 1) == 0);
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
for (i = 1; i <= numitems; ++i) {
(void)snprintf(keybuf, keysize, "%7d", i);
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
#if 0
fp = fopen("before", "w");
dbp->set_msgfile(dbp, fp);
DB_BENCH_ASSERT (dbp->stat_print(dbp, DB_STAT_ALL) == 0);
#endif
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
data.ulen = bulkbufsize;
data.flags = DB_DBT_USERMEM;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
TIMER_START;
for (total = 0; ops > 0; --ops) {
DB_BENCH_ASSERT(dbc->c_get(
dbc, &key, &data, DB_FIRST | DB_MULTIPLE_KEY) == 0);
DB_MULTIPLE_INIT(pointer, &data);
while (pointer != NULL) {
DB_MULTIPLE_KEY_NEXT(pointer, &data, kp, klen, dp, len);
if (kp != NULL)
++total;
}
}
TIMER_STOP;
*totalp = total;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_cache_miss == 0);
#if 0
fp = fopen("before", "w");
dbp->set_msgfile(dbp, fp);
DB_BENCH_ASSERT (dbp->stat_print(dbp, DB_STAT_ALL) == 0);
#endif
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
COMPQUIET(dp, NULL);
COMPQUIET(klen, 0);
COMPQUIET(len, 0);
}
static void
op_tds(u_int ops, int update, u_int32_t env_flags, u_int32_t log_flags)
{
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_MPOOL_STAT *gsp;
DB_TXN *txn;
char *keybuf, *databuf;
DB_BENCH_ASSERT((keybuf = malloc(keysize)) != NULL);
DB_BENCH_ASSERT((databuf = malloc(datasize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
memset(keybuf, 'a', keysize);
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
/* General environment configuration. */
#ifdef DB_AUTO_COMMIT
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, DB_AUTO_COMMIT, 1) == 0);
#endif
if (env_flags != 0)
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, env_flags, 1) == 0);
/* Logging configuration. */
if (log_flags != 0)
#if DB_VERSION_MINOR >= 7
DB_BENCH_ASSERT(
dbenv->log_set_config(dbenv, log_flags, 1) == 0);
#else
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, log_flags, 1) == 0);
#endif
#ifdef DB_LOG_INMEMORY
if (!(log_flags & DB_LOG_INMEMORY))
#endif
#ifdef DB_LOG_IN_MEMORY
if (!(log_flags & DB_LOG_IN_MEMORY))
#endif
DB_BENCH_ASSERT(dbenv->set_lg_max(dbenv, logbufsize * 10) == 0);
DB_BENCH_ASSERT(dbenv->set_lg_bsize(dbenv, logbufsize) == 0);
DB_BENCH_ASSERT(dbenv->open(dbenv, "TESTDIR",
DB_CREATE | DB_PRIVATE | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0666) == 0);
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
if (update) {
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
TIMER_START;
for (; ops > 0; --ops)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_page_out == 0);
} else {
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
TIMER_START;
for (; ops > 0; --ops) {
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(
dbp->get(dbp, NULL, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
}
TIMER_STOP;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_cache_miss == 0);
}
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
}
#define DEFAULT_OPS 1000000
int
b_inmem(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
u_int ops, total;
int ch;
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
++progname;
ops = 0;
while ((ch = getopt(argc, argv, "b:C:d:k:l:o:P:")) != EOF)
switch (ch) {
case 'b':
bulkbufsize = (u_int32_t)atoi(optarg);
break;
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'd':
datasize = (u_int)atoi(optarg);
break;
case 'k':
keysize = (u_int)atoi(optarg);
break;
case 'l':
logbufsize = (u_int32_t)atoi(optarg);
break;
case 'o':
ops = (u_int)atoi(optarg);
break;
case 'P':
pagesize = (u_int32_t)atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 1)
return (usage());
numitems = (cachesize / (keysize + datasize - 1)) / 2;
if (strcasecmp(argv[0], "read") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_ds(ops, 0);
printf(
"# %u in-memory Btree database reads of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "bulk") == 0) {
if (keysize < 8) {
fprintf(stderr,
"%s: bulk read requires a key size >= 10\n", progname);
return (EXIT_FAILURE);
}
/*
* The ops value is the number of bulk operations, not key get
* operations. Reduce the value so the test doesn't take so
* long, and use the returned number of retrievals as the ops
* value for timing purposes.
*/
if (ops == 0)
ops = 100000;
op_ds_bulk(ops, &total);
ops = total;
printf(
"# %u bulk in-memory Btree database reads of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "write") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_ds(ops, 1);
printf(
"# %u in-memory Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "txn-read") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_tds(ops, 0, 0, 0);
printf(
"# %u transactional in-memory Btree database reads of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "txn-write") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
#if defined(DB_LOG_INMEMORY) || defined(DB_LOG_IN_MEMORY)
#if defined(DB_LOG_INMEMORY)
op_tds(ops, 1, 0, DB_LOG_INMEMORY);
#else
op_tds(ops, 1, 0, DB_LOG_IN_MEMORY);
#endif
printf(
"# %u transactional in-memory logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
#else
return (EXIT_SUCCESS);
#endif
} else if (strcasecmp(argv[0], "txn-nosync") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_tds(ops, 1, DB_TXN_NOSYNC, 0);
printf(
"# %u transactional nosync logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "txn-write-nosync") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
#ifdef DB_TXN_WRITE_NOSYNC
op_tds(ops, 1, DB_TXN_WRITE_NOSYNC, 0);
printf(
"# %u transactional OS-write/nosync logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
#else
return (EXIT_SUCCESS);
#endif
} else if (strcasecmp(argv[0], "txn-sync") == 0) {
/*
* Flushing to disk takes a long time, reduce the number of
* default ops.
*/
if (ops == 0)
ops = 100000;
op_tds(ops, 1, 0, 0);
printf(
"# %u transactional logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else {
fprintf(stderr, "%s: unknown keyword %s\n", progname, argv[0]);
return (EXIT_FAILURE);
}
TIMER_DISPLAY(ops);
return (EXIT_SUCCESS);
}
static int
usage()
{
fprintf(stderr, "usage: %s %s%s%s%s",
progname, "[-b bulkbufsz] [-C cachesz]\n\t",
"[-d datasize] [-k keysize] [-l logbufsz] [-o ops] [-P pagesz]\n\t",
"[read | bulk | write | txn-read |\n\t",
"txn-write | txn-nosync | txn-write-nosync | txn-sync]\n");
return (EXIT_FAILURE);
}
#else
int
b_inmem(int argc, char *argv[])
{
COMPQUIET(argc, 0);
COMPQUIET(argv, NULL);
return (0);
}
#endif

160
test_micro/source/b_load.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* $Id: b_load.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_load(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBTYPE type;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize;
int ch, i, count, duplicate;
char *ts, buf[32];
type = DB_BTREE;
cachesize = MEGABYTE;
count = 100000;
duplicate = 0;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:dt:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 'd':
duplicate = 1;
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Usage. */
if (duplicate && (type == DB_QUEUE || type == DB_RECNO)) {
fprintf(stderr,
"b_load: Queue an Recno don't support duplicates\n");
return (usage());
}
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
/*
* DB versions prior to 3.1.17 didn't have off-page duplicates, so
* this test can run forever.
*/
if (duplicate)
return (0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
if (duplicate)
DB_BENCH_ASSERT(dbp->set_flags(dbp, DB_DUP) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* Insert count in-order key/data pairs. */
TIMER_START;
if (duplicate) {
key.size = 10;
key.data = "01234567890123456789";
data.data = buf;
data.size = 20;
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%020d", i);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
} else {
data.data = buf;
data.size = 20;
if (type == DB_BTREE || type == DB_HASH) {
key.size = 10;
key.data = buf;
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%010d", i);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
} else {
key.data = &recno;
key.size = sizeof(recno);
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
}
TIMER_STOP;
printf("# %d %s database in-order put of 10/20 byte key/data %sitems\n",
count, ts, duplicate ? "duplicate " : "");
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_load [-d] [-C cachesz] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

140
test_micro/source/b_open.c Normal file
View File

@@ -0,0 +1,140 @@
/*
* $Id: b_open.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_open(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB *dbp;
DBTYPE type;
int ch, i, count;
char *fname, *dbname, *ts;
type = DB_BTREE;
count = 1000;
fname = dbname = NULL;
ts = "Btree";
while ((ch = getopt(argc, argv, "c:dft:")) != EOF)
switch (ch) {
case 'c':
count = atoi(optarg);
break;
case 'd':
dbname = "dbname";
break;
case 'f':
fname = "filename";
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
#if DB_VERSION_MAJOR < 4
/*
* Don't run in-memory database tests on versions less than 3, it
* takes forever and eats memory.
*/
if (fname == NULL && dbname == NULL)
return (0);
#endif
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 4
/*
* Named in-memory databases weren't available until 4.4.
*/
if (fname == NULL && dbname != NULL)
return (0);
#endif
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, fname, dbname, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, fname, dbname, type, DB_CREATE, 0666) == 0);
#endif
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
/* Open the database count times. */
TIMER_START;
for (i = 0; i < count; ++i) {
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, fname, dbname, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, fname, dbname, type, DB_CREATE, 0666) == 0);
#endif
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
}
TIMER_STOP;
printf("# %d %s %sdatabase open/close pairs\n",
count, ts,
fname == NULL ?
(dbname == NULL ? "in-memory " : "named in-memory ") :
(dbname == NULL ? "" : "sub-"));
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_open [-df] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

217
test_micro/source/b_put.c Normal file
View File

@@ -0,0 +1,217 @@
/*
* $Id: b_put.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
static int b_put_secondary(DB *, const DBT *, const DBT *, DBT *);
int
b_put(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB *dbp, **second;
DBTYPE type;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize;
int ch, dsize, i, count, secondaries;
char *ts, buf[64];
second = NULL;
type = DB_BTREE;
cachesize = MEGABYTE;
dsize = 20;
count = 100000;
secondaries = 0;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:d:s:t:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 'd':
dsize = atoi(optarg);
break;
case 's':
secondaries = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
/*
* Secondaries were added after DB 3.2.9.
*/
if (secondaries)
return (0);
#endif
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
DB_BENCH_ASSERT(dbenv->set_cachesize(dbenv, 0, cachesize, 0) == 0);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#endif
/*
* Create the database.
* Optionally set the record length for Queue.
*/
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, (u_int32_t)dsize) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Optionally create the secondaries. */
if (secondaries != 0) {
DB_BENCH_ASSERT((second =
calloc(sizeof(DB *), (size_t)secondaries)) != NULL);
for (i = 0; i < secondaries; ++i) {
DB_BENCH_ASSERT(db_create(&second[i], dbenv, 0) == 0);
snprintf(buf, sizeof(buf), "%d.db", i);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(second[i]->open(second[i], NULL,
buf, NULL, DB_BTREE, DB_CREATE, 0600) == 0);
#else
DB_BENCH_ASSERT(second[i]->open(second[i],
buf, NULL, DB_BTREE, DB_CREATE, 0600) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3
#if DB_VERSION_MAJOR > 3 && DB_VERSION_MINOR > 0
/*
* The DB_TXN argument to Db.associate was added in
* 4.1.25.
*/
DB_BENCH_ASSERT(dbp->associate(
dbp, NULL, second[i], b_put_secondary, 0) == 0);
#else
DB_BENCH_ASSERT(dbp->associate(
dbp, second[i], b_put_secondary, 0) == 0);
#endif
#endif
}
}
/* Store a key/data pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
switch (type) {
case DB_BTREE:
case DB_HASH:
key.data = "01234567890123456789";
key.size = 20;
break;
case DB_QUEUE:
case DB_RECNO:
recno = 1;
key.data = &recno;
key.size = sizeof(recno);
break;
case DB_UNKNOWN:
b_util_abort();
break;
}
DB_BENCH_ASSERT(
(data.data = malloc(data.size = (size_t)dsize)) != NULL);
/* Store the key/data pair count times. */
TIMER_START;
for (i = 0; i < count; ++i)
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
if (type == DB_BTREE || type == DB_HASH)
printf(
"# %d %s database put of 10 byte key, %lu byte data",
count, ts, (u_long)dsize);
else
printf("# %d %s database put of key, %lu byte data",
count, ts, (u_long)dsize);
if (secondaries)
printf(" with %d secondaries", secondaries);
printf("\n");
TIMER_DISPLAY(count);
if (second != NULL) {
for (i = 0; i < secondaries; ++i)
DB_BENCH_ASSERT(second[i]->close(second[i], 0) == 0);
free(second);
}
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
b_put_secondary(dbp, pkey, pdata, skey)
DB *dbp;
const DBT *pkey, *pdata;
DBT *skey;
{
skey->data = pkey->data;
skey->size = pkey->size;
COMPQUIET(dbp, NULL);
COMPQUIET(pdata, NULL);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_put %s\n",
"[-C cachesz] [-c count] [-d bytes] [-s secondaries] [-t type]");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,137 @@
/*
* $Id: b_recover.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_recover(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_TXN *txn;
u_int32_t cachesize;
int ch, i, count;
/*
* Recover was too slow before release 4.0 that it's not worth
* running the test.
*/
#if DB_VERSION_MAJOR < 4
return (0);
#endif
cachesize = MEGABYTE;
count = 1000;
while ((ch = getopt(argc, argv, "C:c:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
DB_BENCH_ASSERT(dbenv->set_cachesize(dbenv, 0, cachesize, 0) == 0);
#define OFLAGS \
(DB_CREATE | DB_INIT_LOCK | \
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE)
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, NULL, OFLAGS, 0666) == 0);
#endif
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, OFLAGS, 0666) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, OFLAGS, 0666) == 0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(dbp, NULL,
TESTFILE, NULL, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.size = data.size = 20;
key.data = data.data = "01234567890123456789";
/* Start/commit a transaction count times. */
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(
txn_begin(dbenv, NULL, &txn, DB_TXN_NOSYNC) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, DB_TXN_NOSYNC) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
}
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
/* Create a new DB_ENV handle. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
DB_BENCH_ASSERT(
dbenv->set_cachesize(dbenv, 0, 1048576 /* 1MB */, 0) == 0);
/* Now run recovery. */
TIMER_START;
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(dbenv->open(
dbenv, TESTDIR, NULL, OFLAGS | DB_RECOVER, 0666) == 0);
#endif
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, OFLAGS | DB_RECOVER, 0666) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 1
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, OFLAGS | DB_RECOVER, 0666) == 0);
#endif
TIMER_STOP;
/*
* We divide the time by the number of transactions, so an "operation"
* is the recovery of a single transaction.
*/
printf("# recovery after %d transactions\n", count);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_recover [-C cachesz] [-c count]\n");
return (EXIT_FAILURE);
}

89
test_micro/source/b_txn.c Normal file
View File

@@ -0,0 +1,89 @@
/*
* $Id: b_txn.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_txn(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB_TXN *txn;
int tabort, ch, i, count;
count = 1000;
tabort = 0;
while ((ch = getopt(argc, argv, "ac:")) != EOF)
switch (ch) {
case 'a':
tabort = 1;
break;
case 'c':
count = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
NULL, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE, 0666) == 0);
#endif
/* Start and commit/abort a transaction count times. */
TIMER_START;
if (tabort)
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn_abort(txn) == 0);
#else
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn->abort(txn) == 0);
#endif
}
else
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
}
TIMER_STOP;
printf("# %d empty transaction start/%s pairs\n",
count, tabort ? "abort" : "commit");
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_txn [-a] [-c count]\n");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,168 @@
/*
* $Id: b_txn_write.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage __P((void));
#ifdef DB_INIT_REP
static int b_txn_write_send __P((DB_ENV *,
const DBT *, const DBT *, const DB_LSN *, int, u_int32_t));
/*
* b_txn_write_send --
* A stubbed-out replication message function.
*/
static int
b_txn_write_send(dbenv, control, rec, lsn, eid, flags)
DB_ENV *dbenv;
const DBT *control, *rec;
const DB_LSN *lsn;
int eid;
u_int32_t flags;
{
COMPQUIET(dbenv, NULL);
COMPQUIET(control, NULL);
COMPQUIET(rec, NULL);
COMPQUIET(lsn, NULL);
COMPQUIET(eid, 0);
COMPQUIET(flags, 0);
return (0);
}
#endif
int
b_txn_write(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_TXN *txn;
u_int32_t flags, oflags;
int ch, i, count, rep_stub;
char *config;
count = 1000;
oflags = flags = 0;
rep_stub = 0;
config = "synchronous";
while ((ch = getopt(argc, argv, "ac:rw")) != EOF)
switch (ch) {
case 'a':
config = "nosync";
flags = DB_TXN_NOSYNC;
break;
case 'c':
count = atoi(optarg);
break;
case 'r':
#ifdef DB_INIT_REP
rep_stub = 1;
#else
exit(0);
#endif
break;
case 'w':
config = "write-nosync";
#ifdef DB_TXN_WRITE_NOSYNC
flags = DB_TXN_WRITE_NOSYNC;
#else
exit(0);
#endif
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
#ifdef DB_INIT_REP
if (rep_stub) {
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5 || DB_VERSION_MAJOR > 4
DB_BENCH_ASSERT(
dbenv->rep_set_transport(dbenv, 1, b_txn_write_send) == 0);
#else
DB_BENCH_ASSERT(
dbenv->set_rep_transport(dbenv, 1, b_txn_write_send) == 0);
#endif
oflags |= DB_INIT_REP;
}
#endif
oflags |= DB_CREATE | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE;
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, NULL, flags | oflags, 0666) == 0);
#endif
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, flags | oflags, 0666) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 1
if (flags != 0)
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, flags, 1) == 0);
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, oflags, 0666) == 0);
#endif
#ifdef DB_INIT_REP
if (rep_stub)
DB_BENCH_ASSERT(
dbenv->rep_start(dbenv, NULL, DB_REP_MASTER) == 0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(dbp, NULL,
TESTFILE, NULL, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.size = data.size = 20;
key.data = data.data = "01234567890123456789";
/* Start/commit a transaction count times. */
TIMER_START;
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
DB_BENCH_ASSERT(dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
}
TIMER_STOP;
printf("# %d %stransactions write %s commit pairs\n",
count, rep_stub ? "replicated ": "", config);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_txn_write [-arw] [-c count]\n");
return (EXIT_FAILURE);
}

143
test_micro/source/b_uname.c Normal file
View File

@@ -0,0 +1,143 @@
/*
* $Id: b_uname.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
#define UNAMEFILE "NODENAME"
static int write_info __P((FILE *));
int
b_uname()
{
FILE *fp;
int ret;
if ((fp = fopen(UNAMEFILE, "w")) == NULL)
goto file_err;
ret = write_info(fp);
if (fclose(fp) != 0) {
file_err: fprintf(stderr,
"%s: %s: %s\n", progname, UNAMEFILE, strerror(errno));
return (1);
}
return (ret);
}
#ifdef DB_WIN32
static int
write_info(fp)
FILE *fp;
{
OSVERSIONINFO osver;
SYSTEM_INFO sysinfo;
char *p;
#ifdef DB_WINCE
p = "WinCE";
#else
{
DWORD len;
char buf[1024];
len = sizeof(buf) - 1;
GetComputerName(buf, &len);
p = buf;
}
#endif
fprintf(fp, "<p>%s, ", p);
GetSystemInfo(&sysinfo);
switch (sysinfo.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_ALPHA:
p = "alpha";
break;
case PROCESSOR_ARCHITECTURE_INTEL:
p = "x86";
break;
case PROCESSOR_ARCHITECTURE_MIPS:
p = "mips";
break;
case PROCESSOR_ARCHITECTURE_PPC:
p = "ppc";
break;
default:
p = "unknown";
break;
}
fprintf(fp, "%s<br>\n", p);
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
GetVersionEx(&osver);
switch (osver.dwPlatformId) {
case VER_PLATFORM_WIN32_NT: /* NT, Windows 2000 or Windows XP */
if (osver.dwMajorVersion == 4)
p = "Windows NT4x";
else if (osver.dwMajorVersion <= 3)
p = "Windows NT3x";
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion < 1)
p = "Windows 2000";
else if (osver.dwMajorVersion >= 5)
p = "Windows XP";
else
p = "unknown";
break;
case VER_PLATFORM_WIN32_WINDOWS: /* Win95, Win98 or WinME */
if ((osver.dwMajorVersion > 4) ||
((osver.dwMajorVersion == 4) && (osver.dwMinorVersion > 0))) {
if (osver.dwMinorVersion >= 90)
p = "Windows ME";
else
p = "Windows 98";
} else
p = "Windows 95";
break;
case VER_PLATFORM_WIN32s: /* Windows 3.x */
p = "Windows";
break;
default:
p = "unknown";
break;
}
fprintf(fp,
"%s, %ld.%02ld", p, osver.dwMajorVersion, osver.dwMinorVersion);
return (0);
}
#elif defined(HAVE_VXWORKS)
static int
write_info(fp)
FILE *fp;
{
fprintf(fp, "<p>VxWorks");
return (0);
}
#else /* POSIX */
#include <sys/utsname.h>
static int
write_info(fp)
FILE *fp;
{
struct utsname name;
if (uname(&name) == 0)
fprintf(fp, "<p>%s, %s<br>\n%s, %s, %s</p>\n", name.nodename,
name.machine, name.sysname, name.release, name.version);
else {
/*
* We've seen random failures on some systems, complain and
* skip the call if it fails.
*/
fprintf(stderr, "%s: uname: %s\n", progname, strerror(errno));
fprintf(fp, "<p>POSIX");
}
return (0);
}
#endif

154
test_micro/source/b_util.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* $Id: b_util.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int testdir_remove __P((char *));
int
b_util_have_hash()
{
#if defined(HAVE_HASH) ||\
DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 2
return (0);
#else
fprintf(stderr,
"library build did not include support for the Hash access method\n");
return (1);
#endif
}
int
b_util_have_queue()
{
#if defined(HAVE_QUEUE) ||\
DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 2
return (0);
#else
fprintf(stderr,
"library build did not include support for the Queue access method\n");
return (1);
#endif
}
/*
* b_util_dir_setup --
* Create the test directory.
*/
int
b_util_dir_setup()
{
int ret;
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 3
if ((ret = __os_mkdir(NULL, TESTDIR, 0755)) != 0) {
#else
if ((ret = mkdir(TESTDIR, 0755)) != 0) {
#endif
fprintf(stderr,
"%s: %s: %s\n", progname, TESTDIR, db_strerror(ret));
return (1);
}
return (0);
}
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 4
#define OS_EXISTS(a, b, c) __os_exists(a, b, c)
#else
#define OS_EXISTS(a, b, c) __os_exists(b, c)
#endif
/*
* b_util_dir_teardown
* Clean up the test directory.
*/
int
b_util_dir_teardown()
{
int ret;
if (OS_EXISTS(NULL, TESTFILE, NULL) == 0 &&
(ret = b_util_unlink(TESTFILE)) != 0) {
fprintf(stderr,
"%s: %s: %s\n", progname, TESTFILE, db_strerror(ret));
return (1);
}
return (testdir_remove(TESTDIR) ? 1 : 0);
}
/*
* testdir_remove --
* Remove a directory and all its contents, the "dir" must contain no
* subdirectories, because testdir_remove will not recursively delete
* all subdirectories.
*/
static int
testdir_remove(dir)
char *dir;
{
int cnt, i, isdir, ret;
char buf[1024], **names;
ret = 0;
/* If the directory doesn't exist, we're done. */
if (OS_EXISTS(NULL, dir, &isdir) != 0)
return (0);
/* Get a list of the directory contents. */
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6
if ((ret = __os_dirlist(NULL, dir, 0, &names, &cnt)) != 0)
return (ret);
#else
if ((ret = __os_dirlist(NULL, dir, &names, &cnt)) != 0)
return (ret);
#endif
/* Go through the file name list, remove each file in the list */
for (i = 0; i < cnt; ++i) {
(void)snprintf(buf, sizeof(buf),
"%s%c%s", dir, PATH_SEPARATOR[0], names[i]);
if ((ret = OS_EXISTS(NULL, buf, &isdir)) != 0)
goto file_err;
if (!isdir && (ret = b_util_unlink(buf)) != 0) {
file_err: fprintf(stderr, "%s: %s: %s\n",
progname, buf, db_strerror(ret));
break;
}
}
__os_dirfree(NULL, names, cnt);
/*
* If we removed the contents of the directory, remove the directory
* itself.
*/
if (i == cnt && (ret = rmdir(dir)) != 0)
fprintf(stderr,
"%s: %s: %s\n", progname, dir, db_strerror(errno));
return (ret);
}
void
b_util_abort()
{
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 6
abort();
#elif DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 6
__os_abort();
#else
__os_abort(NULL);
#endif
}
int
b_util_unlink(path)
char *path;
{
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 7
return (__os_unlink(NULL, path));
#else
return (__os_unlink(NULL, path, 0));
#endif
}

View File

@@ -0,0 +1,623 @@
/*
* $Id: b_workload.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
#include "b_workload.h"
static int dump_verbose_stats __P((DB *, CONFIG *));
static int is_del_workload __P((int));
static int is_get_workload __P((int));
static int is_put_workload __P((int));
static int run_mixed_workload __P((DB *, CONFIG *));
static int run_std_workload __P((DB *, CONFIG *));
static int usage __P((void));
static char *workload_str __P((int));
/*
* General TODO list:
* * The workload type. Might work better as a bitmask than the current enum.
* * Improve the verbose stats, so they can be easily parsed.
* * Think about doing automatic btree/hash comparison in here.
*/
int
b_workload(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
CONFIG conf;
DB *dbp;
DB_ENV *dbenv;
int ch, ffactor, ksz;
dbenv = NULL;
memset(&conf, 0, sizeof(conf));
conf.seed = 124087;
srand(conf.seed);
conf.pcount = 100000;
conf.ts = "Btree";
conf.type = DB_BTREE;
conf.dsize = 20;
conf.presize = 0;
conf.workload = T_PUT_GET_DELETE;
while ((ch = getopt(argc, argv, "b:c:d:e:g:ik:m:op:r:t:vw:")) != EOF)
switch (ch) {
case 'b':
conf.cachesz = atoi(optarg);
break;
case 'c':
conf.pcount = atoi(optarg);
break;
case 'd':
conf.dsize = atoi(optarg);
break;
case 'e':
conf.cursor_del = atoi(optarg);
break;
case 'g':
conf.gcount = atoi(optarg);
break;
case 'i':
conf.presize = 1;
break;
case 'k':
conf.ksize = atoi(optarg);
break;
case 'm':
conf.message = optarg;
break;
case 'o':
conf.orderedkeys = 1;
break;
case 'p':
conf.pagesz = atoi(optarg);
break;
case 'r':
conf.num_dups = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
conf.ts = "Btree";
conf.type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
conf.ts = "Hash";
conf.type = DB_HASH;
break;
default:
return (usage());
}
break;
case 'v':
conf.verbose = 1;
break;
case 'w':
switch (optarg[0]) {
case 'A':
conf.workload = T_PUT_GET_DELETE;
break;
case 'B':
conf.workload = T_GET;
break;
case 'C':
conf.workload = T_PUT;
break;
case 'D':
conf.workload = T_DELETE;
break;
case 'E':
conf.workload = T_PUT_GET;
break;
case 'F':
conf.workload = T_PUT_DELETE;
break;
case 'G':
conf.workload = T_GET_DELETE;
break;
case 'H':
conf.workload = T_MIXED;
break;
default:
return (usage());
}
break;
case '?':
default:
fprintf(stderr, "Invalid option: %c\n", ch);
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/*
* Validate the input parameters if specified.
*/
if (conf.pagesz != 0)
DB_BENCH_ASSERT(conf.pagesz >= 512 && conf.pagesz <= 65536 &&
((conf.pagesz & (conf.pagesz - 1)) == 0));
if (conf.cachesz != 0)
DB_BENCH_ASSERT(conf.cachesz > 20480);
DB_BENCH_ASSERT(conf.ksize == 0 || conf.orderedkeys == 0);
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
if (conf.cachesz != 0)
DB_BENCH_ASSERT(
dbenv->set_cachesize(dbenv, 0, conf.cachesz, 0) == 0);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
DB_BENCH_ASSERT(dbenv->open(dbenv, "TESTDIR",
NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, "TESTDIR",
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#endif
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
if (conf.pagesz != 0)
DB_BENCH_ASSERT(
dbp->set_pagesize(dbp, conf.pagesz) == 0);
if (conf.presize != 0 && conf.type == DB_HASH) {
ksz = (conf.orderedkeys != 0) ? sizeof(u_int32_t) : conf.ksize;
if (ksz == 0)
ksz = 10;
ffactor = (conf.pagesz - 32)/(ksz + conf.dsize + 8);
fprintf(stderr, "ffactor: %d\n", ffactor);
DB_BENCH_ASSERT(
dbp->set_h_ffactor(dbp, ffactor) == 0);
DB_BENCH_ASSERT(
dbp->set_h_nelem(dbp, conf.pcount*10) == 0);
}
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, conf.type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, TESTFILE, NULL, conf.type, DB_CREATE, 0666) == 0);
#endif
if (conf.workload == T_MIXED)
run_mixed_workload(dbp, &conf);
else
run_std_workload(dbp, &conf);
if (is_put_workload(conf.workload) == 0)
timespecadd(&conf.tot_time, &conf.put_time);
if (is_get_workload(conf.workload) == 0)
timespecadd(&conf.tot_time, &conf.get_time);
if (is_del_workload(conf.workload) == 0)
timespecadd(&conf.tot_time, &conf.del_time);
/* Ensure data is flushed for following measurements. */
DB_BENCH_ASSERT(dbp->sync(dbp, 0) == 0);
if (conf.verbose != 0)
dump_verbose_stats(dbp, &conf);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
/*
* Construct a string for benchmark output.
*
* Insert HTML in-line to make the output prettier -- ugly, but easy.
*/
printf("# workload test: %s: %s<br>%lu ops",
conf.ts, workload_str(conf.workload), (u_long)conf.pcount);
if (conf.ksize != 0)
printf(", key size: %lu", (u_long)conf.ksize);
if (conf.dsize != 0)
printf(", data size: %lu", (u_long)conf.dsize);
if (conf.pagesz != 0)
printf(", page size: %lu", (u_long)conf.pagesz);
else
printf(", page size: default");
if (conf.cachesz != 0)
printf(", cache size: %lu", (u_long)conf.cachesz);
else
printf(", cache size: default");
printf(", %s keys", conf.orderedkeys == 1 ? "ordered" : "unordered");
printf(", num dups: %lu", (u_long)conf.num_dups);
printf("\n");
if (conf.workload != T_MIXED) {
if (conf.message != NULL)
printf("%s %s ", conf.message, conf.ts);
TIME_DISPLAY(conf.pcount, conf.tot_time);
} else
TIMER_DISPLAY(conf.pcount);
return (0);
}
/*
* The mixed workload is designed to simulate a somewhat real
* usage scenario.
* NOTES: * rand is used to decide on the current operation. This will
* be repeatable, since the same seed is always used.
* * All added keys are stored in a FIFO queue, this is not very
* space efficient, but is the best way I could come up with to
* insert random key values, and be able to retrieve/delete them.
* * TODO: the workload will currently only work with unordered
* fixed length keys.
*/
#define GET_PROPORTION 90
#define PUT_PROPORTION 7
#define DEL_PROPORTION 3
static int
run_mixed_workload(dbp, config)
DB *dbp;
CONFIG *config;
{
DBT key, data;
size_t next_op, i, ioff;
char kbuf[KBUF_LEN];
struct bench_q operation_queue;
/* Having ordered insertion does not make sense here */
DB_BENCH_ASSERT(config->orderedkeys == 0);
srand(config->seed);
memset(&operation_queue, 0, sizeof(struct bench_q));
ioff = 0;
INIT_KEY(key, config);
memset(&data, 0, sizeof(data));
DB_BENCH_ASSERT(
(data.data = malloc(data.size = config->dsize)) != NULL);
/*
* Add an initial sample set of data to the DB.
* This should add some stability, and reduce the likelihood
* of deleting all of the entries in the DB.
*/
for (i = 0; i < 2 * config->pcount; ++i) {
GET_KEY_NEXT(key, config, kbuf, i);
BENCH_Q_TAIL_INSERT(operation_queue, kbuf);
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
TIMER_START;
for (i = 0; i < config->pcount; ++i) {
next_op = rand()%100;
if (next_op < GET_PROPORTION ) {
BENCH_Q_POP_PUSH(operation_queue, kbuf);
key.data = kbuf;
key.size = sizeof(kbuf);
dbp->get(dbp, NULL, &key, &data, 0);
} else if (next_op < GET_PROPORTION+PUT_PROPORTION) {
GET_KEY_NEXT(key, config, kbuf, i);
BENCH_Q_TAIL_INSERT(operation_queue, kbuf);
dbp->put(dbp, NULL, &key, &data, 0);
} else {
BENCH_Q_POP(operation_queue, kbuf);
key.data = kbuf;
key.size = sizeof(kbuf);
dbp->del(dbp, NULL, &key, 0);
}
}
TIMER_STOP;
TIMER_GET(config->tot_time);
return (0);
}
static int
run_std_workload(dbp, config)
DB *dbp;
CONFIG *config;
{
DBT key, data;
DBC *dbc;
u_int32_t i;
int ret;
char kbuf[KBUF_LEN];
/* Setup a key/data pair. */
INIT_KEY(key, config);
memset(&data, 0, sizeof(data));
DB_BENCH_ASSERT(
(data.data = malloc(data.size = config->dsize)) != NULL);
/* Store the key/data pair count times. */
TIMER_START;
for (i = 0; i < config->pcount; ++i) {
GET_KEY_NEXT(key, config, kbuf, i);
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
TIMER_STOP;
TIMER_GET(config->put_time);
if (is_get_workload(config->workload) == 0) {
TIMER_START;
for (i = 0; i <= config->gcount; ++i) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while ((dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0);
DB_BENCH_ASSERT(dbc->c_close(dbc) == 0);
}
TIMER_STOP;
TIMER_GET(config->get_time);
}
if (is_del_workload(config->workload) == 0) {
/* reset rand to reproduce key sequence. */
srand(config->seed);
TIMER_START;
if (config->cursor_del != 0) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while (
(ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0)
DB_BENCH_ASSERT(dbc->c_del(dbc, 0) == 0);
DB_BENCH_ASSERT (ret == DB_NOTFOUND);
} else {
INIT_KEY(key, config);
for (i = 0; i < config->pcount; ++i) {
GET_KEY_NEXT(key, config, kbuf, i);
ret = dbp->del(dbp, NULL, &key, 0);
/*
* Random key generation can cause dups,
* so NOTFOUND result is OK.
*/
if (config->ksize == 0)
DB_BENCH_ASSERT
(ret == 0 || ret == DB_NOTFOUND);
else
DB_BENCH_ASSERT(ret == 0);
}
}
TIMER_STOP;
TIMER_GET(config->del_time);
}
return (0);
}
static int
dump_verbose_stats(dbp, config)
DB *dbp;
CONFIG *config;
{
/*
* It would be nice to be able to define stat as _stat on
* Windows, but that substitutes _stat for the db call as well.
*/
#ifdef DB_WIN32
struct _stat fstat;
#else
struct stat fstat;
#endif
DB_HASH_STAT *hstat;
DB_BTREE_STAT *bstat;
double free_prop;
char path[1024];
#ifdef DB_BENCH_INCLUDE_CONFIG_SUMMARY
printf("Completed workload benchmark.\n");
printf("Configuration summary:\n");
printf("\tworkload type: %d\n", (int)config->workload);
printf("\tdatabase type: %s\n", config->ts);
if (config->cachesz != 0)
printf("\tcache size: %lu\n", (u_long)config->cachesz);
if (config->pagesz != 0)
printf("\tdatabase page size: %lu\n", (u_long)config->pagesz);
printf("\tput element count: %lu\n", (u_long)config->pcount);
if ( is_get_workload(config->workload) == 0)
printf("\tget element count: %lu\n", (u_long)config->gcount);
if (config->orderedkeys)
printf("\tInserting items in order\n");
else if (config->ksize == 0)
printf("\tInserting keys with size 10\n");
else
printf(
"\tInserting keys with size: %lu\n", (u_long)config->ksize);
printf("\tInserting data elements size: %lu\n", (u_long)config->dsize);
if (is_del_workload(config->workload) == 0) {
if (config->cursor_del)
printf("\tDeleting items using a cursor\n");
else
printf("\tDeleting items without a cursor\n");
}
#endif /* DB_BENCH_INCLUDE_CONFIG_SUMMARY */
if (is_put_workload(config->workload) == 0)
printf("%s Time spent inserting (%lu) (%s) items: %lu/%lu\n",
config->message[0] == '\0' ? "" : config->message,
(u_long)config->pcount, config->ts,
(u_long)config->put_time.tv_sec, config->put_time.tv_nsec);
if (is_get_workload(config->workload) == 0)
printf("%s Time spent getting (%lu) (%s) items: %lu/%lu\n",
config->message[0] == '\0' ? "" : config->message,
(u_long)config->pcount * ((config->gcount == 0) ?
1 : config->gcount), config->ts,
(u_long)config->get_time.tv_sec, config->get_time.tv_nsec);
if (is_del_workload(config->workload) == 0)
printf("%s Time spent deleting (%lu) (%s) items: %lu/%lu\n",
config->message[0] == '\0' ? "" : config->message,
(u_long)config->pcount, config->ts,
(u_long)config->del_time.tv_sec, config->del_time.tv_nsec);
(void)snprintf(path, sizeof(path),
"%s%c%s", TESTDIR, PATH_SEPARATOR[0], TESTFILE);
#ifdef DB_WIN32
if (_stat(path, &fstat) == 0) {
#else
if (stat(path, &fstat) == 0) {
#endif
printf("%s Size of db file (%s): %lu K\n",
config->message[0] == '\0' ? "" : config->message,
config->ts, (u_long)fstat.st_size/1024);
}
if (config->type == DB_HASH) {
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &hstat, NULL, 0) == 0);
#elif DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &hstat, 0) == 0);
#else
DB_BENCH_ASSERT(dbp->stat(dbp, NULL, &hstat, 0) == 0);
#endif
/*
* Hash fill factor is a bit tricky. Want to include
* both bucket and overflow buckets (not offpage).
*/
free_prop = hstat->hash_pagesize*hstat->hash_buckets;
free_prop += hstat->hash_pagesize*hstat->hash_overflows;
free_prop =
(free_prop - hstat->hash_bfree - hstat->hash_ovfl_free)/
free_prop;
printf("%s db fill factor (%s): %.2f%%\n",
config->message[0] == '\0' ? "" : config->message,
config->ts, free_prop*100);
free(hstat);
} else { /* Btree */
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &bstat, NULL, 0) == 0);
#elif DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &bstat, 0) == 0);
#else
DB_BENCH_ASSERT(dbp->stat(dbp, NULL, &bstat, 0) == 0);
#endif
free_prop = bstat->bt_pagesize*bstat->bt_leaf_pg;
free_prop = (free_prop-bstat->bt_leaf_pgfree)/free_prop;
printf("%s db fill factor (%s): %.2f%%\n",
config->message[0] == '\0' ? "" : config->message,
config->ts, free_prop*100);
free(bstat);
}
return (0);
}
static char *
workload_str(workload)
int workload;
{
static char buf[128];
switch (workload) {
case T_PUT_GET_DELETE:
return ("PUT/GET/DELETE");
/* NOTREACHED */
case T_GET:
return ("GET");
/* NOTREACHED */
case T_PUT:
return ("PUT");
/* NOTREACHED */
case T_DELETE:
return ("DELETE");
/* NOTREACHED */
case T_PUT_GET:
return ("PUT/GET");
/* NOTREACHED */
case T_PUT_DELETE:
return ("PUT/DELETE");
/* NOTREACHED */
case T_GET_DELETE:
return ("GET/DELETE");
/* NOTREACHED */
case T_MIXED:
snprintf(buf, sizeof(buf), "MIXED (get: %d, put: %d, del: %d)",
(int)GET_PROPORTION,
(int)PUT_PROPORTION, (int)DEL_PROPORTION);
return (buf);
default:
break;
}
exit(usage());
/* NOTREACHED */
}
static int
is_get_workload(workload)
int workload;
{
switch (workload) {
case T_GET:
case T_PUT_GET:
case T_PUT_GET_DELETE:
case T_GET_DELETE:
return 0;
}
return 1;
}
static int
is_put_workload(workload)
int workload;
{
switch (workload) {
case T_PUT:
case T_PUT_GET:
case T_PUT_GET_DELETE:
case T_PUT_DELETE:
return 0;
}
return 1;
}
static int
is_del_workload(workload)
int workload;
{
switch (workload) {
case T_DELETE:
case T_PUT_DELETE:
case T_PUT_GET_DELETE:
case T_GET_DELETE:
return 0;
}
return 1;
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_workload [-b cachesz] [-c count] [-d bytes] [-e]\n");
(void)fprintf(stderr,
"\t[-g getitrs] [-i] [-k keysize] [-m message] [-o] [-p pagesz]\n");
(void)fprintf(stderr, "\t[-r dup_count] [-t type] [-w type]\n");
(void)fprintf(stderr, "Where:\n");
(void)fprintf(stderr, "\t-b the size of the DB cache.\n");
(void)fprintf(stderr, "\t-c the number of elements to be measured.\n");
(void)fprintf(stderr, "\t-d the size of each data element.\n");
(void)fprintf(stderr, "\t-e delete entries using a cursor.\n");
(void)fprintf(stderr, "\t-g number of get cursor traverses.\n");
(void)fprintf(stderr, "\t-i Pre-init hash DB bucket count.\n");
(void)fprintf(stderr, "\t-k the size of each key inserted.\n");
(void)fprintf(stderr, "\t-m message pre-pended to log output.\n");
(void)fprintf(stderr, "\t-o keys should be ordered for insert.\n");
(void)fprintf(stderr, "\t-p the page size for the database.\n");
(void)fprintf(stderr, "\t-r the number of duplicates to insert\n");
(void)fprintf(stderr, "\t-t type of the underlying database.\n");
(void)fprintf(stderr, "\t-w the workload to measure, available:\n");
(void)fprintf(stderr, "\t\tA - PUT_GET_DELETE\n");
(void)fprintf(stderr, "\t\tB - GET\n");
(void)fprintf(stderr, "\t\tC - PUT\n");
(void)fprintf(stderr, "\t\tD - DELETE\n");
(void)fprintf(stderr, "\t\tE - PUT_GET\n");
(void)fprintf(stderr, "\t\tF - PUT_DELETE\n");
(void)fprintf(stderr, "\t\tG - GET_DELETE\n");
(void)fprintf(stderr, "\t\tH - MIXED\n");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,149 @@
/*
* $Id: b_workload.h 63573 2008-05-23 21:43:21Z trent.nelson $
*/
/*
* Macros to help with initializing/assigning key dbts
*/
#define KBUF_LEN 12
#define INIT_KEY(key, config) do { \
memset(&key, 0, sizeof(key)); \
if (config->orderedkeys) { \
key.size = sizeof (u_int32_t); \
} else if (config->ksize != 0) { \
DB_BENCH_ASSERT( \
(key.data = malloc(key.size = config->ksize)) != NULL); \
} else { \
key.data = kbuf; \
key.size = 10; \
} \
} while (0)
#define GET_KEY_NEXT(key, config, kbuf, i) do { \
size_t tmp_int; \
if (config->orderedkeys) { \
/* Will be sorted on little-endian system. */ \
tmp_int = i; \
M_32_SWAP(tmp_int); \
key.data = &tmp_int; \
} else if (config->ksize == 0) { \
/* \
* This will produce duplicate keys. \
* That is not such a big deal, since we are \
* using the same seed to srand each time, \
* the scenario is reproducible. \
*/ \
(void)snprintf(kbuf, sizeof(kbuf), "%10d", rand()); \
} else { \
/* TODO: Not sure of the best approach here. */ \
(void)snprintf(key.data, config->ksize, "%10lu", (u_long)i); \
} \
} while (0)
/* Taken from dbinc/db_swap.h */
#undef M_32_SWAP
#define M_32_SWAP(a) { \
u_int32_t _tmp; \
_tmp = (u_int32_t)a; \
((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[3]; \
((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[2]; \
((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1]; \
((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0]; \
}
/*
* A singly linked list, that maintains a pointer
* to the start and the end of the queue.
* Should be possible to use a STAILQ, but this seemed easier
*/
typedef struct bench_qentry {
char data[KBUF_LEN];
struct bench_qentry *next;
}bench_qentry;
typedef struct bench_q {
struct bench_qentry *head;
struct bench_qentry *tail;
} bench_q;
#define BENCH_Q_TAIL_INSERT(queue, buf) do { \
struct bench_qentry *entry; \
DB_BENCH_ASSERT( \
(entry = malloc(sizeof(struct bench_qentry))) != NULL); \
memcpy(entry->data, buf, sizeof(entry->data)); \
if (queue.head == NULL) \
queue.head = queue.tail = entry; \
else { \
queue.tail->next = entry; \
queue.tail = entry; \
} \
} while (0)
#define BENCH_Q_POP(queue, buf) do { \
struct bench_qentry *popped = queue.head; \
if (popped == NULL) \
break; \
if (queue.head->next == NULL) \
queue.head = queue.tail = NULL; \
else \
queue.head = queue.head->next; \
memcpy(buf, popped->data, sizeof(buf)); \
free(popped); \
} while (0)
/*
* Retrieve the head of the queue, save the data into user
* buffer, and push the item back onto the end of the list.
* Same functionality as pop/insert, but saves a malloc/free
*/
#define BENCH_Q_POP_PUSH(queue, buf) do { \
struct bench_qentry *popped = queue.head; \
if (popped == NULL) \
break; \
if (queue.head->next == NULL) \
queue.head = queue.tail = NULL; \
else \
queue.head = queue.head->next; \
memcpy(buf, popped->data, sizeof(buf)); \
if (queue.head == NULL) \
queue.head = queue.tail = popped; \
else { \
queue.tail->next = popped; \
queue.tail = popped; \
} \
} while (0)
typedef enum {
T_PUT,
T_GET,
T_DELETE,
T_PUT_GET,
T_PUT_DELETE,
T_PUT_GET_DELETE,
T_GET_DELETE,
T_MIXED
} test_type;
typedef struct
{
size_t ksize;
size_t dsize;
size_t orderedkeys;
size_t num_dups;
size_t pagesz;
size_t cachesz;
size_t pcount;
size_t gcount;
size_t cursor_del;
size_t verbose;
test_type workload;
size_t seed;
size_t presize;
DBTYPE type;
char *ts;
char *message;
/* Fields used to store timing information */
db_timespec put_time;
db_timespec get_time;
db_timespec del_time;
db_timespec tot_time;
} CONFIG;

211
test_micro/source/bench.h Normal file
View File

@@ -0,0 +1,211 @@
/*
* $Id: bench.h 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#ifndef _BENCH_H_
#define _BENCH_H_
#include "db_config.h"
#include "db_int.h"
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 5
/*
* Older releases of Berkeley DB don't include standard include files in
* db_int.h.
*/
#ifdef DB_WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <direct.h>
#include <sys/timeb.h>
#else
#include <sys/stat.h>
#include <sys/time.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#endif
#define TESTDIR "TESTDIR"
#define TESTFILE "test_micro.db"
/*
* Implement a custom assert to allow consistent behavior across builds and
* platforms.
*
* The BDB library DB_ASSERT implementation is only enabled in diagnostic
* builds -- so is not suitable here.
*/
#define DB_BENCH_ASSERT(e) do { \
(e) ? (void)0 : \
(fprintf(stderr, \
"assert failure: %s/%d: \"%s\"\n", __FILE__, __LINE__, #e), \
b_util_abort()); \
} while (0)
#ifndef NS_PER_SEC
#define NS_PER_SEC 1000000000 /* Nanoseconds in a second */
#endif
#ifndef NS_PER_US
#define NS_PER_US 1000 /* Nanoseconds in a microsecond */
#endif
#ifndef MS_PER_NS
#define MS_PER_NS 1000000 /* Milliseconds in a nanosecond */
#endif
#ifdef DB_TIMEOUT_TO_TIMESPEC
/*
* We have the timer routines in the Berkeley DB library after their conversion
* to the POSIX timespec interfaces. We'd rather use something that gives us
* better information than elapsed wallclock time, so use getrusage instead if
* it's available.
*/
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#define SET_TIMER_FROM_GETRUSAGE(tp) do { \
struct rusage __usage; \
DB_BENCH_ASSERT(getrusage(RUSAGE_SELF, &__usage) == 0); \
(tp)->tv_sec = \
__usage.ru_utime.tv_sec + __usage.ru_stime.tv_sec; \
(tp)->tv_nsec = NS_PER_US * \
(__usage.ru_utime.tv_usec + __usage.ru_stime.tv_usec); \
} while (0);
#define TIMER_START SET_TIMER_FROM_GETRUSAGE(&__start_time);
#define TIMER_STOP SET_TIMER_FROM_GETRUSAGE(&__end_time);
#elif defined(DB_WIN32) && !defined(DB_WINCE)
#define SET_TIMER_FROM_GETPROCESSTIMES(tp) do { \
FILETIME lpCreationTime, lpExitTime, lpKernelTime, lpUserTIme; \
LARGE_INTEGER large_int; \
LONGLONG __ns_since_epoch; \
DB_BENCH_ASSERT( \
GetProcessTimes(GetCurrentProcess(), &lpCreationTime, \
&lpExitTime, &lpKernelTime, &lpUserTIme) != 0); \
memcpy(&large_int, &lpKernelTime, sizeof(lpKernelTime)); \
__ns_since_epoch = (large_int.QuadPart * 100); \
(tp)->tv_sec = (time_t)(__ns_since_epoch / NS_PER_SEC); \
(tp)->tv_nsec = (long)(__ns_since_epoch % NS_PER_SEC); \
memcpy(&large_int, &lpUserTIme, sizeof(lpUserTIme)); \
__ns_since_epoch = (large_int.QuadPart * 100); \
(tp)->tv_sec += (time_t)(__ns_since_epoch / NS_PER_SEC); \
(tp)->tv_nsec += (long)(__ns_since_epoch % NS_PER_SEC); \
} while (0);
#define TIMER_START SET_TIMER_FROM_GETPROCESSTIMES(&__start_time);
#define TIMER_STOP SET_TIMER_FROM_GETPROCESSTIMES(&__end_time);
#else /* !HAVEGETRUSAGE && !DB_WIN32 */
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6
#define TIMER_START __os_gettime(NULL, &__start_time, 1)
#define TIMER_STOP __os_gettime(NULL, &__end_time, 1)
#else
#define TIMER_START __os_gettime(NULL, &__start_time)
#define TIMER_STOP __os_gettime(NULL, &__end_time)
#endif
#endif /* !HAVE_GETRUSAGE */
#else /* !DB_TIMEOUT_TO_TIMESPEC */
#if defined(HAVE_CLOCK_GETTIME)
typedef struct timespec db_timespec;
#else
typedef struct {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
} db_timespec;
#endif
#define timespecadd(vvp, uvp) \
do { \
(vvp)->tv_sec += (uvp)->tv_sec; \
(vvp)->tv_nsec += (uvp)->tv_nsec; \
if ((vvp)->tv_nsec >= NS_PER_SEC) { \
(vvp)->tv_sec++; \
(vvp)->tv_nsec -= NS_PER_SEC; \
} \
} while (0)
#define timespecsub(vvp, uvp) \
do { \
(vvp)->tv_sec -= (uvp)->tv_sec; \
(vvp)->tv_nsec -= (uvp)->tv_nsec; \
if ((vvp)->tv_nsec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_nsec += NS_PER_SEC; \
} \
} while (0)
#define TIMER_START CLOCK(__start_time)
#define TIMER_STOP CLOCK(__end_time)
#if defined(HAVE_CLOCK_GETTIME)
#define CLOCK(tm) do { \
DB_BENCH_ASSERT(clock_gettime( \
CLOCK_REALTIME, (struct timespec *)&(tm)) == 0); \
} while (0)
#elif defined(DB_WIN32)
#define CLOCK(tm) do { \
struct _timeb __now; \
_ftime(&__now); \
(tm).tv_sec = __now.time; \
(tm).tv_nsec = __now.millitm * MS_PER_NS; \
} while (0)
#else
#define CLOCK(tm) do { \
struct timeval __tp; \
DB_BENCH_ASSERT(gettimeofday(&__tp, NULL) == 0); \
(tm).tv_sec = __tp.tv_sec; \
(tm).tv_nsec = __tp.tv_usec * NS_PER_US; \
} while (0)
#endif
#endif /* !DB_TIMEOUT_TO_TIMESPEC */
db_timespec __start_time, __end_time;
#define TIMER_GET(tm) do { \
tm = __end_time; \
timespecsub(&(tm), &__start_time); \
} while (0)
#define TIMER_DISPLAY(ops) do { \
db_timespec __tmp_time; \
__tmp_time = __end_time; \
timespecsub(&__tmp_time, &__start_time); \
TIME_DISPLAY(ops, __tmp_time); \
} while (0)
#define TIME_DISPLAY(ops, tm) do { \
double __secs; \
int __major, __minor, __patch; \
__secs = (tm).tv_sec + (double)(tm).tv_nsec / NS_PER_SEC; \
(void)db_version(&__major, &__minor, &__patch); \
printf("%d.%d.%d\t%.2f\n", __major, __minor, __patch, \
(__secs == 0) ? 0.0 : (ops) / __secs); \
} while (0)
extern char *progname; /* program name */
int b_curalloc __P((int, char *[]));
int b_curwalk __P((int, char *[]));
int b_del __P((int, char *[]));
int b_get __P((int, char *[]));
int b_inmem __P((int, char *[]));
int b_load __P((int, char *[]));
int b_open __P((int, char *[]));
int b_put __P((int, char *[]));
int b_recover __P((int, char *[]));
int b_txn __P((int, char *[]));
int b_txn_write __P((int, char *[]));
int b_uname __P((void));
void b_util_abort __P((void));
int b_util_dir_setup __P((void));
int b_util_dir_teardown __P((void));
int b_util_have_hash __P((void));
int b_util_have_queue __P((void));
int b_util_unlink __P((char *));
int b_workload __P((int, char *[]));
#endif /* !_BENCH_H_ */

View File

@@ -0,0 +1,217 @@
/*
* $Id: test_micro.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
int main __P((int, char *[]));
static int run __P((char *));
static int usage __P((void));
char *progname; /* program name */
static int test_start = 1; /* first test to run */
static int test_end = 0; /* last test to run */
static struct {
char *name; /* command name */
int (*f)(int, char *[]); /* function */
} cmdlist[] = {
{ "b_curalloc", b_curalloc },
{ "b_curwalk", b_curwalk },
{ "b_del", b_del },
{ "b_get", b_get },
{ "b_inmem", b_inmem },
{ "b_load", b_load },
{ "b_open", b_open },
{ "b_put", b_put },
{ "b_recover", b_recover },
{ "b_txn", b_txn },
{ "b_txn_write", b_txn_write },
{ "b_workload", b_workload },
{ NULL, NULL }
};
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
int ch, ret;
char *run_directory, *ifile;
if ((progname = __db_rpath(argv[0])) == NULL)
progname = argv[0];
else
++progname;
#ifdef DB_BREW
if (bdb_brew_begin() != 0) {
fprintf(stderr,
"%s: failed to initialize Berkeley DB on BREW\n");
return (EXIT_FAILURE);
}
#endif
run_directory = NULL;
ifile = "run.std";
while ((ch = getopt(argc, argv, "d:e:i:s:")) != EOF)
switch (ch) {
case 'd':
run_directory = optarg;
break;
case 'e':
test_end = atoi(optarg);
break;
case 'i':
ifile = optarg;
break;
case 's':
test_start = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
/* Run in the target directory. */
if (run_directory != NULL && chdir(run_directory) != 0) {
fprintf(stderr,
"%s: %s: %s\n", progname, run_directory, strerror(errno));
return (1);
}
/* Clean up any left-over test directory. */
if (b_util_dir_teardown())
return (1);
ret = run(ifile);
#ifdef DB_BREW
bdb_brew_end();
#endif
return (ret ? EXIT_FAILURE : EXIT_SUCCESS);
}
/*
* run --
* Read a configuration file and run the tests.
*/
static int
run(ifile)
char *ifile;
{
#ifdef HAVE_GETOPT_OPTRESET
extern int optreset;
#endif
extern int optind;
static int test_cur = 0;
FILE *ifp;
int argc, cmdindx, lineno, ret;
char *p, cmd[1024], path[1024], **argv;
/* Identify the run. */
if (b_uname() != 0)
return (1);
/* Open the list of tests. */
if ((ifp = fopen(ifile, "r")) == NULL) {
fprintf(stderr,
"%s: %s: %s\n", progname, ifile, strerror(errno));
return (1);
}
for (lineno = 1; fgets(cmd, sizeof(cmd), ifp) != NULL; ++lineno) {
/*
* Nul-terminate the command line; check for a trailing \r
* on Windows.
*/
if ((p = strchr(cmd, '\n')) == NULL) {
format_err: fprintf(stderr, "%s: %s: line %d: illegal input\n",
progname, ifile, lineno);
return (1);
}
if (p > cmd && p[-1] == '\r')
--p;
*p = '\0';
/* Skip empty lines and comments. */
if (cmd[0] == '\0' || cmd[0] == '#')
continue;
/* Optionally limit the test run to specific tests. */
if (++test_cur < test_start ||
(test_end != 0 && test_cur > test_end))
continue;
fprintf(stderr, "%d: %s\n", test_cur, cmd);
/* Find the command. */
if ((p = strchr(cmd, ' ')) == NULL)
goto format_err;
*p++ = '\0';
for (cmdindx = 0; cmdlist[cmdindx].name != NULL; ++cmdindx)
if (strcmp(cmd, cmdlist[cmdindx].name) == 0)
break;
if (cmdlist[cmdindx].name == NULL)
goto format_err;
/* Build argc/argv. */
if (__db_util_arg(cmd, p, &argc, &argv) != 0)
return (1);
/* Re-direct output into the test log file. */
(void)snprintf(path, sizeof(path), "%d", test_cur);
if (freopen(path, "a", stdout) == NULL) {
fprintf(stderr,
"%s: %s: %s\n", progname, path, strerror(errno));
return (1);
}
/*
* Each underlying "program" re-parses its arguments --
* reset getopt.
*/
#ifdef HAVE_GETOPT_OPTRESET
optreset = 1;
#endif
optind = 1;
/* Prepare the test directory. */
if (b_util_dir_setup())
return (1);
ret = cmdlist[cmdindx].f(argc, argv);
/* Clean up the test directory. */
if (b_util_dir_teardown())
return (1);
(void)fflush(stdout);
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1
__os_free(NULL, argv, 0);
#else
__os_free(NULL, argv);
#endif
if (ret != 0)
return (ret);
}
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: %s [-d directory] [-e end] [-i input] [-s start]\n",
progname);
return (EXIT_FAILURE);
}