void ANetworkController::SendData() {
	if (!TcpSocket) {
		return;
	}

	// Clear the data if there is anything on the stream
	TryReceiveData();

	AVehiclestats* Stats = NULL;
	for (TActorIterator<AVehiclestats> ObjIt(GetWorld()); ObjIt; ++ObjIt) {
		Stats = *ObjIt;
		break;
	}
	if (Stats == NULL) {
		return;
	}

	// Send crashlog

	msgpack_sbuffer sbuf;
	msgpack_sbuffer_init(&sbuf);

	msgpack_packer pk;
	msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);


	for (auto Iter = Stats->IncidentLog.CreateConstIterator(); Iter; ++Iter) {
		msgpack_pack_array(&pk, 2);
		msgpack_pack_uint16(&pk, EPacketType::PT_IncidentLog);
		Pack(&pk, *Iter);
	}

	Stats->IncidentLog.Empty();


	// Send the statestics

	msgpack_pack_array(&pk, 2);
	msgpack_pack_uint16(&pk, EPacketType::PT_GetStats);

	msgpack_pack_map(&pk, 6);

	msgpack_pack_str(&pk, 7);
	msgpack_pack_str_body(&pk, "spawned", 7);
	msgpack_pack_uint32(&pk, Stats->GetNumVehiclesSpawned());

	msgpack_pack_str(&pk, 6);
	msgpack_pack_str_body(&pk, "onroad", 6);
	msgpack_pack_uint32(&pk, Stats->GetNumVehiclesOnTheRoad());

	msgpack_pack_str(&pk, 7);
	msgpack_pack_str_body(&pk, "crashed", 7);
	msgpack_pack_uint32(&pk, Stats->GetNumVehiclesCrashed());

	msgpack_pack_str(&pk, 9);
	msgpack_pack_str_body(&pk, "incidents", 9);
	msgpack_pack_uint32(&pk, Stats->GetNumVehiclesIncidents());

	TArray<float> Throughputs;

	for (TActorIterator<AMeasurementGate> ObjIt(GetWorld()); ObjIt; ++ObjIt) {
		AMeasurementGate* Gate = *ObjIt;
		Throughputs.Add(Gate->GetThroughput(0));
		Throughputs.Add(Gate->GetThroughput(1));
	}

	msgpack_pack_str(&pk, 11);
	msgpack_pack_str_body(&pk, "throughputs", 11);
	msgpack_pack_array(&pk, Throughputs.Num());
	for (auto Iter = Throughputs.CreateConstIterator(); Iter; ++Iter) {
		msgpack_pack_float(&pk, *Iter);
	}

	msgpack_pack_str(&pk, 4);
	msgpack_pack_str_body(&pk, "time", 4);
	msgpack_pack_float(&pk, Stats->GetTime());

	int32 BytesLeft = sbuf.size;
	while (BytesLeft > 0) {
		int32 Index = sbuf.size - BytesLeft;
		int32 BytesSent;
		TcpSocket->Send((uint8*)sbuf.data + Index, BytesLeft, BytesSent);
		BytesLeft = BytesLeft - BytesSent;
		if (BytesSent == -1) {
			break;
		}
	}

	msgpack_sbuffer_destroy(&sbuf);
}
示例#2
0
/* Init serial input */
int in_serial_init(struct flb_input_instance *in,
                   struct flb_config *config, void *data)
{
    int fd;
    int ret;
    int br;
    struct flb_in_serial_config *ctx;
    (void) data;

    ctx = flb_calloc(1, sizeof(struct flb_in_serial_config));
    if (!ctx) {
        perror("calloc");
        return -1;
    }
    ctx->format = FLB_SERIAL_FORMAT_NONE;

    if (!serial_config_read(ctx, in)) {
        return -1;
    }

    /* Initialize JSON pack state */
    if (ctx->format == FLB_SERIAL_FORMAT_JSON) {
        flb_pack_state_init(&ctx->pack_state);
    }

    /* set context */
    flb_input_set_context(in, ctx);

    /* initialize MessagePack buffers */
    msgpack_sbuffer_init(&ctx->mp_sbuf);
    msgpack_packer_init(&ctx->mp_pck, &ctx->mp_sbuf, msgpack_sbuffer_write);

    /* open device */
    fd = open(ctx->file, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd == -1) {
        perror("open");
        flb_error("[in_serial] Could not open serial port device");
        flb_free(ctx);
        return -1;
    }
    ctx->fd = fd;

