blob: 0d18ef6feb0bad561733ed59e7dd841ee72c76a5 [file] [log] [blame]
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001/*
2 * gfio - gui front end for fio - the flexible io tester
3 *
4 * Copyright (C) 2012 Stephen M. Cameron <stephenmcameron@gmail.com>
5 *
6 * The license below covers all files distributed with fio unless otherwise
7 * noted in the file itself.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
Stephen M. Cameron8232e282012-02-24 08:17:31 +010023#include <locale.h>
Stephen M. Cameron60f6b332012-02-24 08:17:32 +010024#include <malloc.h>
Stephen M. Cameron8232e282012-02-24 08:17:31 +010025
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +010026#include <glib.h>
Stephen M. Cameronff1f3282012-02-24 08:17:30 +010027#include <gtk/gtk.h>
28
Stephen M. Cameron8232e282012-02-24 08:17:31 +010029#include "fio.h"
30
Jens Axboe3e47bd22012-02-29 13:45:02 +010031static void gfio_update_thread_status(char *status_message, double perc);
32
Stephen M. Cameronf3074002012-02-24 08:17:30 +010033#define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0])))
34
35typedef void (*clickfunction)(GtkWidget *widget, gpointer data);
36
Jens Axboe3e47bd22012-02-29 13:45:02 +010037static void connect_clicked(GtkWidget *widget, gpointer data);
Stephen M. Cameronf3074002012-02-24 08:17:30 +010038static void start_job_clicked(GtkWidget *widget, gpointer data);
39
40static struct button_spec {
41 const char *buttontext;
42 clickfunction f;
43 const char *tooltiptext;
Jens Axboe3e47bd22012-02-29 13:45:02 +010044 const int start_insensitive;
Stephen M. Cameronf3074002012-02-24 08:17:30 +010045} buttonspeclist[] = {
Jens Axboe3e47bd22012-02-29 13:45:02 +010046#define CONNECT_BUTTON 0
47#define START_JOB_BUTTON 1
48 { "Connect", connect_clicked, "Connect to host", 0 },
Stephen M. Cameronf3074002012-02-24 08:17:30 +010049 { "Start Job",
50 start_job_clicked,
Jens Axboe3e47bd22012-02-29 13:45:02 +010051 "Send current fio job to fio server to be executed", 1 },
Stephen M. Cameronf3074002012-02-24 08:17:30 +010052};
53
Jens Axboe843ad232012-02-29 11:44:53 +010054struct probe_widget {
55 GtkWidget *hostname;
56 GtkWidget *os;
57 GtkWidget *arch;
58 GtkWidget *fio_ver;
59};
60
Jens Axboe3e47bd22012-02-29 13:45:02 +010061struct eta_widget {
Jens Axboe807f9972012-03-02 10:25:24 +010062 GtkWidget *name;
63 GtkWidget *iotype;
64 GtkWidget *ioengine;
65 GtkWidget *iodepth;
Jens Axboe3e47bd22012-02-29 13:45:02 +010066 GtkWidget *jobs;
67 GtkWidget *files;
68 GtkWidget *read_bw;
69 GtkWidget *read_iops;
70 GtkWidget *cr_bw;
71 GtkWidget *cr_iops;
72 GtkWidget *write_bw;
73 GtkWidget *write_iops;
74 GtkWidget *cw_bw;
75 GtkWidget *cw_iops;
76};
77
Stephen M. Cameronff1f3282012-02-24 08:17:30 +010078struct gui {
79 GtkWidget *window;
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +010080 GtkWidget *vbox;
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +010081 GtkWidget *topvbox;
82 GtkWidget *topalign;
83 GtkWidget *bottomalign;
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +010084 GtkWidget *thread_status_pb;
Stephen M. Cameronf3074002012-02-24 08:17:30 +010085 GtkWidget *buttonbox;
86 GtkWidget *button[ARRAYSIZE(buttonspeclist)];
Stephen M. Cameron736f2df2012-02-24 08:17:32 +010087 GtkWidget *scrolled_window;
88 GtkWidget *textview;
Jens Axboe0420ba62012-02-29 11:16:52 +010089 GtkWidget *error_info_bar;
90 GtkWidget *error_label;
Jens Axboef9d40b42012-03-06 09:52:49 +010091 GtkWidget *results_notebook;
92 GtkWidget *results_window;
Jens Axboe9b260bd2012-03-06 11:02:52 +010093 GtkListStore *log_model;
94 GtkWidget *log_tree;
Jens Axboe4cbe7212012-03-06 13:36:17 +010095 GtkWidget *log_view;
Stephen M. Cameron736f2df2012-02-24 08:17:32 +010096 GtkTextBuffer *text;
Jens Axboe843ad232012-02-29 11:44:53 +010097 struct probe_widget probe;
Jens Axboe3e47bd22012-02-29 13:45:02 +010098 struct eta_widget eta;
Jens Axboe3ec62ec2012-03-01 12:01:29 +010099 int connected;
Stephen M. Cameron25927252012-02-24 08:17:31 +0100100 pthread_t t;
Jens Axboe0420ba62012-02-29 11:16:52 +0100101
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100102 struct fio_client *client;
Jens Axboe0420ba62012-02-29 11:16:52 +0100103 int nr_job_files;
104 char **job_files;
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100105} ui;
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100106
Jens Axboee0681f32012-03-06 12:14:42 +0100107struct gfio_client {
108 struct gui *ui;
109 GtkWidget *results_widget;
110 GtkWidget *disk_util_frame;
111};
112
Jens Axboe8663ea62012-03-02 14:04:30 +0100113static void clear_ui_info(struct gui *ui)
114{
115 gtk_label_set_text(GTK_LABEL(ui->probe.hostname), "");
116 gtk_label_set_text(GTK_LABEL(ui->probe.os), "");
117 gtk_label_set_text(GTK_LABEL(ui->probe.arch), "");
118 gtk_label_set_text(GTK_LABEL(ui->probe.fio_ver), "");
Jens Axboeca850992012-03-05 20:04:43 +0100119 gtk_entry_set_text(GTK_ENTRY(ui->eta.name), "");
120 gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), "");
121 gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), "");
122 gtk_entry_set_text(GTK_ENTRY(ui->eta.iodepth), "");
123 gtk_entry_set_text(GTK_ENTRY(ui->eta.jobs), "");
124 gtk_entry_set_text(GTK_ENTRY(ui->eta.files), "");
125 gtk_entry_set_text(GTK_ENTRY(ui->eta.read_bw), "");
126 gtk_entry_set_text(GTK_ENTRY(ui->eta.read_iops), "");
127 gtk_entry_set_text(GTK_ENTRY(ui->eta.write_bw), "");
128 gtk_entry_set_text(GTK_ENTRY(ui->eta.write_iops), "");
Jens Axboe8663ea62012-03-02 14:04:30 +0100129}
130
Jens Axboe3650a3c2012-03-05 14:09:03 +0100131static GtkWidget *new_info_entry_in_frame(GtkWidget *box, const char *label)
132{
133 GtkWidget *entry, *frame;
134
135 frame = gtk_frame_new(label);
136 entry = gtk_entry_new();
Jens Axboe1c1e4a52012-03-05 14:37:38 +0100137 gtk_entry_set_editable(GTK_ENTRY(entry), 0);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100138 gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
139 gtk_container_add(GTK_CONTAINER(frame), entry);
140
141 return entry;
142}
143
144static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
145{
146 GtkWidget *label_widget;
147 GtkWidget *frame;
148
149 frame = gtk_frame_new(label);
150 label_widget = gtk_label_new(NULL);
151 gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
152 gtk_container_add(GTK_CONTAINER(frame), label_widget);
153
154 return label_widget;
155}
156
157static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, double defval)
158{
159 GtkWidget *button, *box;
160
161 box = gtk_hbox_new(FALSE, 3);
162 gtk_container_add(GTK_CONTAINER(hbox), box);
163
164 button = gtk_spin_button_new_with_range(min, max, 1.0);
165 gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
166
167 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID);
168 gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), defval);
169
170 return button;
171}
172
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100173static void gfio_set_connected(struct gui *ui, int connected)
174{
175 if (connected) {
176 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
177 ui->connected = 1;
178 gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect");
Jens Axboe88f6e7a2012-03-06 12:55:29 +0100179 gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100180 } else {
181 ui->connected = 0;
182 gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect");
183 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
184 }
185}
186
Jens Axboe3650a3c2012-03-05 14:09:03 +0100187static void label_set_int_value(GtkWidget *entry, unsigned int val)
188{
189 char tmp[80];
190
191 sprintf(tmp, "%u", val);
192 gtk_label_set_text(GTK_LABEL(entry), tmp);
193}
194
195static void entry_set_int_value(GtkWidget *entry, unsigned int val)
196{
197 char tmp[80];
198
199 sprintf(tmp, "%u", val);
200 gtk_entry_set_text(GTK_ENTRY(entry), tmp);
201}
202
Jens Axboea2697902012-03-05 16:43:49 +0100203#define ALIGN_LEFT 1
204#define ALIGN_RIGHT 2
205#define INVISIBLE 4
206#define UNSORTABLE 8
207
208GtkTreeViewColumn *tree_view_column(GtkWidget *tree_view, int index, const char *title, unsigned int flags)
209{
210 GtkCellRenderer *renderer;
211 GtkTreeViewColumn *col;
212 double xalign = 0.0; /* left as default */
213 PangoAlignment align;
214 gboolean visible;
215
216 align = (flags & ALIGN_LEFT) ? PANGO_ALIGN_LEFT :
217 (flags & ALIGN_RIGHT) ? PANGO_ALIGN_RIGHT :
218 PANGO_ALIGN_CENTER;
219 visible = !(flags & INVISIBLE);
220
221 renderer = gtk_cell_renderer_text_new();
222 col = gtk_tree_view_column_new();
223
224 gtk_tree_view_column_set_title(col, title);
225 if (!(flags & UNSORTABLE))
226 gtk_tree_view_column_set_sort_column_id(col, index);
227 gtk_tree_view_column_set_resizable(col, TRUE);
228 gtk_tree_view_column_pack_start(col, renderer, TRUE);
229 gtk_tree_view_column_add_attribute(col, renderer, "text", index);
230 gtk_object_set(GTK_OBJECT(renderer), "alignment", align, NULL);
231 switch (align) {
232 case PANGO_ALIGN_LEFT:
233 xalign = 0.0;
234 break;
235 case PANGO_ALIGN_CENTER:
236 xalign = 0.5;
237 break;
238 case PANGO_ALIGN_RIGHT:
239 xalign = 1.0;
240 break;
241 }
242 gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), xalign, 0.5);
243 gtk_tree_view_column_set_visible(col, visible);
244 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), col);
245 return col;
246}
247
Jens Axboe9b260bd2012-03-06 11:02:52 +0100248static void gfio_ui_setup_log(struct gui *ui)
249{
250 GtkTreeSelection *selection;
251 GtkListStore *model;
252 GtkWidget *tree_view;
253
254 model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
255
256 tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
257 gtk_widget_set_can_focus(tree_view, FALSE);
258
259 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
260 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
Jens Axboe661f7412012-03-06 13:55:45 +0100261 g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
262 "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL);
Jens Axboe9b260bd2012-03-06 11:02:52 +0100263
264 tree_view_column(tree_view, 0, "Time", ALIGN_RIGHT | UNSORTABLE);
265 tree_view_column(tree_view, 1, "Host", ALIGN_RIGHT | UNSORTABLE);
266 tree_view_column(tree_view, 2, "Level", ALIGN_RIGHT | UNSORTABLE);
Jens Axboef095d562012-03-06 13:49:12 +0100267 tree_view_column(tree_view, 3, "Text", ALIGN_LEFT | UNSORTABLE);
Jens Axboe9b260bd2012-03-06 11:02:52 +0100268
269 ui->log_model = model;
270 ui->log_tree = tree_view;
271}
272
Jens Axboea2697902012-03-05 16:43:49 +0100273static GtkWidget *gfio_output_clat_percentiles(unsigned int *ovals,
274 fio_fp64_t *plist,
275 unsigned int len,
276 const char *base,
277 unsigned int scale)
278{
279 GType types[FIO_IO_U_LIST_MAX_LEN];
280 GtkWidget *tree_view;
281 GtkTreeSelection *selection;
282 GtkListStore *model;
283 GtkTreeIter iter;
284 int i;
285
286 for (i = 0; i < len; i++)
287 types[i] = G_TYPE_INT;
288
289 model = gtk_list_store_newv(len, types);
290
291 tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
292 gtk_widget_set_can_focus(tree_view, FALSE);
293
Jens Axboe661f7412012-03-06 13:55:45 +0100294 g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
295 "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL);
296
Jens Axboea2697902012-03-05 16:43:49 +0100297 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
298 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
299
300 for (i = 0; i < len; i++) {
301 char fbuf[8];
302
303 sprintf(fbuf, "%2.2f%%", plist[i].u.f);
304 tree_view_column(tree_view, i, fbuf, ALIGN_RIGHT | UNSORTABLE);
305 }
306
307 gtk_list_store_append(model, &iter);
308
Jens Axboee0681f32012-03-06 12:14:42 +0100309 for (i = 0; i < len; i++) {
310 if (scale)
311 ovals[i] = (ovals[i] + 999) / 1000;
Jens Axboea2697902012-03-05 16:43:49 +0100312 gtk_list_store_set(model, &iter, i, ovals[i], -1);
Jens Axboee0681f32012-03-06 12:14:42 +0100313 }
Jens Axboea2697902012-03-05 16:43:49 +0100314
315 return tree_view;
316}
317
318static void gfio_show_clat_percentiles(GtkWidget *vbox, struct thread_stat *ts,
319 int ddir)
320{
321 unsigned int *io_u_plat = ts->io_u_plat[ddir];
322 unsigned long nr = ts->clat_stat[ddir].samples;
323 fio_fp64_t *plist = ts->percentile_list;
324 unsigned int *ovals, len, minv, maxv, scale_down;
325 const char *base;
326 GtkWidget *tree_view, *frame, *hbox;
327 char tmp[64];
328
329 len = calc_clat_percentiles(io_u_plat, nr, plist, &ovals, &maxv, &minv);
330 if (!len)
331 goto out;
332
333 /*
334 * We default to usecs, but if the value range is such that we
335 * should scale down to msecs, do that.
336 */
337 if (minv > 2000 && maxv > 99999) {
338 scale_down = 1;
339 base = "msec";
340 } else {
341 scale_down = 0;
342 base = "usec";
343 }
344
345 tree_view = gfio_output_clat_percentiles(ovals, plist, len, base, scale_down);
346
347 sprintf(tmp, "Completion percentiles (%s)", base);
348 frame = gtk_frame_new(tmp);
349 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
350
351 hbox = gtk_hbox_new(FALSE, 3);
352 gtk_container_add(GTK_CONTAINER(frame), hbox);
353
354 gtk_box_pack_start(GTK_BOX(hbox), tree_view, TRUE, FALSE, 3);
355out:
356 if (ovals)
357 free(ovals);
358}
359
Jens Axboe3650a3c2012-03-05 14:09:03 +0100360static void gfio_show_lat(GtkWidget *vbox, const char *name, unsigned long min,
361 unsigned long max, double mean, double dev)
362{
363 const char *base = "(usec)";
Jens Axboe1c1e4a52012-03-05 14:37:38 +0100364 GtkWidget *hbox, *label, *frame;
Jens Axboe3650a3c2012-03-05 14:09:03 +0100365 char *minp, *maxp;
366 char tmp[64];
367
368 if (!usec_to_msec(&min, &max, &mean, &dev))
369 base = "(msec)";
370
371 minp = num2str(min, 6, 1, 0);
372 maxp = num2str(max, 6, 1, 0);
373
Jens Axboe3650a3c2012-03-05 14:09:03 +0100374 sprintf(tmp, "%s %s", name, base);
375 frame = gtk_frame_new(tmp);
376 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
377
Jens Axboe3650a3c2012-03-05 14:09:03 +0100378 hbox = gtk_hbox_new(FALSE, 3);
Jens Axboe1c1e4a52012-03-05 14:37:38 +0100379 gtk_container_add(GTK_CONTAINER(frame), hbox);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100380
381 label = new_info_label_in_frame(hbox, "Minimum");
382 gtk_label_set_text(GTK_LABEL(label), minp);
383 label = new_info_label_in_frame(hbox, "Maximum");
384 gtk_label_set_text(GTK_LABEL(label), maxp);
385 label = new_info_label_in_frame(hbox, "Average");
386 sprintf(tmp, "%5.02f", mean);
387 gtk_label_set_text(GTK_LABEL(label), tmp);
388 label = new_info_label_in_frame(hbox, "Standard deviation");
389 sprintf(tmp, "%5.02f", dev);
390 gtk_label_set_text(GTK_LABEL(label), tmp);
391
392 free(minp);
393 free(maxp);
394
395}
396
Jens Axboeca850992012-03-05 20:04:43 +0100397#define GFIO_CLAT 1
398#define GFIO_SLAT 2
399#define GFIO_LAT 4
400
Jens Axboe3650a3c2012-03-05 14:09:03 +0100401static void gfio_show_ddir_status(GtkWidget *mbox, struct group_run_stats *rs,
402 struct thread_stat *ts, int ddir)
403{
404 const char *ddir_label[2] = { "Read", "Write" };
Jens Axboe0b761302012-03-05 20:44:11 +0100405 GtkWidget *frame, *label, *box, *vbox, *main_vbox;
Jens Axboee0681f32012-03-06 12:14:42 +0100406 unsigned long min[3], max[3], runt;
Jens Axboe3650a3c2012-03-05 14:09:03 +0100407 unsigned long long bw, iops;
Jens Axboeca850992012-03-05 20:04:43 +0100408 unsigned int flags = 0;
Jens Axboee0681f32012-03-06 12:14:42 +0100409 double mean[3], dev[3];
Jens Axboe3650a3c2012-03-05 14:09:03 +0100410 char *io_p, *bw_p, *iops_p;
411 int i2p;
412
413 if (!ts->runtime[ddir])
414 return;
415
416 i2p = is_power_of_2(rs->kb_base);
417 runt = ts->runtime[ddir];
418
419 bw = (1000 * ts->io_bytes[ddir]) / runt;
420 io_p = num2str(ts->io_bytes[ddir], 6, 1, i2p);
421 bw_p = num2str(bw, 6, 1, i2p);
422
423 iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt;
424 iops_p = num2str(iops, 6, 1, 0);
425
426 box = gtk_hbox_new(FALSE, 3);
427 gtk_box_pack_start(GTK_BOX(mbox), box, TRUE, FALSE, 3);
428
429 frame = gtk_frame_new(ddir_label[ddir]);
430 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 5);
431
Jens Axboe0b761302012-03-05 20:44:11 +0100432 main_vbox = gtk_vbox_new(FALSE, 3);
433 gtk_container_add(GTK_CONTAINER(frame), main_vbox);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100434
435 box = gtk_hbox_new(FALSE, 3);
Jens Axboe0b761302012-03-05 20:44:11 +0100436 gtk_box_pack_start(GTK_BOX(main_vbox), box, TRUE, FALSE, 3);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100437
438 label = new_info_label_in_frame(box, "IO");
439 gtk_label_set_text(GTK_LABEL(label), io_p);
440 label = new_info_label_in_frame(box, "Bandwidth");
441 gtk_label_set_text(GTK_LABEL(label), bw_p);
442 label = new_info_label_in_frame(box, "IOPS");
443 gtk_label_set_text(GTK_LABEL(label), iops_p);
444 label = new_info_label_in_frame(box, "Runtime (msec)");
445 label_set_int_value(label, ts->runtime[ddir]);
446
Jens Axboee0681f32012-03-06 12:14:42 +0100447 if (calc_lat(&ts->bw_stat[ddir], &min[0], &max[0], &mean[0], &dev[0])) {
Jens Axboeca850992012-03-05 20:04:43 +0100448 double p_of_agg = 100.0;
449 const char *bw_str = "KB";
450 char tmp[32];
451
452 if (rs->agg[ddir]) {
Jens Axboee0681f32012-03-06 12:14:42 +0100453 p_of_agg = mean[0] * 100 / (double) rs->agg[ddir];
Jens Axboeca850992012-03-05 20:04:43 +0100454 if (p_of_agg > 100.0)
455 p_of_agg = 100.0;
456 }
457
Jens Axboee0681f32012-03-06 12:14:42 +0100458 if (mean[0] > 999999.9) {
459 min[0] /= 1000.0;
460 max[0] /= 1000.0;
461 mean[0] /= 1000.0;
462 dev[0] /= 1000.0;
Jens Axboeca850992012-03-05 20:04:43 +0100463 bw_str = "MB";
464 }
465
Jens Axboe0b761302012-03-05 20:44:11 +0100466 sprintf(tmp, "Bandwidth (%s)", bw_str);
467 frame = gtk_frame_new(tmp);
468 gtk_box_pack_start(GTK_BOX(main_vbox), frame, FALSE, FALSE, 5);
Jens Axboeca850992012-03-05 20:04:43 +0100469
Jens Axboe0b761302012-03-05 20:44:11 +0100470 box = gtk_hbox_new(FALSE, 3);
471 gtk_container_add(GTK_CONTAINER(frame), box);
Jens Axboeca850992012-03-05 20:04:43 +0100472
Jens Axboe0b761302012-03-05 20:44:11 +0100473 label = new_info_label_in_frame(box, "Minimum");
Jens Axboee0681f32012-03-06 12:14:42 +0100474 label_set_int_value(label, min[0]);
Jens Axboe0b761302012-03-05 20:44:11 +0100475 label = new_info_label_in_frame(box, "Maximum");
Jens Axboee0681f32012-03-06 12:14:42 +0100476 label_set_int_value(label, max[0]);
Jens Axboe0b761302012-03-05 20:44:11 +0100477 label = new_info_label_in_frame(box, "Percentage of jobs");
Jens Axboeca850992012-03-05 20:04:43 +0100478 sprintf(tmp, "%3.2f%%", p_of_agg);
479 gtk_label_set_text(GTK_LABEL(label), tmp);
Jens Axboe0b761302012-03-05 20:44:11 +0100480 label = new_info_label_in_frame(box, "Average");
Jens Axboee0681f32012-03-06 12:14:42 +0100481 sprintf(tmp, "%5.02f", mean[0]);
Jens Axboeca850992012-03-05 20:04:43 +0100482 gtk_label_set_text(GTK_LABEL(label), tmp);
Jens Axboe0b761302012-03-05 20:44:11 +0100483 label = new_info_label_in_frame(box, "Standard deviation");
Jens Axboee0681f32012-03-06 12:14:42 +0100484 sprintf(tmp, "%5.02f", dev[0]);
Jens Axboeca850992012-03-05 20:04:43 +0100485 gtk_label_set_text(GTK_LABEL(label), tmp);
486 }
487
Jens Axboee0681f32012-03-06 12:14:42 +0100488 if (calc_lat(&ts->slat_stat[ddir], &min[0], &max[0], &mean[0], &dev[0]))
Jens Axboe2b089892012-03-06 08:09:17 +0100489 flags |= GFIO_SLAT;
Jens Axboee0681f32012-03-06 12:14:42 +0100490 if (calc_lat(&ts->clat_stat[ddir], &min[1], &max[1], &mean[1], &dev[1]))
Jens Axboe2b089892012-03-06 08:09:17 +0100491 flags |= GFIO_CLAT;
Jens Axboee0681f32012-03-06 12:14:42 +0100492 if (calc_lat(&ts->lat_stat[ddir], &min[2], &max[2], &mean[2], &dev[2]))
Jens Axboe2b089892012-03-06 08:09:17 +0100493 flags |= GFIO_LAT;
494
495 if (flags) {
496 frame = gtk_frame_new("Latency");
497 gtk_box_pack_start(GTK_BOX(main_vbox), frame, FALSE, FALSE, 5);
498
499 vbox = gtk_vbox_new(FALSE, 3);
500 gtk_container_add(GTK_CONTAINER(frame), vbox);
501
502 if (flags & GFIO_SLAT)
Jens Axboee0681f32012-03-06 12:14:42 +0100503 gfio_show_lat(vbox, "Submission latency", min[0], max[0], mean[0], dev[0]);
Jens Axboe2b089892012-03-06 08:09:17 +0100504 if (flags & GFIO_CLAT)
Jens Axboee0681f32012-03-06 12:14:42 +0100505 gfio_show_lat(vbox, "Completion latency", min[1], max[1], mean[1], dev[1]);
Jens Axboe2b089892012-03-06 08:09:17 +0100506 if (flags & GFIO_LAT)
Jens Axboee0681f32012-03-06 12:14:42 +0100507 gfio_show_lat(vbox, "Total latency", min[2], max[2], mean[2], dev[2]);
Jens Axboe2b089892012-03-06 08:09:17 +0100508 }
509
510 if (ts->clat_percentiles)
511 gfio_show_clat_percentiles(main_vbox, ts, ddir);
512
513
Jens Axboe3650a3c2012-03-05 14:09:03 +0100514 free(io_p);
515 free(bw_p);
516 free(iops_p);
517}
518
Jens Axboee5bd1342012-03-05 21:38:12 +0100519static GtkWidget *gfio_output_lat_buckets(double *lat, unsigned int num,
520 const char **labels)
521{
522 GtkWidget *tree_view;
523 GtkTreeSelection *selection;
524 GtkListStore *model;
525 GtkTreeIter iter;
526 GType *types;
527 int i, skipped;
528
529 /*
530 * Check if all are empty, in which case don't bother
531 */
532 for (i = 0, skipped = 0; i < num; i++)
533 if (lat[i] <= 0.0)
534 skipped++;
535
536 if (skipped == num)
537 return NULL;
538
539 types = malloc(num * sizeof(GType));
540
541 for (i = 0; i < num; i++)
542 types[i] = G_TYPE_STRING;
543
544 model = gtk_list_store_newv(num, types);
545 free(types);
546 types = NULL;
547
548 tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
549 gtk_widget_set_can_focus(tree_view, FALSE);
550
Jens Axboe661f7412012-03-06 13:55:45 +0100551 g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
552 "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL);
553
Jens Axboee5bd1342012-03-05 21:38:12 +0100554 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
555 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
556
557 for (i = 0; i < num; i++)
558 tree_view_column(tree_view, i, labels[i], ALIGN_RIGHT | UNSORTABLE);
559
560 gtk_list_store_append(model, &iter);
561
562 for (i = 0; i < num; i++) {
563 char fbuf[32];
564
565 if (lat[i] <= 0.0)
566 sprintf(fbuf, "0.00");
567 else
568 sprintf(fbuf, "%3.2f%%", lat[i]);
569
570 gtk_list_store_set(model, &iter, i, fbuf, -1);
571 }
572
573 return tree_view;
574}
575
576static void gfio_show_latency_buckets(GtkWidget *vbox, struct thread_stat *ts)
577{
578 GtkWidget *box, *frame, *tree_view;
579 double io_u_lat_u[FIO_IO_U_LAT_U_NR];
580 double io_u_lat_m[FIO_IO_U_LAT_M_NR];
581 const char *uranges[] = { "2", "4", "10", "20", "50", "100",
582 "250", "500", "750", "1000", };
583 const char *mranges[] = { "2", "4", "10", "20", "50", "100",
584 "250", "500", "750", "1000", "2000",
585 ">= 2000", };
586
587 stat_calc_lat_u(ts, io_u_lat_u);
588 stat_calc_lat_m(ts, io_u_lat_m);
589
590 tree_view = gfio_output_lat_buckets(io_u_lat_u, FIO_IO_U_LAT_U_NR, uranges);
591 if (tree_view) {
592 frame = gtk_frame_new("Latency buckets (usec)");
593 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
594
595 box = gtk_hbox_new(FALSE, 3);
596 gtk_container_add(GTK_CONTAINER(frame), box);
597 gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 3);
598 }
599
600 tree_view = gfio_output_lat_buckets(io_u_lat_m, FIO_IO_U_LAT_M_NR, mranges);
601 if (tree_view) {
602 frame = gtk_frame_new("Latency buckets (msec)");
603 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
604
605 box = gtk_hbox_new(FALSE, 3);
606 gtk_container_add(GTK_CONTAINER(frame), box);
607 gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 3);
608 }
609}
610
Jens Axboe2e331012012-03-05 22:07:54 +0100611static void gfio_show_cpu_usage(GtkWidget *vbox, struct thread_stat *ts)
612{
613 GtkWidget *box, *frame, *entry;
614 double usr_cpu, sys_cpu;
615 unsigned long runtime;
616 char tmp[32];
617
618 runtime = ts->total_run_time;
619 if (runtime) {
620 double runt = (double) runtime;
621
622 usr_cpu = (double) ts->usr_time * 100 / runt;
623 sys_cpu = (double) ts->sys_time * 100 / runt;
624 } else {
625 usr_cpu = 0;
626 sys_cpu = 0;
627 }
628
629 frame = gtk_frame_new("OS resources");
630 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
631
632 box = gtk_hbox_new(FALSE, 3);
633 gtk_container_add(GTK_CONTAINER(frame), box);
634
635 entry = new_info_entry_in_frame(box, "User CPU");
636 sprintf(tmp, "%3.2f%%", usr_cpu);
637 gtk_entry_set_text(GTK_ENTRY(entry), tmp);
638 entry = new_info_entry_in_frame(box, "System CPU");
639 sprintf(tmp, "%3.2f%%", sys_cpu);
640 gtk_entry_set_text(GTK_ENTRY(entry), tmp);
641 entry = new_info_entry_in_frame(box, "Context switches");
642 entry_set_int_value(entry, ts->ctx);
643 entry = new_info_entry_in_frame(box, "Major faults");
644 entry_set_int_value(entry, ts->majf);
645 entry = new_info_entry_in_frame(box, "Minor faults");
646 entry_set_int_value(entry, ts->minf);
647}
Jens Axboe19998db2012-03-06 09:17:59 +0100648static void gfio_add_sc_depths_tree(GtkListStore *model,
649 struct thread_stat *ts, unsigned int len,
650 int submit)
651{
652 double io_u_dist[FIO_IO_U_MAP_NR];
653 GtkTreeIter iter;
654 /* Bits 0, and 3-8 */
655 const int add_mask = 0x1f9;
656 int i, j;
657
658 if (submit)
659 stat_calc_dist(ts->io_u_submit, ts->total_submit, io_u_dist);
660 else
661 stat_calc_dist(ts->io_u_complete, ts->total_complete, io_u_dist);
662
663 gtk_list_store_append(model, &iter);
664
665 gtk_list_store_set(model, &iter, 0, submit ? "Submit" : "Complete", -1);
666
667 for (i = 1, j = 0; i < len; i++) {
668 char fbuf[32];
669
670 if (!(add_mask & (1UL << (i - 1))))
671 sprintf(fbuf, "0.0%%");
672 else {
673 sprintf(fbuf, "%3.1f%%", io_u_dist[j]);
674 j++;
675 }
676
677 gtk_list_store_set(model, &iter, i, fbuf, -1);
678 }
679
680}
681
682static void gfio_add_total_depths_tree(GtkListStore *model,
683 struct thread_stat *ts, unsigned int len)
684{
685 double io_u_dist[FIO_IO_U_MAP_NR];
686 GtkTreeIter iter;
687 /* Bits 1-6, and 8 */
688 const int add_mask = 0x17e;
689 int i, j;
690
691 stat_calc_dist(ts->io_u_map, ts_total_io_u(ts), io_u_dist);
692
693 gtk_list_store_append(model, &iter);
694
695 gtk_list_store_set(model, &iter, 0, "Total", -1);
696
697 for (i = 1, j = 0; i < len; i++) {
698 char fbuf[32];
699
700 if (!(add_mask & (1UL << (i - 1))))
701 sprintf(fbuf, "0.0%%");
702 else {
703 sprintf(fbuf, "%3.1f%%", io_u_dist[j]);
704 j++;
705 }
706
707 gtk_list_store_set(model, &iter, i, fbuf, -1);
708 }
709
710}
Jens Axboe2e331012012-03-05 22:07:54 +0100711
712static void gfio_show_io_depths(GtkWidget *vbox, struct thread_stat *ts)
713{
Jens Axboe2e331012012-03-05 22:07:54 +0100714 GtkWidget *frame, *box, *tree_view;
715 GtkTreeSelection *selection;
716 GtkListStore *model;
Jens Axboe2e331012012-03-05 22:07:54 +0100717 GType types[FIO_IO_U_MAP_NR + 1];
718 int i;
Jens Axboe19998db2012-03-06 09:17:59 +0100719#define NR_LABELS 10
720 const char *labels[NR_LABELS] = { "Depth", "0", "1", "2", "4", "8", "16", "32", "64", ">= 64" };
Jens Axboe2e331012012-03-05 22:07:54 +0100721
722 frame = gtk_frame_new("IO depths");
723 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
724
725 box = gtk_hbox_new(FALSE, 3);
726 gtk_container_add(GTK_CONTAINER(frame), box);
727
Jens Axboe19998db2012-03-06 09:17:59 +0100728 for (i = 0; i < NR_LABELS; i++)
Jens Axboe2e331012012-03-05 22:07:54 +0100729 types[i] = G_TYPE_STRING;
730
Jens Axboe19998db2012-03-06 09:17:59 +0100731 model = gtk_list_store_newv(NR_LABELS, types);
Jens Axboe2e331012012-03-05 22:07:54 +0100732
733 tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
734 gtk_widget_set_can_focus(tree_view, FALSE);
735
Jens Axboe661f7412012-03-06 13:55:45 +0100736 g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
737 "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL);
738
Jens Axboe2e331012012-03-05 22:07:54 +0100739 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
740 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
741
Jens Axboe19998db2012-03-06 09:17:59 +0100742 for (i = 0; i < NR_LABELS; i++)
Jens Axboe2e331012012-03-05 22:07:54 +0100743 tree_view_column(tree_view, i, labels[i], ALIGN_RIGHT | UNSORTABLE);
744
Jens Axboe19998db2012-03-06 09:17:59 +0100745 gfio_add_total_depths_tree(model, ts, NR_LABELS);
746 gfio_add_sc_depths_tree(model, ts, NR_LABELS, 1);
747 gfio_add_sc_depths_tree(model, ts, NR_LABELS, 0);
Jens Axboe2e331012012-03-05 22:07:54 +0100748
749 gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 3);
750}
751
Jens Axboef9d40b42012-03-06 09:52:49 +0100752static gboolean results_window_delete(GtkWidget *w, gpointer data)
753{
754 struct gui *ui = (struct gui *) data;
755
756 gtk_widget_destroy(w);
757 ui->results_window = NULL;
758 ui->results_notebook = NULL;
759 return TRUE;
760}
761
762static GtkWidget *get_results_window(struct gui *ui)
763{
764 GtkWidget *win, *notebook;
765
766 if (ui->results_window)
767 return ui->results_notebook;
768
769 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
770 gtk_window_set_title(GTK_WINDOW(win), "Results");
771 g_signal_connect(win, "delete-event", G_CALLBACK(results_window_delete), ui);
772 g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ui);
773
774 notebook = gtk_notebook_new();
775 gtk_container_add(GTK_CONTAINER(win), notebook);
776
777 ui->results_window = win;
778 ui->results_notebook = notebook;
779 return ui->results_notebook;
780}
781
Jens Axboe3650a3c2012-03-05 14:09:03 +0100782static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
783 struct group_run_stats *rs)
784{
Jens Axboef9d40b42012-03-06 09:52:49 +0100785 GtkWidget *res_win, *box, *vbox, *entry;
Jens Axboee0681f32012-03-06 12:14:42 +0100786 struct gfio_client *gc = client->client_data;
Jens Axboe3650a3c2012-03-05 14:09:03 +0100787
788 gdk_threads_enter();
789
Jens Axboee0681f32012-03-06 12:14:42 +0100790 res_win = get_results_window(gc->ui);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100791
792 vbox = gtk_vbox_new(FALSE, 3);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100793
794 box = gtk_hbox_new(TRUE, 3);
795 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
796
Jens Axboef9d40b42012-03-06 09:52:49 +0100797 gtk_notebook_append_page(GTK_NOTEBOOK(res_win), vbox, gtk_label_new(ts->name));
798
Jens Axboee0681f32012-03-06 12:14:42 +0100799 gc->results_widget = vbox;
800
Jens Axboe3650a3c2012-03-05 14:09:03 +0100801 entry = new_info_entry_in_frame(box, "Name");
802 gtk_entry_set_text(GTK_ENTRY(entry), ts->name);
803 if (strlen(ts->description)) {
804 entry = new_info_entry_in_frame(box, "Description");
805 gtk_entry_set_text(GTK_ENTRY(entry), ts->description);
806 }
807 entry = new_info_entry_in_frame(box, "Group ID");
808 entry_set_int_value(entry, ts->groupid);
809 entry = new_info_entry_in_frame(box, "Jobs");
810 entry_set_int_value(entry, ts->members);
811 entry = new_info_entry_in_frame(box, "Error");
812 entry_set_int_value(entry, ts->error);
813 entry = new_info_entry_in_frame(box, "PID");
814 entry_set_int_value(entry, ts->pid);
815
816 if (ts->io_bytes[DDIR_READ])
817 gfio_show_ddir_status(vbox, rs, ts, DDIR_READ);
818 if (ts->io_bytes[DDIR_WRITE])
819 gfio_show_ddir_status(vbox, rs, ts, DDIR_WRITE);
820
Jens Axboee5bd1342012-03-05 21:38:12 +0100821 gfio_show_latency_buckets(vbox, ts);
Jens Axboe2e331012012-03-05 22:07:54 +0100822 gfio_show_cpu_usage(vbox, ts);
823 gfio_show_io_depths(vbox, ts);
Jens Axboee5bd1342012-03-05 21:38:12 +0100824
Jens Axboee0681f32012-03-06 12:14:42 +0100825 gtk_widget_show_all(gc->ui->results_window);
Jens Axboe3650a3c2012-03-05 14:09:03 +0100826 gdk_threads_leave();
827}
828
Jens Axboe084d1c62012-03-03 20:28:07 +0100829static void gfio_text_op(struct fio_client *client, struct fio_net_cmd *cmd)
Stephen M. Camerona1820202012-02-24 08:17:31 +0100830{
Jens Axboe9b260bd2012-03-06 11:02:52 +0100831 struct cmd_text_pdu *p = (struct cmd_text_pdu *) cmd->payload;
Jens Axboee0681f32012-03-06 12:14:42 +0100832 struct gfio_client *gc = client->client_data;
Jens Axboe9b260bd2012-03-06 11:02:52 +0100833 GtkTreeIter iter;
834 struct tm *tm;
835 time_t sec;
836 char tmp[64], timebuf[80];
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100837
Jens Axboe9b260bd2012-03-06 11:02:52 +0100838 sec = p->log_sec;
839 tm = localtime(&sec);
840 strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", tm);
841 sprintf(timebuf, "%s.%03ld", tmp, p->log_usec / 1000);
842
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100843 gdk_threads_enter();
Jens Axboe9b260bd2012-03-06 11:02:52 +0100844
Jens Axboee0681f32012-03-06 12:14:42 +0100845 gtk_list_store_append(gc->ui->log_model, &iter);
846 gtk_list_store_set(gc->ui->log_model, &iter, 0, timebuf, -1);
847 gtk_list_store_set(gc->ui->log_model, &iter, 1, client->hostname, -1);
848 gtk_list_store_set(gc->ui->log_model, &iter, 2, p->level, -1);
849 gtk_list_store_set(gc->ui->log_model, &iter, 3, p->buf, -1);
Jens Axboe9b260bd2012-03-06 11:02:52 +0100850
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100851 gdk_threads_leave();
Stephen M. Camerona1820202012-02-24 08:17:31 +0100852}
853
854static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd)
855{
Jens Axboee0681f32012-03-06 12:14:42 +0100856 struct cmd_du_pdu *p = (struct cmd_du_pdu *) cmd->payload;
857 struct gfio_client *gc = client->client_data;
858 GtkWidget *box, *frame, *entry, *vbox;
859
Jens Axboe0050e5f2012-03-06 09:23:27 +0100860 gdk_threads_enter();
Jens Axboee0681f32012-03-06 12:14:42 +0100861
862 if (!gc->results_widget) {
863 printf("no results!\n");
864 goto out;
865 }
866
867 if (!gc->disk_util_frame) {
868 gc->disk_util_frame = gtk_frame_new("Disk utilization");
869 gtk_box_pack_start(GTK_BOX(gc->results_widget), gc->disk_util_frame, FALSE, FALSE, 5);
870 }
871
872 vbox = gtk_vbox_new(FALSE, 3);
873 gtk_container_add(GTK_CONTAINER(gc->disk_util_frame), vbox);
874
875 frame = gtk_frame_new((char *) p->dus.name);
876 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 2);
877
878 box = gtk_vbox_new(FALSE, 3);
879 gtk_container_add(GTK_CONTAINER(frame), box);
880
881 frame = gtk_frame_new("Read");
882 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2);
883 vbox = gtk_hbox_new(TRUE, 3);
884 gtk_container_add(GTK_CONTAINER(frame), vbox);
885 entry = new_info_entry_in_frame(vbox, "IOs");
886 entry_set_int_value(entry, p->dus.ios[0]);
887 entry = new_info_entry_in_frame(vbox, "Merges");
888 entry_set_int_value(entry, p->dus.merges[0]);
889 entry = new_info_entry_in_frame(vbox, "Sectors");
890 entry_set_int_value(entry, p->dus.sectors[0]);
891 entry = new_info_entry_in_frame(vbox, "Ticks");
892 entry_set_int_value(entry, p->dus.ticks[0]);
893
894 frame = gtk_frame_new("Write");
895 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2);
896 vbox = gtk_hbox_new(TRUE, 3);
897 gtk_container_add(GTK_CONTAINER(frame), vbox);
898 entry = new_info_entry_in_frame(vbox, "IOs");
899 entry_set_int_value(entry, p->dus.ios[1]);
900 entry = new_info_entry_in_frame(vbox, "Merges");
901 entry_set_int_value(entry, p->dus.merges[1]);
902 entry = new_info_entry_in_frame(vbox, "Sectors");
903 entry_set_int_value(entry, p->dus.sectors[1]);
904 entry = new_info_entry_in_frame(vbox, "Ticks");
905 entry_set_int_value(entry, p->dus.ticks[1]);
906
907 frame = gtk_frame_new("Shared");
908 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 2);
909 vbox = gtk_hbox_new(TRUE, 3);
910 gtk_container_add(GTK_CONTAINER(frame), vbox);
911 entry = new_info_entry_in_frame(vbox, "IO ticks");
912 entry_set_int_value(entry, p->dus.io_ticks);
913 entry = new_info_entry_in_frame(vbox, "Time in queue");
914 entry_set_int_value(entry, p->dus.time_in_queue);
915
916 gtk_widget_show_all(gc->results_widget);
917out:
Jens Axboe0050e5f2012-03-06 09:23:27 +0100918 gdk_threads_leave();
Stephen M. Camerona1820202012-02-24 08:17:31 +0100919}
920
Jens Axboe3650a3c2012-03-05 14:09:03 +0100921extern int sum_stat_clients;
922extern struct thread_stat client_ts;
923extern struct group_run_stats client_gs;
924
925static int sum_stat_nr;
926
Jens Axboe89e5fad2012-03-05 09:21:12 +0100927static void gfio_thread_status_op(struct fio_client *client,
928 struct fio_net_cmd *cmd)
Stephen M. Camerona1820202012-02-24 08:17:31 +0100929{
Jens Axboe3650a3c2012-03-05 14:09:03 +0100930 struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload;
931
932 gfio_display_ts(client, &p->ts, &p->rs);
933
934 if (sum_stat_clients == 1)
935 return;
936
937 sum_thread_stats(&client_ts, &p->ts, sum_stat_nr);
938 sum_group_stats(&client_gs, &p->rs);
939
940 client_ts.members++;
941 client_ts.groupid = p->ts.groupid;
942
943 if (++sum_stat_nr == sum_stat_clients) {
944 strcpy(client_ts.name, "All clients");
945 gfio_display_ts(client, &client_ts, &client_gs);
946 }
Stephen M. Camerona1820202012-02-24 08:17:31 +0100947}
948
Jens Axboe89e5fad2012-03-05 09:21:12 +0100949static void gfio_group_stats_op(struct fio_client *client,
950 struct fio_net_cmd *cmd)
Stephen M. Camerona1820202012-02-24 08:17:31 +0100951{
Jens Axboe0050e5f2012-03-06 09:23:27 +0100952 gdk_threads_enter();
Stephen M. Camerona1820202012-02-24 08:17:31 +0100953 printf("gfio_group_stats_op called\n");
Jens Axboe89e5fad2012-03-05 09:21:12 +0100954 fio_client_ops.group_stats(client, cmd);
Jens Axboe0050e5f2012-03-06 09:23:27 +0100955 gdk_threads_leave();
Stephen M. Camerona1820202012-02-24 08:17:31 +0100956}
957
Jens Axboe3e47bd22012-02-29 13:45:02 +0100958static void gfio_update_eta(struct jobs_eta *je)
959{
960 static int eta_good;
961 char eta_str[128];
962 char output[256];
963 char tmp[32];
964 double perc = 0.0;
965 int i2p = 0;
966
Jens Axboe0050e5f2012-03-06 09:23:27 +0100967 gdk_threads_enter();
968
Jens Axboe3e47bd22012-02-29 13:45:02 +0100969 eta_str[0] = '\0';
970 output[0] = '\0';
971
972 if (je->eta_sec != INT_MAX && je->elapsed_sec) {
973 perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec);
974 eta_to_str(eta_str, je->eta_sec);
975 }
976
977 sprintf(tmp, "%u", je->nr_running);
Jens Axboeca850992012-03-05 20:04:43 +0100978 gtk_entry_set_text(GTK_ENTRY(ui.eta.jobs), tmp);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100979 sprintf(tmp, "%u", je->files_open);
Jens Axboeca850992012-03-05 20:04:43 +0100980 gtk_entry_set_text(GTK_ENTRY(ui.eta.files), tmp);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100981
982#if 0
983 if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) {
984 if (je->m_rate || je->t_rate) {
985 char *tr, *mr;
986
987 mr = num2str(je->m_rate, 4, 0, i2p);
988 tr = num2str(je->t_rate, 4, 0, i2p);
Jens Axboeca850992012-03-05 20:04:43 +0100989 gtk_entry_set_text(GTK_ENTRY(ui.eta);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100990 p += sprintf(p, ", CR=%s/%s KB/s", tr, mr);
991 free(tr);
992 free(mr);
993 } else if (je->m_iops || je->t_iops)
994 p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops);
Jens Axboeebbd89c2012-03-02 11:21:13 +0100995
Jens Axboeca850992012-03-05 20:04:43 +0100996 gtk_entry_set_text(GTK_ENTRY(ui.eta.cr_bw), "---");
997 gtk_entry_set_text(GTK_ENTRY(ui.eta.cr_iops), "---");
998 gtk_entry_set_text(GTK_ENTRY(ui.eta.cw_bw), "---");
999 gtk_entry_set_text(GTK_ENTRY(ui.eta.cw_iops), "---");
Jens Axboe3e47bd22012-02-29 13:45:02 +01001000#endif
1001
1002 if (je->eta_sec != INT_MAX && je->nr_running) {
1003 char *iops_str[2];
1004 char *rate_str[2];
1005
1006 if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running)
1007 strcpy(output, "-.-% done");
1008 else {
1009 eta_good = 1;
1010 perc *= 100.0;
1011 sprintf(output, "%3.1f%% done", perc);
1012 }
1013
1014 rate_str[0] = num2str(je->rate[0], 5, 10, i2p);
1015 rate_str[1] = num2str(je->rate[1], 5, 10, i2p);
1016
1017 iops_str[0] = num2str(je->iops[0], 4, 1, 0);
1018 iops_str[1] = num2str(je->iops[1], 4, 1, 0);
1019
Jens Axboeca850992012-03-05 20:04:43 +01001020 gtk_entry_set_text(GTK_ENTRY(ui.eta.read_bw), rate_str[0]);
1021 gtk_entry_set_text(GTK_ENTRY(ui.eta.read_iops), iops_str[0]);
1022 gtk_entry_set_text(GTK_ENTRY(ui.eta.write_bw), rate_str[1]);
1023 gtk_entry_set_text(GTK_ENTRY(ui.eta.write_iops), iops_str[1]);
Jens Axboe3e47bd22012-02-29 13:45:02 +01001024
1025 free(rate_str[0]);
1026 free(rate_str[1]);
1027 free(iops_str[0]);
1028 free(iops_str[1]);
1029 }
1030
1031 if (eta_str[0]) {
1032 char *dst = output + strlen(output);
1033
1034 sprintf(dst, " - %s", eta_str);
1035 }
1036
1037 gfio_update_thread_status(output, perc);
Jens Axboe0050e5f2012-03-06 09:23:27 +01001038 gdk_threads_leave();
Jens Axboe3e47bd22012-02-29 13:45:02 +01001039}
1040
Stephen M. Camerona1820202012-02-24 08:17:31 +01001041static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd)
1042{
Jens Axboe843ad232012-02-29 11:44:53 +01001043 struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
Jens Axboe88f6e7a2012-03-06 12:55:29 +01001044 struct gfio_client *gc = client->client_data;
1045 struct gui *ui = gc->ui;
Jens Axboe843ad232012-02-29 11:44:53 +01001046 const char *os, *arch;
1047 char buf[64];
1048
1049 os = fio_get_os_string(probe->os);
1050 if (!os)
1051 os = "unknown";
1052
1053 arch = fio_get_arch_string(probe->arch);
1054 if (!arch)
1055 os = "unknown";
1056
1057 if (!client->name)
1058 client->name = strdup((char *) probe->hostname);
1059
Jens Axboe0050e5f2012-03-06 09:23:27 +01001060 gdk_threads_enter();
1061
Jens Axboe88f6e7a2012-03-06 12:55:29 +01001062 gtk_label_set_text(GTK_LABEL(ui->probe.hostname), (char *) probe->hostname);
1063 gtk_label_set_text(GTK_LABEL(ui->probe.os), os);
1064 gtk_label_set_text(GTK_LABEL(ui->probe.arch), arch);
Jens Axboe843ad232012-02-29 11:44:53 +01001065 sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch);
Jens Axboe88f6e7a2012-03-06 12:55:29 +01001066 gtk_label_set_text(GTK_LABEL(ui->probe.fio_ver), buf);
1067
1068 gfio_set_connected(ui, 1);
Jens Axboe0050e5f2012-03-06 09:23:27 +01001069
1070 gdk_threads_leave();
Stephen M. Camerona1820202012-02-24 08:17:31 +01001071}
1072
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +01001073static void gfio_update_thread_status(char *status_message, double perc)
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +01001074{
1075 static char message[100];
1076 const char *m = message;
1077
1078 strncpy(message, status_message, sizeof(message) - 1);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +01001079 gtk_progress_bar_set_text(
1080 GTK_PROGRESS_BAR(ui.thread_status_pb), m);
1081 gtk_progress_bar_set_fraction(
1082 GTK_PROGRESS_BAR(ui.thread_status_pb), perc / 100.0);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +01001083 gtk_widget_queue_draw(ui.window);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +01001084}
1085
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001086static void gfio_quit_op(struct fio_client *client)
1087{
Jens Axboee0681f32012-03-06 12:14:42 +01001088 struct gfio_client *gc = client->client_data;
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001089
Jens Axboe0050e5f2012-03-06 09:23:27 +01001090 gdk_threads_enter();
Jens Axboee0681f32012-03-06 12:14:42 +01001091 gfio_set_connected(gc->ui, 0);
Jens Axboe0050e5f2012-03-06 09:23:27 +01001092 gdk_threads_leave();
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001093}
1094
Jens Axboe807f9972012-03-02 10:25:24 +01001095static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
1096{
1097 struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
Jens Axboee0681f32012-03-06 12:14:42 +01001098 struct gfio_client *gc = client->client_data;
1099 struct gui *ui = gc->ui;
Jens Axboe807f9972012-03-02 10:25:24 +01001100 char tmp[8];
1101 int i;
1102
1103 p->iodepth = le32_to_cpu(p->iodepth);
1104 p->rw = le32_to_cpu(p->rw);
1105
1106 for (i = 0; i < 2; i++) {
1107 p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
1108 p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
1109 }
1110
1111 p->numjobs = le32_to_cpu(p->numjobs);
1112 p->group_reporting = le32_to_cpu(p->group_reporting);
1113
Jens Axboe0050e5f2012-03-06 09:23:27 +01001114 gdk_threads_enter();
1115
Jens Axboeca850992012-03-05 20:04:43 +01001116 gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) p->jobname);
1117 gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(p->rw));
1118 gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) p->ioengine);
Jens Axboe807f9972012-03-02 10:25:24 +01001119
1120 sprintf(tmp, "%u", p->iodepth);
Jens Axboeca850992012-03-05 20:04:43 +01001121 gtk_entry_set_text(GTK_ENTRY(ui->eta.iodepth), tmp);
Jens Axboe0050e5f2012-03-06 09:23:27 +01001122
1123 gdk_threads_leave();
Jens Axboe807f9972012-03-02 10:25:24 +01001124}
1125
Jens Axboeed727a42012-03-02 12:14:40 +01001126static void gfio_client_timed_out(struct fio_client *client)
1127{
Jens Axboee0681f32012-03-06 12:14:42 +01001128 struct gfio_client *gc = client->client_data;
Jens Axboeed727a42012-03-02 12:14:40 +01001129 GtkWidget *dialog, *label, *content;
1130 char buf[256];
1131
1132 gdk_threads_enter();
1133
Jens Axboee0681f32012-03-06 12:14:42 +01001134 gfio_set_connected(gc->ui, 0);
1135 clear_ui_info(gc->ui);
Jens Axboeed727a42012-03-02 12:14:40 +01001136
1137 sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname);
1138
1139 dialog = gtk_dialog_new_with_buttons("Timed out!",
Jens Axboee0681f32012-03-06 12:14:42 +01001140 GTK_WINDOW(gc->ui->window),
Jens Axboeed727a42012-03-02 12:14:40 +01001141 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1142 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
1143
1144 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1145 label = gtk_label_new((const gchar *) buf);
1146 gtk_container_add(GTK_CONTAINER(content), label);
1147 gtk_widget_show_all(dialog);
1148 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
1149
1150 gtk_dialog_run(GTK_DIALOG(dialog));
1151 gtk_widget_destroy(dialog);
1152
1153 gdk_threads_leave();
1154}
1155
Stephen M. Camerona1820202012-02-24 08:17:31 +01001156struct client_ops gfio_client_ops = {
Jens Axboe0420ba62012-02-29 11:16:52 +01001157 .text_op = gfio_text_op,
1158 .disk_util = gfio_disk_util_op,
1159 .thread_status = gfio_thread_status_op,
1160 .group_stats = gfio_group_stats_op,
Jens Axboea5276612012-03-04 15:15:08 +01001161 .eta = gfio_update_eta,
Jens Axboe0420ba62012-02-29 11:16:52 +01001162 .probe = gfio_probe_op,
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001163 .quit = gfio_quit_op,
Jens Axboe807f9972012-03-02 10:25:24 +01001164 .add_job = gfio_add_job_op,
Jens Axboeed727a42012-03-02 12:14:40 +01001165 .timed_out = gfio_client_timed_out,
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001166 .stay_connected = 1,
Stephen M. Camerona1820202012-02-24 08:17:31 +01001167};
1168
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001169static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
1170 __attribute__((unused)) gpointer data)
1171{
1172 gtk_main_quit();
1173}
1174
Stephen M. Cameron25927252012-02-24 08:17:31 +01001175static void *job_thread(void *arg)
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001176{
Stephen M. Cameron25927252012-02-24 08:17:31 +01001177 fio_handle_clients(&gfio_client_ops);
Stephen M. Cameron25927252012-02-24 08:17:31 +01001178 return NULL;
1179}
1180
Jens Axboe0420ba62012-02-29 11:16:52 +01001181static int send_job_files(struct gui *ui)
Stephen M. Cameron60f6b332012-02-24 08:17:32 +01001182{
Jens Axboe441013b2012-03-01 08:01:52 +01001183 int i, ret = 0;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +01001184
Jens Axboe0420ba62012-02-29 11:16:52 +01001185 for (i = 0; i < ui->nr_job_files; i++) {
1186 ret = fio_clients_send_ini(ui->job_files[i]);
Jens Axboe441013b2012-03-01 08:01:52 +01001187 if (ret)
1188 break;
1189
Jens Axboe0420ba62012-02-29 11:16:52 +01001190 free(ui->job_files[i]);
1191 ui->job_files[i] = NULL;
Jens Axboe441013b2012-03-01 08:01:52 +01001192 }
1193 while (i < ui->nr_job_files) {
1194 free(ui->job_files[i]);
1195 ui->job_files[i] = NULL;
1196 i++;
Jens Axboe0420ba62012-02-29 11:16:52 +01001197 }
1198
Jens Axboe441013b2012-03-01 08:01:52 +01001199 return ret;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +01001200}
1201
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001202static void start_job_thread(struct gui *ui)
Stephen M. Cameron25927252012-02-24 08:17:31 +01001203{
Jens Axboe0420ba62012-02-29 11:16:52 +01001204 if (send_job_files(ui)) {
Stephen M. Cameron60f6b332012-02-24 08:17:32 +01001205 printf("Yeah, I didn't really like those options too much.\n");
Stephen M. Cameron60f6b332012-02-24 08:17:32 +01001206 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
1207 return;
1208 }
Stephen M. Cameron25927252012-02-24 08:17:31 +01001209}
1210
1211static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
1212 gpointer data)
1213{
1214 struct gui *ui = data;
1215
Stephen M. Cameron25927252012-02-24 08:17:31 +01001216 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001217 start_job_thread(ui);
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001218}
1219
Jens Axboedf06f222012-03-02 13:32:04 +01001220static void file_open(GtkWidget *w, gpointer data);
1221
1222static void connect_clicked(GtkWidget *widget, gpointer data)
Jens Axboe3e47bd22012-02-29 13:45:02 +01001223{
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001224 struct gui *ui = data;
1225
1226 if (!ui->connected) {
Jens Axboedf06f222012-03-02 13:32:04 +01001227 if (!ui->nr_job_files)
1228 file_open(widget, data);
Jens Axboe8663ea62012-03-02 14:04:30 +01001229 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001230 fio_clients_connect();
1231 pthread_create(&ui->t, NULL, job_thread, NULL);
Jens Axboe88f6e7a2012-03-06 12:55:29 +01001232 gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 0);
Jens Axboedf06f222012-03-02 13:32:04 +01001233 } else {
1234 fio_clients_terminate();
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001235 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +01001236 clear_ui_info(ui);
Jens Axboedf06f222012-03-02 13:32:04 +01001237 }
Jens Axboe3e47bd22012-02-29 13:45:02 +01001238}
1239
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001240static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
1241 struct button_spec *buttonspec)
1242{
1243 ui->button[i] = gtk_button_new_with_label(buttonspec->buttontext);
1244 g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui);
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001245 gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3);
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001246 gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext);
Jens Axboe3e47bd22012-02-29 13:45:02 +01001247 gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive);
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001248}
1249
1250static void add_buttons(struct gui *ui,
1251 struct button_spec *buttonlist,
1252 int nbuttons)
1253{
1254 int i;
1255
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001256 for (i = 0; i < nbuttons; i++)
1257 add_button(ui, i, ui->buttonbox, &buttonlist[i]);
1258}
1259
Jens Axboe0420ba62012-02-29 11:16:52 +01001260static void on_info_bar_response(GtkWidget *widget, gint response,
1261 gpointer data)
1262{
1263 if (response == GTK_RESPONSE_OK) {
1264 gtk_widget_destroy(widget);
1265 ui.error_info_bar = NULL;
1266 }
1267}
1268
Jens Axboedf06f222012-03-02 13:32:04 +01001269void report_error(GError *error)
Jens Axboe0420ba62012-02-29 11:16:52 +01001270{
1271 if (ui.error_info_bar == NULL) {
1272 ui.error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK,
1273 GTK_RESPONSE_OK,
1274 NULL);
1275 g_signal_connect(ui.error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL);
1276 gtk_info_bar_set_message_type(GTK_INFO_BAR(ui.error_info_bar),
1277 GTK_MESSAGE_ERROR);
1278
1279 ui.error_label = gtk_label_new(error->message);
1280 GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(ui.error_info_bar));
1281 gtk_container_add(GTK_CONTAINER(container), ui.error_label);
1282
1283 gtk_box_pack_start(GTK_BOX(ui.vbox), ui.error_info_bar, FALSE, FALSE, 0);
1284 gtk_widget_show_all(ui.vbox);
1285 } else {
1286 char buffer[256];
1287 snprintf(buffer, sizeof(buffer), "Failed to open file.");
1288 gtk_label_set(GTK_LABEL(ui.error_label), buffer);
1289 }
1290}
1291
Jens Axboeb9f3c7e2012-03-02 14:27:17 +01001292static int get_connection_details(char **host, int *port, int *type,
1293 int *server_start)
Jens Axboea7a42ce2012-03-02 13:12:04 +01001294{
1295 GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +01001296 GtkWidget *button;
Jens Axboea7a42ce2012-03-02 13:12:04 +01001297 char *typeentry;
1298
1299 dialog = gtk_dialog_new_with_buttons("Connection details",
1300 GTK_WINDOW(ui.window),
1301 GTK_DIALOG_DESTROY_WITH_PARENT,
1302 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1303 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
1304
1305 frame = gtk_frame_new("Hostname / socket name");
1306 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1307 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1308
1309 box = gtk_vbox_new(FALSE, 6);
1310 gtk_container_add(GTK_CONTAINER(frame), box);
1311
1312 hbox = gtk_hbox_new(TRUE, 10);
1313 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1314 hentry = gtk_entry_new();
1315 gtk_entry_set_text(GTK_ENTRY(hentry), "localhost");
1316 gtk_box_pack_start(GTK_BOX(hbox), hentry, TRUE, TRUE, 0);
1317
1318 frame = gtk_frame_new("Port");
1319 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1320 box = gtk_vbox_new(FALSE, 10);
1321 gtk_container_add(GTK_CONTAINER(frame), box);
1322
1323 hbox = gtk_hbox_new(TRUE, 4);
1324 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1325 pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT);
1326
1327 frame = gtk_frame_new("Type");
1328 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1329 box = gtk_vbox_new(FALSE, 10);
1330 gtk_container_add(GTK_CONTAINER(frame), box);
1331
1332 hbox = gtk_hbox_new(TRUE, 4);
1333 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1334
Jens Axboeb4655622012-03-06 13:46:21 +01001335 combo = gtk_combo_box_new_text();
1336 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "IPv4");
1337 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "IPv6");
1338 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "local socket");
Jens Axboea7a42ce2012-03-02 13:12:04 +01001339 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
1340
1341 gtk_container_add(GTK_CONTAINER(hbox), combo);
1342
Jens Axboeb9f3c7e2012-03-02 14:27:17 +01001343 frame = gtk_frame_new("Options");
1344 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1345 box = gtk_vbox_new(FALSE, 10);
1346 gtk_container_add(GTK_CONTAINER(frame), box);
1347
1348 hbox = gtk_hbox_new(TRUE, 4);
1349 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1350
1351 button = gtk_check_button_new_with_label("Auto-spawn fio backend");
1352 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
1353 gtk_widget_set_tooltip_text(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.");
1354 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
1355
Jens Axboea7a42ce2012-03-02 13:12:04 +01001356 gtk_widget_show_all(dialog);
1357
1358 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
1359 gtk_widget_destroy(dialog);
1360 return 1;
1361 }
1362
1363 *host = strdup(gtk_entry_get_text(GTK_ENTRY(hentry)));
1364 *port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
1365
Jens Axboeb4655622012-03-06 13:46:21 +01001366 typeentry = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
Jens Axboea7a42ce2012-03-02 13:12:04 +01001367 if (!typeentry || !strncmp(typeentry, "IPv4", 4))
1368 *type = Fio_client_ipv4;
1369 else if (!strncmp(typeentry, "IPv6", 4))
1370 *type = Fio_client_ipv6;
1371 else
1372 *type = Fio_client_socket;
1373 g_free(typeentry);
1374
Jens Axboeb9f3c7e2012-03-02 14:27:17 +01001375 *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
1376
Jens Axboea7a42ce2012-03-02 13:12:04 +01001377 gtk_widget_destroy(dialog);
1378 return 0;
1379}
1380
Jens Axboee0681f32012-03-06 12:14:42 +01001381static void gfio_client_added(struct gui *ui, struct fio_client *client)
1382{
1383 struct gfio_client *gc;
1384
1385 gc = malloc(sizeof(*gc));
1386 memset(gc, 0, sizeof(*gc));
1387 gc->ui = ui;
1388
1389 client->client_data = gc;
1390}
1391
Jens Axboe0420ba62012-02-29 11:16:52 +01001392static void file_open(GtkWidget *w, gpointer data)
1393{
1394 GtkWidget *dialog;
1395 GSList *filenames, *fn_glist;
1396 GtkFileFilter *filter;
Jens Axboea7a42ce2012-03-02 13:12:04 +01001397 char *host;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +01001398 int port, type, server_start;
Jens Axboe0420ba62012-02-29 11:16:52 +01001399
1400 dialog = gtk_file_chooser_dialog_new("Open File",
1401 GTK_WINDOW(ui.window),
1402 GTK_FILE_CHOOSER_ACTION_OPEN,
1403 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1404 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1405 NULL);
1406 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
1407
1408 filter = gtk_file_filter_new();
1409 gtk_file_filter_add_pattern(filter, "*.fio");
1410 gtk_file_filter_add_pattern(filter, "*.job");
1411 gtk_file_filter_add_mime_type(filter, "text/fio");
1412 gtk_file_filter_set_name(filter, "Fio job file");
1413 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
1414
1415 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
1416 gtk_widget_destroy(dialog);
1417 return;
1418 }
1419
1420 fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
Jens Axboea7a42ce2012-03-02 13:12:04 +01001421
1422 gtk_widget_destroy(dialog);
1423
Jens Axboeb9f3c7e2012-03-02 14:27:17 +01001424 if (get_connection_details(&host, &port, &type, &server_start))
Jens Axboea7a42ce2012-03-02 13:12:04 +01001425 goto err;
1426
Jens Axboe0420ba62012-02-29 11:16:52 +01001427 filenames = fn_glist;
1428 while (filenames != NULL) {
Jens Axboee0681f32012-03-06 12:14:42 +01001429 struct fio_client *client;
1430
Jens Axboe0420ba62012-02-29 11:16:52 +01001431 ui.job_files = realloc(ui.job_files, (ui.nr_job_files + 1) * sizeof(char *));
1432 ui.job_files[ui.nr_job_files] = strdup(filenames->data);
1433 ui.nr_job_files++;
1434
Jens Axboee0681f32012-03-06 12:14:42 +01001435 client = fio_client_add_explicit(&gfio_client_ops, host, type, port);
1436 if (!client) {
Jens Axboedf06f222012-03-02 13:32:04 +01001437 GError *error;
1438
1439 error = g_error_new(g_quark_from_string("fio"), 1,
1440 "Failed to add client %s", host);
Jens Axboe0420ba62012-02-29 11:16:52 +01001441 report_error(error);
1442 g_error_free(error);
Jens Axboe0420ba62012-02-29 11:16:52 +01001443 }
Jens Axboee0681f32012-03-06 12:14:42 +01001444 gfio_client_added(&ui, client);
Jens Axboe0420ba62012-02-29 11:16:52 +01001445
1446 g_free(filenames->data);
1447 filenames = g_slist_next(filenames);
1448 }
Jens Axboea7a42ce2012-03-02 13:12:04 +01001449 free(host);
1450err:
Jens Axboe0420ba62012-02-29 11:16:52 +01001451 g_slist_free(fn_glist);
Jens Axboe0420ba62012-02-29 11:16:52 +01001452}
1453
1454static void file_save(GtkWidget *w, gpointer data)
1455{
1456 GtkWidget *dialog;
1457
1458 dialog = gtk_file_chooser_dialog_new("Save File",
1459 GTK_WINDOW(ui.window),
1460 GTK_FILE_CHOOSER_ACTION_SAVE,
1461 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1462 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
1463 NULL);
1464
1465 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
1466 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document");
1467
1468 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1469 char *filename;
1470
1471 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
1472 // save_job_file(filename);
1473 g_free(filename);
1474 }
1475 gtk_widget_destroy(dialog);
1476}
1477
Jens Axboe9b260bd2012-03-06 11:02:52 +01001478static void view_log_destroy(GtkWidget *w, gpointer data)
1479{
1480 struct gui *ui = (struct gui *) data;
1481
1482 gtk_widget_ref(ui->log_tree);
1483 gtk_container_remove(GTK_CONTAINER(w), ui->log_tree);
1484 gtk_widget_destroy(w);
Jens Axboe4cbe7212012-03-06 13:36:17 +01001485 ui->log_view = NULL;
Jens Axboe9b260bd2012-03-06 11:02:52 +01001486}
1487
1488static void view_log(GtkWidget *w, gpointer data)
1489{
Jens Axboe4cbe7212012-03-06 13:36:17 +01001490 GtkWidget *win, *scroll, *vbox, *box;
1491 struct gui *ui = (struct gui *) data;
Jens Axboe9b260bd2012-03-06 11:02:52 +01001492
Jens Axboe4cbe7212012-03-06 13:36:17 +01001493 if (ui->log_view)
1494 return;
1495
1496 ui->log_view = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
Jens Axboe9b260bd2012-03-06 11:02:52 +01001497 gtk_window_set_title(GTK_WINDOW(win), "Log");
Jens Axboe4cbe7212012-03-06 13:36:17 +01001498 gtk_window_set_default_size(GTK_WINDOW(win), 700, 500);
Jens Axboe9b260bd2012-03-06 11:02:52 +01001499
Jens Axboe4cbe7212012-03-06 13:36:17 +01001500 scroll = gtk_scrolled_window_new(NULL, NULL);
Jens Axboe9b260bd2012-03-06 11:02:52 +01001501
Jens Axboe4cbe7212012-03-06 13:36:17 +01001502 gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
1503
1504 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1505
1506 box = gtk_hbox_new(TRUE, 0);
1507 gtk_box_pack_start_defaults(GTK_BOX(box), ui->log_tree);
1508 g_signal_connect(box, "destroy", G_CALLBACK(view_log_destroy), ui);
1509 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), box);
1510
1511 vbox = gtk_vbox_new(TRUE, 5);
1512 gtk_box_pack_start_defaults(GTK_BOX(vbox), scroll);
1513
1514 gtk_container_add(GTK_CONTAINER(win), vbox);
Jens Axboe9b260bd2012-03-06 11:02:52 +01001515 gtk_widget_show_all(win);
1516}
1517
Jens Axboe46974a72012-03-02 19:34:13 +01001518static void preferences(GtkWidget *w, gpointer data)
1519{
1520 GtkWidget *dialog, *frame, *box, **buttons;
1521 int i;
1522
1523 dialog = gtk_dialog_new_with_buttons("Preferences",
1524 GTK_WINDOW(ui.window),
1525 GTK_DIALOG_DESTROY_WITH_PARENT,
1526 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1527 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1528 NULL);
1529
Jens Axboe0b8d11e2012-03-02 19:44:15 +01001530 frame = gtk_frame_new("Debug logging");
Jens Axboe46974a72012-03-02 19:34:13 +01001531 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
1532 box = gtk_hbox_new(FALSE, 6);
1533 gtk_container_add(GTK_CONTAINER(frame), box);
1534
1535 buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
1536
1537 for (i = 0; i < FD_DEBUG_MAX; i++) {
1538 buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
Jens Axboe0b8d11e2012-03-02 19:44:15 +01001539 gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
Jens Axboe46974a72012-03-02 19:34:13 +01001540 gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
1541 }
1542
1543 gtk_widget_show_all(dialog);
1544
1545 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
1546 gtk_widget_destroy(dialog);
1547 return;
1548 }
1549
1550 for (i = 0; i < FD_DEBUG_MAX; i++) {
1551 int set;
1552
1553 set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i]));
1554 if (set)
1555 fio_debug |= (1UL << i);
1556 }
1557
1558 gtk_widget_destroy(dialog);
1559}
1560
Jens Axboe0420ba62012-02-29 11:16:52 +01001561static void about_dialog(GtkWidget *w, gpointer data)
1562{
1563 gtk_show_about_dialog(NULL,
1564 "program-name", "gfio",
1565 "comments", "Gtk2 UI for fio",
1566 "license", "GPLv2",
1567 "version", fio_version_string,
1568 "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
1569 "logo-icon-name", "fio",
1570 /* Must be last: */
1571 NULL, NULL,
1572 NULL);
1573}
1574
1575static GtkActionEntry menu_items[] = {
Jens Axboe46974a72012-03-02 19:34:13 +01001576 { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
Jens Axboe9b260bd2012-03-06 11:02:52 +01001577 { "ViewMenuAction", GTK_STOCK_FILE, "View", NULL, NULL, NULL},
Jens Axboe46974a72012-03-02 19:34:13 +01001578 { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
1579 { "OpenFile", GTK_STOCK_OPEN, NULL, "<Control>O", NULL, G_CALLBACK(file_open) },
1580 { "SaveFile", GTK_STOCK_SAVE, NULL, "<Control>S", NULL, G_CALLBACK(file_save) },
1581 { "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) },
Jens Axboe9b260bd2012-03-06 11:02:52 +01001582 { "ViewLog", NULL, "Log", "<Control>l", NULL, G_CALLBACK(view_log) },
Jens Axboe46974a72012-03-02 19:34:13 +01001583 { "Quit", GTK_STOCK_QUIT, NULL, "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
1584 { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) },
Jens Axboe0420ba62012-02-29 11:16:52 +01001585};
Jens Axboe3e47bd22012-02-29 13:45:02 +01001586static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
Jens Axboe0420ba62012-02-29 11:16:52 +01001587
1588static const gchar *ui_string = " \
1589 <ui> \
1590 <menubar name=\"MainMenu\"> \
1591 <menu name=\"FileMenu\" action=\"FileMenuAction\"> \
1592 <menuitem name=\"Open\" action=\"OpenFile\" /> \
1593 <menuitem name=\"Save\" action=\"SaveFile\" /> \
1594 <separator name=\"Separator\"/> \
Jens Axboe46974a72012-03-02 19:34:13 +01001595 <menuitem name=\"Preferences\" action=\"Preferences\" /> \
1596 <separator name=\"Separator2\"/> \
Jens Axboe0420ba62012-02-29 11:16:52 +01001597 <menuitem name=\"Quit\" action=\"Quit\" /> \
1598 </menu> \
Jens Axboe9b260bd2012-03-06 11:02:52 +01001599 <menu name=\"ViewMenu\" action=\"ViewMenuAction\"> \
1600 <menuitem name=\"Log\" action=\"ViewLog\" /> \
1601 </menu>\
Jens Axboe0420ba62012-02-29 11:16:52 +01001602 <menu name=\"Help\" action=\"HelpMenuAction\"> \
1603 <menuitem name=\"About\" action=\"About\" /> \
1604 </menu> \
1605 </menubar> \
1606 </ui> \
1607";
1608
Jens Axboe4cbe7212012-03-06 13:36:17 +01001609static GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager,
1610 struct gui *ui)
Jens Axboe0420ba62012-02-29 11:16:52 +01001611{
1612 GtkActionGroup *action_group = gtk_action_group_new("Menu");
1613 GError *error = 0;
1614
1615 action_group = gtk_action_group_new("Menu");
Jens Axboe4cbe7212012-03-06 13:36:17 +01001616 gtk_action_group_add_actions(action_group, menu_items, nmenu_items, ui);
Jens Axboe0420ba62012-02-29 11:16:52 +01001617
1618 gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
1619 gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error);
1620
1621 gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager));
1622 return gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
1623}
1624
1625void gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar,
1626 GtkWidget *vbox, GtkUIManager *ui_manager)
1627{
1628 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
1629}
1630
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001631static void init_ui(int *argc, char **argv[], struct gui *ui)
1632{
Jens Axboe0420ba62012-02-29 11:16:52 +01001633 GtkSettings *settings;
1634 GtkUIManager *uimanager;
Jens Axboe843ad232012-02-29 11:44:53 +01001635 GtkWidget *menu, *probe, *probe_frame, *probe_box;
Jens Axboe0420ba62012-02-29 11:16:52 +01001636
1637 memset(ui, 0, sizeof(*ui));
Stephen M. Cameron45032dd2012-02-24 08:17:31 +01001638
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +01001639 /* Magical g*thread incantation, you just need this thread stuff.
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +01001640 * Without it, the update that happens in gfio_update_thread_status
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +01001641 * doesn't really happen in a timely fashion, you need expose events
1642 */
Jens Axboeed727a42012-03-02 12:14:40 +01001643 if (!g_thread_supported())
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +01001644 g_thread_init(NULL);
1645 gdk_threads_init();
1646
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001647 gtk_init(argc, argv);
Jens Axboe0420ba62012-02-29 11:16:52 +01001648 settings = gtk_settings_get_default();
1649 gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting");
1650 g_type_init();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001651
1652 ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1653 gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
1654 gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500);
1655
Jens Axboe0420ba62012-02-29 11:16:52 +01001656 g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
1657 g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001658
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +01001659 ui->vbox = gtk_vbox_new(FALSE, 0);
1660 gtk_container_add(GTK_CONTAINER (ui->window), ui->vbox);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +01001661
Jens Axboe0420ba62012-02-29 11:16:52 +01001662 uimanager = gtk_ui_manager_new();
Jens Axboe4cbe7212012-03-06 13:36:17 +01001663 menu = get_menubar_menu(ui->window, uimanager, ui);
Jens Axboe0420ba62012-02-29 11:16:52 +01001664 gfio_ui_setup(settings, menu, ui->vbox, uimanager);
1665
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +01001666 /*
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +01001667 * Set up alignments for widgets at the top of ui,
1668 * align top left, expand horizontally but not vertically
1669 */
1670 ui->topalign = gtk_alignment_new(0, 0, 1, 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001671 ui->topvbox = gtk_vbox_new(FALSE, 3);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +01001672 gtk_container_add(GTK_CONTAINER(ui->topalign), ui->topvbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +01001673 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->topalign, FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +01001674
Jens Axboe3e47bd22012-02-29 13:45:02 +01001675 probe = gtk_frame_new("Job");
Jens Axboe843ad232012-02-29 11:44:53 +01001676 gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3);
1677 probe_frame = gtk_vbox_new(FALSE, 3);
1678 gtk_container_add(GTK_CONTAINER(probe), probe_frame);
1679
1680 probe_box = gtk_hbox_new(FALSE, 3);
1681 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe843ad232012-02-29 11:44:53 +01001682 ui->probe.hostname = new_info_label_in_frame(probe_box, "Host");
1683 ui->probe.os = new_info_label_in_frame(probe_box, "OS");
1684 ui->probe.arch = new_info_label_in_frame(probe_box, "Architecture");
1685 ui->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version");
1686
Jens Axboe3e47bd22012-02-29 13:45:02 +01001687 probe_box = gtk_hbox_new(FALSE, 3);
1688 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe807f9972012-03-02 10:25:24 +01001689
Jens Axboeca850992012-03-05 20:04:43 +01001690 ui->eta.name = new_info_entry_in_frame(probe_box, "Name");
1691 ui->eta.iotype = new_info_entry_in_frame(probe_box, "IO");
1692 ui->eta.ioengine = new_info_entry_in_frame(probe_box, "IO Engine");
1693 ui->eta.iodepth = new_info_entry_in_frame(probe_box, "IO Depth");
1694 ui->eta.jobs = new_info_entry_in_frame(probe_box, "Jobs");
1695 ui->eta.files = new_info_entry_in_frame(probe_box, "Open files");
Jens Axboe3e47bd22012-02-29 13:45:02 +01001696
1697 probe_box = gtk_hbox_new(FALSE, 3);
1698 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboeca850992012-03-05 20:04:43 +01001699 ui->eta.read_bw = new_info_entry_in_frame(probe_box, "Read BW");
1700 ui->eta.read_iops = new_info_entry_in_frame(probe_box, "IOPS");
1701 ui->eta.write_bw = new_info_entry_in_frame(probe_box, "Write BW");
1702 ui->eta.write_iops = new_info_entry_in_frame(probe_box, "IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +01001703
1704 /*
1705 * Only add this if we have a commit rate
1706 */
1707#if 0
1708 probe_box = gtk_hbox_new(FALSE, 3);
1709 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
1710
Jens Axboe3e47bd22012-02-29 13:45:02 +01001711 ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
1712 ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
1713
Jens Axboe3e47bd22012-02-29 13:45:02 +01001714 ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
1715 ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +01001716#endif
Jens Axboe3e47bd22012-02-29 13:45:02 +01001717
Stephen M. Cameron45032dd2012-02-24 08:17:31 +01001718 /*
Stephen M. Cameron736f2df2012-02-24 08:17:32 +01001719 * Add a text box for text op messages
1720 */
1721 ui->textview = gtk_text_view_new();
1722 ui->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->textview));
1723 gtk_text_buffer_set_text(ui->text, "", -1);
1724 gtk_text_view_set_editable(GTK_TEXT_VIEW(ui->textview), FALSE);
1725 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ui->textview), FALSE);
1726 ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1727 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
1728 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1729 gtk_container_add(GTK_CONTAINER(ui->scrolled_window), ui->textview);
Stephen M. Camerone1645342012-02-24 08:17:32 +01001730 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->scrolled_window,
1731 TRUE, TRUE, 0);
Stephen M. Cameron736f2df2012-02-24 08:17:32 +01001732
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +01001733 /*
1734 * Set up alignments for widgets at the bottom of ui,
1735 * align bottom left, expand horizontally but not vertically
1736 */
1737 ui->bottomalign = gtk_alignment_new(0, 1, 1, 0);
1738 ui->buttonbox = gtk_hbox_new(FALSE, 0);
1739 gtk_container_add(GTK_CONTAINER(ui->bottomalign), ui->buttonbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +01001740 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->bottomalign,
1741 FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +01001742
Stephen M. Cameronf3074002012-02-24 08:17:30 +01001743 add_buttons(ui, buttonspeclist, ARRAYSIZE(buttonspeclist));
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001744
1745 /*
1746 * Set up thread status progress bar
1747 */
1748 ui->thread_status_pb = gtk_progress_bar_new();
1749 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
Jens Axboe8663ea62012-03-02 14:04:30 +01001750 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections");
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001751 gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb);
1752
Jens Axboe9b260bd2012-03-06 11:02:52 +01001753 gfio_ui_setup_log(ui);
Jens Axboe3ec62ec2012-03-01 12:01:29 +01001754
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001755 gtk_widget_show_all(ui->window);
1756}
1757
Stephen M. Cameron8232e282012-02-24 08:17:31 +01001758int main(int argc, char *argv[], char *envp[])
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001759{
Stephen M. Cameron8232e282012-02-24 08:17:31 +01001760 if (initialize_fio(envp))
1761 return 1;
Jens Axboe0420ba62012-02-29 11:16:52 +01001762 if (fio_init_options())
1763 return 1;
Stephen M. Camerona1820202012-02-24 08:17:31 +01001764
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001765 init_ui(&argc, &argv, &ui);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +01001766
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +01001767 gdk_threads_enter();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001768 gtk_main();
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +01001769 gdk_threads_leave();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +01001770 return 0;
1771}