+static GtkWidget *get_results_window(struct gui_entry *ge)
+{
+ GtkWidget *win, *notebook, *vbox;
+
+ if (ge->results_window)
+ return ge->results_notebook;
+
+ 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), ge);
+ g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ge);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(win), vbox);
+
+ ge->results_menu = get_results_menubar(win, ge);
+ gtk_box_pack_start(GTK_BOX(vbox), ge->results_menu, FALSE, FALSE, 0);
+
+ notebook = gtk_notebook_new();
+ gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), 1);
+ gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook));
+ gtk_container_add(GTK_CONTAINER(vbox), notebook);
+
+ ge->results_window = win;
+ ge->results_notebook = notebook;
+ return ge->results_notebook;
+}
+
+static void disk_util_destroy(GtkWidget *w, gpointer data)
+{
+ struct gui_entry *ge = (struct gui_entry *) data;
+
+ ge->disk_util_vbox = NULL;
+ gtk_widget_destroy(w);
+}
+
+static GtkWidget *get_scrolled_window(gint border_width)
+{
+ GtkWidget *scroll;
+
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(scroll), border_width);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ return scroll;
+}
+
+static GtkWidget *gfio_disk_util_get_vbox(struct gui_entry *ge)
+{
+ GtkWidget *vbox, *box, *scroll, *res_notebook;
+
+ if (ge->disk_util_vbox)
+ return ge->disk_util_vbox;
+
+ scroll = get_scrolled_window(5);
+ vbox = gtk_vbox_new(FALSE, 3);
+ 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);
+ res_notebook = get_results_window(ge);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(res_notebook), scroll, gtk_label_new("Disk utilization"));
+ ge->disk_util_vbox = box;
+ g_signal_connect(vbox, "destroy", G_CALLBACK(disk_util_destroy), ge);
+
+ return ge->disk_util_vbox;
+}
+
+static int __gfio_disk_util_show(GtkWidget *res_notebook,
+ struct gfio_client *gc, struct cmd_du_pdu *p)
+{
+ GtkWidget *box, *frame, *entry, *vbox, *util_vbox;
+ struct gui_entry *ge = gc->ge;
+ double util;
+ char tmp[16];
+
+ util_vbox = gfio_disk_util_get_vbox(ge);
+
+ vbox = gtk_vbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(util_vbox), vbox);
+
+ frame = gtk_frame_new((char *) p->dus.name);
+ gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 2);
+
+ box = gtk_vbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(frame), box);
+
+ frame = gtk_frame_new("Read");
+ gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2);
+ vbox = gtk_hbox_new(TRUE, 3);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ entry = new_info_entry_in_frame(vbox, "IOs");
+ entry_set_int_value(entry, p->dus.ios[0]);
+ entry = new_info_entry_in_frame(vbox, "Merges");
+ entry_set_int_value(entry, p->dus.merges[0]);
+ entry = new_info_entry_in_frame(vbox, "Sectors");
+ entry_set_int_value(entry, p->dus.sectors[0]);
+ entry = new_info_entry_in_frame(vbox, "Ticks");
+ entry_set_int_value(entry, p->dus.ticks[0]);
+
+ frame = gtk_frame_new("Write");
+ gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2);
+ vbox = gtk_hbox_new(TRUE, 3);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ entry = new_info_entry_in_frame(vbox, "IOs");
+ entry_set_int_value(entry, p->dus.ios[1]);
+ entry = new_info_entry_in_frame(vbox, "Merges");
+ entry_set_int_value(entry, p->dus.merges[1]);
+ entry = new_info_entry_in_frame(vbox, "Sectors");
+ entry_set_int_value(entry, p->dus.sectors[1]);
+ entry = new_info_entry_in_frame(vbox, "Ticks");
+ entry_set_int_value(entry, p->dus.ticks[1]);
+
+ frame = gtk_frame_new("Shared");
+ gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2);
+ vbox = gtk_hbox_new(TRUE, 3);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ entry = new_info_entry_in_frame(vbox, "IO ticks");
+ entry_set_int_value(entry, p->dus.io_ticks);
+ 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(ge->results_window);
+ return 0;
+}
+
+static int gfio_disk_util_show(struct gfio_client *gc)
+{
+ struct gui_entry *ge = gc->ge;
+ GtkWidget *res_notebook;
+ int i;
+
+ if (!gc->nr_du)
+ return 1;
+
+ res_notebook = get_results_window(ge);
+
+ for (i = 0; i < gc->nr_du; i++) {
+ struct cmd_du_pdu *p = &gc->du[i];
+
+ __gfio_disk_util_show(res_notebook, gc, p);
+ }
+
+ gtk_widget_show_all(ge->results_window);
+ return 0;
+}
+
+static void gfio_add_end_results(struct gfio_client *gc, struct thread_stat *ts,
+ struct group_run_stats *rs)
+{
+ unsigned int nr = gc->nr_results;
+
+ gc->results = realloc(gc->results, (nr + 1) * sizeof(struct end_results));
+ memcpy(&gc->results[nr].ts, ts, sizeof(*ts));
+ memcpy(&gc->results[nr].gs, rs, sizeof(*rs));
+ gc->nr_results++;
+}
+
+static void __gfio_display_end_results(GtkWidget *win, struct gfio_client *gc,
+ struct thread_stat *ts,
+ struct group_run_stats *rs)
+{
+ GtkWidget *box, *vbox, *entry, *scroll;
+
+ 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(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(win), scroll, gtk_label_new(ts->name));
+
+ entry = new_info_entry_in_frame(box, "Name");
+ gtk_entry_set_text(GTK_ENTRY(entry), ts->name);
+ if (strlen(ts->description)) {
+ entry = new_info_entry_in_frame(box, "Description");