Unify cli latency display
[fio.git] / gfio.c
diff --git a/gfio.c b/gfio.c
index 718d82174102fdc78178b44071f78413071290af..ebfa4b9de7dcd752926baaf00d66836d60caa334 100644 (file)
--- a/gfio.c
+++ b/gfio.c
@@ -99,6 +99,24 @@ struct gui {
        char **job_files;
 } ui;
 
+static void clear_ui_info(struct gui *ui)
+{
+       gtk_label_set_text(GTK_LABEL(ui->probe.hostname), "");
+       gtk_label_set_text(GTK_LABEL(ui->probe.os), "");
+       gtk_label_set_text(GTK_LABEL(ui->probe.arch), "");
+       gtk_label_set_text(GTK_LABEL(ui->probe.fio_ver), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.name), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.iotype), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.jobs), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.files), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.read_bw), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.read_iops), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.write_bw), "");
+       gtk_label_set_text(GTK_LABEL(ui->eta.write_iops), "");
+}
+
 static void gfio_set_connected(struct gui *ui, int connected)
 {
        if (connected) {
@@ -112,8 +130,7 @@ static void gfio_set_connected(struct gui *ui, int connected)
        }
 }
 
-static void gfio_text_op(struct fio_client *client,
-                FILE *f, __u16 pdu_len, const char *buf)
+static void gfio_text_op(struct fio_client *client, struct fio_net_cmd *cmd)
 {
 #if 0
        GtkTextBuffer *buffer;
@@ -127,7 +144,7 @@ static void gfio_text_op(struct fio_client *client,
        gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ui.textview),
                                        &end, 0.0, FALSE, 0.0,0.0);
 #else
-       fio_client_ops.text_op(client, f, pdu_len, buf);
+       fio_client_ops.text_op(client, cmd);
 #endif
 }
 
@@ -137,16 +154,18 @@ static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd
        fio_client_ops.disk_util(client, cmd);
 }
 
-static void gfio_thread_status_op(struct fio_net_cmd *cmd)
+static void gfio_thread_status_op(struct fio_client *client,
+                                 struct fio_net_cmd *cmd)
 {
        printf("gfio_thread_status_op called\n");
-       fio_client_ops.thread_status(cmd);
+       fio_client_ops.thread_status(client, cmd);
 }
 
-static void gfio_group_stats_op(struct fio_net_cmd *cmd)
+static void gfio_group_stats_op(struct fio_client *client,
+                               struct fio_net_cmd *cmd)
 {
        printf("gfio_group_stats_op called\n");
-       fio_client_ops.group_stats(cmd);
+       fio_client_ops.group_stats(client, cmd);
 }
 
 static void gfio_update_eta(struct jobs_eta *je)
@@ -229,19 +248,6 @@ static void gfio_update_eta(struct jobs_eta *je)
        gfio_update_thread_status(output, perc);
 }
 
-static void gfio_eta_op(struct fio_client *client, struct fio_net_cmd *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)
 {
        struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
@@ -323,6 +329,7 @@ static void gfio_client_timed_out(struct fio_client *client)
        gdk_threads_enter();
 
        gfio_set_connected(ui, 0);
+       clear_ui_info(ui);
 
        sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname);
 
@@ -348,7 +355,7 @@ struct client_ops gfio_client_ops = {
        .disk_util              = gfio_disk_util_op,
        .thread_status          = gfio_thread_status_op,
        .group_stats            = gfio_group_stats_op,
-       .eta                    = gfio_eta_op,
+       .eta                    = gfio_update_eta,
        .probe                  = gfio_probe_op,
        .quit                   = gfio_quit_op,
        .add_job                = gfio_add_job_op,
@@ -411,20 +418,6 @@ static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
        return label_widget;
 }
 
