Update GUI to attempt to graphically handle ETA output
authorJens Axboe <axboe@kernel.dk>
Wed, 29 Feb 2012 12:45:02 +0000 (13:45 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 29 Feb 2012 12:45:02 +0000 (13:45 +0100)
The whole layout will probably be changed, but for now it
demonstrates how to properly integrate with the net client
to handle the data and output it.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
client.c
client.h
eta.c
gfio.c
server.c
server.h
stat.h

index faa990b..842f225 100644 (file)
--- a/client.c
+++ b/client.c
 #include "flist.h"
 #include "hash.h"
 
-extern void (*update_thread_status)(char *status_message, double perc);
-
-struct client_eta {
-       struct jobs_eta eta;
-       unsigned int pending;
-};
-
 static void fio_client_text_op(struct fio_client *client,
                FILE *f, __u16 pdu_len, const char *buf)
 {
@@ -56,7 +49,6 @@ struct client_ops fio_client_ops = {
        .group_stats    = handle_gs,
        .eta            = handle_eta,
        .probe          = handle_probe,
-       /* status display, if NULL, printf is used */
 };
 
 static struct timeval eta_tv;
@@ -85,9 +77,6 @@ static int sum_stat_nr;
 #define FIO_CLIENT_HASH_MASK   (FIO_CLIENT_HASH_SZ - 1)
 static struct flist_head client_hash[FIO_CLIENT_HASH_SZ];
 
-static int handle_client(struct fio_client *client, struct client_ops *ops);
-static void dec_jobs_eta(struct client_eta *eta);
-
 static void fio_client_add_hash(struct fio_client *client)
 {
        int bucket = hash_long(client->fd, FIO_CLIENT_HASH_BITS);
@@ -135,7 +124,7 @@ static void remove_client(struct fio_client *client)
 
        if (!flist_empty(&client->eta_list)) {
                flist_del_init(&client->eta_list);
-               dec_jobs_eta(client->eta_in_flight);
+               fio_client_dec_jobs_eta(client->eta_in_flight, display_thread_status);
        }
 
        free(client->hostname);
@@ -681,7 +670,7 @@ static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd)
        print_disk_util(&du->dus, &du->agg, terse_output);
 }
 
-static void convert_jobs_eta(struct jobs_eta *je)
+void fio_client_convert_jobs_eta(struct jobs_eta *je)
 {
        int i;
 
@@ -689,12 +678,12 @@ static void convert_jobs_eta(struct jobs_eta *je)
        je->nr_ramp             = le32_to_cpu(je->nr_ramp);
        je->nr_pending          = le32_to_cpu(je->nr_pending);
        je->files_open          = le32_to_cpu(je->files_open);
-       je->m_rate              = le32_to_cpu(je->m_rate);
-       je->t_rate              = le32_to_cpu(je->t_rate);
-       je->m_iops              = le32_to_cpu(je->m_iops);
-       je->t_iops              = le32_to_cpu(je->t_iops);
 
        for (i = 0; i < 2; i++) {
+               je->m_rate[i]           = le32_to_cpu(je->m_rate[i]);
+               je->t_rate[i]           = le32_to_cpu(je->t_rate[i]);
+               je->m_iops[i]           = le32_to_cpu(je->m_iops[i]);
+               je->t_iops[i]           = le32_to_cpu(je->t_iops[i]);
                je->rate[i]     = le32_to_cpu(je->rate[i]);
                je->iops[i]     = le32_to_cpu(je->iops[i]);
        }
@@ -703,7 +692,7 @@ static void convert_jobs_eta(struct jobs_eta *je)
        je->eta_sec             = le64_to_cpu(je->eta_sec);
 }
 
-static void sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je)
+void fio_client_sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je)
 {
        int i;
 
@@ -711,12 +700,12 @@ static void sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je)
        dst->nr_ramp            += je->nr_ramp;
        dst->nr_pending         += je->nr_pending;
        dst->files_open         += je->files_open;