    /* Store original settings */
    tcgetattr(fd, &ctx->tio_orig);

    /* Reset for new... */
    memset(&ctx->tio, 0, sizeof(ctx->tio));
    tcgetattr(fd, &ctx->tio);

    br = atoi(ctx->bitrate);
    cfsetospeed(&ctx->tio, (speed_t) flb_serial_speed(br));
    cfsetispeed(&ctx->tio, (speed_t) flb_serial_speed(br));

    /* Settings */
    ctx->tio.c_cflag     &=  ~PARENB;        /* 8N1 */
    ctx->tio.c_cflag     &=  ~CSTOPB;
    ctx->tio.c_cflag     &=  ~CSIZE;
    ctx->tio.c_cflag     |=  CS8;
    ctx->tio.c_cflag     &=  ~CRTSCTS;       /* No flow control */
    ctx->tio.c_cc[VMIN]   =  ctx->min_bytes; /* Min number of bytes to read  */
    ctx->tio.c_cflag     |=  CREAD | CLOCAL; /* Enable READ & ign ctrl lines */

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &ctx->tio);

#if __linux__
    /* Set our collector based on a file descriptor event */
    ret = flb_input_set_collector_event(in,
                                        in_serial_collect,
                                        ctx->fd,
                                        config);
#else
    /* Set our collector based on a timer event */
    ret = flb_input_set_collector_time(in,
                                       in_serial_collect,
                                       IN_SERIAL_COLLECT_SEC,
                                       IN_SERIAL_COLLECT_NSEC,
                                       config);
