diff options
| author | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 | 
|---|---|---|
| committer | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 | 
| commit | 54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch) | |
| tree | 18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/test_micro/source | |
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/test_micro/source')
| -rw-r--r-- | db-4.8.30/test_micro/source/LIST | 101 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_curalloc.c | 69 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_curwalk.c | 208 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_del.c | 166 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_get.c | 162 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_inmem.c | 426 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_latch.c | 199 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_load.c | 164 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_open.c | 144 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_put.c | 225 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_recover.c | 141 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_txn.c | 93 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_txn_write.c | 172 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_uname.c | 147 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_util.c | 157 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_workload.c | 631 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/b_workload.h | 153 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/bench.h | 217 | ||||
| -rw-r--r-- | db-4.8.30/test_micro/source/test_micro.c | 223 | 
19 files changed, 3798 insertions, 0 deletions
| diff --git a/db-4.8.30/test_micro/source/LIST b/db-4.8.30/test_micro/source/LIST new file mode 100644 index 0000000..8c02b4a --- /dev/null +++ b/db-4.8.30/test_micro/source/LIST @@ -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 diff --git a/db-4.8.30/test_micro/source/b_curalloc.c b/db-4.8.30/test_micro/source/b_curalloc.c new file mode 100644 index 0000000..410d720 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_curalloc.c @@ -0,0 +1,69 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_curwalk.c b/db-4.8.30/test_micro/source/b_curwalk.c new file mode 100644 index 0000000..8e935f2 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_curwalk.c @@ -0,0 +1,208 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_del.c b/db-4.8.30/test_micro/source/b_del.c new file mode 100644 index 0000000..6385267 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_del.c @@ -0,0 +1,166 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_get.c b/db-4.8.30/test_micro/source/b_get.c new file mode 100644 index 0000000..b63f02a --- /dev/null +++ b/db-4.8.30/test_micro/source/b_get.c @@ -0,0 +1,162 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#include "bench.h" + +static int usage(void); + +u_int32_t part_callback(dbp, dbt) +	DB *dbp; +	DBT *dbt; +{ +	extern u_int32_t __ham_func2(DB *, const void *, u_int32_t); +	return (__ham_func2(dbp, dbt->data, dbt->size)); +} + +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 == 7 && DB_VERSION_PATCH == 30 +	if (type == DB_BTREE) { +		DBT keys[3]; + +		memset(keys, 0, sizeof(keys)); +		keys[0].data = "a"; +		keys[0].size = 1; +		keys[1].data = "b"; +		keys[1].size = 1; +		keys[2].data = "c"; +		keys[2].size = 1; + +		DB_BENCH_ASSERT( +		     dbp->set_partition_keys(dbp, 4, keys, NULL) == 0); +	} + +	if (type == DB_HASH) { +		DB_BENCH_ASSERT( +		    dbp->set_partition_callback(dbp, 4, part_callback) == 0); +	} +#endif + +#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); +} diff --git a/db-4.8.30/test_micro/source/b_inmem.c b/db-4.8.30/test_micro/source/b_inmem.c new file mode 100644 index 0000000..ee0ddda --- /dev/null +++ b/db-4.8.30/test_micro/source/b_inmem.c @@ -0,0 +1,426 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +#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; + +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; +	} + +	if (dbenv->memp_stat(dbenv, &gsp, NULL, 0) == 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; + +	if (dbenv->memp_stat(dbenv, &gsp, NULL, 0) == 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; + +		if (dbenv->memp_stat(dbenv, &gsp, NULL, 0) == 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; + +		if (dbenv->memp_stat(dbenv, &gsp, NULL, 0) == 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 %s", +		    ops, keysize, datasize, "byte key/data pairs\n"); +	} 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%s", +		    ops, keysize, datasize, " byte key/data pairs\n"); +#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 %s", +		    ops, keysize, datasize, "byte key/data pairs\n"); +	} 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%s", +		    ops, keysize, datasize, " byte key/data pairs\n"); +#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 %s", +		    ops, keysize, datasize, "byte key/data pairs\n"); +	} 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 diff --git a/db-4.8.30/test_micro/source/b_latch.c b/db-4.8.30/test_micro/source/b_latch.c new file mode 100644 index 0000000..83ae181 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_latch.c @@ -0,0 +1,199 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +#include "bench.h" + +#ifdef _POSIX_THREADS +typedef struct { +	pthread_t	id; +	DB_ENV		*dbenv; +	int		iterations; +	db_mutex_t	mutex; +	int		contentions; +} threadinfo_t; + +static void *latch_threadmain __P((void *)); +#endif + +static int   time_latches __P((DB_ENV *, db_mutex_t, int)); + +#define	LATCH_THREADS_MAX	100 + +/* Return the environment needed for __mutex_lock(), depending on release. + */ +#if DB_VERSION_MAJOR <4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 7 +#define	ENV_ARG(dbenv)	(dbenv) +#else +#define	ENV_ARG(dbenv)	((dbenv)->env) +#endif + +/* + * In the mulithreaded latch test each thread locks and updates this variable. + * It detects contention when the value of this counter changes during the + * mutex lock call. + */ +static int CurrentCounter = 0; +static int   latch_usage __P((void)); + +static int +latch_usage() +{ +	(void)fprintf(stderr, "usage: b_latch [-c number of %s", +	    "lock+unlock pairs] [-n number of threads]\n"); +	return (EXIT_FAILURE); +} + +/* + * time_latches -- + *	Repeat acquire and release of an exclusive latch, counting the + *	number of times that 'someone else' got it just as we tried to. + */ +static int time_latches(dbenv, mutex, iterations) +	DB_ENV *dbenv; +	db_mutex_t mutex; +	int iterations; +{ +	int contended, i, previous; + +	contended = 0; +	for (i = 0; i < iterations; ++i) { +		previous = CurrentCounter; +		DB_BENCH_ASSERT(__mutex_lock(ENV_ARG(dbenv), mutex) == 0); +		if (previous != CurrentCounter) +			contended++; +		CurrentCounter++; +		DB_BENCH_ASSERT(__mutex_unlock(ENV_ARG(dbenv), mutex) == 0); +	} +	return (contended); +} + +#ifdef _POSIX_THREADS +/* + * latch_threadmain -- + *	Entry point for multithreaded latching test. + * + *	Currently only supported for POSIX threads. + */ +static void * +latch_threadmain(arg) +	void *arg; +{ +	threadinfo_t	*info = arg; + +	info->contentions = time_latches(info->dbenv, +	    info->mutex, info->iterations); + +	return ((void *) 0); +} +#endif + +/* + * b_latch -- + *	Measure the speed of latching and mutex operations. + * + * + */ +int +b_latch(argc, argv) +	int argc; +	char *argv[]; +{ +	extern char *optarg; +	extern int optind; +	DB_ENV *dbenv; +	int ch, count, nthreads; +#ifdef _POSIX_THREADS +	threadinfo_t threads[LATCH_THREADS_MAX]; +	int i, ret; +	void *status; +#endif +	db_mutex_t mutex; +	int contended; + +	contended = 0; +	count = 1000000; +	nthreads = 0;	/* Default to running the test without extra threads */ +	while ((ch = getopt(argc, argv, "c:n:")) != EOF) +		switch (ch) { +		case 'c': +			count = atoi(optarg); +			break; +		case 'n': +			nthreads = atoi(optarg); +			break; +		case '?': +		default: +			return (latch_usage()); +		} +	argc -= optind; +	argv += optind; +	if (argc != 0 || count < 1 || nthreads < 0 || +	    nthreads > LATCH_THREADS_MAX) +		return (latch_usage()); +#ifndef _POSIX_THREADS +	if (nthreads > 1) { +		(void)fprintf(stderr, +		    "Sorry, support for -n %d: threads not yet available\n", +		    nthreads); +		exit(EXIT_FAILURE); +	} +#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 < 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 +	DB_BENCH_ASSERT(dbenv->mutex_alloc(dbenv, DB_MUTEX_SELF_BLOCK, +	    &mutex) == 0); +#ifdef _POSIX_THREADS +	for (i = 0; i < nthreads; i++)  { +		threads[i].dbenv = dbenv; +		threads[i].mutex = mutex; +		threads[i].iterations = +		    nthreads <= 1 ? count : count / nthreads; +	} +#endif + +	/* Start and acquire and release a mutex count times. If there's +	 * posix support and a non-zero number of threads start them. +	 */ +	TIMER_START; +#ifdef _POSIX_THREADS +	if (nthreads > 0) { +		for (i = 0; i < nthreads; i++) +			DB_BENCH_ASSERT(pthread_create(&threads[i].id, +			    NULL, latch_threadmain, &threads[i]) == 0); +		for (i = 0; i < nthreads; i++) { +			ret = pthread_join(threads[i].id, &status); +			DB_BENCH_ASSERT(ret == 0); +			contended += threads[i].contentions; +		} + +	} else +#endif +		contended = time_latches(dbenv, mutex, count); +	TIMER_STOP; + +	printf("# %d mutex lock-unlock pairs of %d thread%s\n", count, +	    nthreads, nthreads == 1 ? "" : "s"); +	TIMER_DISPLAY(count); + +	DB_BENCH_ASSERT(dbenv->mutex_free(dbenv, mutex) == 0); +	DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0); +	COMPQUIET(contended, 0); + +	return (0); +} diff --git a/db-4.8.30/test_micro/source/b_load.c b/db-4.8.30/test_micro/source/b_load.c new file mode 100644 index 0000000..9cbb968 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_load.c @@ -0,0 +1,164 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_open.c b/db-4.8.30/test_micro/source/b_open.c new file mode 100644 index 0000000..1c47e43 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_open.c @@ -0,0 +1,144 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_put.c b/db-4.8.30/test_micro/source/b_put.c new file mode 100644 index 0000000..c9b2d61 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_put.c @@ -0,0 +1,225 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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, dsize; +	int ch, 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 = (u_int32_t)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, 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); +			(void)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; +	} + +	data.size = dsize; +	DB_BENCH_ASSERT( +	    (data.data = malloc((size_t)dsize)) != NULL); + +	/* Store the key/data pair count times. */ +	TIMER_START; +	for (i = 0; i < count; ++i) { +		/* Change data value so the secondaries are updated. */ +		(void)snprintf(data.data, data.size, "%10lu", (u_long)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 = pdata->data; +	skey->size = pdata->size; + +	COMPQUIET(dbp, NULL); +	COMPQUIET(pkey, 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); +} diff --git a/db-4.8.30/test_micro/source/b_recover.c b/db-4.8.30/test_micro/source/b_recover.c new file mode 100644 index 0000000..cbe3306 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_recover.c @@ -0,0 +1,141 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_txn.c b/db-4.8.30/test_micro/source/b_txn.c new file mode 100644 index 0000000..ddd7045 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_txn.c @@ -0,0 +1,93 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_txn_write.c b/db-4.8.30/test_micro/source/b_txn_write.c new file mode 100644 index 0000000..dcf189f --- /dev/null +++ b/db-4.8.30/test_micro/source/b_txn_write.c @@ -0,0 +1,172 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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); +} diff --git a/db-4.8.30/test_micro/source/b_uname.c b/db-4.8.30/test_micro/source/b_uname.c new file mode 100644 index 0000000..fab0e7c --- /dev/null +++ b/db-4.8.30/test_micro/source/b_uname.c @@ -0,0 +1,147 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +#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 diff --git a/db-4.8.30/test_micro/source/b_util.c b/db-4.8.30/test_micro/source/b_util.c new file mode 100644 index 0000000..2610bc5 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_util.c @@ -0,0 +1,157 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +#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 +} diff --git a/db-4.8.30/test_micro/source/b_workload.c b/db-4.8.30/test_micro/source/b_workload.c new file mode 100644 index 0000000..6851a43 --- /dev/null +++ b/db-4.8.30/test_micro/source/b_workload.c @@ -0,0 +1,631 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +#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, inscount; +	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. +	 */ +	inscount = 2 * config->pcount; +	if (inscount > 100000) +		inscount = 100000; + +	for (i = 0; i < inscount; ++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); +} diff --git a/db-4.8.30/test_micro/source/b_workload.h b/db-4.8.30/test_micro/source/b_workload.h new file mode 100644 index 0000000..799720d --- /dev/null +++ b/db-4.8.30/test_micro/source/b_workload.h @@ -0,0 +1,153 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +/* + * 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 +{ +	u_int32_t ksize; +	u_int32_t dsize; +	size_t orderedkeys; +	size_t num_dups; +	u_int32_t pagesz; +	u_int32_t cachesz; +	u_int32_t pcount; +	size_t gcount; +	size_t cursor_del; +	size_t verbose; +	test_type workload; +	u_int32_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; diff --git a/db-4.8.30/test_micro/source/bench.h b/db-4.8.30/test_micro/source/bench.h new file mode 100644 index 0000000..08493ab --- /dev/null +++ b/db-4.8.30/test_micro/source/bench.h @@ -0,0 +1,217 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ +#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 */ + +extern 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_latch __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 *[])); +u_int32_t part_callback __P((DB *, DBT *)); + +#endif /* !_BENCH_H_ */ diff --git a/db-4.8.30/test_micro/source/test_micro.c b/db-4.8.30/test_micro/source/test_micro.c new file mode 100644 index 0000000..49b43de --- /dev/null +++ b/db-4.8.30/test_micro/source/test_micro.c @@ -0,0 +1,223 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2009 Oracle.  All rights reserved. + * + * $Id$ + */ + +#include "bench.h" + +int main __P((int, char *[])); + +static int  run __P((char *)); +static int  usage __P((void)); + +char *progname;					/* program name */ +db_timespec __start_time, __end_time;		/* TIMER_START & TIMER_END */ + +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_latch", b_latch }, +	{ "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); +} | 