-       dst->m_rate             += je->m_rate;
-       dst->t_rate             += je->t_rate;
-       dst->m_iops             += je->m_iops;
-       dst->t_iops             += je->t_iops;
 
        for (i = 0; i < 2; i++) {
+               dst->m_rate[i]  += je->m_rate[i];
+               dst->t_rate[i]  += je->t_rate[i];
+               dst->m_iops[i]  += je->m_iops[i];
+               dst->t_iops[i]  += je->t_iops[i];
                dst->rate[i]    += je->rate[i];
                dst->iops[i]    += je->iops[i];
        }
@@ -727,10 +716,10 @@ static void sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je)
                dst->eta_sec = je->eta_sec;
 }
 
-static void dec_jobs_eta(struct client_eta *eta)
+void fio_client_dec_jobs_eta(struct client_eta *eta, void (*fn)(struct jobs_eta *))
 {
        if (!--eta->pending) {
-               display_thread_status(&eta->eta);
+               fn(&eta->eta);
                free(eta);
        }
 }
@@ -771,9 +760,9 @@ static void handle_eta(struct fio_client *client, struct fio_net_cmd *cmd)
        client->eta_in_flight = NULL;
        flist_del_init(&client->eta_list);
 
-       convert_jobs_eta(je);
-       sum_jobs_eta(&eta->eta, je);
-       dec_jobs_eta(eta);
+       fio_client_convert_jobs_eta(je);
+       fio_client_sum_jobs_eta(&eta->eta, je);
+       fio_client_dec_jobs_eta(eta, display_thread_status);
 }
 
 static void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd)
@@ -819,7 +808,7 @@ static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd)
                log_info("client <%s>: exited with error %d\n", client->hostname, client->error);
 }
 
-static int handle_client(struct fio_client *client, struct client_ops *ops)
+int fio_handle_client(struct fio_client *client, struct client_ops *ops)
 {
        struct fio_net_cmd *cmd;
 
@@ -917,7 +906,7 @@ static void request_client_etas(void)
        }
 
        while (skipped--)
-               dec_jobs_eta(eta);
+               fio_client_dec_jobs_eta(eta, display_thread_status);
 
        dprint(FD_NET, "client: requested eta tag %p\n", eta);
 }
@@ -984,9 +973,6 @@ int fio_handle_clients(struct client_ops *ops)
        init_thread_stat(&client_ts);
        init_group_run_stat(&client_gs);
 
-       /* Used by eta.c:display_thread_status() */
-       update_thread_status = ops->thread_status_display;
-
        while (!exit_backend && nr_clients) {
                struct flist_head *entry, *tmp;
                struct fio_client *client;
@@ -1042,7 +1028,7 @@ int fio_handle_clients(struct client_ops *ops)
                                log_err("fio: unknown client fd %d\n", pfds[i].fd);
                                continue;
                        }