#endif
    return ret;
}
示例#3
0
/* It parse a JSON string and convert it to MessagePack format */
char *flb_pack_json(char *js, size_t len, int *size)
{
    int i;
    int flen;
    int arr_size;
    char *p;
    char *buf;
    jsmntok_t *t;
    jsmntok_t *tokens;
    msgpack_packer pck;
    msgpack_sbuffer sbuf;

    if (!js) {
        return NULL;
    }

    tokens = json_tokenise(js, len, &arr_size);
    if (!tokens) {
        return NULL;
    }

    flb_debug("JSON to pack: '%s'", js);

    /* initialize buffers */
    msgpack_sbuffer_init(&sbuf);
    msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write);

    for (i = 0; i < arr_size ; i++) {
        t = &tokens[i];
        if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) {
            break;
        }
        flen = (t->end - t->start);

        switch (t->type) {
        case JSMN_OBJECT:
            flb_debug("json_pack: token=%i is OBJECT (size=%i)", i, t->size);
            msgpack_pack_map(&pck, t->size);
            break;
        case JSMN_ARRAY:
            flb_debug("json_pack: token=%i is ARRAY (size=%i)", i, t->size);
            msgpack_pack_array(&pck, t->size);
            break;
        case JSMN_STRING:
            flb_debug("json_pack: token=%i is STRING (len=%i)\n", i, flen);
            msgpack_pack_bin(&pck, flen);
            msgpack_pack_bin_body(&pck, js + t->start, flen);
            break;
        case JSMN_PRIMITIVE:
            p = js + t->start;
            if (strncmp(p, "false", 5) == 0) {
                flb_debug("json_pack: token=%i is FALSE", i);
                msgpack_pack_false(&pck);
            }
            else if (strncmp(p, "true", 4) == 0) {
                flb_debug("json_pack: token=%i is TRUE", i);
                msgpack_pack_true(&pck);
            }
            else if (strncmp(p, "null", 4) == 0) {
                flb_debug("json_pack: token=%i is NULL", i);
                msgpack_pack_nil(&pck);
            }
            else {
                flb_debug("json_pack: token=%i is INT64", i);
                msgpack_pack_int64(&pck, atol(p));
            }
            break;
        }
    }

    /* dump data back to a new buffer */
    *size = sbuf.size;
    buf = malloc(sbuf.size);
    memcpy(buf, sbuf.data, sbuf.size);
    msgpack_sbuffer_destroy(&sbuf);

    free(tokens);
    return buf;
}
示例#4
0
/* Init xbee input */
int in_xbee_init(struct flb_config *config, void *data)
{
    int ret;
    struct stat dev_st;
    struct xbee *xbee;
    struct xbee_conAddress address;
    struct flb_in_xbee_config *ctx;
    struct xbee_conSettings settings;
    (void) data;

    /* Prepare the configuration context */
    ctx = calloc(1, sizeof(struct flb_in_xbee_config));
    if (!ctx) {
        perror("calloc");
        return -1;
    }

    if (!config->file) {
        flb_utils_error_c("XBee input plugin needs configuration file");
        return -1;
    }

    xbee_config_read(ctx, config->file);

    /* initialize MessagePack buffers */
    msgpack_sbuffer_init(&ctx->mp_sbuf);
    msgpack_packer_init(&ctx->mp_pck, &ctx->mp_sbuf, msgpack_sbuffer_write);

    flb_info("XBee device=%s, baudrate=%i", ctx->file, ctx->baudrate);

    ret = stat(ctx->file, &dev_st);
    if (ret < 0) {
        printf("Error: could not open %s device\n", ctx->file);
        free(ctx->file);
        exit(EXIT_FAILURE);
    }

    if (!S_ISCHR(dev_st.st_mode)) {
        printf("Error: invalid device %s \n", ctx->file);
        free(ctx->file);
        exit(EXIT_FAILURE);
    }

    if (access(ctx->file, R_OK | W_OK) == -1) {
        printf("Error: cannot open the device %s (permission denied ?)\n",
               ctx->file);
        free(ctx->file);
        exit(EXIT_FAILURE);
    }

    ctx->config = config;
    pthread_mutex_init(&ctx->mtx_mp, NULL);
    ctx->buffer_len = 0;

    /* Init library */
    xbee_init();

    ret = xbee_setup(&xbee, ctx->xbeeMode, ctx->file, ctx->baudrate);
    if (ret != XBEE_ENONE) {
        flb_utils_error_c("xbee_setup");
        return ret;
    }

    /* 000000000000FFFF: broadcast address */
    memset(&address, 0, sizeof(address));
    address.addr64_enabled = 1;
    address.addr64[0] = 0x00;
    address.addr64[1] = 0x00;
    address.addr64[2] = 0x00;
    address.addr64[3] = 0x00;
    address.addr64[4] = 0x00;
    address.addr64[5] = 0x00;
    address.addr64[6] = 0xFF;
    address.addr64[7] = 0xFF;

    if (ctx->xbeeLogLevel >= 0)
        xbee_logLevelSet(xbee, ctx->xbeeLogLevel);

    /* Prepare a connection with the peer XBee */

    if ((ret = xbee_conNew(xbee, &ctx->con_data, "Data", &address)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret));
        return ret;
    }

    xbee_conSettings(ctx->con_data, NULL, &settings);
    settings.disableAck = ctx->xbeeDisableAck ? 1 : 0;
    settings.catchAll = ctx->xbeeCatchAll ? 1 : 0;
    xbee_conSettings(ctx->con_data, &settings, NULL);

    if ((ret = xbee_conDataSet(ctx->con_data, ctx, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conDataSet() returned: %d", ret);
        return ret;
    }

    if ((ret = xbee_conCallbackSet(ctx->con_data, in_xbee_cb, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret);
        return ret;
    }


    if ((ret = xbee_conNew(xbee, &ctx->con_io, "I/O", &address)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret));
        return ret;
    }

    xbee_conSettings(ctx->con_io, NULL, &settings);
    settings.disableAck = ctx->xbeeDisableAck ? 1 : 0;
    settings.catchAll = ctx->xbeeCatchAll ? 1 : 0;
    xbee_conSettings(ctx->con_io, &settings, NULL);

    if ((ret = xbee_conDataSet(ctx->con_io, ctx, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conDataSet() returned: %d", ret);
        return ret;
    }

    if ((ret = xbee_conCallbackSet(ctx->con_io, in_xbee_iosampling_cb, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret);
        return ret;
    }

    /* Set the context */
    ret = flb_input_set_context("xbee", ctx, config);
    if (ret == -1) {
        flb_utils_error_c("Could not set configuration for xbee input plugin");
    }

    return 0;
}
示例#5
0
/* Init serial input */
int in_serial_init(struct flb_config *config, void *data)
{
    int fd;
    int ret;
    struct flb_in_serial_config *ctx;
    (void) data;

    ctx = calloc(1, sizeof(struct flb_in_serial_config));
    if (!ctx) {
        perror("calloc");
        return -1;
    }

    if (!config->file) {
        flb_utils_error_c("serial input plugin needs configuration file");
        free(ctx);
        return -1;
    }

    serial_config_read(ctx, config->file);

    /* set context */
    ret = flb_input_set_context("serial", ctx, config);
    if (ret == -1) {
        flb_utils_error_c("Could not set configuration for"
                "serial input plugin");
    }

    if (ret == -1) {
        flb_utils_error_c("Could not set collector for serial input plugin");
    }

    /* initialize MessagePack buffers */
    msgpack_sbuffer_init(&ctx->mp_sbuf);
    msgpack_packer_init(&ctx->mp_pck, &ctx->mp_sbuf, msgpack_sbuffer_write);

    memset(&ctx->tio, 0, sizeof(ctx->tio));
    ctx->tio.c_cflag = ctx->tio.c_ispeed = ctx->tio.c_ospeed = atoi(ctx->bitrate);
    ctx->tio.c_cflag |= CRTSCTS | CS8 | CLOCAL | CREAD;
    ctx->tio.c_iflag = IGNPAR | IGNCR;
    ctx->tio.c_oflag = 0;
    ctx->tio.c_lflag = ICANON;

    /* open device */
    fd = open(ctx->file, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd == -1) {
        perror("open");
        flb_utils_error_c("Could not open serial port device");
    }
    ctx->fd = fd;

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &ctx->tio);

#if __linux__
    /* Set our collector based on a file descriptor event */
    ret = flb_input_set_collector_event("serial",
                                        in_serial_collect,
                                        ctx->fd,
                                        config);
#else
    /* Set our collector based on a timer event */
    ret = flb_input_set_collector_time("serial",
                                       in_serial_collect,
                                       IN_SERIAL_COLLECT_SEC,
                                       IN_SERIAL_COLLECT_NSEC,
                                       config);
#endif

    return ret;
}
示例#6
0
int cb_fluentd_flush(void *data, size_t bytes, void *out_context,
                     struct flb_config *config)
{
    int fd;
    int ret = -1;
    int maps = 0;
    size_t total;
    char *buf = NULL;
    msgpack_packer   mp_pck;
    msgpack_sbuffer  mp_sbuf;
    msgpack_unpacked mp_umsg;
    size_t mp_upos = 0;
    (void) out_context;
    (void) config;

    /*
     * The incoming data comes in Fluent Bit format an array of objects, as we
     * aim to send this information to Fluentd through it in_forward plugin, we
     * need to transform the data. The Fluentd in_forward plugin allows one
     * of the following formats:
     *
     *   1. [tag, time, record]
     *
     *    or
     *
     *   2. [tag, [[time,record], [time,record], ...]]
     *
     *   we use the format #2
     */

    /* Initialize packager */
    msgpack_sbuffer_init(&mp_sbuf);
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);

    /*
     * Count the number of map entries
     *
     * FIXME: Fluent Bit should expose the number of maps into the
     * data, so we avoid this silly counting.
     */
    msgpack_unpacked_init(&mp_umsg);
    while (msgpack_unpack_next(&mp_umsg, data, bytes, &mp_upos)) {
        maps++;
    }
    msgpack_unpacked_destroy(&mp_umsg);

    /* Output: root array */
    msgpack_pack_array(&mp_pck, 2);
    msgpack_pack_bin(&mp_pck, sizeof(FLB_CONFIG_DEFAULT_TAG) - 1);
    msgpack_pack_bin_body(&mp_pck,
                          FLB_CONFIG_DEFAULT_TAG,
                          sizeof(FLB_CONFIG_DEFAULT_TAG) - 1);
    msgpack_pack_array(&mp_pck, maps);

    /* Allocate a new buffer to merge data */
    total = bytes + mp_sbuf.size;
    buf = malloc(total);
    if (!buf) {
        perror("malloc");
        return -1;
    }

    memcpy(buf, mp_sbuf.data, mp_sbuf.size);
    memcpy(buf + mp_sbuf.size, data, bytes);
    msgpack_sbuffer_destroy(&mp_sbuf);

    fd = flb_net_tcp_connect(out_fluentd_plugin.host,
                             out_fluentd_plugin.port);
    if (fd <= 0) {
        free(buf);
        return -1;
    }


    /* FIXME: plain TCP write */
    ret = write(fd, buf, total);
    close(fd);
    free(buf);

    return ret;
}
示例#7
0
void tmate_encoder_init(struct tmate_encoder *encoder)
{
	encoder->buffer = evbuffer_new();
	msgpack_packer_init(&encoder->pk, encoder, &msgpack_write);
}
示例#8
0
void *in_kmsg_flush(void *in_context, int *size)
{
    int i;
    char *buf;
    msgpack_packer pck;
    msgpack_sbuffer sbuf;
    struct kmsg_line *entry;
    struct flb_in_kmsg_config *ctx = in_context;

    /* initialize buffers */
    msgpack_sbuffer_init(&sbuf);
    msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write);

    msgpack_pack_array(&pck, 2);

    /* Tag */
    msgpack_pack_raw(&pck, ctx->tag_len);
    msgpack_pack_raw_body(&pck, ctx->tag, ctx->tag_len);

    /* Primary Array: ['TAG', [ */
    msgpack_pack_array(&pck, ctx->buffer_id);

    /* Pack each data_array entry */
    for (i = 0; i < ctx->buffer_id; i++) {
        entry = &ctx->buffer[i];

        uint64_t t = ctx->boot_time.tv_sec + entry->tv.tv_sec;

        msgpack_pack_array(&pck, 2);
        msgpack_pack_uint64(&pck, t);

        msgpack_pack_map(&pck, 3);

        /* Priority */
        msgpack_pack_raw(&pck, 8);
        msgpack_pack_raw_body(&pck, "priority", 8);
        msgpack_pack_char(&pck, entry->priority);

        /* Sequence */
        msgpack_pack_raw(&pck, 8);
        msgpack_pack_raw_body(&pck, "sequence", 8);
        msgpack_pack_uint64(&pck, entry->sequence);

        /* Time: FIXME */

        /* Data message (line) */
        msgpack_pack_raw(&pck, 3);
        msgpack_pack_raw_body(&pck, "msg", 3);
        msgpack_pack_raw(&pck, entry->line_len);
        msgpack_pack_raw_body(&pck, entry->line, entry->line_len);
    }

    *size = sbuf.size;
    buf = malloc(sbuf.size);
    memcpy(buf, sbuf.data, sbuf.size);
    msgpack_sbuffer_destroy(&sbuf);

    ctx->buffer_id = 0;

    return buf;
}
示例#9
0
static grn_rc
grn_ctx_impl_init(grn_ctx *ctx)
{
  grn_io_mapinfo mi;
  if (!(ctx->impl = grn_io_anon_map(ctx, &mi, IMPL_SIZE))) {
    return ctx->rc;
  }
  grn_alloc_init_ctx_impl(ctx);
  ctx->impl->encoding = ctx->encoding;
  ctx->impl->lifoseg = -1;
  ctx->impl->currseg = -1;
  CRITICAL_SECTION_INIT(ctx->impl->lock);
  if (!(ctx->impl->values = grn_array_create(ctx, NULL, sizeof(grn_db_obj *),
                                             GRN_ARRAY_TINY))) {
    CRITICAL_SECTION_FIN(ctx->impl->lock);
    grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
    ctx->impl = NULL;
    return ctx->rc;
  }
  if (!(ctx->impl->temporary_columns = grn_pat_create(ctx, NULL,
                                                      GRN_TABLE_MAX_KEY_SIZE,
                                                      sizeof(grn_obj *),
                                                      0))) {
    grn_array_close(ctx, ctx->impl->values);
    CRITICAL_SECTION_FIN(ctx->impl->lock);
    grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
    ctx->impl = NULL;
    return ctx->rc;
  }
  if (!(ctx->impl->ios = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE,
                                         sizeof(grn_io *),
                                         GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) {
    grn_array_close(ctx, ctx->impl->values);
    grn_pat_close(ctx, ctx->impl->temporary_columns);
    CRITICAL_SECTION_FIN(ctx->impl->lock);
    grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
    ctx->impl = NULL;
    return ctx->rc;
  }
  ctx->impl->db = NULL;

  ctx->impl->expr_vars = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_obj *), 0);
  ctx->impl->stack_curr = 0;
  ctx->impl->curr_expr = NULL;
  ctx->impl->qe_next = NULL;
  GRN_TEXT_INIT(&ctx->impl->current_request_id, 0);
  ctx->impl->current_request_timer_id = NULL;
  ctx->impl->parser = NULL;

  GRN_TEXT_INIT(&ctx->impl->output.names, GRN_OBJ_VECTOR);
  GRN_UINT32_INIT(&ctx->impl->output.levels, GRN_OBJ_VECTOR);

  if (ctx == &grn_gctx) {
    ctx->impl->command_version = GRN_COMMAND_VERSION_STABLE;
  } else {
    ctx->impl->command_version = grn_get_default_command_version();
  }

  if (ctx == &grn_gctx) {
    ctx->impl->match_escalation_threshold =
      GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD;
  } else {
    ctx->impl->match_escalation_threshold =
      grn_get_default_match_escalation_threshold();
  }

  ctx->impl->finalizer = NULL;

  ctx->impl->com = NULL;
  ctx->impl->output.buf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT);
  ctx->impl->output.func = NULL;
  ctx->impl->output.data.ptr = NULL;
