From ececeffd85db1b27c07cdf91a921fd203006daf6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 24 Feb 2010 10:53:05 +1030 Subject: tdb: add -k option to tdbtorture To test the case of death of a process during transaction commit, add a -k (kill random) option to tdbtorture. The easiest way to do this is to make every worker a child (unless there's only one child), which is why this patch is bigger than you might expect. Using -k without -t (always transactions) you expect corruption, though it doesn't happen every time. With -t, we currently get corruption but the next patch fixes that. Signed-off-by: Rusty Russell --- lib/tdb/tools/tdbtorture.c | 199 ++++++++++++++++++++++++++++++++------------- 1 file changed, 142 insertions(+), 57 deletions(-) (limited to 'lib/tdb/tools') diff --git a/lib/tdb/tools/tdbtorture.c b/lib/tdb/tools/tdbtorture.c index b0221a2503..5ee6991825 100644 --- a/lib/tdb/tools/tdbtorture.c +++ b/lib/tdb/tools/tdbtorture.c @@ -30,6 +30,10 @@ static struct tdb_context *db; static int in_transaction; 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); @@ -48,8 +52,9 @@ static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const c 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); @@ -211,24 +216,74 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, static void usage(void) { - printf("Usage: tdbtorture [-t] [-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); } - int main(int argc, char * const *argv) +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