/*
* gfio - gui front end for fio - the flexible io tester
*
- * Copyright (C) 2012 Stephen M. Cameron <stephenmcameron@gmail.com>
+ * Copyright (C) 2012 Stephen M. Cameron <stephenmcameron@gmail.com>
* Copyright (C) 2012 Jens Axboe <axboe@kernel.dk>
*
* The license below covers all files distributed with fio unless otherwise
static unsigned int gfio_graph_limit = 100;
GdkColor gfio_color_white;
-const char *gfio_graph_font;
+GdkColor gfio_color_lightyellow;
+const char *gfio_graph_font = GRAPH_DEFAULT_FONT;
typedef void (*clickfunction)(GtkWidget *widget, gpointer data);
},
};
-static struct graph *setup_iops_graph(void)
+static void setup_iops_graph(struct gfio_graphs *gg)
{
struct graph *g;
g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font);
graph_title(g, "IOPS (IOs/sec)");
graph_x_title(g, "Time (secs)");
- graph_add_label(g, "Read IOPS");
- 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);
+ gg->read_iops = graph_add_label(g, "Read IOPS");
+ gg->write_iops = graph_add_label(g, "Write IOPS");
+ gg->trim_iops = graph_add_label(g, "Trim IOPS");
+ graph_set_color(g, gg->read_iops, GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
+ graph_set_color(g, gg->write_iops, GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
+ graph_set_color(g, gg->trim_iops, GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
line_graph_set_data_count_limit(g, gfio_graph_limit);
graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0);
- return g;
+ graph_set_graph_all_zeroes(g, 0);
+ gg->iops_graph = g;
}
-static struct graph *setup_bandwidth_graph(void)
+static void setup_bandwidth_graph(struct gfio_graphs *gg)
{
struct graph *g;
g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font);
graph_title(g, "Bandwidth (bytes/sec)");
graph_x_title(g, "Time (secs)");
- graph_add_label(g, "Read Bandwidth");
- graph_add_label(g, "Write Bandwidth");
- graph_set_color(g, "Read Bandwidth", 0.13, 0.54, 0.13);
- graph_set_color(g, "Write Bandwidth", 1.0, 0.0, 0.0);
+ gg->read_bw = graph_add_label(g, "Read Bandwidth");
+ gg->write_bw = graph_add_label(g, "Write Bandwidth");
+ gg->trim_bw = graph_add_label(g, "Trim Bandwidth");
+ graph_set_color(g, gg->read_bw, GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
+ graph_set_color(g, gg->write_bw, GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
+ graph_set_color(g, gg->trim_bw, GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
graph_set_base_offset(g, 1);
line_graph_set_data_count_limit(g, 100);
graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0);
- return g;
+ graph_set_graph_all_zeroes(g, 0);
+ gg->bandwidth_graph = g;
}
static void setup_graphs(struct gfio_graphs *g)
{
- g->iops_graph = setup_iops_graph();
- g->bandwidth_graph = setup_bandwidth_graph();
+ setup_iops_graph(g);
+ setup_bandwidth_graph(g);
}
void clear_ge_ui_info(struct gui_entry *ge)
GtkListStore *model;
GtkWidget *tree_view;
- model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
+ model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
gtk_widget_set_can_focus(tree_view, FALSE);
static gint on_config_drawing_area(GtkWidget *w, GdkEventConfigure *event,
gpointer data)
{
+ guint width = gtk_widget_get_allocated_width(w);
+ guint height = gtk_widget_get_allocated_height(w);
struct gfio_graphs *g = data;
- graph_set_size(g->iops_graph, w->allocation.width / 2.0, w->allocation.height);
- graph_set_position(g->iops_graph, w->allocation.width / 2.0, 0.0);
- graph_set_size(g->bandwidth_graph, w->allocation.width / 2.0, w->allocation.height);
+ graph_set_size(g->iops_graph, width / 2.0, height);
+ graph_set_position(g->iops_graph, width / 2.0, 0.0);
+ graph_set_size(g->bandwidth_graph, width / 2.0, height);
graph_set_position(g->bandwidth_graph, 0, 0);
return TRUE;
}
struct gfio_graphs *g = p;
cairo_t *cr;
- cr = gdk_cairo_create(w->window);
+ cr = gdk_cairo_create(gtk_widget_get_window(w));
if (graph_has_tooltips(g->iops_graph) ||
graph_has_tooltips(g->bandwidth_graph)) {
static void gfio_quit(struct gui *ui)
{
- gtk_main_quit();
+ gtk_main_quit();
}
static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
- __attribute__((unused)) gpointer data)
+ gpointer data)
{
struct gui *ui = (struct gui *) data;
struct gfio_client *gc = ge->client;
int ret = 0;
- ret = fio_client_send_ini(gc->client, ge->job_file);
+ /*
+ * Prune old options, we are expecting the return options
+ * when the job file is parsed remotely and returned to us.
+ */
+ while (!flist_empty(&gc->o_list)) {
+ struct gfio_client_options *gco;
+
+ gco = flist_first_entry(&gc->o_list, struct gfio_client_options, list);
+ flist_del(&gco->list);
+ free(gco);
+ }
+
+ ret = fio_client_send_ini(gc->client, ge->job_file, 0);
if (!ret)
return 0;
}
static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
- gpointer data)
+ gpointer data)
{
struct gui_entry *ge = data;
struct gfio_client *gc = ge->client;
* or not. Show it if we are a localhost and using network,
* or using a socket.
*/
- ctext = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cw->combo));
+ ctext = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(cw->combo));
if (!ctext || !strncmp(ctext, "IPv4", 4) || !strncmp(ctext, "IPv6", 4))
uses_net = 1;
g_free(ctext);
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
frame = gtk_frame_new("Hostname / socket name");
- /* gtk_dialog_get_content_area() is 2.14 and newer */
- vbox = GTK_DIALOG(dialog)->vbox;
+ vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
box = gtk_vbox_new(FALSE, 6);
hbox = gtk_hbox_new(TRUE, 4);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
- cw.combo = gtk_combo_box_new_text();
- gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "IPv4");
- gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "IPv6");
- gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "local socket");
+ cw.combo = gtk_combo_box_text_new();
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw.combo), "IPv4");
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw.combo), "IPv6");
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw.combo), "local socket");
gtk_combo_box_set_active(GTK_COMBO_BOX(cw.combo), 0);
gtk_container_add(GTK_CONTAINER(hbox), cw.combo);
/*
* Connect edit signal, so we can show/not-show the auto start button
*/
- g_signal_connect(GTK_OBJECT(cw.hentry), "changed", G_CALLBACK(hostname_cb), &cw);
- g_signal_connect(GTK_OBJECT(cw.combo), "changed", G_CALLBACK(hostname_cb), &cw);
+ g_signal_connect(G_OBJECT(cw.hentry), "changed", G_CALLBACK(hostname_cb), &cw);
+ g_signal_connect(G_OBJECT(cw.combo), "changed", G_CALLBACK(hostname_cb), &cw);
gtk_widget_show_all(dialog);
ge->host = strdup(gtk_entry_get_text(GTK_ENTRY(cw.hentry)));
ge->port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
- typeentry = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cw.combo));
+ typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(cw.combo));
if (!typeentry || !strncmp(typeentry, "IPv4", 4))
ge->type = Fio_client_ipv4;
else if (!strncmp(typeentry, "IPv6", 4))
static void gfio_client_added(struct gui_entry *ge, struct fio_client *client)
{
+ struct gfio_client_options *gco;
struct gfio_client *gc;
- gc = malloc(sizeof(*gc));
- memset(gc, 0, sizeof(*gc));
- options_default_fill(&gc->o);
+ gc = calloc(1, sizeof(*gc));
+ INIT_FLIST_HEAD(&gc->o_list);
gc->ge = ge;
ge->client = gc;
gfio_set_client(gc, client);
+
+ /*
+ * Just add a default set of options, need to consider how best
+ * to handle this
+ */
+ gco = calloc(1, sizeof(*gco));
+ INIT_FLIST_HEAD(&gco->list);
+ options_default_fill(&gco->o);
+ flist_add_tail(&gco->list, &gc->o_list);
+ gc->o_list_nr++;
+}
+
+static void gfio_clear_graph_data(struct gfio_graphs *g)
+{
+ graph_clear_values(g->iops_graph);
+ graph_clear_values(g->bandwidth_graph);
}
static void connect_clicked(GtkWidget *widget, gpointer data)
if (!ge->ui->handler_running)
pthread_create(&ge->ui->t, NULL, job_thread, ge->ui);
gfio_set_state(ge, GE_STATE_CONNECTED);
+ gfio_clear_graph_data(&ge->graphs);
} else {
gfio_report_error(ge, "Failed to connect to %s: %s\n", ge->client->client->hostname, strerror(-ret));
}
if (get_connection_details(ge)) {
if (ge_is_new)
gtk_widget_destroy(ge->vbox);
-
+
return 1;
}
{
struct gui *ui = (struct gui *) data;
- gtk_widget_ref(ui->log_tree);
+ g_object_ref(G_OBJECT(ui->log_tree));
gtk_container_remove(GTK_CONTAINER(w), ui->log_tree);
gtk_widget_destroy(w);
ui->log_view = NULL;
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
box = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start_defaults(GTK_BOX(box), ui->log_tree);
+ gtk_box_pack_start(GTK_BOX(box), ui->log_tree, TRUE, TRUE, 0);
g_signal_connect(box, "destroy", G_CALLBACK(view_log_destroy), ui);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), box);
vbox = gtk_vbox_new(TRUE, 5);
- gtk_box_pack_start_defaults(GTK_BOX(vbox), scroll);
+ gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(win), vbox);
gtk_widget_show_all(win);
{
struct gui *ui = (struct gui *) data;
struct gui_entry *ge;
-
+
ge = get_ge_from_cur_tab(ui);
if (ge)
connect_clicked(w, ge);
ge = get_ge_from_cur_tab(ui);
if (ge && ge->client)
- gopt_get_options_window(ui->window, &ge->client->o);
+ gopt_get_options_window(ui->window, ge->client);
}
static void start_job_entry(GtkWidget *w, gpointer data)
gfio_display_end_results(gc);
}
-static void __update_graph_limits(struct gfio_graphs *g)
+static void __update_graph_settings(struct gfio_graphs *g)
{
line_graph_set_data_count_limit(g->iops_graph, gfio_graph_limit);
+ graph_set_font(g->iops_graph, gfio_graph_font);
line_graph_set_data_count_limit(g->bandwidth_graph, gfio_graph_limit);
+ graph_set_font(g->bandwidth_graph, gfio_graph_font);
}
-static void ge_update_lim_fn(gpointer key, gpointer value, gpointer data)
+static void ge_update_settings_fn(gpointer key, gpointer value, gpointer data)
{
struct gui_entry *ge = (struct gui_entry *) value;
+ GdkEvent *ev;
+
+ __update_graph_settings(&ge->graphs);
- __update_graph_limits(&ge->graphs);
+ ev = gdk_event_new(GDK_EXPOSE);
+ g_signal_emit_by_name(G_OBJECT(ge->graphs.drawing_area), GFIO_DRAW_EVENT, GTK_WIDGET(ge->graphs.drawing_area), ev, &ge->graphs);
+ gdk_event_free(ev);
}
static void update_graph_limits(void)
{
struct gui *ui = &main_ui;
+ GdkEvent *ev;
- __update_graph_limits(&ui->graphs);
+ __update_graph_settings(&ui->graphs);
- g_hash_table_foreach(ui->ge_hash, ge_update_lim_fn, NULL);
+ ev = gdk_event_new(GDK_EXPOSE);
+ g_signal_emit_by_name(G_OBJECT(ui->graphs.drawing_area), GFIO_DRAW_EVENT, GTK_WIDGET(ui->graphs.drawing_area), ev, &ui->graphs);
+ gdk_event_free(ev);
+
+ g_hash_table_foreach(ui->ge_hash, ge_update_settings_fn, NULL);
}
static void preferences(GtkWidget *w, gpointer data)
NULL);
frame = gtk_frame_new("Graphing");
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+ vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
vbox = gtk_vbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(frame), vbox);
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();
+ font = gtk_font_button_new_with_font(gfio_graph_font);
gtk_box_pack_start(GTK_BOX(hbox), font, FALSE, FALSE, 5);
box = gtk_vbox_new(FALSE, 6);
spin_int = create_spinbutton(hbox, 100, 100000, gfio_client_ops.eta_msec);
frame = gtk_frame_new("Debug logging");
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+ vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
vbox = gtk_vbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(frame), vbox);
probe_box = gtk_hbox_new(FALSE, 3);
gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
- ge->eta.read_bw = new_info_entry_in_frame(probe_box, "Read BW");
- ge->eta.read_iops = new_info_entry_in_frame(probe_box, "IOPS");
- ge->eta.write_bw = new_info_entry_in_frame(probe_box, "Write BW");
- ge->eta.write_iops = new_info_entry_in_frame(probe_box, "IOPS");
+ ge->eta.read_bw = new_info_entry_in_frame_rgb(probe_box, "Read BW", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
+ ge->eta.read_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
+ ge->eta.write_bw = new_info_entry_in_frame_rgb(probe_box, "Write BW", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
+ ge->eta.write_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
+ ge->eta.trim_bw = new_info_entry_in_frame_rgb(probe_box, "Trim BW", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
+ ge->eta.trim_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
/*
* Only add this if we have a commit rate
ge->graphs.drawing_area = gtk_drawing_area_new();
gtk_widget_set_size_request(GTK_WIDGET(ge->graphs.drawing_area),
DRAWING_AREA_XDIM, DRAWING_AREA_YDIM);
- gtk_widget_modify_bg(ge->graphs.drawing_area, GTK_STATE_NORMAL, &gfio_color_white);
- g_signal_connect(G_OBJECT(ge->graphs.drawing_area), "expose_event",
+ gtk_widget_modify_bg(ge->graphs.drawing_area, GTK_STATE_NORMAL, &gfio_color_lightyellow);
+ g_signal_connect(G_OBJECT(ge->graphs.drawing_area), GFIO_DRAW_EVENT,
G_CALLBACK(on_expose_drawing_area), &ge->graphs);
g_signal_connect(G_OBJECT(ge->graphs.drawing_area), "configure_event",
G_CALLBACK(on_config_drawing_area), &ge->graphs);
setup_graphs(&ge->graphs);
/*
- * Set up alignments for widgets at the bottom of ui,
+ * Set up alignments for widgets at the bottom of ui,
* align bottom left, expand horizontally but not vertically
*/
bottom_align = gtk_alignment_new(0, 1, 1, 0);
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->eta.write_iops = new_info_entry_in_frame(probe_box, "IOPS");
+ ui->eta.read_bw = new_info_entry_in_frame_rgb(probe_box, "Read BW", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
+ ui->eta.read_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
+ ui->eta.write_bw = new_info_entry_in_frame_rgb(probe_box, "Write BW", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
+ ui->eta.write_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
+ ui->eta.trim_bw = new_info_entry_in_frame_rgb(probe_box, "Trim BW", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
+ ui->eta.trim_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
/*
* Only add this if we have a commit rate
ui->graphs.drawing_area = gtk_drawing_area_new();
gtk_widget_set_size_request(GTK_WIDGET(ui->graphs.drawing_area),
DRAWING_AREA_XDIM, DRAWING_AREA_YDIM);
- gtk_widget_modify_bg(ui->graphs.drawing_area, GTK_STATE_NORMAL, &gfio_color_white);
- g_signal_connect(G_OBJECT(ui->graphs.drawing_area), "expose_event",
+ gtk_widget_modify_bg(ui->graphs.drawing_area, GTK_STATE_NORMAL, &gfio_color_lightyellow);
+ g_signal_connect(G_OBJECT(ui->graphs.drawing_area), GFIO_DRAW_EVENT,
G_CALLBACK(on_expose_drawing_area), &ui->graphs);
g_signal_connect(G_OBJECT(ui->graphs.drawing_area), "configure_event",
G_CALLBACK(on_config_drawing_area), &ui->graphs);
setup_graphs(&ui->graphs);
/*
- * Set up alignments for widgets at the bottom of ui,
+ * Set up alignments for widgets at the bottom of ui,
* align bottom left, expand horizontally but not vertically
*/
bottom_align = gtk_alignment_new(0, 1, 1, 0);
* Without it, the update that happens in gfio_update_thread_status
* doesn't really happen in a timely fashion, you need expose events
*/
+#if !GTK_CHECK_VERSION(2, 24, 0)
if (!g_thread_supported())
g_thread_init(NULL);
+#endif
+
gdk_threads_init();
gtk_init(argc, argv);
settings = gtk_settings_get_default();
gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting");
+#if !GLIB_CHECK_VERSION(2, 36, 0)
g_type_init();
+#endif
+ gdk_color_parse("#fffff4", &gfio_color_lightyellow);
gdk_color_parse("white", &gfio_color_white);
-
+
ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
gtk_window_set_default_size(GTK_WINDOW(ui->window), 1024, 768);
if (fio_init_options())
return 1;
+ gopt_init();
+
memset(&main_ui, 0, sizeof(main_ui));
main_ui.ge_hash = g_hash_table_new(g_int_hash, g_int_equal);
gdk_threads_leave();
g_hash_table_destroy(main_ui.ge_hash);
+
+ gopt_exit();
return 0;
}