#ifdef GRN_WITH_MESSAGE_PACK
  msgpack_packer_init(&ctx->impl->output.msgpacker,
                      ctx, grn_msgpack_buffer_write);
#endif
  ctx->impl->tv.tv_sec = 0;
  ctx->impl->tv.tv_nsec = 0;
  ctx->impl->edge = NULL;
  grn_loader_init(&ctx->impl->loader);
  ctx->impl->plugin_path = NULL;

  GRN_TEXT_INIT(&ctx->impl->query_log_buf, 0);

  ctx->impl->previous_errbuf[0] = '\0';
  ctx->impl->n_same_error_messages = 0;

  grn_ctx_impl_mrb_init(ctx);

  return ctx->rc;
}
示例#10
0
文件: td.c 项目: pandax381/fluent-bit
/*
 * Convert the internal Fluent Bit data representation to the required
 * one by Treasure Data cloud service.
 *
 * This function returns a new msgpack buffer and store the bytes length
 * in the out_size variable.
 */
static char *td_format(void *data, size_t bytes, int *out_size)
{
    int i;
    int ret;
    int n_size;
    size_t off = 0;
    time_t atime;
    char *buf;
    struct msgpack_sbuffer mp_sbuf;
    struct msgpack_packer mp_pck;
    msgpack_unpacked result;
    msgpack_object root;
    msgpack_object map;
    msgpack_sbuffer *sbuf;

    /* Initialize contexts for new output */
    msgpack_sbuffer_init(&mp_sbuf);
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);

    /* Iterate the original buffer and perform adjustments */
    msgpack_unpacked_init(&result);

    /* Perform some format validation */
    ret = msgpack_unpack_next(&result, data, bytes, &off);
    if (!ret) {
        return NULL;
    }

    /* We 'should' get an array */
    if (result.data.type != MSGPACK_OBJECT_ARRAY) {
        /*
         * If we got a different format, we assume the caller knows what he is
         * doing, we just duplicate the content in a new buffer and cleanup.
         */
        buf = malloc(bytes);
        if (!buf) {
            return NULL;
        }

        memcpy(buf, data, bytes);
        *out_size = bytes;
        return buf;
    }

    root = result.data;
    if (root.via.array.size == 0) {
        return NULL;
    }

    off = 0;
    msgpack_unpacked_destroy(&result);
    msgpack_unpacked_init(&result);
    while (msgpack_unpack_next(&result, data, bytes, &off)) {
        if (result.data.type != MSGPACK_OBJECT_ARRAY) {
            continue;
        }

        /* Each array must have two entries: time and record */
        root = result.data;
        if (root.via.array.size != 2) {
            continue;
        }

        atime = root.via.array.ptr[0].via.u64;
        map   = root.via.array.ptr[1];

        n_size = map.via.map.size + 1;
        msgpack_pack_map(&mp_pck, n_size);
        msgpack_pack_bin(&mp_pck, 4);
        msgpack_pack_bin_body(&mp_pck, "time", 4);
        msgpack_pack_int32(&mp_pck, atime);

        for (i = 0; i < n_size - 1; i++) {
            msgpack_pack_object(&mp_pck, map.via.map.ptr[i].key);
            msgpack_pack_object(&mp_pck, map.via.map.ptr[i].val);
        }
    }
    msgpack_unpacked_destroy(&result);

    /* Create new buffer */
    sbuf = &mp_sbuf;
    *out_size = sbuf->size;
    buf = malloc(sbuf->size);
    if (!buf) {
        return NULL;
    }

    /* set a new buffer and re-initialize our MessagePack context */
    memcpy(buf, sbuf->data, sbuf->size);
    msgpack_sbuffer_destroy(&mp_sbuf);

    return buf;
}