Beispiel #1
0
/** Finalise a marshalled message.
 *
 * Depending on the number of values packed, change the type of message, and
 * write the actual size in the right location of the header, in network byte
 * order.
 *
 * \param mbuf MBuffer where marshalled data is
 * \return 1
 * \see marshal_init, marshal_measurements, marshal_values
 */
int
marshal_finalize(MBuffer*  mbuf)
{
  uint8_t* buf = mbuf_message (mbuf);
  OmlBinMsgType type = marshal_get_msgtype (mbuf);
  size_t len = mbuf_message_length (mbuf);

  if (len > UINT32_MAX) {
    logwarn("Message length %d longer than maximum packet length (%d); "
            "packet will be truncated\n",
            len, UINT32_MAX);
    len = UINT32_MAX;
  }

  if (type == OMB_DATA_P && len > UINT16_MAX) {
    /*
     * We assumed a short packet, but there is too much data, so we
     * have to shift the whole buffer down by 2 bytes and convert to a
     * long packet.
     */
    uint8_t s[2] = {0};
    /* Put some padding in the buffer to make sure it has room, and maintains its invariants */
    mbuf_write (mbuf, s, sizeof (s));
    memmove (&buf[PACKET_HEADER_SIZE+2], &buf[PACKET_HEADER_SIZE],
             len - PACKET_HEADER_SIZE);
    len += 2;
    buf[2] = type = OMB_LDATA_P;
  }


  switch (type) {
  case OMB_DATA_P:
    len -= PACKET_HEADER_SIZE; // Data length minus header
    uint16_t nlen16 = htons (len);
    memcpy (&buf[3], &nlen16, sizeof (nlen16));
    break;
  case OMB_LDATA_P:
    len -= PACKET_HEADER_SIZE + 2; // Data length minus header
    uint32_t nlen32 = htonl (len); // pure data length
    memcpy (&buf[3], &nlen32, sizeof (nlen32));
    break;
  }

  return 1;
}
Beispiel #2
0
/** Marshal the array of values into an MBuffer.
 *
 * Metadata of the measurement stream should already have been written
 * with marshal_measurements(). Each element of values is written with
 * marshal_value().  Finally, the number of elements in the message is
 * updated in its header, by incrementing the relevant field
 * (depending on its OmlBinMsgType) by value_count.
 *
 * If the returned number is negative, marshalling didn't finish as
 * the provided buffer was short of the number of bytes returned (when
 * multiplied by -1); the entire message has been reset (by
 * marshal_value()), and marshalling should restart with
 * marshal_init(), after the MBuffer has been adequately resized or
 * repacked.
 *
 * Once all data has been marshalled, marshal_finalize() should be
 * called to finish preparing the message.
 *
 * \param mbuf MBuffer to write marshalled data to
 * \param values array of OmlValue of length value_count
 * \param value_count length  the values array
 * \return 1 on success, or -1 otherwise (marshalling should then restart from marshal_init())
 * \see marshal_init, marshal_measurements, marshal_value, marshal_finalize, mbuf_repack_message, mbuf_repack_message2, mbuf_resize
 */
int marshal_values(MBuffer* mbuf, OmlValue* values, int value_count)
{
  OmlValue* val = values;
  int i;

  for (i = 0; i < value_count; i++, val++) {
    if(!marshal_value(mbuf, oml_value_get_type(val), oml_value_get_value(val)))
      return -1;
  }

  uint8_t* buf = mbuf_message (mbuf);
  OmlBinMsgType type = marshal_get_msgtype (mbuf);
  switch (type) {
  case OMB_DATA_P: buf[5] += value_count; break;
  case OMB_LDATA_P: buf[7] += value_count; break;
  }
  return 1;
}
Beispiel #3
0
/** Function called after all items in a tuple have been sent
 * \see oml_writer_row_end
 *
 * This releases the lock on the BufferedWriter.
 *
 * \see BufferedWriter, bw_unlock_buf, marshal_finalize
 */
static int
owb_row_end(OmlWriter* writer, OmlMStream* ms) {
  (void)ms;
  OmlBinWriter* self = (OmlBinWriter*)writer;
  MBuffer* mbuf;
  if ((mbuf = self->mbuf) == NULL) {
    return 0; /* previous use of mbuf failed */
  }

  marshal_finalize(self->mbuf);
  if (marshal_get_msgtype (self->mbuf) == OMB_LDATA_P) {
    self->msgtype = OMB_LDATA_P; // Generate long packets from now on.
  }

  if (0 == ms->index) {
    /* This is schema0, also push the data into the meta_buf
     * to be replayed after a disconnection.
     *
     * At the moment, the oml_outs_write_f takes header information as a
     * whole, but does not push more once it has sent the initial block. Its
     * two last parameters are only used to resend the entirety of the headers
     * when a disconnection does occur, nothing before.
     *
     * We therefore send the extra piece of data the normal way, but also
     * record it, separately, in the meta_buf
     *
     * XXX: This logic should be in higher layer levels, but given the current
     * implementation, with some of it already spread down into the
     * OmlOutStream (oml_outs_write_f), this require a much bigger refactoring.
     * It is also duplicated with the OmlTextWriter (see #1101).
     */
    _bw_push_meta(self->bufferedWriter,
        mbuf_message(self->mbuf), mbuf_message_length(self->mbuf));
  }

  mbuf_begin_write(mbuf);

  self->mbuf = NULL;
  bw_unlock_buf(self->bufferedWriter);
  return 1;
}