static int gfio_server_running;
static const char *gfio_graph_font;
+static unsigned int gfio_graph_limit = 100;
-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])))
};
struct eta_widget {
- GtkWidget *name;
+ GtkWidget *names;
GtkWidget *iotype;
GtkWidget *ioengine;
GtkWidget *iodepth;
struct thread_options o;
};
+static void gfio_update_thread_status(struct gui_entry *ge, char *status_message, double perc);
+static void gfio_update_thread_status_all(char *status_message, double perc);
+void report_error(GError *error);
+
static struct graph *setup_iops_graph(void)
{
struct graph *g;
graph_add_label(g, "Write IOPS");
graph_set_color(g, "Read IOPS", 0.13, 0.54, 0.13);
graph_set_color(g, "Write IOPS", 1.0, 0.0, 0.0);
- line_graph_set_data_count_limit(g, 100);
+ line_graph_set_data_count_limit(g, gfio_graph_limit);
return g;
}
gtk_label_set_text(GTK_LABEL(ge->probe.os), "");
gtk_label_set_text(GTK_LABEL(ge->probe.arch), "");
gtk_label_set_text(GTK_LABEL(ge->probe.fio_ver), "");
+#if 0
+ /* should we empty it... */
gtk_entry_set_text(GTK_ENTRY(ge->eta.name), "");
+#endif
gtk_entry_set_text(GTK_ENTRY(ge->eta.iotype), "");
gtk_entry_set_text(GTK_ENTRY(ge->eta.ioengine), "");
gtk_entry_set_text(GTK_ENTRY(ge->eta.iodepth), "");
gtk_entry_set_text(GTK_ENTRY(ge->eta.write_iops), "");
}
+static GtkWidget *new_combo_entry_in_frame(GtkWidget *box, const char *label)
+{
+ GtkWidget *entry, *frame;
+
+ frame = gtk_frame_new(label);
+ entry = gtk_combo_box_new_text();
+ gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
+ gtk_container_add(GTK_CONTAINER(frame), entry);
+
+ return entry;
+}
+
static GtkWidget *new_info_entry_in_frame(GtkWidget *box, const char *label)
{
GtkWidget *entry, *frame;
g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ge);
notebook = gtk_notebook_new();
+ gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), 1);
+ gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook));
gtk_container_add(GTK_CONTAINER(win), notebook);
ge->results_window = win;
sprintf(dst, " - %s", eta_str);
}
- gfio_update_thread_status(output, perc);
+ gfio_update_thread_status(ge, output, perc);
gdk_threads_leave();
}
gtk_entry_set_text(GTK_ENTRY(ui->eta.cw_iops), "---");
#endif
+ entry_set_int_value(ui->eta.jobs, je->nr_running);
+
if (je->eta_sec != INT_MAX && je->nr_running) {
char *iops_str[2];
char *rate_str[2];
sprintf(dst, " - %s", eta_str);
}
- gfio_update_thread_status(output, perc);
+ gfio_update_thread_status_all(output, perc);
gdk_threads_leave();
}
gdk_threads_leave();
}
-static void gfio_update_thread_status(char *status_message, double perc)
+static void gfio_update_thread_status(struct gui_entry *ge,
+ char *status_message, double perc)
+{
+ static char message[100];
+ const char *m = message;
+
+ strncpy(message, status_message, sizeof(message) - 1);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), m);
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), perc / 100.0);
+ gtk_widget_queue_draw(main_ui.window);
+}
+
+static void gfio_update_thread_status_all(char *status_message, double perc)
{
struct gui *ui = &main_ui;
static char message[100];
gtk_label_set_text(GTK_LABEL(ge->page_label), (gchar *) o->name);
- gtk_entry_set_text(GTK_ENTRY(ge->eta.name), (gchar *) o->name);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(ge->eta.names), (gchar *) o->name);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(ge->eta.names), 0);
+
gtk_entry_set_text(GTK_ENTRY(ge->eta.iotype), ddir_str(o->td_ddir));
gtk_entry_set_text(GTK_ENTRY(ge->eta.ioengine), (gchar *) o->ioengine);
.add_job = gfio_add_job_op,
.timed_out = gfio_client_timed_out,
.stop = gfio_client_stop,
+ .eta_msec = FIO_CLIENT_DEF_ETA_MSEC,
.stay_connected = 1,
};
static int send_job_files(struct gui_entry *ge)
{
+ struct gfio_client *gc = ge->client;
int i, ret = 0;
for (i = 0; i < ge->nr_job_files; i++) {
- ret = fio_clients_send_ini(ge->job_files[i]);
- if (ret)
+ ret = fio_client_send_ini(gc->client, ge->job_files[i]);
+ if (ret < 0) {
+ GError *error;
+
+ error = g_error_new(g_quark_from_string("fio"), 1, "Failed to send file %s: %s\n", ge->job_files[i], strerror(-ret));
+ report_error(error);
+ g_error_free(error);
+ break;
+ } else if (ret)
break;
free(ge->job_files[i]);
struct gfio_client *gc = ge->client;
if (!ge->connected) {
+ int ret;
+
if (!ge->nr_job_files)
file_open(widget, data);
if (!ge->nr_job_files)
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), "No jobs running");
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), 0.0);
- if (!fio_client_connect(gc->client)) {
+ ret = fio_client_connect(gc->client);
+ if (!ret) {
if (!ge->ui->handler_running)
pthread_create(&ge->ui->t, NULL, job_thread, ge->ui);
gtk_widget_set_sensitive(ge->button[CONNECT_BUTTON], 0);
gtk_widget_set_sensitive(ge->button[SEND_BUTTON], 1);
+ } else {
+ GError *error;
+
+ error = g_error_new(g_quark_from_string("fio"), 1, "Failed to connect to %s: %s\n", ge->client->client->hostname, strerror(-ret));
+ report_error(error);
+ g_error_free(error);
}
} else {
fio_client_terminate(gc->client);
struct gui_entry *ge = data;
if (send_job_files(ge)) {
- printf("Yeah, I didn't really like those options too much.\n");
+ GError *error;
+
+ error = g_error_new(g_quark_from_string("fio"), 1, "Failed to send one or more job files for client %s", ge->client->client->hostname);
+ report_error(error);
+ g_error_free(error);
+
gtk_widget_set_sensitive(ge->button[START_JOB_BUTTON], 1);
}
gc = malloc(sizeof(*gc));
memset(gc, 0, sizeof(*gc));
gc->ge = ge;
- gc->client = client;
+ gc->client = fio_get_client(client);
ge->client = gc;
static void ge_destroy(GtkWidget *w, gpointer data)
{
struct gui_entry *ge = data;
+ struct gfio_client *gc = ge->client;
+
+ if (gc->client)
+ fio_put_client(gc->client);
flist_del(&ge->list);
free(ge);
gtk_widget_show_all(win);
}
+static void __update_graph_limits(struct gfio_graphs *g)
+{
+ line_graph_set_data_count_limit(g->iops_graph, gfio_graph_limit);
+ line_graph_set_data_count_limit(g->bandwidth_graph, gfio_graph_limit);
+}
+
+static void update_graph_limits(void)
+{
+ struct flist_head *entry;
+ struct gui_entry *ge;
+
+ __update_graph_limits(&main_ui.graphs);
+
+ flist_for_each(entry, &main_ui.list) {
+ ge = flist_entry(entry, struct gui_entry, list);
+ __update_graph_limits(&ge->graphs);
+ }
+}
+
static void preferences(GtkWidget *w, gpointer data)
{
GtkWidget *dialog, *frame, *box, **buttons, *vbox, *font;
+ GtkWidget *hbox, *spin, *entry, *spin_int;
int i;
dialog = gtk_dialog_new_with_buttons("Preferences",
gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
}
- frame = gtk_frame_new("Graph font");
+ frame = gtk_frame_new("Graphing");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
vbox = gtk_vbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(frame), vbox);
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+ entry = gtk_label_new("Font face to use for graph labels");
+ gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 5);
+
font = gtk_font_button_new();
- gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), font, FALSE, FALSE, 5);
+ box = gtk_vbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 5);
+ entry = gtk_label_new("Maximum number of data points in graph (seconds)");
+ gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
+
+ spin = create_spinbutton(hbox, 10, 1000000, 100);
+
+ box = gtk_vbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 5);
+ entry = gtk_label_new("Client ETA request interval (msec)");
+ gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
+
+ spin_int = create_spinbutton(hbox, 100, 100000, gfio_client_ops.eta_msec);
gtk_widget_show_all(dialog);
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
}
gfio_graph_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font)));
+ gfio_graph_limit = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin));
+ update_graph_limits();
+ gfio_client_ops.eta_msec = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_int));
+
gtk_widget_destroy(dialog);
}
probe_box = gtk_hbox_new(FALSE, 3);
gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
- ge->eta.name = new_info_entry_in_frame(probe_box, "Name");
+ ge->eta.names = new_combo_entry_in_frame(probe_box, "Jobs");
ge->eta.iotype = new_info_entry_in_frame(probe_box, "IO");
ge->eta.ioengine = new_info_entry_in_frame(probe_box, "IO Engine");
ge->eta.iodepth = new_info_entry_in_frame(probe_box, "IO Depth");
probe_box = gtk_hbox_new(FALSE, 3);
gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
+ ui->eta.jobs = new_info_entry_in_frame(probe_box, "Running");
ui->eta.read_bw = new_info_entry_in_frame(probe_box, "Read BW");
ui->eta.read_iops = new_info_entry_in_frame(probe_box, "IOPS");
ui->eta.write_bw = new_info_entry_in_frame(probe_box, "Write BW");
ui->notebook = gtk_notebook_new();
g_signal_connect(ui->notebook, "switch-page", G_CALLBACK(notebook_switch_page), ui);
+ gtk_notebook_set_scrollable(GTK_NOTEBOOK(ui->notebook), 1);
+ gtk_notebook_popup_enable(GTK_NOTEBOOK(ui->notebook));
gtk_container_add(GTK_CONTAINER(ui->vbox), ui->notebook);
vbox = new_main_page(ui);