-                       if (!handle_client(client, ops)) {
+                       if (!fio_handle_client(client, ops)) {
                                log_info("client: host=%s disconnected\n",
                                                client->hostname);
                                remove_client(client);
index acf31ff..4146607 100644 (file)
--- a/client.h
+++ b/client.h
@@ -6,6 +6,8 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include "stat.h"
+
 struct fio_net_cmd;
 
 struct fio_client {
@@ -64,10 +66,19 @@ struct client_ops {
        client_group_stats_op group_stats;
        client_eta_op eta;
        client_probe_op probe;
-       client_thread_status_display_op thread_status_display;
 };
 
 extern struct client_ops fio_client_ops;
 
+struct client_eta {
+       struct jobs_eta eta;
+       unsigned int pending;
+};
+
+extern int fio_handle_client(struct fio_client *, struct client_ops *ops);
+extern void fio_client_dec_jobs_eta(struct client_eta *eta, void (*fn)(struct jobs_eta *));
+extern void fio_client_sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je);
+extern void fio_client_convert_jobs_eta(struct jobs_eta *je);
+
 #endif
 
diff --git a/eta.c b/eta.c
index 64c02fe..b07ae80 100644 (file)
--- a/eta.c
+++ b/eta.c
@@ -7,8 +7,6 @@
 
 #include "fio.h"
 
-void (*update_thread_status)(char *status_message, double perc) = NULL;
-
 static char run_str[REAL_MAX_JOBS + 1];
 
 /*
@@ -85,7 +83,7 @@ static void check_str_update(struct thread_data *td)
 /*
  * Convert seconds to a printable string.
  */
-static void eta_to_str(char *str, unsigned long eta_sec)
+void eta_to_str(char *str, unsigned long eta_sec)
 {
        unsigned int d, h, m, s;
        int disp_hour = 0;
@@ -275,11 +273,14 @@ int calc_thread_status(struct jobs_eta *je, int force)
                    || td->runstate == TD_FSYNCING
                    || td->runstate == TD_PRE_READING) {
                        je->nr_running++;
-                       je->t_rate += td->o.rate[0] + td->o.rate[1];
-                       je->m_rate += td->o.ratemin[0] + td->o.ratemin[1];
-                       je->t_iops += td->o.rate_iops[0] + td->o.rate_iops[1];
-                       je->m_iops += td->o.rate_iops_min[0] +
-                                       td->o.rate_iops_min[1];
+                       je->t_rate[0] += td->o.rate[0];
+                       je->t_rate[1] += td->o.rate[1];
+                       je->m_rate[0] += td->o.ratemin[0];
+                       je->m_rate[1] += td->o.ratemin[1];
+                       je->t_iops[0] += td->o.rate_iops[0];
+                       je->t_iops[1] += td->o.rate_iops[1];
+                       je->m_iops[0] += td->o.rate_iops_min[0];
+                       je->m_iops[1] += td->o.rate_iops_min[1];
                        je->files_open += td->nr_open_files;
                } else if (td->runstate == TD_RAMP) {
                        je->nr_running++;
@@ -368,16 +369,19 @@ void display_thread_status(struct jobs_eta *je)
        }
 
        p += sprintf(p, "Jobs: %d (f=%d)", je->nr_running, je->files_open);
-       if (je->m_rate || je->t_rate) {
+       if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) {
                char *tr, *mr;
 
-               mr = num2str(je->m_rate, 4, 0, i2p);
-               tr = num2str(je->t_rate, 4, 0, i2p);
+               mr = num2str(je->m_rate[0] + je->m_rate[1], 4, 0, i2p);
+               tr = num2str(je->t_rate[0] + je->t_rate[1], 4, 0, i2p);
                p += sprintf(p, ", CR=%s/%s KB/s", tr, mr);
                free(tr);
                free(mr);
-       } else if (je->m_iops || je->t_iops)
-               p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops);
+       } else if (je->m_iops[0] || je->m_iops[1] || je->t_iops[0] || je->t_iops[1]) {
+               p += sprintf(p, ", CR=%d/%d IOPS",
+                                       je->t_iops[0] + je->t_iops[1],
+                                       je->m_iops[0] + je->t_iops[1]);
+       }
        if (je->eta_sec != INT_MAX && je->nr_running) {
                char perc_str[32];
                char *iops_str[2];
@@ -413,12 +417,8 @@ void display_thread_status(struct jobs_eta *je)
        }
        p += sprintf(p, "\r");
 
-       if (update_thread_status) {
-               update_thread_status(output, perc);
-       } else {
-               printf("%s", output);
-               fflush(stdout);
-       }
+       printf("%s", output);
+       fflush(stdout);
 }
 
 void print_thread_status(void)
diff --git a/gfio.c b/gfio.c
index 382b54b..b14eed3 100644 (file)
--- a/gfio.c
+++ b/gfio.c
 
 #include "fio.h"
 
+static void gfio_update_thread_status(char *status_message, double perc);
+
 #define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0])))
 
 typedef void (*clickfunction)(GtkWidget *widget, gpointer data);
 
