blob: 157dd667f4ed928aca615626aa93f39deb4f4a4c [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;
Stephen M. Cameron736f2df2012-02-24 08:17:32 +010091 GtkTextBuffer *text;
Jens Axboe843ad232012-02-29 11:44:53 +010092 struct probe_widget probe;
Jens Axboe3e47bd22012-02-29 13:45:02 +010093 struct eta_widget eta;
Jens Axboe3ec62ec2012-03-01 12:01:29 +010094 int connected;
Stephen M. Cameron25927252012-02-24 08:17:31 +010095 pthread_t t;
Jens Axboe0420ba62012-02-29 11:16:52 +010096
Jens Axboe3ec62ec2012-03-01 12:01:29 +010097 struct fio_client *client;
Jens Axboe0420ba62012-02-29 11:16:52 +010098 int nr_job_files;
99 char **job_files;
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100100} ui;
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100101
Jens Axboe8663ea62012-03-02 14:04:30 +0100102static void clear_ui_info(struct gui *ui)
103{
104 gtk_label_set_text(GTK_LABEL(ui->probe.hostname), "");
105 gtk_label_set_text(GTK_LABEL(ui->probe.os), "");
106 gtk_label_set_text(GTK_LABEL(ui->probe.arch), "");
107 gtk_label_set_text(GTK_LABEL(ui->probe.fio_ver), "");
108 gtk_label_set_text(GTK_LABEL(ui->eta.name), "");
109 gtk_label_set_text(GTK_LABEL(ui->eta.iotype), "");
110 gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), "");
111 gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), "");
112 gtk_label_set_text(GTK_LABEL(ui->eta.jobs), "");
113 gtk_label_set_text(GTK_LABEL(ui->eta.files), "");
114 gtk_label_set_text(GTK_LABEL(ui->eta.read_bw), "");
115 gtk_label_set_text(GTK_LABEL(ui->eta.read_iops), "");
116 gtk_label_set_text(GTK_LABEL(ui->eta.write_bw), "");
117 gtk_label_set_text(GTK_LABEL(ui->eta.write_iops), "");
118}
119
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100120static void gfio_set_connected(struct gui *ui, int connected)
121{
122 if (connected) {
123 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
124 ui->connected = 1;
125 gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect");
126 } else {
127 ui->connected = 0;
128 gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect");
129 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
130 }
131}
132
Jens Axboe084d1c62012-03-03 20:28:07 +0100133static void gfio_text_op(struct fio_client *client, struct fio_net_cmd *cmd)
Stephen M. Camerona1820202012-02-24 08:17:31 +0100134{
Jens Axboe807f9972012-03-02 10:25:24 +0100135#if 0
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100136 GtkTextBuffer *buffer;
137 GtkTextIter end;
138
139 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui.textview));
140 gdk_threads_enter();
141 gtk_text_buffer_get_end_iter(buffer, &end);
142 gtk_text_buffer_insert(buffer, &end, buf, -1);
143 gdk_threads_leave();
144 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ui.textview),
145 &end, 0.0, FALSE, 0.0,0.0);
Jens Axboe807f9972012-03-02 10:25:24 +0100146#else
Jens Axboe084d1c62012-03-03 20:28:07 +0100147 fio_client_ops.text_op(client, cmd);
Jens Axboe807f9972012-03-02 10:25:24 +0100148#endif
Stephen M. Camerona1820202012-02-24 08:17:31 +0100149}
150
151static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd)
152{
153 printf("gfio_disk_util_op called\n");
154 fio_client_ops.disk_util(client, cmd);
155}
156
157static void gfio_thread_status_op(struct fio_net_cmd *cmd)
158{
159 printf("gfio_thread_status_op called\n");
160 fio_client_ops.thread_status(cmd);
161}
162
163static void gfio_group_stats_op(struct fio_net_cmd *cmd)
164{
165 printf("gfio_group_stats_op called\n");
166 fio_client_ops.group_stats(cmd);
167}
168
Jens Axboe3e47bd22012-02-29 13:45:02 +0100169static void gfio_update_eta(struct jobs_eta *je)
170{
171 static int eta_good;
172 char eta_str[128];
173 char output[256];
174 char tmp[32];
175 double perc = 0.0;
176 int i2p = 0;
177
178 eta_str[0] = '\0';
179 output[0] = '\0';
180
181 if (je->eta_sec != INT_MAX && je->elapsed_sec) {
182 perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec);
183 eta_to_str(eta_str, je->eta_sec);
184 }
185
186 sprintf(tmp, "%u", je->nr_running);
187 gtk_label_set_text(GTK_LABEL(ui.eta.jobs), tmp);
188 sprintf(tmp, "%u", je->files_open);
189 gtk_label_set_text(GTK_LABEL(ui.eta.files), tmp);
190
191#if 0
192 if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) {
193 if (je->m_rate || je->t_rate) {
194 char *tr, *mr;
195
196 mr = num2str(je->m_rate, 4, 0, i2p);
197 tr = num2str(je->t_rate, 4, 0, i2p);
198 gtk_label_set_text(GTK_LABEL(ui.eta.
199 p += sprintf(p, ", CR=%s/%s KB/s", tr, mr);
200 free(tr);
201 free(mr);
202 } else if (je->m_iops || je->t_iops)
203 p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops);
Jens Axboeebbd89c2012-03-02 11:21:13 +0100204
Jens Axboe3e47bd22012-02-29 13:45:02 +0100205 gtk_label_set_text(GTK_LABEL(ui.eta.cr_bw), "---");
206 gtk_label_set_text(GTK_LABEL(ui.eta.cr_iops), "---");
207 gtk_label_set_text(GTK_LABEL(ui.eta.cw_bw), "---");
208 gtk_label_set_text(GTK_LABEL(ui.eta.cw_iops), "---");
209#endif
210
211 if (je->eta_sec != INT_MAX && je->nr_running) {
212 char *iops_str[2];
213 char *rate_str[2];
214
215 if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running)
216 strcpy(output, "-.-% done");
217 else {
218 eta_good = 1;
219 perc *= 100.0;
220 sprintf(output, "%3.1f%% done", perc);
221 }
222
223 rate_str[0] = num2str(je->rate[0], 5, 10, i2p);
224 rate_str[1] = num2str(je->rate[1], 5, 10, i2p);
225
226 iops_str[0] = num2str(je->iops[0], 4, 1, 0);
227 iops_str[1] = num2str(je->iops[1], 4, 1, 0);
228
229 gtk_label_set_text(GTK_LABEL(ui.eta.read_bw), rate_str[0]);
230 gtk_label_set_text(GTK_LABEL(ui.eta.read_iops), iops_str[0]);
231 gtk_label_set_text(GTK_LABEL(ui.eta.write_bw), rate_str[1]);
232 gtk_label_set_text(GTK_LABEL(ui.eta.write_iops), iops_str[1]);
233
234 free(rate_str[0]);
235 free(rate_str[1]);
236 free(iops_str[0]);
237 free(iops_str[1]);
238 }
239
240 if (eta_str[0]) {
241 char *dst = output + strlen(output);
242
243 sprintf(dst, " - %s", eta_str);
244 }
245
246 gfio_update_thread_status(output, perc);
247}
248
Stephen M. Camerona1820202012-02-24 08:17:31 +0100249static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd)
250{
Jens Axboe843ad232012-02-29 11:44:53 +0100251 struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
252 const char *os, *arch;
253 char buf[64];
254
255 os = fio_get_os_string(probe->os);
256 if (!os)
257 os = "unknown";
258
259 arch = fio_get_arch_string(probe->arch);
260 if (!arch)
261 os = "unknown";
262
263 if (!client->name)
264 client->name = strdup((char *) probe->hostname);
265
266 gtk_label_set_text(GTK_LABEL(ui.probe.hostname), (char *) probe->hostname);
267 gtk_label_set_text(GTK_LABEL(ui.probe.os), os);
268 gtk_label_set_text(GTK_LABEL(ui.probe.arch), arch);
269 sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch);
270 gtk_label_set_text(GTK_LABEL(ui.probe.fio_ver), buf);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100271}
272
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100273static void gfio_update_thread_status(char *status_message, double perc)
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100274{
275 static char message[100];
276 const char *m = message;
277
278 strncpy(message, status_message, sizeof(message) - 1);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100279 gtk_progress_bar_set_text(
280 GTK_PROGRESS_BAR(ui.thread_status_pb), m);
281 gtk_progress_bar_set_fraction(
282 GTK_PROGRESS_BAR(ui.thread_status_pb), perc / 100.0);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100283 gdk_threads_enter();
284 gtk_widget_queue_draw(ui.window);
285 gdk_threads_leave();
286}
287
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100288static void gfio_quit_op(struct fio_client *client)
289{
290 struct gui *ui = client->client_data;
291
292 gfio_set_connected(ui, 0);
293}
294
Jens Axboe807f9972012-03-02 10:25:24 +0100295static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
296{
297 struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
298 struct gui *ui = client->client_data;
299 char tmp[8];
300 int i;
301
302 p->iodepth = le32_to_cpu(p->iodepth);
303 p->rw = le32_to_cpu(p->rw);
304
305 for (i = 0; i < 2; i++) {
306 p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
307 p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
308 }
309
310 p->numjobs = le32_to_cpu(p->numjobs);
311 p->group_reporting = le32_to_cpu(p->group_reporting);
312
313 gtk_label_set_text(GTK_LABEL(ui->eta.name), (gchar *) p->jobname);
314 gtk_label_set_text(GTK_LABEL(ui->eta.iotype), ddir_str(p->rw));
315 gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), (gchar *) p->ioengine);
316
317 sprintf(tmp, "%u", p->iodepth);
318 gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), tmp);
319}
320
Jens Axboeed727a42012-03-02 12:14:40 +0100321static void gfio_client_timed_out(struct fio_client *client)
322{
323 struct gui *ui = client->client_data;
324 GtkWidget *dialog, *label, *content;
325 char buf[256];
326
327 gdk_threads_enter();
328
329 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100330 clear_ui_info(ui);
Jens Axboeed727a42012-03-02 12:14:40 +0100331
332 sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname);
333
334 dialog = gtk_dialog_new_with_buttons("Timed out!",
335 GTK_WINDOW(ui->window),
336 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
337 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
338
339 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
340 label = gtk_label_new((const gchar *) buf);
341 gtk_container_add(GTK_CONTAINER(content), label);
342 gtk_widget_show_all(dialog);
343 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
344
345 gtk_dialog_run(GTK_DIALOG(dialog));
346 gtk_widget_destroy(dialog);
347
348 gdk_threads_leave();
349}
350
Stephen M. Camerona1820202012-02-24 08:17:31 +0100351struct client_ops gfio_client_ops = {
Jens Axboe0420ba62012-02-29 11:16:52 +0100352 .text_op = gfio_text_op,
353 .disk_util = gfio_disk_util_op,
354 .thread_status = gfio_thread_status_op,
355 .group_stats = gfio_group_stats_op,
Jens Axboea5276612012-03-04 15:15:08 +0100356 .eta = gfio_update_eta,
Jens Axboe0420ba62012-02-29 11:16:52 +0100357 .probe = gfio_probe_op,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100358 .quit = gfio_quit_op,
Jens Axboe807f9972012-03-02 10:25:24 +0100359 .add_job = gfio_add_job_op,
Jens Axboeed727a42012-03-02 12:14:40 +0100360 .timed_out = gfio_client_timed_out,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100361 .stay_connected = 1,
Stephen M. Camerona1820202012-02-24 08:17:31 +0100362};
363
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100364static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
365 __attribute__((unused)) gpointer data)
366{
367 gtk_main_quit();
368}
369
Stephen M. Cameron25927252012-02-24 08:17:31 +0100370static void *job_thread(void *arg)
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100371{
Stephen M. Cameron25927252012-02-24 08:17:31 +0100372 fio_handle_clients(&gfio_client_ops);
Stephen M. Cameron25927252012-02-24 08:17:31 +0100373 return NULL;
374}
375
Jens Axboe0420ba62012-02-29 11:16:52 +0100376static int send_job_files(struct gui *ui)
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100377{
Jens Axboe441013b2012-03-01 08:01:52 +0100378 int i, ret = 0;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100379
Jens Axboe0420ba62012-02-29 11:16:52 +0100380 for (i = 0; i < ui->nr_job_files; i++) {
381 ret = fio_clients_send_ini(ui->job_files[i]);
Jens Axboe441013b2012-03-01 08:01:52 +0100382 if (ret)
383 break;
384
Jens Axboe0420ba62012-02-29 11:16:52 +0100385 free(ui->job_files[i]);
386 ui->job_files[i] = NULL;
Jens Axboe441013b2012-03-01 08:01:52 +0100387 }
388 while (i < ui->nr_job_files) {
389 free(ui->job_files[i]);
390 ui->job_files[i] = NULL;
391 i++;
Jens Axboe0420ba62012-02-29 11:16:52 +0100392 }
393
Jens Axboe441013b2012-03-01 08:01:52 +0100394 return ret;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100395}
396
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100397static void start_job_thread(struct gui *ui)
Stephen M. Cameron25927252012-02-24 08:17:31 +0100398{
Jens Axboe0420ba62012-02-29 11:16:52 +0100399 if (send_job_files(ui)) {
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100400 printf("Yeah, I didn't really like those options too much.\n");
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100401 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
402 return;
403 }
Stephen M. Cameron25927252012-02-24 08:17:31 +0100404}
405
Jens Axboea7a42ce2012-03-02 13:12:04 +0100406static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
407{
408 GtkWidget *label_widget;
409 GtkWidget *frame;
410
411 frame = gtk_frame_new(label);
412 label_widget = gtk_label_new(NULL);
413 gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
414 gtk_container_add(GTK_CONTAINER(frame), label_widget);
415
416 return label_widget;
417}
418
Jens Axboea7a42ce2012-03-02 13:12:04 +0100419static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, double defval)
420{
421 GtkWidget *button, *box;
422
423 box = gtk_hbox_new(FALSE, 3);
424 gtk_container_add(GTK_CONTAINER(hbox), box);
425
426 button = gtk_spin_button_new_with_range(min, max, 1.0);
427 gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
428
429 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID);
430 gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), defval);
431
432 return button;
433}
434
Stephen M. Cameron25927252012-02-24 08:17:31 +0100435static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
436 gpointer data)
437{
438 struct gui *ui = data;
439
Stephen M. Cameron25927252012-02-24 08:17:31 +0100440 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100441 start_job_thread(ui);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100442}
443
Jens Axboedf06f222012-03-02 13:32:04 +0100444static void file_open(GtkWidget *w, gpointer data);
445
446static void connect_clicked(GtkWidget *widget, gpointer data)
Jens Axboe3e47bd22012-02-29 13:45:02 +0100447{
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100448 struct gui *ui = data;
449
450 if (!ui->connected) {
Jens Axboedf06f222012-03-02 13:32:04 +0100451 if (!ui->nr_job_files)
452 file_open(widget, data);
Jens Axboe8663ea62012-03-02 14:04:30 +0100453 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100454 fio_clients_connect();
455 pthread_create(&ui->t, NULL, job_thread, NULL);
456 gfio_set_connected(ui, 1);
Jens Axboedf06f222012-03-02 13:32:04 +0100457 } else {
458 fio_clients_terminate();
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100459 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100460 clear_ui_info(ui);
Jens Axboedf06f222012-03-02 13:32:04 +0100461 }
Jens Axboe3e47bd22012-02-29 13:45:02 +0100462}
463
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100464static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
465 struct button_spec *buttonspec)
466{
467 ui->button[i] = gtk_button_new_with_label(buttonspec->buttontext);
468 g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100469 gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100470 gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100471 gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100472}
473
474static void add_buttons(struct gui *ui,
475 struct button_spec *buttonlist,
476 int nbuttons)
477{
478 int i;
479
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100480 for (i = 0; i < nbuttons; i++)
481 add_button(ui, i, ui->buttonbox, &buttonlist[i]);
482}
483
Jens Axboe0420ba62012-02-29 11:16:52 +0100484static void on_info_bar_response(GtkWidget *widget, gint response,
485 gpointer data)
486{
487 if (response == GTK_RESPONSE_OK) {
488 gtk_widget_destroy(widget);
489 ui.error_info_bar = NULL;
490 }
491}
492
Jens Axboedf06f222012-03-02 13:32:04 +0100493void report_error(GError *error)
Jens Axboe0420ba62012-02-29 11:16:52 +0100494{
495 if (ui.error_info_bar == NULL) {
496 ui.error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK,
497 GTK_RESPONSE_OK,
498 NULL);
499 g_signal_connect(ui.error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL);
500 gtk_info_bar_set_message_type(GTK_INFO_BAR(ui.error_info_bar),
501 GTK_MESSAGE_ERROR);
502
503 ui.error_label = gtk_label_new(error->message);
504 GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(ui.error_info_bar));
505 gtk_container_add(GTK_CONTAINER(container), ui.error_label);
506
507 gtk_box_pack_start(GTK_BOX(ui.vbox), ui.error_info_bar, FALSE, FALSE, 0);
508 gtk_widget_show_all(ui.vbox);
509 } else {
510 char buffer[256];
511 snprintf(buffer, sizeof(buffer), "Failed to open file.");
512 gtk_label_set(GTK_LABEL(ui.error_label), buffer);
513 }
514}
515
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100516static int get_connection_details(char **host, int *port, int *type,
517 int *server_start)
Jens Axboea7a42ce2012-03-02 13:12:04 +0100518{
519 GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100520 GtkWidget *button;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100521 char *typeentry;
522
523 dialog = gtk_dialog_new_with_buttons("Connection details",
524 GTK_WINDOW(ui.window),
525 GTK_DIALOG_DESTROY_WITH_PARENT,
526 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
527 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
528
529 frame = gtk_frame_new("Hostname / socket name");
530 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
531 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
532
533 box = gtk_vbox_new(FALSE, 6);
534 gtk_container_add(GTK_CONTAINER(frame), box);
535
536 hbox = gtk_hbox_new(TRUE, 10);
537 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
538 hentry = gtk_entry_new();
539 gtk_entry_set_text(GTK_ENTRY(hentry), "localhost");
540 gtk_box_pack_start(GTK_BOX(hbox), hentry, TRUE, TRUE, 0);
541
542 frame = gtk_frame_new("Port");
543 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
544 box = gtk_vbox_new(FALSE, 10);
545 gtk_container_add(GTK_CONTAINER(frame), box);
546
547 hbox = gtk_hbox_new(TRUE, 4);
548 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
549 pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT);
550
551 frame = gtk_frame_new("Type");
552 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
553 box = gtk_vbox_new(FALSE, 10);
554 gtk_container_add(GTK_CONTAINER(frame), box);
555
556 hbox = gtk_hbox_new(TRUE, 4);
557 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
558
559 combo = gtk_combo_box_text_new();
560 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv4");
561 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv6");
562 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "local socket");
563 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
564
565 gtk_container_add(GTK_CONTAINER(hbox), combo);
566
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100567 frame = gtk_frame_new("Options");
568 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
569 box = gtk_vbox_new(FALSE, 10);
570 gtk_container_add(GTK_CONTAINER(frame), box);
571
572 hbox = gtk_hbox_new(TRUE, 4);
573 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
574
575 button = gtk_check_button_new_with_label("Auto-spawn fio backend");
576 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
577 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.");
578 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
579
Jens Axboea7a42ce2012-03-02 13:12:04 +0100580 gtk_widget_show_all(dialog);
581
582 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
583 gtk_widget_destroy(dialog);
584 return 1;
585 }
586
587 *host = strdup(gtk_entry_get_text(GTK_ENTRY(hentry)));
588 *port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
589
590 typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
591 if (!typeentry || !strncmp(typeentry, "IPv4", 4))
592 *type = Fio_client_ipv4;
593 else if (!strncmp(typeentry, "IPv6", 4))
594 *type = Fio_client_ipv6;
595 else
596 *type = Fio_client_socket;
597 g_free(typeentry);
598
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100599 *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
600
Jens Axboea7a42ce2012-03-02 13:12:04 +0100601 gtk_widget_destroy(dialog);
602 return 0;
603}
604
Jens Axboe0420ba62012-02-29 11:16:52 +0100605static void file_open(GtkWidget *w, gpointer data)
606{
607 GtkWidget *dialog;
608 GSList *filenames, *fn_glist;
609 GtkFileFilter *filter;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100610 char *host;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100611 int port, type, server_start;
Jens Axboe0420ba62012-02-29 11:16:52 +0100612
613 dialog = gtk_file_chooser_dialog_new("Open File",
614 GTK_WINDOW(ui.window),
615 GTK_FILE_CHOOSER_ACTION_OPEN,
616 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
617 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
618 NULL);
619 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
620
621 filter = gtk_file_filter_new();
622 gtk_file_filter_add_pattern(filter, "*.fio");
623 gtk_file_filter_add_pattern(filter, "*.job");
624 gtk_file_filter_add_mime_type(filter, "text/fio");
625 gtk_file_filter_set_name(filter, "Fio job file");
626 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
627
628 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
629 gtk_widget_destroy(dialog);
630 return;
631 }
632
633 fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
Jens Axboea7a42ce2012-03-02 13:12:04 +0100634
635 gtk_widget_destroy(dialog);
636
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100637 if (get_connection_details(&host, &port, &type, &server_start))
Jens Axboea7a42ce2012-03-02 13:12:04 +0100638 goto err;
639
Jens Axboe0420ba62012-02-29 11:16:52 +0100640 filenames = fn_glist;
641 while (filenames != NULL) {
Jens Axboe0420ba62012-02-29 11:16:52 +0100642 ui.job_files = realloc(ui.job_files, (ui.nr_job_files + 1) * sizeof(char *));
643 ui.job_files[ui.nr_job_files] = strdup(filenames->data);
644 ui.nr_job_files++;
645
Jens Axboea5276612012-03-04 15:15:08 +0100646 ui.client = fio_client_add_explicit(&gfio_client_ops, host, type, port);
Jens Axboedf06f222012-03-02 13:32:04 +0100647 if (!ui.client) {
648 GError *error;
649
650 error = g_error_new(g_quark_from_string("fio"), 1,
651 "Failed to add client %s", host);
Jens Axboe0420ba62012-02-29 11:16:52 +0100652 report_error(error);
653 g_error_free(error);
Jens Axboe0420ba62012-02-29 11:16:52 +0100654 }
Jens Axboedf06f222012-03-02 13:32:04 +0100655 ui.client->client_data = &ui;
Jens Axboe0420ba62012-02-29 11:16:52 +0100656
657 g_free(filenames->data);
658 filenames = g_slist_next(filenames);
659 }
Jens Axboea7a42ce2012-03-02 13:12:04 +0100660 free(host);
661err:
Jens Axboe0420ba62012-02-29 11:16:52 +0100662 g_slist_free(fn_glist);
Jens Axboe0420ba62012-02-29 11:16:52 +0100663}
664
665static void file_save(GtkWidget *w, gpointer data)
666{
667 GtkWidget *dialog;
668
669 dialog = gtk_file_chooser_dialog_new("Save File",
670 GTK_WINDOW(ui.window),
671 GTK_FILE_CHOOSER_ACTION_SAVE,
672 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
673 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
674 NULL);
675
676 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
677 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document");
678
679 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
680 char *filename;
681
682 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
683 // save_job_file(filename);
684 g_free(filename);
685 }
686 gtk_widget_destroy(dialog);
687}
688
Jens Axboe46974a72012-03-02 19:34:13 +0100689static void preferences(GtkWidget *w, gpointer data)
690{
691 GtkWidget *dialog, *frame, *box, **buttons;
692 int i;
693
694 dialog = gtk_dialog_new_with_buttons("Preferences",
695 GTK_WINDOW(ui.window),
696 GTK_DIALOG_DESTROY_WITH_PARENT,
697 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
698 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
699 NULL);
700
Jens Axboe0b8d11e2012-03-02 19:44:15 +0100701 frame = gtk_frame_new("Debug logging");
Jens Axboe46974a72012-03-02 19:34:13 +0100702 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
703 box = gtk_hbox_new(FALSE, 6);
704 gtk_container_add(GTK_CONTAINER(frame), box);
705
706 buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
707
708 for (i = 0; i < FD_DEBUG_MAX; i++) {
709 buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
Jens Axboe0b8d11e2012-03-02 19:44:15 +0100710 gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
Jens Axboe46974a72012-03-02 19:34:13 +0100711 gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
712 }
713
714 gtk_widget_show_all(dialog);
715
716 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
717 gtk_widget_destroy(dialog);
718 return;
719 }
720
721 for (i = 0; i < FD_DEBUG_MAX; i++) {
722 int set;
723
724 set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i]));
725 if (set)
726 fio_debug |= (1UL << i);
727 }
728
729 gtk_widget_destroy(dialog);
730}
731
Jens Axboe0420ba62012-02-29 11:16:52 +0100732static void about_dialog(GtkWidget *w, gpointer data)
733{
734 gtk_show_about_dialog(NULL,
735 "program-name", "gfio",
736 "comments", "Gtk2 UI for fio",
737 "license", "GPLv2",
738 "version", fio_version_string,
739 "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
740 "logo-icon-name", "fio",
741 /* Must be last: */
742 NULL, NULL,
743 NULL);
744}
745
746static GtkActionEntry menu_items[] = {
Jens Axboe46974a72012-03-02 19:34:13 +0100747 { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
748 { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
749 { "OpenFile", GTK_STOCK_OPEN, NULL, "<Control>O", NULL, G_CALLBACK(file_open) },
750 { "SaveFile", GTK_STOCK_SAVE, NULL, "<Control>S", NULL, G_CALLBACK(file_save) },
751 { "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) },
752 { "Quit", GTK_STOCK_QUIT, NULL, "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
753 { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) },
Jens Axboe0420ba62012-02-29 11:16:52 +0100754};
Jens Axboe3e47bd22012-02-29 13:45:02 +0100755static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
Jens Axboe0420ba62012-02-29 11:16:52 +0100756
757static const gchar *ui_string = " \
758 <ui> \
759 <menubar name=\"MainMenu\"> \
760 <menu name=\"FileMenu\" action=\"FileMenuAction\"> \
761 <menuitem name=\"Open\" action=\"OpenFile\" /> \
762 <menuitem name=\"Save\" action=\"SaveFile\" /> \
763 <separator name=\"Separator\"/> \
Jens Axboe46974a72012-03-02 19:34:13 +0100764 <menuitem name=\"Preferences\" action=\"Preferences\" /> \
765 <separator name=\"Separator2\"/> \
Jens Axboe0420ba62012-02-29 11:16:52 +0100766 <menuitem name=\"Quit\" action=\"Quit\" /> \
767 </menu> \
768 <menu name=\"Help\" action=\"HelpMenuAction\"> \
769 <menuitem name=\"About\" action=\"About\" /> \
770 </menu> \
771 </menubar> \
772 </ui> \
773";
774
775static GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager)
776{
777 GtkActionGroup *action_group = gtk_action_group_new("Menu");
778 GError *error = 0;
779
780 action_group = gtk_action_group_new("Menu");
781 gtk_action_group_add_actions(action_group, menu_items, nmenu_items, 0);
782
783 gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
784 gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error);
785
786 gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager));
787 return gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
788}
789
790void gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar,
791 GtkWidget *vbox, GtkUIManager *ui_manager)
792{
793 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
794}
795
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100796static void init_ui(int *argc, char **argv[], struct gui *ui)
797{
Jens Axboe0420ba62012-02-29 11:16:52 +0100798 GtkSettings *settings;
799 GtkUIManager *uimanager;
Jens Axboe843ad232012-02-29 11:44:53 +0100800 GtkWidget *menu, *probe, *probe_frame, *probe_box;
Jens Axboe0420ba62012-02-29 11:16:52 +0100801
802 memset(ui, 0, sizeof(*ui));
Stephen M. Cameron45032dd2012-02-24 08:17:31 +0100803
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100804 /* Magical g*thread incantation, you just need this thread stuff.
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100805 * Without it, the update that happens in gfio_update_thread_status
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100806 * doesn't really happen in a timely fashion, you need expose events
807 */
Jens Axboeed727a42012-03-02 12:14:40 +0100808 if (!g_thread_supported())
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100809 g_thread_init(NULL);
810 gdk_threads_init();
811
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100812 gtk_init(argc, argv);
Jens Axboe0420ba62012-02-29 11:16:52 +0100813 settings = gtk_settings_get_default();
814 gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting");
815 g_type_init();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100816
817 ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
818 gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
819 gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500);
820
Jens Axboe0420ba62012-02-29 11:16:52 +0100821 g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
822 g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100823
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100824 ui->vbox = gtk_vbox_new(FALSE, 0);
825 gtk_container_add(GTK_CONTAINER (ui->window), ui->vbox);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100826
Jens Axboe0420ba62012-02-29 11:16:52 +0100827 uimanager = gtk_ui_manager_new();
828 menu = get_menubar_menu(ui->window, uimanager);
829 gfio_ui_setup(settings, menu, ui->vbox, uimanager);
830
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100831 /*
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100832 * Set up alignments for widgets at the top of ui,
833 * align top left, expand horizontally but not vertically
834 */
835 ui->topalign = gtk_alignment_new(0, 0, 1, 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100836 ui->topvbox = gtk_vbox_new(FALSE, 3);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100837 gtk_container_add(GTK_CONTAINER(ui->topalign), ui->topvbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100838 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->topalign, FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100839
Jens Axboe3e47bd22012-02-29 13:45:02 +0100840 probe = gtk_frame_new("Job");
Jens Axboe843ad232012-02-29 11:44:53 +0100841 gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3);
842 probe_frame = gtk_vbox_new(FALSE, 3);
843 gtk_container_add(GTK_CONTAINER(probe), probe_frame);
844
845 probe_box = gtk_hbox_new(FALSE, 3);
846 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe843ad232012-02-29 11:44:53 +0100847 ui->probe.hostname = new_info_label_in_frame(probe_box, "Host");
848 ui->probe.os = new_info_label_in_frame(probe_box, "OS");
849 ui->probe.arch = new_info_label_in_frame(probe_box, "Architecture");
850 ui->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version");
851
Jens Axboe3e47bd22012-02-29 13:45:02 +0100852 probe_box = gtk_hbox_new(FALSE, 3);
853 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe807f9972012-03-02 10:25:24 +0100854
855 ui->eta.name = new_info_label_in_frame(probe_box, "Name");
856 ui->eta.iotype = new_info_label_in_frame(probe_box, "IO");
857 ui->eta.ioengine = new_info_label_in_frame(probe_box, "IO Engine");
858 ui->eta.iodepth = new_info_label_in_frame(probe_box, "IO Depth");
Jens Axboe3e47bd22012-02-29 13:45:02 +0100859 ui->eta.jobs = new_info_label_in_frame(probe_box, "Jobs");
860 ui->eta.files = new_info_label_in_frame(probe_box, "Open files");
861
862 probe_box = gtk_hbox_new(FALSE, 3);
863 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
864 ui->eta.read_bw = new_info_label_in_frame(probe_box, "Read BW");
865 ui->eta.read_iops = new_info_label_in_frame(probe_box, "IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +0100866 ui->eta.write_bw = new_info_label_in_frame(probe_box, "Write BW");
867 ui->eta.write_iops = new_info_label_in_frame(probe_box, "IOPS");
868
869 /*
870 * Only add this if we have a commit rate
871 */
872#if 0
873 probe_box = gtk_hbox_new(FALSE, 3);
874 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
875
Jens Axboe3e47bd22012-02-29 13:45:02 +0100876 ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
877 ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
878
Jens Axboe3e47bd22012-02-29 13:45:02 +0100879 ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
880 ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +0100881#endif
Jens Axboe3e47bd22012-02-29 13:45:02 +0100882
Stephen M. Cameron45032dd2012-02-24 08:17:31 +0100883 /*
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100884 * Add a text box for text op messages
885 */
886 ui->textview = gtk_text_view_new();
887 ui->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->textview));
888 gtk_text_buffer_set_text(ui->text, "", -1);
889 gtk_text_view_set_editable(GTK_TEXT_VIEW(ui->textview), FALSE);
890 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ui->textview), FALSE);
891 ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
892 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
893 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
894 gtk_container_add(GTK_CONTAINER(ui->scrolled_window), ui->textview);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100895 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->scrolled_window,
896 TRUE, TRUE, 0);
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100897
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100898 /*
899 * Set up alignments for widgets at the bottom of ui,
900 * align bottom left, expand horizontally but not vertically
901 */
902 ui->bottomalign = gtk_alignment_new(0, 1, 1, 0);
903 ui->buttonbox = gtk_hbox_new(FALSE, 0);
904 gtk_container_add(GTK_CONTAINER(ui->bottomalign), ui->buttonbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100905 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->bottomalign,
906 FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100907
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100908 add_buttons(ui, buttonspeclist, ARRAYSIZE(buttonspeclist));
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100909
910 /*
911 * Set up thread status progress bar
912 */
913 ui->thread_status_pb = gtk_progress_bar_new();
914 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
Jens Axboe8663ea62012-03-02 14:04:30 +0100915 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100916 gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb);
917
918
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100919 gtk_widget_show_all(ui->window);
920}
921
Stephen M. Cameron8232e282012-02-24 08:17:31 +0100922int main(int argc, char *argv[], char *envp[])
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100923{
Stephen M. Cameron8232e282012-02-24 08:17:31 +0100924 if (initialize_fio(envp))
925 return 1;
Jens Axboe0420ba62012-02-29 11:16:52 +0100926 if (fio_init_options())
927 return 1;
Stephen M. Camerona1820202012-02-24 08:17:31 +0100928
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100929 init_ui(&argc, &argv, &ui);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100930
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100931 gdk_threads_enter();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100932 gtk_main();
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100933 gdk_threads_leave();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100934 return 0;
935}