Separate the act of adding and starting a job
[fio.git] / gfio.c
diff --git a/gfio.c b/gfio.c
index 8db04ab463695fc0137f56db2a6699040c757dab..877438a5b130bc330ece62409259b82f31dea450 100644 (file)
--- a/gfio.c
+++ b/gfio.c
@@ -23,6 +23,7 @@
  */
 #include <locale.h>
 #include <malloc.h>
+#include <string.h>
 
 #include <glib.h>
 #include <cairo.h>
@@ -35,6 +36,7 @@ static int gfio_server_running;
 static const char *gfio_graph_font;
 
 static void gfio_update_thread_status(char *status_message, double perc);
+static void view_log(GtkWidget *w, gpointer data);
 
 #define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0])))
 
@@ -42,6 +44,7 @@ typedef void (*clickfunction)(GtkWidget *widget, gpointer data);
 
 static void connect_clicked(GtkWidget *widget, gpointer data);
 static void start_job_clicked(GtkWidget *widget, gpointer data);
+static void send_clicked(GtkWidget *widget, gpointer data);
 
 static struct button_spec {
        const char *buttontext;
@@ -50,10 +53,11 @@ static struct button_spec {
        const int start_insensitive;
 } buttonspeclist[] = {
 #define CONNECT_BUTTON 0
-#define START_JOB_BUTTON 1
+#define SEND_BUTTON 1
+#define START_JOB_BUTTON 2
        { "Connect", connect_clicked, "Connect to host", 0 },
-       { "Start Job",
-               start_job_clicked,
+       { "Send", send_clicked, "Send job description to host", 1 },
+       { "Start Job", start_job_clicked,
                "Send current fio job to fio server to be executed", 1 },
 };
 
@@ -112,15 +116,19 @@ struct gui {
 
        struct graph *iops_graph;
        struct graph *bandwidth_graph;
-       struct fio_client *client;
+       struct gfio_client *client;
        int nr_job_files;
        char **job_files;
 } ui;
 
 struct gfio_client {
        struct gui *ui;
+       struct fio_client *client;
        GtkWidget *results_widget;
        GtkWidget *disk_util_frame;
+       GtkWidget *err_entry;
+       unsigned int job_added;
+       struct thread_options o;
 };
 
 static void setup_iops_graph(struct gui *ui)
@@ -131,6 +139,7 @@ static void setup_iops_graph(struct gui *ui)
                                        DRAWING_AREA_YDIM, gfio_graph_font);
        graph_title(ui->iops_graph, "IOPS");
        graph_x_title(ui->iops_graph, "Time (secs)");
+       graph_y_title(ui->iops_graph, "IOs / sec");
        graph_add_label(ui->iops_graph, "Read IOPS");
        graph_add_label(ui->iops_graph, "Write IOPS");
        graph_set_color(ui->iops_graph, "Read IOPS", 0.13, 0.54, 0.13);
@@ -146,6 +155,7 @@ static void setup_bandwidth_graph(struct gui *ui)
                                        DRAWING_AREA_YDIM, gfio_graph_font);
        graph_title(ui->bandwidth_graph, "Bandwidth");
        graph_x_title(ui->bandwidth_graph, "Time (secs)");
+       graph_y_title(ui->bandwidth_graph, "Kbytes / sec");
        graph_add_label(ui->bandwidth_graph, "Read Bandwidth");
        graph_add_label(ui->bandwidth_graph, "Write Bandwidth");
        graph_set_color(ui->bandwidth_graph, "Read Bandwidth", 0.13, 0.54, 0.13);
@@ -216,13 +226,14 @@ static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, dou
 static void gfio_set_connected(struct gui *ui, int connected)
 {
        if (connected) {
-               gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+               gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1);
                ui->connected = 1;
                gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect");
                gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
        } else {
                ui->connected = 0;
                gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect");
+               gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0);
                gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
                gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
        }
@@ -812,6 +823,7 @@ static GtkWidget *get_results_window(struct gui *ui)
 
        win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(win), "Results");
+       gtk_window_set_default_size(GTK_WINDOW(win), 1024, 768);
        g_signal_connect(win, "delete-event", G_CALLBACK(results_window_delete), ui);
        g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ui);
 
@@ -826,19 +838,25 @@ static GtkWidget *get_results_window(struct gui *ui)
 static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
                            struct group_run_stats *rs)
 {
-       GtkWidget *res_win, *box, *vbox, *entry;
+       GtkWidget *res_win, *box, *vbox, *entry, *scroll;
        struct gfio_client *gc = client->client_data;
 
        gdk_threads_enter();
 
        res_win = get_results_window(gc->ui);
 
+       scroll = gtk_scrolled_window_new(NULL, NULL);
+       gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
        vbox = gtk_vbox_new(FALSE, 3);
 
-       box = gtk_hbox_new(TRUE, 3);
-       gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
+       box = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox), box, TRUE, FALSE, 5);
+
+       gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox);
 
-       gtk_notebook_append_page(GTK_NOTEBOOK(res_win), vbox, gtk_label_new(ts->name));
+       gtk_notebook_append_page(GTK_NOTEBOOK(res_win), scroll, gtk_label_new(ts->name));
 
        gc->results_widget = vbox;
 
@@ -852,7 +870,7 @@ static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
        entry_set_int_value(entry, ts->groupid);
        entry = new_info_entry_in_frame(box, "Jobs");
        entry_set_int_value(entry, ts->members);
