From: Jens Axboe Date: Thu, 1 Mar 2012 11:01:29 +0000 (+0100) Subject: More gui changes X-Git-Tag: gfio-0.1~286 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=3ec62ec45ce971b76dd3029412dfd3d0c6221384 More gui changes - Move progress bar into connect/start field - Pretty up port/type boxes - Hook better into adding clients - Add ->quit hook for client ops - Ensure fio_handle_clients() stays connected for GUI clients - Stop server from repeatedly sending RUN commands Signed-off-by: Jens Axboe --- diff --git a/client.c b/client.c index 842f225c..d8012364 100644 --- a/client.c +++ b/client.c @@ -169,6 +169,49 @@ void fio_client_add_cmd_option(void *cookie, const char *opt) } } +struct fio_client *fio_client_add_explicit(const char *hostname, int type, + int port) +{ + struct fio_client *client; + + client = malloc(sizeof(*client)); + memset(client, 0, sizeof(*client)); + + INIT_FLIST_HEAD(&client->list); + INIT_FLIST_HEAD(&client->hash_list); + INIT_FLIST_HEAD(&client->arg_list); + INIT_FLIST_HEAD(&client->eta_list); + INIT_FLIST_HEAD(&client->cmd_list); + + client->hostname = strdup(hostname); + + if (type == Fio_client_socket) + client->is_sock = 1; + else { + int ipv6; + + ipv6 = type == Fio_client_ipv6; + if (fio_server_parse_host(hostname, &ipv6, + &client->addr.sin_addr, + &client->addr6.sin6_addr)) + goto err; + + client->port = port; + } + + client->fd = -1; + + __fio_client_add_cmd_option(client, "fio"); + + flist_add(&client->list, &client_list); + nr_clients++; + dprint(FD_NET, "client: added <%s>\n", client->hostname); + return client; +err: + free(client); + return NULL; +} + int fio_client_add(const char *hostname, void **cookie) { struct fio_client *existing = *cookie; @@ -823,6 +866,8 @@ int fio_handle_client(struct fio_client *client, struct client_ops *ops) switch (cmd->opcode) { case FIO_NET_CMD_QUIT: + if (ops->quit) + ops->quit(client); remove_client(client); free(cmd); break; @@ -981,7 +1026,7 @@ int fio_handle_clients(struct client_ops *ops) flist_for_each_safe(entry, tmp, &client_list) { client = flist_entry(entry, struct fio_client, list); - if (!client->sent_job && + if (!client->sent_job && !ops->stay_connected && flist_empty(&client->cmd_list)) { remove_client(client); continue; diff --git a/client.h b/client.h index 4146607e..00714841 100644 --- a/client.h +++ b/client.h @@ -42,6 +42,8 @@ struct fio_client { uint16_t argc; char **argv; + + void *client_data; }; typedef void (*client_text_op_func)(struct fio_client *client, @@ -59,6 +61,8 @@ typedef void (*client_probe_op)(struct fio_client *client, struct fio_net_cmd *c typedef void (*client_thread_status_display_op)(char *status_message, double perc); +typedef void (*client_quit_op)(struct fio_client *); + struct client_ops { client_text_op_func text_op; client_disk_util_op_func disk_util; @@ -66,6 +70,8 @@ struct client_ops { client_group_stats_op group_stats; client_eta_op eta; client_probe_op probe; + client_quit_op quit; + int stay_connected; }; extern struct client_ops fio_client_ops; @@ -80,5 +86,18 @@ extern void fio_client_dec_jobs_eta(struct client_eta *eta, void (*fn)(struct jo extern void fio_client_sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je); extern void fio_client_convert_jobs_eta(struct jobs_eta *je); +enum { + Fio_client_ipv4 = 1, + Fio_client_ipv6, + Fio_client_socket, +}; + +extern int fio_clients_connect(void); +extern int fio_clients_send_ini(const char *); +extern int fio_handle_clients(struct client_ops *ops); +extern int fio_client_add(const char *, void **); +extern struct fio_client *fio_client_add_explicit(const char *, int, int); +extern void fio_client_add_cmd_option(void *, const char *); + #endif diff --git a/gfio.c b/gfio.c index 34b578d2..848e511a 100644 --- a/gfio.c +++ b/gfio.c @@ -83,8 +83,8 @@ struct gui { GtkWidget *hostname_hbox; GtkWidget *hostname_label; GtkWidget *hostname_entry; + GtkWidget *port_button; GtkWidget *port_label; - GtkWidget *port_entry; GtkWidget *hostname_combo_box; /* ipv4, ipv6 or socket */ GtkWidget *scrolled_window; GtkWidget *textview; @@ -93,13 +93,27 @@ struct gui { GtkTextBuffer *text; struct probe_widget probe; struct eta_widget eta; + int connected; pthread_t t; - void *cookie; + struct fio_client *client; int nr_job_files; char **job_files; } ui; +static void gfio_set_connected(struct gui *ui, int connected) +{ + if (connected) { + gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); + ui->connected = 1; + gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect"); + } else { + ui->connected = 0; + gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect"); + gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0); + } +} + static void gfio_text_op(struct fio_client *client, FILE *f, __u16 pdu_len, const char *buf) { @@ -265,6 +279,13 @@ static void gfio_update_thread_status(char *status_message, double perc) gdk_threads_leave(); } +static void gfio_quit_op(struct fio_client *client) +{ + struct gui *ui = client->client_data; + + gfio_set_connected(ui, 0); +} + struct client_ops gfio_client_ops = { .text_op = gfio_text_op, .disk_util = gfio_disk_util_op, @@ -272,6 +293,8 @@ struct client_ops gfio_client_ops = { .group_stats = gfio_group_stats_op, .eta = gfio_eta_op, .probe = gfio_probe_op, + .quit = gfio_quit_op, + .stay_connected = 1, }; static void quit_clicked(__attribute__((unused)) GtkWidget *widget, @@ -282,10 +305,9 @@ static void quit_clicked(__attribute__((unused)) GtkWidget *widget, static void *job_thread(void *arg) { - struct gui *ui = arg; - + printf("job thread starts\n"); fio_handle_clients(&gfio_client_ops); - gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); + printf("job thread exits\n"); return NULL; } @@ -310,15 +332,13 @@ static int send_job_files(struct gui *ui) return ret; } -static void start_job_thread(pthread_t *t, struct gui *ui) +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; } - - pthread_create(t, NULL, job_thread, ui); } static void start_job_clicked(__attribute__((unused)) GtkWidget *widget, @@ -327,14 +347,20 @@ static void start_job_clicked(__attribute__((unused)) GtkWidget *widget, struct gui *ui = data; gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0); - start_job_thread(&ui->t, ui); + start_job_thread(ui); } static void connect_clicked(__attribute__((unused)) GtkWidget *widget, gpointer data) { - fio_clients_connect(); - gtk_widget_set_sensitive(ui.button[START_JOB_BUTTON], 1); + struct gui *ui = data; + + if (!ui->connected) { + fio_clients_connect(); + pthread_create(&ui->t, NULL, job_thread, NULL); + gfio_set_connected(ui, 1); + } else + gfio_set_connected(ui, 0); } static void add_button(struct gui *ui, int i, GtkWidget *buttonbox, @@ -342,7 +368,7 @@ static void add_button(struct gui *ui, int i, GtkWidget *buttonbox, { ui->button[i] = gtk_button_new_with_label(buttonspec->buttontext); g_signal_connect(ui->button[i], "clicked", G_CALLBACK (buttonspec->f), ui); - gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX (ui->buttonbox), ui->button[i], FALSE, FALSE, 3); gtk_widget_set_tooltip_text(ui->button[i], buttonspeclist[i].tooltiptext); gtk_widget_set_sensitive(ui->button[i], !buttonspec->start_insensitive); } @@ -419,13 +445,27 @@ static void file_open(GtkWidget *w, gpointer data) filenames = fn_glist; while (filenames != NULL) { const char *hostname; + char *typeentry; + gint port; + int type; ui.job_files = realloc(ui.job_files, (ui.nr_job_files + 1) * sizeof(char *)); ui.job_files[ui.nr_job_files] = strdup(filenames->data); ui.nr_job_files++; hostname = gtk_entry_get_text(GTK_ENTRY(ui.hostname_entry)); - fio_client_add(hostname, &ui.cookie); + port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ui.port_button)); + typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(ui.hostname_combo_box)); + if (!typeentry || !strncmp(typeentry, "IPv4", 4)) + type = Fio_client_ipv4; + else if (!strncmp(typeentry, "IPv6", 4)) + type = Fio_client_ipv6; + else + type = Fio_client_socket; + g_free(typeentry); + + ui.client = fio_client_add_explicit(hostname, type, port); + ui.client->client_data = &ui; #if 0 if (error) { report_error(error); @@ -539,10 +579,42 @@ static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label) return label_widget; } +static GtkWidget *create_text_entry(GtkWidget *hbox, GtkWidget *label, const char *defval) +{ + GtkWidget *text, *box; + + gtk_container_add(GTK_CONTAINER(hbox), label); + + box = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(hbox), box); + + text = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(box), text, TRUE, TRUE, 0); + gtk_entry_set_text(GTK_ENTRY(text), "localhost"); + + return text; +} + +static GtkWidget *create_spinbutton(GtkWidget *hbox, GtkWidget *label, double min, double max, double defval) +{ + GtkWidget *button, *box; + + gtk_container_add(GTK_CONTAINER(hbox), label); + + box = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(hbox), box); + + button = gtk_spin_button_new_with_range(min, max, 1.0); + gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0); + + gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), defval); + + return button; +} + static void init_ui(int *argc, char **argv[], struct gui *ui) { - GList *hostname_type_list = NULL; - char portnum[20]; GtkSettings *settings; GtkUIManager *uimanager; GtkWidget *menu, *probe, *probe_frame, *probe_box; @@ -581,7 +653,7 @@ static void init_ui(int *argc, char **argv[], struct gui *ui) * align top left, expand horizontally but not vertically */ ui->topalign = gtk_alignment_new(0, 0, 1, 0); - ui->topvbox = gtk_vbox_new(FALSE, 0); + ui->topvbox = gtk_vbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(ui->topalign), ui->topvbox); gtk_box_pack_start(GTK_BOX(ui->vbox), ui->topalign, FALSE, FALSE, 0); @@ -589,31 +661,24 @@ static void init_ui(int *argc, char **argv[], struct gui *ui) * Set up hostname label + entry, port label + entry, */ ui->hostname_hbox = gtk_hbox_new(FALSE, 0); - ui->hostname_label = gtk_label_new("Host:"); - ui->hostname_entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(ui->hostname_entry), "localhost"); + + ui->hostname_label = gtk_label_new("Hostname:"); + ui->hostname_entry = create_text_entry(ui->hostname_hbox, ui->hostname_label, "localhost"); + ui->port_label = gtk_label_new("Port:"); - ui->port_entry = gtk_entry_new(); - snprintf(portnum, sizeof(portnum) - 1, "%d", FIO_NET_PORT); - gtk_entry_set_text(GTK_ENTRY(ui->port_entry), (gchar *) portnum); + ui->port_button = create_spinbutton(ui->hostname_hbox, ui->port_label, 1, 65535, FIO_NET_PORT); /* * Set up combo box for address type */ - ui->hostname_combo_box = gtk_combo_new(); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ui->hostname_combo_box)->entry), "IPv4"); - hostname_type_list = g_list_append(hostname_type_list, (gpointer) "IPv4"); - hostname_type_list = g_list_append(hostname_type_list, (gpointer) "local socket"); - hostname_type_list = g_list_append(hostname_type_list, (gpointer) "IPv6"); - gtk_combo_set_popdown_strings(GTK_COMBO(ui->hostname_combo_box), hostname_type_list); - g_list_free(hostname_type_list); - - gtk_container_add(GTK_CONTAINER (ui->hostname_hbox), ui->hostname_label); - gtk_container_add(GTK_CONTAINER (ui->hostname_hbox), ui->hostname_entry); - gtk_container_add(GTK_CONTAINER (ui->hostname_hbox), ui->port_label); - gtk_container_add(GTK_CONTAINER (ui->hostname_hbox), ui->port_entry); - gtk_container_add(GTK_CONTAINER (ui->hostname_hbox), ui->hostname_combo_box); - gtk_container_add(GTK_CONTAINER (ui->topvbox), ui->hostname_hbox); + ui->hostname_combo_box = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(ui->hostname_combo_box), "IPv4"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(ui->hostname_combo_box), "IPv6"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(ui->hostname_combo_box), "local socket"); + gtk_combo_box_set_active(GTK_COMBO_BOX(ui->hostname_combo_box), 0); + + gtk_container_add(GTK_CONTAINER(ui->hostname_hbox), ui->hostname_combo_box); + gtk_container_add(GTK_CONTAINER(ui->topvbox), ui->hostname_hbox); probe = gtk_frame_new("Job"); gtk_box_pack_start(GTK_BOX(ui->topvbox), probe, TRUE, FALSE, 3); @@ -646,14 +711,6 @@ static void init_ui(int *argc, char **argv[], struct gui *ui) ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW"); ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS"); - /* - * Set up thread status progress bar - */ - ui->thread_status_pb = gtk_progress_bar_new(); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running"); - gtk_container_add(GTK_CONTAINER(ui->topvbox), ui->thread_status_pb); - /* * Add a text box for text op messages */ @@ -680,6 +737,16 @@ static void init_ui(int *argc, char **argv[], struct gui *ui) FALSE, FALSE, 0); add_buttons(ui, buttonspeclist, ARRAYSIZE(buttonspeclist)); + + /* + * Set up thread status progress bar + */ + ui->thread_status_pb = gtk_progress_bar_new(); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running"); + gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb); + + gtk_widget_show_all(ui->window); } @@ -690,6 +757,7 @@ int main(int argc, char *argv[], char *envp[]) if (fio_init_options()) return 1; + fio_debug = ~0UL; init_ui(&argc, &argv, &ui); gdk_threads_enter(); diff --git a/server.c b/server.c index 2d9b009f..a2db9dd5 100644 --- a/server.c +++ b/server.c @@ -554,8 +554,10 @@ static int handle_connection(int sk, int block) void fio_server_idle_loop(void) { - if (!first_cmd_check) + if (!first_cmd_check) { fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_RUN, 0, NULL); + first_cmd_check = 1; + } if (server_fd != -1) handle_connection(server_fd, 0); } @@ -943,6 +945,46 @@ static int fio_init_server_connection(void) return sk; } +int fio_server_parse_host(const char *host, int *ipv6, struct in_addr *inp, + struct in6_addr *inp6) + +{ + int ret = 0; + + if (*ipv6) + ret = inet_pton(AF_INET6, host, inp6); + else + ret = inet_pton(AF_INET, host, inp); + + if (ret != 1) { + struct hostent *hent; + + hent = gethostbyname(host); + if (!hent) { + log_err("fio: failed to resolve <%s>\n", host); + return 0; + } + + if (*ipv6) { + if (hent->h_addrtype != AF_INET6) { + log_info("fio: falling back to IPv4\n"); + *ipv6 = 0; + } else + memcpy(inp6, hent->h_addr_list[0], 16); + } + if (!*ipv6) { + if (hent->h_addrtype != AF_INET) { + log_err("fio: lookup type mismatch\n"); + return 0; + } + memcpy(inp, hent->h_addr_list[0], 4); + } + ret = 1; + } + + return !(ret == 1); +} + /* * Parse a host/ip/port string. Reads from 'str'. * @@ -961,7 +1003,7 @@ int fio_server_parse_string(const char *str, char **ptr, int *is_sock, { const char *host = str; char *portp; - int ret, lport = 0; + int lport = 0; *ptr = NULL; *is_sock = 0; @@ -1022,38 +1064,10 @@ int fio_server_parse_string(const char *str, char **ptr, int *is_sock, *ptr = strdup(host); - if (*ipv6) - ret = inet_pton(AF_INET6, host, inp6); - else - ret = inet_pton(AF_INET, host, inp); - - if (ret != 1) { - struct hostent *hent; - - hent = gethostbyname(host); - if (!hent) { - log_err("fio: failed to resolve <%s>\n", host); - free(*ptr); - *ptr = NULL; - return 1; - } - - if (*ipv6) { - if (hent->h_addrtype != AF_INET6) { - log_info("fio: falling back to IPv4\n"); - *ipv6 = 0; - } else - memcpy(inp6, hent->h_addr_list[0], 16); - } - if (!*ipv6) { - if (hent->h_addrtype != AF_INET) { - log_err("fio: lookup type mismatch\n"); - free(*ptr); - *ptr = NULL; - return 1; - } - memcpy(inp, hent->h_addr_list[0], 4); - } + if (fio_server_parse_host(*ptr, ipv6, inp, inp6)) { + free(*ptr); + *ptr = NULL; + return 1; } if (*port == 0) diff --git a/server.h b/server.h index f2dd29fa..d17c0cea 100644 --- a/server.h +++ b/server.h @@ -113,6 +113,7 @@ extern int fio_net_send_cmd(int, uint16_t, const void *, off_t, uint64_t); extern int fio_net_send_simple_cmd(int, uint16_t, uint64_t, struct flist_head *); extern void fio_server_set_arg(const char *); extern int fio_server_parse_string(const char *, char **, int *, int *, struct in_addr *, struct in6_addr *, int *); +extern int fio_server_parse_host(const char *, int *, struct in_addr *, struct in6_addr *); extern const char *fio_server_op(unsigned int); extern void fio_server_got_signal(int); @@ -123,12 +124,6 @@ extern void fio_server_send_gs(struct group_run_stats *); extern void fio_server_send_du(void); extern void fio_server_idle_loop(void); -extern int fio_clients_connect(void); -extern int fio_clients_send_ini(const char *); -extern int fio_handle_clients(struct client_ops *ops); -extern int fio_client_add(const char *, void **); -extern void fio_client_add_cmd_option(void *, const char *); - extern int fio_recv_data(int sk, void *p, unsigned int len); extern int fio_send_data(int sk, const void *p, unsigned int len); extern void fio_net_cmd_crc(struct fio_net_cmd *);