gfio: allow different tooltips for a button depending on state
[fio.git] / client.c
index 6371c2be8d9e05592864ae8168af0571f470fe2f..6230a66e032258f338c55fa8c05e72bf4d6ad833 100644 (file)
--- a/client.c
+++ b/client.c
@@ -14,6 +14,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <signal.h>
+#include <zlib.h>
 
 #include "fio.h"
 #include "client.h"
@@ -627,10 +628,11 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src)
 {
        int i, j;
 
-       dst->error      = le32_to_cpu(src->error);
-       dst->groupid    = le32_to_cpu(src->groupid);
-       dst->pid        = le32_to_cpu(src->pid);
-       dst->members    = le32_to_cpu(src->members);
+       dst->error              = le32_to_cpu(src->error);
+       dst->thread_number      = le32_to_cpu(src->thread_number);
+       dst->groupid            = le32_to_cpu(src->groupid);
+       dst->pid                = le32_to_cpu(src->pid);
+       dst->members            = le32_to_cpu(src->members);
 
        for (i = 0; i < 2; i++) {
                convert_io_stat(&dst->clat_stat[i], &src->clat_stat[i]);
@@ -718,6 +720,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
        sum_group_stats(&client_gs, &p->rs);
 
        client_ts.members++;
+       client_ts.thread_number = p->ts.thread_number;
        client_ts.groupid = p->ts.groupid;
 
        if (++sum_stat_nr == sum_stat_clients) {
@@ -950,6 +953,83 @@ static void convert_text(struct fio_net_cmd *cmd)
        pdu->log_usec   = le64_to_cpu(pdu->log_usec);
 }
 
+/*
+ * This has been compressed on the server side, since it can be big.
+ * Uncompress here.
+ */
+static struct cmd_iolog_pdu *convert_iolog(struct fio_net_cmd *cmd)
+{
+       struct cmd_iolog_pdu *pdu = (struct cmd_iolog_pdu *) cmd->payload;
+       struct cmd_iolog_pdu *ret;
+       uint32_t nr_samples;
+       unsigned long total;
+       z_stream stream;
+       void *p;
+       int i;
+
+       stream.zalloc = Z_NULL;
+       stream.zfree = Z_NULL;
+       stream.opaque = Z_NULL;
+       stream.avail_in = 0;
+       stream.next_in = Z_NULL;
+
+       if (inflateInit(&stream) != Z_OK)
+               return NULL;
+
+       /*
+        * Get header first, it's not compressed
+        */
+       nr_samples = le32_to_cpu(pdu->nr_samples);
+
+       total = nr_samples * sizeof(struct io_sample);
+       ret = malloc(total + sizeof(*pdu));
+       ret->thread_number = le32_to_cpu(pdu->thread_number);
+       ret->nr_samples = nr_samples;
+       ret->log_type = le32_to_cpu(pdu->log_type);
+       strcpy((char *) ret->name, (char *) pdu->name);
+
+       p = (void *) ret + sizeof(*pdu);
+
+       stream.avail_in = cmd->pdu_len - sizeof(*pdu);
+       stream.next_in = (void *) pdu + sizeof(*pdu);
+       while (stream.avail_in) {
+               unsigned int this_chunk = 65536;
+               unsigned int this_len;
+               int err;
+
+               if (this_chunk > total)
+                       this_chunk = total;
+
+               stream.avail_out = this_chunk;
+               stream.next_out = p;
+               err = inflate(&stream, Z_NO_FLUSH);
+               /* may be Z_OK, or Z_STREAM_END */
+               if (err < 0) {
+                       log_err("fio: inflate error %d\n", err);
+                       free(ret);
+                       ret = NULL;
+                       goto out;
+               }
+
+               this_len = this_chunk - stream.avail_out;
+               p += this_len;
+               total -= this_len;
+       }
+
+       for (i = 0; i < ret->nr_samples; i++) {
+               struct io_sample *s = &ret->samples[i];
+
+               s->time = le64_to_cpu(s->time);
+               s->val  = le64_to_cpu(s->val);
+               s->ddir = le32_to_cpu(s->ddir);
+               s->bs   = le32_to_cpu(s->bs);
+       }
+
+out:
+       inflateEnd(&stream);
+       return ret;
+}
+
 int fio_handle_client(struct fio_client *client)
 {
        struct client_ops *ops = client->ops;
@@ -1048,6 +1128,15 @@ int fio_handle_client(struct fio_client *client)
                        ops->add_job(client, cmd);
                free(cmd);
                break;
+       case FIO_NET_CMD_IOLOG:
+               if (ops->iolog) {
+                       struct cmd_iolog_pdu *pdu;
+
+                       pdu = convert_iolog(cmd);
+                       ops->iolog(client, pdu);
+               }
+               free(cmd);
+               break;
        default:
                log_err("fio: unknown client op: %s\n", fio_server_op(cmd->opcode));
                free(cmd);