-       entry = new_info_entry_in_frame(box, "Error");
+       gc->err_entry = entry = new_info_entry_in_frame(box, "Error");
        entry_set_int_value(entry, ts->error);
        entry = new_info_entry_in_frame(box, "PID");
        entry_set_int_value(entry, ts->pid);
@@ -892,6 +910,9 @@ static void gfio_text_op(struct fio_client *client, struct fio_net_cmd *cmd)
        gtk_list_store_set(gc->ui->log_model, &iter, 2, p->level, -1);
        gtk_list_store_set(gc->ui->log_model, &iter, 3, p->buf, -1);
 
+       if (p->level == FIO_LOG_ERR)
+               view_log(NULL, (gpointer) gc->ui);
+
        gdk_threads_leave();
 }
 
@@ -1191,30 +1212,23 @@ static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
 {
        struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
        struct gfio_client *gc = client->client_data;
+       struct thread_options *o = &gc->o;
        struct gui *ui = gc->ui;
        char tmp[8];
-       int i;
-
-       p->iodepth              = le32_to_cpu(p->iodepth);
-       p->rw                   = le32_to_cpu(p->rw);
 
-       for (i = 0; i < 2; i++) {
-               p->min_bs[i]    = le32_to_cpu(p->min_bs[i]);
-               p->max_bs[i]    = le32_to_cpu(p->max_bs[i]);
-       }
-
-       p->numjobs              = le32_to_cpu(p->numjobs);
-       p->group_reporting      = le32_to_cpu(p->group_reporting);
+       convert_thread_options_to_cpu(o, &p->top);
 
        gdk_threads_enter();
 
-       gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) p->jobname);
-       gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(p->rw));
-       gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) p->ioengine);
+       gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) o->name);
+       gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(o->td_ddir));
+       gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) o->ioengine);
 
-       sprintf(tmp, "%u", p->iodepth);
+       sprintf(tmp, "%u", o->iodepth);
        gtk_entry_set_text(GTK_ENTRY(ui->eta.iodepth), tmp);
 
+       gc->job_added++;
+
        gdk_threads_leave();
 }
 
@@ -1236,7 +1250,9 @@ static void gfio_client_timed_out(struct fio_client *client)
                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                        GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
 
-       content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+       /* gtk_dialog_get_content_area() is 2.14 and newer */
+       content = GTK_DIALOG(dialog)->vbox;
+
        label = gtk_label_new((const gchar *) buf);
        gtk_container_add(GTK_CONTAINER(content), label);
        gtk_widget_show_all(dialog);
@@ -1248,6 +1264,20 @@ static void gfio_client_timed_out(struct fio_client *client)
        gdk_threads_leave();
 }
 
+static void gfio_client_stop(struct fio_client *client, struct fio_net_cmd *cmd)
+{
+       struct gfio_client *gc = client->client_data;
+
+       gdk_threads_enter();
+
+       gfio_set_connected(gc->ui, 0);
+
+       if (gc->err_entry)
+               entry_set_int_value(gc->err_entry, client->error);
+
+       gdk_threads_leave();
+}
+
 struct client_ops gfio_client_ops = {
        .text_op                = gfio_text_op,
        .disk_util              = gfio_disk_util_op,
@@ -1258,6 +1288,7 @@ struct client_ops gfio_client_ops = {
        .quit                   = gfio_quit_op,
        .add_job                = gfio_add_job_op,
        .timed_out              = gfio_client_timed_out,
+       .stop                   = gfio_client_stop,
        .stay_connected         = 1,
 };
 
@@ -1294,15 +1325,6 @@ static int send_job_files(struct gui *ui)
        return ret;
 }
 
-static void start_job_thread(struct gui *ui)
-{
-       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);
-               return;
-       }
-}
-
 static void *server_thread(void *arg)
 {
        is_backend = 1;
@@ -1325,9 +1347,10 @@ static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
                 gpointer data)
 {
        struct gui *ui = data;
+       struct gfio_client *gc = ui->client;
 
        gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
-       start_job_thread(ui);
+       fio_net_send_simple_cmd(gc->client->fd, FIO_NET_CMD_RUN, 0, NULL);
 }
 
 static void file_open(GtkWidget *w, gpointer data);
@@ -1344,6 +1367,7 @@ static void connect_clicked(GtkWidget *widget, gpointer data)
                if (!fio_clients_connect()) {
                        pthread_create(&ui->t, NULL, job_thread, NULL);
                        gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 0);
+                       gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1);
                }
        } else {
                fio_clients_terminate();
@@ -1352,6 +1376,19 @@ static void connect_clicked(GtkWidget *widget, gpointer data)
        }
 }
 
+static void send_clicked(GtkWidget *widget, gpointer data)
+{
+       struct gui *ui = data;
+
+       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);
+       }
+
+       gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0);
+       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)
 {
@@ -1459,7 +1496,8 @@ static int get_connection_details(char **host, int *port, int *type,
                        GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
 
        frame = gtk_frame_new("Hostname / socket name");
-       vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+       /* gtk_dialog_get_content_area() is 2.14 and newer */
+       vbox = GTK_DIALOG(dialog)->vbox;
        gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
 
        box = gtk_vbox_new(FALSE, 6);
@@ -1547,6 +1585,9 @@ static void gfio_client_added(struct gui *ui, struct fio_client *client)
        gc = malloc(sizeof(*gc));
        memset(gc, 0, sizeof(*gc));
        gc->ui = ui;
+       gc->client = client;
+
+       ui->client = gc;
 
        client->client_data = gc;
 }