Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 1 | /* |
| 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. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 23 | #include <locale.h> |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 24 | #include <malloc.h> |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 25 | |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 26 | #include <glib.h> |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 27 | #include <gtk/gtk.h> |
| 28 | |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 29 | #include "fio.h" |
| 30 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 31 | static void gfio_update_thread_status(char *status_message, double perc); |
| 32 | |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 33 | #define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0]))) |
| 34 | |
| 35 | typedef void (*clickfunction)(GtkWidget *widget, gpointer data); |
| 36 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 37 | static void connect_clicked(GtkWidget *widget, gpointer data); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 38 | static void start_job_clicked(GtkWidget *widget, gpointer data); |
| 39 | |
| 40 | static struct button_spec { |
| 41 | const char *buttontext; |
| 42 | clickfunction f; |
| 43 | const char *tooltiptext; |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 44 | const int start_insensitive; |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 45 | } buttonspeclist[] = { |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 46 | #define CONNECT_BUTTON 0 |
| 47 | #define START_JOB_BUTTON 1 |
| 48 | { "Connect", connect_clicked, "Connect to host", 0 }, |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 49 | { "Start Job", |
| 50 | start_job_clicked, |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 51 | "Send current fio job to fio server to be executed", 1 }, |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 52 | }; |
| 53 | |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 54 | struct probe_widget { |
| 55 | GtkWidget *hostname; |
| 56 | GtkWidget *os; |
| 57 | GtkWidget *arch; |
| 58 | GtkWidget *fio_ver; |
| 59 | }; |
| 60 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 61 | struct eta_widget { |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 62 | GtkWidget *name; |
| 63 | GtkWidget *iotype; |
| 64 | GtkWidget *ioengine; |
| 65 | GtkWidget *iodepth; |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 66 | 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. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 78 | struct gui { |
| 79 | GtkWidget *window; |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 80 | GtkWidget *vbox; |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 81 | GtkWidget *topvbox; |
| 82 | GtkWidget *topalign; |
| 83 | GtkWidget *bottomalign; |
Stephen M. Cameron | 04cc6b7 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 84 | GtkWidget *thread_status_pb; |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 85 | GtkWidget *buttonbox; |
| 86 | GtkWidget *button[ARRAYSIZE(buttonspeclist)]; |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 87 | GtkWidget *scrolled_window; |
| 88 | GtkWidget *textview; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 89 | GtkWidget *error_info_bar; |
| 90 | GtkWidget *error_label; |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 91 | GtkTextBuffer *text; |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 92 | struct probe_widget probe; |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 93 | struct eta_widget eta; |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 94 | int connected; |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 95 | pthread_t t; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 96 | |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 97 | struct fio_client *client; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 98 | int nr_job_files; |
| 99 | char **job_files; |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 100 | } ui; |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 101 | |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 102 | static 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 Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 120 | static 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); |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 130 | clear_ui_info(ui); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 134 | static void gfio_text_op(struct fio_client *client, |
| 135 | FILE *f, __u16 pdu_len, const char *buf) |
| 136 | { |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 137 | #if 0 |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 138 | GtkTextBuffer *buffer; |
| 139 | GtkTextIter end; |
| 140 | |
| 141 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui.textview)); |
| 142 | gdk_threads_enter(); |
| 143 | gtk_text_buffer_get_end_iter(buffer, &end); |
| 144 | gtk_text_buffer_insert(buffer, &end, buf, -1); |
| 145 | gdk_threads_leave(); |
| 146 | gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ui.textview), |
| 147 | &end, 0.0, FALSE, 0.0,0.0); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 148 | #else |
| 149 | fio_client_ops.text_op(client, f, pdu_len, buf); |
| 150 | #endif |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 154 | { |
| 155 | printf("gfio_disk_util_op called\n"); |
| 156 | fio_client_ops.disk_util(client, cmd); |
| 157 | } |
| 158 | |
| 159 | static void gfio_thread_status_op(struct fio_net_cmd *cmd) |
| 160 | { |
| 161 | printf("gfio_thread_status_op called\n"); |
| 162 | fio_client_ops.thread_status(cmd); |
| 163 | } |
| 164 | |
| 165 | static void gfio_group_stats_op(struct fio_net_cmd *cmd) |
| 166 | { |
| 167 | printf("gfio_group_stats_op called\n"); |
| 168 | fio_client_ops.group_stats(cmd); |
| 169 | } |
| 170 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 171 | static 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 Axboe | ebbd89c | 2012-03-02 11:21:13 +0100 | [diff] [blame] | 206 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 207 | 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. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 251 | static void gfio_eta_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 252 | { |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 253 | struct jobs_eta *je = (struct jobs_eta *) cmd->payload; |
| 254 | struct client_eta *eta = (struct client_eta *) (uintptr_t) cmd->tag; |
| 255 | |
| 256 | client->eta_in_flight = NULL; |
| 257 | flist_del_init(&client->eta_list); |
| 258 | |
| 259 | fio_client_convert_jobs_eta(je); |
| 260 | fio_client_sum_jobs_eta(&eta->eta, je); |
| 261 | fio_client_dec_jobs_eta(eta, gfio_update_eta); |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | static void gfio_probe_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 265 | { |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 266 | struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload; |
| 267 | const char *os, *arch; |
| 268 | char buf[64]; |
| 269 | |
| 270 | os = fio_get_os_string(probe->os); |
| 271 | if (!os) |
| 272 | os = "unknown"; |
| 273 | |
| 274 | arch = fio_get_arch_string(probe->arch); |
| 275 | if (!arch) |
| 276 | os = "unknown"; |
| 277 | |
| 278 | if (!client->name) |
| 279 | client->name = strdup((char *) probe->hostname); |
| 280 | |
| 281 | gtk_label_set_text(GTK_LABEL(ui.probe.hostname), (char *) probe->hostname); |
| 282 | gtk_label_set_text(GTK_LABEL(ui.probe.os), os); |
| 283 | gtk_label_set_text(GTK_LABEL(ui.probe.arch), arch); |
| 284 | sprintf(buf, "%u.%u.%u", probe->fio_major, probe->fio_minor, probe->fio_patch); |
| 285 | gtk_label_set_text(GTK_LABEL(ui.probe.fio_ver), buf); |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 286 | } |
| 287 | |
Stephen M. Cameron | 04cc6b7 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 288 | static void gfio_update_thread_status(char *status_message, double perc) |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 289 | { |
| 290 | static char message[100]; |
| 291 | const char *m = message; |
| 292 | |
| 293 | strncpy(message, status_message, sizeof(message) - 1); |
Stephen M. Cameron | 04cc6b7 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 294 | gtk_progress_bar_set_text( |
| 295 | GTK_PROGRESS_BAR(ui.thread_status_pb), m); |
| 296 | gtk_progress_bar_set_fraction( |
| 297 | GTK_PROGRESS_BAR(ui.thread_status_pb), perc / 100.0); |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 298 | gdk_threads_enter(); |
| 299 | gtk_widget_queue_draw(ui.window); |
| 300 | gdk_threads_leave(); |
| 301 | } |
| 302 | |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 303 | static void gfio_quit_op(struct fio_client *client) |
| 304 | { |
| 305 | struct gui *ui = client->client_data; |
| 306 | |
| 307 | gfio_set_connected(ui, 0); |
| 308 | } |
| 309 | |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 310 | static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd) |
| 311 | { |
| 312 | struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload; |
| 313 | struct gui *ui = client->client_data; |
| 314 | char tmp[8]; |
| 315 | int i; |
| 316 | |
| 317 | p->iodepth = le32_to_cpu(p->iodepth); |
| 318 | p->rw = le32_to_cpu(p->rw); |
| 319 | |
| 320 | for (i = 0; i < 2; i++) { |
| 321 | p->min_bs[i] = le32_to_cpu(p->min_bs[i]); |
| 322 | p->max_bs[i] = le32_to_cpu(p->max_bs[i]); |
| 323 | } |
| 324 | |
| 325 | p->numjobs = le32_to_cpu(p->numjobs); |
| 326 | p->group_reporting = le32_to_cpu(p->group_reporting); |
| 327 | |
| 328 | gtk_label_set_text(GTK_LABEL(ui->eta.name), (gchar *) p->jobname); |
| 329 | gtk_label_set_text(GTK_LABEL(ui->eta.iotype), ddir_str(p->rw)); |
| 330 | gtk_label_set_text(GTK_LABEL(ui->eta.ioengine), (gchar *) p->ioengine); |
| 331 | |
| 332 | sprintf(tmp, "%u", p->iodepth); |
| 333 | gtk_label_set_text(GTK_LABEL(ui->eta.iodepth), tmp); |
| 334 | } |
| 335 | |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 336 | static void gfio_client_timed_out(struct fio_client *client) |
| 337 | { |
| 338 | struct gui *ui = client->client_data; |
| 339 | GtkWidget *dialog, *label, *content; |
| 340 | char buf[256]; |
| 341 | |
| 342 | gdk_threads_enter(); |
| 343 | |
| 344 | gfio_set_connected(ui, 0); |
| 345 | |
| 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. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 365 | struct client_ops gfio_client_ops = { |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 366 | .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 Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 372 | .quit = gfio_quit_op, |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 373 | .add_job = gfio_add_job_op, |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 374 | .timed_out = gfio_client_timed_out, |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 375 | .stay_connected = 1, |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 376 | }; |
| 377 | |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 378 | static void quit_clicked(__attribute__((unused)) GtkWidget *widget, |
| 379 | __attribute__((unused)) gpointer data) |
| 380 | { |
| 381 | gtk_main_quit(); |
| 382 | } |
| 383 | |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 384 | static void *job_thread(void *arg) |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 385 | { |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 386 | fio_handle_clients(&gfio_client_ops); |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 387 | return NULL; |
| 388 | } |
| 389 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 390 | static int send_job_files(struct gui *ui) |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 391 | { |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 392 | int i, ret = 0; |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 393 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 394 | for (i = 0; i < ui->nr_job_files; i++) { |
| 395 | ret = fio_clients_send_ini(ui->job_files[i]); |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 396 | if (ret) |
| 397 | break; |
| 398 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 399 | free(ui->job_files[i]); |
| 400 | ui->job_files[i] = NULL; |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 401 | } |
| 402 | while (i < ui->nr_job_files) { |
| 403 | free(ui->job_files[i]); |
| 404 | ui->job_files[i] = NULL; |
| 405 | i++; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 406 | } |
| 407 | |
Jens Axboe | 441013b | 2012-03-01 08:01:52 +0100 | [diff] [blame] | 408 | return ret; |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 409 | } |
| 410 | |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 411 | static void start_job_thread(struct gui *ui) |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 412 | { |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 413 | if (send_job_files(ui)) { |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 414 | printf("Yeah, I didn't really like those options too much.\n"); |
Stephen M. Cameron | 60f6b33 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 415 | gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); |
| 416 | return; |
| 417 | } |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 418 | } |
| 419 | |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 420 | static 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 Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 433 | static 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. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 449 | static void start_job_clicked(__attribute__((unused)) GtkWidget *widget, |
| 450 | gpointer data) |
| 451 | { |
| 452 | struct gui *ui = data; |
| 453 | |
Stephen M. Cameron | 2592725 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 454 | gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 455 | start_job_thread(ui); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 456 | } |
| 457 | |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 458 | static void file_open(GtkWidget *w, gpointer data); |
| 459 | |
| 460 | static void connect_clicked(GtkWidget *widget, gpointer data) |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 461 | { |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 462 | struct gui *ui = data; |
| 463 | |
| 464 | if (!ui->connected) { |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 465 | if (!ui->nr_job_files) |
| 466 | file_open(widget, data); |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 467 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running"); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 468 | fio_clients_connect(); |
| 469 | pthread_create(&ui->t, NULL, job_thread, NULL); |
| 470 | gfio_set_connected(ui, 1); |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 471 | } else { |
| 472 | fio_clients_terminate(); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 473 | gfio_set_connected(ui, 0); |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 474 | } |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 475 | } |
| 476 | |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 477 | static 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 Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 482 | gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 483 | gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 484 | gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive); |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 485 | } |
| 486 | |
| 487 | static void add_buttons(struct gui *ui, |
| 488 | struct button_spec *buttonlist, |
| 489 | int nbuttons) |
| 490 | { |
| 491 | int i; |
| 492 | |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 493 | for (i = 0; i < nbuttons; i++) |
| 494 | add_button(ui, i, ui->buttonbox, &buttonlist[i]); |
| 495 | } |
| 496 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 497 | static 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 Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 506 | void report_error(GError *error) |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 507 | { |
| 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 Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame^] | 529 | static int get_connection_details(char **host, int *port, int *type, |
| 530 | int *server_start) |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 531 | { |
| 532 | GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo; |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame^] | 533 | GtkWidget *button; |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 534 | 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 Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame^] | 580 | 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 Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 593 | 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 Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame^] | 612 | *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); |
| 613 | |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 614 | gtk_widget_destroy(dialog); |
| 615 | return 0; |
| 616 | } |
| 617 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 618 | static void file_open(GtkWidget *w, gpointer data) |
| 619 | { |
| 620 | GtkWidget *dialog; |
| 621 | GSList *filenames, *fn_glist; |
| 622 | GtkFileFilter *filter; |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 623 | char *host; |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame^] | 624 | int port, type, server_start; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 625 | |
| 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 Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 647 | |
| 648 | gtk_widget_destroy(dialog); |
| 649 | |
Jens Axboe | b9f3c7e | 2012-03-02 14:27:17 +0100 | [diff] [blame^] | 650 | if (get_connection_details(&host, &port, &type, &server_start)) |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 651 | goto err; |
| 652 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 653 | filenames = fn_glist; |
| 654 | while (filenames != NULL) { |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 655 | 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 Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 659 | ui.client = fio_client_add_explicit(host, type, port); |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 660 | 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 Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 665 | report_error(error); |
| 666 | g_error_free(error); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 667 | } |
Jens Axboe | df06f22 | 2012-03-02 13:32:04 +0100 | [diff] [blame] | 668 | ui.client->client_data = &ui; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 669 | |
| 670 | g_free(filenames->data); |
| 671 | filenames = g_slist_next(filenames); |
| 672 | } |
Jens Axboe | a7a42ce | 2012-03-02 13:12:04 +0100 | [diff] [blame] | 673 | free(host); |
| 674 | err: |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 675 | g_slist_free(fn_glist); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 676 | } |
| 677 | |
| 678 | static 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 | |
| 702 | static void about_dialog(GtkWidget *w, gpointer data) |
| 703 | { |
| 704 | gtk_show_about_dialog(NULL, |
| 705 | "program-name", "gfio", |
| 706 | "comments", "Gtk2 UI for fio", |
| 707 | "license", "GPLv2", |
| 708 | "version", fio_version_string, |
| 709 | "copyright", "Jens Axboe <axboe@kernel.dk> 2012", |
| 710 | "logo-icon-name", "fio", |
| 711 | /* Must be last: */ |
| 712 | NULL, NULL, |
| 713 | NULL); |
| 714 | } |
| 715 | |
| 716 | static GtkActionEntry menu_items[] = { |
| 717 | { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL}, |
| 718 | { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL}, |
| 719 | { "OpenFile", GTK_STOCK_OPEN, NULL, "<Control>O", NULL, G_CALLBACK(file_open) }, |
| 720 | { "SaveFile", GTK_STOCK_SAVE, NULL, "<Control>S", NULL, G_CALLBACK(file_save) }, |
| 721 | { "Quit", GTK_STOCK_QUIT, NULL, "<Control>Q", NULL, G_CALLBACK(quit_clicked) }, |
| 722 | { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) }, |
| 723 | }; |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 724 | static gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 725 | |
| 726 | static const gchar *ui_string = " \ |
| 727 | <ui> \ |
| 728 | <menubar name=\"MainMenu\"> \ |
| 729 | <menu name=\"FileMenu\" action=\"FileMenuAction\"> \ |
| 730 | <menuitem name=\"Open\" action=\"OpenFile\" /> \ |
| 731 | <menuitem name=\"Save\" action=\"SaveFile\" /> \ |
| 732 | <separator name=\"Separator\"/> \ |
| 733 | <menuitem name=\"Quit\" action=\"Quit\" /> \ |
| 734 | </menu> \ |
| 735 | <menu name=\"Help\" action=\"HelpMenuAction\"> \ |
| 736 | <menuitem name=\"About\" action=\"About\" /> \ |
| 737 | </menu> \ |
| 738 | </menubar> \ |
| 739 | </ui> \ |
| 740 | "; |
| 741 | |
| 742 | static GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager) |
| 743 | { |
| 744 | GtkActionGroup *action_group = gtk_action_group_new("Menu"); |
| 745 | GError *error = 0; |
| 746 | |
| 747 | action_group = gtk_action_group_new("Menu"); |
| 748 | gtk_action_group_add_actions(action_group, menu_items, nmenu_items, 0); |
| 749 | |
| 750 | gtk_ui_manager_insert_action_group(ui_manager, action_group, 0); |
| 751 | gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error); |
| 752 | |
| 753 | gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager)); |
| 754 | return gtk_ui_manager_get_widget(ui_manager, "/MainMenu"); |
| 755 | } |
| 756 | |
| 757 | void gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar, |
| 758 | GtkWidget *vbox, GtkUIManager *ui_manager) |
| 759 | { |
| 760 | gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); |
| 761 | } |
| 762 | |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 763 | static void init_ui(int *argc, char **argv[], struct gui *ui) |
| 764 | { |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 765 | GtkSettings *settings; |
| 766 | GtkUIManager *uimanager; |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 767 | GtkWidget *menu, *probe, *probe_frame, *probe_box; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 768 | |
| 769 | memset(ui, 0, sizeof(*ui)); |
Stephen M. Cameron | 45032dd | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 770 | |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 771 | /* Magical g*thread incantation, you just need this thread stuff. |
Stephen M. Cameron | 04cc6b7 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 772 | * Without it, the update that happens in gfio_update_thread_status |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 773 | * doesn't really happen in a timely fashion, you need expose events |
| 774 | */ |
Jens Axboe | ed727a4 | 2012-03-02 12:14:40 +0100 | [diff] [blame] | 775 | if (!g_thread_supported()) |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 776 | g_thread_init(NULL); |
| 777 | gdk_threads_init(); |
| 778 | |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 779 | gtk_init(argc, argv); |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 780 | settings = gtk_settings_get_default(); |
| 781 | gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting"); |
| 782 | g_type_init(); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 783 | |
| 784 | ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 785 | gtk_window_set_title(GTK_WINDOW(ui->window), "fio"); |
| 786 | gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500); |
| 787 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 788 | g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL); |
| 789 | g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 790 | |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 791 | ui->vbox = gtk_vbox_new(FALSE, 0); |
| 792 | gtk_container_add(GTK_CONTAINER (ui->window), ui->vbox); |
Stephen M. Cameron | 04cc6b7 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 793 | |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 794 | uimanager = gtk_ui_manager_new(); |
| 795 | menu = get_menubar_menu(ui->window, uimanager); |
| 796 | gfio_ui_setup(settings, menu, ui->vbox, uimanager); |
| 797 | |
Stephen M. Cameron | 04cc6b7 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 798 | /* |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 799 | * Set up alignments for widgets at the top of ui, |
| 800 | * align top left, expand horizontally but not vertically |
| 801 | */ |
| 802 | ui->topalign = gtk_alignment_new(0, 0, 1, 0); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 803 | ui->topvbox = gtk_vbox_new(FALSE, 3); |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 804 | gtk_container_add(GTK_CONTAINER(ui->topalign), ui->topvbox); |
Stephen M. Cameron | e164534 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 805 | gtk_box_pack_start(GTK_BOX(ui->vbox), ui->topalign, FALSE, FALSE, 0); |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 806 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 807 | probe = gtk_frame_new("Job"); |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 808 | gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3); |
| 809 | probe_frame = gtk_vbox_new(FALSE, 3); |
| 810 | gtk_container_add(GTK_CONTAINER(probe), probe_frame); |
| 811 | |
| 812 | probe_box = gtk_hbox_new(FALSE, 3); |
| 813 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3); |
Jens Axboe | 843ad23 | 2012-02-29 11:44:53 +0100 | [diff] [blame] | 814 | ui->probe.hostname = new_info_label_in_frame(probe_box, "Host"); |
| 815 | ui->probe.os = new_info_label_in_frame(probe_box, "OS"); |
| 816 | ui->probe.arch = new_info_label_in_frame(probe_box, "Architecture"); |
| 817 | ui->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version"); |
| 818 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 819 | probe_box = gtk_hbox_new(FALSE, 3); |
| 820 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 821 | |
| 822 | ui->eta.name = new_info_label_in_frame(probe_box, "Name"); |
| 823 | ui->eta.iotype = new_info_label_in_frame(probe_box, "IO"); |
| 824 | ui->eta.ioengine = new_info_label_in_frame(probe_box, "IO Engine"); |
| 825 | ui->eta.iodepth = new_info_label_in_frame(probe_box, "IO Depth"); |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 826 | ui->eta.jobs = new_info_label_in_frame(probe_box, "Jobs"); |
| 827 | ui->eta.files = new_info_label_in_frame(probe_box, "Open files"); |
| 828 | |
| 829 | probe_box = gtk_hbox_new(FALSE, 3); |
| 830 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3); |
| 831 | ui->eta.read_bw = new_info_label_in_frame(probe_box, "Read BW"); |
| 832 | ui->eta.read_iops = new_info_label_in_frame(probe_box, "IOPS"); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 833 | ui->eta.write_bw = new_info_label_in_frame(probe_box, "Write BW"); |
| 834 | ui->eta.write_iops = new_info_label_in_frame(probe_box, "IOPS"); |
| 835 | |
| 836 | /* |
| 837 | * Only add this if we have a commit rate |
| 838 | */ |
| 839 | #if 0 |
| 840 | probe_box = gtk_hbox_new(FALSE, 3); |
| 841 | gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3); |
| 842 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 843 | ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW"); |
| 844 | ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); |
| 845 | |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 846 | ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW"); |
| 847 | ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); |
Jens Axboe | 807f997 | 2012-03-02 10:25:24 +0100 | [diff] [blame] | 848 | #endif |
Jens Axboe | 3e47bd2 | 2012-02-29 13:45:02 +0100 | [diff] [blame] | 849 | |
Stephen M. Cameron | 45032dd | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 850 | /* |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 851 | * Add a text box for text op messages |
| 852 | */ |
| 853 | ui->textview = gtk_text_view_new(); |
| 854 | ui->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->textview)); |
| 855 | gtk_text_buffer_set_text(ui->text, "", -1); |
| 856 | gtk_text_view_set_editable(GTK_TEXT_VIEW(ui->textview), FALSE); |
| 857 | gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ui->textview), FALSE); |
| 858 | ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
| 859 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window), |
| 860 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
| 861 | gtk_container_add(GTK_CONTAINER(ui->scrolled_window), ui->textview); |
Stephen M. Cameron | e164534 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 862 | gtk_box_pack_start(GTK_BOX(ui->vbox), ui->scrolled_window, |
| 863 | TRUE, TRUE, 0); |
Stephen M. Cameron | 736f2df | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 864 | |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 865 | /* |
| 866 | * Set up alignments for widgets at the bottom of ui, |
| 867 | * align bottom left, expand horizontally but not vertically |
| 868 | */ |
| 869 | ui->bottomalign = gtk_alignment_new(0, 1, 1, 0); |
| 870 | ui->buttonbox = gtk_hbox_new(FALSE, 0); |
| 871 | gtk_container_add(GTK_CONTAINER(ui->bottomalign), ui->buttonbox); |
Stephen M. Cameron | e164534 | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 872 | gtk_box_pack_start(GTK_BOX(ui->vbox), ui->bottomalign, |
| 873 | FALSE, FALSE, 0); |
Stephen M. Cameron | c36f98d | 2012-02-24 08:17:32 +0100 | [diff] [blame] | 874 | |
Stephen M. Cameron | f307400 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 875 | add_buttons(ui, buttonspeclist, ARRAYSIZE(buttonspeclist)); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 876 | |
| 877 | /* |
| 878 | * Set up thread status progress bar |
| 879 | */ |
| 880 | ui->thread_status_pb = gtk_progress_bar_new(); |
| 881 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0); |
Jens Axboe | 8663ea6 | 2012-03-02 14:04:30 +0100 | [diff] [blame] | 882 | gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections"); |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 883 | gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb); |
| 884 | |
| 885 | |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 886 | gtk_widget_show_all(ui->window); |
| 887 | } |
| 888 | |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 889 | int main(int argc, char *argv[], char *envp[]) |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 890 | { |
Stephen M. Cameron | 8232e28 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 891 | if (initialize_fio(envp)) |
| 892 | return 1; |
Jens Axboe | 0420ba6 | 2012-02-29 11:16:52 +0100 | [diff] [blame] | 893 | if (fio_init_options()) |
| 894 | return 1; |
Stephen M. Cameron | a182020 | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 895 | |
Jens Axboe | 3ec62ec | 2012-03-01 12:01:29 +0100 | [diff] [blame] | 896 | fio_debug = ~0UL; |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 897 | init_ui(&argc, &argv, &ui); |
Stephen M. Cameron | 5b7573a | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 898 | |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 899 | gdk_threads_enter(); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 900 | gtk_main(); |
Stephen M. Cameron | 2839f0c | 2012-02-24 08:17:31 +0100 | [diff] [blame] | 901 | gdk_threads_leave(); |
Stephen M. Cameron | ff1f328 | 2012-02-24 08:17:30 +0100 | [diff] [blame] | 902 | return 0; |
| 903 | } |