-static GtkWidget *create_text_entry(GtkWidget *hbox, const char *defval)
-{
-       GtkWidget *text, *box;
-
-       box = gtk_hbox_new(FALSE, 3);
-       gtk_container_add(GTK_CONTAINER(hbox), box);
-
-       text = gtk_entry_new();
-       gtk_box_pack_start(GTK_BOX(box), text, TRUE, TRUE, 0);
-       gtk_entry_set_text(GTK_ENTRY(text), defval);
-
-       return text;
-}
-
 static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, double defval)
 {
        GtkWidget *button, *box;
@@ -450,17 +443,24 @@ static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
        start_job_thread(ui);
 }
 
-static void connect_clicked(__attribute__((unused)) GtkWidget *widget,
-                gpointer data)
+static void file_open(GtkWidget *w, gpointer data);
+
+static void connect_clicked(GtkWidget *widget, gpointer data)
 {
        struct gui *ui = data;
 
        if (!ui->connected) {
+               if (!ui->nr_job_files)
+                       file_open(widget, data);
+               gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
                fio_clients_connect();
                pthread_create(&ui->t, NULL, job_thread, NULL);
                gfio_set_connected(ui, 1);
-       } else
+       } else {
+               fio_clients_terminate();
                gfio_set_connected(ui, 0);
+               clear_ui_info(ui);
+       }
 }
 
 static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
@@ -492,7 +492,7 @@ static void on_info_bar_response(GtkWidget *widget, gint response,
        }
 }
 
-void report_error(GErrorerror)
+void report_error(GError *error)
 {
        if (ui.error_info_bar == NULL) {
                ui.error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK,
@@ -515,9 +515,11 @@ void report_error(GError* error)
        }
 }
 
