*/
#include <locale.h>
#include <malloc.h>
+#include <string.h>
#include <glib.h>
#include <cairo.h>
#include "graph.h"
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])))
#define DRAWING_AREA_XDIM 1000
#define DRAWING_AREA_YDIM 400
GtkWidget *drawing_area;
+ int drawing_area_xdim;
+ int drawing_area_ydim;
GtkWidget *error_info_bar;
GtkWidget *error_label;
GtkWidget *results_notebook;
struct gui *ui;
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)
if (ui->iops_graph)
graph_free(ui->iops_graph);
ui->iops_graph = graph_new(DRAWING_AREA_XDIM / 2.0,
- DRAWING_AREA_YDIM);
+ DRAWING_AREA_YDIM, gfio_graph_font);
graph_title(ui->iops_graph, "IOPS");
- graph_x_title(ui->iops_graph, "Time");
- graph_y_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.7, 0.0, 0.0);
- graph_set_color(ui->iops_graph, "Write IOPS", 0.0, 0.0, 0.7);
+ graph_set_color(ui->iops_graph, "Read IOPS", 0.13, 0.54, 0.13);
+ graph_set_color(ui->iops_graph, "Write IOPS", 1.0, 0.0, 0.0);
+ line_graph_set_data_count_limit(ui->iops_graph, 100);
}
static void setup_bandwidth_graph(struct gui *ui)
if (ui->bandwidth_graph)
graph_free(ui->bandwidth_graph);
ui->bandwidth_graph = graph_new(DRAWING_AREA_XDIM / 2.0,
- DRAWING_AREA_YDIM);
+ DRAWING_AREA_YDIM, gfio_graph_font);
graph_title(ui->bandwidth_graph, "Bandwidth");
- graph_x_title(ui->bandwidth_graph, "Time");
- graph_y_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.7, 0.0, 0.0);
- graph_set_color(ui->bandwidth_graph, "Write Bandwidth", 0.0, 0.0, 0.7);
+ graph_set_color(ui->bandwidth_graph, "Read Bandwidth", 0.13, 0.54, 0.13);
+ graph_set_color(ui->bandwidth_graph, "Write Bandwidth", 1.0, 0.0, 0.0);
+ line_graph_set_data_count_limit(ui->bandwidth_graph, 100);
}
static void clear_ui_info(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);
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;
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);
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();
}
struct cmd_du_pdu *p = (struct cmd_du_pdu *) cmd->payload;
struct gfio_client *gc = client->client_data;
GtkWidget *box, *frame, *entry, *vbox;
+ double util;
+ char tmp[16];
gdk_threads_enter();
- if (!gc->results_widget) {
- printf("no results!\n");
+ if (!gc->results_widget)
goto out;
- }
if (!gc->disk_util_frame) {
gc->disk_util_frame = gtk_frame_new("Disk utilization");
entry = new_info_entry_in_frame(vbox, "Time in queue");
entry_set_int_value(entry, p->dus.time_in_queue);
+ util = 0.0;
+ if (p->dus.msec)
+ util = (double) 100 * p->dus.io_ticks / (double) p->dus.msec;
+ if (util > 100.0)
+ util = 100.0;
+
+ sprintf(tmp, "%3.2f%%", util);
+ entry = new_info_entry_in_frame(vbox, "Disk utilization");
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+
gtk_widget_show_all(gc->results_widget);
out:
gdk_threads_leave();
gdk_threads_leave();
}
+static gint on_config_drawing_area(GtkWidget *w, GdkEventConfigure *event)
+{
+ ui.drawing_area_xdim = w->allocation.width;
+ ui.drawing_area_ydim = w->allocation.height;
+ return TRUE;
+}
+
static int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p)
{
struct gui *ui = (struct gui *) p;
cairo_t *cr;
+ graph_set_size(ui->iops_graph, ui->drawing_area_xdim / 2.0,
+ ui->drawing_area_ydim);
+ graph_set_size(ui->bandwidth_graph, ui->drawing_area_xdim / 2.0,
+ ui->drawing_area_ydim);
cr = gdk_cairo_create(w->window);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_restore(cr);
cairo_save(cr);
- cairo_translate(cr, DRAWING_AREA_XDIM / 2.0, 0);
- // DRAWING_AREA_YDIM * 0.05);
+ cairo_translate(cr, ui->drawing_area_xdim / 2.0, 0);
line_graph_draw(ui->iops_graph, cr);
cairo_stroke(cr);
cairo_restore(cr);
{
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();
}
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);
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,
.quit = gfio_quit_op,
.add_job = gfio_add_job_op,
.timed_out = gfio_client_timed_out,
+ .stop = gfio_client_stop,
.stay_connected = 1,
};
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);
static void preferences(GtkWidget *w, gpointer data)
{
- GtkWidget *dialog, *frame, *box, **buttons;
+ GtkWidget *dialog, *frame, *box, **buttons, *vbox, *font;
int i;
dialog = gtk_dialog_new_with_buttons("Preferences",
frame = gtk_frame_new("Debug logging");
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);
+
box = gtk_hbox_new(FALSE, 6);
- gtk_container_add(GTK_CONTAINER(frame), box);
+ gtk_container_add(GTK_CONTAINER(vbox), box);
buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
for (i = 0; i < FD_DEBUG_MAX; i++) {
+ if (i == 7) {
+ box = gtk_hbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(vbox), box);
+ }
+
+
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);
}
+ frame = gtk_frame_new("Graph font");
+ 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);
+
+ font = gtk_font_button_new();
+ gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5);
+
gtk_widget_show_all(dialog);
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
fio_debug |= (1UL << i);
}
+ gfio_graph_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font)));
gtk_widget_destroy(dialog);
}
static void about_dialog(GtkWidget *w, gpointer data)
{
+ const char *authors[] = {
+ "Jens Axboe <axboe@kernel.dk>",
+ "Stephen Carmeron <stephenmcameron@gmail.com>",
+ NULL
+ };
+ const char *license[] = {
+ "Fio is free software; you can redistribute it and/or modify "
+ "it under the terms of the GNU General Public License as published by "
+ "the Free Software Foundation; either version 2 of the License, or "
+ "(at your option) any later version.\n",
+ "Fio is distributed in the hope that it will be useful, "
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of "
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
+ "GNU General Public License for more details.\n",
+ "You should have received a copy of the GNU General Public License "
+ "along with Fio; if not, write to the Free Software Foundation, Inc., "
+ "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ };
+ char *license_trans;
+
+ license_trans = g_strconcat(license[0], "\n", license[1], "\n",
+ license[2], "\n", NULL);
+
gtk_show_about_dialog(NULL,
"program-name", "gfio",
"comments", "Gtk2 UI for fio",
- "license", "GPLv2",
+ "license", license_trans,
+ "website", "http://git.kernel.dk/?p=fio.git;a=summary",
+ "authors", authors,
"version", fio_version_string,
- "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
+ "copyright", "© 2012 Jens Axboe <axboe@kernel.dk>",
"logo-icon-name", "fio",
/* Must be last: */
- NULL, NULL,
+ "wrap-license", TRUE,
NULL);
+
+ g_free (license_trans);
}
static GtkActionEntry menu_items[] = {
GtkSettings *settings;
GtkUIManager *uimanager;
GtkWidget *menu, *probe, *probe_frame, *probe_box;
+ GdkColor white;
memset(ui, 0, sizeof(*ui));
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), 700, 500);
+ gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 700);
g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
/*
* Set up a drawing area and IOPS and bandwidth graphs
*/
+ gdk_color_parse("white", &white);
ui->drawing_area = gtk_drawing_area_new();
+ ui->drawing_area_xdim = DRAWING_AREA_XDIM;
+ ui->drawing_area_ydim = DRAWING_AREA_YDIM;
gtk_widget_set_size_request(GTK_WIDGET(ui->drawing_area),
- DRAWING_AREA_XDIM, DRAWING_AREA_YDIM);
+ ui->drawing_area_xdim, ui->drawing_area_ydim);
+ gtk_widget_modify_bg(ui->drawing_area, GTK_STATE_NORMAL, &white);
g_signal_connect(G_OBJECT(ui->drawing_area), "expose_event",
G_CALLBACK (on_expose_drawing_area), ui);
+ g_signal_connect(G_OBJECT(ui->drawing_area), "configure_event",
+ G_CALLBACK (on_config_drawing_area), ui);
ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);