client/server: pass back job options to client
authorJens Axboe <axboe@fb.com>
Wed, 16 Dec 2015 03:33:29 +0000 (20:33 -0700)
committerJens Axboe <axboe@fb.com>
Wed, 16 Dec 2015 03:33:29 +0000 (20:33 -0700)
Also fill in a few more missing pieces from the server based
json output, like time stamp.

Now the json output should match the local, on all accounts.

Signed-off-by: Jens Axboe <axboe@fb.com>
client.c
client.h
server.c
server.h
stat.c
stat.h

index c24f89b..366db71 100644 (file)
--- a/client.c
+++ b/client.c
@@ -59,6 +59,7 @@ int sum_stat_clients;
 
 static int sum_stat_nr;
 static struct json_object *root = NULL;
+static struct json_object *job_opt_object = NULL;
 static struct json_array *clients_array = NULL;
 static struct json_array *du_array = NULL;
 
@@ -117,11 +118,23 @@ static int read_data(int fd, void *data, size_t size)
 
 static void fio_client_json_init(void)
 {
+       char time_buf[32];
+       time_t time_p;
+
        if (!(output_format & FIO_OUTPUT_JSON))
                return;
 
+       time(&time_p);
+       os_ctime_r((const time_t *) &time_p, time_buf, sizeof(time_buf));
+       time_buf[strlen(time_buf) - 1] = '\0';
+
        root = json_create_object();
        json_object_add_value_string(root, "fio version", fio_version_string);
+       json_object_add_value_int(root, "timestamp", time_p);
+       json_object_add_value_string(root, "time", time_buf);
+
+       job_opt_object = json_create_object();
+       json_object_add_value_object(root, "global options", job_opt_object);
        clients_array = json_create_array();
        json_object_add_value_array(root, "client_stats", clients_array);
        du_array = json_create_array();
@@ -132,6 +145,7 @@ static void fio_client_json_fini(void)
 {
        if (!(output_format & FIO_OUTPUT_JSON))
                return;
+
        log_info("\n");
        json_print_object(root, NULL);
        log_info("\n");
@@ -176,6 +190,8 @@ void fio_put_client(struct fio_client *client)
        }
        if (client->files)
                free(client->files);
+       if (client->opt_lists)
+               free(client->opt_lists);
 
        if (!client->did_stat)
                sum_stat_clients--;
@@ -936,9 +952,13 @@ static void json_object_add_client_info(struct json_object *obj,
 static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
 {
        struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload;
+       struct flist_head *opt_list = NULL;
        struct json_object *tsobj;
 
-       tsobj = show_thread_status(&p->ts, &p->rs, NULL);
+       if (client->opt_lists && p->ts.thread_number <= client->jobs)
+               opt_list = &client->opt_lists[p->ts.thread_number - 1];
+
+       tsobj = show_thread_status(&p->ts, &p->rs, opt_list, NULL);
        client->did_stat = 1;
        if (tsobj) {
                json_object_add_client_info(tsobj, client);
@@ -958,7 +978,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
 
        if (++sum_stat_nr == sum_stat_clients) {
                strcpy(client_ts.name, "All clients");
-               tsobj = show_thread_status(&client_ts, &client_gs, NULL);
+               tsobj = show_thread_status(&client_ts, &client_gs, NULL, NULL);
                if (tsobj) {
                        json_object_add_client_info(tsobj, client);
                        json_array_add_value_object(clients_array, tsobj);
@@ -974,6 +994,35 @@ static void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd)
                show_group_stats(gs, NULL);
 }
 
+static void handle_job_opt(struct fio_client *client, struct fio_net_cmd *cmd)
+{
+       struct cmd_job_option *pdu = (struct cmd_job_option *) cmd->payload;
+       struct print_option *p;
+
+       pdu->global = le16_to_cpu(pdu->global);
+       pdu->groupid = le16_to_cpu(pdu->groupid);
+
+       p = malloc(sizeof(*p));
+       p->name = strdup((char *) pdu->name);
+       if (pdu->value[0] != '\0')
+               p->value = strdup((char *) pdu->value);
+       else
+               p->value = NULL;
+
+       if (pdu->global) {
+               const char *pos = "";
+
+               if (p->value)
+                       pos = p->value;
+
+               json_object_add_value_string(job_opt_object, p->name, pos);
+       } else if (client->opt_lists) {
+               struct flist_head *opt_list = &client->opt_lists[pdu->groupid];
+
+               flist_add_tail(&p->list, opt_list);
+       }
+}
+
 static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd)
 {
        struct cmd_text_pdu *pdu = (struct cmd_text_pdu *) cmd->payload;
@@ -1204,6 +1253,17 @@ static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd)
        client->jobs = le32_to_cpu(pdu->jobs);
        client->nr_stat = le32_to_cpu(pdu->stat_outputs);
 
+       if (client->jobs) {
+               int i;
+
+               if (client->opt_lists)
+                       free(client->opt_lists);
+
+               client->opt_lists = malloc(client->jobs * sizeof(struct flist_head));
+               for (i = 0; i < client->jobs; i++)
+                       INIT_FLIST_HEAD(&client->opt_lists[i]);
+       }
+
        sum_stat_clients += client->nr_stat;
 }
 
@@ -1516,6 +1576,10 @@ int fio_handle_client(struct fio_client *client)
                send_file(client, pdu, cmd->tag);
                break;
                }
+       case FIO_NET_CMD_JOB_OPT: {
+               handle_job_opt(client, cmd);
+               break;
+       }
        default:
                log_err("fio: unknown client op: %s\n", fio_server_op(cmd->opcode));
                break;
index 46e30ed..035e606 100644 (file)
--- a/client.h
+++ b/client.h
@@ -41,6 +41,8 @@ struct fio_client {
 
        char *name;
 
+       struct flist_head *opt_lists;
+
        int state;
 
        int skip_newline;
index ca17f9a..38a6bf8 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1512,6 +1512,34 @@ void fio_server_send_gs(struct group_run_stats *rs)
        fio_net_queue_cmd(FIO_NET_CMD_GS, &gs, sizeof(gs), NULL, SK_F_COPY);
 }
 
+void fio_server_send_job_options(struct flist_head *opt_list,
+                                unsigned int groupid)
+{
+       struct cmd_job_option pdu;
+       struct flist_head *entry;
+
+       if (flist_empty(opt_list))
+               return;
+
+       flist_for_each(entry, opt_list) {
+               struct print_option *p;
+
+               p = flist_entry(entry, struct print_option, list);
+               memset(&pdu, 0, sizeof(pdu));
+               if (groupid == -1U) {
+                       pdu.global = __cpu_to_le16(1);
+                       pdu.groupid = 0;
+               } else {
+                       pdu.global = 0;
+                       pdu.groupid = __cpu_to_le16(groupid);
+               }
+               memcpy(pdu.name, p->name, strlen(p->name));
+               if (p->value)
+                       memcpy(pdu.value, p->value, strlen(p->value));
+               fio_net_queue_cmd(FIO_NET_CMD_JOB_OPT, &pdu, sizeof(pdu), NULL, SK_F_COPY);
+       }
+}
+
 static void convert_agg(struct disk_util_agg *dst, struct disk_util_agg *src)
 {
        int i;
index d73ce1d..fca9a87 100644 (file)
--- a/server.h
+++ b/server.h
@@ -38,7 +38,7 @@ struct fio_net_cmd_reply {
 };
 
 enum {
-       FIO_SERVER_VER                  = 49,
+       FIO_SERVER_VER                  = 50,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
@@ -64,7 +64,8 @@ enum {
        FIO_NET_CMD_LOAD_FILE           = 19,
        FIO_NET_CMD_VTRIGGER            = 20,
        FIO_NET_CMD_SENDFILE            = 21,
-       FIO_NET_CMD_NR                  = 22,
+       FIO_NET_CMD_JOB_OPT             = 22,
+       FIO_NET_CMD_NR                  = 23,
 
        FIO_NET_CMD_F_MORE              = 1UL << 0,
 
@@ -181,6 +182,13 @@ struct cmd_iolog_pdu {
        struct io_sample samples[0];
 };
 
+struct cmd_job_option {
+       uint16_t global;
+       uint16_t groupid;
+       uint8_t name[64];
+       uint8_t value[128];
+};
+
 extern int fio_start_server(char *);
 extern int fio_server_text_output(int, const char *, size_t);
 extern int fio_net_send_cmd(int, uint16_t, const void *, off_t, uint64_t *, struct flist_head *);
@@ -196,6 +204,7 @@ struct group_run_stats;
 extern void fio_server_send_ts(struct thread_stat *, struct group_run_stats *);
 extern void fio_server_send_gs(struct group_run_stats *);
 extern void fio_server_send_du(void);
+extern void fio_server_send_job_options(struct flist_head *, unsigned int);
 extern int fio_server_get_verify_state(const char *, int, void **, int *);
 
 extern struct fio_net_cmd *fio_net_recv_cmd(int sk);
diff --git a/stat.c b/stat.c
index 1c1dceb..a3bfe63 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -1086,8 +1086,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts,
        log_buf(out, "\n");
 }
 
-static void json_add_job_opts(struct json_object *root, const char *name,
-                             struct flist_head *opt_list, bool num_jobs)
+void json_add_job_opts(struct json_object *root, const char *name,
+                      struct flist_head *opt_list, bool num_jobs)
 {
        struct json_object *dir_object;
        struct flist_head *entry;
@@ -1268,6 +1268,7 @@ static void show_thread_status_terse(struct thread_stat *ts,
 
 struct json_object *show_thread_status(struct thread_stat *ts,
                                       struct group_run_stats *rs,
+                                      struct flist_head *opt_list,
                                       struct buf_output *out)
 {
        struct json_object *ret = NULL;
@@ -1275,7 +1276,7 @@ struct json_object *show_thread_status(struct thread_stat *ts,
        if (output_format & FIO_OUTPUT_TERSE)
                show_thread_status_terse(ts, rs,  out);
        if (output_format & FIO_OUTPUT_JSON)
-               ret = show_thread_status_json(ts, rs, NULL);
+               ret = show_thread_status_json(ts, rs, opt_list);
        if (output_format & FIO_OUTPUT_NORMAL)
                show_thread_status_normal(ts, rs,  out);
 
@@ -1649,13 +1650,17 @@ void __show_run_stats(void)
                json_object_add_value_array(root, "jobs", array);
        }
 
+       if (is_backend)
+               fio_server_send_job_options(&get_global_options()->opt_list, -1U);
+
        for (i = 0; i < nr_ts; i++) {
                ts = &threadstats[i];
                rs = &runstats[ts->groupid];
 
-               if (is_backend)
+               if (is_backend) {
+                       fio_server_send_job_options(opt_lists[i], i);
                        fio_server_send_ts(ts, rs);
-               else {
+               else {
                        if (output_format & FIO_OUTPUT_TERSE)
                                show_thread_status_terse(ts, rs, &output[__FIO_OUTPUT_TERSE]);
                        if (output_format & FIO_OUTPUT_JSON) {
diff --git a/stat.h b/stat.h
index dda88fc..9c3f192 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -247,7 +247,7 @@ extern struct jobs_eta *get_jobs_eta(bool force, size_t *size);
 extern void stat_init(void);
 extern void stat_exit(void);
 
-extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct buf_output *);
+extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct flist_head *, struct buf_output *);
 extern void show_group_stats(struct group_run_stats *rs, struct buf_output *);
 extern int calc_thread_status(struct jobs_eta *je, int force);
 extern void display_thread_status(struct jobs_eta *je);