blkparse: split off the timestamp correction code in to a separate function
[blktrace.git] / btt / args.c
index d7ecb489937869e8f1b48300411199d58f855ef4..5c5078ab2c81a8f86a5b1a31e647b346a5d9e736 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-
 #include "globals.h"
 
-#define S_OPTS "d:D:e:hlmM:i:o:Vv"
+#define SETBUFFER_SIZE (64 * 1024)
+
+#define S_OPTS "aAB:d:D:e:hi:I:l:L:m:M:o:p:P:q:Q:rs:S:t:T:u:VvXz:Z"
 static struct option l_opts[] = {
+       {
+               .name = "seek-absolute",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'a'
+       },
+       {
+               .name = "all-data",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'A'
+       },
+       {
+               .name = "dump-blocknos",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'B'
+       },
        {
                .name = "range-delta",
                .has_arg = required_argument,
@@ -55,14 +74,32 @@ static struct option l_opts[] = {
                .val = 'h'
        },
        {
-               .name = "lvm",
-               .has_arg = no_argument,
+               .name = "input-file",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'i'
+       },
+       {
+               .name = "iostat",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'I'
+       },
+       {
+               .name = "d2c-latencies",
+               .has_arg = required_argument,
                .flag = NULL,
                .val = 'l'
        },
        {
-               .name = "md",
-               .has_arg = no_argument,
+               .name = "periodic-latencies",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'L'
+       },
+       {
+               .name = "seeks-per-second",
+               .has_arg = required_argument,
                .flag = NULL,
                .val = 'm'
        },
@@ -73,16 +110,70 @@ static struct option l_opts[] = {
                .val = 'M'
        },
        {
-               .name = "input-file",
+               .name = "output-file",
                .has_arg = required_argument,
                .flag = NULL,
-               .val = 'i'
+               .val = 'o'
        },
        {
-               .name = "output-file",
+               .name = "per-io-dump",
                .has_arg = required_argument,
                .flag = NULL,
-               .val = 'o'
+               .val = 'p'
+       },
+       {
+               .name = "per-io-trees",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'P'
+       },
+       {
+               .name = "q2c-latencies",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'q'
+       },
+       {
+               .name = "active-queue-depth",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'Q'
+       },
+       {
+               .name = "no-remaps",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'r'
+       },
+       {
+               .name = "seeks",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 's'
+       },
+       {
+               .name = "iostat-interval",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'S'
+       },
+       {
+               .name = "time-start",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 't'
+       },
+       {
+               .name = "time-end",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'T'
+       },
+       {
+               .name = "unplug-hist",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'u'
        },
        {
                .name = "version",
@@ -96,34 +187,121 @@ static struct option l_opts[] = {
                .flag = NULL,
                .val = 'v'
        },
+       {
+               .name = "do-active",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'z'
+       },
+       {
+               .name = "easy-parse-avgs",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'X'
+       },
+       {
+               .name = "q2d-latencies",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'z'
+       },
        {
                .name = NULL,
        }
 };
 
 static char usage_str[] = \
-       "\n[ -d <seconds>     | --range-delta=<seconds> ]\n" \
+       "\n[ -a               | --seek-absolute ]\n" \
+       "[ -A               | --all-data ]\n" \
+       "[ -B <output name> | --dump-blocknos=<output name> ]\n" \
+       "[ -d <seconds>     | --range-delta=<seconds> ]\n" \
+       "[ -D <dev;...>     | --devices=<dev;...> ]\n" \
        "[ -e <exe,...>     | --exes=<exe,...>  ]\n" \
        "[ -h               | --help ]\n" \
        "[ -i <input name>  | --input-file=<input name> ]\n" \
-       "(-l | -m)          | (--lvm | -md)\n" \
+       "[ -I <output name> | --iostat=<output name> ]\n" \
+       "[ -l <output name> | --d2c-latencies=<output name> ]\n" \
+       "[ -L <freq>        | --periodic-latencies=<freq> ]\n" \
+       "[ -m <output name> | --seeks-per-second=<output name> ]\n" \
+       "[ -M <dev map>     | --dev-maps=<dev map>\n" \
        "[ -o <output name> | --output-file=<output name> ]\n" \
+       "[ -p <output name> | --per-io-dump=<output name> ]\n" \
+       "[ -P <output name> | --per-io-trees=<output name> ]\n" \
+       "[ -q <output name> | --q2c-latencies=<output name> ]\n" \
+       "[ -Q <output name> | --active-queue-depth=<output name> ]\n" \
+       "[ -r               | --no-remaps ]\n" \
+       "[ -s <output name> | --seeks=<output name> ]\n" \
+       "[ -S <interval>    | --iostat-interval=<interval> ]\n" \
+       "[ -t <sec>         | --time-start=<sec> ]\n" \
+       "[ -T <sec>         | --time-end=<sec> ]\n" \
+       "[ -u <output name> | --unplug-hist=<output name> ]\n" \
        "[ -V               | --version ]\n" \
-       "[ -v               | --verbose ]\n\n";
+       "[ -v               | --verbose ]\n" \
+       "[ -X               | --easy-parse-avgs ]\n" \
+       "[ -z <output name> | --q2d-latencies=<output name> ]\n" \
+       "[ -Z               | --do-active\n" \
+       "\n";
 
 static void usage(char *prog)
 {
-       fprintf(stderr, "Usage: %s %s %s", prog, bt_timeline_version,
-               usage_str);
+       fprintf(stderr, "Usage: %s %s", prog, usage_str);
+}
+
+static FILE *setup_ofile(char *fname)
+{
+       if (fname) {
+               char *buf;
+               FILE *ofp = my_fopen(fname, "w");
+
+               if (!ofp) {
+                       perror(fname);
+                       exit(1);
+               }
+
+               buf = malloc(SETBUFFER_SIZE);
+               setbuffer(ofp, buf, SETBUFFER_SIZE);
+
+               add_file(ofp, fname);
+               add_buf(buf);
+
+               return ofp;
+       }
+
+       return NULL;
+}
+
+static FILE *std_open(char *output_name, char *sfx, char *msg)
+{
+       FILE *fp;
+       char fname[strlen(output_name) + 32];
+
+       sprintf(fname, "%s.%s", output_name, sfx);
+       fp = my_fopen(fname, "w");
+       if (fp == NULL) {
+               perror(fname);
+               exit(1);
+       }
+       if (verbose)
+               printf("Sending %s to %s\n", msg, fname);
+
+       return fp;
 }
 
 void handle_args(int argc, char *argv[])
 {
        int c;
-       char *dev_map_fname = NULL;
 
        while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) {
                switch (c) {
+               case 'a':
+                       seek_absolute = 1;
+                       break;
+               case 'A':
+                       output_all_data = 1;
+                       break;
+               case 'B':
+                       bno_dump_name = optarg;
+                       break;
                case 'd':
                        sscanf(optarg, "%lf", &range_delta);
                        break;
@@ -140,66 +318,106 @@ void handle_args(int argc, char *argv[])
                        input_name = optarg;
                        break;
                case 'l':
-                       is_lvm = 1;
+                       d2c_name = optarg;
+                       break;
+               case 'L':
+                       plat_freq = atof(optarg);
+                       break;
+               case 'I':
+                       iostat_name = strdup(optarg);
                        break;
                case 'm':
-                       is_lvm = 0;
+                       sps_name = optarg;
                        break;
                case 'M':
-                       dev_map_fname = optarg;
+                       if (dev_map_read(optarg))
+                               exit(1);
                        break;
                case 'o':
                        output_name = optarg;
                        break;
+               case 'p':
+                       per_io_name = strdup(optarg);
+                       break;
+               case 'P':
+                       per_io_trees = optarg;
+                       break;
+               case 'q':
+                       q2c_name = optarg;
+                       break;
+               case 'Q':
+                       aqd_name = optarg;
+                       break;
+               case 'r':
+                       ignore_remaps = 1;
+                       break;
+               case 's':
+                       seek_name = optarg;
+                       break;
+               case 'S': {
+                       unsigned int interval;
+
+                       sscanf(optarg, "%u", &interval);
+                       iostat_interval = (__u64)interval * 1000000000LL;
+                       break;
+               }
+               case 't':
+                       sscanf(optarg, "%lf", &t_astart);
+                       time_bounded = 1;
+                       break;
+               case 'T':
+                       sscanf(optarg, "%lf", &t_aend);
+                       time_bounded = 1;
+                       break;
+               case 'u':
+                       unplug_hist_name = optarg;
+                       break;
                case 'v':
                        verbose = 1;
                        break;
                case 'V':
                        printf("%s version %s\n", argv[0], bt_timeline_version);
                        exit(0);
+               case 'X':
+                       easy_parse_avgs++;
+                       break;
+               case 'z':
+                       q2d_name = optarg;
+                       break;
+               case 'Z':
+                       do_p_live = 1;
+                       break;
                default:
                        usage(argv[0]);
                        exit(1);
                }
        }
 
-       if (input_name == NULL || is_lvm < 0) {
+       if (input_name == NULL) {
                usage(argv[0]);
                exit(1);
        }
 
-       ifd = open(input_name, O_RDONLY);
-       if (ifd < 0) {
-               perror(input_name);
+       if (sps_name && !seek_name) {
+               fprintf(stderr, "FATAL: -m option requires -s options\n");
                exit(1);
        }
 
-       if (dev_map_fname && dev_map_read(dev_map_fname))
-               exit(1);
-
-       if (output_name == NULL)
-               ranges_ofp = avgs_ofp = stdout;
-       else {
-               char *fname = malloc(sizeof(output_name) + 20);
+       setup_ifile(input_name);
 
-               sprintf(fname, "%s.dat", output_name);
-               ranges_ofp = fopen(fname, "w");
-               if (ranges_ofp == NULL) {
-                       perror(fname);
-                       exit(1);
-               }
-               if (verbose)
-                       printf("Sending range data to %s\n", output_name);
-
-               sprintf(fname, "%s.avg", output_name);
-               avgs_ofp = fopen(fname, "w");
-               if (avgs_ofp == NULL) {
-                       perror(fname);
-                       exit(1);
+       if (output_name == NULL) {
+               rngs_ofp = avgs_ofp = msgs_ofp = stdout;
+               easy_parse_avgs = 0;
+       } else {
+               rngs_ofp = std_open(output_name, "dat", "range data");
+               avgs_ofp = std_open(output_name, "avg", "stats data");
+               msgs_ofp = std_open(output_name, "msg", "K messages");
+               if (easy_parse_avgs) {
+                       xavgs_ofp = std_open(output_name, "xvg",
+                                            "EZ stats data");
                }
-               if (verbose)
-                       printf("Sending stats data to %s\n", output_name);
-
-               free(fname);
        }
+
+       iostat_ofp = setup_ofile(iostat_name);
+       per_io_ofp = setup_ofile(per_io_name);
 }