blkparse: split off the timestamp correction code in to a separate function
[blktrace.git] / btt / args.c
index 7fa087e6902edc60dd04a8d5218636802936e52f..5c5078ab2c81a8f86a5b1a31e647b346a5d9e736 100644 (file)
 #include <fcntl.h>
 #include "globals.h"
 
-#define S_OPTS "Ad:D:e:hi:I:l:M:o:p:q:s:S:t:T: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,
@@ -77,6 +91,18 @@ static struct option l_opts[] = {
                .flag = NULL,
                .val = 'l'
        },
+       {
+               .name = "periodic-latencies",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'L'
+       },
+       {
+               .name = "seeks-per-second",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'm'
+       },
        {
                .name = "dev-maps",
                .has_arg = required_argument,
@@ -95,12 +121,30 @@ static struct option l_opts[] = {
                .flag = NULL,
                .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,
@@ -125,6 +169,12 @@ static struct option l_opts[] = {
                .flag = NULL,
                .val = 'T'
        },
+       {
+               .name = "unplug-hist",
+               .has_arg = required_argument,
+               .flag = NULL,
+               .val = 'u'
+       },
        {
                .name = "version",
                .has_arg = no_argument,
@@ -137,13 +187,33 @@ 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[ -A               | --all-data ]\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" \
@@ -151,21 +221,70 @@ static char usage_str[] = \
        "[ -i <input name>  | --input-file=<input name> ]\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[])
@@ -174,48 +293,70 @@ void handle_args(int argc, char *argv[])
 
        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;
                case 'D':
-                       devices = strdup(optarg);
+                       devices = optarg;
                        break;
                case 'e':
-                       exes = strdup(optarg);
+                       exes = optarg;
                        break;
                case 'h':
                        usage(argv[0]);
                        exit(0);
                case 'i':
-                       input_name = strdup(optarg);
+                       input_name = optarg;
                        break;
                case 'l':
-                       d2c_name = strdup(optarg);
+                       d2c_name = optarg;
+                       break;
+               case 'L':
+                       plat_freq = atof(optarg);
                        break;
                case 'I':
                        iostat_name = strdup(optarg);
                        break;
+               case 'm':
+                       sps_name = optarg;
+                       break;
                case 'M':
                        if (dev_map_read(optarg))
                                exit(1);
                        break;
                case 'o':
-                       output_name = strdup(optarg);
+                       output_name = optarg;
                        break;
                case 'p':
                        per_io_name = strdup(optarg);
                        break;
+               case 'P':
+                       per_io_trees = optarg;
+                       break;
                case 'q':
-                       q2c_name = strdup(optarg);
+                       q2c_name = optarg;
+                       break;
+               case 'Q':
+                       aqd_name = optarg;
+                       break;
+               case 'r':
+                       ignore_remaps = 1;
                        break;
                case 's':
-                       seek_name = strdup(optarg);
+                       seek_name = optarg;
                        break;
                case 'S': {
                        unsigned int interval;
+
                        sscanf(optarg, "%u", &interval);
                        iostat_interval = (__u64)interval * 1000000000LL;
                        break;
@@ -228,12 +369,24 @@ void handle_args(int argc, char *argv[])
                        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);
@@ -245,49 +398,26 @@ void handle_args(int argc, char *argv[])
                exit(1);
        }
 
-       setup_ifile(input_name);
-
-       if (output_name == NULL)
-               ranges_ofp = avgs_ofp = stdout;
-       else {
-               char *fname = malloc(strlen(output_name) + 32);
-
-               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.dat\n", output_name);
-
-               sprintf(fname, "%s.avg", output_name);
-               avgs_ofp = fopen(fname, "w");
-               if (avgs_ofp == NULL) {
-                       perror(fname);
-                       exit(1);
-               }
-               if (verbose)
-                       printf("Sending stats data to %s.avg\n", output_name);
-
-               free(fname);
+       if (sps_name && !seek_name) {
+               fprintf(stderr, "FATAL: -m option requires -s options\n");
+               exit(1);
        }
 
-       if (iostat_name != NULL) {
-               iostat_ofp = fopen(iostat_name, "w");
-               if (iostat_ofp == NULL) {
-                       perror(iostat_name);
-                       exit(1);
-               }
-               setbuffer(iostat_ofp, malloc(64 * 1024), 64 * 1024);
-       }
+       setup_ifile(input_name);
 
-       if (per_io_name != NULL) {
-               per_io_ofp = fopen(per_io_name, "w");
-               if (per_io_ofp == NULL) {
-                       perror(per_io_name);
-                       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");
                }
-               setbuffer(per_io_ofp, malloc(64 * 1024), 64 * 1024);
        }
+
+       iostat_ofp = setup_ofile(iostat_name);
+       per_io_ofp = setup_ofile(per_io_name);
 }