*/
#include <locale.h>
#include <malloc.h>
+#include <string.h>
#include <glib.h>
#include <cairo.h>
static const char *gfio_graph_font;
static void gfio_update_thread_status(char *status_message, double perc);
+static void view_log(GtkWidget *w, gpointer data);
#define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0])))
static void connect_clicked(GtkWidget *widget, gpointer data);
static void start_job_clicked(GtkWidget *widget, gpointer data);
+static void send_clicked(GtkWidget *widget, gpointer data);
static struct button_spec {
const char *buttontext;
const int start_insensitive;
} buttonspeclist[] = {
#define CONNECT_BUTTON 0
-#define START_JOB_BUTTON 1
+#define SEND_BUTTON 1
+#define START_JOB_BUTTON 2
{ "Connect", connect_clicked, "Connect to host", 0 },
- { "Start Job",
- start_job_clicked,
+ { "Send", send_clicked, "Send job description to host", 1 },
+ { "Start Job", start_job_clicked,
"Send current fio job to fio server to be executed", 1 },
};
struct graph *iops_graph;
struct graph *bandwidth_graph;
- struct fio_client *client;
+ struct gfio_client *client;
int nr_job_files;
char **job_files;
} ui;
struct gfio_client {
struct gui *ui;
+ struct fio_client *client;
GtkWidget *results_widget;
GtkWidget *disk_util_frame;
+ GtkWidget *err_entry;
+ unsigned int job_added;
+ struct thread_options o;
};
static void setup_iops_graph(struct gui *ui)
DRAWING_AREA_YDIM, gfio_graph_font);
graph_title(ui->iops_graph, "IOPS");
graph_x_title(ui->iops_graph, "Time (secs)");
+ graph_y_title(ui->iops_graph, "IOs / sec");
graph_add_label(ui->iops_graph, "Read IOPS");
graph_add_label(ui->iops_graph, "Write IOPS");
graph_set_color(ui->iops_graph, "Read IOPS", 0.13, 0.54, 0.13);
DRAWING_AREA_YDIM, gfio_graph_font);
graph_title(ui->bandwidth_graph, "Bandwidth");
graph_x_title(ui->bandwidth_graph, "Time (secs)");
+ graph_y_title(ui->bandwidth_graph, "Kbytes / sec");
graph_add_label(ui->bandwidth_graph, "Read Bandwidth");
graph_add_label(ui->bandwidth_graph, "Write Bandwidth");
graph_set_color(ui->bandwidth_graph, "Read Bandwidth", 0.13, 0.54, 0.13);
static void gfio_set_connected(struct gui *ui, int connected)
{
if (connected) {
- gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+ gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1);
ui->connected = 1;
gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect");
gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
} else {
ui->connected = 0;
gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect");
+ gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0);
gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
}
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(win), "Results");
+ gtk_window_set_default_size(GTK_WINDOW(win), 1024, 768);
g_signal_connect(win, "delete-event", G_CALLBACK(results_window_delete), ui);
g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ui);
static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
struct group_run_stats *rs)
{
- GtkWidget *res_win, *box, *vbox, *entry;
+ GtkWidget *res_win, *box, *vbox, *entry, *scroll;
struct gfio_client *gc = client->client_data;
gdk_threads_enter();
res_win = get_results_window(gc->ui);
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
vbox = gtk_vbox_new(FALSE, 3);
- box = gtk_hbox_new(TRUE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
+ box = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), box, TRUE, FALSE, 5);
+
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox);
- gtk_notebook_append_page(GTK_NOTEBOOK(res_win), vbox, gtk_label_new(ts->name));
+ gtk_notebook_append_page(GTK_NOTEBOOK(res_win), scroll, gtk_label_new(ts->name));
gc->results_widget = vbox;
entry_set_int_value(entry, ts->groupid);
entry = new_info_entry_in_frame(box, "Jobs");
entry_set_int_value(entry, ts->members);
- entry = new_info_entry_in_frame(box, "Error");
+ gc->err_entry = entry = new_info_entry_in_frame(box, "Error");
entry_set_int_value(entry, ts->error);
entry = new_info_entry_in_frame(box, "PID");
entry_set_int_value(entry, ts->pid);
gtk_list_store_set(gc->ui->log_model, &iter, 2, p->level, -1);
gtk_list_store_set(gc->ui->log_model, &iter, 3, p->buf, -1);
+ if (p->level == FIO_LOG_ERR)
+ view_log(NULL, (gpointer) gc->ui);
+
gdk_threads_leave();
}
{
struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
struct gfio_client *gc = client->client_data;
+ struct thread_options *o = &gc->o;
struct gui *ui = gc->ui;
char tmp[8];
- int i;
-
- p->iodepth = le32_to_cpu(p->iodepth);
- p->rw = le32_to_cpu(p->rw);
- for (i = 0; i < 2; i++) {
- p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
- p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
- }
-
- p->numjobs = le32_to_cpu(p->numjobs);
- p->group_reporting = le32_to_cpu(p->group_reporting);
+ convert_thread_options_to_cpu(o, &p->top);
gdk_threads_enter();
- gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) p->jobname);
- gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(p->rw));
- gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) p->ioengine);
+ gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) o->name);
+ gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(o->td_ddir));
+ gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) o->ioengine);
- sprintf(tmp, "%u", p->iodepth);
+ sprintf(tmp, "%u", o->iodepth);
gtk_entry_set_text(GTK_ENTRY(ui->eta.iodepth), tmp);
+ gc->job_added++;
+
gdk_threads_leave();
}
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ /* gtk_dialog_get_content_area() is 2.14 and newer */
+ content = GTK_DIALOG(dialog)->vbox;
+
label = gtk_label_new((const gchar *) buf);
gtk_container_add(GTK_CONTAINER(content), label);
gtk_widget_show_all(dialog);
gdk_threads_leave();
}
+static void gfio_client_stop(struct fio_client *client, struct fio_net_cmd *cmd)
+{
+ struct gfio_client *gc = client->client_data;
+
+ gdk_threads_enter();
+
+ gfio_set_connected(gc->ui, 0);
+
+ if (gc->err_entry)
+ entry_set_int_value(gc->err_entry, client->error);
+
+ gdk_threads_leave();
+}
+
struct client_ops gfio_client_ops = {
.text_op = gfio_text_op,
.disk_util = gfio_disk_util_op,
.quit = gfio_quit_op,
.add_job = gfio_add_job_op,
.timed_out = gfio_client_timed_out,
+ .stop = gfio_client_stop,
.stay_connected = 1,
};
return ret;
}
-static void start_job_thread(struct gui *ui)
-{
- if (send_job_files(ui)) {
- printf("Yeah, I didn't really like those options too much.\n");
- gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
- return;
- }
-}
-
static void *server_thread(void *arg)
{
is_backend = 1;
gpointer data)
{
struct gui *ui = data;
+ struct gfio_client *gc = ui->client;
gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
- start_job_thread(ui);
+ fio_net_send_simple_cmd(gc->client->fd, FIO_NET_CMD_RUN, 0, NULL);
}
static void file_open(GtkWidget *w, gpointer data);
if (!fio_clients_connect()) {
pthread_create(&ui->t, NULL, job_thread, NULL);
gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 0);
+ gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1);
}
} else {
fio_clients_terminate();
}
}
+static void send_clicked(GtkWidget *widget, gpointer data)
+{
+ struct gui *ui = data;
+
+ if (send_job_files(ui)) {
+ printf("Yeah, I didn't really like those options too much.\n");
+ gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+ }
+
+ gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0);
+ gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+}
+
static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
struct button_spec *buttonspec)
{
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
frame = gtk_frame_new("Hostname / socket name");
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ /* gtk_dialog_get_content_area() is 2.14 and newer */
+ vbox = GTK_DIALOG(dialog)->vbox;
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
box = gtk_vbox_new(FALSE, 6);
gc = malloc(sizeof(*gc));
memset(gc, 0, sizeof(*gc));
gc->ui = ui;
+ gc->client = client;
+
+ ui->client = gc;
client->client_data = gc;
}