blob: 32e012e7ba360535157a97f856fe5ec7b0117249 [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_eta_op(struct fio_client *client, struct fio_net_cmd *cmd)
250{
Jens Axboe3e47bd22012-02-29 13:45:02 +0100251 struct jobs_eta *je = (struct jobs_eta *) cmd->payload;
252 struct client_eta *eta = (struct client_eta *) (uintptr_t) cmd->tag;
253
254 client->eta_in_flight = NULL;
255 flist_del_init(&client->eta_list);
256
257 fio_client_convert_jobs_eta(je);
258 fio_client_sum_jobs_eta(&eta->eta, je);
259 fio_client_dec_jobs_eta(eta, gfio_update_eta);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100260}
261
262static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd)
263{
Jens Axboe843ad232012-02-29 11:44:53 +0100264 struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
265 const char *os, *arch;
266 char buf[64];
267
268 os = fio_get_os_string(probe->os);
269 if (!os)
270 os = "unknown";
271
272 arch = fio_get_arch_string(probe->arch);
273 if (!arch)
274 os = "unknown";
275
276 if (!client->name)
277 client->name = strdup((char *) probe->hostname);
278
279 gtk_label_set_text(GTK_LABEL(ui.probe.hostname), (char *) probe->hostname);
280 gtk_label_set_text(GTK_LABEL(ui.probe.os), os);
281 gtk_label_set_text(GTK_LABEL(ui.probe.arch), arch);
282 sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch);
283 gtk_label_set_text(GTK_LABEL(ui.probe.fio_ver), buf);
Stephen M. Camerona1820202012-02-24 08:17:31 +0100284}
285
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100286static void gfio_update_thread_status(char *status_message, double perc)
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100287{
288 static char message[100];
289 const char *m = message;
290
291 strncpy(message, status_message, sizeof(message) - 1);
Stephen M. Cameron04cc6b72012-02-24 08:17:31 +0100292 gtk_progress_bar_set_text(
293 GTK_PROGRESS_BAR(ui.thread_status_pb), m);
294 gtk_progress_bar_set_fraction(
295 GTK_PROGRESS_BAR(ui.thread_status_pb), perc / 100.0);
Stephen M. Cameron5b7573a2012-02-24 08:17:31 +0100296 gdk_threads_enter();
297 gtk_widget_queue_draw(ui.window);
298 gdk_threads_leave();
299}
300
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100301static void gfio_quit_op(struct fio_client *client)
302{
303 struct gui *ui = client->client_data;
304
305 gfio_set_connected(ui, 0);
306}
307
Jens Axboe807f9972012-03-02 10:25:24 +0100308static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
309{
310 struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
311 struct gui *ui = client->client_data;
312 char tmp[8];
313 int i;
314
315 p->iodepth = le32_to_cpu(p->iodepth);
316 p->rw = le32_to_cpu(p->rw);
317
318 for (i = 0; i < 2; i++) {
319 p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
320 p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
321 }
322
323 p->numjobs = le32_to_cpu(p->numjobs);
324 p->group_reporting = le32_to_cpu(p->group_reporting);
325
326 gtk_label_set_text(GTK_LABEL(ui->eta.name), (gchar *) p->jobname);
327 gtk_label_set_text(GTK_LABEL(ui->eta.iotype), ddir_str(p->rw));
328 gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), (gchar *) p->ioengine);
329
330 sprintf(tmp, "%u", p->iodepth);
331 gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), tmp);
332}
333
Jens Axboeed727a42012-03-02 12:14:40 +0100334static void gfio_client_timed_out(struct fio_client *client)
335{
336 struct gui *ui = client->client_data;
337 GtkWidget *dialog, *label, *content;
338 char buf[256];
339
340 gdk_threads_enter();
341
342 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100343 clear_ui_info(ui);
Jens Axboeed727a42012-03-02 12:14:40 +0100344
345 sprintf(buf, "Client %s: timeout talking to server.\n", client->hostname);
346
347 dialog = gtk_dialog_new_with_buttons("Timed out!",
348 GTK_WINDOW(ui->window),
349 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
350 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
351
352 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
353 label = gtk_label_new((const gchar *) buf);
354 gtk_container_add(GTK_CONTAINER(content), label);
355 gtk_widget_show_all(dialog);
356 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
357
358 gtk_dialog_run(GTK_DIALOG(dialog));
359 gtk_widget_destroy(dialog);
360
361 gdk_threads_leave();
362}
363
Stephen M. Camerona1820202012-02-24 08:17:31 +0100364struct client_ops gfio_client_ops = {
Jens Axboe0420ba62012-02-29 11:16:52 +0100365 .text_op = gfio_text_op,
366 .disk_util = gfio_disk_util_op,
367 .thread_status = gfio_thread_status_op,
368 .group_stats = gfio_group_stats_op,
369 .eta = gfio_eta_op,
370 .probe = gfio_probe_op,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100371 .quit = gfio_quit_op,
Jens Axboe807f9972012-03-02 10:25:24 +0100372 .add_job = gfio_add_job_op,
Jens Axboeed727a42012-03-02 12:14:40 +0100373 .timed_out = gfio_client_timed_out,
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100374 .stay_connected = 1,
Stephen M. Camerona1820202012-02-24 08:17:31 +0100375};
376
Stephen M. Cameronff1f3282012-02-24 08:17:30 +0100377static void quit_clicked(__attribute__((unused)) GtkWidget *widget,
378 __attribute__((unused)) gpointer data)
379{
380 gtk_main_quit();
381}
382
Stephen M. Cameron25927252012-02-24 08:17:31 +0100383static void *job_thread(void *arg)
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100384{
Stephen M. Cameron25927252012-02-24 08:17:31 +0100385 fio_handle_clients(&gfio_client_ops);
Stephen M. Cameron25927252012-02-24 08:17:31 +0100386 return NULL;
387}
388
Jens Axboe0420ba62012-02-29 11:16:52 +0100389static int send_job_files(struct gui *ui)
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100390{
Jens Axboe441013b2012-03-01 08:01:52 +0100391 int i, ret = 0;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100392
Jens Axboe0420ba62012-02-29 11:16:52 +0100393 for (i = 0; i < ui->nr_job_files; i++) {
394 ret = fio_clients_send_ini(ui->job_files[i]);
Jens Axboe441013b2012-03-01 08:01:52 +0100395 if (ret)
396 break;
397
Jens Axboe0420ba62012-02-29 11:16:52 +0100398 free(ui->job_files[i]);
399 ui->job_files[i] = NULL;
Jens Axboe441013b2012-03-01 08:01:52 +0100400 }
401 while (i < ui->nr_job_files) {
402 free(ui->job_files[i]);
403 ui->job_files[i] = NULL;
404 i++;
Jens Axboe0420ba62012-02-29 11:16:52 +0100405 }
406
Jens Axboe441013b2012-03-01 08:01:52 +0100407 return ret;
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100408}
409
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100410static void start_job_thread(struct gui *ui)
Stephen M. Cameron25927252012-02-24 08:17:31 +0100411{
Jens Axboe0420ba62012-02-29 11:16:52 +0100412 if (send_job_files(ui)) {
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100413 printf("Yeah, I didn't really like those options too much.\n");
Stephen M. Cameron60f6b332012-02-24 08:17:32 +0100414 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
415 return;
416 }
Stephen M. Cameron25927252012-02-24 08:17:31 +0100417}
418
Jens Axboea7a42ce2012-03-02 13:12:04 +0100419static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
420{
421 GtkWidget *label_widget;
422 GtkWidget *frame;
423
424 frame = gtk_frame_new(label);
425 label_widget = gtk_label_new(NULL);
426 gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
427 gtk_container_add(GTK_CONTAINER(frame), label_widget);
428
429 return label_widget;
430}
431
Jens Axboea7a42ce2012-03-02 13:12:04 +0100432static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, double defval)
433{
434 GtkWidget *button, *box;
435
436 box = gtk_hbox_new(FALSE, 3);
437 gtk_container_add(GTK_CONTAINER(hbox), box);
438
439 button = gtk_spin_button_new_with_range(min, max, 1.0);
440 gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
441
442 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID);
443 gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), defval);
444
445 return button;
446}
447
Stephen M. Cameron25927252012-02-24 08:17:31 +0100448static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
449 gpointer data)
450{
451 struct gui *ui = data;
452
Stephen M. Cameron25927252012-02-24 08:17:31 +0100453 gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100454 start_job_thread(ui);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100455}
456
Jens Axboedf06f222012-03-02 13:32:04 +0100457static void file_open(GtkWidget *w, gpointer data);
458
459static void connect_clicked(GtkWidget *widget, gpointer data)
Jens Axboe3e47bd22012-02-29 13:45:02 +0100460{
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100461 struct gui *ui = data;
462
463 if (!ui->connected) {
Jens Axboedf06f222012-03-02 13:32:04 +0100464 if (!ui->nr_job_files)
465 file_open(widget, data);
Jens Axboe8663ea62012-03-02 14:04:30 +0100466 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100467 fio_clients_connect();
468 pthread_create(&ui->t, NULL, job_thread, NULL);
469 gfio_set_connected(ui, 1);
Jens Axboedf06f222012-03-02 13:32:04 +0100470 } else {
471 fio_clients_terminate();
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100472 gfio_set_connected(ui, 0);
Jens Axboe88432652012-03-02 19:09:31 +0100473 clear_ui_info(ui);
Jens Axboedf06f222012-03-02 13:32:04 +0100474 }
Jens Axboe3e47bd22012-02-29 13:45:02 +0100475}
476
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100477static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
478 struct button_spec *buttonspec)
479{
480 ui->button[i] = gtk_button_new_with_label(buttonspec->buttontext);
481 g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui);
Jens Axboe3ec62ec2012-03-01 12:01:29 +0100482 gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100483 gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext);
Jens Axboe3e47bd22012-02-29 13:45:02 +0100484 gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive);
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100485}
486
487static void add_buttons(struct gui *ui,
488 struct button_spec *buttonlist,
489 int nbuttons)
490{
491 int i;
492
Stephen M. Cameronf3074002012-02-24 08:17:30 +0100493 for (i = 0; i < nbuttons; i++)
494 add_button(ui, i, ui->buttonbox, &buttonlist[i]);
495}
496
Jens Axboe0420ba62012-02-29 11:16:52 +0100497static void on_info_bar_response(GtkWidget *widget, gint response,
498 gpointer data)
499{
500 if (response == GTK_RESPONSE_OK) {
501 gtk_widget_destroy(widget);
502 ui.error_info_bar = NULL;
503 }
504}
505
Jens Axboedf06f222012-03-02 13:32:04 +0100506void report_error(GError *error)
Jens Axboe0420ba62012-02-29 11:16:52 +0100507{
508 if (ui.error_info_bar == NULL) {
509 ui.error_info_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK,
510 GTK_RESPONSE_OK,
511 NULL);
512 g_signal_connect(ui.error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL);
513 gtk_info_bar_set_message_type(GTK_INFO_BAR(ui.error_info_bar),
514 GTK_MESSAGE_ERROR);
515
516 ui.error_label = gtk_label_new(error->message);
517 GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(ui.error_info_bar));
518 gtk_container_add(GTK_CONTAINER(container), ui.error_label);
519
520 gtk_box_pack_start(GTK_BOX(ui.vbox), ui.error_info_bar, FALSE, FALSE, 0);
521 gtk_widget_show_all(ui.vbox);
522 } else {
523 char buffer[256];
524 snprintf(buffer, sizeof(buffer), "Failed to open file.");
525 gtk_label_set(GTK_LABEL(ui.error_label), buffer);
526 }
527}
528
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100529static int get_connection_details(char **host, int *port, int *type,
530 int *server_start)
Jens Axboea7a42ce2012-03-02 13:12:04 +0100531{
532 GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100533 GtkWidget *button;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100534 char *typeentry;
535
536 dialog = gtk_dialog_new_with_buttons("Connection details",
537 GTK_WINDOW(ui.window),
538 GTK_DIALOG_DESTROY_WITH_PARENT,
539 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
540 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
541
542 frame = gtk_frame_new("Hostname / socket name");
543 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
544 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
545
546 box = gtk_vbox_new(FALSE, 6);
547 gtk_container_add(GTK_CONTAINER(frame), box);
548
549 hbox = gtk_hbox_new(TRUE, 10);
550 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
551 hentry = gtk_entry_new();
552 gtk_entry_set_text(GTK_ENTRY(hentry), "localhost");
553 gtk_box_pack_start(GTK_BOX(hbox), hentry, TRUE, TRUE, 0);
554
555 frame = gtk_frame_new("Port");
556 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
557 box = gtk_vbox_new(FALSE, 10);
558 gtk_container_add(GTK_CONTAINER(frame), box);
559
560 hbox = gtk_hbox_new(TRUE, 4);
561 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
562 pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT);
563
564 frame = gtk_frame_new("Type");
565 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
566 box = gtk_vbox_new(FALSE, 10);
567 gtk_container_add(GTK_CONTAINER(frame), box);
568
569 hbox = gtk_hbox_new(TRUE, 4);
570 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
571
572 combo = gtk_combo_box_text_new();
573 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv4");
574 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "IPv6");
575 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), "local socket");
576 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
577
578 gtk_container_add(GTK_CONTAINER(hbox), combo);
579
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100580 frame = gtk_frame_new("Options");
581 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
582 box = gtk_vbox_new(FALSE, 10);
583 gtk_container_add(GTK_CONTAINER(frame), box);
584
585 hbox = gtk_hbox_new(TRUE, 4);
586 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
587
588 button = gtk_check_button_new_with_label("Auto-spawn fio backend");
589 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
590 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.");
591 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
592
Jens Axboea7a42ce2012-03-02 13:12:04 +0100593 gtk_widget_show_all(dialog);
594
595 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
596 gtk_widget_destroy(dialog);
597 return 1;
598 }
599
600 *host = strdup(gtk_entry_get_text(GTK_ENTRY(hentry)));
601 *port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
602
603 typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
604 if (!typeentry || !strncmp(typeentry, "IPv4", 4))
605 *type = Fio_client_ipv4;
606 else if (!strncmp(typeentry, "IPv6", 4))
607 *type = Fio_client_ipv6;
608 else
609 *type = Fio_client_socket;
610 g_free(typeentry);
611
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100612 *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
613
Jens Axboea7a42ce2012-03-02 13:12:04 +0100614 gtk_widget_destroy(dialog);
615 return 0;
616}
617
Jens Axboe0420ba62012-02-29 11:16:52 +0100618static void file_open(GtkWidget *w, gpointer data)
619{
620 GtkWidget *dialog;
621 GSList *filenames, *fn_glist;
622 GtkFileFilter *filter;
Jens Axboea7a42ce2012-03-02 13:12:04 +0100623 char *host;
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100624 int port, type, server_start;
Jens Axboe0420ba62012-02-29 11:16:52 +0100625
626 dialog = gtk_file_chooser_dialog_new("Open File",
627 GTK_WINDOW(ui.window),
628 GTK_FILE_CHOOSER_ACTION_OPEN,
629 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
630 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
631 NULL);
632 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
633
634 filter = gtk_file_filter_new();
635 gtk_file_filter_add_pattern(filter, "*.fio");
636 gtk_file_filter_add_pattern(filter, "*.job");
637 gtk_file_filter_add_mime_type(filter, "text/fio");
638 gtk_file_filter_set_name(filter, "Fio job file");
639 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
640
641 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
642 gtk_widget_destroy(dialog);
643 return;
644 }
645
646 fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
Jens Axboea7a42ce2012-03-02 13:12:04 +0100647
648 gtk_widget_destroy(dialog);
649
Jens Axboeb9f3c7e2012-03-02 14:27:17 +0100650 if (get_connection_details(&host, &port, &type, &server_start))
Jens Axboea7a42ce2012-03-02 13:12:04 +0100651 goto err;
652
Jens Axboe0420ba62012-02-29 11:16:52 +0100653 filenames = fn_glist;
654 while (filenames != NULL) {
Jens Axboe0420ba62012-02-29 11:16:52 +0100655 ui.job_files = realloc(ui.job_files, (ui.nr_job_files + 1) * sizeof(char *));
656 ui.job_files[ui.nr_job_files] = strdup(filenames->data);
657 ui.nr_job_files++;
658
Jens Axboea7a42ce2012-03-02 13:12:04 +0100659 ui.client = fio_client_add_explicit(host, type, port);
Jens Axboedf06f222012-03-02 13:32:04 +0100660 if (!ui.client) {
661 GError *error;
662
663 error = g_error_new(g_quark_from_string("fio"), 1,
664 "Failed to add client %s", host);
Jens Axboe0420ba62012-02-29 11:16:52 +0100665 report_error(error);
666 g_error_free(error);
Jens Axboe0420ba62012-02-29 11:16:52 +0100667 }
Jens Axboedf06f222012-03-02 13:32:04 +0100668 ui.client->client_data = &ui;
Jens Axboe0420ba62012-02-29 11:16:52 +0100669
670 g_free(filenames->data);
671 filenames = g_slist_next(filenames);
672 }
Jens Axboea7a42ce2012-03-02 13:12:04 +0100673 free(host);
674err:
Jens Axboe0420ba62012-02-29 11:16:52 +0100675 g_slist_free(fn_glist);
Jens Axboe0420ba62012-02-29 11:16:52 +0100676}
677
678static void file_save(GtkWidget *w, gpointer data)
679{
680 GtkWidget *dialog;
681
682 dialog = gtk_file_chooser_dialog_new("Save File",
683 GTK_WINDOW(ui.window),
684 GTK_FILE_CHOOSER_ACTION_SAVE,
685 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
686 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
687 NULL);
688
689 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
690 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document");
691
692 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
693 char *filename;
694
695 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
696 // save_job_file(filename);
697 g_free(filename);
698 }
699 gtk_widget_destroy(dialog);
700}
701
Jens Axboe46974a72012-03-02 19:34:13 +0100702static void preferences(GtkWidget *w, gpointer data)
703{
704 GtkWidget *dialog, *frame, *box, **buttons;
705 int i;
706
707 dialog = gtk_dialog_new_with_buttons("Preferences",
708 GTK_WINDOW(ui.window),
709 GTK_DIALOG_DESTROY_WITH_PARENT,
710 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
711 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
712 NULL);
713
Jens Axboe0b8d11e2012-03-02 19:44:15 +0100714 frame = gtk_frame_new("Debug logging");
Jens Axboe46974a72012-03-02 19:34:13 +0100715 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
716 box = gtk_hbox_new(FALSE, 6);
717 gtk_container_add(GTK_CONTAINER(frame), box);
718
719 buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
720
721 for (i = 0; i < FD_DEBUG_MAX; i++) {
722 buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
Jens Axboe0b8d11e2012-03-02 19:44:15 +0100723 gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
Jens Axboe46974a72012-03-02 19:34:13 +0100724 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}