-static void quit_clicked(GtkWidget *widget, gpointer data);
+static void connect_clicked(GtkWidget *widget, gpointer data);
 static void start_job_clicked(GtkWidget *widget, gpointer data);
 
 static struct button_spec {
        const char *buttontext;
        clickfunction f;
        const char *tooltiptext;
+       const int start_insensitive;
 } buttonspeclist[] = {
-#define START_JOB_BUTTON 0
+#define CONNECT_BUTTON 0
+#define START_JOB_BUTTON 1
+       { "Connect", connect_clicked, "Connect to host", 0 },
        { "Start Job",
                start_job_clicked,
-               "Send current fio job to fio server to be executed" },
+               "Send current fio job to fio server to be executed", 1 },
 };
 
 struct probe_widget {
@@ -53,6 +58,19 @@ struct probe_widget {
        GtkWidget *fio_ver;
 };
 
+struct eta_widget {
+       GtkWidget *jobs;
+       GtkWidget *files;
+       GtkWidget *read_bw;
+       GtkWidget *read_iops;
+       GtkWidget *cr_bw;
+       GtkWidget *cr_iops;
+       GtkWidget *write_bw;
+       GtkWidget *write_iops;
+       GtkWidget *cw_bw;
+       GtkWidget *cw_iops;
+};
+
 struct gui {
        GtkWidget *window;
        GtkWidget *vbox;
@@ -74,6 +92,7 @@ struct gui {
        GtkWidget *error_label;
        GtkTextBuffer *text;
        struct probe_widget probe;
+       struct eta_widget eta;
        pthread_t t;
 
        void *cookie;
@@ -114,9 +133,97 @@ static void gfio_group_stats_op(struct fio_net_cmd *cmd)
        fio_client_ops.group_stats(cmd);
 }
 
+static void gfio_update_eta(struct jobs_eta *je)
+{
+       static int eta_good;
+       char eta_str[128];
+       char output[256];
+       char tmp[32];
+       double perc = 0.0;
+       int i2p = 0;
+
+       eta_str[0] = '\0';
+       output[0] = '\0';
+
+       if (je->eta_sec != INT_MAX && je->elapsed_sec) {
+               perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec);
+               eta_to_str(eta_str, je->eta_sec);
+       }
+
+       sprintf(tmp, "%u", je->nr_running);
+       gtk_label_set_text(GTK_LABEL(ui.eta.jobs), tmp);
+       sprintf(tmp, "%u", je->files_open);
+       gtk_label_set_text(GTK_LABEL(ui.eta.files), tmp);
+
+#if 0
+       if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) {
+       if (je->m_rate || je->t_rate) {
+               char *tr, *mr;
+
+               mr = num2str(je->m_rate, 4, 0, i2p);
+               tr = num2str(je->t_rate, 4, 0, i2p);
+               gtk_label_set_text(GTK_LABEL(ui.eta.
+               p += sprintf(p, ", CR=%s/%s KB/s", tr, mr);
+               free(tr);
+               free(mr);
+       } else if (je->m_iops || je->t_iops)
+               p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops);
+#else
+       gtk_label_set_text(GTK_LABEL(ui.eta.cr_bw), "---");
+       gtk_label_set_text(GTK_LABEL(ui.eta.cr_iops), "---");
+       gtk_label_set_text(GTK_LABEL(ui.eta.cw_bw), "---");
+       gtk_label_set_text(GTK_LABEL(ui.eta.cw_iops), "---");
+#endif
+
+       if (je->eta_sec != INT_MAX && je->nr_running) {
+               char *iops_str[2];
+               char *rate_str[2];
+
+               if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running)
+                       strcpy(output, "-.-% done");
+               else {
+                       eta_good = 1;
+                       perc *= 100.0;
+                       sprintf(output, "%3.1f%% done", perc);
+               }
+
+               rate_str[0] = num2str(je->rate[0], 5, 10, i2p);
+               rate_str[1] = num2str(je->rate[1], 5, 10, i2p);
+
+               iops_str[0] = num2str(je->iops[0], 4, 1, 0);
+               iops_str[1] = num2str(je->iops[1], 4, 1, 0);
+
+               gtk_label_set_text(GTK_LABEL(ui.eta.read_bw), rate_str[0]);
+               gtk_label_set_text(GTK_LABEL(ui.eta.read_iops), iops_str[0]);
+               gtk_label_set_text(GTK_LABEL(ui.eta.write_bw), rate_str[1]);
+               gtk_label_set_text(GTK_LABEL(ui.eta.write_iops), iops_str[1]);
+
+               free(rate_str[0]);
+               free(rate_str[1]);
+               free(iops_str[0]);
+               free(iops_str[1]);
+       }
+
+       if (eta_str[0]) {
+               char *dst = output + strlen(output);
+
+               sprintf(dst, " - %s", eta_str);
+       }
+               
+       gfio_update_thread_status(output, perc);
+}
+
 static void gfio_eta_op(struct fio_client *client, struct fio_net_cmd *cmd)
 {
-       fio_client_ops.eta(client, cmd);
+       struct jobs_eta *je = (struct jobs_eta *) cmd->payload;
+       struct client_eta *eta = (struct client_eta *) (uintptr_t) cmd->tag;
+
+       client->eta_in_flight = NULL;
+       flist_del_init(&client->eta_list);
+
+       fio_client_convert_jobs_eta(je);
+       fio_client_sum_jobs_eta(&eta->eta, je);
+       fio_client_dec_jobs_eta(eta, gfio_update_eta);
 }
 
 static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd)
