diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-09-22 03:56:41 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:38:41 -0500 |
commit | ede8415d61b6791114c65de1c283a4e8c11f1585 (patch) | |
tree | f57fed9af4459d650db40546527ba230382a3248 /source4/lib/tdb/tools | |
parent | d6de10b409329084075c59d9371695871c738362 (diff) | |
download | samba-ede8415d61b6791114c65de1c283a4e8c11f1585.tar.gz samba-ede8415d61b6791114c65de1c283a4e8c11f1585.tar.bz2 samba-ede8415d61b6791114c65de1c283a4e8c11f1585.zip |
r10405: added transactions into tdb, and hook them into ldb. See my
samba-technical posting for more details on the transactions design.
This also adds a number of command line arguments to tdbtorture,
making it more flexible, and fixes some lock deadlock conditions in
the tdbtorture code.
(This used to be commit 06bd8abba942ec9f1e23f5c5d546cbb71ca3a701)
Diffstat (limited to 'source4/lib/tdb/tools')
-rw-r--r-- | source4/lib/tdb/tools/tdbtool.c | 26 | ||||
-rw-r--r-- | source4/lib/tdb/tools/tdbtorture.c | 129 |
2 files changed, 114 insertions, 41 deletions
diff --git a/source4/lib/tdb/tools/tdbtool.c b/source4/lib/tdb/tools/tdbtool.c index 5a8c871699..0941a73118 100644 --- a/source4/lib/tdb/tools/tdbtool.c +++ b/source4/lib/tdb/tools/tdbtool.c @@ -34,6 +34,7 @@ #include <sys/time.h> #include <ctype.h> #include <signal.h> +#include <stdarg.h> #include "tdb.h" /* a tdb tool for manipulating a tdb database */ @@ -77,6 +78,19 @@ static void print_asc(unsigned char *buf,int len) printf("%c",isprint(buf[i])?buf[i]:'.'); } +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(struct tdb_context *t, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log(struct tdb_context *t, int level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +} + static void print_data(unsigned char *buf,int len) { int i=0; @@ -131,7 +145,7 @@ static void help(void) "\n"); } -static void terror(char *why) +static void terror(const char *why) { printf("%s\n", why); } @@ -175,8 +189,8 @@ static void create_tdb(void) return; } if (tdb) tdb_close(tdb); - tdb = tdb_open(tok, 0, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT | O_TRUNC, 0600); + tdb = tdb_open_ex(tok, 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT | O_TRUNC, 0600, tdb_log, NULL); if (!tdb) { printf("Could not create %s: %s\n", tok, strerror(errno)); } @@ -190,7 +204,7 @@ static void open_tdb(void) return; } if (tdb) tdb_close(tdb); - tdb = tdb_open(tok, 0, 0, O_RDWR, 0600); + tdb = tdb_open_ex(tok, 0, 0, O_RDWR, 0600, tdb_log, NULL); if (!tdb) { printf("Could not open %s: %s\n", tok, strerror(errno)); } @@ -326,7 +340,7 @@ static void move_rec(void) print_rec(tdb, key, dbuf, NULL); - dst_tdb = tdb_open(file, 0, 0, O_RDWR, 0600); + dst_tdb = tdb_open_ex(file, 0, 0, O_RDWR, 0600, tdb_log, NULL); if ( !dst_tdb ) { terror("unable to open destination tdb"); return; @@ -377,7 +391,7 @@ static void info_tdb(void) printf("%d records totalling %d bytes\n", count, total_bytes); } -static char *tdb_getline(char *prompt) +static char *tdb_getline(const char *prompt) { static char line[1024]; char *p; diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 0cf82fa5a5..b0a2e7484f 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -1,6 +1,8 @@ /* this tests tdb by doing lots of ops from several simultaneous - writers - that stresses the locking code. Build with TDB_DEBUG=1 - for best effect */ + writers - that stresses the locking code. +*/ + +#define _GNU_SOURCE #ifndef _SAMBA_BUILD_ #include <stdlib.h> @@ -28,11 +30,14 @@ #endif +#include <getopt.h> + #define REOPEN_PROB 30 #define DELETE_PROB 8 #define STORE_PROB 4 #define APPEND_PROB 6 -#define LOCKSTORE_PROB 0 +#define TRANSACTION_PROB 10 +#define LOCKSTORE_PROB 5 #define TRAVERSE_PROB 20 #define CULL_PROB 100 #define KEYLEN 3 @@ -40,6 +45,7 @@ #define LOCKLEN 20 static struct tdb_context *db; +static int in_transaction; #ifdef PRINTF_ATTRIBUTE static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); @@ -84,25 +90,25 @@ static char *randbuf(int len) static int cull_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { +#if CULL_PROB if (random() % CULL_PROB == 0) { tdb_delete(tdb, key); } +#endif return 0; } static void addrec_db(void) { - int klen, dlen, slen; - char *k, *d, *s; - TDB_DATA key, data, lockkey; + int klen, dlen; + char *k, *d; + TDB_DATA key, data; klen = 1 + (rand() % KEYLEN); dlen = 1 + (rand() % DATALEN); - slen = 1 + (rand() % LOCKLEN); k = randbuf(klen); d = randbuf(dlen); - s = randbuf(slen); key.dptr = (unsigned char *)k; key.dsize = klen+1; @@ -110,11 +116,32 @@ static void addrec_db(void) data.dptr = (unsigned char *)d; data.dsize = dlen+1; - lockkey.dptr = (unsigned char *)s; - lockkey.dsize = slen+1; +#if TRANSACTION_PROB + if (in_transaction == 0 && random() % TRANSACTION_PROB == 0) { + if (tdb_transaction_start(db) != 0) { + fatal("tdb_transaction_start failed"); + } + in_transaction++; + goto next; + } + if (in_transaction && random() % TRANSACTION_PROB == 0) { + if (tdb_transaction_commit(db) != 0) { + fatal("tdb_transaction_commit failed"); + } + in_transaction--; + goto next; + } + if (in_transaction && random() % TRANSACTION_PROB == 0) { + if (tdb_transaction_cancel(db) != 0) { + fatal("tdb_transaction_cancel failed"); + } + in_transaction--; + goto next; + } +#endif #if REOPEN_PROB - if (random() % REOPEN_PROB == 0) { + if (in_transaction == 0 && random() % REOPEN_PROB == 0) { tdb_reopen_all(); goto next; } @@ -147,13 +174,13 @@ static void addrec_db(void) #if LOCKSTORE_PROB if (random() % LOCKSTORE_PROB == 0) { - tdb_chainlock(db, lockkey); + tdb_chainlock(db, key); data = tdb_fetch(db, key); if (tdb_store(db, key, data, TDB_REPLACE) != 0) { fatal("tdb_store failed"); } if (data.dptr) free(data.dptr); - tdb_chainunlock(db, lockkey); + tdb_chainunlock(db, key); goto next; } #endif @@ -171,7 +198,6 @@ static void addrec_db(void) next: free(k); free(d); - free(s); } static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, @@ -181,38 +207,71 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, return 0; } -#ifndef NPROC -#define NPROC 2 -#endif - -#ifndef NLOOPS -#define NLOOPS 5000 -#endif - - int main(int argc, const char *argv[]) +static void usage(void) { - int i, seed=0; - int loops = NLOOPS; - pid_t pids[NPROC]; + printf("Usage: tdbtorture [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n"); + exit(0); +} - pids[0] = getpid(); + int main(int argc, char * const *argv) +{ + int i, seed = -1; + int num_procs = 2; + int num_loops = 5000; + int hash_size = 2; + int c; + extern char *optarg; + pid_t *pids; + + while ((c = getopt(argc, argv, "n:l:s:H:h")) != -1) { + switch (c) { + case 'n': + num_procs = strtol(optarg, NULL, 0); + break; + case 'l': + num_loops = strtol(optarg, NULL, 0); + break; + case 'H': + hash_size = strtol(optarg, NULL, 0); + break; + case 's': + seed = strtol(optarg, NULL, 0); + break; + default: + usage(); + } + } unlink("torture.tdb"); - for (i=0;i<NPROC-1;i++) { + pids = calloc(sizeof(pid_t), num_procs); + pids[0] = getpid(); + + for (i=0;i<num_procs-1;i++) { if ((pids[i+1]=fork()) == 0) break; } - db = tdb_open("torture.tdb", 2, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT, 0600); + db = tdb_open_ex("torture.tdb", hash_size, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT, 0600, tdb_log, NULL); if (!db) { fatal("db open failed"); } - tdb_logging_function(db, tdb_log); - srand(seed + getpid()); - srandom(seed + getpid() + time(NULL)); - for (i=0;i<loops;i++) addrec_db(); + if (seed == -1) { + seed = (getpid() + time(NULL)) & 0x7FFFFFFF; + } + + if (i == 0) { + printf("testing with %d processes, %d loops, %d hash_size, seed=%d\n", + num_procs, num_loops, hash_size, seed); + } + + srand(seed + i); + srandom(seed + i); + + for (i=0;i<num_loops;i++) { + addrec_db(); + } tdb_traverse(db, NULL, NULL); tdb_traverse(db, traverse_fn, NULL); @@ -221,7 +280,7 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, tdb_close(db); if (getpid() == pids[0]) { - for (i=0;i<NPROC-1;i++) { + for (i=0;i<num_procs-1;i++) { int status; if (waitpid(pids[i+1], &status, 0) != pids[i+1]) { printf("failed to wait for %d\n", |