-static int get_connection_details(char **host, int *port, int *type)
+static int get_connection_details(char **host, int *port, int *type,
+                                 int *server_start)
 {
        GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
+       GtkWidget *button;
        char *typeentry;
 
        dialog = gtk_dialog_new_with_buttons("Connection details",
@@ -564,6 +566,19 @@ static int get_connection_details(char **host, int *port, int *type)
 
        gtk_container_add(GTK_CONTAINER(hbox), combo);
 
+       frame = gtk_frame_new("Options");
+       gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
+       box = gtk_vbox_new(FALSE, 10);
+       gtk_container_add(GTK_CONTAINER(frame), box);
+
+       hbox = gtk_hbox_new(TRUE, 4);
+       gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
+
+       button = gtk_check_button_new_with_label("Auto-spawn fio backend");
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
+       gtk_widget_set_tooltip_text(button, "When running fio locally, it is necessary to have the backend running on the same system. If this is checked, gfio will start the backend automatically for you if it isn't already running.");
+       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
+
        gtk_widget_show_all(dialog);
 
        if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
@@ -583,6 +598,8 @@ static int get_connection_details(char **host, int *port, int *type)
                *type = Fio_client_socket;
        g_free(typeentry);
 
+       *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+
        gtk_widget_destroy(dialog);
        return 0;
 }
@@ -593,7 +610,7 @@ static void file_open(GtkWidget *w, gpointer data)
        GSList *filenames, *fn_glist;
        GtkFileFilter *filter;
        char *host;
-       int port, type;
+       int port, type, server_start;
 
        dialog = gtk_file_chooser_dialog_new("Open File",
                GTK_WINDOW(ui.window),
@@ -619,7 +636,7 @@ static void file_open(GtkWidget *w, gpointer data)
 
        gtk_widget_destroy(dialog);
 
-       if (get_connection_details(&host, &port, &type))
+       if (get_connection_details(&host, &port, &type, &server_start))
                goto err;
 
        filenames = fn_glist;
@@ -628,15 +645,16 @@ static void file_open(GtkWidget *w, gpointer data)
                ui.job_files[ui.nr_job_files] = strdup(filenames->data);
                ui.nr_job_files++;
 
-               ui.client = fio_client_add_explicit(host, type, port);
-               ui.client->client_data = &ui;
-#if 0
-               if (error) {
+               ui.client = fio_client_add_explicit(&gfio_client_ops, host, type, port);
+               if (!ui.client) {
+                       GError *error;
+
+                       error = g_error_new(g_quark_from_string("fio"), 1,
+                                       "Failed to add client %s", host);
                        report_error(error);
                        g_error_free(error);
-                       error = NULL;
                }
-#endif
+               ui.client->client_data = &ui;
                        
                g_free(filenames->data);
                filenames = g_slist_next(filenames);
@@ -670,6 +688,49 @@ static void file_save(GtkWidget *w, gpointer data)
        gtk_widget_destroy(dialog);
 }
 
+static void preferences(GtkWidget *w, gpointer data)
+{
+       GtkWidget *dialog, *frame, *box, **buttons;
+       int i;
+
+       dialog = gtk_dialog_new_with_buttons("Preferences",
+               GTK_WINDOW(ui.window),
+               GTK_DIALOG_DESTROY_WITH_PARENT,
+               GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+               GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+               NULL);
+
+       frame = gtk_frame_new("Debug logging");
+       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+       box = gtk_hbox_new(FALSE, 6);
+       gtk_container_add(GTK_CONTAINER(frame), box);
+
+       buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
+
+       for (i = 0; i < FD_DEBUG_MAX; i++) {
+               buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
+               gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
+               gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
+       }
+
+       gtk_widget_show_all(dialog);
+
+       if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
+               gtk_widget_destroy(dialog);
+               return;
+       }
+
+       for (i = 0; i < FD_DEBUG_MAX; i++) {
+               int set;
+
+               set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i]));
+               if (set)
+                       fio_debug |= (1UL << i);
+       }
+
+       gtk_widget_destroy(dialog);
+}
+
 static void about_dialog(GtkWidget *w, gpointer data)
 {
        gtk_show_about_dialog(NULL,
@@ -685,12 +746,13 @@ static void about_dialog(GtkWidget *w, gpointer data)
 }
 
 static GtkActionEntry menu_items[] = {
-        { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
-        { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
-       { "OpenFile",       GTK_STOCK_OPEN, NULL,   "<Control>O", NULL, G_CALLBACK(file_open) },
-        { "SaveFile",       GTK_STOCK_SAVE, NULL,   "<Control>S", NULL, G_CALLBACK(file_save) },
-        { "Quit",           GTK_STOCK_QUIT, NULL,   "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
-       { "About",          GTK_STOCK_ABOUT, NULL,  NULL, NULL, G_CALLBACK(about_dialog) },
+       { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
+       { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
+       { "OpenFile", GTK_STOCK_OPEN, NULL,   "<Control>O", NULL, G_CALLBACK(file_open) },
+       { "SaveFile", GTK_STOCK_SAVE, NULL,   "<Control>S", NULL, G_CALLBACK(file_save) },
+       { "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) },
+       { "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]);
 
@@ -701,6 +763,8 @@ static const gchar *ui_string = " \
                                <menuitem name=\"Open\" action=\"OpenFile\" /> \
                                <menuitem name=\"Save\" action=\"SaveFile\" /> \
                                <separator name=\"Separator\"/> \
+                               <menuitem name=\"Preferences\" action=\"Preferences\" /> \
+                               <separator name=\"Separator2\"/> \
                                <menuitem name=\"Quit\" action=\"Quit\" /> \
                        </menu> \
                        <menu name=\"Help\" action=\"HelpMenuAction\"> \
@@ -850,7 +914,7 @@ static void init_ui(int *argc, char **argv[], struct gui *ui)
         */
        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_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections");
        gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb);
 
 
@@ -864,7 +928,6 @@ int main(int argc, char *argv[], char *envp[])
        if (fio_init_options())
                return 1;
 
-       fio_debug = ~0UL;
        init_ui(&argc, &argv, &ui);
 
        gdk_threads_enter();