X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb%2Ftools%2Ftdbtorture.c;h=0d5bcd2baf656ad67553e7e16114ddb09a9e3627;hp=9bc799530851a239538d8ca5aeeb7725550ec184;hb=233e3055c46ba2ed8fea326ac40ea0545eb0444f;hpb=6d35d746f123291ba93a592997dcd5b6fe7828cf diff --git a/ccan/tdb/tools/tdbtorture.c b/ccan/tdb/tools/tdbtorture.c index 9bc79953..0d5bcd2b 100644 --- a/ccan/tdb/tools/tdbtorture.c +++ b/ccan/tdb/tools/tdbtorture.c @@ -25,13 +25,21 @@ #define LOCKSTORE_PROB 5 #define TRAVERSE_PROB 20 #define TRAVERSE_READ_PROB 20 +#define TRAVERSE_MOD_PROB 100 +#define TRAVERSE_ABORT_PROB 500 #define CULL_PROB 100 #define KEYLEN 3 #define DATALEN 100 static struct tdb_context *db; static int in_transaction; +static int in_traverse; static int error_count; +static int always_transaction = 0; +static int hash_size = 2; +static int loopnum; +static int count_pipe; +static struct tdb_logging_context log_ctx; #ifdef PRINTF_ATTRIBUTE static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); @@ -39,16 +47,18 @@ static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const c static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) { va_list ap; - - error_count++; + + if (level != TDB_DEBUG_TRACE) + error_count++; va_start(ap, format); vfprintf(stdout, format, ap); va_end(ap); fflush(stdout); #if 0 - { + if (level != TDB_DEBUG_TRACE) { char *ptr; + signal(SIGUSR1, SIG_IGN); asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid()); system(ptr); free(ptr); @@ -75,14 +85,27 @@ static char *randbuf(int len) return buf; } -static int cull_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, - void *state) +static void addrec_db(void); +static int modify_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 + +#if TRAVERSE_MOD_PROB + if (random() % TRAVERSE_MOD_PROB == 0) { + addrec_db(); + } +#endif + +#if TRAVERSE_ABORT_PROB + if (random() % TRAVERSE_ABORT_PROB == 0) + return 1; +#endif + return 0; } @@ -104,29 +127,35 @@ static void addrec_db(void) data.dptr = (unsigned char *)d; data.dsize = dlen+1; +#if REOPEN_PROB + if (in_traverse == 0 && in_transaction == 0 && random() % REOPEN_PROB == 0) { + tdb_reopen_all(0); + goto next; + } +#endif + #if TRANSACTION_PROB - if (in_transaction == 0 && random() % TRANSACTION_PROB == 0) { + if (in_traverse == 0 && in_transaction == 0 && (always_transaction || 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 0 + if (in_traverse == 0 && in_transaction && random() % TRANSACTION_PROB == 0) { if (random() % TRANSACTION_PREPARE_PROB == 0) { if (tdb_transaction_prepare_commit(db) != 0) { fatal("tdb_transaction_prepare_commit failed"); } } -#endif if (tdb_transaction_commit(db) != 0) { fatal("tdb_transaction_commit failed"); } in_transaction--; goto next; } - if (in_transaction && random() % TRANSACTION_PROB == 0) { + + if (in_traverse == 0 && in_transaction && random() % TRANSACTION_PROB == 0) { if (tdb_transaction_cancel(db) != 0) { fatal("tdb_transaction_cancel failed"); } @@ -135,13 +164,6 @@ static void addrec_db(void) } #endif -#if REOPEN_PROB - if (in_transaction == 0 && random() % REOPEN_PROB == 0) { - tdb_reopen_all(0); - goto next; - } -#endif - #if DELETE_PROB if (random() % DELETE_PROB == 0) { tdb_delete(db, key); @@ -181,15 +203,20 @@ static void addrec_db(void) #endif #if TRAVERSE_PROB - if (random() % TRAVERSE_PROB == 0) { - tdb_traverse(db, cull_traverse, NULL); + /* FIXME: recursive traverses break transactions? */ + if (in_traverse == 0 && random() % TRAVERSE_PROB == 0) { + in_traverse++; + tdb_traverse(db, modify_traverse, NULL); + in_traverse--; goto next; } #endif #if TRAVERSE_READ_PROB - if (random() % TRAVERSE_READ_PROB == 0) { + if (in_traverse == 0 && random() % TRAVERSE_READ_PROB == 0) { + in_traverse++; tdb_traverse_read(db, NULL, NULL); + in_traverse--; goto next; } #endif @@ -211,24 +238,74 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, static void usage(void) { - printf("Usage: tdbtorture [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n"); + printf("Usage: tdbtorture [-t] [-k] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n"); exit(0); } +static void send_count_and_suicide(int sig) +{ + /* This ensures our successor can continue where we left off. */ + write(count_pipe, &loopnum, sizeof(loopnum)); + /* This gives a unique signature. */ + kill(getpid(), SIGUSR2); +} + +static int run_child(int i, int seed, unsigned num_loops, unsigned start) +{ + db = tdb_open_ex("torture.tdb", hash_size, TDB_DEFAULT, + O_RDWR | O_CREAT, 0600, &log_ctx, NULL); + if (!db) { + fatal("db open failed"); + } + + srand(seed + i); + srandom(seed + i); + + /* Set global, then we're ready to handle being killed. */ + loopnum = start; + signal(SIGUSR1, send_count_and_suicide); + + for (;loopnum