static struct timeval eta_tv;
-enum {
- Client_created = 0,
- Client_connected = 1,
- Client_started = 2,
- Client_running = 3,
- Client_stopped = 4,
- Client_exited = 5,
-};
-
static FLIST_HEAD(client_list);
static FLIST_HEAD(eta_list);
return !nr_clients;
}
+int fio_start_client(struct fio_client *client)
+{
+ dprint(FD_NET, "client: start %s\n", client->hostname);
+ return fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_RUN, 0, NULL);
+}
+
+int fio_start_all_clients(void)
+{
+ struct fio_client *client;
+ struct flist_head *entry, *tmp;
+ int ret;
+
+ dprint(FD_NET, "client: start all\n");
+
+ flist_for_each_safe(entry, tmp, &client_list) {
+ client = flist_entry(entry, struct fio_client, list);
+
+ ret = fio_start_client(client);
+ if (ret) {
+ remove_client(client);
+ continue;
+ }
+ }
+
+ return flist_empty(&client_list);
+}
+
/*
* Send file contents to server backend. We could use sendfile(), but to remain
* more portable lets just read/write the darn thing.
if (!cmd)
return 0;
- dprint(FD_NET, "client: got cmd op %s from %s\n",
- fio_server_op(cmd->opcode), client->hostname);
+ dprint(FD_NET, "client: got cmd op %s from %s (pdu=%u)\n",
+ fio_server_op(cmd->opcode), client->hostname, cmd->pdu_len);
switch (cmd->opcode) {
case FIO_NET_CMD_QUIT:
struct fio_net_cmd;
struct client_ops;
+enum {
+ Client_created = 0,
+ Client_connected = 1,
+ Client_started = 2,
+ Client_running = 3,
+ Client_stopped = 4,
+ Client_exited = 5,
+};
+
struct fio_client {
struct flist_head list;
struct flist_head hash_list;
};
extern int fio_clients_connect(void);
+extern int fio_start_client(struct fio_client *);
+extern int fio_start_all_clients(void);
extern int fio_clients_send_ini(const char *);
extern int fio_handle_clients(struct client_ops *);
extern int fio_client_add(struct client_ops *, const char *, void **);
if (parse_options(argc, argv))
return 1;
- if (nr_clients)
+ if (nr_clients) {
+ if (fio_start_all_clients())
+ return 1;
return fio_handle_clients(&fio_client_ops);
- else
+ } else
return fio_backend();
}
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;
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);
}
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)
{
gc = malloc(sizeof(*gc));
memset(gc, 0, sizeof(*gc));
gc->ui = ui;
+ gc->client = client;
+
+ ui->client = gc;
client->client_data = gc;
}
"START",
"STOP",
"DISK_UTIL",
- "RUN",
+ "SERVER_START",
"ADD_JOB",
+ "CMD_RUN"
};
const char *fio_server_op(unsigned int op)
int fio_send_data(int sk, const void *p, unsigned int len)
{
- assert(len <= sizeof(struct fio_net_cmd) + FIO_SERVER_MAX_PDU);
+ assert(len <= sizeof(struct fio_net_cmd) + FIO_SERVER_MAX_FRAGMENT_PDU);
do {
int ret = send(sk, p, len, 0);
return 1;
}
- if (cmd->pdu_len > FIO_SERVER_MAX_PDU) {
+ if (cmd->pdu_len > FIO_SERVER_MAX_FRAGMENT_PDU) {
log_err("fio: command payload too large: %u\n", cmd->pdu_len);
return 1;
}
do {
this_len = size;
- if (this_len > FIO_SERVER_MAX_PDU)
- this_len = FIO_SERVER_MAX_PDU;
+ if (this_len > FIO_SERVER_MAX_FRAGMENT_PDU)
+ this_len = FIO_SERVER_MAX_FRAGMENT_PDU;
if (!cmd || cur_len < sizeof(*cmd) + this_len) {
if (cmd)
return fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_QUIT, 0, NULL);
}
-static int handle_job_cmd(struct fio_net_cmd *cmd)
+static int handle_run_cmd(struct fio_net_cmd *cmd)
{
- char *buf = (char *) cmd->payload;
- struct cmd_start_pdu spdu;
struct cmd_end_pdu epdu;
int ret;
- if (parse_jobs_ini(buf, 1, 0)) {
- fio_server_send_quit_cmd();
- return -1;
- }
-
- spdu.jobs = cpu_to_le32(thread_number);
- fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), 0);
-
ret = fio_backend();
epdu.error = ret;
return ret;
}
+static int handle_job_cmd(struct fio_net_cmd *cmd)
+{
+ char *buf = (char *) cmd->payload;
+ struct cmd_start_pdu spdu;
+
+ if (parse_jobs_ini(buf, 1, 0)) {
+ fio_server_send_quit_cmd();
+ return -1;
+ }
+
+ spdu.jobs = cpu_to_le32(thread_number);
+ fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), 0);
+ return 0;
+}
+
static int handle_jobline_cmd(struct fio_net_cmd *cmd)
{
void *pdu = cmd->payload;
struct cmd_single_line_pdu *cslp;
struct cmd_line_pdu *clp;
unsigned long offset;
+ struct cmd_start_pdu spdu;
char **argv;
- int ret, i;
+ int i;
clp = pdu;
clp->lines = le16_to_cpu(clp->lines);
free(argv);
- fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_START, 0, NULL);
-
- ret = fio_backend();
- fio_server_send_quit_cmd();
- reset_fio_state();
- first_cmd_check = 0;
- return ret;
+ spdu.jobs = cpu_to_le32(thread_number);
+ fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), 0);
+ return 0;
}
static int handle_probe_cmd(struct fio_net_cmd *cmd)
case FIO_NET_CMD_SEND_ETA:
ret = handle_send_eta_cmd(cmd);
break;
+ case FIO_NET_CMD_RUN:
+ ret = handle_run_cmd(cmd);
+ break;
default:
log_err("fio: unknown opcode: %s\n",fio_server_op(cmd->opcode));
ret = 1;
};
enum {
- FIO_SERVER_VER = 9,
+ FIO_SERVER_VER = 10,
- FIO_SERVER_MAX_PDU = 1024,
+ FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_NET_CMD_QUIT = 1,
FIO_NET_CMD_EXIT = 2,
FIO_NET_CMD_DU = 13,
FIO_NET_CMD_SERVER_START = 14,
FIO_NET_CMD_ADD_JOB = 15,
- FIO_NET_CMD_NR = 16,
+ FIO_NET_CMD_RUN = 16,
+ FIO_NET_CMD_NR = 17,
FIO_NET_CMD_F_MORE = 1UL << 0,