fix a debug statement to print also the directory name (and not
[tridge/dbench.git] / dbench.c
index 5b8d910f6bd6779ca625e846b7231d65a76b8ec2..725deb7abfdf246544f5306224d05a8d6c8cfb74 100644 (file)
--- a/dbench.c
+++ b/dbench.c
@@ -27,6 +27,7 @@
 #include <sys/sem.h>
 
 struct options options = {
+       .backend             = "fileio",
        .timelimit           = 600,
        .loadfile            = DATADIR "/client.txt",
        .directory           = ".",
@@ -41,12 +42,17 @@ struct options options = {
        .ea_enable           = 0,
        .clients_per_process = 1,
        .server              = "localhost",
+       .export              = "/tmp",
+       .protocol            = "tcp",
+       .run_once            = 0,
+       .trunc_io            = 0,
 };
 
 static struct timeval tv_start;
 static struct timeval tv_end;
 static int barrier=-1;
 static double throughput;
+struct nb_operations *nb_ops;
 
 static FILE *open_loadfile(void)
 {
@@ -108,7 +114,7 @@ static void sig_alarm(int sig)
                for (i=0;i<nclients;i++) {
                        children[i].bytes_done_warmup = children[i].bytes;
                        children[i].worst_latency = 0;
-                       memset(&children[i].op, 0, sizeof(children[i].op));
+                       memset(&children[i].ops, 0, sizeof(children[i].ops));
                }
                goto next;
        }
@@ -157,59 +163,55 @@ next:
 }
 
 
-static const struct {
-       const char *name;
-       size_t offset;
-} op_names[] = {
-#define OP_NAME(opname) { #opname, offsetof(struct opnames, op_ ## opname) }
-       OP_NAME(NTCreateX),
-       OP_NAME(Close),
-       OP_NAME(Rename),
-       OP_NAME(Unlink),
-       OP_NAME(Deltree),
-       OP_NAME(Rmdir),
-       OP_NAME(Mkdir),
-       OP_NAME(Qpathinfo),
-       OP_NAME(Qfileinfo),
-       OP_NAME(Qfsinfo),
-       OP_NAME(Sfileinfo),
-       OP_NAME(Find),
-       OP_NAME(WriteX),
-       OP_NAME(ReadX),
-       OP_NAME(LockX),
-       OP_NAME(UnlockX),
-       OP_NAME(Flush),
-};
+static void show_one_latency(struct op *ops, struct op *ops_all)
+{
+       int i;
+       printf(" Operation                Count    AvgLat    MaxLat\n");
+       printf(" --------------------------------------------------\n");
+       for (i=0;nb_ops->ops[i].name;i++) {
+               struct op *op1, *op_all;
+               op1    = &ops[i];
+               op_all = &ops_all[i];
+               if (op_all->count == 0) continue;
+               printf(" %-22s %7u %9.03f %9.03f\n",
+                      nb_ops->ops[i].name, op1->count, 
+                      1000*op1->total_time/op1->count,
+                      op1->max_latency*1000);
+       }
+       printf("\n");
+}
 
 static void report_latencies(void)
 {
-       struct opnames sum;
-       int i, j, n = (sizeof(op_names)/sizeof(op_names[0]));
+       struct op sum[MAX_OPS];
+       int i, j;
        struct op *op1, *op2;
        struct child_struct *child;
 
-       memset(&sum, 0, sizeof(sum));
-       for (i=0;i<n;i++) {
-               op1 = (struct op *)(op_names[i].offset + (char *)&sum);
+       memset(sum, 0, sizeof(sum));
+       for (i=0;nb_ops->ops[i].name;i++) {
+               op1 = &sum[i];
                for (j=0;j<options.nprocs * options.clients_per_process;j++) {
                        child = &children[j];
-                       op2 = (struct op *)(op_names[i].offset + (char *)&child->op);
+                       op2 = &child->ops[i];
                        op1->count += op2->count;
                        op1->total_time += op2->total_time;
                        op1->max_latency = MAX(op1->max_latency, op2->max_latency);
                }
        }
-       printf(" Operation      Count    AvgLat    MaxLat\n");
-       printf(" ----------------------------------------\n");
-       for (i=0;i<n;i++) {
-               op1 = (struct op *)(op_names[i].offset + (char *)&sum);
-               if (op1->count == 0) continue;
-               printf(" %-12s %7u %9.03f %9.03f\n",
-                      op_names[i].name, op1->count, 
-                      1000*op1->total_time/op1->count,
-                      op1->max_latency*1000);
+       show_one_latency(sum, sum);
+
+       if (!options.per_client_results) {
+               return;
+       }
+
+       printf("Per client results:\n");
+       for (i=0;i<options.nprocs * options.clients_per_process;i++) {
+               child = &children[i];
+               printf("Client %u did %u lines and %.0f bytes\n", 
+                      i, child->line, child->bytes - child->bytes_done_warmup);
+               show_one_latency(child->ops, sum);              
        }
-       printf("\n");
 }
 
 /* this creates the specified number of child processes and runs fn()
@@ -275,7 +277,7 @@ static void create_procs(int nprocs, void (*fn)(struct child_struct *, const cha
                        setlinebuf(stdout);
 
                        for (j=0;j<options.clients_per_process;j++) {
-                               nb_setup(&children[i*options.clients_per_process + j]);
+                               nb_ops->setup(&children[i*options.clients_per_process + j]);
                        }
 
                        sbuf.sem_op = 0;
@@ -338,32 +340,15 @@ static void create_procs(int nprocs, void (*fn)(struct child_struct *, const cha
 }
 
 
-static void show_usage(void)
-{
-       printf("usage: dbench [OPTIONS] nprocs\n" \
-              "usage: tbench [OPTIONS] nprocs <server>\n" \
-              "options:\n" \
-              "  -v               show version\n" \
-              "  -t timelimit     run time in seconds (default 600)\n" \
-              "  -D directory     base directory to run in\n" \
-              "  -c loadfile      set location of the loadfile\n" \
-              "  -R               target rate (MByte/sec)\n" \
-              "  -s               synchronous file IO\n" \
-              "  -F               fsync on write\n" \
-              "  -S               synchronous directories (mkdir, unlink...)\n" \
-              "  -x               enable EA support\n" \
-              "  -T options       set socket options for tbench\n");
-       exit(1);
-}
-
-
 
-static int process_opts(int argc, const char **argv)
+static void process_opts(int argc, const char **argv)
 {
        const char **extra_argv;
        int extra_argc = 0;
        struct poptOption popt_options[] = {
                POPT_AUTOHELP
+               { "backend", 'B', POPT_ARG_STRING, &options.backend, 0, 
+                 "dbench backend (fileio, sockio, nfs)", "string" },
                { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, 
                  "timelimit", "integer" },
                { "loadfile",  'c', POPT_ARG_STRING, &options.loadfile, 0, 
@@ -386,8 +371,30 @@ static int process_opts(int argc, const char **argv)
                  "disable name resolution simulation", NULL },
                { "clients-per-process", 0, POPT_ARG_INT, &options.clients_per_process, 0, 
                  "number of clients per process", NULL },
+               { "trunc-io", 0, POPT_ARG_INT, &options.trunc_io, 0, 
+                 "truncate all io to this size", NULL },
                { "one-byte-write-fix", 0, POPT_ARG_NONE, &options.one_byte_write_fix, 0, 
                  "try to fix 1 byte writes", NULL },
+               { "stat-check", 0, POPT_ARG_NONE, &options.stat_check, 0, 
+                 "check for pointless calls with stat", NULL },
+               { "fake-io", 0, POPT_ARG_NONE, &options.fake_io, 0, 
+                 "fake up read/write calls", NULL },
+               { "skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0, 
+                 "skip cleanup operations", NULL },
+               { "per-client-results", 0, POPT_ARG_NONE, &options.per_client_results, 0, 
+                 "show results per client", NULL },
+               { "server",  0, POPT_ARG_STRING, &options.server, 0, 
+                 "server", NULL },
+               { "export",  0, POPT_ARG_STRING, &options.export, 0, 
+                 "export", NULL },
+               { "protocol",  0, POPT_ARG_STRING, &options.protocol, 0, 
+                 "protocol", NULL },
+               { "run-once", 0, POPT_ARG_NONE, &options.run_once, 0,
+                 "Stop once reaching the end of the loadfile", NULL},
+               { "scsi",  0, POPT_ARG_STRING, &options.scsi_dev, 0, 
+                 "scsi device", NULL },
+               { "warmup", 0, POPT_ARG_INT, &options.warmup, 0, 
+                 "How meny seconds of warmup to run", NULL },
                POPT_TABLEEND
        };
        poptContext pc;
@@ -396,12 +403,13 @@ static int process_opts(int argc, const char **argv)
        pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
-               switch (opt) {
-               default:
-                       fprintf(stderr, "Invalid option %s: %s\n", 
-                               poptBadOption(pc, 0), poptStrerror(opt));
+               if (strcmp(poptBadOption(pc, 0), "-h") == 0) {
+                       poptPrintHelp(pc, stdout, 0);
                        exit(1);
                }
+               fprintf(stderr, "Invalid option %s: %s\n", 
+                       poptBadOption(pc, 0), poptStrerror(opt));
+               exit(1);
        }
 
        /* setup the remaining options for the main program to use */
@@ -429,8 +437,6 @@ static int process_opts(int argc, const char **argv)
        if (extra_argc >= 2) {
                options.server = extra_argv[1];
        }
-
-       return 1;
 }
 
 
@@ -445,8 +451,36 @@ static int process_opts(int argc, const char **argv)
 
        printf("dbench version %s - Copyright Andrew Tridgell 1999-2004\n\n", VERSION);
 
-       if (!process_opts(argc, argv))
-               show_usage();
+       if (strstr(argv[0], "dbench")) {
+               options.backend = "fileio";
+       } else if (strstr(argv[0], "tbench")) {
+               options.backend = "sockio";
+       } else if (strstr(argv[0], "nfsbench")) {
+               options.backend = "nfs";
+       } else if (strstr(argv[0], "scsibench")) {
+               options.backend = "scsi";
+       }
+
+       process_opts(argc, argv);
+
+       if (strcmp(options.backend, "fileio") == 0) {
+               extern struct nb_operations fileio_ops;
+               nb_ops = &fileio_ops;
+       } else if (strcmp(options.backend, "sockio") == 0) {
+               extern struct nb_operations sockio_ops;
+               nb_ops = &sockio_ops;
+       } else if (strcmp(options.backend, "nfs") == 0) {
+               extern struct nb_operations nfs_ops;
+               nb_ops = &nfs_ops;
+#ifdef HAVE_LINUX_SCSI_SG
+       } else if (strcmp(options.backend, "scsi") == 0) {
+               extern struct nb_operations scsi_ops;
+               nb_ops = &scsi_ops;
+#endif /* HAVE_LINUX_SCSI_SG */
+       } else {
+               printf("Unknown backend '%s'\n", options.backend);
+               exit(1);
+       }
 
        if (options.warmup == -1) {
                options.warmup = options.timelimit / 5;