+int fio_send_iolog(struct thread_data *td, struct io_log *log, const char *name)
+{
+ struct cmd_iolog_pdu pdu;
+ struct fio_net_cmd cmd;
+ z_stream stream;
+ void *out_pdu;
+ int i;
+
+ pdu.nr_samples = __cpu_to_le32(log->nr_samples);
+ pdu.log_type = cpu_to_le32(log->log_type);
+ strcpy((char *) pdu.name, name);
+
+ for (i = 0; i < log->nr_samples; i++) {
+ struct io_sample *s = &log->log[i];
+
+ s->time = cpu_to_le64(s->time);
+ s->val = cpu_to_le64(s->val);
+ s->ddir = cpu_to_le32(s->ddir);
+ s->bs = cpu_to_le32(s->bs);
+ }
+
+ /*
+ * Dirty - since the log is potentially huge, compress it into
+ * FIO_SERVER_MAX_FRAGMENT_PDU chunks and let the receiving
+ * side defragment it.
+ */
+ out_pdu = malloc(FIO_SERVER_MAX_FRAGMENT_PDU);
+
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ if (deflateInit(&stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
+ free(out_pdu);
+ return 1;
+ }
+
+ /*
+ * Send header first, it's not compressed.
+ */
+ __fio_init_net_cmd(&cmd, FIO_NET_CMD_IOLOG, sizeof(pdu), 0);
+ cmd.flags = __cpu_to_le32(FIO_NET_CMD_F_MORE);
+ fio_net_cmd_crc_pdu(&cmd, &pdu);
+ fio_send_data(server_fd, &cmd, sizeof(cmd));
+ fio_send_data(server_fd, &pdu, sizeof(pdu));
+
+ stream.next_in = (void *) log->log;
+ stream.avail_in = log->nr_samples * sizeof(struct io_sample);
+
+ do {
+ unsigned int this_len;
+
+ stream.avail_out = FIO_SERVER_MAX_FRAGMENT_PDU;
+ stream.next_out = out_pdu;
+ assert(deflate(&stream, Z_FINISH) == Z_OK);
+
+ this_len = FIO_SERVER_MAX_FRAGMENT_PDU - stream.avail_out;
+
+ __fio_init_net_cmd(&cmd, FIO_NET_CMD_IOLOG, this_len, 0);
+
+ if (stream.avail_in)
+ cmd.flags = __cpu_to_le32(FIO_NET_CMD_F_MORE);
+
+ fio_net_cmd_crc_pdu(&cmd, out_pdu);
+
+ fio_send_data(server_fd, &cmd, sizeof(cmd));
+ fio_send_data(server_fd, out_pdu, this_len);
+ } while (stream.avail_in);
+
+ free(out_pdu);
+ deflateEnd(&stream);
+ return 0;
+}
+