Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 1 | /* |
| 2 | * gfio - gui front end for fio - the flexible io tester |
| 3 | * |
| 4 | * Copyright (C) 2012 Stephen M. Cameron <stephenmcameron@gmail.com> |
Jens Axboe | c0187f3 | 2012-03-06 15:39:15 +0100 | [diff] [blame] | 5 | * Copyright (C) 2012 Jens Axboe <axboe@kernel.dk> |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 6 | * |
| 7 | * The license below covers all files distributed with fio unless otherwise |
| 8 | * noted in the file itself. |
| 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License version 2 as |
| 12 | * published by the Free Software Foundation. |
| 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | * GNU General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program; if not, write to the Free Software |
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 22 | * |
| 23 | */ |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 24 | #include <locale.h> |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 25 | #include <malloc.h> |
Jens Axboe | 6b79c80 | 2012-03-08 10:51:36 +0100 | [diff] [blame] | 26 | #include <string.h> |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 27 | |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 28 | #include <glib.h> |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 29 | #include <cairo.h> |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 30 | #include <gtk/gtk.h> |
| 31 | |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 32 | #include "fio.h" |
Jens Axboe | 53e0e85 | 2012-03-15 19:38:01 +0100 | [diff] [blame] | 33 | #include "gfio.h" |
| 34 | #include "ghelpers.h" |
Jens Axboe | 9af4a24 | 2012-03-16 10:13:49 +0100 | [diff] [blame^] | 35 | #include "goptions.h" |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 36 | #include "graph.h" |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 37 | |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 38 | static int gfio_server_running; |
Jens Axboe | f3e8440 | 2012-03-07 13:14:32 +0100 | [diff] [blame] | 39 | static const char *gfio_graph_font; |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 40 | static unsigned int gfio_graph_limit = 100; |
Stephen M. Cameron | 814479d | 2012-03-15 07:58:14 +0100 | [diff] [blame] | 41 | static GdkColor white; |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 42 | |
Jens Axboe | 6b79c80 | 2012-03-08 10:51:36 +0100 | [diff] [blame] | 43 | static void view_log(GtkWidget *w, gpointer data); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 44 | |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 45 | typedef void (*clickfunction)(GtkWidget *widget, gpointer data); |
| 46 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 47 | static void connect_clicked(GtkWidget *widget, gpointer data); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 48 | static void start_job_clicked(GtkWidget *widget, gpointer data); |
Jens Axboe | b9d2f30 | 2012-03-08 20:36:28 +0100 | [diff] [blame] | 49 | static void send_clicked(GtkWidget *widget, gpointer data); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 50 | |
| 51 | static struct button_spec { |
| 52 | const char *buttontext; |
| 53 | clickfunction f; |
Jens Axboe | 014f402 | 2012-03-15 14:03:01 +0100 | [diff] [blame] | 54 | const char *tooltiptext[2]; |
| 55 | const int start_sensitive; |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 56 | } buttonspeclist[] = { |
Jens Axboe | 53e0e85 | 2012-03-15 19:38:01 +0100 | [diff] [blame] | 57 | { |
| 58 | .buttontext = "Connect", |
| 59 | .f = connect_clicked, |
| 60 | .tooltiptext = { "Disconnect from host", "Connect to host" }, |
| 61 | .start_sensitive = 1, |
| 62 | }, |
| 63 | { |
| 64 | .buttontext = "Send", |
| 65 | .f = send_clicked, |
| 66 | .tooltiptext = { "Send job description to host", NULL }, |
| 67 | .start_sensitive = 0, |
| 68 | }, |
| 69 | { |
| 70 | .buttontext = "Start Job", |
| 71 | .f = start_job_clicked, |
| 72 | .tooltiptext = { "Start the current job on the server", NULL }, |
| 73 | .start_sensitive = 0, |
| 74 | }, |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 75 | }; |
| 76 | |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 77 | static void gfio_update_thread_status(struct gui_entry *ge, char *status_message, double perc); |
| 78 | static void gfio_update_thread_status_all(char *status_message, double perc); |
Jens Axboe | c724926 | 2012-03-09 17:11:04 +0100 | [diff] [blame] | 79 | void report_error(GError *error); |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 80 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 81 | static struct graph *setup_iops_graph(void) |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 82 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 83 | struct graph *g; |
| 84 | |
| 85 | g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font); |
Jens Axboe | d8fbeef | 2012-03-14 10:25:44 +0100 | [diff] [blame] | 86 | graph_title(g, "IOPS (IOs/sec)"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 87 | graph_x_title(g, "Time (secs)"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 88 | graph_add_label(g, "Read IOPS"); |
| 89 | graph_add_label(g, "Write IOPS"); |
| 90 | graph_set_color(g, "Read IOPS", 0.13, 0.54, 0.13); |
| 91 | graph_set_color(g, "Write IOPS", 1.0, 0.0, 0.0); |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 92 | line_graph_set_data_count_limit(g, gfio_graph_limit); |
Jens Axboe | d8fbeef | 2012-03-14 10:25:44 +0100 | [diff] [blame] | 93 | graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 94 | return g; |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 95 | } |
| 96 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 97 | static struct graph *setup_bandwidth_graph(void) |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 98 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 99 | struct graph *g; |
| 100 | |
| 101 | g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font); |
Jens Axboe | d8fbeef | 2012-03-14 10:25:44 +0100 | [diff] [blame] | 102 | graph_title(g, "Bandwidth (bytes/sec)"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 103 | graph_x_title(g, "Time (secs)"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 104 | graph_add_label(g, "Read Bandwidth"); |
| 105 | graph_add_label(g, "Write Bandwidth"); |
| 106 | graph_set_color(g, "Read Bandwidth", 0.13, 0.54, 0.13); |
| 107 | graph_set_color(g, "Write Bandwidth", 1.0, 0.0, 0.0); |
Jens Axboe | d8fbeef | 2012-03-14 10:25:44 +0100 | [diff] [blame] | 108 | graph_set_base_offset(g, 1); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 109 | line_graph_set_data_count_limit(g, 100); |
Jens Axboe | d8fbeef | 2012-03-14 10:25:44 +0100 | [diff] [blame] | 110 | graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 111 | return g; |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 112 | } |
| 113 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 114 | static void setup_graphs(struct gfio_graphs *g) |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 115 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 116 | g->iops_graph = setup_iops_graph(); |
| 117 | g->bandwidth_graph = setup_bandwidth_graph(); |
| 118 | } |
| 119 | |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 120 | static void multitext_add_entry(struct multitext_widget *mt, const char *text) |
| 121 | { |
| 122 | mt->text = realloc(mt->text, (mt->max_text + 1) * sizeof(char *)); |
| 123 | mt->text[mt->max_text] = strdup(text); |
| 124 | mt->max_text++; |
| 125 | } |
| 126 | |
| 127 | static void multitext_set_entry(struct multitext_widget *mt, unsigned int index) |
| 128 | { |
| 129 | if (index >= mt->max_text) |
| 130 | return; |
Jens Axboe | da18543 | 2012-03-12 11:05:46 +0100 | [diff] [blame] | 131 | if (!mt->text || !mt->text[index]) |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 132 | return; |
| 133 | |
| 134 | mt->cur_text = index; |
| 135 | gtk_entry_set_text(GTK_ENTRY(mt->entry), mt->text[index]); |
| 136 | } |
| 137 | |
| 138 | static void multitext_update_entry(struct multitext_widget *mt, |
| 139 | unsigned int index, const char *text) |
| 140 | { |
Jens Axboe | da18543 | 2012-03-12 11:05:46 +0100 | [diff] [blame] | 141 | if (!mt->text) |
| 142 | return; |
| 143 | |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 144 | if (mt->text[index]) |
| 145 | free(mt->text[index]); |
| 146 | |
| 147 | mt->text[index] = strdup(text); |
| 148 | if (mt->cur_text == index) |
| 149 | gtk_entry_set_text(GTK_ENTRY(mt->entry), mt->text[index]); |
| 150 | } |
| 151 | |
| 152 | static void multitext_free(struct multitext_widget *mt) |
| 153 | { |
| 154 | int i; |
| 155 | |
| 156 | gtk_entry_set_text(GTK_ENTRY(mt->entry), ""); |
| 157 | |
| 158 | for (i = 0; i < mt->max_text; i++) { |
| 159 | if (mt->text[i]) |
| 160 | free(mt->text[i]); |
| 161 | } |
| 162 | |
| 163 | free(mt->text); |
| 164 | mt->cur_text = -1; |
| 165 | mt->max_text = 0; |
| 166 | } |
| 167 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 168 | static void clear_ge_ui_info(struct gui_entry *ge) |
| 169 | { |
| 170 | gtk_label_set_text(GTK_LABEL(ge->probe.hostname), ""); |
| 171 | gtk_label_set_text(GTK_LABEL(ge->probe.os), ""); |
| 172 | gtk_label_set_text(GTK_LABEL(ge->probe.arch), ""); |
| 173 | gtk_label_set_text(GTK_LABEL(ge->probe.fio_ver), ""); |
Jens Axboe | 3863d1a | 2012-03-09 17:39:05 +0100 | [diff] [blame] | 174 | #if 0 |
| 175 | /* should we empty it... */ |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 176 | gtk_entry_set_text(GTK_ENTRY(ge->eta.name), ""); |
Jens Axboe | 3863d1a | 2012-03-09 17:39:05 +0100 | [diff] [blame] | 177 | #endif |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 178 | multitext_update_entry(&ge->eta.iotype, 0, ""); |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 179 | multitext_update_entry(&ge->eta.bs, 0, ""); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 180 | multitext_update_entry(&ge->eta.ioengine, 0, ""); |
| 181 | multitext_update_entry(&ge->eta.iodepth, 0, ""); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 182 | gtk_entry_set_text(GTK_ENTRY(ge->eta.jobs), ""); |
| 183 | gtk_entry_set_text(GTK_ENTRY(ge->eta.files), ""); |
| 184 | gtk_entry_set_text(GTK_ENTRY(ge->eta.read_bw), ""); |
| 185 | gtk_entry_set_text(GTK_ENTRY(ge->eta.read_iops), ""); |
| 186 | gtk_entry_set_text(GTK_ENTRY(ge->eta.write_bw), ""); |
| 187 | gtk_entry_set_text(GTK_ENTRY(ge->eta.write_iops), ""); |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 188 | } |
| 189 | |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 190 | static void show_info_dialog(struct gui *ui, const char *title, |
| 191 | const char *message) |
| 192 | { |
| 193 | GtkWidget *dialog, *content, *label; |
| 194 | |
| 195 | dialog = gtk_dialog_new_with_buttons(title, GTK_WINDOW(ui->window), |
| 196 | GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, |
| 197 | GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); |
| 198 | |
| 199 | content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); |
| 200 | label = gtk_label_new(message); |
| 201 | gtk_container_add(GTK_CONTAINER(content), label); |
| 202 | gtk_widget_show_all(dialog); |
| 203 | gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); |
| 204 | gtk_dialog_run(GTK_DIALOG(dialog)); |
| 205 | gtk_widget_destroy(dialog); |
| 206 | } |
| 207 | |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 208 | static void set_menu_entry_text(struct gui *ui, const char *path, |
| 209 | const char *text) |
| 210 | { |
| 211 | GtkWidget *w; |
| 212 | |
| 213 | w = gtk_ui_manager_get_widget(ui->uimanager, path); |
| 214 | if (w) |
| 215 | gtk_menu_item_set_label(GTK_MENU_ITEM(w), text); |
| 216 | else |
| 217 | fprintf(stderr, "gfio: can't find path %s\n", path); |
| 218 | } |
| 219 | |
| 220 | |
| 221 | static void set_menu_entry_visible(struct gui *ui, const char *path, int show) |
| 222 | { |
| 223 | GtkWidget *w; |
| 224 | |
| 225 | w = gtk_ui_manager_get_widget(ui->uimanager, path); |
| 226 | if (w) |
| 227 | gtk_widget_set_sensitive(w, show); |
| 228 | else |
| 229 | fprintf(stderr, "gfio: can't find path %s\n", path); |
| 230 | } |
| 231 | |
| 232 | static void set_job_menu_visible(struct gui *ui, int visible) |
| 233 | { |
| 234 | set_menu_entry_visible(ui, "/MainMenu/JobMenu", visible); |
| 235 | } |
| 236 | |
| 237 | static void set_view_results_visible(struct gui *ui, int visible) |
| 238 | { |
| 239 | set_menu_entry_visible(ui, "/MainMenu/ViewMenu/Results", visible); |
| 240 | } |
| 241 | |
Jens Axboe | 014f402 | 2012-03-15 14:03:01 +0100 | [diff] [blame] | 242 | static const char *get_button_tooltip(struct button_spec *s, int sensitive) |
| 243 | { |
| 244 | if (s->tooltiptext[sensitive]) |
| 245 | return s->tooltiptext[sensitive]; |
| 246 | |
| 247 | return s->tooltiptext[0]; |
| 248 | } |
| 249 | |
| 250 | static GtkWidget *add_button(GtkWidget *buttonbox, |
| 251 | struct button_spec *buttonspec, gpointer data) |
| 252 | { |
| 253 | GtkWidget *button = gtk_button_new_with_label(buttonspec->buttontext); |
| 254 | gboolean sens = buttonspec->start_sensitive; |
| 255 | |
| 256 | g_signal_connect(button, "clicked", G_CALLBACK(buttonspec->f), data); |
| 257 | gtk_box_pack_start(GTK_BOX(buttonbox), button, FALSE, FALSE, 3); |
| 258 | |
| 259 | sens = buttonspec->start_sensitive; |
| 260 | gtk_widget_set_tooltip_text(button, get_button_tooltip(buttonspec, sens)); |
| 261 | gtk_widget_set_sensitive(button, sens); |
| 262 | |
| 263 | return button; |
| 264 | } |
| 265 | |
| 266 | static void add_buttons(struct gui_entry *ge, struct button_spec *buttonlist, |
| 267 | int nbuttons) |
| 268 | { |
| 269 | int i; |
| 270 | |
| 271 | for (i = 0; i < nbuttons; i++) |
| 272 | ge->button[i] = add_button(ge->buttonbox, &buttonlist[i], ge); |
| 273 | } |
| 274 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 275 | /* |
| 276 | * Update sensitivity of job buttons and job menu items, based on the |
| 277 | * state of the client. |
| 278 | */ |
| 279 | static void update_button_states(struct gui *ui, struct gui_entry *ge) |
| 280 | { |
| 281 | unsigned int connect_state, send_state, start_state, edit_state; |
| 282 | const char *connect_str = NULL; |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 283 | |
| 284 | switch (ge->state) { |
| 285 | default: { |
| 286 | char tmp[80]; |
| 287 | |
| 288 | sprintf(tmp, "Bad client state: %u\n", ge->state); |
| 289 | show_info_dialog(ui, "Error", tmp); |
| 290 | /* fall through to new state */ |
| 291 | } |
| 292 | |
| 293 | case GE_STATE_NEW: |
| 294 | connect_state = 1; |
Jens Axboe | 9af4a24 | 2012-03-16 10:13:49 +0100 | [diff] [blame^] | 295 | edit_state = 1; |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 296 | connect_str = "Connect"; |
| 297 | send_state = 0; |
| 298 | start_state = 0; |
| 299 | break; |
| 300 | case GE_STATE_CONNECTED: |
| 301 | connect_state = 1; |
Jens Axboe | 9af4a24 | 2012-03-16 10:13:49 +0100 | [diff] [blame^] | 302 | edit_state = 1; |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 303 | connect_str = "Disconnect"; |
| 304 | send_state = 1; |
| 305 | start_state = 0; |
| 306 | break; |
| 307 | case GE_STATE_JOB_SENT: |
| 308 | connect_state = 1; |
Jens Axboe | 9af4a24 | 2012-03-16 10:13:49 +0100 | [diff] [blame^] | 309 | edit_state = 1; |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 310 | connect_str = "Disconnect"; |
| 311 | send_state = 0; |
| 312 | start_state = 1; |
| 313 | break; |
| 314 | case GE_STATE_JOB_STARTED: |
| 315 | connect_state = 1; |
| 316 | edit_state = 1; |
| 317 | connect_str = "Disconnect"; |
| 318 | send_state = 0; |
| 319 | start_state = 1; |
| 320 | break; |
| 321 | case GE_STATE_JOB_RUNNING: |
| 322 | connect_state = 1; |
| 323 | edit_state = 0; |
| 324 | connect_str = "Disconnect"; |
| 325 | send_state = 0; |
| 326 | start_state = 0; |
| 327 | break; |
| 328 | case GE_STATE_JOB_DONE: |
| 329 | connect_state = 1; |
| 330 | edit_state = 0; |
| 331 | connect_str = "Connect"; |
| 332 | send_state = 0; |
| 333 | start_state = 0; |
| 334 | break; |
| 335 | } |
| 336 | |
Jens Axboe | 53e0e85 | 2012-03-15 19:38:01 +0100 | [diff] [blame] | 337 | gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_CONNECT], connect_state); |
| 338 | gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_SEND], send_state); |
| 339 | gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_START], start_state); |
| 340 | gtk_button_set_label(GTK_BUTTON(ge->button[GFIO_BUTTON_CONNECT]), connect_str); |
| 341 | gtk_widget_set_tooltip_text(ge->button[GFIO_BUTTON_CONNECT], get_button_tooltip(&buttonspeclist[GFIO_BUTTON_CONNECT], connect_state)); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 342 | |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 343 | set_menu_entry_visible(ui, "/MainMenu/JobMenu/Connect", connect_state); |
| 344 | set_menu_entry_text(ui, "/MainMenu/JobMenu/Connect", connect_str); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 345 | |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 346 | set_menu_entry_visible(ui, "/MainMenu/JobMenu/Edit job", edit_state); |
| 347 | set_menu_entry_visible(ui, "/MainMenu/JobMenu/Send job", send_state); |
| 348 | set_menu_entry_visible(ui, "/MainMenu/JobMenu/Start job", start_state); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 349 | |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 350 | if (ge->client && ge->client->nr_results) |
| 351 | set_view_results_visible(ui, 1); |
| 352 | else |
| 353 | set_view_results_visible(ui, 0); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | static void gfio_set_state(struct gui_entry *ge, unsigned int state) |
| 357 | { |
| 358 | ge->state = state; |
| 359 | update_button_states(ge->ui, ge); |
| 360 | } |
| 361 | |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 362 | #define ALIGN_LEFT 1 |
| 363 | #define ALIGN_RIGHT 2 |
| 364 | #define INVISIBLE 4 |
| 365 | #define UNSORTABLE 8 |
| 366 | |
| 367 | GtkTreeViewColumn *tree_view_column(GtkWidget *tree_view, int index, const char *title, unsigned int flags) |
| 368 | { |
| 369 | GtkCellRenderer *renderer; |
| 370 | GtkTreeViewColumn *col; |
| 371 | double xalign = 0.0; /* left as default */ |
| 372 | PangoAlignment align; |
| 373 | gboolean visible; |
| 374 | |
| 375 | align = (flags & ALIGN_LEFT) ? PANGO_ALIGN_LEFT : |
| 376 | (flags & ALIGN_RIGHT) ? PANGO_ALIGN_RIGHT : |
| 377 | PANGO_ALIGN_CENTER; |
| 378 | visible = !(flags & INVISIBLE); |
| 379 | |
| 380 | renderer = gtk_cell_renderer_text_new(); |
| 381 | col = gtk_tree_view_column_new(); |
| 382 | |
| 383 | gtk_tree_view_column_set_title(col, title); |
| 384 | if (!(flags & UNSORTABLE)) |
| 385 | gtk_tree_view_column_set_sort_column_id(col, index); |
| 386 | gtk_tree_view_column_set_resizable(col, TRUE); |
| 387 | gtk_tree_view_column_pack_start(col, renderer, TRUE); |
| 388 | gtk_tree_view_column_add_attribute(col, renderer, "text", index); |
| 389 | gtk_object_set(GTK_OBJECT(renderer), "alignment", align, NULL); |
| 390 | switch (align) { |
| 391 | case PANGO_ALIGN_LEFT: |
| 392 | xalign = 0.0; |
| 393 | break; |
| 394 | case PANGO_ALIGN_CENTER: |
| 395 | xalign = 0.5; |
| 396 | break; |
| 397 | case PANGO_ALIGN_RIGHT: |
| 398 | xalign = 1.0; |
| 399 | break; |
| 400 | } |
| 401 | gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), xalign, 0.5); |
| 402 | gtk_tree_view_column_set_visible(col, visible); |
| 403 | gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), col); |
| 404 | return col; |
| 405 | } |
| 406 | |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 407 | static void gfio_ui_setup_log(struct gui *ui) |
| 408 | { |
| 409 | GtkTreeSelection *selection; |
| 410 | GtkListStore *model; |
| 411 | GtkWidget *tree_view; |
| 412 | |
| 413 | model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING); |
| 414 | |
| 415 | tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); |
| 416 | gtk_widget_set_can_focus(tree_view, FALSE); |
| 417 | |
| 418 | selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)); |
| 419 | gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE); |
Jens Axboe | 661f741 | 2012-03-06 13:55:45 +0100 | [diff] [blame] | 420 | g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE, |
| 421 | "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL); |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 422 | |
| 423 | tree_view_column(tree_view, 0, "Time", ALIGN_RIGHT | UNSORTABLE); |
| 424 | tree_view_column(tree_view, 1, "Host", ALIGN_RIGHT | UNSORTABLE); |
| 425 | tree_view_column(tree_view, 2, "Level", ALIGN_RIGHT | UNSORTABLE); |
Jens Axboe | f095d56 | 2012-03-06 13:49:12 +0100 | [diff] [blame] | 426 | tree_view_column(tree_view, 3, "Text", ALIGN_LEFT | UNSORTABLE); |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 427 | |
| 428 | ui->log_model = model; |
| 429 | ui->log_tree = tree_view; |
| 430 | } |
| 431 | |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 432 | static struct graph *setup_clat_graph(char *title, unsigned int *ovals, |
| 433 | fio_fp64_t *plist, |
| 434 | unsigned int len, |
| 435 | double xdim, double ydim) |
| 436 | { |
| 437 | struct graph *g; |
| 438 | int i; |
| 439 | |
| 440 | g = graph_new(xdim, ydim, gfio_graph_font); |
| 441 | graph_title(g, title); |
| 442 | graph_x_title(g, "Percentile"); |
| 443 | |
| 444 | for (i = 0; i < len; i++) { |
| 445 | char fbuf[8]; |
| 446 | |
| 447 | sprintf(fbuf, "%2.2f%%", plist[i].u.f); |
| 448 | graph_add_label(g, fbuf); |
| 449 | graph_add_data(g, fbuf, (double) ovals[i]); |
| 450 | } |
| 451 | |
| 452 | return g; |
| 453 | } |
| 454 | |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 455 | static GtkWidget *gfio_output_clat_percentiles(unsigned int *ovals, |
| 456 | fio_fp64_t *plist, |
| 457 | unsigned int len, |
| 458 | const char *base, |
| 459 | unsigned int scale) |
| 460 | { |
| 461 | GType types[FIO_IO_U_LIST_MAX_LEN]; |
| 462 | GtkWidget *tree_view; |
| 463 | GtkTreeSelection *selection; |
| 464 | GtkListStore *model; |
| 465 | GtkTreeIter iter; |
| 466 | int i; |
| 467 | |
| 468 | for (i = 0; i < len; i++) |
| 469 | types[i] = G_TYPE_INT; |
| 470 | |
| 471 | model = gtk_list_store_newv(len, types); |
| 472 | |
| 473 | tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); |
| 474 | gtk_widget_set_can_focus(tree_view, FALSE); |
| 475 | |
Jens Axboe | 661f741 | 2012-03-06 13:55:45 +0100 | [diff] [blame] | 476 | g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE, |
| 477 | "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL); |
| 478 | |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 479 | selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)); |
| 480 | gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE); |
| 481 | |
| 482 | for (i = 0; i < len; i++) { |
| 483 | char fbuf[8]; |
| 484 | |
| 485 | sprintf(fbuf, "%2.2f%%", plist[i].u.f); |
| 486 | tree_view_column(tree_view, i, fbuf, ALIGN_RIGHT | UNSORTABLE); |
| 487 | } |
| 488 | |
| 489 | gtk_list_store_append(model, &iter); |
| 490 | |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 491 | for (i = 0; i < len; i++) { |
| 492 | if (scale) |
| 493 | ovals[i] = (ovals[i] + 999) / 1000; |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 494 | gtk_list_store_set(model, &iter, i, ovals[i], -1); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 495 | } |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 496 | |
| 497 | return tree_view; |
| 498 | } |
| 499 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 500 | static int on_expose_lat_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p) |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 501 | { |
| 502 | struct graph *g = p; |
| 503 | cairo_t *cr; |
| 504 | |
| 505 | cr = gdk_cairo_create(w->window); |
| 506 | #if 0 |
| 507 | if (graph_has_tooltips(g)) { |
| 508 | g_object_set(w, "has-tooltip", TRUE, NULL); |
| 509 | g_signal_connect(w, "query-tooltip", G_CALLBACK(clat_graph_tooltip), g); |
| 510 | } |
| 511 | #endif |
| 512 | cairo_set_source_rgb(cr, 0, 0, 0); |
| 513 | bar_graph_draw(g, cr); |
| 514 | cairo_destroy(cr); |
| 515 | |
| 516 | return FALSE; |
| 517 | } |
| 518 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 519 | static gint on_config_lat_drawing_area(GtkWidget *w, GdkEventConfigure *event, |
| 520 | gpointer data) |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 521 | { |
| 522 | struct graph *g = data; |
| 523 | |
| 524 | graph_set_size(g, w->allocation.width, w->allocation.height); |
| 525 | graph_set_size(g, w->allocation.width, w->allocation.height); |
| 526 | graph_set_position(g, 0, 0); |
| 527 | return TRUE; |
| 528 | } |
| 529 | |
| 530 | static void gfio_show_clat_percentiles(struct gfio_client *gc, |
| 531 | GtkWidget *vbox, struct thread_stat *ts, |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 532 | int ddir) |
| 533 | { |
| 534 | unsigned int *io_u_plat = ts->io_u_plat[ddir]; |
| 535 | unsigned long nr = ts->clat_stat[ddir].samples; |
| 536 | fio_fp64_t *plist = ts->percentile_list; |
| 537 | unsigned int *ovals, len, minv, maxv, scale_down; |
| 538 | const char *base; |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 539 | GtkWidget *tree_view, *frame, *hbox, *drawing_area, *completion_vbox; |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 540 | struct gui_entry *ge = gc->ge; |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 541 | char tmp[64]; |
| 542 | |
| 543 | len = calc_clat_percentiles(io_u_plat, nr, plist, &ovals, &maxv, &minv); |
| 544 | if (!len) |
| 545 | goto out; |
| 546 | |
| 547 | /* |
| 548 | * We default to usecs, but if the value range is such that we |
| 549 | * should scale down to msecs, do that. |
| 550 | */ |
| 551 | if (minv > 2000 && maxv > 99999) { |
| 552 | scale_down = 1; |
| 553 | base = "msec"; |
| 554 | } else { |
| 555 | scale_down = 0; |
| 556 | base = "usec"; |
| 557 | } |
| 558 | |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 559 | sprintf(tmp, "Completion percentiles (%s)", base); |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 560 | tree_view = gfio_output_clat_percentiles(ovals, plist, len, base, scale_down); |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 561 | ge->clat_graph = setup_clat_graph(tmp, ovals, plist, len, 700.0, 300.0); |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 562 | |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 563 | frame = gtk_frame_new(tmp); |
| 564 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 565 | |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 566 | completion_vbox = gtk_vbox_new(FALSE, 3); |
| 567 | gtk_container_add(GTK_CONTAINER(frame), completion_vbox); |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 568 | hbox = gtk_hbox_new(FALSE, 3); |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 569 | gtk_container_add(GTK_CONTAINER(completion_vbox), hbox); |
| 570 | drawing_area = gtk_drawing_area_new(); |
| 571 | gtk_widget_set_size_request(GTK_WIDGET(drawing_area), 700, 300); |
| 572 | gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &white); |
| 573 | gtk_container_add(GTK_CONTAINER(completion_vbox), drawing_area); |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 574 | g_signal_connect(G_OBJECT(drawing_area), "expose_event", G_CALLBACK(on_expose_lat_drawing_area), ge->clat_graph); |
| 575 | g_signal_connect(G_OBJECT(drawing_area), "configure_event", G_CALLBACK(on_config_lat_drawing_area), ge->clat_graph); |
Jens Axboe | a269790 | 2012-03-05 16:43:49 +0100 | [diff] [blame] | 576 | |
| 577 | gtk_box_pack_start(GTK_BOX(hbox), tree_view, TRUE, FALSE, 3); |
| 578 | out: |
| 579 | if (ovals) |
| 580 | free(ovals); |
| 581 | } |
| 582 | |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 583 | static void gfio_show_lat(GtkWidget *vbox, const char *name, unsigned long min, |
| 584 | unsigned long max, double mean, double dev) |
| 585 | { |
| 586 | const char *base = "(usec)"; |
Jens Axboe | 1c1e4a5 | 2012-03-05 14:37:38 +0100 | [diff] [blame] | 587 | GtkWidget *hbox, *label, *frame; |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 588 | char *minp, *maxp; |
| 589 | char tmp[64]; |
| 590 | |
| 591 | if (!usec_to_msec(&min, &max, &mean, &dev)) |
| 592 | base = "(msec)"; |
| 593 | |
| 594 | minp = num2str(min, 6, 1, 0); |
| 595 | maxp = num2str(max, 6, 1, 0); |
| 596 | |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 597 | sprintf(tmp, "%s %s", name, base); |
| 598 | frame = gtk_frame_new(tmp); |
| 599 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 600 | |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 601 | hbox = gtk_hbox_new(FALSE, 3); |
Jens Axboe | 1c1e4a5 | 2012-03-05 14:37:38 +0100 | [diff] [blame] | 602 | gtk_container_add(GTK_CONTAINER(frame), hbox); |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 603 | |
| 604 | label = new_info_label_in_frame(hbox, "Minimum"); |
| 605 | gtk_label_set_text(GTK_LABEL(label), minp); |
| 606 | label = new_info_label_in_frame(hbox, "Maximum"); |
| 607 | gtk_label_set_text(GTK_LABEL(label), maxp); |
| 608 | label = new_info_label_in_frame(hbox, "Average"); |
| 609 | sprintf(tmp, "%5.02f", mean); |
| 610 | gtk_label_set_text(GTK_LABEL(label), tmp); |
| 611 | label = new_info_label_in_frame(hbox, "Standard deviation"); |
| 612 | sprintf(tmp, "%5.02f", dev); |
| 613 | gtk_label_set_text(GTK_LABEL(label), tmp); |
| 614 | |
| 615 | free(minp); |
| 616 | free(maxp); |
| 617 | |
| 618 | } |
| 619 | |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 620 | #define GFIO_CLAT 1 |
| 621 | #define GFIO_SLAT 2 |
| 622 | #define GFIO_LAT 4 |
| 623 | |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 624 | static void gfio_show_ddir_status(struct gfio_client *gc, GtkWidget *mbox, |
| 625 | struct group_run_stats *rs, |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 626 | struct thread_stat *ts, int ddir) |
| 627 | { |
| 628 | const char *ddir_label[2] = { "Read", "Write" }; |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 629 | GtkWidget *frame, *label, *box, *vbox, *main_vbox; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 630 | unsigned long min[3], max[3], runt; |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 631 | unsigned long long bw, iops; |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 632 | unsigned int flags = 0; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 633 | double mean[3], dev[3]; |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 634 | char *io_p, *bw_p, *iops_p; |
| 635 | int i2p; |
| 636 | |
| 637 | if (!ts->runtime[ddir]) |
| 638 | return; |
| 639 | |
| 640 | i2p = is_power_of_2(rs->kb_base); |
| 641 | runt = ts->runtime[ddir]; |
| 642 | |
| 643 | bw = (1000 * ts->io_bytes[ddir]) / runt; |
| 644 | io_p = num2str(ts->io_bytes[ddir], 6, 1, i2p); |
| 645 | bw_p = num2str(bw, 6, 1, i2p); |
| 646 | |
| 647 | iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt; |
| 648 | iops_p = num2str(iops, 6, 1, 0); |
| 649 | |
| 650 | box = gtk_hbox_new(FALSE, 3); |
| 651 | gtk_box_pack_start(GTK_BOX(mbox), box, TRUE, FALSE, 3); |
| 652 | |
| 653 | frame = gtk_frame_new(ddir_label[ddir]); |
| 654 | gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 5); |
| 655 | |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 656 | main_vbox = gtk_vbox_new(FALSE, 3); |
| 657 | gtk_container_add(GTK_CONTAINER(frame), main_vbox); |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 658 | |
| 659 | box = gtk_hbox_new(FALSE, 3); |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 660 | gtk_box_pack_start(GTK_BOX(main_vbox), box, TRUE, FALSE, 3); |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 661 | |
| 662 | label = new_info_label_in_frame(box, "IO"); |
| 663 | gtk_label_set_text(GTK_LABEL(label), io_p); |
| 664 | label = new_info_label_in_frame(box, "Bandwidth"); |
| 665 | gtk_label_set_text(GTK_LABEL(label), bw_p); |
| 666 | label = new_info_label_in_frame(box, "IOPS"); |
| 667 | gtk_label_set_text(GTK_LABEL(label), iops_p); |
| 668 | label = new_info_label_in_frame(box, "Runtime (msec)"); |
| 669 | label_set_int_value(label, ts->runtime[ddir]); |
| 670 | |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 671 | if (calc_lat(&ts->bw_stat[ddir], &min[0], &max[0], &mean[0], &dev[0])) { |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 672 | double p_of_agg = 100.0; |
| 673 | const char *bw_str = "KB"; |
| 674 | char tmp[32]; |
| 675 | |
| 676 | if (rs->agg[ddir]) { |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 677 | p_of_agg = mean[0] * 100 / (double) rs->agg[ddir]; |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 678 | if (p_of_agg > 100.0) |
| 679 | p_of_agg = 100.0; |
| 680 | } |
| 681 | |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 682 | if (mean[0] > 999999.9) { |
| 683 | min[0] /= 1000.0; |
| 684 | max[0] /= 1000.0; |
| 685 | mean[0] /= 1000.0; |
| 686 | dev[0] /= 1000.0; |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 687 | bw_str = "MB"; |
| 688 | } |
| 689 | |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 690 | sprintf(tmp, "Bandwidth (%s)", bw_str); |
| 691 | frame = gtk_frame_new(tmp); |
| 692 | gtk_box_pack_start(GTK_BOX(main_vbox), frame, FALSE, FALSE, 5); |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 693 | |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 694 | box = gtk_hbox_new(FALSE, 3); |
| 695 | gtk_container_add(GTK_CONTAINER(frame), box); |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 696 | |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 697 | label = new_info_label_in_frame(box, "Minimum"); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 698 | label_set_int_value(label, min[0]); |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 699 | label = new_info_label_in_frame(box, "Maximum"); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 700 | label_set_int_value(label, max[0]); |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 701 | label = new_info_label_in_frame(box, "Percentage of jobs"); |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 702 | sprintf(tmp, "%3.2f%%", p_of_agg); |
| 703 | gtk_label_set_text(GTK_LABEL(label), tmp); |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 704 | label = new_info_label_in_frame(box, "Average"); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 705 | sprintf(tmp, "%5.02f", mean[0]); |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 706 | gtk_label_set_text(GTK_LABEL(label), tmp); |
Jens Axboe | 0b76130 | 2012-03-05 20:44:11 +0100 | [diff] [blame] | 707 | label = new_info_label_in_frame(box, "Standard deviation"); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 708 | sprintf(tmp, "%5.02f", dev[0]); |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 709 | gtk_label_set_text(GTK_LABEL(label), tmp); |
| 710 | } |
| 711 | |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 712 | if (calc_lat(&ts->slat_stat[ddir], &min[0], &max[0], &mean[0], &dev[0])) |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 713 | flags |= GFIO_SLAT; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 714 | if (calc_lat(&ts->clat_stat[ddir], &min[1], &max[1], &mean[1], &dev[1])) |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 715 | flags |= GFIO_CLAT; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 716 | if (calc_lat(&ts->lat_stat[ddir], &min[2], &max[2], &mean[2], &dev[2])) |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 717 | flags |= GFIO_LAT; |
| 718 | |
| 719 | if (flags) { |
| 720 | frame = gtk_frame_new("Latency"); |
| 721 | gtk_box_pack_start(GTK_BOX(main_vbox), frame, FALSE, FALSE, 5); |
| 722 | |
| 723 | vbox = gtk_vbox_new(FALSE, 3); |
| 724 | gtk_container_add(GTK_CONTAINER(frame), vbox); |
| 725 | |
| 726 | if (flags & GFIO_SLAT) |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 727 | gfio_show_lat(vbox, "Submission latency", min[0], max[0], mean[0], dev[0]); |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 728 | if (flags & GFIO_CLAT) |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 729 | gfio_show_lat(vbox, "Completion latency", min[1], max[1], mean[1], dev[1]); |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 730 | if (flags & GFIO_LAT) |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 731 | gfio_show_lat(vbox, "Total latency", min[2], max[2], mean[2], dev[2]); |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 732 | } |
| 733 | |
| 734 | if (ts->clat_percentiles) |
Stephen M. Cameron | c57f254 | 2012-03-15 08:10:40 +0100 | [diff] [blame] | 735 | gfio_show_clat_percentiles(gc, main_vbox, ts, ddir); |
Jens Axboe | 2b08989 | 2012-03-06 08:09:17 +0100 | [diff] [blame] | 736 | |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 737 | free(io_p); |
| 738 | free(bw_p); |
| 739 | free(iops_p); |
| 740 | } |
| 741 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 742 | static struct graph *setup_lat_bucket_graph(const char *title, double *lat, |
| 743 | const char **labels, |
| 744 | unsigned int len, |
| 745 | double xdim, double ydim) |
| 746 | { |
| 747 | struct graph *g; |
| 748 | int i; |
| 749 | |
| 750 | g = graph_new(xdim, ydim, gfio_graph_font); |
| 751 | graph_title(g, title); |
| 752 | graph_x_title(g, "Buckets"); |
| 753 | |
| 754 | for (i = 0; i < len; i++) { |
| 755 | graph_add_label(g, labels[i]); |
| 756 | graph_add_data(g, labels[i], lat[i]); |
| 757 | } |
| 758 | |
| 759 | return g; |
| 760 | } |
| 761 | |
| 762 | static GtkWidget *gfio_output_lat_buckets(double *lat, const char **labels, |
| 763 | int num) |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 764 | { |
| 765 | GtkWidget *tree_view; |
| 766 | GtkTreeSelection *selection; |
| 767 | GtkListStore *model; |
| 768 | GtkTreeIter iter; |
| 769 | GType *types; |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 770 | int i; |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 771 | |
| 772 | types = malloc(num * sizeof(GType)); |
| 773 | |
| 774 | for (i = 0; i < num; i++) |
| 775 | types[i] = G_TYPE_STRING; |
| 776 | |
| 777 | model = gtk_list_store_newv(num, types); |
| 778 | free(types); |
| 779 | types = NULL; |
| 780 | |
| 781 | tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); |
| 782 | gtk_widget_set_can_focus(tree_view, FALSE); |
| 783 | |
Jens Axboe | 661f741 | 2012-03-06 13:55:45 +0100 | [diff] [blame] | 784 | g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE, |
| 785 | "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL); |
| 786 | |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 787 | selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)); |
| 788 | gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE); |
| 789 | |
| 790 | for (i = 0; i < num; i++) |
| 791 | tree_view_column(tree_view, i, labels[i], ALIGN_RIGHT | UNSORTABLE); |
| 792 | |
| 793 | gtk_list_store_append(model, &iter); |
| 794 | |
| 795 | for (i = 0; i < num; i++) { |
| 796 | char fbuf[32]; |
| 797 | |
| 798 | if (lat[i] <= 0.0) |
| 799 | sprintf(fbuf, "0.00"); |
| 800 | else |
| 801 | sprintf(fbuf, "%3.2f%%", lat[i]); |
| 802 | |
| 803 | gtk_list_store_set(model, &iter, i, fbuf, -1); |
| 804 | } |
| 805 | |
| 806 | return tree_view; |
| 807 | } |
| 808 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 809 | static void gfio_show_latency_buckets(struct gfio_client *gc, GtkWidget *vbox, |
| 810 | struct thread_stat *ts) |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 811 | { |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 812 | double io_u_lat[FIO_IO_U_LAT_U_NR + FIO_IO_U_LAT_M_NR]; |
| 813 | const char *ranges[] = { "2u", "4u", "10u", "20u", "50u", "100u", |
| 814 | "250u", "500u", "750u", "1m", "2m", |
| 815 | "4m", "10m", "20m", "50m", "100m", |
| 816 | "250m", "500m", "750m", "1s", "2s", ">= 2s" }; |
| 817 | int start, end, i; |
| 818 | const int total = FIO_IO_U_LAT_U_NR + FIO_IO_U_LAT_M_NR; |
| 819 | GtkWidget *frame, *tree_view, *hbox, *completion_vbox, *drawing_area; |
| 820 | struct gui_entry *ge = gc->ge; |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 821 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 822 | stat_calc_lat_u(ts, io_u_lat); |
| 823 | stat_calc_lat_m(ts, &io_u_lat[FIO_IO_U_LAT_U_NR]); |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 824 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 825 | /* |
| 826 | * Found out which first bucket has entries, and which last bucket |
| 827 | */ |
| 828 | start = end = -1U; |
| 829 | for (i = 0; i < total; i++) { |
| 830 | if (io_u_lat[i] == 0.00) |
| 831 | continue; |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 832 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 833 | if (start == -1U) |
| 834 | start = i; |
| 835 | end = i; |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 836 | } |
| 837 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 838 | /* |
| 839 | * No entries... |
| 840 | */ |
| 841 | if (start == -1U) |
| 842 | return; |
| 843 | |
| 844 | tree_view = gfio_output_lat_buckets(&io_u_lat[start], &ranges[start], end - start + 1); |
| 845 | ge->lat_bucket_graph = setup_lat_bucket_graph("Latency Buckets", &io_u_lat[start], &ranges[start], end - start + 1, 700.0, 300.0); |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 846 | |
Jens Axboe | 09d574e | 2012-03-15 10:45:48 +0100 | [diff] [blame] | 847 | frame = gtk_frame_new("Latency buckets"); |
| 848 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 849 | |
| 850 | completion_vbox = gtk_vbox_new(FALSE, 3); |
| 851 | gtk_container_add(GTK_CONTAINER(frame), completion_vbox); |
| 852 | hbox = gtk_hbox_new(FALSE, 3); |
| 853 | gtk_container_add(GTK_CONTAINER(completion_vbox), hbox); |
| 854 | |
| 855 | drawing_area = gtk_drawing_area_new(); |
| 856 | gtk_widget_set_size_request(GTK_WIDGET(drawing_area), 700, 300); |
| 857 | gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &white); |
| 858 | gtk_container_add(GTK_CONTAINER(completion_vbox), drawing_area); |
| 859 | g_signal_connect(G_OBJECT(drawing_area), "expose_event", G_CALLBACK(on_expose_lat_drawing_area), ge->lat_bucket_graph); |
| 860 | g_signal_connect(G_OBJECT(drawing_area), "configure_event", G_CALLBACK(on_config_lat_drawing_area), ge->lat_bucket_graph); |
| 861 | |
| 862 | gtk_box_pack_start(GTK_BOX(hbox), tree_view, TRUE, FALSE, 3); |
Jens Axboe | e5bd134 | 2012-03-05 21:38:12 +0100 | [diff] [blame] | 863 | } |
| 864 | |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 865 | static void gfio_show_cpu_usage(GtkWidget *vbox, struct thread_stat *ts) |
| 866 | { |
| 867 | GtkWidget *box, *frame, *entry; |
| 868 | double usr_cpu, sys_cpu; |
| 869 | unsigned long runtime; |
| 870 | char tmp[32]; |
| 871 | |
| 872 | runtime = ts->total_run_time; |
| 873 | if (runtime) { |
| 874 | double runt = (double) runtime; |
| 875 | |
| 876 | usr_cpu = (double) ts->usr_time * 100 / runt; |
| 877 | sys_cpu = (double) ts->sys_time * 100 / runt; |
| 878 | } else { |
| 879 | usr_cpu = 0; |
| 880 | sys_cpu = 0; |
| 881 | } |
| 882 | |
| 883 | frame = gtk_frame_new("OS resources"); |
| 884 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 885 | |
| 886 | box = gtk_hbox_new(FALSE, 3); |
| 887 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 888 | |
| 889 | entry = new_info_entry_in_frame(box, "User CPU"); |
| 890 | sprintf(tmp, "%3.2f%%", usr_cpu); |
| 891 | gtk_entry_set_text(GTK_ENTRY(entry), tmp); |
| 892 | entry = new_info_entry_in_frame(box, "System CPU"); |
| 893 | sprintf(tmp, "%3.2f%%", sys_cpu); |
| 894 | gtk_entry_set_text(GTK_ENTRY(entry), tmp); |
| 895 | entry = new_info_entry_in_frame(box, "Context switches"); |
| 896 | entry_set_int_value(entry, ts->ctx); |
| 897 | entry = new_info_entry_in_frame(box, "Major faults"); |
| 898 | entry_set_int_value(entry, ts->majf); |
| 899 | entry = new_info_entry_in_frame(box, "Minor faults"); |
| 900 | entry_set_int_value(entry, ts->minf); |
| 901 | } |
Jens Axboe | 19998db | 2012-03-06 09:17:59 +0100 | [diff] [blame] | 902 | static void gfio_add_sc_depths_tree(GtkListStore *model, |
| 903 | struct thread_stat *ts, unsigned int len, |
| 904 | int submit) |
| 905 | { |
| 906 | double io_u_dist[FIO_IO_U_MAP_NR]; |
| 907 | GtkTreeIter iter; |
| 908 | /* Bits 0, and 3-8 */ |
| 909 | const int add_mask = 0x1f9; |
| 910 | int i, j; |
| 911 | |
| 912 | if (submit) |
| 913 | stat_calc_dist(ts->io_u_submit, ts->total_submit, io_u_dist); |
| 914 | else |
| 915 | stat_calc_dist(ts->io_u_complete, ts->total_complete, io_u_dist); |
| 916 | |
| 917 | gtk_list_store_append(model, &iter); |
| 918 | |
| 919 | gtk_list_store_set(model, &iter, 0, submit ? "Submit" : "Complete", -1); |
| 920 | |
| 921 | for (i = 1, j = 0; i < len; i++) { |
| 922 | char fbuf[32]; |
| 923 | |
| 924 | if (!(add_mask & (1UL << (i - 1)))) |
| 925 | sprintf(fbuf, "0.0%%"); |
| 926 | else { |
| 927 | sprintf(fbuf, "%3.1f%%", io_u_dist[j]); |
| 928 | j++; |
| 929 | } |
| 930 | |
| 931 | gtk_list_store_set(model, &iter, i, fbuf, -1); |
| 932 | } |
| 933 | |
| 934 | } |
| 935 | |
| 936 | static void gfio_add_total_depths_tree(GtkListStore *model, |
| 937 | struct thread_stat *ts, unsigned int len) |
| 938 | { |
| 939 | double io_u_dist[FIO_IO_U_MAP_NR]; |
| 940 | GtkTreeIter iter; |
| 941 | /* Bits 1-6, and 8 */ |
| 942 | const int add_mask = 0x17e; |
| 943 | int i, j; |
| 944 | |
| 945 | stat_calc_dist(ts->io_u_map, ts_total_io_u(ts), io_u_dist); |
| 946 | |
| 947 | gtk_list_store_append(model, &iter); |
| 948 | |
| 949 | gtk_list_store_set(model, &iter, 0, "Total", -1); |
| 950 | |
| 951 | for (i = 1, j = 0; i < len; i++) { |
| 952 | char fbuf[32]; |
| 953 | |
| 954 | if (!(add_mask & (1UL << (i - 1)))) |
| 955 | sprintf(fbuf, "0.0%%"); |
| 956 | else { |
| 957 | sprintf(fbuf, "%3.1f%%", io_u_dist[j]); |
| 958 | j++; |
| 959 | } |
| 960 | |
| 961 | gtk_list_store_set(model, &iter, i, fbuf, -1); |
| 962 | } |
| 963 | |
| 964 | } |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 965 | |
| 966 | static void gfio_show_io_depths(GtkWidget *vbox, struct thread_stat *ts) |
| 967 | { |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 968 | GtkWidget *frame, *box, *tree_view; |
| 969 | GtkTreeSelection *selection; |
| 970 | GtkListStore *model; |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 971 | GType types[FIO_IO_U_MAP_NR + 1]; |
| 972 | int i; |
Jens Axboe | 19998db | 2012-03-06 09:17:59 +0100 | [diff] [blame] | 973 | #define NR_LABELS 10 |
| 974 | const char *labels[NR_LABELS] = { "Depth", "0", "1", "2", "4", "8", "16", "32", "64", ">= 64" }; |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 975 | |
| 976 | frame = gtk_frame_new("IO depths"); |
| 977 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 978 | |
| 979 | box = gtk_hbox_new(FALSE, 3); |
| 980 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 981 | |
Jens Axboe | 19998db | 2012-03-06 09:17:59 +0100 | [diff] [blame] | 982 | for (i = 0; i < NR_LABELS; i++) |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 983 | types[i] = G_TYPE_STRING; |
| 984 | |
Jens Axboe | 19998db | 2012-03-06 09:17:59 +0100 | [diff] [blame] | 985 | model = gtk_list_store_newv(NR_LABELS, types); |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 986 | |
| 987 | tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); |
| 988 | gtk_widget_set_can_focus(tree_view, FALSE); |
| 989 | |
Jens Axboe | 661f741 | 2012-03-06 13:55:45 +0100 | [diff] [blame] | 990 | g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE, |
| 991 | "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL); |
| 992 | |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 993 | selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)); |
| 994 | gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE); |
| 995 | |
Jens Axboe | 19998db | 2012-03-06 09:17:59 +0100 | [diff] [blame] | 996 | for (i = 0; i < NR_LABELS; i++) |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 997 | tree_view_column(tree_view, i, labels[i], ALIGN_RIGHT | UNSORTABLE); |
| 998 | |
Jens Axboe | 19998db | 2012-03-06 09:17:59 +0100 | [diff] [blame] | 999 | gfio_add_total_depths_tree(model, ts, NR_LABELS); |
| 1000 | gfio_add_sc_depths_tree(model, ts, NR_LABELS, 1); |
| 1001 | gfio_add_sc_depths_tree(model, ts, NR_LABELS, 0); |
Jens Axboe | 2e33101 | 2012-03-05 22:07:54 +0100 | [diff] [blame] | 1002 | |
| 1003 | gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 3); |
| 1004 | } |
| 1005 | |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1006 | static gboolean results_window_delete(GtkWidget *w, gpointer data) |
| 1007 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1008 | struct gui_entry *ge = (struct gui_entry *) data; |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1009 | |
| 1010 | gtk_widget_destroy(w); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1011 | ge->results_window = NULL; |
| 1012 | ge->results_notebook = NULL; |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1013 | return TRUE; |
| 1014 | } |
| 1015 | |
Jens Axboe | 17b9721 | 2012-03-14 20:17:57 +0100 | [diff] [blame] | 1016 | static void results_close(GtkWidget *w, gpointer *data) |
| 1017 | { |
| 1018 | struct gui_entry *ge = (struct gui_entry *) data; |
| 1019 | |
| 1020 | gtk_widget_destroy(ge->results_window); |
| 1021 | } |
| 1022 | |
| 1023 | static GtkActionEntry results_menu_items[] = { |
| 1024 | { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL}, |
| 1025 | { "GraphMenuAction", GTK_STOCK_FILE, "Graph", NULL, NULL, NULL}, |
| 1026 | { "CloseFile", GTK_STOCK_CLOSE, "Close", "<Control>W", NULL, G_CALLBACK(results_close) }, |
| 1027 | }; |
| 1028 | static gint results_nmenu_items = sizeof(results_menu_items) / sizeof(results_menu_items[0]); |
| 1029 | |
| 1030 | static const gchar *results_ui_string = " \ |
| 1031 | <ui> \ |
| 1032 | <menubar name=\"MainMenu\"> \ |
| 1033 | <menu name=\"FileMenu\" action=\"FileMenuAction\"> \ |
| 1034 | <menuitem name=\"Close\" action=\"CloseFile\" /> \ |
| 1035 | </menu> \ |
| 1036 | <menu name=\"GraphMenu\" action=\"GraphMenuAction\"> \ |
| 1037 | </menu>\ |
| 1038 | </menubar> \ |
| 1039 | </ui> \ |
| 1040 | "; |
| 1041 | |
| 1042 | static GtkWidget *get_results_menubar(GtkWidget *window, struct gui_entry *ge) |
| 1043 | { |
| 1044 | GtkActionGroup *action_group; |
| 1045 | GtkWidget *widget; |
| 1046 | GError *error = 0; |
| 1047 | |
| 1048 | ge->results_uimanager = gtk_ui_manager_new(); |
| 1049 | |
| 1050 | action_group = gtk_action_group_new("ResultsMenu"); |
| 1051 | gtk_action_group_add_actions(action_group, results_menu_items, results_nmenu_items, ge); |
| 1052 | |
| 1053 | gtk_ui_manager_insert_action_group(ge->results_uimanager, action_group, 0); |
| 1054 | gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ge->results_uimanager), results_ui_string, -1, &error); |
| 1055 | |
| 1056 | gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ge->results_uimanager)); |
| 1057 | |
| 1058 | widget = gtk_ui_manager_get_widget(ge->results_uimanager, "/MainMenu"); |
| 1059 | return widget; |
| 1060 | } |
| 1061 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1062 | static GtkWidget *get_results_window(struct gui_entry *ge) |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1063 | { |
Jens Axboe | 17b9721 | 2012-03-14 20:17:57 +0100 | [diff] [blame] | 1064 | GtkWidget *win, *notebook, *vbox; |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1065 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1066 | if (ge->results_window) |
| 1067 | return ge->results_notebook; |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1068 | |
| 1069 | win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 1070 | gtk_window_set_title(GTK_WINDOW(win), "Results"); |
Jens Axboe | b01329d | 2012-03-07 20:31:28 +0100 | [diff] [blame] | 1071 | gtk_window_set_default_size(GTK_WINDOW(win), 1024, 768); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1072 | g_signal_connect(win, "delete-event", G_CALLBACK(results_window_delete), ge); |
| 1073 | g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ge); |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1074 | |
Jens Axboe | 17b9721 | 2012-03-14 20:17:57 +0100 | [diff] [blame] | 1075 | vbox = gtk_vbox_new(FALSE, 0); |
| 1076 | gtk_container_add(GTK_CONTAINER(win), vbox); |
| 1077 | |
| 1078 | ge->results_menu = get_results_menubar(win, ge); |
| 1079 | gtk_box_pack_start(GTK_BOX(vbox), ge->results_menu, FALSE, FALSE, 0); |
| 1080 | |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1081 | notebook = gtk_notebook_new(); |
Jens Axboe | 0aa928c | 2012-03-09 17:24:07 +0100 | [diff] [blame] | 1082 | gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), 1); |
| 1083 | gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook)); |
Jens Axboe | 17b9721 | 2012-03-14 20:17:57 +0100 | [diff] [blame] | 1084 | gtk_container_add(GTK_CONTAINER(vbox), notebook); |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1085 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1086 | ge->results_window = win; |
| 1087 | ge->results_notebook = notebook; |
| 1088 | return ge->results_notebook; |
Jens Axboe | f9d40b4 | 2012-03-06 09:52:49 +0100 | [diff] [blame] | 1089 | } |
| 1090 | |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1091 | static void disk_util_destroy(GtkWidget *w, gpointer data) |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 1092 | { |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1093 | struct gui_entry *ge = (struct gui_entry *) data; |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 1094 | |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1095 | ge->disk_util_vbox = NULL; |
| 1096 | gtk_widget_destroy(w); |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 1097 | } |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 1098 | |
Jens Axboe | f0602d7 | 2012-03-15 15:38:02 +0100 | [diff] [blame] | 1099 | static GtkWidget *get_scrolled_window(gint border_width) |
| 1100 | { |
| 1101 | GtkWidget *scroll; |
| 1102 | |
| 1103 | scroll = gtk_scrolled_window_new(NULL, NULL); |
| 1104 | gtk_container_set_border_width(GTK_CONTAINER(scroll), border_width); |
| 1105 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
| 1106 | |
| 1107 | return scroll; |
| 1108 | } |
| 1109 | |
| 1110 | static GtkWidget *gfio_disk_util_get_vbox(struct gui_entry *ge) |
| 1111 | { |
| 1112 | GtkWidget *vbox, *box, *scroll, *res_notebook; |
| 1113 | |
| 1114 | if (ge->disk_util_vbox) |
| 1115 | return ge->disk_util_vbox; |
| 1116 | |
| 1117 | scroll = get_scrolled_window(5); |
| 1118 | vbox = gtk_vbox_new(FALSE, 3); |
| 1119 | box = gtk_hbox_new(FALSE, 0); |
| 1120 | gtk_box_pack_start(GTK_BOX(vbox), box, TRUE, FALSE, 5); |
| 1121 | |
| 1122 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox); |
| 1123 | res_notebook = get_results_window(ge); |
| 1124 | |
| 1125 | gtk_notebook_append_page(GTK_NOTEBOOK(res_notebook), scroll, gtk_label_new("Disk utilization")); |
| 1126 | ge->disk_util_vbox = box; |
| 1127 | g_signal_connect(vbox, "destroy", G_CALLBACK(disk_util_destroy), ge); |
| 1128 | |
| 1129 | return ge->disk_util_vbox; |
| 1130 | } |
| 1131 | |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1132 | static int __gfio_disk_util_show(GtkWidget *res_notebook, |
| 1133 | struct gfio_client *gc, struct cmd_du_pdu *p) |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 1134 | { |
Jens Axboe | f0602d7 | 2012-03-15 15:38:02 +0100 | [diff] [blame] | 1135 | GtkWidget *box, *frame, *entry, *vbox, *util_vbox; |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1136 | struct gui_entry *ge = gc->ge; |
Jens Axboe | 604cfe3 | 2012-03-07 19:51:36 +0100 | [diff] [blame] | 1137 | double util; |
| 1138 | char tmp[16]; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 1139 | |
Jens Axboe | f0602d7 | 2012-03-15 15:38:02 +0100 | [diff] [blame] | 1140 | util_vbox = gfio_disk_util_get_vbox(ge); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 1141 | |
| 1142 | vbox = gtk_vbox_new(FALSE, 3); |
Jens Axboe | f0602d7 | 2012-03-15 15:38:02 +0100 | [diff] [blame] | 1143 | gtk_container_add(GTK_CONTAINER(util_vbox), vbox); |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 1144 | |
| 1145 | frame = gtk_frame_new((char *) p->dus.name); |
| 1146 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 2); |
| 1147 | |
| 1148 | box = gtk_vbox_new(FALSE, 3); |
| 1149 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 1150 | |
| 1151 | frame = gtk_frame_new("Read"); |
| 1152 | gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2); |
| 1153 | vbox = gtk_hbox_new(TRUE, 3); |
| 1154 | gtk_container_add(GTK_CONTAINER(frame), vbox); |
| 1155 | entry = new_info_entry_in_frame(vbox, "IOs"); |
| 1156 | entry_set_int_value(entry, p->dus.ios[0]); |
| 1157 | entry = new_info_entry_in_frame(vbox, "Merges"); |
| 1158 | entry_set_int_value(entry, p->dus.merges[0]); |
| 1159 | entry = new_info_entry_in_frame(vbox, "Sectors"); |
| 1160 | entry_set_int_value(entry, p->dus.sectors[0]); |
| 1161 | entry = new_info_entry_in_frame(vbox, "Ticks"); |
| 1162 | entry_set_int_value(entry, p->dus.ticks[0]); |
| 1163 | |
| 1164 | frame = gtk_frame_new("Write"); |
| 1165 | gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2); |
| 1166 | vbox = gtk_hbox_new(TRUE, 3); |
| 1167 | gtk_container_add(GTK_CONTAINER(frame), vbox); |
| 1168 | entry = new_info_entry_in_frame(vbox, "IOs"); |
| 1169 | entry_set_int_value(entry, p->dus.ios[1]); |
| 1170 | entry = new_info_entry_in_frame(vbox, "Merges"); |
| 1171 | entry_set_int_value(entry, p->dus.merges[1]); |
| 1172 | entry = new_info_entry_in_frame(vbox, "Sectors"); |
| 1173 | entry_set_int_value(entry, p->dus.sectors[1]); |
| 1174 | entry = new_info_entry_in_frame(vbox, "Ticks"); |
| 1175 | entry_set_int_value(entry, p->dus.ticks[1]); |
| 1176 | |
| 1177 | frame = gtk_frame_new("Shared"); |
| 1178 | gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2); |
| 1179 | vbox = gtk_hbox_new(TRUE, 3); |
| 1180 | gtk_container_add(GTK_CONTAINER(frame), vbox); |
| 1181 | entry = new_info_entry_in_frame(vbox, "IO ticks"); |
| 1182 | entry_set_int_value(entry, p->dus.io_ticks); |
| 1183 | entry = new_info_entry_in_frame(vbox, "Time in queue"); |
| 1184 | entry_set_int_value(entry, p->dus.time_in_queue); |
| 1185 | |
Jens Axboe | 604cfe3 | 2012-03-07 19:51:36 +0100 | [diff] [blame] | 1186 | util = 0.0; |
| 1187 | if (p->dus.msec) |
| 1188 | util = (double) 100 * p->dus.io_ticks / (double) p->dus.msec; |
| 1189 | if (util > 100.0) |
| 1190 | util = 100.0; |
| 1191 | |
| 1192 | sprintf(tmp, "%3.2f%%", util); |
| 1193 | entry = new_info_entry_in_frame(vbox, "Disk utilization"); |
| 1194 | gtk_entry_set_text(GTK_ENTRY(entry), tmp); |
| 1195 | |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1196 | gtk_widget_show_all(ge->results_window); |
| 1197 | return 0; |
| 1198 | } |
| 1199 | |
| 1200 | static int gfio_disk_util_show(struct gfio_client *gc) |
| 1201 | { |
| 1202 | struct gui_entry *ge = gc->ge; |
| 1203 | GtkWidget *res_notebook; |
| 1204 | int i; |
| 1205 | |
| 1206 | if (!gc->nr_du) |
| 1207 | return 1; |
| 1208 | |
| 1209 | res_notebook = get_results_window(ge); |
| 1210 | |
| 1211 | for (i = 0; i < gc->nr_du; i++) { |
| 1212 | struct cmd_du_pdu *p = &gc->du[i]; |
| 1213 | |
| 1214 | __gfio_disk_util_show(res_notebook, gc, p); |
| 1215 | } |
| 1216 | |
| 1217 | gtk_widget_show_all(ge->results_window); |
| 1218 | return 0; |
| 1219 | } |
| 1220 | |
| 1221 | static void gfio_add_end_results(struct gfio_client *gc, struct thread_stat *ts, |
| 1222 | struct group_run_stats *rs) |
| 1223 | { |
| 1224 | unsigned int nr = gc->nr_results; |
| 1225 | |
| 1226 | gc->results = realloc(gc->results, (nr + 1) * sizeof(struct end_results)); |
| 1227 | memcpy(&gc->results[nr].ts, ts, sizeof(*ts)); |
| 1228 | memcpy(&gc->results[nr].gs, rs, sizeof(*rs)); |
| 1229 | gc->nr_results++; |
| 1230 | } |
| 1231 | |
| 1232 | static void __gfio_display_end_results(GtkWidget *win, struct gfio_client *gc, |
| 1233 | struct thread_stat *ts, |
| 1234 | struct group_run_stats *rs) |
| 1235 | { |
| 1236 | GtkWidget *box, *vbox, *entry, *scroll; |
| 1237 | |
| 1238 | scroll = gtk_scrolled_window_new(NULL, NULL); |
| 1239 | gtk_container_set_border_width(GTK_CONTAINER(scroll), 5); |
| 1240 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
| 1241 | |
| 1242 | vbox = gtk_vbox_new(FALSE, 3); |
| 1243 | |
| 1244 | box = gtk_hbox_new(FALSE, 0); |
| 1245 | gtk_box_pack_start(GTK_BOX(vbox), box, TRUE, FALSE, 5); |
| 1246 | |
| 1247 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox); |
| 1248 | |
| 1249 | gtk_notebook_append_page(GTK_NOTEBOOK(win), scroll, gtk_label_new(ts->name)); |
| 1250 | |
| 1251 | entry = new_info_entry_in_frame(box, "Name"); |
| 1252 | gtk_entry_set_text(GTK_ENTRY(entry), ts->name); |
| 1253 | if (strlen(ts->description)) { |
| 1254 | entry = new_info_entry_in_frame(box, "Description"); |
| 1255 | gtk_entry_set_text(GTK_ENTRY(entry), ts->description); |
| 1256 | } |
| 1257 | entry = new_info_entry_in_frame(box, "Group ID"); |
| 1258 | entry_set_int_value(entry, ts->groupid); |
| 1259 | entry = new_info_entry_in_frame(box, "Jobs"); |
| 1260 | entry_set_int_value(entry, ts->members); |
| 1261 | gc->err_entry = entry = new_info_entry_in_frame(box, "Error"); |
| 1262 | entry_set_int_value(entry, ts->error); |
| 1263 | entry = new_info_entry_in_frame(box, "PID"); |
| 1264 | entry_set_int_value(entry, ts->pid); |
| 1265 | |
| 1266 | if (ts->io_bytes[DDIR_READ]) |
| 1267 | gfio_show_ddir_status(gc, vbox, rs, ts, DDIR_READ); |
| 1268 | if (ts->io_bytes[DDIR_WRITE]) |
| 1269 | gfio_show_ddir_status(gc, vbox, rs, ts, DDIR_WRITE); |
| 1270 | |
| 1271 | gfio_show_latency_buckets(gc, vbox, ts); |
| 1272 | gfio_show_cpu_usage(vbox, ts); |
| 1273 | gfio_show_io_depths(vbox, ts); |
| 1274 | } |
| 1275 | |
| 1276 | static void gfio_display_end_results(struct gfio_client *gc) |
| 1277 | { |
| 1278 | struct gui_entry *ge = gc->ge; |
| 1279 | GtkWidget *res_notebook; |
| 1280 | int i; |
| 1281 | |
| 1282 | res_notebook = get_results_window(ge); |
| 1283 | |
| 1284 | for (i = 0; i < gc->nr_results; i++) { |
| 1285 | struct end_results *e = &gc->results[i]; |
| 1286 | |
| 1287 | __gfio_display_end_results(res_notebook, gc, &e->ts, &e->gs); |
| 1288 | } |
| 1289 | |
| 1290 | if (gfio_disk_util_show(gc)) |
| 1291 | gtk_widget_show_all(ge->results_window); |
| 1292 | } |
| 1293 | |
| 1294 | static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts, |
| 1295 | struct group_run_stats *rs) |
| 1296 | { |
| 1297 | struct gfio_client *gc = client->client_data; |
Jens Axboe | 0ed83bc | 2012-03-15 14:36:39 +0100 | [diff] [blame] | 1298 | struct gui_entry *ge = gc->ge; |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1299 | |
| 1300 | gfio_add_end_results(gc, ts, rs); |
| 1301 | |
| 1302 | gdk_threads_enter(); |
Jens Axboe | 0ed83bc | 2012-03-15 14:36:39 +0100 | [diff] [blame] | 1303 | if (ge->results_window) |
| 1304 | __gfio_display_end_results(ge->results_notebook, gc, ts, rs); |
| 1305 | else |
| 1306 | gfio_display_end_results(gc); |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1307 | gdk_threads_leave(); |
| 1308 | } |
| 1309 | |
| 1310 | static void gfio_text_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1311 | { |
| 1312 | struct cmd_text_pdu *p = (struct cmd_text_pdu *) cmd->payload; |
| 1313 | struct gui *ui = &main_ui; |
| 1314 | GtkTreeIter iter; |
| 1315 | struct tm *tm; |
| 1316 | time_t sec; |
| 1317 | char tmp[64], timebuf[80]; |
| 1318 | |
| 1319 | sec = p->log_sec; |
| 1320 | tm = localtime(&sec); |
| 1321 | strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", tm); |
| 1322 | sprintf(timebuf, "%s.%03ld", tmp, p->log_usec / 1000); |
| 1323 | |
| 1324 | gdk_threads_enter(); |
| 1325 | |
| 1326 | gtk_list_store_append(ui->log_model, &iter); |
| 1327 | gtk_list_store_set(ui->log_model, &iter, 0, timebuf, -1); |
| 1328 | gtk_list_store_set(ui->log_model, &iter, 1, client->hostname, -1); |
| 1329 | gtk_list_store_set(ui->log_model, &iter, 2, p->level, -1); |
| 1330 | gtk_list_store_set(ui->log_model, &iter, 3, p->buf, -1); |
| 1331 | |
| 1332 | if (p->level == FIO_LOG_ERR) |
| 1333 | view_log(NULL, (gpointer) ui); |
| 1334 | |
| 1335 | gdk_threads_leave(); |
| 1336 | } |
| 1337 | |
| 1338 | static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1339 | { |
| 1340 | struct cmd_du_pdu *p = (struct cmd_du_pdu *) cmd->payload; |
| 1341 | struct gfio_client *gc = client->client_data; |
Jens Axboe | 0ed83bc | 2012-03-15 14:36:39 +0100 | [diff] [blame] | 1342 | struct gui_entry *ge = gc->ge; |
Jens Axboe | 7da23b4 | 2012-03-15 13:45:02 +0100 | [diff] [blame] | 1343 | unsigned int nr = gc->nr_du; |
| 1344 | |
| 1345 | gc->du = realloc(gc->du, (nr + 1) * sizeof(struct cmd_du_pdu)); |
| 1346 | memcpy(&gc->du[nr], p, sizeof(*p)); |
| 1347 | gc->nr_du++; |
| 1348 | |
| 1349 | gdk_threads_enter(); |
Jens Axboe | 0ed83bc | 2012-03-15 14:36:39 +0100 | [diff] [blame] | 1350 | if (ge->results_window) |
| 1351 | __gfio_disk_util_show(ge->results_notebook, gc, p); |
| 1352 | else |
| 1353 | gfio_disk_util_show(gc); |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1354 | gdk_threads_leave(); |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1355 | } |
| 1356 | |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 1357 | extern int sum_stat_clients; |
| 1358 | extern struct thread_stat client_ts; |
| 1359 | extern struct group_run_stats client_gs; |
| 1360 | |
| 1361 | static int sum_stat_nr; |
| 1362 | |
Jens Axboe | 89e5fad | 2012-03-05 09:21:12 +0100 | [diff] [blame] | 1363 | static void gfio_thread_status_op(struct fio_client *client, |
| 1364 | struct fio_net_cmd *cmd) |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1365 | { |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 1366 | struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload; |
| 1367 | |
| 1368 | gfio_display_ts(client, &p->ts, &p->rs); |
| 1369 | |
| 1370 | if (sum_stat_clients == 1) |
| 1371 | return; |
| 1372 | |
| 1373 | sum_thread_stats(&client_ts, &p->ts, sum_stat_nr); |
| 1374 | sum_group_stats(&client_gs, &p->rs); |
| 1375 | |
| 1376 | client_ts.members++; |
Jens Axboe | 2f122b1 | 2012-03-15 13:10:19 +0100 | [diff] [blame] | 1377 | client_ts.thread_number = p->ts.thread_number; |
Jens Axboe | 3650a3c | 2012-03-05 14:09:03 +0100 | [diff] [blame] | 1378 | client_ts.groupid = p->ts.groupid; |
| 1379 | |
| 1380 | if (++sum_stat_nr == sum_stat_clients) { |
| 1381 | strcpy(client_ts.name, "All clients"); |
| 1382 | gfio_display_ts(client, &client_ts, &client_gs); |
| 1383 | } |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1384 | } |
| 1385 | |
Jens Axboe | 89e5fad | 2012-03-05 09:21:12 +0100 | [diff] [blame] | 1386 | static void gfio_group_stats_op(struct fio_client *client, |
| 1387 | struct fio_net_cmd *cmd) |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1388 | { |
Jens Axboe | 98ceabd | 2012-03-09 08:53:28 +0100 | [diff] [blame] | 1389 | /* We're ignoring group stats for now */ |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1390 | } |
| 1391 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1392 | static gint on_config_drawing_area(GtkWidget *w, GdkEventConfigure *event, |
| 1393 | gpointer data) |
Stephen M. Cameron | 3ea48b8 | 2012-03-07 19:40:58 +0100 | [diff] [blame] | 1394 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1395 | struct gfio_graphs *g = data; |
| 1396 | |
Stephen M. Cameron | 57f9d28 | 2012-03-11 11:36:51 +0100 | [diff] [blame] | 1397 | graph_set_size(g->iops_graph, w->allocation.width / 2.0, w->allocation.height); |
| 1398 | graph_set_position(g->iops_graph, w->allocation.width / 2.0, 0.0); |
| 1399 | graph_set_size(g->bandwidth_graph, w->allocation.width / 2.0, w->allocation.height); |
| 1400 | graph_set_position(g->bandwidth_graph, 0, 0); |
Stephen M. Cameron | 3ea48b8 | 2012-03-07 19:40:58 +0100 | [diff] [blame] | 1401 | return TRUE; |
| 1402 | } |
| 1403 | |
Stephen M. Cameron | 57f9d28 | 2012-03-11 11:36:51 +0100 | [diff] [blame] | 1404 | static void draw_graph(struct graph *g, cairo_t *cr) |
| 1405 | { |
| 1406 | line_graph_draw(g, cr); |
| 1407 | cairo_stroke(cr); |
| 1408 | } |
| 1409 | |
Jens Axboe | 93e2db2 | 2012-03-13 09:45:22 +0100 | [diff] [blame] | 1410 | static gboolean graph_tooltip(GtkWidget *w, gint x, gint y, |
| 1411 | gboolean keyboard_mode, GtkTooltip *tooltip, |
| 1412 | gpointer data) |
| 1413 | { |
| 1414 | struct gfio_graphs *g = data; |
| 1415 | const char *text = NULL; |
| 1416 | |
| 1417 | if (graph_contains_xy(g->iops_graph, x, y)) |
| 1418 | text = graph_find_tooltip(g->iops_graph, x, y); |
| 1419 | else if (graph_contains_xy(g->bandwidth_graph, x, y)) |
| 1420 | text = graph_find_tooltip(g->bandwidth_graph, x, y); |
| 1421 | |
| 1422 | if (text) { |
| 1423 | gtk_tooltip_set_text(tooltip, text); |
| 1424 | return TRUE; |
| 1425 | } |
| 1426 | |
| 1427 | return FALSE; |
| 1428 | } |
| 1429 | |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 1430 | static int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p) |
| 1431 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1432 | struct gfio_graphs *g = p; |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 1433 | cairo_t *cr; |
| 1434 | |
| 1435 | cr = gdk_cairo_create(w->window); |
Jens Axboe | 93e2db2 | 2012-03-13 09:45:22 +0100 | [diff] [blame] | 1436 | |
| 1437 | if (graph_has_tooltips(g->iops_graph) || |
| 1438 | graph_has_tooltips(g->bandwidth_graph)) { |
| 1439 | g_object_set(w, "has-tooltip", TRUE, NULL); |
| 1440 | g_signal_connect(w, "query-tooltip", G_CALLBACK(graph_tooltip), g); |
| 1441 | } |
| 1442 | |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 1443 | cairo_set_source_rgb(cr, 0, 0, 0); |
Stephen M. Cameron | 57f9d28 | 2012-03-11 11:36:51 +0100 | [diff] [blame] | 1444 | draw_graph(g->iops_graph, cr); |
| 1445 | draw_graph(g->bandwidth_graph, cr); |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 1446 | cairo_destroy(cr); |
| 1447 | |
| 1448 | return FALSE; |
| 1449 | } |
| 1450 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1451 | /* |
| 1452 | * Client specific ETA |
| 1453 | */ |
| 1454 | static void gfio_update_client_eta(struct fio_client *client, struct jobs_eta *je) |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1455 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1456 | struct gfio_client *gc = client->client_data; |
| 1457 | struct gui_entry *ge = gc->ge; |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1458 | static int eta_good; |
| 1459 | char eta_str[128]; |
| 1460 | char output[256]; |
| 1461 | char tmp[32]; |
| 1462 | double perc = 0.0; |
| 1463 | int i2p = 0; |
| 1464 | |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1465 | gdk_threads_enter(); |
| 1466 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1467 | eta_str[0] = '\0'; |
| 1468 | output[0] = '\0'; |
| 1469 | |
| 1470 | if (je->eta_sec != INT_MAX && je->elapsed_sec) { |
| 1471 | perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec); |
| 1472 | eta_to_str(eta_str, je->eta_sec); |
| 1473 | } |
| 1474 | |
| 1475 | sprintf(tmp, "%u", je->nr_running); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1476 | gtk_entry_set_text(GTK_ENTRY(ge->eta.jobs), tmp); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1477 | sprintf(tmp, "%u", je->files_open); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1478 | gtk_entry_set_text(GTK_ENTRY(ge->eta.files), tmp); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1479 | |
| 1480 | #if 0 |
| 1481 | if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) { |
| 1482 | if (je->m_rate || je->t_rate) { |
| 1483 | char *tr, *mr; |
| 1484 | |
| 1485 | mr = num2str(je->m_rate, 4, 0, i2p); |
| 1486 | tr = num2str(je->t_rate, 4, 0, i2p); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1487 | gtk_entry_set_text(GTK_ENTRY(ge->eta); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1488 | p += sprintf(p, ", CR=%s/%s KB/s", tr, mr); |
| 1489 | free(tr); |
| 1490 | free(mr); |
| 1491 | } else if (je->m_iops || je->t_iops) |
| 1492 | p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops); |
Jens Axboe | ebbd89c | 2012-03-02 11:21:13 +0100 | [diff] [blame] | 1493 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1494 | gtk_entry_set_text(GTK_ENTRY(ge->eta.cr_bw), "---"); |
| 1495 | gtk_entry_set_text(GTK_ENTRY(ge->eta.cr_iops), "---"); |
| 1496 | gtk_entry_set_text(GTK_ENTRY(ge->eta.cw_bw), "---"); |
| 1497 | gtk_entry_set_text(GTK_ENTRY(ge->eta.cw_iops), "---"); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1498 | #endif |
| 1499 | |
| 1500 | if (je->eta_sec != INT_MAX && je->nr_running) { |
| 1501 | char *iops_str[2]; |
| 1502 | char *rate_str[2]; |
| 1503 | |
| 1504 | if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running) |
| 1505 | strcpy(output, "-.-% done"); |
| 1506 | else { |
| 1507 | eta_good = 1; |
| 1508 | perc *= 100.0; |
| 1509 | sprintf(output, "%3.1f%% done", perc); |
| 1510 | } |
| 1511 | |
| 1512 | rate_str[0] = num2str(je->rate[0], 5, 10, i2p); |
| 1513 | rate_str[1] = num2str(je->rate[1], 5, 10, i2p); |
| 1514 | |
| 1515 | iops_str[0] = num2str(je->iops[0], 4, 1, 0); |
| 1516 | iops_str[1] = num2str(je->iops[1], 4, 1, 0); |
| 1517 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1518 | gtk_entry_set_text(GTK_ENTRY(ge->eta.read_bw), rate_str[0]); |
| 1519 | gtk_entry_set_text(GTK_ENTRY(ge->eta.read_iops), iops_str[0]); |
| 1520 | gtk_entry_set_text(GTK_ENTRY(ge->eta.write_bw), rate_str[1]); |
| 1521 | gtk_entry_set_text(GTK_ENTRY(ge->eta.write_iops), iops_str[1]); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1522 | |
Jens Axboe | 93e2db2 | 2012-03-13 09:45:22 +0100 | [diff] [blame] | 1523 | graph_add_xy_data(ge->graphs.iops_graph, "Read IOPS", je->elapsed_sec, je->iops[0], iops_str[0]); |
| 1524 | graph_add_xy_data(ge->graphs.iops_graph, "Write IOPS", je->elapsed_sec, je->iops[1], iops_str[1]); |
| 1525 | graph_add_xy_data(ge->graphs.bandwidth_graph, "Read Bandwidth", je->elapsed_sec, je->rate[0], rate_str[0]); |
| 1526 | graph_add_xy_data(ge->graphs.bandwidth_graph, "Write Bandwidth", je->elapsed_sec, je->rate[1], rate_str[1]); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1527 | |
| 1528 | free(rate_str[0]); |
| 1529 | free(rate_str[1]); |
| 1530 | free(iops_str[0]); |
| 1531 | free(iops_str[1]); |
| 1532 | } |
| 1533 | |
| 1534 | if (eta_str[0]) { |
| 1535 | char *dst = output + strlen(output); |
| 1536 | |
| 1537 | sprintf(dst, " - %s", eta_str); |
| 1538 | } |
| 1539 | |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 1540 | gfio_update_thread_status(ge, output, perc); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1541 | gdk_threads_leave(); |
| 1542 | } |
| 1543 | |
| 1544 | /* |
| 1545 | * Update ETA in main window for all clients |
| 1546 | */ |
| 1547 | static void gfio_update_all_eta(struct jobs_eta *je) |
| 1548 | { |
| 1549 | struct gui *ui = &main_ui; |
| 1550 | static int eta_good; |
| 1551 | char eta_str[128]; |
| 1552 | char output[256]; |
| 1553 | double perc = 0.0; |
| 1554 | int i2p = 0; |
| 1555 | |
| 1556 | gdk_threads_enter(); |
| 1557 | |
| 1558 | eta_str[0] = '\0'; |
| 1559 | output[0] = '\0'; |
| 1560 | |
| 1561 | if (je->eta_sec != INT_MAX && je->elapsed_sec) { |
| 1562 | perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec); |
| 1563 | eta_to_str(eta_str, je->eta_sec); |
| 1564 | } |
| 1565 | |
| 1566 | #if 0 |
| 1567 | if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) { |
| 1568 | if (je->m_rate || je->t_rate) { |
| 1569 | char *tr, *mr; |
| 1570 | |
| 1571 | mr = num2str(je->m_rate, 4, 0, i2p); |
| 1572 | tr = num2str(je->t_rate, 4, 0, i2p); |
| 1573 | gtk_entry_set_text(GTK_ENTRY(ui->eta); |
| 1574 | p += sprintf(p, ", CR=%s/%s KB/s", tr, mr); |
| 1575 | free(tr); |
| 1576 | free(mr); |
| 1577 | } else if (je->m_iops || je->t_iops) |
| 1578 | p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops); |
| 1579 | |
| 1580 | gtk_entry_set_text(GTK_ENTRY(ui->eta.cr_bw), "---"); |
| 1581 | gtk_entry_set_text(GTK_ENTRY(ui->eta.cr_iops), "---"); |
| 1582 | gtk_entry_set_text(GTK_ENTRY(ui->eta.cw_bw), "---"); |
| 1583 | gtk_entry_set_text(GTK_ENTRY(ui->eta.cw_iops), "---"); |
| 1584 | #endif |
| 1585 | |
Jens Axboe | 3863d1a | 2012-03-09 17:39:05 +0100 | [diff] [blame] | 1586 | entry_set_int_value(ui->eta.jobs, je->nr_running); |
| 1587 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1588 | if (je->eta_sec != INT_MAX && je->nr_running) { |
| 1589 | char *iops_str[2]; |
| 1590 | char *rate_str[2]; |
| 1591 | |
| 1592 | if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running) |
| 1593 | strcpy(output, "-.-% done"); |
| 1594 | else { |
| 1595 | eta_good = 1; |
| 1596 | perc *= 100.0; |
| 1597 | sprintf(output, "%3.1f%% done", perc); |
| 1598 | } |
| 1599 | |
| 1600 | rate_str[0] = num2str(je->rate[0], 5, 10, i2p); |
| 1601 | rate_str[1] = num2str(je->rate[1], 5, 10, i2p); |
| 1602 | |
| 1603 | iops_str[0] = num2str(je->iops[0], 4, 1, 0); |
| 1604 | iops_str[1] = num2str(je->iops[1], 4, 1, 0); |
| 1605 | |
| 1606 | gtk_entry_set_text(GTK_ENTRY(ui->eta.read_bw), rate_str[0]); |
| 1607 | gtk_entry_set_text(GTK_ENTRY(ui->eta.read_iops), iops_str[0]); |
| 1608 | gtk_entry_set_text(GTK_ENTRY(ui->eta.write_bw), rate_str[1]); |
| 1609 | gtk_entry_set_text(GTK_ENTRY(ui->eta.write_iops), iops_str[1]); |
| 1610 | |
Jens Axboe | 93e2db2 | 2012-03-13 09:45:22 +0100 | [diff] [blame] | 1611 | graph_add_xy_data(ui->graphs.iops_graph, "Read IOPS", je->elapsed_sec, je->iops[0], iops_str[0]); |
| 1612 | graph_add_xy_data(ui->graphs.iops_graph, "Write IOPS", je->elapsed_sec, je->iops[1], iops_str[1]); |
| 1613 | graph_add_xy_data(ui->graphs.bandwidth_graph, "Read Bandwidth", je->elapsed_sec, je->rate[0], rate_str[0]); |
| 1614 | graph_add_xy_data(ui->graphs.bandwidth_graph, "Write Bandwidth", je->elapsed_sec, je->rate[1], rate_str[1]); |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 1615 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1616 | free(rate_str[0]); |
| 1617 | free(rate_str[1]); |
| 1618 | free(iops_str[0]); |
| 1619 | free(iops_str[1]); |
| 1620 | } |
| 1621 | |
| 1622 | if (eta_str[0]) { |
| 1623 | char *dst = output + strlen(output); |
| 1624 | |
| 1625 | sprintf(dst, " - %s", eta_str); |
| 1626 | } |
| 1627 | |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 1628 | gfio_update_thread_status_all(output, perc); |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1629 | gdk_threads_leave(); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1630 | } |
| 1631 | |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1632 | static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1633 | { |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 1634 | struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload; |
Jens Axboe | 88f6e7a | 2012-03-06 12:55:29 +0100 | [diff] [blame] | 1635 | struct gfio_client *gc = client->client_data; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1636 | struct gui_entry *ge = gc->ge; |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 1637 | const char *os, *arch; |
| 1638 | char buf[64]; |
| 1639 | |
| 1640 | os = fio_get_os_string(probe->os); |
| 1641 | if (!os) |
| 1642 | os = "unknown"; |
| 1643 | |
| 1644 | arch = fio_get_arch_string(probe->arch); |
| 1645 | if (!arch) |
| 1646 | os = "unknown"; |
| 1647 | |
| 1648 | if (!client->name) |
| 1649 | client->name = strdup((char *) probe->hostname); |
| 1650 | |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1651 | gdk_threads_enter(); |
| 1652 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1653 | gtk_label_set_text(GTK_LABEL(ge->probe.hostname), (char *) probe->hostname); |
| 1654 | gtk_label_set_text(GTK_LABEL(ge->probe.os), os); |
| 1655 | gtk_label_set_text(GTK_LABEL(ge->probe.arch), arch); |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 1656 | sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1657 | gtk_label_set_text(GTK_LABEL(ge->probe.fio_ver), buf); |
Jens Axboe | 88f6e7a | 2012-03-06 12:55:29 +0100 | [diff] [blame] | 1658 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1659 | gfio_set_state(ge, GE_STATE_CONNECTED); |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1660 | |
| 1661 | gdk_threads_leave(); |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1662 | } |
| 1663 | |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 1664 | static void gfio_update_thread_status(struct gui_entry *ge, |
| 1665 | char *status_message, double perc) |
| 1666 | { |
| 1667 | static char message[100]; |
| 1668 | const char *m = message; |
| 1669 | |
| 1670 | strncpy(message, status_message, sizeof(message) - 1); |
| 1671 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), m); |
| 1672 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), perc / 100.0); |
| 1673 | gtk_widget_queue_draw(main_ui.window); |
| 1674 | } |
| 1675 | |
| 1676 | static void gfio_update_thread_status_all(char *status_message, double perc) |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1677 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1678 | struct gui *ui = &main_ui; |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1679 | static char message[100]; |
| 1680 | const char *m = message; |
| 1681 | |
| 1682 | strncpy(message, status_message, sizeof(message) - 1); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1683 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), m); |
| 1684 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), perc / 100.0); |
| 1685 | gtk_widget_queue_draw(ui->window); |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1686 | } |
| 1687 | |
Jens Axboe | 35c0ba7 | 2012-03-14 10:56:40 +0100 | [diff] [blame] | 1688 | static void gfio_quit_op(struct fio_client *client, struct fio_net_cmd *cmd) |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 1689 | { |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 1690 | struct gfio_client *gc = client->client_data; |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 1691 | |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1692 | gdk_threads_enter(); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1693 | gfio_set_state(gc->ge, GE_STATE_NEW); |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1694 | gdk_threads_leave(); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 1695 | } |
| 1696 | |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 1697 | static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1698 | { |
| 1699 | struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 1700 | struct gfio_client *gc = client->client_data; |
Jens Axboe | dcaeb60 | 2012-03-08 19:45:37 +0100 | [diff] [blame] | 1701 | struct thread_options *o = &gc->o; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1702 | struct gui_entry *ge = gc->ge; |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 1703 | char *c1, *c2, *c3, *c4; |
| 1704 | char tmp[80]; |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 1705 | |
Jens Axboe | 2f122b1 | 2012-03-15 13:10:19 +0100 | [diff] [blame] | 1706 | p->thread_number = le32_to_cpu(p->thread_number); |
| 1707 | p->groupid = le32_to_cpu(p->groupid); |
Jens Axboe | dcaeb60 | 2012-03-08 19:45:37 +0100 | [diff] [blame] | 1708 | convert_thread_options_to_cpu(o, &p->top); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 1709 | |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1710 | gdk_threads_enter(); |
| 1711 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1712 | gtk_label_set_text(GTK_LABEL(ge->page_label), (gchar *) o->name); |
| 1713 | |
Jens Axboe | 3863d1a | 2012-03-09 17:39:05 +0100 | [diff] [blame] | 1714 | gtk_combo_box_append_text(GTK_COMBO_BOX(ge->eta.names), (gchar *) o->name); |
| 1715 | gtk_combo_box_set_active(GTK_COMBO_BOX(ge->eta.names), 0); |
| 1716 | |
Jens Axboe | ddbafc1 | 2012-03-15 18:57:03 +0100 | [diff] [blame] | 1717 | sprintf(tmp, "%s %s", o->odirect ? "direct" : "buffered", ddir_str(o->td_ddir)); |
| 1718 | multitext_add_entry(&ge->eta.iotype, tmp); |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 1719 | |
| 1720 | c1 = fio_uint_to_kmg(o->min_bs[DDIR_READ]); |
| 1721 | c2 = fio_uint_to_kmg(o->max_bs[DDIR_WRITE]); |
| 1722 | c3 = fio_uint_to_kmg(o->min_bs[DDIR_READ]); |
| 1723 | c4 = fio_uint_to_kmg(o->max_bs[DDIR_WRITE]); |
| 1724 | sprintf(tmp, "%s-%s/%s-%s", c1, c2, c3, c4); |
| 1725 | free(c1); |
| 1726 | free(c2); |
| 1727 | free(c3); |
| 1728 | free(c4); |
| 1729 | multitext_add_entry(&ge->eta.bs, tmp); |
| 1730 | |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 1731 | multitext_add_entry(&ge->eta.ioengine, (const char *) o->ioengine); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 1732 | |
Jens Axboe | dcaeb60 | 2012-03-08 19:45:37 +0100 | [diff] [blame] | 1733 | sprintf(tmp, "%u", o->iodepth); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 1734 | multitext_add_entry(&ge->eta.iodepth, tmp); |
| 1735 | |
| 1736 | multitext_set_entry(&ge->eta.iotype, 0); |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 1737 | multitext_set_entry(&ge->eta.bs, 0); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 1738 | multitext_set_entry(&ge->eta.ioengine, 0); |
| 1739 | multitext_set_entry(&ge->eta.iodepth, 0); |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1740 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1741 | gfio_set_state(ge, GE_STATE_JOB_SENT); |
| 1742 | |
Jens Axboe | 0050e5f | 2012-03-06 09:23:27 +0100 | [diff] [blame] | 1743 | gdk_threads_leave(); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 1744 | } |
| 1745 | |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 1746 | static void gfio_client_timed_out(struct fio_client *client) |
| 1747 | { |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 1748 | struct gfio_client *gc = client->client_data; |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 1749 | char buf[256]; |
| 1750 | |
| 1751 | gdk_threads_enter(); |
| 1752 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1753 | gfio_set_state(gc->ge, GE_STATE_NEW); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1754 | clear_ge_ui_info(gc->ge); |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 1755 | |
| 1756 | sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname); |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 1757 | show_info_dialog(gc->ge->ui, "Network timeout", buf); |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 1758 | |
| 1759 | gdk_threads_leave(); |
| 1760 | } |
| 1761 | |
Jens Axboe | 6b79c80 | 2012-03-08 10:51:36 +0100 | [diff] [blame] | 1762 | static void gfio_client_stop(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1763 | { |
| 1764 | struct gfio_client *gc = client->client_data; |
| 1765 | |
| 1766 | gdk_threads_enter(); |
| 1767 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1768 | gfio_set_state(gc->ge, GE_STATE_JOB_DONE); |
Jens Axboe | 6b79c80 | 2012-03-08 10:51:36 +0100 | [diff] [blame] | 1769 | |
| 1770 | if (gc->err_entry) |
| 1771 | entry_set_int_value(gc->err_entry, client->error); |
| 1772 | |
| 1773 | gdk_threads_leave(); |
| 1774 | } |
| 1775 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1776 | static void gfio_client_start(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1777 | { |
| 1778 | struct gfio_client *gc = client->client_data; |
| 1779 | |
| 1780 | gdk_threads_enter(); |
| 1781 | gfio_set_state(gc->ge, GE_STATE_JOB_STARTED); |
| 1782 | gdk_threads_leave(); |
| 1783 | } |
| 1784 | |
| 1785 | static void gfio_client_job_start(struct fio_client *client, struct fio_net_cmd *cmd) |
| 1786 | { |
| 1787 | struct gfio_client *gc = client->client_data; |
| 1788 | |
| 1789 | gdk_threads_enter(); |
| 1790 | gfio_set_state(gc->ge, GE_STATE_JOB_RUNNING); |
| 1791 | gdk_threads_leave(); |
| 1792 | } |
| 1793 | |
Jens Axboe | 1b42725 | 2012-03-14 15:03:03 +0100 | [diff] [blame] | 1794 | static void gfio_client_iolog(struct fio_client *client, struct cmd_iolog_pdu *pdu) |
| 1795 | { |
Jens Axboe | 284b1e6 | 2012-03-14 21:55:07 +0100 | [diff] [blame] | 1796 | printf("got iolog: name=%s, type=%u, entries=%u\n", pdu->name, pdu->log_type, pdu->nr_samples); |
Jens Axboe | 1b42725 | 2012-03-14 15:03:03 +0100 | [diff] [blame] | 1797 | free(pdu); |
| 1798 | } |
| 1799 | |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1800 | struct client_ops gfio_client_ops = { |
Jens Axboe | 35c0ba7 | 2012-03-14 10:56:40 +0100 | [diff] [blame] | 1801 | .text = gfio_text_op, |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1802 | .disk_util = gfio_disk_util_op, |
| 1803 | .thread_status = gfio_thread_status_op, |
| 1804 | .group_stats = gfio_group_stats_op, |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1805 | .jobs_eta = gfio_update_client_eta, |
| 1806 | .eta = gfio_update_all_eta, |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1807 | .probe = gfio_probe_op, |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 1808 | .quit = gfio_quit_op, |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 1809 | .add_job = gfio_add_job_op, |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 1810 | .timed_out = gfio_client_timed_out, |
Jens Axboe | 6b79c80 | 2012-03-08 10:51:36 +0100 | [diff] [blame] | 1811 | .stop = gfio_client_stop, |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1812 | .start = gfio_client_start, |
| 1813 | .job_start = gfio_client_job_start, |
Jens Axboe | 1b42725 | 2012-03-14 15:03:03 +0100 | [diff] [blame] | 1814 | .iolog = gfio_client_iolog, |
Jens Axboe | 6433ee0 | 2012-03-09 20:10:51 +0100 | [diff] [blame] | 1815 | .eta_msec = FIO_CLIENT_DEF_ETA_MSEC, |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 1816 | .stay_connected = 1, |
Jens Axboe | 46bcd49 | 2012-03-14 11:31:21 +0100 | [diff] [blame] | 1817 | .client_type = FIO_CLIENT_TYPE_GUI, |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1818 | }; |
| 1819 | |
Jens Axboe | 0fd1898 | 2012-03-14 10:34:48 +0100 | [diff] [blame] | 1820 | /* |
| 1821 | * FIXME: need more handling here |
| 1822 | */ |
| 1823 | static void ge_destroy(struct gui_entry *ge) |
| 1824 | { |
| 1825 | struct gfio_client *gc = ge->client; |
| 1826 | |
| 1827 | if (gc && gc->client) { |
| 1828 | if (ge->state >= GE_STATE_CONNECTED) |
| 1829 | fio_client_terminate(gc->client); |
| 1830 | |
| 1831 | fio_put_client(gc->client); |
| 1832 | } |
| 1833 | |
| 1834 | flist_del(&ge->list); |
| 1835 | free(ge); |
| 1836 | } |
| 1837 | |
| 1838 | static void ge_widget_destroy(GtkWidget *w, gpointer data) |
| 1839 | { |
Jens Axboe | 0fd1898 | 2012-03-14 10:34:48 +0100 | [diff] [blame] | 1840 | } |
| 1841 | |
| 1842 | static void gfio_quit(struct gui *ui) |
| 1843 | { |
| 1844 | struct gui_entry *ge; |
| 1845 | |
| 1846 | while (!flist_empty(&ui->list)) { |
| 1847 | ge = flist_entry(ui->list.next, struct gui_entry, list); |
| 1848 | ge_destroy(ge); |
| 1849 | } |
| 1850 | |
| 1851 | gtk_main_quit(); |
| 1852 | } |
| 1853 | |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 1854 | static void quit_clicked(__attribute__((unused)) GtkWidget *widget, |
| 1855 | __attribute__((unused)) gpointer data) |
| 1856 | { |
Jens Axboe | 0fd1898 | 2012-03-14 10:34:48 +0100 | [diff] [blame] | 1857 | gfio_quit(data); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 1858 | } |
| 1859 | |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1860 | static void *job_thread(void *arg) |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 1861 | { |
Jens Axboe | a9eccde | 2012-03-09 14:59:42 +0100 | [diff] [blame] | 1862 | struct gui *ui = arg; |
| 1863 | |
| 1864 | ui->handler_running = 1; |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1865 | fio_handle_clients(&gfio_client_ops); |
Jens Axboe | a9eccde | 2012-03-09 14:59:42 +0100 | [diff] [blame] | 1866 | ui->handler_running = 0; |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1867 | return NULL; |
| 1868 | } |
| 1869 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1870 | static int send_job_files(struct gui_entry *ge) |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 1871 | { |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 1872 | struct gfio_client *gc = ge->client; |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 1873 | int i, ret = 0; |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 1874 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1875 | for (i = 0; i < ge->nr_job_files; i++) { |
Jens Axboe | 9988ca7 | 2012-03-09 15:14:06 +0100 | [diff] [blame] | 1876 | ret = fio_client_send_ini(gc->client, ge->job_files[i]); |
Jens Axboe | c724926 | 2012-03-09 17:11:04 +0100 | [diff] [blame] | 1877 | if (ret < 0) { |
| 1878 | GError *error; |
| 1879 | |
| 1880 | error = g_error_new(g_quark_from_string("fio"), 1, "Failed to send file %s: %s\n", ge->job_files[i], strerror(-ret)); |
| 1881 | report_error(error); |
| 1882 | g_error_free(error); |
| 1883 | break; |
| 1884 | } else if (ret) |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 1885 | break; |
| 1886 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1887 | free(ge->job_files[i]); |
| 1888 | ge->job_files[i] = NULL; |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 1889 | } |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1890 | while (i < ge->nr_job_files) { |
| 1891 | free(ge->job_files[i]); |
| 1892 | ge->job_files[i] = NULL; |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 1893 | i++; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1894 | } |
| 1895 | |
Jens Axboe | 2c77d83 | 2012-03-13 19:02:04 +0100 | [diff] [blame] | 1896 | free(ge->job_files); |
| 1897 | ge->job_files = NULL; |
Jens Axboe | 3af4520 | 2012-03-13 09:59:53 +0100 | [diff] [blame] | 1898 | ge->nr_job_files = 0; |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 1899 | return ret; |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 1900 | } |
| 1901 | |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 1902 | static void *server_thread(void *arg) |
| 1903 | { |
| 1904 | is_backend = 1; |
| 1905 | gfio_server_running = 1; |
| 1906 | fio_start_server(NULL); |
| 1907 | gfio_server_running = 0; |
| 1908 | return NULL; |
| 1909 | } |
| 1910 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1911 | static void gfio_start_server(void) |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 1912 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1913 | struct gui *ui = &main_ui; |
| 1914 | |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 1915 | if (!gfio_server_running) { |
| 1916 | gfio_server_running = 1; |
| 1917 | pthread_create(&ui->server_t, NULL, server_thread, NULL); |
Jens Axboe | e34f6ad | 2012-03-06 20:47:15 +0100 | [diff] [blame] | 1918 | pthread_detach(ui->server_t); |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 1919 | } |
| 1920 | } |
| 1921 | |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1922 | static void start_job_clicked(__attribute__((unused)) GtkWidget *widget, |
| 1923 | gpointer data) |
| 1924 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1925 | struct gui_entry *ge = data; |
| 1926 | struct gfio_client *gc = ge->client; |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 1927 | |
Jens Axboe | 78cb2fe | 2012-03-12 23:05:29 +0100 | [diff] [blame] | 1928 | if (gc) |
| 1929 | fio_start_client(gc->client); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 1930 | } |
| 1931 | |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 1932 | static void file_open(GtkWidget *w, gpointer data); |
| 1933 | |
| 1934 | static void connect_clicked(GtkWidget *widget, gpointer data) |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1935 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1936 | struct gui_entry *ge = data; |
| 1937 | struct gfio_client *gc = ge->client; |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 1938 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1939 | if (ge->state == GE_STATE_NEW) { |
Jens Axboe | c724926 | 2012-03-09 17:11:04 +0100 | [diff] [blame] | 1940 | int ret; |
| 1941 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1942 | if (!ge->nr_job_files) |
Jens Axboe | cf4b044 | 2012-03-12 15:09:42 +0100 | [diff] [blame] | 1943 | file_open(widget, ge->ui); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1944 | if (!ge->nr_job_files) |
| 1945 | return; |
| 1946 | |
Jens Axboe | d3b70f3 | 2012-03-15 14:05:01 +0100 | [diff] [blame] | 1947 | gc = ge->client; |
| 1948 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1949 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), "No jobs running"); |
| 1950 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), 0.0); |
Jens Axboe | c724926 | 2012-03-09 17:11:04 +0100 | [diff] [blame] | 1951 | ret = fio_client_connect(gc->client); |
| 1952 | if (!ret) { |
Jens Axboe | a9eccde | 2012-03-09 14:59:42 +0100 | [diff] [blame] | 1953 | if (!ge->ui->handler_running) |
| 1954 | pthread_create(&ge->ui->t, NULL, job_thread, ge->ui); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1955 | gfio_set_state(ge, GE_STATE_CONNECTED); |
Jens Axboe | c724926 | 2012-03-09 17:11:04 +0100 | [diff] [blame] | 1956 | } else { |
| 1957 | GError *error; |
| 1958 | |
| 1959 | error = g_error_new(g_quark_from_string("fio"), 1, "Failed to connect to %s: %s\n", ge->client->client->hostname, strerror(-ret)); |
| 1960 | report_error(error); |
| 1961 | g_error_free(error); |
Jens Axboe | 69406b9 | 2012-03-06 14:00:42 +0100 | [diff] [blame] | 1962 | } |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 1963 | } else { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1964 | fio_client_terminate(gc->client); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 1965 | gfio_set_state(ge, GE_STATE_NEW); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1966 | clear_ge_ui_info(ge); |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 1967 | } |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 1968 | } |
| 1969 | |
Jens Axboe | b9d2f30 | 2012-03-08 20:36:28 +0100 | [diff] [blame] | 1970 | static void send_clicked(GtkWidget *widget, gpointer data) |
| 1971 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1972 | struct gui_entry *ge = data; |
Jens Axboe | b9d2f30 | 2012-03-08 20:36:28 +0100 | [diff] [blame] | 1973 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1974 | if (send_job_files(ge)) { |
Jens Axboe | c724926 | 2012-03-09 17:11:04 +0100 | [diff] [blame] | 1975 | GError *error; |
| 1976 | |
| 1977 | 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); |
| 1978 | report_error(error); |
| 1979 | g_error_free(error); |
| 1980 | |
Jens Axboe | 53e0e85 | 2012-03-15 19:38:01 +0100 | [diff] [blame] | 1981 | gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_START], 1); |
Jens Axboe | b9d2f30 | 2012-03-08 20:36:28 +0100 | [diff] [blame] | 1982 | } |
Jens Axboe | b9d2f30 | 2012-03-08 20:36:28 +0100 | [diff] [blame] | 1983 | } |
| 1984 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1985 | static void on_info_bar_response(GtkWidget *widget, gint response, |
| 1986 | gpointer data) |
| 1987 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1988 | struct gui *ui = &main_ui; |
| 1989 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1990 | if (response == GTK_RESPONSE_OK) { |
| 1991 | gtk_widget_destroy(widget); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1992 | ui->error_info_bar = NULL; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1993 | } |
| 1994 | } |
| 1995 | |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 1996 | void report_error(GError *error) |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 1997 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 1998 | struct gui *ui = &main_ui; |
| 1999 | |
| 2000 | if (ui->error_info_bar == NULL) { |
| 2001 | ui->error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK, |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2002 | GTK_RESPONSE_OK, |
| 2003 | NULL); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2004 | g_signal_connect(ui->error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL); |
| 2005 | gtk_info_bar_set_message_type(GTK_INFO_BAR(ui->error_info_bar), |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2006 | GTK_MESSAGE_ERROR); |
| 2007 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2008 | ui->error_label = gtk_label_new(error->message); |
| 2009 | GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(ui->error_info_bar)); |
| 2010 | gtk_container_add(GTK_CONTAINER(container), ui->error_label); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2011 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2012 | gtk_box_pack_start(GTK_BOX(ui->vbox), ui->error_info_bar, FALSE, FALSE, 0); |
| 2013 | gtk_widget_show_all(ui->vbox); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2014 | } else { |
| 2015 | char buffer[256]; |
| 2016 | snprintf(buffer, sizeof(buffer), "Failed to open file."); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2017 | gtk_label_set(GTK_LABEL(ui->error_label), buffer); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2018 | } |
| 2019 | } |
| 2020 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2021 | struct connection_widgets |
| 2022 | { |
| 2023 | GtkWidget *hentry; |
| 2024 | GtkWidget *combo; |
| 2025 | GtkWidget *button; |
| 2026 | }; |
| 2027 | |
| 2028 | static void hostname_cb(GtkEntry *entry, gpointer data) |
| 2029 | { |
| 2030 | struct connection_widgets *cw = data; |
| 2031 | int uses_net = 0, is_localhost = 0; |
| 2032 | const gchar *text; |
| 2033 | gchar *ctext; |
| 2034 | |
| 2035 | /* |
| 2036 | * Check whether to display the 'auto start backend' box |
| 2037 | * or not. Show it if we are a localhost and using network, |
| 2038 | * or using a socket. |
| 2039 | */ |
| 2040 | ctext = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cw->combo)); |
| 2041 | if (!ctext || !strncmp(ctext, "IPv4", 4) || !strncmp(ctext, "IPv6", 4)) |
| 2042 | uses_net = 1; |
| 2043 | g_free(ctext); |
| 2044 | |
| 2045 | if (uses_net) { |
| 2046 | text = gtk_entry_get_text(GTK_ENTRY(cw->hentry)); |
| 2047 | if (!strcmp(text, "127.0.0.1") || !strcmp(text, "localhost") || |
| 2048 | !strcmp(text, "::1") || !strcmp(text, "ip6-localhost") || |
| 2049 | !strcmp(text, "ip6-loopback")) |
| 2050 | is_localhost = 1; |
| 2051 | } |
| 2052 | |
| 2053 | if (!uses_net || is_localhost) { |
| 2054 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw->button), 1); |
| 2055 | gtk_widget_set_sensitive(cw->button, 1); |
| 2056 | } else { |
| 2057 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw->button), 0); |
| 2058 | gtk_widget_set_sensitive(cw->button, 0); |
| 2059 | } |
| 2060 | } |
| 2061 | |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame] | 2062 | static int get_connection_details(char **host, int *port, int *type, |
| 2063 | int *server_start) |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2064 | { |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2065 | GtkWidget *dialog, *box, *vbox, *hbox, *frame, *pentry; |
| 2066 | struct connection_widgets cw; |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2067 | char *typeentry; |
| 2068 | |
| 2069 | dialog = gtk_dialog_new_with_buttons("Connection details", |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2070 | GTK_WINDOW(main_ui.window), |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2071 | GTK_DIALOG_DESTROY_WITH_PARENT, |
| 2072 | GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
| 2073 | GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); |
| 2074 | |
| 2075 | frame = gtk_frame_new("Hostname / socket name"); |
Jens Axboe | f129909 | 2012-03-07 20:00:02 +0100 | [diff] [blame] | 2076 | /* gtk_dialog_get_content_area() is 2.14 and newer */ |
| 2077 | vbox = GTK_DIALOG(dialog)->vbox; |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2078 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 2079 | |
| 2080 | box = gtk_vbox_new(FALSE, 6); |
| 2081 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 2082 | |
| 2083 | hbox = gtk_hbox_new(TRUE, 10); |
| 2084 | gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2085 | cw.hentry = gtk_entry_new(); |
| 2086 | gtk_entry_set_text(GTK_ENTRY(cw.hentry), "localhost"); |
| 2087 | gtk_box_pack_start(GTK_BOX(hbox), cw.hentry, TRUE, TRUE, 0); |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2088 | |
| 2089 | frame = gtk_frame_new("Port"); |
| 2090 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 2091 | box = gtk_vbox_new(FALSE, 10); |
| 2092 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 2093 | |
| 2094 | hbox = gtk_hbox_new(TRUE, 4); |
| 2095 | gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); |
| 2096 | pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT); |
| 2097 | |
| 2098 | frame = gtk_frame_new("Type"); |
| 2099 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 2100 | box = gtk_vbox_new(FALSE, 10); |
| 2101 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 2102 | |
| 2103 | hbox = gtk_hbox_new(TRUE, 4); |
| 2104 | gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); |
| 2105 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2106 | cw.combo = gtk_combo_box_new_text(); |
| 2107 | gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "IPv4"); |
| 2108 | gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "IPv6"); |
| 2109 | gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "local socket"); |
| 2110 | gtk_combo_box_set_active(GTK_COMBO_BOX(cw.combo), 0); |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2111 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2112 | gtk_container_add(GTK_CONTAINER(hbox), cw.combo); |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2113 | |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame] | 2114 | frame = gtk_frame_new("Options"); |
| 2115 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); |
| 2116 | box = gtk_vbox_new(FALSE, 10); |
| 2117 | gtk_container_add(GTK_CONTAINER(frame), box); |
| 2118 | |
| 2119 | hbox = gtk_hbox_new(TRUE, 4); |
| 2120 | gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); |
| 2121 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2122 | cw.button = gtk_check_button_new_with_label("Auto-spawn fio backend"); |
| 2123 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.button), 1); |
| 2124 | gtk_widget_set_tooltip_text(cw.button, "When running fio locally, it is necessary to have the backend running on the same system. If this is checked, gfio will start the backend automatically for you if it isn't already running."); |
| 2125 | gtk_box_pack_start(GTK_BOX(hbox), cw.button, FALSE, FALSE, 6); |
| 2126 | |
| 2127 | /* |
| 2128 | * Connect edit signal, so we can show/not-show the auto start button |
| 2129 | */ |
| 2130 | g_signal_connect(GTK_OBJECT(cw.hentry), "changed", G_CALLBACK(hostname_cb), &cw); |
| 2131 | g_signal_connect(GTK_OBJECT(cw.combo), "changed", G_CALLBACK(hostname_cb), &cw); |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame] | 2132 | |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2133 | gtk_widget_show_all(dialog); |
| 2134 | |
| 2135 | if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { |
| 2136 | gtk_widget_destroy(dialog); |
| 2137 | return 1; |
| 2138 | } |
| 2139 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2140 | *host = strdup(gtk_entry_get_text(GTK_ENTRY(cw.hentry))); |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2141 | *port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry)); |
| 2142 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2143 | typeentry = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cw.combo)); |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2144 | if (!typeentry || !strncmp(typeentry, "IPv4", 4)) |
| 2145 | *type = Fio_client_ipv4; |
| 2146 | else if (!strncmp(typeentry, "IPv6", 4)) |
| 2147 | *type = Fio_client_ipv6; |
| 2148 | else |
| 2149 | *type = Fio_client_socket; |
| 2150 | g_free(typeentry); |
| 2151 | |
Jens Axboe | 62bc937 | 2012-03-07 11:45:07 +0100 | [diff] [blame] | 2152 | *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.button)); |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame] | 2153 | |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2154 | gtk_widget_destroy(dialog); |
| 2155 | return 0; |
| 2156 | } |
| 2157 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2158 | static void gfio_client_added(struct gui_entry *ge, struct fio_client *client) |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 2159 | { |
| 2160 | struct gfio_client *gc; |
| 2161 | |
| 2162 | gc = malloc(sizeof(*gc)); |
| 2163 | memset(gc, 0, sizeof(*gc)); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2164 | gc->ge = ge; |
Jens Axboe | 343cb4a | 2012-03-09 17:16:51 +0100 | [diff] [blame] | 2165 | gc->client = fio_get_client(client); |
Jens Axboe | b9d2f30 | 2012-03-08 20:36:28 +0100 | [diff] [blame] | 2166 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2167 | ge->client = gc; |
Jens Axboe | e0681f3 | 2012-03-06 12:14:42 +0100 | [diff] [blame] | 2168 | |
| 2169 | client->client_data = gc; |
| 2170 | } |
| 2171 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2172 | static GtkWidget *new_client_page(struct gui_entry *ge); |
| 2173 | |
| 2174 | static struct gui_entry *alloc_new_gui_entry(struct gui *ui) |
| 2175 | { |
| 2176 | struct gui_entry *ge; |
| 2177 | |
| 2178 | ge = malloc(sizeof(*ge)); |
| 2179 | memset(ge, 0, sizeof(*ge)); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2180 | ge->state = GE_STATE_NEW; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2181 | INIT_FLIST_HEAD(&ge->list); |
| 2182 | flist_add_tail(&ge->list, &ui->list); |
| 2183 | ge->ui = ui; |
| 2184 | return ge; |
| 2185 | } |
| 2186 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2187 | static struct gui_entry *get_new_ge_with_tab(const char *name) |
| 2188 | { |
| 2189 | struct gui_entry *ge; |
| 2190 | |
| 2191 | ge = alloc_new_gui_entry(&main_ui); |
| 2192 | |
| 2193 | ge->vbox = new_client_page(ge); |
Jens Axboe | 0fd1898 | 2012-03-14 10:34:48 +0100 | [diff] [blame] | 2194 | g_signal_connect(ge->vbox, "destroy", G_CALLBACK(ge_widget_destroy), ge); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2195 | |
| 2196 | ge->page_label = gtk_label_new(name); |
| 2197 | ge->page_num = gtk_notebook_append_page(GTK_NOTEBOOK(main_ui.notebook), ge->vbox, ge->page_label); |
| 2198 | |
| 2199 | gtk_widget_show_all(main_ui.window); |
| 2200 | return ge; |
| 2201 | } |
| 2202 | |
| 2203 | static void file_new(GtkWidget *w, gpointer data) |
| 2204 | { |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2205 | struct gui *ui = (struct gui *) data; |
| 2206 | struct gui_entry *ge; |
| 2207 | |
| 2208 | ge = get_new_ge_with_tab("Untitled"); |
| 2209 | gtk_notebook_set_current_page(GTK_NOTEBOOK(ui->notebook), ge->page_num); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2210 | } |
| 2211 | |
| 2212 | /* |
| 2213 | * Return the 'ge' corresponding to the tab. If the active tab is the |
| 2214 | * main tab, open a new tab. |
| 2215 | */ |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2216 | static struct gui_entry *get_ge_from_page(gint cur_page, int *created) |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2217 | { |
| 2218 | struct flist_head *entry; |
| 2219 | struct gui_entry *ge; |
| 2220 | |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2221 | if (!cur_page) { |
| 2222 | if (created) |
| 2223 | *created = 1; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2224 | return get_new_ge_with_tab("Untitled"); |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2225 | } |
| 2226 | |
| 2227 | if (created) |
| 2228 | *created = 0; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2229 | |
| 2230 | flist_for_each(entry, &main_ui.list) { |
| 2231 | ge = flist_entry(entry, struct gui_entry, list); |
| 2232 | if (ge->page_num == cur_page) |
| 2233 | return ge; |
| 2234 | } |
| 2235 | |
| 2236 | return NULL; |
| 2237 | } |
| 2238 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2239 | static struct gui_entry *get_ge_from_cur_tab(struct gui *ui) |
| 2240 | { |
| 2241 | gint cur_page; |
| 2242 | |
| 2243 | /* |
| 2244 | * Main tab is tab 0, so any current page other than 0 holds |
| 2245 | * a ge entry. |
| 2246 | */ |
| 2247 | cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(ui->notebook)); |
| 2248 | if (cur_page) |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2249 | return get_ge_from_page(cur_page, NULL); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2250 | |
| 2251 | return NULL; |
| 2252 | } |
| 2253 | |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2254 | static void file_close(GtkWidget *w, gpointer data) |
| 2255 | { |
| 2256 | struct gui *ui = (struct gui *) data; |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2257 | struct gui_entry *ge; |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2258 | |
| 2259 | /* |
| 2260 | * Can't close the main tab |
| 2261 | */ |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2262 | ge = get_ge_from_cur_tab(ui); |
| 2263 | if (ge) { |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2264 | gtk_widget_destroy(ge->vbox); |
| 2265 | return; |
| 2266 | } |
| 2267 | |
Jens Axboe | f5c6726 | 2012-03-13 08:20:41 +0100 | [diff] [blame] | 2268 | if (!flist_empty(&ui->list)) { |
| 2269 | show_info_dialog(ui, "Error", "The main page view cannot be closed\n"); |
| 2270 | return; |
| 2271 | } |
| 2272 | |
Jens Axboe | 0fd1898 | 2012-03-14 10:34:48 +0100 | [diff] [blame] | 2273 | gfio_quit(ui); |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2274 | } |
| 2275 | |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2276 | static void file_add_recent(struct gui *ui, const gchar *uri) |
| 2277 | { |
Jens Axboe | a217ba7 | 2012-03-13 20:29:39 +0100 | [diff] [blame] | 2278 | GtkRecentData grd; |
| 2279 | |
| 2280 | memset(&grd, 0, sizeof(grd)); |
| 2281 | grd.display_name = strdup("gfio"); |
| 2282 | grd.description = strdup("Fio job file"); |
| 2283 | grd.mime_type = strdup(GFIO_MIME); |
| 2284 | grd.app_name = strdup(g_get_application_name()); |
| 2285 | grd.app_exec = strdup("gfio %f/%u"); |
| 2286 | |
| 2287 | gtk_recent_manager_add_full(ui->recentmanager, uri, &grd); |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2288 | } |
| 2289 | |
| 2290 | static gchar *get_filename_from_uri(const gchar *uri) |
| 2291 | { |
| 2292 | if (strncmp(uri, "file://", 7)) |
| 2293 | return strdup(uri); |
| 2294 | |
| 2295 | return strdup(uri + 7); |
| 2296 | } |
| 2297 | |
| 2298 | static int do_file_open(struct gui_entry *ge, const gchar *uri, char *host, |
| 2299 | int type, int port) |
| 2300 | { |
| 2301 | struct fio_client *client; |
| 2302 | gchar *filename; |
| 2303 | |
| 2304 | filename = get_filename_from_uri(uri); |
| 2305 | |
| 2306 | ge->job_files = realloc(ge->job_files, (ge->nr_job_files + 1) * sizeof(char *)); |
| 2307 | ge->job_files[ge->nr_job_files] = strdup(filename); |
| 2308 | ge->nr_job_files++; |
| 2309 | |
| 2310 | client = fio_client_add_explicit(&gfio_client_ops, host, type, port); |
| 2311 | if (!client) { |
| 2312 | GError *error; |
| 2313 | |
| 2314 | error = g_error_new(g_quark_from_string("fio"), 1, |
| 2315 | "Failed to add client %s", host); |
| 2316 | report_error(error); |
| 2317 | g_error_free(error); |
| 2318 | return 1; |
| 2319 | } |
| 2320 | |
| 2321 | gfio_client_added(ge, client); |
| 2322 | file_add_recent(ge->ui, uri); |
| 2323 | return 0; |
| 2324 | } |
| 2325 | |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 2326 | static int do_file_open_with_tab(struct gui *ui, const gchar *uri) |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2327 | { |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 2328 | int port, type, server_start; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2329 | struct gui_entry *ge; |
| 2330 | gint cur_page; |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2331 | char *host; |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 2332 | int ret, ge_is_new = 0; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2333 | |
| 2334 | /* |
| 2335 | * Creates new tab if current tab is the main window, or the |
| 2336 | * current tab already has a client. |
| 2337 | */ |
| 2338 | cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(ui->notebook)); |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2339 | ge = get_ge_from_page(cur_page, &ge_is_new); |
| 2340 | if (ge->client) { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2341 | ge = get_new_ge_with_tab("Untitled"); |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2342 | ge_is_new = 1; |
| 2343 | } |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2344 | |
| 2345 | gtk_notebook_set_current_page(GTK_NOTEBOOK(ui->notebook), ge->page_num); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2346 | |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 2347 | if (get_connection_details(&host, &port, &type, &server_start)) { |
| 2348 | if (ge_is_new) |
| 2349 | gtk_widget_destroy(ge->vbox); |
| 2350 | |
| 2351 | return 1; |
| 2352 | } |
| 2353 | |
| 2354 | ret = do_file_open(ge, uri, host, type, port); |
| 2355 | |
| 2356 | free(host); |
| 2357 | |
| 2358 | if (!ret) { |
| 2359 | if (server_start) |
| 2360 | gfio_start_server(); |
| 2361 | } else { |
| 2362 | if (ge_is_new) |
| 2363 | gtk_widget_destroy(ge->vbox); |
| 2364 | } |
| 2365 | |
| 2366 | return ret; |
| 2367 | } |
| 2368 | |
| 2369 | static void recent_open(GtkAction *action, gpointer data) |
| 2370 | { |
| 2371 | struct gui *ui = (struct gui *) data; |
| 2372 | GtkRecentInfo *info; |
| 2373 | const gchar *uri; |
| 2374 | |
| 2375 | info = g_object_get_data(G_OBJECT(action), "gtk-recent-info"); |
| 2376 | uri = gtk_recent_info_get_uri(info); |
| 2377 | |
| 2378 | do_file_open_with_tab(ui, uri); |
| 2379 | } |
| 2380 | |
| 2381 | static void file_open(GtkWidget *w, gpointer data) |
| 2382 | { |
| 2383 | struct gui *ui = data; |
| 2384 | GtkWidget *dialog; |
| 2385 | GSList *filenames, *fn_glist; |
| 2386 | GtkFileFilter *filter; |
| 2387 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2388 | dialog = gtk_file_chooser_dialog_new("Open File", |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 2389 | GTK_WINDOW(ui->window), |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2390 | GTK_FILE_CHOOSER_ACTION_OPEN, |
| 2391 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 2392 | GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
| 2393 | NULL); |
| 2394 | gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); |
| 2395 | |
| 2396 | filter = gtk_file_filter_new(); |
| 2397 | gtk_file_filter_add_pattern(filter, "*.fio"); |
| 2398 | gtk_file_filter_add_pattern(filter, "*.job"); |
Jens Axboe | 2d26299 | 2012-03-07 08:19:30 +0100 | [diff] [blame] | 2399 | gtk_file_filter_add_pattern(filter, "*.ini"); |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2400 | gtk_file_filter_add_mime_type(filter, GFIO_MIME); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2401 | gtk_file_filter_set_name(filter, "Fio job file"); |
| 2402 | gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); |
| 2403 | |
| 2404 | if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { |
| 2405 | gtk_widget_destroy(dialog); |
| 2406 | return; |
| 2407 | } |
| 2408 | |
| 2409 | fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 2410 | |
| 2411 | gtk_widget_destroy(dialog); |
| 2412 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2413 | filenames = fn_glist; |
| 2414 | while (filenames != NULL) { |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 2415 | if (do_file_open_with_tab(ui, filenames->data)) |
| 2416 | break; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2417 | filenames = g_slist_next(filenames); |
| 2418 | } |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 2419 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2420 | g_slist_free(fn_glist); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2421 | } |
| 2422 | |
| 2423 | static void file_save(GtkWidget *w, gpointer data) |
| 2424 | { |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 2425 | struct gui *ui = data; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2426 | GtkWidget *dialog; |
| 2427 | |
| 2428 | dialog = gtk_file_chooser_dialog_new("Save File", |
Jens Axboe | 63a130b | 2012-03-06 20:08:59 +0100 | [diff] [blame] | 2429 | GTK_WINDOW(ui->window), |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2430 | GTK_FILE_CHOOSER_ACTION_SAVE, |
| 2431 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 2432 | GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, |
| 2433 | NULL); |
| 2434 | |
| 2435 | gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); |
| 2436 | gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document"); |
| 2437 | |
| 2438 | if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { |
| 2439 | char *filename; |
| 2440 | |
| 2441 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); |
| 2442 | // save_job_file(filename); |
| 2443 | g_free(filename); |
| 2444 | } |
| 2445 | gtk_widget_destroy(dialog); |
| 2446 | } |
| 2447 | |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2448 | static void view_log_destroy(GtkWidget *w, gpointer data) |
| 2449 | { |
| 2450 | struct gui *ui = (struct gui *) data; |
| 2451 | |
| 2452 | gtk_widget_ref(ui->log_tree); |
| 2453 | gtk_container_remove(GTK_CONTAINER(w), ui->log_tree); |
| 2454 | gtk_widget_destroy(w); |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2455 | ui->log_view = NULL; |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2456 | } |
| 2457 | |
| 2458 | static void view_log(GtkWidget *w, gpointer data) |
| 2459 | { |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2460 | GtkWidget *win, *scroll, *vbox, *box; |
| 2461 | struct gui *ui = (struct gui *) data; |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2462 | |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2463 | if (ui->log_view) |
| 2464 | return; |
| 2465 | |
| 2466 | ui->log_view = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2467 | gtk_window_set_title(GTK_WINDOW(win), "Log"); |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2468 | gtk_window_set_default_size(GTK_WINDOW(win), 700, 500); |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2469 | |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2470 | scroll = gtk_scrolled_window_new(NULL, NULL); |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2471 | |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2472 | gtk_container_set_border_width(GTK_CONTAINER(scroll), 5); |
| 2473 | |
| 2474 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
| 2475 | |
| 2476 | box = gtk_hbox_new(TRUE, 0); |
| 2477 | gtk_box_pack_start_defaults(GTK_BOX(box), ui->log_tree); |
| 2478 | g_signal_connect(box, "destroy", G_CALLBACK(view_log_destroy), ui); |
| 2479 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), box); |
| 2480 | |
| 2481 | vbox = gtk_vbox_new(TRUE, 5); |
| 2482 | gtk_box_pack_start_defaults(GTK_BOX(vbox), scroll); |
| 2483 | |
| 2484 | gtk_container_add(GTK_CONTAINER(win), vbox); |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2485 | gtk_widget_show_all(win); |
| 2486 | } |
| 2487 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2488 | static void connect_job_entry(GtkWidget *w, gpointer data) |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2489 | { |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2490 | struct gui *ui = (struct gui *) data; |
| 2491 | struct gui_entry *ge; |
| 2492 | |
| 2493 | ge = get_ge_from_cur_tab(ui); |
| 2494 | if (ge) |
| 2495 | connect_clicked(w, ge); |
| 2496 | } |
| 2497 | |
| 2498 | static void send_job_entry(GtkWidget *w, gpointer data) |
| 2499 | { |
| 2500 | struct gui *ui = (struct gui *) data; |
| 2501 | struct gui_entry *ge; |
| 2502 | |
| 2503 | ge = get_ge_from_cur_tab(ui); |
| 2504 | if (ge) |
| 2505 | send_clicked(w, ge); |
| 2506 | |
| 2507 | } |
| 2508 | |
| 2509 | static void edit_job_entry(GtkWidget *w, gpointer data) |
| 2510 | { |
Jens Axboe | 9af4a24 | 2012-03-16 10:13:49 +0100 | [diff] [blame^] | 2511 | struct gui *ui = (struct gui *) data; |
| 2512 | |
| 2513 | gopt_get_options_window(ui->window); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2514 | } |
| 2515 | |
| 2516 | static void start_job_entry(GtkWidget *w, gpointer data) |
| 2517 | { |
| 2518 | struct gui *ui = (struct gui *) data; |
| 2519 | struct gui_entry *ge; |
| 2520 | |
| 2521 | ge = get_ge_from_cur_tab(ui); |
| 2522 | if (ge) |
| 2523 | start_job_clicked(w, ge); |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2524 | } |
| 2525 | |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 2526 | static void view_results(GtkWidget *w, gpointer data) |
| 2527 | { |
| 2528 | struct gui *ui = (struct gui *) data; |
| 2529 | struct gfio_client *gc; |
| 2530 | struct gui_entry *ge; |
| 2531 | |
| 2532 | ge = get_ge_from_cur_tab(ui); |
| 2533 | if (!ge) |
| 2534 | return; |
| 2535 | |
| 2536 | if (ge->results_window) |
| 2537 | return; |
| 2538 | |
| 2539 | gc = ge->client; |
| 2540 | if (gc && gc->nr_results) |
| 2541 | gfio_display_end_results(gc); |
| 2542 | } |
| 2543 | |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2544 | static void __update_graph_limits(struct gfio_graphs *g) |
| 2545 | { |
| 2546 | line_graph_set_data_count_limit(g->iops_graph, gfio_graph_limit); |
| 2547 | line_graph_set_data_count_limit(g->bandwidth_graph, gfio_graph_limit); |
| 2548 | } |
| 2549 | |
| 2550 | static void update_graph_limits(void) |
| 2551 | { |
| 2552 | struct flist_head *entry; |
| 2553 | struct gui_entry *ge; |
| 2554 | |
| 2555 | __update_graph_limits(&main_ui.graphs); |
| 2556 | |
| 2557 | flist_for_each(entry, &main_ui.list) { |
| 2558 | ge = flist_entry(entry, struct gui_entry, list); |
| 2559 | __update_graph_limits(&ge->graphs); |
| 2560 | } |
| 2561 | } |
| 2562 | |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2563 | static void preferences(GtkWidget *w, gpointer data) |
| 2564 | { |
Jens Axboe | f3e8440 | 2012-03-07 13:14:32 +0100 | [diff] [blame] | 2565 | GtkWidget *dialog, *frame, *box, **buttons, *vbox, *font; |
Jens Axboe | 1cf6bca | 2012-03-09 20:20:17 +0100 | [diff] [blame] | 2566 | GtkWidget *hbox, *spin, *entry, *spin_int; |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2567 | int i; |
| 2568 | |
| 2569 | dialog = gtk_dialog_new_with_buttons("Preferences", |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2570 | GTK_WINDOW(main_ui.window), |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2571 | GTK_DIALOG_DESTROY_WITH_PARENT, |
| 2572 | GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
| 2573 | GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
| 2574 | NULL); |
| 2575 | |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2576 | frame = gtk_frame_new("Graphing"); |
Jens Axboe | f3e8440 | 2012-03-07 13:14:32 +0100 | [diff] [blame] | 2577 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5); |
| 2578 | vbox = gtk_vbox_new(FALSE, 6); |
| 2579 | gtk_container_add(GTK_CONTAINER(frame), vbox); |
| 2580 | |
Jens Axboe | 1cf6bca | 2012-03-09 20:20:17 +0100 | [diff] [blame] | 2581 | hbox = gtk_hbox_new(FALSE, 5); |
| 2582 | gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); |
| 2583 | entry = gtk_label_new("Font face to use for graph labels"); |
| 2584 | gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 5); |
| 2585 | |
Jens Axboe | f3e8440 | 2012-03-07 13:14:32 +0100 | [diff] [blame] | 2586 | font = gtk_font_button_new(); |
Jens Axboe | 1cf6bca | 2012-03-09 20:20:17 +0100 | [diff] [blame] | 2587 | gtk_box_pack_start(GTK_BOX(hbox), font, FALSE, FALSE, 5); |
Jens Axboe | f3e8440 | 2012-03-07 13:14:32 +0100 | [diff] [blame] | 2588 | |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2589 | box = gtk_vbox_new(FALSE, 6); |
| 2590 | gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5); |
| 2591 | |
| 2592 | hbox = gtk_hbox_new(FALSE, 5); |
Jens Axboe | 1cf6bca | 2012-03-09 20:20:17 +0100 | [diff] [blame] | 2593 | gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 5); |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2594 | entry = gtk_label_new("Maximum number of data points in graph (seconds)"); |
| 2595 | gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5); |
| 2596 | |
Jens Axboe | c05d905 | 2012-03-11 13:05:35 +0100 | [diff] [blame] | 2597 | spin = create_spinbutton(hbox, 10, 1000000, gfio_graph_limit); |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2598 | |
Jens Axboe | 1cf6bca | 2012-03-09 20:20:17 +0100 | [diff] [blame] | 2599 | box = gtk_vbox_new(FALSE, 6); |
| 2600 | gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5); |
| 2601 | |
| 2602 | hbox = gtk_hbox_new(FALSE, 5); |
| 2603 | gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 5); |
| 2604 | entry = gtk_label_new("Client ETA request interval (msec)"); |
| 2605 | gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5); |
| 2606 | |
| 2607 | spin_int = create_spinbutton(hbox, 100, 100000, gfio_client_ops.eta_msec); |
Jens Axboe | a31d9fa | 2012-03-09 20:23:05 +0100 | [diff] [blame] | 2608 | frame = gtk_frame_new("Debug logging"); |
| 2609 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5); |
| 2610 | vbox = gtk_vbox_new(FALSE, 6); |
| 2611 | gtk_container_add(GTK_CONTAINER(frame), vbox); |
| 2612 | |
| 2613 | box = gtk_hbox_new(FALSE, 6); |
| 2614 | gtk_container_add(GTK_CONTAINER(vbox), box); |
| 2615 | |
| 2616 | buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX); |
| 2617 | |
| 2618 | for (i = 0; i < FD_DEBUG_MAX; i++) { |
| 2619 | if (i == 7) { |
| 2620 | box = gtk_hbox_new(FALSE, 6); |
| 2621 | gtk_container_add(GTK_CONTAINER(vbox), box); |
| 2622 | } |
| 2623 | |
| 2624 | |
| 2625 | buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name); |
| 2626 | gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help); |
| 2627 | gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6); |
| 2628 | } |
| 2629 | |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2630 | gtk_widget_show_all(dialog); |
| 2631 | |
| 2632 | if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { |
| 2633 | gtk_widget_destroy(dialog); |
| 2634 | return; |
| 2635 | } |
| 2636 | |
| 2637 | for (i = 0; i < FD_DEBUG_MAX; i++) { |
| 2638 | int set; |
| 2639 | |
| 2640 | set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i])); |
| 2641 | if (set) |
| 2642 | fio_debug |= (1UL << i); |
| 2643 | } |
| 2644 | |
Jens Axboe | f3e8440 | 2012-03-07 13:14:32 +0100 | [diff] [blame] | 2645 | gfio_graph_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font))); |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2646 | gfio_graph_limit = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)); |
| 2647 | update_graph_limits(); |
Jens Axboe | 1cf6bca | 2012-03-09 20:20:17 +0100 | [diff] [blame] | 2648 | gfio_client_ops.eta_msec = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_int)); |
Jens Axboe | 8577f4f | 2012-03-09 19:28:27 +0100 | [diff] [blame] | 2649 | |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2650 | gtk_widget_destroy(dialog); |
| 2651 | } |
| 2652 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2653 | static void about_dialog(GtkWidget *w, gpointer data) |
| 2654 | { |
Jens Axboe | 81e4ea6 | 2012-03-07 14:18:28 +0100 | [diff] [blame] | 2655 | const char *authors[] = { |
| 2656 | "Jens Axboe <axboe@kernel.dk>", |
| 2657 | "Stephen Carmeron <stephenmcameron@gmail.com>", |
| 2658 | NULL |
| 2659 | }; |
Jens Axboe | 84a72ed | 2012-03-07 14:24:57 +0100 | [diff] [blame] | 2660 | const char *license[] = { |
| 2661 | "Fio is free software; you can redistribute it and/or modify " |
| 2662 | "it under the terms of the GNU General Public License as published by " |
| 2663 | "the Free Software Foundation; either version 2 of the License, or " |
| 2664 | "(at your option) any later version.\n", |
| 2665 | "Fio is distributed in the hope that it will be useful, " |
| 2666 | "but WITHOUT ANY WARRANTY; without even the implied warranty of " |
| 2667 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " |
| 2668 | "GNU General Public License for more details.\n", |
| 2669 | "You should have received a copy of the GNU General Public License " |
| 2670 | "along with Fio; if not, write to the Free Software Foundation, Inc., " |
| 2671 | "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" |
| 2672 | }; |
| 2673 | char *license_trans; |
| 2674 | |
| 2675 | license_trans = g_strconcat(license[0], "\n", license[1], "\n", |
| 2676 | license[2], "\n", NULL); |
Jens Axboe | 81e4ea6 | 2012-03-07 14:18:28 +0100 | [diff] [blame] | 2677 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2678 | gtk_show_about_dialog(NULL, |
| 2679 | "program-name", "gfio", |
| 2680 | "comments", "Gtk2 UI for fio", |
Jens Axboe | 84a72ed | 2012-03-07 14:24:57 +0100 | [diff] [blame] | 2681 | "license", license_trans, |
Jens Axboe | 81e4ea6 | 2012-03-07 14:18:28 +0100 | [diff] [blame] | 2682 | "website", "http://git.kernel.dk/?p=fio.git;a=summary", |
| 2683 | "authors", authors, |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2684 | "version", fio_version_string, |
Jens Axboe | 81e4ea6 | 2012-03-07 14:18:28 +0100 | [diff] [blame] | 2685 | "copyright", "© 2012 Jens Axboe <axboe@kernel.dk>", |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2686 | "logo-icon-name", "fio", |
| 2687 | /* Must be last: */ |
Jens Axboe | 81e4ea6 | 2012-03-07 14:18:28 +0100 | [diff] [blame] | 2688 | "wrap-license", TRUE, |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2689 | NULL); |
Jens Axboe | 84a72ed | 2012-03-07 14:24:57 +0100 | [diff] [blame] | 2690 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2691 | g_free(license_trans); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2692 | } |
| 2693 | |
| 2694 | static GtkActionEntry menu_items[] = { |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2695 | { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL}, |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2696 | { "ViewMenuAction", GTK_STOCK_FILE, "View", NULL, NULL, NULL}, |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2697 | { "JobMenuAction", GTK_STOCK_FILE, "Job", NULL, NULL, NULL}, |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2698 | { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL}, |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2699 | { "NewFile", GTK_STOCK_NEW, "New", "<Control>N", NULL, G_CALLBACK(file_new) }, |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2700 | { "CloseFile", GTK_STOCK_CLOSE, "Close", "<Control>W", NULL, G_CALLBACK(file_close) }, |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2701 | { "OpenFile", GTK_STOCK_OPEN, NULL, "<Control>O", NULL, G_CALLBACK(file_open) }, |
| 2702 | { "SaveFile", GTK_STOCK_SAVE, NULL, "<Control>S", NULL, G_CALLBACK(file_save) }, |
| 2703 | { "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) }, |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2704 | { "ViewLog", NULL, "Log", "<Control>l", NULL, G_CALLBACK(view_log) }, |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 2705 | { "ViewResults", NULL, "Results", "<Control>R", NULL, G_CALLBACK(view_results) }, |
Jens Axboe | bc271d8 | 2012-03-15 21:57:40 +0100 | [diff] [blame] | 2706 | { "ConnectJob", NULL, "Connect", "<Control>D", NULL, G_CALLBACK(connect_job_entry) }, |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2707 | { "EditJob", NULL, "Edit job", "<Control>E", NULL, G_CALLBACK(edit_job_entry) }, |
| 2708 | { "SendJob", NULL, "Send job", "<Control>X", NULL, G_CALLBACK(send_job_entry) }, |
| 2709 | { "StartJob", NULL, "Start job", "<Control>L", NULL, G_CALLBACK(start_job_entry) }, |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2710 | { "Quit", GTK_STOCK_QUIT, NULL, "<Control>Q", NULL, G_CALLBACK(quit_clicked) }, |
| 2711 | { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) }, |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2712 | }; |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2713 | static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2714 | |
| 2715 | static const gchar *ui_string = " \ |
| 2716 | <ui> \ |
| 2717 | <menubar name=\"MainMenu\"> \ |
| 2718 | <menu name=\"FileMenu\" action=\"FileMenuAction\"> \ |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2719 | <menuitem name=\"New\" action=\"NewFile\" /> \ |
Jens Axboe | bf64138 | 2012-03-15 13:46:16 +0100 | [diff] [blame] | 2720 | <menuitem name=\"Open\" action=\"OpenFile\" /> \ |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2721 | <menuitem name=\"Close\" action=\"CloseFile\" /> \ |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2722 | <separator name=\"Separator1\"/> \ |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2723 | <menuitem name=\"Save\" action=\"SaveFile\" /> \ |
Jens Axboe | 46974a7 | 2012-03-02 19:34:13 +0100 | [diff] [blame] | 2724 | <separator name=\"Separator2\"/> \ |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2725 | <menuitem name=\"Preferences\" action=\"Preferences\" /> \ |
| 2726 | <separator name=\"Separator3\"/> \ |
Jens Axboe | 261f21d | 2012-03-12 14:58:22 +0100 | [diff] [blame] | 2727 | <placeholder name=\"FileRecentFiles\"/> \ |
| 2728 | <separator name=\"Separator4\"/> \ |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2729 | <menuitem name=\"Quit\" action=\"Quit\" /> \ |
| 2730 | </menu> \ |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2731 | <menu name=\"JobMenu\" action=\"JobMenuAction\"> \ |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2732 | <menuitem name=\"Connect\" action=\"ConnectJob\" /> \ |
Jens Axboe | 261f21d | 2012-03-12 14:58:22 +0100 | [diff] [blame] | 2733 | <separator name=\"Separator5\"/> \ |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2734 | <menuitem name=\"Edit job\" action=\"EditJob\" /> \ |
| 2735 | <menuitem name=\"Send job\" action=\"SendJob\" /> \ |
Jens Axboe | 261f21d | 2012-03-12 14:58:22 +0100 | [diff] [blame] | 2736 | <separator name=\"Separator6\"/> \ |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2737 | <menuitem name=\"Start job\" action=\"StartJob\" /> \ |
Jens Axboe | 16ce5ad | 2012-03-12 11:56:09 +0100 | [diff] [blame] | 2738 | </menu>\ |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2739 | <menu name=\"ViewMenu\" action=\"ViewMenuAction\"> \ |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 2740 | <menuitem name=\"Results\" action=\"ViewResults\" /> \ |
| 2741 | <separator name=\"Separator7\"/> \ |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 2742 | <menuitem name=\"Log\" action=\"ViewLog\" /> \ |
| 2743 | </menu>\ |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2744 | <menu name=\"Help\" action=\"HelpMenuAction\"> \ |
| 2745 | <menuitem name=\"About\" action=\"About\" /> \ |
| 2746 | </menu> \ |
| 2747 | </menubar> \ |
| 2748 | </ui> \ |
| 2749 | "; |
| 2750 | |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2751 | static GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager, |
| 2752 | struct gui *ui) |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2753 | { |
Jens Axboe | ca664f4 | 2012-03-14 19:49:40 +0100 | [diff] [blame] | 2754 | GtkActionGroup *action_group; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2755 | GError *error = 0; |
| 2756 | |
| 2757 | action_group = gtk_action_group_new("Menu"); |
Jens Axboe | 4cbe721 | 2012-03-06 13:36:17 +0100 | [diff] [blame] | 2758 | gtk_action_group_add_actions(action_group, menu_items, nmenu_items, ui); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2759 | |
| 2760 | gtk_ui_manager_insert_action_group(ui_manager, action_group, 0); |
| 2761 | gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error); |
| 2762 | |
| 2763 | gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager)); |
Jens Axboe | 02421e6 | 2012-03-12 12:05:50 +0100 | [diff] [blame] | 2764 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2765 | return gtk_ui_manager_get_widget(ui_manager, "/MainMenu"); |
| 2766 | } |
| 2767 | |
| 2768 | void gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar, |
| 2769 | GtkWidget *vbox, GtkUIManager *ui_manager) |
| 2770 | { |
| 2771 | gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); |
| 2772 | } |
| 2773 | |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 2774 | static void combo_entry_changed(GtkComboBox *box, gpointer data) |
| 2775 | { |
| 2776 | struct gui_entry *ge = (struct gui_entry *) data; |
| 2777 | gint index; |
| 2778 | |
| 2779 | index = gtk_combo_box_get_active(box); |
| 2780 | |
| 2781 | multitext_set_entry(&ge->eta.iotype, index); |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 2782 | multitext_set_entry(&ge->eta.bs, index); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 2783 | multitext_set_entry(&ge->eta.ioengine, index); |
| 2784 | multitext_set_entry(&ge->eta.iodepth, index); |
| 2785 | } |
| 2786 | |
| 2787 | static void combo_entry_destroy(GtkWidget *widget, gpointer data) |
| 2788 | { |
| 2789 | struct gui_entry *ge = (struct gui_entry *) data; |
| 2790 | |
| 2791 | multitext_free(&ge->eta.iotype); |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 2792 | multitext_free(&ge->eta.bs); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 2793 | multitext_free(&ge->eta.ioengine); |
| 2794 | multitext_free(&ge->eta.iodepth); |
| 2795 | } |
| 2796 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2797 | static GtkWidget *new_client_page(struct gui_entry *ge) |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 2798 | { |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2799 | GtkWidget *main_vbox, *probe, *probe_frame, *probe_box; |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2800 | GtkWidget *scrolled_window, *bottom_align, *top_align, *top_vbox; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 2801 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2802 | main_vbox = gtk_vbox_new(FALSE, 3); |
Stephen M. Cameron | 45032dd | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 2803 | |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2804 | top_align = gtk_alignment_new(0, 0, 1, 0); |
| 2805 | top_vbox = gtk_vbox_new(FALSE, 3); |
| 2806 | gtk_container_add(GTK_CONTAINER(top_align), top_vbox); |
| 2807 | gtk_box_pack_start(GTK_BOX(main_vbox), top_align, FALSE, FALSE, 0); |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2808 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2809 | probe = gtk_frame_new("Job"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2810 | gtk_box_pack_start(GTK_BOX(main_vbox), probe, FALSE, FALSE, 3); |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 2811 | probe_frame = gtk_vbox_new(FALSE, 3); |
| 2812 | gtk_container_add(GTK_CONTAINER(probe), probe_frame); |
| 2813 | |
| 2814 | probe_box = gtk_hbox_new(FALSE, 3); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2815 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3); |
| 2816 | ge->probe.hostname = new_info_label_in_frame(probe_box, "Host"); |
| 2817 | ge->probe.os = new_info_label_in_frame(probe_box, "OS"); |
| 2818 | ge->probe.arch = new_info_label_in_frame(probe_box, "Architecture"); |
| 2819 | ge->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version"); |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 2820 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2821 | probe_box = gtk_hbox_new(FALSE, 3); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2822 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3); |
| 2823 | |
Jens Axboe | 3863d1a | 2012-03-09 17:39:05 +0100 | [diff] [blame] | 2824 | ge->eta.names = new_combo_entry_in_frame(probe_box, "Jobs"); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 2825 | g_signal_connect(ge->eta.names, "changed", G_CALLBACK(combo_entry_changed), ge); |
| 2826 | g_signal_connect(ge->eta.names, "destroy", G_CALLBACK(combo_entry_destroy), ge); |
| 2827 | ge->eta.iotype.entry = new_info_entry_in_frame(probe_box, "IO"); |
Jens Axboe | 99d633a | 2012-03-15 15:55:04 +0100 | [diff] [blame] | 2828 | ge->eta.bs.entry = new_info_entry_in_frame(probe_box, "Blocksize (Read/Write)"); |
Jens Axboe | c80b74b | 2012-03-12 10:23:28 +0100 | [diff] [blame] | 2829 | ge->eta.ioengine.entry = new_info_entry_in_frame(probe_box, "IO Engine"); |
| 2830 | ge->eta.iodepth.entry = new_info_entry_in_frame(probe_box, "IO Depth"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2831 | ge->eta.jobs = new_info_entry_in_frame(probe_box, "Jobs"); |
| 2832 | ge->eta.files = new_info_entry_in_frame(probe_box, "Open files"); |
| 2833 | |
| 2834 | probe_box = gtk_hbox_new(FALSE, 3); |
| 2835 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3); |
| 2836 | ge->eta.read_bw = new_info_entry_in_frame(probe_box, "Read BW"); |
| 2837 | ge->eta.read_iops = new_info_entry_in_frame(probe_box, "IOPS"); |
| 2838 | ge->eta.write_bw = new_info_entry_in_frame(probe_box, "Write BW"); |
| 2839 | ge->eta.write_iops = new_info_entry_in_frame(probe_box, "IOPS"); |
| 2840 | |
| 2841 | /* |
| 2842 | * Only add this if we have a commit rate |
| 2843 | */ |
| 2844 | #if 0 |
| 2845 | probe_box = gtk_hbox_new(FALSE, 3); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2846 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 2847 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2848 | ge->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW"); |
| 2849 | ge->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); |
| 2850 | |
| 2851 | ge->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW"); |
| 2852 | ge->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); |
| 2853 | #endif |
| 2854 | |
| 2855 | /* |
| 2856 | * Set up a drawing area and IOPS and bandwidth graphs |
| 2857 | */ |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2858 | ge->graphs.drawing_area = gtk_drawing_area_new(); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2859 | gtk_widget_set_size_request(GTK_WIDGET(ge->graphs.drawing_area), |
Stephen M. Cameron | 57f9d28 | 2012-03-11 11:36:51 +0100 | [diff] [blame] | 2860 | DRAWING_AREA_XDIM, DRAWING_AREA_YDIM); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2861 | gtk_widget_modify_bg(ge->graphs.drawing_area, GTK_STATE_NORMAL, &white); |
| 2862 | g_signal_connect(G_OBJECT(ge->graphs.drawing_area), "expose_event", |
| 2863 | G_CALLBACK(on_expose_drawing_area), &ge->graphs); |
| 2864 | g_signal_connect(G_OBJECT(ge->graphs.drawing_area), "configure_event", |
| 2865 | G_CALLBACK(on_config_drawing_area), &ge->graphs); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2866 | scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
| 2867 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2868 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2869 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2870 | ge->graphs.drawing_area); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2871 | gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_window, TRUE, TRUE, 0); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2872 | |
| 2873 | setup_graphs(&ge->graphs); |
| 2874 | |
| 2875 | /* |
| 2876 | * Set up alignments for widgets at the bottom of ui, |
| 2877 | * align bottom left, expand horizontally but not vertically |
| 2878 | */ |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2879 | bottom_align = gtk_alignment_new(0, 1, 1, 0); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2880 | ge->buttonbox = gtk_hbox_new(FALSE, 0); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2881 | gtk_container_add(GTK_CONTAINER(bottom_align), ge->buttonbox); |
| 2882 | gtk_box_pack_start(GTK_BOX(main_vbox), bottom_align, FALSE, FALSE, 0); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2883 | |
| 2884 | add_buttons(ge, buttonspeclist, ARRAYSIZE(buttonspeclist)); |
| 2885 | |
| 2886 | /* |
| 2887 | * Set up thread status progress bar |
| 2888 | */ |
| 2889 | ge->thread_status_pb = gtk_progress_bar_new(); |
| 2890 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), 0.0); |
| 2891 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), "No connections"); |
| 2892 | gtk_container_add(GTK_CONTAINER(ge->buttonbox), ge->thread_status_pb); |
| 2893 | |
| 2894 | |
| 2895 | return main_vbox; |
| 2896 | } |
| 2897 | |
| 2898 | static GtkWidget *new_main_page(struct gui *ui) |
| 2899 | { |
| 2900 | GtkWidget *main_vbox, *probe, *probe_frame, *probe_box; |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2901 | GtkWidget *scrolled_window, *bottom_align, *top_align, *top_vbox; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2902 | |
| 2903 | main_vbox = gtk_vbox_new(FALSE, 3); |
| 2904 | |
| 2905 | /* |
| 2906 | * Set up alignments for widgets at the top of ui, |
| 2907 | * align top left, expand horizontally but not vertically |
| 2908 | */ |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2909 | top_align = gtk_alignment_new(0, 0, 1, 0); |
| 2910 | top_vbox = gtk_vbox_new(FALSE, 0); |
| 2911 | gtk_container_add(GTK_CONTAINER(top_align), top_vbox); |
| 2912 | gtk_box_pack_start(GTK_BOX(main_vbox), top_align, FALSE, FALSE, 0); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2913 | |
| 2914 | probe = gtk_frame_new("Run statistics"); |
| 2915 | gtk_box_pack_start(GTK_BOX(main_vbox), probe, FALSE, FALSE, 3); |
| 2916 | probe_frame = gtk_vbox_new(FALSE, 3); |
| 2917 | gtk_container_add(GTK_CONTAINER(probe), probe_frame); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2918 | |
| 2919 | probe_box = gtk_hbox_new(FALSE, 3); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2920 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3); |
Jens Axboe | 3863d1a | 2012-03-09 17:39:05 +0100 | [diff] [blame] | 2921 | ui->eta.jobs = new_info_entry_in_frame(probe_box, "Running"); |
Jens Axboe | ca85099 | 2012-03-05 20:04:43 +0100 | [diff] [blame] | 2922 | ui->eta.read_bw = new_info_entry_in_frame(probe_box, "Read BW"); |
| 2923 | ui->eta.read_iops = new_info_entry_in_frame(probe_box, "IOPS"); |
| 2924 | ui->eta.write_bw = new_info_entry_in_frame(probe_box, "Write BW"); |
| 2925 | ui->eta.write_iops = new_info_entry_in_frame(probe_box, "IOPS"); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 2926 | |
| 2927 | /* |
| 2928 | * Only add this if we have a commit rate |
| 2929 | */ |
| 2930 | #if 0 |
| 2931 | probe_box = gtk_hbox_new(FALSE, 3); |
| 2932 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3); |
| 2933 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2934 | ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW"); |
| 2935 | ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); |
| 2936 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2937 | ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW"); |
| 2938 | ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 2939 | #endif |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 2940 | |
Stephen M. Cameron | 45032dd | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 2941 | /* |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 2942 | * Set up a drawing area and IOPS and bandwidth graphs |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2943 | */ |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2944 | ui->graphs.drawing_area = gtk_drawing_area_new(); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2945 | gtk_widget_set_size_request(GTK_WIDGET(ui->graphs.drawing_area), |
Stephen M. Cameron | 57f9d28 | 2012-03-11 11:36:51 +0100 | [diff] [blame] | 2946 | DRAWING_AREA_XDIM, DRAWING_AREA_YDIM); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2947 | gtk_widget_modify_bg(ui->graphs.drawing_area, GTK_STATE_NORMAL, &white); |
| 2948 | g_signal_connect(G_OBJECT(ui->graphs.drawing_area), "expose_event", |
| 2949 | G_CALLBACK(on_expose_drawing_area), &ui->graphs); |
| 2950 | g_signal_connect(G_OBJECT(ui->graphs.drawing_area), "configure_event", |
| 2951 | G_CALLBACK(on_config_drawing_area), &ui->graphs); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2952 | scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
| 2953 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2954 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2955 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2956 | ui->graphs.drawing_area); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2957 | gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_window, |
Stephen M. Cameron | e164534 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2958 | TRUE, TRUE, 0); |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2959 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2960 | setup_graphs(&ui->graphs); |
Jens Axboe | 2fd3bb0 | 2012-03-07 08:07:39 +0100 | [diff] [blame] | 2961 | |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2962 | /* |
| 2963 | * Set up alignments for widgets at the bottom of ui, |
| 2964 | * align bottom left, expand horizontally but not vertically |
| 2965 | */ |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2966 | bottom_align = gtk_alignment_new(0, 1, 1, 0); |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2967 | ui->buttonbox = gtk_hbox_new(FALSE, 0); |
Jens Axboe | 6547633 | 2012-03-13 10:37:04 +0100 | [diff] [blame] | 2968 | gtk_container_add(GTK_CONTAINER(bottom_align), ui->buttonbox); |
| 2969 | gtk_box_pack_start(GTK_BOX(main_vbox), bottom_align, FALSE, FALSE, 0); |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 2970 | |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 2971 | /* |
| 2972 | * Set up thread status progress bar |
| 2973 | */ |
| 2974 | ui->thread_status_pb = gtk_progress_bar_new(); |
| 2975 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0); |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 2976 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections"); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 2977 | gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb); |
| 2978 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 2979 | return main_vbox; |
| 2980 | } |
| 2981 | |
| 2982 | static gboolean notebook_switch_page(GtkNotebook *notebook, GtkWidget *widget, |
| 2983 | guint page, gpointer data) |
| 2984 | |
| 2985 | { |
Jens Axboe | 02421e6 | 2012-03-12 12:05:50 +0100 | [diff] [blame] | 2986 | struct gui *ui = (struct gui *) data; |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2987 | struct gui_entry *ge; |
Jens Axboe | 02421e6 | 2012-03-12 12:05:50 +0100 | [diff] [blame] | 2988 | |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2989 | if (!page) { |
| 2990 | set_job_menu_visible(ui, 0); |
Jens Axboe | 781ccba | 2012-03-15 09:44:42 +0100 | [diff] [blame] | 2991 | set_view_results_visible(ui, 0); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2992 | return TRUE; |
| 2993 | } |
| 2994 | |
| 2995 | set_job_menu_visible(ui, 1); |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 2996 | ge = get_ge_from_page(page, NULL); |
Jens Axboe | 85dd01e | 2012-03-12 14:33:16 +0100 | [diff] [blame] | 2997 | if (ge) |
| 2998 | update_button_states(ui, ge); |
| 2999 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3000 | return TRUE; |
| 3001 | } |
| 3002 | |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 3003 | static gint compare_recent_items(GtkRecentInfo *a, GtkRecentInfo *b) |
| 3004 | { |
| 3005 | time_t time_a = gtk_recent_info_get_visited(a); |
| 3006 | time_t time_b = gtk_recent_info_get_visited(b); |
| 3007 | |
| 3008 | return time_b - time_a; |
| 3009 | } |
| 3010 | |
| 3011 | static void add_recent_file_items(struct gui *ui) |
| 3012 | { |
| 3013 | const gchar *gfio = g_get_application_name(); |
| 3014 | GList *items, *item; |
| 3015 | int i = 0; |
| 3016 | |
| 3017 | if (ui->recent_ui_id) { |
| 3018 | gtk_ui_manager_remove_ui(ui->uimanager, ui->recent_ui_id); |
| 3019 | gtk_ui_manager_ensure_update(ui->uimanager); |
| 3020 | } |
| 3021 | ui->recent_ui_id = gtk_ui_manager_new_merge_id(ui->uimanager); |
| 3022 | |
| 3023 | if (ui->actiongroup) { |
| 3024 | gtk_ui_manager_remove_action_group(ui->uimanager, ui->actiongroup); |
| 3025 | g_object_unref(ui->actiongroup); |
| 3026 | } |
| 3027 | ui->actiongroup = gtk_action_group_new("RecentFileActions"); |
| 3028 | |
| 3029 | gtk_ui_manager_insert_action_group(ui->uimanager, ui->actiongroup, -1); |
| 3030 | |
| 3031 | items = gtk_recent_manager_get_items(ui->recentmanager); |
| 3032 | items = g_list_sort(items, (GCompareFunc) compare_recent_items); |
| 3033 | |
| 3034 | for (item = items; item && item->data; item = g_list_next(item)) { |
| 3035 | GtkRecentInfo *info = (GtkRecentInfo *) item->data; |
| 3036 | gchar *action_name; |
| 3037 | const gchar *label; |
| 3038 | GtkAction *action; |
| 3039 | |
| 3040 | if (!gtk_recent_info_has_application(info, gfio)) |
| 3041 | continue; |
| 3042 | |
| 3043 | /* |
| 3044 | * We only support local files for now |
| 3045 | */ |
| 3046 | if (!gtk_recent_info_is_local(info) || !gtk_recent_info_exists(info)) |
| 3047 | continue; |
| 3048 | |
| 3049 | action_name = g_strdup_printf("RecentFile%u", i++); |
| 3050 | label = gtk_recent_info_get_display_name(info); |
| 3051 | |
| 3052 | action = g_object_new(GTK_TYPE_ACTION, |
| 3053 | "name", action_name, |
| 3054 | "label", label, NULL); |
| 3055 | |
| 3056 | g_object_set_data_full(G_OBJECT(action), "gtk-recent-info", |
| 3057 | gtk_recent_info_ref(info), |
| 3058 | (GDestroyNotify) gtk_recent_info_unref); |
| 3059 | |
| 3060 | |
| 3061 | g_signal_connect(action, "activate", G_CALLBACK(recent_open), ui); |
| 3062 | |
| 3063 | gtk_action_group_add_action(ui->actiongroup, action); |
| 3064 | g_object_unref(action); |
| 3065 | |
| 3066 | gtk_ui_manager_add_ui(ui->uimanager, ui->recent_ui_id, |
| 3067 | "/MainMenu/FileMenu/FileRecentFiles", |
| 3068 | label, action_name, |
| 3069 | GTK_UI_MANAGER_MENUITEM, FALSE); |
| 3070 | |
| 3071 | g_free(action_name); |
| 3072 | |
| 3073 | if (i == 8) |
| 3074 | break; |
| 3075 | } |
| 3076 | |
| 3077 | g_list_foreach(items, (GFunc) gtk_recent_info_unref, NULL); |
| 3078 | g_list_free(items); |
| 3079 | } |
| 3080 | |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 3081 | static void drag_and_drop_received(GtkWidget *widget, GdkDragContext *ctx, |
| 3082 | gint x, gint y, GtkSelectionData *data, |
| 3083 | guint info, guint time) |
| 3084 | { |
| 3085 | struct gui *ui = &main_ui; |
| 3086 | gchar **uris; |
| 3087 | GtkWidget *source; |
| 3088 | int i; |
| 3089 | |
| 3090 | source = gtk_drag_get_source_widget(ctx); |
| 3091 | if (source && widget == gtk_widget_get_toplevel(source)) { |
| 3092 | gtk_drag_finish(ctx, FALSE, FALSE, time); |
| 3093 | return; |
| 3094 | } |
| 3095 | |
| 3096 | uris = gtk_selection_data_get_uris(data); |
| 3097 | if (!uris) { |
| 3098 | gtk_drag_finish(ctx, FALSE, FALSE, time); |
| 3099 | return; |
| 3100 | } |
| 3101 | |
| 3102 | i = 0; |
| 3103 | while (uris[i]) { |
| 3104 | if (do_file_open_with_tab(ui, uris[i])) |
| 3105 | break; |
| 3106 | i++; |
| 3107 | } |
| 3108 | |
| 3109 | gtk_drag_finish(ctx, TRUE, FALSE, time); |
| 3110 | g_strfreev(uris); |
| 3111 | } |
| 3112 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3113 | static void init_ui(int *argc, char **argv[], struct gui *ui) |
| 3114 | { |
| 3115 | GtkSettings *settings; |
Jens Axboe | 02421e6 | 2012-03-12 12:05:50 +0100 | [diff] [blame] | 3116 | GtkWidget *vbox; |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3117 | |
| 3118 | /* Magical g*thread incantation, you just need this thread stuff. |
| 3119 | * Without it, the update that happens in gfio_update_thread_status |
| 3120 | * doesn't really happen in a timely fashion, you need expose events |
| 3121 | */ |
| 3122 | if (!g_thread_supported()) |
| 3123 | g_thread_init(NULL); |
| 3124 | gdk_threads_init(); |
| 3125 | |
| 3126 | gtk_init(argc, argv); |
| 3127 | settings = gtk_settings_get_default(); |
| 3128 | gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting"); |
| 3129 | g_type_init(); |
Stephen M. Cameron | 814479d | 2012-03-15 07:58:14 +0100 | [diff] [blame] | 3130 | gdk_color_parse("white", &white); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3131 | |
| 3132 | ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
Stephen M. Cameron | 814479d | 2012-03-15 07:58:14 +0100 | [diff] [blame] | 3133 | gtk_window_set_title(GTK_WINDOW(ui->window), "fio"); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3134 | gtk_window_set_default_size(GTK_WINDOW(ui->window), 1024, 768); |
| 3135 | |
| 3136 | g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL); |
| 3137 | g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL); |
| 3138 | |
| 3139 | ui->vbox = gtk_vbox_new(FALSE, 0); |
| 3140 | gtk_container_add(GTK_CONTAINER(ui->window), ui->vbox); |
| 3141 | |
Jens Axboe | 02421e6 | 2012-03-12 12:05:50 +0100 | [diff] [blame] | 3142 | ui->uimanager = gtk_ui_manager_new(); |
| 3143 | ui->menu = get_menubar_menu(ui->window, ui->uimanager, ui); |
| 3144 | gfio_ui_setup(settings, ui->menu, ui->vbox, ui->uimanager); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3145 | |
Jens Axboe | 38634cb | 2012-03-13 12:26:41 +0100 | [diff] [blame] | 3146 | ui->recentmanager = gtk_recent_manager_get_default(); |
| 3147 | add_recent_file_items(ui); |
| 3148 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3149 | ui->notebook = gtk_notebook_new(); |
| 3150 | g_signal_connect(ui->notebook, "switch-page", G_CALLBACK(notebook_switch_page), ui); |
Jens Axboe | b870c31 | 2012-03-09 17:22:01 +0100 | [diff] [blame] | 3151 | gtk_notebook_set_scrollable(GTK_NOTEBOOK(ui->notebook), 1); |
Jens Axboe | 0aa928c | 2012-03-09 17:24:07 +0100 | [diff] [blame] | 3152 | gtk_notebook_popup_enable(GTK_NOTEBOOK(ui->notebook)); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3153 | gtk_container_add(GTK_CONTAINER(ui->vbox), ui->notebook); |
| 3154 | |
| 3155 | vbox = new_main_page(ui); |
Jens Axboe | a679090 | 2012-03-13 15:16:11 +0100 | [diff] [blame] | 3156 | gtk_drag_dest_set(GTK_WIDGET(ui->window), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY); |
| 3157 | gtk_drag_dest_add_uri_targets(GTK_WIDGET(ui->window)); |
| 3158 | g_signal_connect(ui->window, "drag-data-received", G_CALLBACK(drag_and_drop_received), ui); |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3159 | |
| 3160 | gtk_notebook_append_page(GTK_NOTEBOOK(ui->notebook), vbox, gtk_label_new("Main")); |
| 3161 | |
Jens Axboe | 9b260bd | 2012-03-06 11:02:52 +0100 | [diff] [blame] | 3162 | gfio_ui_setup_log(ui); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 3163 | |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 3164 | gtk_widget_show_all(ui->window); |
| 3165 | } |
| 3166 | |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 3167 | int main(int argc, char *argv[], char *envp[]) |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 3168 | { |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 3169 | if (initialize_fio(envp)) |
| 3170 | return 1; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 3171 | if (fio_init_options()) |
| 3172 | return 1; |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 3173 | |
Jens Axboe | 2f99deb | 2012-03-09 14:37:29 +0100 | [diff] [blame] | 3174 | memset(&main_ui, 0, sizeof(main_ui)); |
| 3175 | INIT_FLIST_HEAD(&main_ui.list); |
| 3176 | |
| 3177 | init_ui(&argc, &argv, &main_ui); |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 3178 | |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 3179 | gdk_threads_enter(); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 3180 | gtk_main(); |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 3181 | gdk_threads_leave(); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 3182 | return 0; |
| 3183 | } |