blob: f39bfbff8f226f25510ba2e1412af480442af54b [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
Stephen M. Camerona1820202012-02-24 08:17:31 +0100133static void gfio_text_op(struct fio_client *client,
134 FILE *f, __u16 pdu_len, const char *buf)
135{
Jens Axboe807f9972012-03-02 10:25:24 +0100136#if 0
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100137 GtkTextBuffer *buffer;
138 GtkTextIter end;
139
140 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui.textview));
141 gdk_threads_enter();
142 gtk_text_buffer_get_end_iter(buffer, &end);
143 gtk_text_buffer_insert(buffer, &end, buf, -1);
144 gdk_threads_leave();
145 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ui.textview),
146 &end, 0.0, FALSE, 0.0,0.0);
Jens Axboe807f9972012-03-02 10:25:24 +0100147#else
148 fio_client_ops.text_op(client, f, pdu_len, buf);
149#endif
Stephen M. Camerona1820202012-02-24 08:17:31 +0100150}
151
152static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd)
153{
154 printf("gfio_disk_util_op called\n");
155 fio_client_ops.disk_util(client, cmd);
156}
157
158static void gfio_thread_status_op(struct fio_net_cmd *cmd)
159{
160 printf("gfio_thread_status_op called\n");
161 fio_client_ops.thread_status(cmd);
162}
163
164static void gfio_group_stats_op(struct fio_net_cmd *cmd)
165{
166 printf("gfio_group_stats_op called\n");
167 fio_client_ops.group_stats(cmd);
168}
169
Jens Axboe3e47bd22012-02-29 13:45:02 +0100170static void gfio_update_eta(struct jobs_eta *je)
171{
172 static int eta_good;
173 char eta_str[128];
174 char output[256];
175 char tmp[32];
176 double perc = 0.0;
177 int i2p = 0;
178
179 eta_str[0] = '\0';
180 output[0] = '\0';
181
182 if (je->eta_sec != INT_MAX && je->elapsed_sec) {
183 perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec);
184 eta_to_str(eta_str, je->eta_sec);
185 }
186
187 sprintf(tmp, "%u", je->nr_running);
188 gtk_label_set_text(GTK_LABEL(ui.eta.jobs), tmp);
189 sprintf(tmp, "%u", je->files_open);
190 gtk_label_set_text(GTK_LABEL(ui.eta.files), tmp);
191
192#if 0
193 if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) {
194 if (je->m_rate || je->t_rate) {
195 char *tr, *mr;
196
197 mr = num2str(je->m_rate, 4, 0, i2p);
198 tr = num2str(je->t_rate, 4, 0, i2p);
199 gtk_label_set_text(GTK_LABEL(ui.eta.
200 p += sprintf(p, ", CR=%s/%s KB/s", tr, mr);
201 free(tr);
202 free(mr);
203 } else if (je->m_iops || je->t_iops)
204 p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops);
Jens Axboeebbd89c2012-03-02 11:21:13 +0100205
Jens Axboe3e47bd22012-02-29 13:45:02 +0100206 gtk_label_set_text(GTK_LABEL(ui.eta.cr_bw), "---");
207 gtk_label_set_text(GTK_LABEL(ui.eta.cr_iops), "---");
208 gtk_label_set_text(GTK_LABEL(ui.eta.cw_bw), "---");
209 gtk_label_set_text(GTK_LABEL(ui.eta.cw_iops), "---");
210#endif
211
212 if (je->eta_sec != INT_MAX && je->nr_running) {
213 char *iops_str[2];
214 char *rate_str[2];
215
216 if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running)
217 strcpy(output, "-.-% done");
218 else {
219 eta_good = 1;
220 perc *= 100.0;
221 sprintf(output, "%3.1f%% done", perc);
222 }
223
224 rate_str[0] = num2str(je->rate[0], 5, 10, i2p);
225 rate_str[1] = num2str(je->rate[1], 5, 10, i2p);
226
227 iops_str[0] = num2str(je->iops[0], 4, 1, 0);
228 iops_str[1] = num2str(je->iops[1], 4, 1, 0);
229
230 gtk_label_set_text(GTK_LABEL(ui.eta.read_bw), rate_str[0]);
231 gtk_label_set_text(GTK_LABEL(ui.eta.read_iops), iops_str[0]);
232 gtk_label_set_text(GTK_LABEL(ui.eta.write_bw), rate_str[1]);
233 gtk_label_set_text(GTK_LABEL(ui.eta.write_iops), iops_str[1]);
234
235 free(rate_str[0]);
236 free(rate_str[1]);
237 free(iops_str[0]);
238 free(iops_str[1]);
239 }
240
241 if (eta_str[0]) {
242 char *dst = output + strlen(output);
243
244 sprintf(dst, " - %s", eta_str);
245 }
246
247 gfio_update_thread_status(output, perc);
248}
249
Stephen M. Camerona1820202012-02-24 08:17:31 +0100250static void gfio_eta_op(struct fio_client *client, struct fio_net_cmd *cmd)
251{
Jens Axboe3e47bd22012-02-29 13:45:02 +0100252 struct jobs_eta *je = (struct jobs_eta *) cmd->payload;
253 struct client_eta *eta = (struct client_eta *) (uintptr_t) cmd->tag;
254
255 client->eta_in_flight = NULL;
256 flist_del_init(&client->eta_list);
257
258 fio_client_convert_jobs_eta(je);
259 fio_client_sum_jobs_eta(&eta->eta, je);
260 fio_client_dec_jobs_eta(eta, gfio_update_eta);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100261}
262
263static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd)
264{
Jens Axboe843ad232012-02-29 11:44:53 +0100265 struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
266 const char *os, *arch;
267 char buf[64];
268
269 os = fio_get_os_string(probe->os);
270 if (!os)
271 os = "unknown";
272
273 arch = fio_get_arch_string(probe->arch);
274 if (!arch)
275 os = "unknown";
276
277 if (!client->name)
278 client->name = strdup((char *) probe->hostname);
279
280 gtk_label_set_text(GTK_LABEL(ui.probe.hostname), (char *) probe->hostname);
281 gtk_label_set_text(GTK_LABEL(ui.probe.os), os);
282 gtk_label_set_text(GTK_LABEL(ui.probe.arch), arch);
283 sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch);
284 gtk_label_set_text(GTK_LABEL(ui.probe.fio_ver), buf);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100285}
286
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100287static void gfio_update_thread_status(char *status_message, double perc)
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100288{
289 static char message[100];
290 const char *m = message;
291
292 strncpy(message, status_message, sizeof(message) - 1);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100293 gtk_progress_bar_set_text(
294 GTK_PROGRESS_BAR(ui.thread_status_pb), m);
295 gtk_progress_bar_set_fraction(
296 GTK_PROGRESS_BAR(ui.thread_status_pb), perc / 100.0);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100297 gdk_threads_enter();
298 gtk_widget_queue_draw(ui.window);
299 gdk_threads_leave();
300}
301
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100302static void gfio_quit_op(struct fio_client *client)
303{
304 struct gui *ui = client->client_data;
305
306 gfio_set_connected(ui, 0);
307}
308
Jens Axboe807f9972012-03-02 10:25:24 +0100309static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
310{
311 struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
312 struct gui *ui = client->client_data;
313 char tmp[8];
314 int i;
315
316 p->iodepth = le32_to_cpu(p->iodepth);
317 p->rw = le32_to_cpu(p->rw);
318
319 for (i = 0; i < 2; i++) {
320 p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
321 p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
322 }
323
324 p->numjobs = le32_to_cpu(p->numjobs);
325 p->group_reporting = le32_to_cpu(p->group_reporting);
326
327 gtk_label_set_text(GTK_LABEL(ui->eta.name), (gchar *) p->jobname);
328 gtk_label_set_text(GTK_LABEL(ui->eta.iotype), ddir_str(p->rw));
329 gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), (gchar *) p->ioengine);
330
331 sprintf(tmp, "%u", p->iodepth);
332 gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), tmp);
333}
334
Jens Axboeed727a42012-03-02 12:14:40 +0100335static void gfio_client_timed_out(struct fio_client *client)
336{
337 struct gui *ui = client->client_data;
338 GtkWidget *dialog, *label, *content;
339 char buf[256];
340
341 gdk_threads_enter();
342
343 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100344 clear_ui_info(ui);
Jens Axboeed727a42012-03-02 12:14:40 +0100345
346 sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname);
347
348 dialog = gtk_dialog_new_with_buttons("Timed out!",
349 GTK_WINDOW(ui->window),
350 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
351 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
352
353 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
354 label = gtk_label_new((const gchar *) buf);
355 gtk_container_add(GTK_CONTAINER(content), label);
356 gtk_widget_show_all(dialog);
357 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
358
359 gtk_dialog_run(GTK_DIALOG(dialog));
360 gtk_widget_destroy(dialog);
361
362 gdk_threads_leave();
363}
364
Stephen M. Camerona1820202012-02-24 08:17:31 +0100365struct client_ops gfio_client_ops = {
Jens Axboe0420ba62012-02-29 11:16:52 +0100366 .text_op = gfio_text_op,
367 .disk_util = gfio_disk_util_op,
368 .thread_status = gfio_thread_status_op,
369 .group_stats = gfio_group_stats_op,
370 .eta = gfio_eta_op,
371 .probe = gfio_probe_op,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100372 .quit = gfio_quit_op,
Jens Axboe807f9972012-03-02 10:25:24 +0100373 .add_job = gfio_add_job_op,
Jens Axboeed727a42012-03-02 12:14:40 +0100374 .timed_out = gfio_client_timed_out,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100375 .stay_connected = 1,
Stephen M. Camerona1820202012-02-24 08:17:31 +0100376};
377
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100378static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
379 __attribute__((unused)) gpointer data)
380{
381 gtk_main_quit();
382}
383
Stephen M. Cameron25927252012-02-24 08:17:31 +0100384static void *job_thread(void *arg)
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100385{
Stephen M. Cameron25927252012-02-24 08:17:31 +0100386 fio_handle_clients(&gfio_client_ops);
Stephen M. Cameron25927252012-02-24 08:17:31 +0100387 return NULL;
388}
389
Jens Axboe0420ba62012-02-29 11:16:52 +0100390static int send_job_files(struct gui *ui)
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100391{
Jens Axboe441013b2012-03-01 08:01:52 +0100392 int i, ret = 0;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100393
Jens Axboe0420ba62012-02-29 11:16:52 +0100394 for (i = 0; i < ui->nr_job_files; i++) {
395 ret = fio_clients_send_ini(ui->job_files[i]);
Jens Axboe441013b2012-03-01 08:01:52 +0100396 if (ret)
397 break;
398
Jens Axboe0420ba62012-02-29 11:16:52 +0100399 free(ui->job_files[i]);
400 ui->job_files[i] = NULL;
Jens Axboe441013b2012-03-01 08:01:52 +0100401 }
402 while (i < ui->nr_job_files) {
403 free(ui->job_files[i]);
404 ui->job_files[i] = NULL;
405 i++;
Jens Axboe0420ba62012-02-29 11:16:52 +0100406 }
407
Jens Axboe441013b2012-03-01 08:01:52 +0100408 return ret;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100409}
410
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100411static void start_job_thread(struct gui *ui)
Stephen M. Cameron25927252012-02-24 08:17:31 +0100412{
Jens Axboe0420ba62012-02-29 11:16:52 +0100413 if (send_job_files(ui)) {
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100414 printf("Yeah, I didn't really like those options too much.\n");
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100415 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
416 return;
417 }
Stephen M. Cameron25927252012-02-24 08:17:31 +0100418}
419
Jens Axboea7a42ce2012-03-02 13:12:04 +0100420static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
421{
422 GtkWidget *label_widget;
423 GtkWidget *frame;
424
425 frame = gtk_frame_new(label);
426 label_widget = gtk_label_new(NULL);
427 gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
428 gtk_container_add(GTK_CONTAINER(frame), label_widget);
429
430 return label_widget;
431}
432
Jens Axboea7a42ce2012-03-02 13:12:04 +0100433static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, double defval)
434{
435 GtkWidget *button, *box;
436
437 box = gtk_hbox_new(FALSE, 3);
438 gtk_container_add(GTK_CONTAINER(hbox), box);
439
440 button = gtk_spin_button_new_with_range(min, max, 1.0);
441 gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
442
443 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID);
444 gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), defval);
445
446 return button;
447}
448
Stephen M. Cameron25927252012-02-24 08:17:31 +0100449static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
450 gpointer data)
451{
452 struct gui *ui = data;
453
Stephen M. Cameron25927252012-02-24 08:17:31 +0100454 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100455 start_job_thread(ui);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100456}
457
Jens Axboedf06f222012-03-02 13:32:04 +0100458static void file_open(GtkWidget *w, gpointer data);
459
460static void connect_clicked(GtkWidget *widget, gpointer data)
Jens Axboe3e47bd22012-02-29 13:45:02 +0100461{
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100462 struct gui *ui = data;
463
464 if (!ui->connected) {
Jens Axboedf06f222012-03-02 13:32:04 +0100465 if (!ui->nr_job_files)
466 file_open(widget, data);
Jens Axboe8663ea62012-03-02 14:04:30 +0100467 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100468 fio_clients_connect();
469 pthread_create(&ui->t, NULL, job_thread, NULL);
470 gfio_set_connected(ui, 1);
Jens Axboedf06f222012-03-02 13:32:04 +0100471 } else {
472 fio_clients_terminate();
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100473 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100474 clear_ui_info(ui);
Jens Axboedf06f222012-03-02 13:32:04 +0100475 }
Jens Axboe3e47bd22012-02-29 13:45:02 +0100476}
477
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100478static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
479 struct button_spec *buttonspec)
480{
481 ui->button[i] = gtk_button_new_with_label(buttonspec->buttontext);
482 g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100483 gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100484 gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100485 gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100486}
487
488static void add_buttons(struct gui *ui,
489 struct button_spec *buttonlist,
490 int nbuttons)
491{
492 int i;
493
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100494 for (i = 0; i < nbuttons; i++)
495 add_button(ui, i, ui->buttonbox, &buttonlist[i]);
496}
497
Jens Axboe0420ba62012-02-29 11:16:52 +0100498static void on_info_bar_response(GtkWidget *widget, gint response,
499 gpointer data)
500{
501 if (response == GTK_RESPONSE_OK) {
502 gtk_widget_destroy(widget);
503 ui.error_info_bar = NULL;
504 }
505}
506
Jens Axboedf06f222012-03-02 13:32:04 +0100507void report_error(GError *error)
Jens Axboe0420ba62012-02-29 11:16:52 +0100508{
509 if (ui.error_info_bar == NULL) {
510 ui.error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK,
511 GTK_RESPONSE_OK,
512 NULL);
513 g_signal_connect(ui.error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL);
514 gtk_info_bar_set_message_type(GTK_INFO_BAR(ui.error_info_bar),
515 GTK_MESSAGE_ERROR);
516
517 ui.error_label = gtk_label_new(error->message);
518 GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(ui.error_info_bar));
519 gtk_container_add(GTK_CONTAINER(container), ui.error_label);
520
521 gtk_box_pack_start(GTK_BOX(ui.vbox), ui.error_info_bar, FALSE, FALSE, 0);
522 gtk_widget_show_all(ui.vbox);
523 } else {
524 char buffer[256];
525 snprintf(buffer, sizeof(buffer), "Failed to open file.");
526 gtk_label_set(GTK_LABEL(ui.error_label), buffer);
527 }
528}
529
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100530static int get_connection_details(char **host, int *port, int *type,
531 int *server_start)
Jens Axboea7a42ce2012-03-02 13:12:04 +0100532{
533 GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100534 GtkWidget *button;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100535 char *typeentry;
536
537 dialog = gtk_dialog_new_with_buttons("Connection details",
538 GTK_WINDOW(ui.window),
539 GTK_DIALOG_DESTROY_WITH_PARENT,
540 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
541 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
542
543 frame = gtk_frame_new("Hostname / socket name");
544 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
545 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
546
547 box = gtk_vbox_new(FALSE, 6);
548 gtk_container_add(GTK_CONTAINER(frame), box);
549
550 hbox = gtk_hbox_new(TRUE, 10);
551 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
552 hentry = gtk_entry_new();
553 gtk_entry_set_text(GTK_ENTRY(hentry), "localhost");
554 gtk_box_pack_start(GTK_BOX(hbox), hentry, TRUE, TRUE, 0);
555
556 frame = gtk_frame_new("Port");
557 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
558 box = gtk_vbox_new(FALSE, 10);
559 gtk_container_add(GTK_CONTAINER(frame), box);
560
561 hbox = gtk_hbox_new(TRUE, 4);
562 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
563 pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT);
564
565 frame = gtk_frame_new("Type");
566 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
567 box = gtk_vbox_new(FALSE, 10);
568 gtk_container_add(GTK_CONTAINER(frame), box);
569
570 hbox = gtk_hbox_new(TRUE, 4);
571 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
572
573 combo = gtk_combo_box_text_new();
574 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv4");
575 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv6");
576 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "local socket");
577 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
578
579 gtk_container_add(GTK_CONTAINER(hbox), combo);
580
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100581 frame = gtk_frame_new("Options");
582 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
583 box = gtk_vbox_new(FALSE, 10);
584 gtk_container_add(GTK_CONTAINER(frame), box);
585
586 hbox = gtk_hbox_new(TRUE, 4);
587 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
588
589 button = gtk_check_button_new_with_label("Auto-spawn fio backend");
590 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
591 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.");
592 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
593
Jens Axboea7a42ce2012-03-02 13:12:04 +0100594 gtk_widget_show_all(dialog);
595
596 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
597 gtk_widget_destroy(dialog);
598 return 1;
599 }
600
601 *host = strdup(gtk_entry_get_text(GTK_ENTRY(hentry)));
602 *port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
603
604 typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
605 if (!typeentry || !strncmp(typeentry, "IPv4", 4))
606 *type = Fio_client_ipv4;
607 else if (!strncmp(typeentry, "IPv6", 4))
608 *type = Fio_client_ipv6;
609 else
610 *type = Fio_client_socket;
611 g_free(typeentry);
612
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100613 *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
614
Jens Axboea7a42ce2012-03-02 13:12:04 +0100615 gtk_widget_destroy(dialog);
616 return 0;
617}
618
Jens Axboe0420ba62012-02-29 11:16:52 +0100619static void file_open(GtkWidget *w, gpointer data)
620{
621 GtkWidget *dialog;
622 GSList *filenames, *fn_glist;
623 GtkFileFilter *filter;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100624 char *host;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100625 int port, type, server_start;
Jens Axboe0420ba62012-02-29 11:16:52 +0100626
627 dialog = gtk_file_chooser_dialog_new("Open File",
628 GTK_WINDOW(ui.window),
629 GTK_FILE_CHOOSER_ACTION_OPEN,
630 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
631 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
632 NULL);
633 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
634
635 filter = gtk_file_filter_new();
636 gtk_file_filter_add_pattern(filter, "*.fio");
637 gtk_file_filter_add_pattern(filter, "*.job");
638 gtk_file_filter_add_mime_type(filter, "text/fio");
639 gtk_file_filter_set_name(filter, "Fio job file");
640 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
641
642 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
643 gtk_widget_destroy(dialog);
644 return;
645 }
646
647 fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
Jens Axboea7a42ce2012-03-02 13:12:04 +0100648
649 gtk_widget_destroy(dialog);
650
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100651 if (get_connection_details(&host, &port, &type, &server_start))
Jens Axboea7a42ce2012-03-02 13:12:04 +0100652 goto err;
653
Jens Axboe0420ba62012-02-29 11:16:52 +0100654 filenames = fn_glist;
655 while (filenames != NULL) {
Jens Axboe0420ba62012-02-29 11:16:52 +0100656 ui.job_files = realloc(ui.job_files, (ui.nr_job_files + 1) * sizeof(char *));
657 ui.job_files[ui.nr_job_files] = strdup(filenames->data);
658 ui.nr_job_files++;
659
Jens Axboea7a42ce2012-03-02 13:12:04 +0100660 ui.client = fio_client_add_explicit(host, type, port);
Jens Axboedf06f222012-03-02 13:32:04 +0100661 if (!ui.client) {
662 GError *error;
663
664 error = g_error_new(g_quark_from_string("fio"), 1,
665 "Failed to add client %s", host);
Jens Axboe0420ba62012-02-29 11:16:52 +0100666 report_error(error);
667 g_error_free(error);
Jens Axboe0420ba62012-02-29 11:16:52 +0100668 }
Jens Axboedf06f222012-03-02 13:32:04 +0100669 ui.client->client_data = &ui;
Jens Axboe0420ba62012-02-29 11:16:52 +0100670
671 g_free(filenames->data);
672 filenames = g_slist_next(filenames);
673 }
Jens Axboea7a42ce2012-03-02 13:12:04 +0100674 free(host);
675err:
Jens Axboe0420ba62012-02-29 11:16:52 +0100676 g_slist_free(fn_glist);
Jens Axboe0420ba62012-02-29 11:16:52 +0100677}
678
679static void file_save(GtkWidget *w, gpointer data)
680{
681 GtkWidget *dialog;
682
683 dialog = gtk_file_chooser_dialog_new("Save File",
684 GTK_WINDOW(ui.window),
685 GTK_FILE_CHOOSER_ACTION_SAVE,
686 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
687 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
688 NULL);
689
690 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
691 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document");
692
693 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
694 char *filename;
695
696 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
697 // save_job_file(filename);
698 g_free(filename);
699 }
700 gtk_widget_destroy(dialog);
701}
702
Jens Axboe46974a72012-03-02 19:34:13 +0100703static void preferences(GtkWidget *w, gpointer data)
704{
705 GtkWidget *dialog, *frame, *box, **buttons;
706 int i;
707
708 dialog = gtk_dialog_new_with_buttons("Preferences",
709 GTK_WINDOW(ui.window),
710 GTK_DIALOG_DESTROY_WITH_PARENT,
711 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
712 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
713 NULL);
714
715 frame = gtk_frame_new("Debug");
716 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
717 box = gtk_hbox_new(FALSE, 6);
718 gtk_container_add(GTK_CONTAINER(frame), box);
719
720 buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
721
722 for (i = 0; i < FD_DEBUG_MAX; i++) {
723 buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
724 gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
725 }
726
727 gtk_widget_show_all(dialog);
728
729 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
730 gtk_widget_destroy(dialog);
731 return;
732 }
733
734 for (i = 0; i < FD_DEBUG_MAX; i++) {
735 int set;
736
737 set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i]));
738 if (set)
739 fio_debug |= (1UL << i);
740 }
741
742 gtk_widget_destroy(dialog);
743}
744
Jens Axboe0420ba62012-02-29 11:16:52 +0100745static void about_dialog(GtkWidget *w, gpointer data)
746{
747 gtk_show_about_dialog(NULL,
748 "program-name", "gfio",
749 "comments", "Gtk2 UI for fio",
750 "license", "GPLv2",
751 "version", fio_version_string,
752 "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
753 "logo-icon-name", "fio",
754 /* Must be last: */
755 NULL, NULL,
756 NULL);
757}
758
759static GtkActionEntry menu_items[] = {
Jens Axboe46974a72012-03-02 19:34:13 +0100760 { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
761 { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
762 { "OpenFile", GTK_STOCK_OPEN, NULL, "<Control>O", NULL, G_CALLBACK(file_open) },
763 { "SaveFile", GTK_STOCK_SAVE, NULL, "<Control>S", NULL, G_CALLBACK(file_save) },
764 { "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) },
765 { "Quit", GTK_STOCK_QUIT, NULL, "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
766 { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) },
Jens Axboe0420ba62012-02-29 11:16:52 +0100767};
Jens Axboe3e47bd22012-02-29 13:45:02 +0100768static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
Jens Axboe0420ba62012-02-29 11:16:52 +0100769
770static const gchar *ui_string = " \
771 <ui> \
772 <menubar name=\"MainMenu\"> \
773 <menu name=\"FileMenu\" action=\"FileMenuAction\"> \
774 <menuitem name=\"Open\" action=\"OpenFile\" /> \
775 <menuitem name=\"Save\" action=\"SaveFile\" /> \
776 <separator name=\"Separator\"/> \
Jens Axboe46974a72012-03-02 19:34:13 +0100777 <menuitem name=\"Preferences\" action=\"Preferences\" /> \
778 <separator name=\"Separator2\"/> \
Jens Axboe0420ba62012-02-29 11:16:52 +0100779 <menuitem name=\"Quit\" action=\"Quit\" /> \
780 </menu> \
781 <menu name=\"Help\" action=\"HelpMenuAction\"> \
782 <menuitem name=\"About\" action=\"About\" /> \
783 </menu> \
784 </menubar> \
785 </ui> \
786";
787
788static GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager)
789{
790 GtkActionGroup *action_group = gtk_action_group_new("Menu");
791 GError *error = 0;
792
793 action_group = gtk_action_group_new("Menu");
794 gtk_action_group_add_actions(action_group, menu_items, nmenu_items, 0);
795
796 gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
797 gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error);
798
799 gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager));
800 return gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
801}
802
803void gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar,
804 GtkWidget *vbox, GtkUIManager *ui_manager)
805{
806 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
807}
808
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100809static void init_ui(int *argc, char **argv[], struct gui *ui)
810{
Jens Axboe0420ba62012-02-29 11:16:52 +0100811 GtkSettings *settings;
812 GtkUIManager *uimanager;
Jens Axboe843ad232012-02-29 11:44:53 +0100813 GtkWidget *menu, *probe, *probe_frame, *probe_box;
Jens Axboe0420ba62012-02-29 11:16:52 +0100814
815 memset(ui, 0, sizeof(*ui));
Stephen M. Cameron45032dd2012-02-24 08:17:31 +0100816
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100817 /* Magical g*thread incantation, you just need this thread stuff.
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100818 * Without it, the update that happens in gfio_update_thread_status
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100819 * doesn't really happen in a timely fashion, you need expose events
820 */
Jens Axboeed727a42012-03-02 12:14:40 +0100821 if (!g_thread_supported())
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100822 g_thread_init(NULL);
823 gdk_threads_init();
824
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100825 gtk_init(argc, argv);
Jens Axboe0420ba62012-02-29 11:16:52 +0100826 settings = gtk_settings_get_default();
827 gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting");
828 g_type_init();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100829
830 ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
831 gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
832 gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500);
833
Jens Axboe0420ba62012-02-29 11:16:52 +0100834 g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
835 g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100836
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100837 ui->vbox = gtk_vbox_new(FALSE, 0);
838 gtk_container_add(GTK_CONTAINER (ui->window), ui->vbox);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100839
Jens Axboe0420ba62012-02-29 11:16:52 +0100840 uimanager = gtk_ui_manager_new();
841 menu = get_menubar_menu(ui->window, uimanager);
842 gfio_ui_setup(settings, menu, ui->vbox, uimanager);
843
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100844 /*
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100845 * Set up alignments for widgets at the top of ui,
846 * align top left, expand horizontally but not vertically
847 */
848 ui->topalign = gtk_alignment_new(0, 0, 1, 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100849 ui->topvbox = gtk_vbox_new(FALSE, 3);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100850 gtk_container_add(GTK_CONTAINER(ui->topalign), ui->topvbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100851 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->topalign, FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100852
Jens Axboe3e47bd22012-02-29 13:45:02 +0100853 probe = gtk_frame_new("Job");
Jens Axboe843ad232012-02-29 11:44:53 +0100854 gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3);
855 probe_frame = gtk_vbox_new(FALSE, 3);
856 gtk_container_add(GTK_CONTAINER(probe), probe_frame);
857
858 probe_box = gtk_hbox_new(FALSE, 3);
859 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe843ad232012-02-29 11:44:53 +0100860 ui->probe.hostname = new_info_label_in_frame(probe_box, "Host");
861 ui->probe.os = new_info_label_in_frame(probe_box, "OS");
862 ui->probe.arch = new_info_label_in_frame(probe_box, "Architecture");
863 ui->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version");
864
Jens Axboe3e47bd22012-02-29 13:45:02 +0100865 probe_box = gtk_hbox_new(FALSE, 3);
866 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe807f9972012-03-02 10:25:24 +0100867
868 ui->eta.name = new_info_label_in_frame(probe_box, "Name");
869 ui->eta.iotype = new_info_label_in_frame(probe_box, "IO");
870 ui->eta.ioengine = new_info_label_in_frame(probe_box, "IO Engine");
871 ui->eta.iodepth = new_info_label_in_frame(probe_box, "IO Depth");
Jens Axboe3e47bd22012-02-29 13:45:02 +0100872 ui->eta.jobs = new_info_label_in_frame(probe_box, "Jobs");
873 ui->eta.files = new_info_label_in_frame(probe_box, "Open files");
874
875 probe_box = gtk_hbox_new(FALSE, 3);
876 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
877 ui->eta.read_bw = new_info_label_in_frame(probe_box, "Read BW");
878 ui->eta.read_iops = new_info_label_in_frame(probe_box, "IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +0100879 ui->eta.write_bw = new_info_label_in_frame(probe_box, "Write BW");
880 ui->eta.write_iops = new_info_label_in_frame(probe_box, "IOPS");
881
882 /*
883 * Only add this if we have a commit rate
884 */
885#if 0
886 probe_box = gtk_hbox_new(FALSE, 3);
887 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
888
Jens Axboe3e47bd22012-02-29 13:45:02 +0100889 ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
890 ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
891
Jens Axboe3e47bd22012-02-29 13:45:02 +0100892 ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
893 ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +0100894#endif
Jens Axboe3e47bd22012-02-29 13:45:02 +0100895
Stephen M. Cameron45032dd2012-02-24 08:17:31 +0100896 /*
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100897 * Add a text box for text op messages
898 */
899 ui->textview = gtk_text_view_new();
900 ui->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->textview));
901 gtk_text_buffer_set_text(ui->text, "", -1);
902 gtk_text_view_set_editable(GTK_TEXT_VIEW(ui->textview), FALSE);
903 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ui->textview), FALSE);
904 ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
905 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
906 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
907 gtk_container_add(GTK_CONTAINER(ui->scrolled_window), ui->textview);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100908 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->scrolled_window,
909 TRUE, TRUE, 0);
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100910
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100911 /*
912 * Set up alignments for widgets at the bottom of ui,
913 * align bottom left, expand horizontally but not vertically
914 */
915 ui->bottomalign = gtk_alignment_new(0, 1, 1, 0);
916 ui->buttonbox = gtk_hbox_new(FALSE, 0);
917 gtk_container_add(GTK_CONTAINER(ui->bottomalign), ui->buttonbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100918 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->bottomalign,
919 FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100920
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100921 add_buttons(ui, buttonspeclist, ARRAYSIZE(buttonspeclist));
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100922
923 /*
924 * Set up thread status progress bar
925 */
926 ui->thread_status_pb = gtk_progress_bar_new();
927 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
Jens Axboe8663ea62012-03-02 14:04:30 +0100928 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100929 gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb);
930
931
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100932 gtk_widget_show_all(ui->window);
933}
934
Stephen M. Cameron8232e282012-02-24 08:17:31 +0100935int main(int argc, char *argv[], char *envp[])
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100936{
Stephen M. Cameron8232e282012-02-24 08:17:31 +0100937 if (initialize_fio(envp))
938 return 1;
Jens Axboe0420ba62012-02-29 11:16:52 +0100939 if (fio_init_options())
940 return 1;
Stephen M. Camerona1820202012-02-24 08:17:31 +0100941
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100942 init_ui(&argc, &argv, &ui);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100943
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100944 gdk_threads_enter();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100945 gtk_main();
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100946 gdk_threads_leave();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100947 return 0;
948}