tdb: test for readonly locks mode on tdbbackup command
[samba.git] / lib / tdb / tools / tdbtorture.c
index a23d1543e57321147aab6f9ac003b8b3e3b582f7..3640dc7ed6cd592fcc21d1f3cb4d82d037c54b8c 100644 (file)
@@ -33,6 +33,7 @@ static int always_transaction = 0;
 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
@@ -216,21 +217,31 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
 
 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(const char *filename, int i, int seed, unsigned num_loops, unsigned start)
 {
-       db = tdb_open_ex(filename, 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");
@@ -302,7 +313,7 @@ int main(int argc, char * const *argv)
 
        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);
@@ -322,6 +333,13 @@ int main(int argc, char * const *argv)
                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();
                }
@@ -335,6 +353,10 @@ int main(int argc, char * const *argv)
                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(test_tdb, 0, seed, num_loops, 0);
@@ -342,7 +364,15 @@ int main(int argc, char * const *argv)
        }
 
        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");
@@ -353,10 +383,6 @@ int main(int argc, char * const *argv)
        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(test_tdb, i, seed, num_loops, 0));
                }
        }
@@ -405,8 +431,12 @@ int main(int argc, char * const *argv)
                            || 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)
@@ -435,7 +465,13 @@ int main(int argc, char * const *argv)
 
 done:
        if (error_count == 0) {
-               db = tdb_open_ex(test_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\n");