/* this tests tdb by doing lots of ops from several simultaneous
- writers - that stresses the locking code.
+ writers - that stresses the locking code.
*/
#include "replace.h"
static int hash_size = 2;
static int loopnum;
static int count_pipe;
+static bool mutex = false;
static struct tdb_logging_context log_ctx;
#ifdef PRINTF_ATTRIBUTE
system(ptr);
free(ptr);
}
-#endif
+#endif
}
static void fatal(const char *why)
static void usage(void)
{
- printf("Usage: tdbtorture [-t] [-k] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
+ printf("Usage: tdbtorture [-t] [-k] [-m] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
exit(0);
}
static void send_count_and_suicide(int sig)
{
+ ssize_t ret;
+
/* This ensures our successor can continue where we left off. */
- write(count_pipe, &loopnum, sizeof(loopnum));
+ do {
+ ret = write(count_pipe, &loopnum, sizeof(loopnum));
+ } while (ret == -1 && errno == EINTR);
/* This gives a unique signature. */
kill(getpid(), SIGUSR2);
}
-static int run_child(int i, int seed, unsigned num_loops, unsigned start)
+static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start)
{
- db = tdb_open_ex("torture.tdb", hash_size, TDB_DEFAULT,
+ int tdb_flags = TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH;
+
+ if (mutex) {
+ tdb_flags |= TDB_MUTEX_LOCKING;
+ }
+
+ db = tdb_open_ex(filename, hash_size, tdb_flags,
O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
if (!db) {
fatal("db open failed");
return (error_count < 100 ? error_count : 100);
}
+static char *test_path(const char *filename)
+{
+ const char *prefix = getenv("TEST_DATA_PREFIX");
+
+ if (prefix) {
+ char *path = NULL;
+ int ret;
+
+ ret = asprintf(&path, "%s/%s", prefix, filename);
+ if (ret == -1) {
+ return NULL;
+ }
+ return path;
+ }
+
+ return strdup(filename);
+}
+
int main(int argc, char * const *argv)
{
int i, seed = -1;
pid_t *pids;
int kill_random = 0;
int *done;
+ char *test_tdb;
log_ctx.log_fn = tdb_log;
- while ((c = getopt(argc, argv, "n:l:s:H:thk")) != -1) {
+ while ((c = getopt(argc, argv, "n:l:s:H:thkm")) != -1) {
switch (c) {
case 'n':
num_procs = strtol(optarg, NULL, 0);
case 'k':
kill_random = 1;
break;
+ case 'm':
+ mutex = tdb_runtime_check_for_robust_mutexes();
+ if (!mutex) {
+ printf("tdb_runtime_check_for_robust_mutexes() returned false\n");
+ exit(1);
+ }
+ break;
default:
usage();
}
}
- unlink("torture.tdb");
+ test_tdb = test_path("torture.tdb");
+
+ unlink(test_tdb);
if (seed == -1) {
seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
}
+ printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
+ num_procs, num_loops, hash_size, seed,
+ (always_transaction ? " (all within transactions)" : ""));
+
if (num_procs == 1 && !kill_random) {
/* Don't fork for this case, makes debugging easier. */
- error_count = run_child(0, seed, num_loops, 0);
+ error_count = run_child(test_tdb, 0, seed, num_loops, 0);
goto done;
}
pids = (pid_t *)calloc(sizeof(pid_t), num_procs);
+ if (pids == NULL) {
+ perror("Unable to allocate memory for pids");
+ exit(1);
+ }
done = (int *)calloc(sizeof(int), num_procs);
+ if (done == NULL) {
+ perror("Unable to allocate memory for done");
+ exit(1);
+ }
if (pipe(pfds) != 0) {
perror("Creating pipe");
for (i=0;i<num_procs;i++) {
if ((pids[i]=fork()) == 0) {
close(pfds[0]);
- if (i == 0) {
- printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
- num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");
- }
- exit(run_child(i, seed, num_loops, 0));
+ exit(run_child(test_tdb, i, seed, num_loops, 0));
}
}
|| WTERMSIG(status) == SIGUSR1) {
/* SIGUSR2 means they wrote to pipe. */
if (WTERMSIG(status) == SIGUSR2) {
- read(pfds[0], &done[j],
- sizeof(done[j]));
+ ssize_t ret;
+
+ do {
+ ret = read(pfds[0], &done[j],
+ sizeof(done[j]));
+ } while (ret == -1 && errno == EINTR);
}
pids[j] = fork();
if (pids[j] == 0)
- exit(run_child(j, seed, num_loops,
- done[j]));
+ exit(run_child(test_tdb, j, seed,
+ num_loops, done[j]));
printf("Restarting child %i for %u-%u\n",
j, done[j], num_loops);
continue;
done:
if (error_count == 0) {
- db = tdb_open_ex("torture.tdb", hash_size, TDB_DEFAULT,
+ int tdb_flags = TDB_DEFAULT;
+
+ if (mutex) {
+ tdb_flags |= TDB_NOLOCK;
+ }
+
+ db = tdb_open_ex(test_tdb, hash_size, tdb_flags,
O_RDWR, 0, &log_ctx, NULL);
if (!db) {
- fatal("db open failed");
+ fatal("db open failed\n");
+ exit(1);
}
if (tdb_check(db, NULL, NULL) == -1) {
- printf("db check failed");
+ printf("db check failed\n");
exit(1);
}
tdb_close(db);
printf("OK\n");
}
+ free(test_tdb);
return error_count;
}