blob: ebfa4b9de7dcd752926baaf00d66836d60caa334 [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
Jens Axboe89e5fad2012-03-05 09:21:12 +0100157static void gfio_thread_status_op(struct fio_client *client,
158 struct fio_net_cmd *cmd)
Stephen M. Camerona1820202012-02-24 08:17:31 +0100159{
160 printf("gfio_thread_status_op called\n");
Jens Axboe89e5fad2012-03-05 09:21:12 +0100161 fio_client_ops.thread_status(client, cmd);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100162}
163
Jens Axboe89e5fad2012-03-05 09:21:12 +0100164static void gfio_group_stats_op(struct fio_client *client,
165 struct fio_net_cmd *cmd)
Stephen M. Camerona1820202012-02-24 08:17:31 +0100166{
167 printf("gfio_group_stats_op called\n");
Jens Axboe89e5fad2012-03-05 09:21:12 +0100168 fio_client_ops.group_stats(client, cmd);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100169}
170
Jens Axboe3e47bd22012-02-29 13:45:02 +0100171static void gfio_update_eta(struct jobs_eta *je)
172{
173 static int eta_good;
174 char eta_str[128];
175 char output[256];
176 char tmp[32];
177 double perc = 0.0;
178 int i2p = 0;
179
180 eta_str[0] = '\0';
181 output[0] = '\0';
182
183 if (je->eta_sec != INT_MAX && je->elapsed_sec) {
184 perc = (double) je->elapsed_sec / (double) (je->elapsed_sec + je->eta_sec);
185 eta_to_str(eta_str, je->eta_sec);
186 }
187
188 sprintf(tmp, "%u", je->nr_running);
189 gtk_label_set_text(GTK_LABEL(ui.eta.jobs), tmp);
190 sprintf(tmp, "%u", je->files_open);
191 gtk_label_set_text(GTK_LABEL(ui.eta.files), tmp);
192
193#if 0
194 if (je->m_rate[0] || je->m_rate[1] || je->t_rate[0] || je->t_rate[1]) {
195 if (je->m_rate || je->t_rate) {
196 char *tr, *mr;
197
198 mr = num2str(je->m_rate, 4, 0, i2p);
199 tr = num2str(je->t_rate, 4, 0, i2p);
200 gtk_label_set_text(GTK_LABEL(ui.eta.
201 p += sprintf(p, ", CR=%s/%s KB/s", tr, mr);
202 free(tr);
203 free(mr);
204 } else if (je->m_iops || je->t_iops)
205 p += sprintf(p, ", CR=%d/%d IOPS", je->t_iops, je->m_iops);
Jens Axboeebbd89c2012-03-02 11:21:13 +0100206
Jens Axboe3e47bd22012-02-29 13:45:02 +0100207 gtk_label_set_text(GTK_LABEL(ui.eta.cr_bw), "---");
208 gtk_label_set_text(GTK_LABEL(ui.eta.cr_iops), "---");
209 gtk_label_set_text(GTK_LABEL(ui.eta.cw_bw), "---");
210 gtk_label_set_text(GTK_LABEL(ui.eta.cw_iops), "---");
211#endif
212
213 if (je->eta_sec != INT_MAX && je->nr_running) {
214 char *iops_str[2];
215 char *rate_str[2];
216
217 if ((!je->eta_sec && !eta_good) || je->nr_ramp == je->nr_running)
218 strcpy(output, "-.-% done");
219 else {
220 eta_good = 1;
221 perc *= 100.0;
222 sprintf(output, "%3.1f%% done", perc);
223 }
224
225 rate_str[0] = num2str(je->rate[0], 5, 10, i2p);
226 rate_str[1] = num2str(je->rate[1], 5, 10, i2p);
227
228 iops_str[0] = num2str(je->iops[0], 4, 1, 0);
229 iops_str[1] = num2str(je->iops[1], 4, 1, 0);
230
231 gtk_label_set_text(GTK_LABEL(ui.eta.read_bw), rate_str[0]);
232 gtk_label_set_text(GTK_LABEL(ui.eta.read_iops), iops_str[0]);
233 gtk_label_set_text(GTK_LABEL(ui.eta.write_bw), rate_str[1]);
234 gtk_label_set_text(GTK_LABEL(ui.eta.write_iops), iops_str[1]);
235
236 free(rate_str[0]);
237 free(rate_str[1]);
238 free(iops_str[0]);
239 free(iops_str[1]);
240 }
241
242 if (eta_str[0]) {
243 char *dst = output + strlen(output);
244
245 sprintf(dst, " - %s", eta_str);
246 }
247
248 gfio_update_thread_status(output, perc);
249}
250
Stephen M. Camerona1820202012-02-24 08:17:31 +0100251static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd)
252{
Jens Axboe843ad232012-02-29 11:44:53 +0100253 struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
254 const char *os, *arch;
255 char buf[64];
256
257 os = fio_get_os_string(probe->os);
258 if (!os)
259 os = "unknown";
260
261 arch = fio_get_arch_string(probe->arch);
262 if (!arch)
263 os = "unknown";
264
265 if (!client->name)
266 client->name = strdup((char *) probe->hostname);
267
268 gtk_label_set_text(GTK_LABEL(ui.probe.hostname), (char *) probe->hostname);
269 gtk_label_set_text(GTK_LABEL(ui.probe.os), os);
270 gtk_label_set_text(GTK_LABEL(ui.probe.arch), arch);
271 sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch);
272 gtk_label_set_text(GTK_LABEL(ui.probe.fio_ver), buf);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100273}
274
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100275static void gfio_update_thread_status(char *status_message, double perc)
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100276{
277 static char message[100];
278 const char *m = message;
279
280 strncpy(message, status_message, sizeof(message) - 1);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100281 gtk_progress_bar_set_text(
282 GTK_PROGRESS_BAR(ui.thread_status_pb), m);
283 gtk_progress_bar_set_fraction(
284 GTK_PROGRESS_BAR(ui.thread_status_pb), perc / 100.0);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100285 gdk_threads_enter();
286 gtk_widget_queue_draw(ui.window);
287 gdk_threads_leave();
288}
289
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100290static void gfio_quit_op(struct fio_client *client)
291{
292 struct gui *ui = client->client_data;
293
294 gfio_set_connected(ui, 0);
295}
296
Jens Axboe807f9972012-03-02 10:25:24 +0100297static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
298{
299 struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
300 struct gui *ui = client->client_data;
301 char tmp[8];
302 int i;
303
304 p->iodepth = le32_to_cpu(p->iodepth);
305 p->rw = le32_to_cpu(p->rw);
306
307 for (i = 0; i < 2; i++) {
308 p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
309 p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
310 }
311
312 p->numjobs = le32_to_cpu(p->numjobs);
313 p->group_reporting = le32_to_cpu(p->group_reporting);
314
315 gtk_label_set_text(GTK_LABEL(ui->eta.name), (gchar *) p->jobname);
316 gtk_label_set_text(GTK_LABEL(ui->eta.iotype), ddir_str(p->rw));
317 gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), (gchar *) p->ioengine);
318
319 sprintf(tmp, "%u", p->iodepth);
320 gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), tmp);
321}
322
Jens Axboeed727a42012-03-02 12:14:40 +0100323static void gfio_client_timed_out(struct fio_client *client)
324{
325 struct gui *ui = client->client_data;
326 GtkWidget *dialog, *label, *content;
327 char buf[256];
328
329 gdk_threads_enter();
330
331 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100332 clear_ui_info(ui);
Jens Axboeed727a42012-03-02 12:14:40 +0100333
334 sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname);
335
336 dialog = gtk_dialog_new_with_buttons("Timed out!",
337 GTK_WINDOW(ui->window),
338 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
339 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
340
341 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
342 label = gtk_label_new((const gchar *) buf);
343 gtk_container_add(GTK_CONTAINER(content), label);
344 gtk_widget_show_all(dialog);
345 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
346
347 gtk_dialog_run(GTK_DIALOG(dialog));
348 gtk_widget_destroy(dialog);
349
350 gdk_threads_leave();
351}
352
Stephen M. Camerona1820202012-02-24 08:17:31 +0100353struct client_ops gfio_client_ops = {
Jens Axboe0420ba62012-02-29 11:16:52 +0100354 .text_op = gfio_text_op,
355 .disk_util = gfio_disk_util_op,
356 .thread_status = gfio_thread_status_op,
357 .group_stats = gfio_group_stats_op,
Jens Axboea5276612012-03-04 15:15:08 +0100358 .eta = gfio_update_eta,
Jens Axboe0420ba62012-02-29 11:16:52 +0100359 .probe = gfio_probe_op,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100360 .quit = gfio_quit_op,
Jens Axboe807f9972012-03-02 10:25:24 +0100361 .add_job = gfio_add_job_op,
Jens Axboeed727a42012-03-02 12:14:40 +0100362 .timed_out = gfio_client_timed_out,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100363 .stay_connected = 1,
Stephen M. Camerona1820202012-02-24 08:17:31 +0100364};
365
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100366static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
367 __attribute__((unused)) gpointer data)
368{
369 gtk_main_quit();
370}
371
Stephen M. Cameron25927252012-02-24 08:17:31 +0100372static void *job_thread(void *arg)
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100373{
Stephen M. Cameron25927252012-02-24 08:17:31 +0100374 fio_handle_clients(&gfio_client_ops);
Stephen M. Cameron25927252012-02-24 08:17:31 +0100375 return NULL;
376}
377
Jens Axboe0420ba62012-02-29 11:16:52 +0100378static int send_job_files(struct gui *ui)
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100379{
Jens Axboe441013b2012-03-01 08:01:52 +0100380 int i, ret = 0;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100381
Jens Axboe0420ba62012-02-29 11:16:52 +0100382 for (i = 0; i < ui->nr_job_files; i++) {
383 ret = fio_clients_send_ini(ui->job_files[i]);
Jens Axboe441013b2012-03-01 08:01:52 +0100384 if (ret)
385 break;
386
Jens Axboe0420ba62012-02-29 11:16:52 +0100387 free(ui->job_files[i]);
388 ui->job_files[i] = NULL;
Jens Axboe441013b2012-03-01 08:01:52 +0100389 }
390 while (i < ui->nr_job_files) {
391 free(ui->job_files[i]);
392 ui->job_files[i] = NULL;
393 i++;
Jens Axboe0420ba62012-02-29 11:16:52 +0100394 }
395
Jens Axboe441013b2012-03-01 08:01:52 +0100396 return ret;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100397}
398
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100399static void start_job_thread(struct gui *ui)
Stephen M. Cameron25927252012-02-24 08:17:31 +0100400{
Jens Axboe0420ba62012-02-29 11:16:52 +0100401 if (send_job_files(ui)) {
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100402 printf("Yeah, I didn't really like those options too much.\n");
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100403 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
404 return;
405 }
Stephen M. Cameron25927252012-02-24 08:17:31 +0100406}
407
Jens Axboea7a42ce2012-03-02 13:12:04 +0100408static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
409{
410 GtkWidget *label_widget;
411 GtkWidget *frame;
412
413 frame = gtk_frame_new(label);
414 label_widget = gtk_label_new(NULL);
415 gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
416 gtk_container_add(GTK_CONTAINER(frame), label_widget);
417
418 return label_widget;
419}
420
Jens Axboea7a42ce2012-03-02 13:12:04 +0100421static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, double defval)
422{
423 GtkWidget *button, *box;
424
425 box = gtk_hbox_new(FALSE, 3);
426 gtk_container_add(GTK_CONTAINER(hbox), box);
427
428 button = gtk_spin_button_new_with_range(min, max, 1.0);
429 gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
430
431 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID);
432 gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), defval);
433
434 return button;
435}
436
Stephen M. Cameron25927252012-02-24 08:17:31 +0100437static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
438 gpointer data)
439{
440 struct gui *ui = data;
441
Stephen M. Cameron25927252012-02-24 08:17:31 +0100442 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100443 start_job_thread(ui);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100444}
445
Jens Axboedf06f222012-03-02 13:32:04 +0100446static void file_open(GtkWidget *w, gpointer data);
447
448static void connect_clicked(GtkWidget *widget, gpointer data)
Jens Axboe3e47bd22012-02-29 13:45:02 +0100449{
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100450 struct gui *ui = data;
451
452 if (!ui->connected) {
Jens Axboedf06f222012-03-02 13:32:04 +0100453 if (!ui->nr_job_files)
454 file_open(widget, data);
Jens Axboe8663ea62012-03-02 14:04:30 +0100455 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100456 fio_clients_connect();
457 pthread_create(&ui->t, NULL, job_thread, NULL);
458 gfio_set_connected(ui, 1);
Jens Axboedf06f222012-03-02 13:32:04 +0100459 } else {
460 fio_clients_terminate();
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100461 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100462 clear_ui_info(ui);
Jens Axboedf06f222012-03-02 13:32:04 +0100463 }
Jens Axboe3e47bd22012-02-29 13:45:02 +0100464}
465
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100466static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
467 struct button_spec *buttonspec)
468{
469 ui->button[i] = gtk_button_new_with_label(buttonspec->buttontext);
470 g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100471 gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100472 gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100473 gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100474}
475
476static void add_buttons(struct gui *ui,
477 struct button_spec *buttonlist,
478 int nbuttons)
479{
480 int i;
481
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100482 for (i = 0; i < nbuttons; i++)
483 add_button(ui, i, ui->buttonbox, &buttonlist[i]);
484}
485
Jens Axboe0420ba62012-02-29 11:16:52 +0100486static void on_info_bar_response(GtkWidget *widget, gint response,
487 gpointer data)
488{
489 if (response == GTK_RESPONSE_OK) {
490 gtk_widget_destroy(widget);
491 ui.error_info_bar = NULL;
492 }
493}
494
Jens Axboedf06f222012-03-02 13:32:04 +0100495void report_error(GError *error)
Jens Axboe0420ba62012-02-29 11:16:52 +0100496{
497 if (ui.error_info_bar == NULL) {
498 ui.error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK,
499 GTK_RESPONSE_OK,
500 NULL);
501 g_signal_connect(ui.error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL);
502 gtk_info_bar_set_message_type(GTK_INFO_BAR(ui.error_info_bar),
503 GTK_MESSAGE_ERROR);
504
505 ui.error_label = gtk_label_new(error->message);
506 GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(ui.error_info_bar));
507 gtk_container_add(GTK_CONTAINER(container), ui.error_label);
508
509 gtk_box_pack_start(GTK_BOX(ui.vbox), ui.error_info_bar, FALSE, FALSE, 0);
510 gtk_widget_show_all(ui.vbox);
511 } else {
512 char buffer[256];
513 snprintf(buffer, sizeof(buffer), "Failed to open file.");
514 gtk_label_set(GTK_LABEL(ui.error_label), buffer);
515 }
516}
517
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100518static int get_connection_details(char **host, int *port, int *type,
519 int *server_start)
Jens Axboea7a42ce2012-03-02 13:12:04 +0100520{
521 GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100522 GtkWidget *button;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100523 char *typeentry;
524
525 dialog = gtk_dialog_new_with_buttons("Connection details",
526 GTK_WINDOW(ui.window),
527 GTK_DIALOG_DESTROY_WITH_PARENT,
528 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
529 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
530
531 frame = gtk_frame_new("Hostname / socket name");
532 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
533 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
534
535 box = gtk_vbox_new(FALSE, 6);
536 gtk_container_add(GTK_CONTAINER(frame), box);
537
538 hbox = gtk_hbox_new(TRUE, 10);
539 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
540 hentry = gtk_entry_new();
541 gtk_entry_set_text(GTK_ENTRY(hentry), "localhost");
542 gtk_box_pack_start(GTK_BOX(hbox), hentry, TRUE, TRUE, 0);
543
544 frame = gtk_frame_new("Port");
545 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
546 box = gtk_vbox_new(FALSE, 10);
547 gtk_container_add(GTK_CONTAINER(frame), box);
548
549 hbox = gtk_hbox_new(TRUE, 4);
550 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
551 pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT);
552
553 frame = gtk_frame_new("Type");
554 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
555 box = gtk_vbox_new(FALSE, 10);
556 gtk_container_add(GTK_CONTAINER(frame), box);
557
558 hbox = gtk_hbox_new(TRUE, 4);
559 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
560
561 combo = gtk_combo_box_text_new();
562 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv4");
563 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv6");
564 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "local socket");
565 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
566
567 gtk_container_add(GTK_CONTAINER(hbox), combo);
568
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100569 frame = gtk_frame_new("Options");
570 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
571 box = gtk_vbox_new(FALSE, 10);
572 gtk_container_add(GTK_CONTAINER(frame), box);
573
574 hbox = gtk_hbox_new(TRUE, 4);
575 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
576
577 button = gtk_check_button_new_with_label("Auto-spawn fio backend");
578 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
579 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.");
580 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
581
Jens Axboea7a42ce2012-03-02 13:12:04 +0100582 gtk_widget_show_all(dialog);
583
584 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
585 gtk_widget_destroy(dialog);
586 return 1;
587 }
588
589 *host = strdup(gtk_entry_get_text(GTK_ENTRY(hentry)));
590 *port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
591
592 typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
593 if (!typeentry || !strncmp(typeentry, "IPv4", 4))
594 *type = Fio_client_ipv4;
595 else if (!strncmp(typeentry, "IPv6", 4))
596 *type = Fio_client_ipv6;
597 else
598 *type = Fio_client_socket;
599 g_free(typeentry);
600
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100601 *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
602
Jens Axboea7a42ce2012-03-02 13:12:04 +0100603 gtk_widget_destroy(dialog);
604 return 0;
605}
606
Jens Axboe0420ba62012-02-29 11:16:52 +0100607static void file_open(GtkWidget *w, gpointer data)
608{
609 GtkWidget *dialog;
610 GSList *filenames, *fn_glist;
611 GtkFileFilter *filter;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100612 char *host;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100613 int port, type, server_start;
Jens Axboe0420ba62012-02-29 11:16:52 +0100614
615 dialog = gtk_file_chooser_dialog_new("Open File",
616 GTK_WINDOW(ui.window),
617 GTK_FILE_CHOOSER_ACTION_OPEN,
618 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
619 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
620 NULL);
621 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
622
623 filter = gtk_file_filter_new();
624 gtk_file_filter_add_pattern(filter, "*.fio");
625 gtk_file_filter_add_pattern(filter, "*.job");
626 gtk_file_filter_add_mime_type(filter, "text/fio");
627 gtk_file_filter_set_name(filter, "Fio job file");
628 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
629
630 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
631 gtk_widget_destroy(dialog);
632 return;
633 }
634
635 fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
Jens Axboea7a42ce2012-03-02 13:12:04 +0100636
637 gtk_widget_destroy(dialog);
638
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100639 if (get_connection_details(&host, &port, &type, &server_start))
Jens Axboea7a42ce2012-03-02 13:12:04 +0100640 goto err;
641
Jens Axboe0420ba62012-02-29 11:16:52 +0100642 filenames = fn_glist;
643 while (filenames != NULL) {
Jens Axboe0420ba62012-02-29 11:16:52 +0100644 ui.job_files = realloc(ui.job_files, (ui.nr_job_files + 1) * sizeof(char *));
645 ui.job_files[ui.nr_job_files] = strdup(filenames->data);
646 ui.nr_job_files++;
647
Jens Axboea5276612012-03-04 15:15:08 +0100648 ui.client = fio_client_add_explicit(&gfio_client_ops, host, type, port);
Jens Axboedf06f222012-03-02 13:32:04 +0100649 if (!ui.client) {
650 GError *error;
651
652 error = g_error_new(g_quark_from_string("fio"), 1,
653 "Failed to add client %s", host);
Jens Axboe0420ba62012-02-29 11:16:52 +0100654 report_error(error);
655 g_error_free(error);
Jens Axboe0420ba62012-02-29 11:16:52 +0100656 }
Jens Axboedf06f222012-03-02 13:32:04 +0100657 ui.client->client_data = &ui;
Jens Axboe0420ba62012-02-29 11:16:52 +0100658
659 g_free(filenames->data);
660 filenames = g_slist_next(filenames);
661 }
Jens Axboea7a42ce2012-03-02 13:12:04 +0100662 free(host);
663err:
Jens Axboe0420ba62012-02-29 11:16:52 +0100664 g_slist_free(fn_glist);
Jens Axboe0420ba62012-02-29 11:16:52 +0100665}
666
667static void file_save(GtkWidget *w, gpointer data)
668{
669 GtkWidget *dialog;
670
671 dialog = gtk_file_chooser_dialog_new("Save File",
672 GTK_WINDOW(ui.window),
673 GTK_FILE_CHOOSER_ACTION_SAVE,
674 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
675 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
676 NULL);
677
678 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
679 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document");
680
681 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
682 char *filename;
683
684 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
685 // save_job_file(filename);
686 g_free(filename);
687 }
688 gtk_widget_destroy(dialog);
689}
690
Jens Axboe46974a72012-03-02 19:34:13 +0100691static void preferences(GtkWidget *w, gpointer data)
692{
693 GtkWidget *dialog, *frame, *box, **buttons;
694 int i;
695
696 dialog = gtk_dialog_new_with_buttons("Preferences",
697 GTK_WINDOW(ui.window),
698 GTK_DIALOG_DESTROY_WITH_PARENT,
699 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
700 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
701 NULL);
702
Jens Axboe0b8d11e2012-03-02 19:44:15 +0100703 frame = gtk_frame_new("Debug logging");
Jens Axboe46974a72012-03-02 19:34:13 +0100704 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
705 box = gtk_hbox_new(FALSE, 6);
706 gtk_container_add(GTK_CONTAINER(frame), box);
707
708 buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
709
710 for (i = 0; i < FD_DEBUG_MAX; i++) {
711 buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
Jens Axboe0b8d11e2012-03-02 19:44:15 +0100712 gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
Jens Axboe46974a72012-03-02 19:34:13 +0100713 gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
714 }
715
716 gtk_widget_show_all(dialog);
717
718 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
719 gtk_widget_destroy(dialog);
720 return;
721 }
722
723 for (i = 0; i < FD_DEBUG_MAX; i++) {
724 int set;
725
726 set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i]));
727 if (set)
728 fio_debug |= (1UL << i);
729 }
730
731 gtk_widget_destroy(dialog);
732}
733
Jens Axboe0420ba62012-02-29 11:16:52 +0100734static void about_dialog(GtkWidget *w, gpointer data)
735{
736 gtk_show_about_dialog(NULL,
737 "program-name", "gfio",
738 "comments", "Gtk2 UI for fio",
739 "license", "GPLv2",
740 "version", fio_version_string,
741 "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
742 "logo-icon-name", "fio",
743 /* Must be last: */
744 NULL, NULL,
745 NULL);
746}
747
748static GtkActionEntry menu_items[] = {
Jens Axboe46974a72012-03-02 19:34:13 +0100749 { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
750 { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
751 { "OpenFile", GTK_STOCK_OPEN, NULL, "<Control>O", NULL, G_CALLBACK(file_open) },
752 { "SaveFile", GTK_STOCK_SAVE, NULL, "<Control>S", NULL, G_CALLBACK(file_save) },
753 { "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) },
754 { "Quit", GTK_STOCK_QUIT, NULL, "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
755 { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) },
Jens Axboe0420ba62012-02-29 11:16:52 +0100756};
Jens Axboe3e47bd22012-02-29 13:45:02 +0100757static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
Jens Axboe0420ba62012-02-29 11:16:52 +0100758
759static const gchar *ui_string = " \
760 <ui> \
761 <menubar name=\"MainMenu\"> \
762 <menu name=\"FileMenu\" action=\"FileMenuAction\"> \
763 <menuitem name=\"Open\" action=\"OpenFile\" /> \
764 <menuitem name=\"Save\" action=\"SaveFile\" /> \
765 <separator name=\"Separator\"/> \
Jens Axboe46974a72012-03-02 19:34:13 +0100766 <menuitem name=\"Preferences\" action=\"Preferences\" /> \
767 <separator name=\"Separator2\"/> \
Jens Axboe0420ba62012-02-29 11:16:52 +0100768 <menuitem name=\"Quit\" action=\"Quit\" /> \
769 </menu> \
770 <menu name=\"Help\" action=\"HelpMenuAction\"> \
771 <menuitem name=\"About\" action=\"About\" /> \
772 </menu> \
773 </menubar> \
774 </ui> \
775";
776
777static GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager)
778{
779 GtkActionGroup *action_group = gtk_action_group_new("Menu");
780 GError *error = 0;
781
782 action_group = gtk_action_group_new("Menu");
783 gtk_action_group_add_actions(action_group, menu_items, nmenu_items, 0);
784
785 gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
786 gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error);
787
788 gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager));
789 return gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
790}
791
792void gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar,
793 GtkWidget *vbox, GtkUIManager *ui_manager)
794{
795 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
796}
797
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100798static void init_ui(int *argc, char **argv[], struct gui *ui)
799{
Jens Axboe0420ba62012-02-29 11:16:52 +0100800 GtkSettings *settings;
801 GtkUIManager *uimanager;
Jens Axboe843ad232012-02-29 11:44:53 +0100802 GtkWidget *menu, *probe, *probe_frame, *probe_box;
Jens Axboe0420ba62012-02-29 11:16:52 +0100803
804 memset(ui, 0, sizeof(*ui));
Stephen M. Cameron45032dd2012-02-24 08:17:31 +0100805
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100806 /* Magical g*thread incantation, you just need this thread stuff.
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100807 * Without it, the update that happens in gfio_update_thread_status
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100808 * doesn't really happen in a timely fashion, you need expose events
809 */
Jens Axboeed727a42012-03-02 12:14:40 +0100810 if (!g_thread_supported())
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100811 g_thread_init(NULL);
812 gdk_threads_init();
813
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100814 gtk_init(argc, argv);
Jens Axboe0420ba62012-02-29 11:16:52 +0100815 settings = gtk_settings_get_default();
816 gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting");
817 g_type_init();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100818
819 ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
820 gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
821 gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500);
822
Jens Axboe0420ba62012-02-29 11:16:52 +0100823 g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
824 g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100825
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100826 ui->vbox = gtk_vbox_new(FALSE, 0);
827 gtk_container_add(GTK_CONTAINER (ui->window), ui->vbox);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100828
Jens Axboe0420ba62012-02-29 11:16:52 +0100829 uimanager = gtk_ui_manager_new();
830 menu = get_menubar_menu(ui->window, uimanager);
831 gfio_ui_setup(settings, menu, ui->vbox, uimanager);
832
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100833 /*
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100834 * Set up alignments for widgets at the top of ui,
835 * align top left, expand horizontally but not vertically
836 */
837 ui->topalign = gtk_alignment_new(0, 0, 1, 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100838 ui->topvbox = gtk_vbox_new(FALSE, 3);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100839 gtk_container_add(GTK_CONTAINER(ui->topalign), ui->topvbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100840 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->topalign, FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100841
Jens Axboe3e47bd22012-02-29 13:45:02 +0100842 probe = gtk_frame_new("Job");
Jens Axboe843ad232012-02-29 11:44:53 +0100843 gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3);
844 probe_frame = gtk_vbox_new(FALSE, 3);
845 gtk_container_add(GTK_CONTAINER(probe), probe_frame);
846
847 probe_box = gtk_hbox_new(FALSE, 3);
848 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe843ad232012-02-29 11:44:53 +0100849 ui->probe.hostname = new_info_label_in_frame(probe_box, "Host");
850 ui->probe.os = new_info_label_in_frame(probe_box, "OS");
851 ui->probe.arch = new_info_label_in_frame(probe_box, "Architecture");
852 ui->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version");
853
Jens Axboe3e47bd22012-02-29 13:45:02 +0100854 probe_box = gtk_hbox_new(FALSE, 3);
855 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
Jens Axboe807f9972012-03-02 10:25:24 +0100856
857 ui->eta.name = new_info_label_in_frame(probe_box, "Name");
858 ui->eta.iotype = new_info_label_in_frame(probe_box, "IO");
859 ui->eta.ioengine = new_info_label_in_frame(probe_box, "IO Engine");
860 ui->eta.iodepth = new_info_label_in_frame(probe_box, "IO Depth");
Jens Axboe3e47bd22012-02-29 13:45:02 +0100861 ui->eta.jobs = new_info_label_in_frame(probe_box, "Jobs");
862 ui->eta.files = new_info_label_in_frame(probe_box, "Open files");
863
864 probe_box = gtk_hbox_new(FALSE, 3);
865 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
866 ui->eta.read_bw = new_info_label_in_frame(probe_box, "Read BW");
867 ui->eta.read_iops = new_info_label_in_frame(probe_box, "IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +0100868 ui->eta.write_bw = new_info_label_in_frame(probe_box, "Write BW");
869 ui->eta.write_iops = new_info_label_in_frame(probe_box, "IOPS");
870
871 /*
872 * Only add this if we have a commit rate
873 */
874#if 0
875 probe_box = gtk_hbox_new(FALSE, 3);
876 gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
877
Jens Axboe3e47bd22012-02-29 13:45:02 +0100878 ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
879 ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
880
Jens Axboe3e47bd22012-02-29 13:45:02 +0100881 ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
882 ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
Jens Axboe807f9972012-03-02 10:25:24 +0100883#endif
Jens Axboe3e47bd22012-02-29 13:45:02 +0100884
Stephen M. Cameron45032dd2012-02-24 08:17:31 +0100885 /*
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100886 * Add a text box for text op messages
887 */
888 ui->textview = gtk_text_view_new();
889 ui->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->textview));
890 gtk_text_buffer_set_text(ui->text, "", -1);
891 gtk_text_view_set_editable(GTK_TEXT_VIEW(ui->textview), FALSE);
892 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ui->textview), FALSE);
893 ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
894 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
895 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
896 gtk_container_add(GTK_CONTAINER(ui->scrolled_window), ui->textview);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100897 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->scrolled_window,
898 TRUE, TRUE, 0);
Stephen M. Cameron736f2df2012-02-24 08:17:32 +0100899
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100900 /*
901 * Set up alignments for widgets at the bottom of ui,
902 * align bottom left, expand horizontally but not vertically
903 */
904 ui->bottomalign = gtk_alignment_new(0, 1, 1, 0);
905 ui->buttonbox = gtk_hbox_new(FALSE, 0);
906 gtk_container_add(GTK_CONTAINER(ui->bottomalign), ui->buttonbox);
Stephen M. Camerone1645342012-02-24 08:17:32 +0100907 gtk_box_pack_start(GTK_BOX(ui->vbox), ui->bottomalign,
908 FALSE, FALSE, 0);
Stephen M. Cameronc36f98d2012-02-24 08:17:32 +0100909
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100910 add_buttons(ui, buttonspeclist, ARRAYSIZE(buttonspeclist));
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100911
912 /*
913 * Set up thread status progress bar
914 */
915 ui->thread_status_pb = gtk_progress_bar_new();
916 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
Jens Axboe8663ea62012-03-02 14:04:30 +0100917 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100918 gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb);
919
920
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100921 gtk_widget_show_all(ui->window);
922}
923
Stephen M. Cameron8232e282012-02-24 08:17:31 +0100924int main(int argc, char *argv[], char *envp[])
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100925{
Stephen M. Cameron8232e282012-02-24 08:17:31 +0100926 if (initialize_fio(envp))
927 return 1;
Jens Axboe0420ba62012-02-29 11:16:52 +0100928 if (fio_init_options())
929 return 1;
Stephen M. Camerona1820202012-02-24 08:17:31 +0100930
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100931 init_ui(&argc, &argv, &ui);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100932
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100933 gdk_threads_enter();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100934 gtk_main();
Stephen M. Cameron2839f0c2012-02-24 08:17:31 +0100935 gdk_threads_leave();
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100936 return 0;
937}