@@ -165,7 +272,6 @@ struct client_ops gfio_client_ops = {
        .group_stats            = gfio_group_stats_op,
        .eta                    = gfio_eta_op,
        .probe                  = gfio_probe_op,
-       .thread_status_display  = gfio_update_thread_status,
 };
 
 static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
@@ -200,8 +306,6 @@ static int send_job_files(struct gui *ui)
 
 static void start_job_thread(pthread_t *t, struct gui *ui)
 {
-       fio_clients_connect();
-
        if (send_job_files(ui)) {
                printf("Yeah, I didn't really like those options too much.\n");
                gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
@@ -216,11 +320,17 @@ static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
 {
        struct gui *ui = data;
 
-       printf("Start job button was clicked.\n");
        gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
        start_job_thread(&ui->t, ui);
 }
 
+static void connect_clicked(__attribute__((unused)) GtkWidget *widget,
+                gpointer data)
+{
+       fio_clients_connect();
+       gtk_widget_set_sensitive(ui.button[START_JOB_BUTTON], 1);
+}
+
 static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
                        struct button_spec *buttonspec)
 {
@@ -228,6 +338,7 @@ static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
        g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui);
        gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], TRUE, TRUE, 0);
        gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext);
+       gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive);
 }
 
 static void add_buttons(struct gui *ui,
@@ -370,7 +481,7 @@ static GtkActionEntry menu_items[] = {
         { "Quit",           GTK_STOCK_QUIT, NULL,   "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
        { "About",          GTK_STOCK_ABOUT, NULL,  NULL, NULL, G_CALLBACK(about_dialog) },
 };
-static gint nmenu_items = sizeof (menu_items) / sizeof(menu_items[0]);
+static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
 
 static const gchar *ui_string = " \
        <ui> \
@@ -498,28 +609,44 @@ static void init_ui(int *argc, char **argv[], struct gui *ui)
        gtk_container_add(GTK_CONTAINER (ui->hostname_hbox), ui->hostname_combo_box);
        gtk_container_add(GTK_CONTAINER (ui->topvbox), ui->hostname_hbox);
 
-       probe = gtk_frame_new("Host");
+       probe = gtk_frame_new("Job");
        gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3);
        probe_frame = gtk_vbox_new(FALSE, 3);
        gtk_container_add(GTK_CONTAINER(probe), probe_frame);
 
        probe_box = gtk_hbox_new(FALSE, 3);
        gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
-
        ui->probe.hostname = new_info_label_in_frame(probe_box, "Host");
        ui->probe.os = new_info_label_in_frame(probe_box, "OS");
        ui->probe.arch = new_info_label_in_frame(probe_box, "Architecture");
        ui->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version");
 
+       probe_box = gtk_hbox_new(FALSE, 3);
+       gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
+       ui->eta.jobs = new_info_label_in_frame(probe_box, "Jobs");
+       ui->eta.files = new_info_label_in_frame(probe_box, "Open files");
+
+       probe_box = gtk_hbox_new(FALSE, 3);
+       gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
+       ui->eta.read_bw = new_info_label_in_frame(probe_box, "Read BW");
+       ui->eta.read_iops = new_info_label_in_frame(probe_box, "IOPS");
+       ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
+       ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
+
+       probe_box = gtk_hbox_new(FALSE, 3);
+       gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
+       ui->eta.write_bw = new_info_label_in_frame(probe_box, "Write BW");
+       ui->eta.write_iops = new_info_label_in_frame(probe_box, "IOPS");
+       ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
+       ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
+
        /*
         * Set up thread status progress bar
         */
        ui->thread_status_pb = gtk_progress_bar_new();
-       gtk_progress_bar_set_fraction(
-               GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
-       gtk_progress_bar_set_text(
-               GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
-       gtk_container_add(GTK_CONTAINER (ui->topvbox), ui->thread_status_pb);
+       gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
+       gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
+       gtk_container_add(GTK_CONTAINER(ui->topvbox), ui->thread_status_pb);
 
        /*
         * Add a text box for text op messages 
index f263a0a..2d9b009 100644 (file)
--- a/server.c
+++ b/server.c
@@ -443,12 +443,12 @@ static int handle_send_eta_cmd(struct fio_net_cmd *cmd)
        je->nr_ramp             = cpu_to_le32(je->nr_ramp);
        je->nr_pending          = cpu_to_le32(je->nr_pending);
        je->files_open          = cpu_to_le32(je->files_open);
-       je->m_rate              = cpu_to_le32(je->m_rate);
-       je->t_rate              = cpu_to_le32(je->t_rate);
-       je->m_iops              = cpu_to_le32(je->m_iops);
-       je->t_iops              = cpu_to_le32(je->t_iops);
 
        for (i = 0; i < 2; i++) {
+               je->m_rate[i]   = cpu_to_le32(je->m_rate[i]);
+               je->t_rate[i]   = cpu_to_le32(je->t_rate[i]);
+               je->m_iops[i]   = cpu_to_le32(je->m_iops[i]);
+               je->t_iops[i]   = cpu_to_le32(je->t_iops[i]);
                je->rate[i]     = cpu_to_le32(je->rate[i]);
                je->iops[i]     = cpu_to_le32(je->iops[i]);
        }
index 2be6173..f2dd29f 100644 (file)
--- a/server.h
+++ b/server.h
@@ -38,7 +38,7 @@ struct fio_net_int_cmd {
 };
 
 enum {
-       FIO_SERVER_VER          = 6,
+       FIO_SERVER_VER          = 7,
 
        FIO_SERVER_MAX_PDU      = 1024,
 
diff --git a/stat.h b/stat.h
index 3115539..bdb858e 100644 (file)
--- a/stat.h
+++ b/stat.h
@@ -174,8 +174,8 @@ struct jobs_eta {
        uint32_t nr_ramp;
        uint32_t nr_pending;
        uint32_t files_open;
-       uint32_t m_rate, t_rate;
-       uint32_t m_iops, t_iops;
+       uint32_t m_rate[2], t_rate[2];
+       uint32_t m_iops[2], t_iops[2];
        uint32_t rate[2];
        uint32_t iops[2];
        uint64_t elapsed_sec;
@@ -197,5 +197,6 @@ extern void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, i
 extern void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src);
 extern void init_thread_stat(struct thread_stat *ts);
 extern void init_group_run_stat(struct group_run_stats *gs);
+extern void eta_to_str(char *str, unsigned long eta_sec);
 
 #endif