Beispiel #1
0
/** Assign the content of an OmlValueU of the given OmlValueT to an OmlValue.
 *
 * This function copies value, which is assumed to be of the given type (no
 * check can be made), into the OmlValue pointed to by to.  The to object is
 * set to have the given type. If type is a simple numeric type, the copy
 * simply copies the value.
 *
 * If type is OML_STRING_VALUE, then the string contents are copied into new
 * storage in to.  If to was previously set to be a const string, then the
 * is_const flag is cleared and a new block of memory is allocated to store the
 * copy and its terminating null character. If to did not previously have the
 * is_const flag set, and its string pointer was NULL, then a new block of
 * memory is also allocated as well.  If the string pointer was not NULL, then
 * the string is copied into the previously allocated memory block if it is
 * large enough to fit; otherwise the block is freed and a new one allocated
 * large enough to hold the string (and its terminator).
 *
 * Blobs are handled in a similar fashion.
 *
 * If the source pointer is NULL then an error is returned and a warning
 * message is sent to the log.
 *
 * \param to pointer to OmlValue into which the value should be copied
 * \param value pointer to original OmlValueU to copy into to
 * \param type OmlValueT of value
 * \return 0 if successful, -1 otherwise
 * \see oml_value_init, omlc_copy_string, omlc_copy_blob
 */
int
oml_value_set(OmlValue *to, const OmlValueU *value, OmlValueT type)
{
    oml_value_set_type(to, type);
    if (omlc_is_numeric_type (type) ||
            omlc_is_guid_type (type) ||
            omlc_is_bool_type (type)) {
        to->value = *value;
    } else {
        switch (type) {
        case OML_STRING_VALUE:
            if (!omlc_get_string_ptr(*value)) {
                logwarn("Trying to copy OML_STRING_VALUE from a NULL source\n");
                return -1;
            }
            omlc_copy_string(*oml_value_get_value(to), *value);
            break;

        case OML_DATETIME_VALUE:
            if (!omlc_get_string_ptr(*value)) {
                logwarn("Trying to copy OML_DATETIME_VALUE from a NULL source\n");
                return -1;
            }
            omlc_copy_string(*oml_value_get_value(to), *value);
            break;

        case OML_BLOB_VALUE:
            if (!omlc_get_blob_ptr(*value)) {
                logwarn("Trying to copy OML_BLOB_VALUE from a NULL source\n");
                return -1;
            }
            omlc_copy_blob(*oml_value_get_value(to), *value);
            break;

        case OML_VECTOR_DOUBLE_VALUE:
        case OML_VECTOR_INT32_VALUE:
        case OML_VECTOR_UINT32_VALUE:
        case OML_VECTOR_INT64_VALUE:
        case OML_VECTOR_UINT64_VALUE:
        case OML_VECTOR_BOOL_VALUE:
            if (!omlc_get_vector_ptr(*value)) {
                logwarn("Trying to copy OML_VECTOR_*_VALUE from a NULL source\n");
                return -1;
            }
            omlc_copy_vector(*oml_value_get_value(to), *value);
            break;

        default:
            logerror("%s() for type '%d' not implemented'\n", __FUNCTION__, type);
            return -1;
        }
    }
    return 0;
}
Beispiel #2
0
/**
 * \brief write the result inside the file
 * \param writer pointer to writer instance
 * \param values type of sample
 * \param value_count size of above array
 * \return 1 if successful, 0 otherwise
 */
static int
row_cols(OmlWriter* writer, OmlValue* values, int value_count)
{
  OmlTextWriter* self = (OmlTextWriter*)writer;
  MBuffer* mbuf;
  if ((mbuf = self->mbuf) == NULL) return 0; /* previous use of mbuf failed */

  int i;
  OmlValue* v = values;
  for (i = 0; i < value_count; i++, v++) {
    int res;
    switch (oml_value_get_type(v)) {
    case OML_LONG_VALUE: {
      res = mbuf_print(mbuf, "\t%" PRId32, oml_value_clamp_long (v->value.longValue));
      break;
    }
    case OML_INT32_VALUE:  res = mbuf_print(mbuf, "\t%" PRId32,  v->value.int32Value);  break;
    case OML_UINT32_VALUE: res = mbuf_print(mbuf, "\t%" PRIu32,  v->value.uint32Value); break;
    case OML_INT64_VALUE:  res = mbuf_print(mbuf, "\t%" PRId64,  v->value.int64Value);  break;
    case OML_UINT64_VALUE: res = mbuf_print(mbuf, "\t%" PRIu64,  v->value.uint64Value); break;
    case OML_DOUBLE_VALUE: res = mbuf_print(mbuf, "\t%f",  v->value.doubleValue); break;
    case OML_STRING_VALUE: res = mbuf_print(mbuf, "\t%s",  omlc_get_string_ptr(*oml_value_get_value(v))); break;
    case OML_BLOB_VALUE: {
      const unsigned int max_bytes = 6;
      int bytes = v->value.blobValue.length < max_bytes ? v->value.blobValue.length : max_bytes;
      int i = 0;
      res = mbuf_print(mbuf, "blob ");
      for (i = 0; i < bytes; i++) {
        res = mbuf_print(mbuf, "%02x", ((uint8_t*)v->value.blobValue.ptr)[i]);
      }
      res = mbuf_print (mbuf, " ...");
      break;
    }
    default:
      res = -1;
      logerror( "Unsupported value type '%d'\n", oml_value_get_type(v));
      return 0;
    }
    if (res < 0) {
      mbuf_reset_write(mbuf);
      self->mbuf = NULL;
      return 0;
    }
  }
  return 1;
}
Beispiel #3
0
/** Insert value in the PostgreSQL database.
 *
 * \param db Database that links to the PostgreSQL db
 * \param table DbTable to insert data in
 * \param sender_id sender ID
 * \param seq_no sequence number
 * \param time_stamp timestamp of the receiving data
 * \param values OmlValue array to insert
 * \param value_count number of values
 * \return 0 if successful, -1 otherwise
 */
static int
psql_insert(Database* db,
            DbTable*  table,
            int       sender_id,
            int       seq_no,
            double    time_stamp,
            OmlValue* values,
            int       value_count)
{
  PsqlDB* psqldb = (PsqlDB*)db->handle;
  PsqlTable* psqltable = (PsqlTable*)table->handle;
  PGresult* res;
  int i;
  double time_stamp_server;
  const char* insert_stmt = mstring_buf (psqltable->insert_stmt);
  unsigned char *escaped_blob;
  size_t eblob_len=-1;

  char * paramValues[4+value_count];
  for (i=0;i<4+value_count;i++) {
    paramValues[i] = xmalloc(512*sizeof(char));
  }

  int paramLength[4+value_count];
  int paramFormat[4+value_count];

  sprintf(paramValues[0],"%i",sender_id);
  paramLength[0] = 0;
  paramFormat[0] = 0;

  sprintf(paramValues[1],"%i",seq_no);
  paramLength[1] = 0;
  paramFormat[1] = 0;

  sprintf(paramValues[2],"%.8f",time_stamp);
  paramLength[2] = 0;
  paramFormat[2] = 0;

  struct timeval tv;
  gettimeofday(&tv, NULL);
  time_stamp_server = tv.tv_sec - db->start_time + 0.000001 * tv.tv_usec;

  if (tv.tv_sec > psqldb->last_commit) {
    if (reopen_transaction (psqldb) == -1)
      return -1;
    psqldb->last_commit = tv.tv_sec;
  }

  sprintf(paramValues[3],"%.8f",time_stamp_server);
  paramLength[3] = 0;
  paramFormat[3] = 0;

  OmlValue* v = values;
  for (i = 0; i < value_count; i++, v++) {
    struct schema_field *field = &table->schema->fields[i];
    if (oml_value_get_type(v) != field->type) {
      logerror("psql:%s: Value %d type mismatch for table '%s'\n", db->name, i, table->schema->name);
      return -1;
    }
    switch (field->type) {
    case OML_LONG_VALUE: sprintf(paramValues[4+i],"%i",(int)v->value.longValue); break;
    case OML_INT32_VALUE:  sprintf(paramValues[4+i],"%" PRId32,v->value.int32Value); break;
    case OML_UINT32_VALUE: sprintf(paramValues[4+i],"%" PRIu32,v->value.uint32Value); break;
    case OML_INT64_VALUE:  sprintf(paramValues[4+i],"%" PRId64,v->value.int64Value); break;
    case OML_UINT64_VALUE: sprintf(paramValues[4+i],"%" PRIu64,v->value.uint64Value); break;
    case OML_DOUBLE_VALUE: sprintf(paramValues[4+i],"%.8f",v->value.doubleValue); break;
    case OML_STRING_VALUE: sprintf(paramValues[4+i],"%s", omlc_get_string_ptr(*oml_value_get_value(v))); break;
    case OML_BLOB_VALUE:
                           escaped_blob = PQescapeByteaConn(psqldb->conn,
                               v->value.blobValue.ptr, v->value.blobValue.length, &eblob_len);
                           if (!escaped_blob) {
                             logerror("psql:%s: Error escaping blob in field %d of table '%s': %s\n",
                                 db->name, i, table->schema->name, PQerrorMessage(psqldb->conn));
                           }
                           /* XXX: 512 char is the size allocated above. Nasty. */
                           if (eblob_len > 512) {
                             logdebug("psql:%s: Reallocating %d bytes for big blob\n", db->name, eblob_len);
                             paramValues[4+i] = xrealloc(paramValues[4+i], eblob_len);
                             if (!paramValues[4+i]) {
                               logerror("psql:%s: Could not realloc()at memory for escaped blob in field %d of table '%s'\n",
                                   db->name, i, table->schema->name);
                               return -1;
                             }
                           }
                           snprintf(paramValues[4+i], eblob_len, "%s", escaped_blob);
                           PQfreemem(escaped_blob);
                           break;
    default:
      logerror("psql:%s: Unknown type %d in col '%s' of table '%s'; this is probably a bug\n",
          db->name, field->type, field->name, table->schema->name);
      return -1;
    }
    paramLength[4+i] = 0;
    paramFormat[4+i] = 0;
  }
  /* Use stuff from http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING */

  res = PQexecPrepared(psqldb->conn, insert_stmt,
                       4+value_count, (const char**)paramValues,
                       (int*) &paramLength, (int*) &paramFormat, 0 );

  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
    logerror("psql:%s: INSERT INTO '%s' failed: %s\n",
        db->name, table->schema->name, PQerrorMessage(psqldb->conn));
    PQclear(res);
    return -1;
  }
  PQclear(res);

  for (i=0;i<4+value_count;i++) {
    xfree(paramValues[i]);
  }

  return 0;
}
Beispiel #4
0
/** Convert data stored in an OmlValueU of the given OmlValueT to a string representation.
 *
 * The given buffer will contain a nul-terminated C string.
 *
 * \param value pointer to OmlValue containing data
 * \param buf buffer to put the textual representation of the value in
 * \param size size of the buffer
 * \return a pointer to buf, or NULL on error
 */
static char*
oml_value_ut_to_s(OmlValueU* value, OmlValueT type, char *buf, size_t size)
{
    size_t i, m, n = 0;

    switch (type) {
    case OML_LONG_VALUE:
        logwarn("%s(): OML_LONG_VALUE is deprecated, please use OML_INT32_VALUE instead\n", __FUNCTION__);
        n += snprintf(buf, size, "%ld", omlc_get_long(*value));
        break;
    case OML_INT32_VALUE:
        n += snprintf(buf, size, "%" PRId32, omlc_get_int32(*value));
        break;
    case OML_UINT32_VALUE:
        n += snprintf(buf, size, "%" PRIu32, omlc_get_uint32(*value));
        break;
    case OML_INT64_VALUE:
        n += snprintf(buf, size, "%" PRId64, omlc_get_int64(*value));
        break;
    case OML_UINT64_VALUE:
        n += snprintf(buf, size, "%" PRIu64, omlc_get_uint64(*value));
        break;
    case OML_DOUBLE_VALUE:
        n += snprintf(buf, size, "%f", omlc_get_double(*value));
        break;
    case OML_STRING_VALUE:
        n += snprintf(buf, size, "%s", omlc_get_string_ptr(*value));
        break;
    case OML_DATETIME_VALUE:
        n += snprintf(buf, size, "%s", omlc_get_string_ptr(*value));
        break;
    case OML_BLOB_VALUE:
        strncpy(buf, "0x", size);
        for(n = 2, i = 0; i < omlc_get_blob_length(*value) &&  n < size; i++) /* n = 2 because of the 0x prefix */
            n += snprintf(buf + n, size - n, "%02x", ((uint8_t*)(omlc_get_blob_ptr(*value)))[i]);
        break;
    case OML_GUID_VALUE:
        n += omlc_guid_to_string(omlc_get_guid(*value), buf);
        break;
    case OML_BOOL_VALUE:
        n += snprintf(buf, size, "%s", (omlc_get_bool(*value)==OMLC_BOOL_FALSE) ? "false" : "true");
        break;
    case OML_VECTOR_DOUBLE_VALUE:
        m = omlc_get_vector_nof_elts(*value);
        n += snprintf(buf, size, "%zu", m);
        for(i = 0; i < m && n < size; i++)
            n += snprintf(&buf[n], size - n, " %.*g", DBL_DIG, ((double*)(omlc_get_vector_ptr(*value)))[i]);
        break;
    case OML_VECTOR_INT32_VALUE:
        m = omlc_get_vector_nof_elts(*value);
        n += snprintf(buf, size, "%zu", m);
        for(i = 0; i < m && n < size; i++)
            n += snprintf(&buf[n], size - n, " %" PRId32, ((int32_t*)(omlc_get_vector_ptr(*value)))[i]);
        break;
    case OML_VECTOR_UINT32_VALUE:
        m = omlc_get_vector_nof_elts(*value);
        n += snprintf(buf, size, "%zu", m);
        for(i = 0; i < m && n < size; i++)
            n += snprintf(&buf[n], size - n, " %" PRIu32, ((uint32_t*)(omlc_get_vector_ptr(*value)))[i]);
        break;
    case OML_VECTOR_INT64_VALUE:
        m = omlc_get_vector_nof_elts(*value);
        n += snprintf(buf, size, "%zu", m);
        for(i = 0; i < m && n < size; i++)
            n += snprintf(&buf[n], size - n, " %" PRId64, ((int64_t*)(omlc_get_vector_ptr(*value)))[i]);
        break;
    case OML_VECTOR_UINT64_VALUE:
        m = omlc_get_vector_nof_elts(*value);
        n += snprintf(buf, size, "%zu", m);
        for(i = 0; i < m && n < size; i++)
            n += snprintf(&buf[n], size - n, " %" PRIu64, ((uint64_t*)(omlc_get_vector_ptr(*value)))[i]);
        break;
    case OML_VECTOR_BOOL_VALUE:
        m = omlc_get_vector_nof_elts(*value);
        n += snprintf(buf, size, "%zu", m);
        for(i = 0; i < m && n < size; i++)
            n += snprintf(&buf[n], size - n, " %s", ((bool*)(omlc_get_vector_ptr(*value)))[i] ? "true" : "false");
        break;
    default:
        logerror("%s() for type '%d' not implemented'\n", __FUNCTION__, type);
        return NULL;
    }

    /* Ensure string is NUL-terminated... */
    if(n < size)
        buf[n] = '\0';
    else {
        /* Indicate truncation when space permits */
        const char ldots[] = "...";
        const size_t ldots_sz = sizeof(ldots);
        if(ldots_sz < size)
            strcpy(buf + size - ldots_sz, ldots);
        else
            buf[size] = '\0';
    }

    return buf;
}
Beispiel #5
0
/** Marshal a single OmlValueU of type OmlValueT into mbuf.
 *
 * Usually called by marshal_values(). On failure, the whole message writing is
 * reset using mbuf_reset_write(), and marshalling should restart with
 * marshal_init(), after the MBuffer has been adequately resized or repacked.
 *
 * \param mbuf MBuffer to write marshalled data to
 * \param val_type OmlValueT representing the type of val
 * \param val pointer to OmlValueU, of type val_type, to marshall
 * \return 1 on success, or 0 otherwise (marshalling should then restart from marshal_init())
 * \see marshal_values, marshal_init, mbuf_reset_write, mbuf_repack_message, mbuf_repack_message2, mbuf_resize
 */
int
marshal_value(MBuffer* mbuf, OmlValueT val_type, OmlValueU* val)
{
  switch (val_type) {
  case OML_LONG_VALUE: {
    long v = oml_value_clamp_long (omlc_get_long(*val));
    uint32_t uv = (uint32_t)v;
    uint32_t nv = htonl(uv);
    uint8_t buf[LONG_T_SIZE+1];

    buf[0] = LONG_T;
    memcpy(&buf[1], &nv, sizeof (nv));

    logdebug3("Marshalling long %ld\n", nv);
    int result = mbuf_write (mbuf, buf, LENGTH (buf));
    if (result == -1) {
      logerror("Failed to marshal OML_LONG_VALUE (mbuf_write())\n");
      mbuf_reset_write (mbuf);
      return 0;
    }
    break;
  }
  case OML_INT32_VALUE:
  case OML_UINT32_VALUE:
  case OML_INT64_VALUE:
  case OML_UINT64_VALUE: {
    uint8_t buf[UINT64_T_SIZE+1]; // Max integer size
    uint32_t uv32;
    uint32_t nv32;
    uint64_t uv64;
    uint64_t nv64;
    uint8_t *p_nv;

    if (oml_size_map[val_type] == 4)
    {
      uv32 = omlc_get_uint32(*val);
      nv32 = htonl(uv32);
      p_nv = (uint8_t*)&nv32;
      logdebug3("Marshalling %s %" PRIu32 "\n", oml_type_to_s(val_type), uv32);
    } else {
      uv64 = omlc_get_uint64(*val);
      nv64 = htonll(uv64);
      p_nv = (uint8_t*)&nv64;
      logdebug3("Marshalling %s %" PRIu64 "\n", oml_type_to_s(val_type), uv64);
    }

    buf[0] = oml_type_map[val_type];
    memcpy(&buf[1], p_nv, oml_size_map[val_type]);

    int result = mbuf_write (mbuf, buf, oml_size_map[val_type] + 1);
    if (result == -1)
      {
        logerror("Failed to marshal %s value (mbuf_write())\n",
               oml_type_to_s (val_type));
        mbuf_reset_write (mbuf);
        return 0;
      }
    break;
  }
  case OML_DOUBLE_VALUE: {
    uint8_t type = DOUBLE_T;
    double v = omlc_get_double(*val);
    int exp;
    double mant = frexp(v, &exp);
    int8_t nexp = (int8_t)exp;
    logdebug3("Marshalling double %f\n", v);
    if (isnan(v)) {
      type = DOUBLE_NAN;
      nexp = 0;
      mant = 0;
    } else if (nexp != exp) {
      logerror("Double number '%lf' is out of bounds, sending NaN\n", v);
      type = DOUBLE_NAN;
      nexp = 0;
      mant = 0;
   }
   int32_t imant = (int32_t)(mant * (1 << BIG_L));
   uint32_t nmant = htonl(imant);

   uint8_t buf[6] = { type, 0, 0, 0, 0, nexp };

   memcpy(&buf[1], &nmant, sizeof (nmant));

   int result = mbuf_write (mbuf, buf, LENGTH (buf));

   if (result == -1)
     {
       logerror("Failed to marshal OML_DOUBLE_VALUE (mbuf_write())\n");
       mbuf_reset_write (mbuf);
       return 0;
     }
   break;
 }
 case OML_STRING_VALUE: {
   char* str = omlc_get_string_ptr(*val);

   if (str == NULL) {
     str = "";
     logdebug("Attempting to send a NULL string; sending empty string instead\n");
   }

   size_t len = strlen(str);
   if (len > STRING_T_MAX_SIZE) {
     logerror("Truncated string '%s'\n", str);
     len = STRING_T_MAX_SIZE;
   }

   logdebug3("Marshalling string '%s' of length %d\n", str, len);
   uint8_t buf[2] = { STRING_T, (uint8_t)(len & 0xff) };
   int result = mbuf_write (mbuf, buf, LENGTH (buf));
   if (result == -1) {
     logerror("Failed to marshal OML_STRING_VALUE type and length (mbuf_write())\n");
     mbuf_reset_write (mbuf);
     return 0;
   }

   result = mbuf_write (mbuf, (uint8_t*)str, len);

   if (result == -1)
     {
       logerror("Failed to marshal OML_STRING_VALUE (mbuf_write())\n");
       mbuf_reset_write (mbuf);
       return 0;
     }
   break;
 }
 case OML_BLOB_VALUE: {
   int result = 0;
   void *blob = omlc_get_blob_ptr(*val);
   size_t length = omlc_get_blob_length(*val);
   if (blob == NULL || length == 0) {
     logdebug ("Attempting to send NULL or empty blob; blob of length 0 will be sent\n");
     length = 0;
   }

   uint8_t buf[5] = { BLOB_T, 0, 0, 0, 0 };
   size_t n_length = htonl (length);
   memcpy (&buf[1], &n_length, 4);

   logdebug3("Marshalling blob of size %d\n", length);
   result = mbuf_write (mbuf, buf, sizeof (buf));

   if (result == -1) {
     logerror ("Failed to marshall OML_BLOB_VALUE type and length (mbuf_write())\n");
     mbuf_reset_write (mbuf);
     return 0;
   }

   result = mbuf_write (mbuf, blob, length);

   if (result == -1) {
     logerror ("Failed to marshall %d bytes of OML_BLOB_VALUE data\n", length);
     mbuf_reset_write (mbuf);
     return 0;
   }
   break;
 }

  case OML_GUID_VALUE: {
    /* FIXME: Wrap with UINT64 marshalling, just change the type */
    uint64_t nv64;
    uint8_t buf[GUID_T_SIZE+1];
    buf[0] = GUID_T;
    nv64 = htonll(omlc_get_guid(*val));
    memcpy(&buf[1], &nv64, sizeof(nv64));
    logdebug3("Marshalling GUID %" PRIu64 "\n", nv64);
    if (-1 == mbuf_write(mbuf, buf, LENGTH(buf))) {
      logerror("Failed to marshal OML_GUID_VALUE (mbuf_write())\n");
      mbuf_reset_write(mbuf);
      return 0;
    }
    break;
  }

  case OML_BOOL_VALUE: {
    uint8_t buf;
    if (!omlc_get_bool(*val)) {
      buf = BOOL_FALSE_T;
    } else {
      buf = BOOL_TRUE_T;
    }
    logdebug3("Marshalling boolean %d\n", BOOL_TRUE_T == buf);
    if (-1 == mbuf_write(mbuf, &buf, 1)) {
      logerror("Failed to marshal OML_BOOL_VALUE (mbuf_write())\n");
      mbuf_reset_write(mbuf);
      return 0;
    }
    break;
  }

  case OML_VECTOR_INT32_VALUE:
  case OML_VECTOR_UINT32_VALUE: {
    size_t i;
    uint8_t buf[VECTOR_T_SIZE] = { VECTOR_T, 0, 0, 0 };
    uint16_t hn = omlc_get_vector_nof_elts(*val);
    uint16_t nn = htons(hn);
    buf[1] = vector_protocol_map[val_type];
    memcpy(&buf[2], &nn, sizeof(nn));
    if(mbuf_write(mbuf, buf, VECTOR_T_SIZE) == 0) {
      uint32_t elts[hn];
      uint32_t *v = omlc_get_vector_ptr(*val);
      for(i = 0; i < hn; i++)
        elts[i] = htonl(*((uint32_t*)(v+i)));
      if(mbuf_write(mbuf, (const uint8_t*)(elts), sizeof(elts)) == -1) {
        logerror("%s(): failed to marshal %s of size %" PRIu16 " (mbuf_write())\n", __func__, oml_type_to_s(val_type), hn);
        mbuf_reset_write(mbuf);
        return 0;
      }
    } else {
      logerror("%s(): failed to marshal %s length (mbuf_write())\n", __func__, oml_type_to_s(val_type));
      mbuf_reset_write(mbuf);
      return 0;
    }
    break;
  }

  case OML_VECTOR_INT64_VALUE:
  case OML_VECTOR_UINT64_VALUE:
  case OML_VECTOR_DOUBLE_VALUE: {
    size_t i;
    uint8_t buf[VECTOR_T_SIZE] = { VECTOR_T, 0, 0, 0 };
    uint16_t hn = omlc_get_vector_nof_elts(*val);
    uint16_t nn = htons(hn);
    buf[1] = vector_protocol_map[val_type];
    memcpy(&buf[2], &nn, sizeof(nn));
    if(mbuf_write(mbuf, buf, VECTOR_T_SIZE) == 0) {
      uint64_t elts[hn];
      uint64_t *v = omlc_get_vector_ptr(*val);
      for(i = 0; i < hn; i++)
        elts[i] = htonll(*((uint64_t*)(v+i)));
      if(mbuf_write(mbuf, (const uint8_t*)(elts), sizeof(elts)) == -1) {
        logerror("%s(): failed to marshal %s of size %" PRIu16 " (mbuf_write())\n", __func__, oml_type_to_s(val_type), hn);
        mbuf_reset_write(mbuf);
        return 0;
      }
    } else {
      logerror("%s(): failed to marshal %s length (mbuf_write())\n", __func__, oml_type_to_s(val_type));
      mbuf_reset_write(mbuf);
        return 0;
    }
    break;
  }

  case OML_VECTOR_BOOL_VALUE: {
    size_t i;
    uint8_t buf[VECTOR_T_SIZE] = { VECTOR_T, 0, 0, 0 };
    uint16_t hn = omlc_get_vector_nof_elts(*val);
    uint16_t nn = htons(hn);
    buf[1] = vector_protocol_map[val_type];
    memcpy(&buf[2], &nn, sizeof(nn));
    if(mbuf_write(mbuf, buf, VECTOR_T_SIZE) == 0) {
      uint8_t elts[hn];
      bool *v = omlc_get_vector_ptr(*val);
      for(i = 0; i < hn; i++)
        elts[i] = v[i] ? BOOL_TRUE_T : BOOL_FALSE_T;
      if(mbuf_write(mbuf, (const uint8_t*)(elts), hn) == -1) {
        logerror("%s(): failed to marshal %s of size %" PRIu16 " (mbuf_write())\n", __func__, oml_type_to_s(val_type), hn);
        mbuf_reset_write(mbuf);
        return 0;
      }
    } else {
      logerror("%s(): failed to marshal %s length (mbuf_write())\n", __func__, oml_type_to_s(val_type));
      mbuf_reset_write(mbuf);
      return 0;
    }
    break;
  }

  default:
    logerror("%s(): Unsupported value type '%d'\n", __func__, val_type);
    return 0;
  }

  return 1;
}
Beispiel #6
0
/** Unmarshals the next content of an MBuffer into a OmlValue
 *
 * \param mbuf MBuffer to read from
 * \param value pointer to OmlValue to unmarshall the read data into
 * \return 1 if successful, 0 otherwise
 */
int
unmarshal_value(MBuffer *mbuf, OmlValue *value)
{
  if (mbuf_rd_remaining(mbuf) == 0) {
    logerror("Tried to unmarshal a value from the buffer, but didn't receive enough data to do that\n");
    return 0;
  }

  int type = mbuf_read_byte (mbuf);
  if (type == -1) return 0;

  switch (type) {
  case LONG_T: {
    uint8_t buf [LONG_T_SIZE];

    if (mbuf_read (mbuf, buf, LENGTH (buf)) == -1)
    {
      logerror("Failed to unmarshal OML_LONG_VALUE; not enough data?\n");
      return 0;
    }

    uint32_t hv = ntohl(*((uint32_t*)buf));
    int32_t v = (int32_t)(hv);

    /*
     * The server no longer needs to know about OML_LONG_VALUE, as the
     * marshalling process now maps OML_LONG_VALUE into OML_INT32_VALUE
     * (by truncating to [INT_MIN, INT_MAX].  Therefore, unmarshall a
     * LONG_T value into an OML_INT32_VALUE object.
     */
    oml_value_set_type(value, OML_INT32_VALUE);
    omlc_set_int32(*oml_value_get_value(value), v);
    break;
  }
  case INT32_T:
  case UINT32_T:
  case INT64_T:
  case UINT64_T: {
    uint8_t buf [UINT64_T_SIZE]; // Maximum integer size
    OmlValueT oml_type = protocol_type_map[type];
    if (mbuf_read (mbuf, buf, protocol_size_map[type]) == -1) {
      logerror("Failed to unmarshall %d value; not enough data?\n", type);
      return 0;
    }
    oml_value_set_type(value, oml_type);
    switch (type) {
    case INT32_T:
      omlc_set_int32(*oml_value_get_value(value), ntohl(*((int32_t*)buf)));
      logdebug3("Unmarshalled %s %" PRId32 "\n", oml_type_to_s(oml_type), omlc_get_int32(*oml_value_get_value(value)));
      break;

    case UINT32_T:
      omlc_set_uint32(*oml_value_get_value(value), ntohl(*((uint32_t*)buf)));
      logdebug3("Unmarshalled %s %" PRIu32 "\n", oml_type_to_s(oml_type), omlc_get_uint32(*oml_value_get_value(value)));
      break;

    case INT64_T:
      omlc_set_int64(*oml_value_get_value(value), ntohll(*((int64_t*)buf)));
      logdebug3("Unmarshalled %s %" PRId64 "\n", oml_type_to_s(oml_type), omlc_get_int64(*oml_value_get_value(value)));
      break;

    case UINT64_T:
      omlc_set_uint64(*oml_value_get_value(value), ntohll(*((uint64_t*)buf)));
      logdebug3("Unmarshalled %s %" PRIu64 "\n", oml_type_to_s(oml_type), omlc_get_uint64(*oml_value_get_value(value)));
      break;

    default:
      logerror("Integer morphed, something magic has just happened\n");
      return 0;
    }
    break;
  }
  case DOUBLE_T: {
    uint8_t buf [DOUBLE_T_SIZE];
    OmlValueT oml_type = protocol_type_map[type];
    if (mbuf_read (mbuf, buf, LENGTH (buf)) == -1)
    {
      logerror("Failed to unmarshal OML_DOUBLE_VALUE; not enough data?\n");
      return 0;
    }

    int hmant = (int)ntohl(*((uint32_t*)buf));
    double mant = hmant * 1.0 / (1 << BIG_L);
    int exp = (int8_t) buf[4];
    double v = ldexp(mant, exp);
    oml_value_set_type(value, oml_type);
    omlc_set_double(*oml_value_get_value(value), v);
    logdebug3("Unmarshalled double %f\n", omlc_get_double(*oml_value_get_value(value)));
    break;
  }
  case DOUBLE_NAN: {
    OmlValueT oml_type = protocol_type_map[type];
    mbuf_read_skip(mbuf, DOUBLE_T_SIZE); /* The data is irrelevant */
    oml_value_set_type(value, oml_type);
    omlc_set_double(*oml_value_get_value(value), NAN);
    logdebug("Received NaN\n");
    break;
  }
  case STRING_T: {
    int len = 0;
    uint8_t buf [STRING_T_MAX_SIZE];

    len = mbuf_read_byte (mbuf);

    if (len == -1 || mbuf_read (mbuf, buf, len) == -1)
    {
      logerror("Failed to unmarshal OML_STRING_VALUE; not enough data?\n");
      return 0;
    }

    oml_value_set_type(value, OML_STRING_VALUE);
    omlc_set_string_copy(*oml_value_get_value(value), buf, len);
    logdebug3("Unmarshalled string '%s' of length %d\n", omlc_get_string_ptr(*oml_value_get_value(value)), len);
    break;
  }
  case BLOB_T: {
    uint32_t n_len;

    if (mbuf_read (mbuf, (uint8_t*)&n_len, 4) == -1) {
      logerror ("Failed to unmarshal OML_BLOB_VALUE length field; not enough data?\n");
      return 0;
    }

    size_t len = ntohl (n_len);
    size_t remaining = mbuf_rd_remaining (mbuf);

    if (len > remaining) {
      logerror ("Failed to unmarshal OML_BLOB_VALUE data:  not enough data available "
                "(wanted %d, but only have %d bytes\n",
                len, remaining);
      return 0;
    }

    void *ptr = mbuf_rdptr (mbuf);
    oml_value_set_type(value, OML_BLOB_VALUE);
    omlc_set_blob (*oml_value_get_value(value), ptr, len); /*XXX*/
    logdebug3("Unmarshalled blob of size %d\n", len);
    mbuf_read_skip (mbuf, len);
    break;
  }

  case GUID_T: {
    uint64_t nv64;
    uint8_t buf[GUID_T_SIZE];
    if(mbuf_read(mbuf, buf, GUID_T_SIZE) == -1) {
      logerror("Failed to unmarshall OML_GUID_VALUE data; not enough data?\n");
      return 0;
    }
    memcpy(&nv64, buf, sizeof(nv64));
    oml_value_set_type(value, OML_GUID_VALUE);
    omlc_set_guid(*oml_value_get_value(value), ntohll(nv64));
    logdebug3("Unmarshalled GUID %" PRIu64 "\n", omlc_get_guid(*oml_value_get_value(value)));
    break;
  }

  case BOOL_FALSE_T:
  case BOOL_TRUE_T:
    oml_value_set_type(value, OML_BOOL_VALUE);
    omlc_set_bool(*oml_value_get_value(value),
                  (type == BOOL_TRUE_T)?OMLC_BOOL_TRUE:OMLC_BOOL_FALSE);
    logdebug3("Unmarshalled boolean %d\n", OMLC_BOOL_TRUE == omlc_get_bool(*oml_value_get_value(value)));
    break;

  case VECTOR_T: {
    uint16_t i, nof_elts;
    int type = mbuf_read_byte(mbuf);
    if(-1 == type) {
      logerror("%s(): failed to unmarshall VECTOR_T length\n", __func__);
      return 0;
    }
    if(mbuf_read(mbuf,(uint8_t*)(&nof_elts), sizeof(nof_elts)) == -1) {
      logerror("%s(): failed to unmarshall VECTOR_T length\n", __func__);
      return 0;
    }
    nof_elts = ntohs(nof_elts);

    OmlValueT oml_type = vector_type_map[type];
    OmlValueU *v = oml_value_get_value(value);
    switch(type) {
    case INT32_T:
    case UINT32_T: {
      size_t bytes = nof_elts * sizeof(uint32_t);
      uint32_t *elts = oml_calloc(nof_elts, sizeof(uint32_t));
      if(mbuf_read(mbuf, (uint8_t*)(elts), nof_elts * sizeof(uint32_t)) == -1) {
        logerror("%s(): failed to unmarshall OML_VECTOR_(U)INT32_VALUE\n", __func__);
        return 0;
      }
      for(i = 0; i < nof_elts; i++)
        elts[i] = ntohl(elts[i]);
      oml_value_set_type(value, oml_type);
      omlc_set_vector_ptr(*v, elts);
      omlc_set_vector_length(*v, bytes);
      omlc_set_vector_size(*v, bytes);
      omlc_set_vector_nof_elts(*v, nof_elts);
      omlc_set_vector_elt_size(*v, sizeof(uint32_t));
      break;
    }
    case INT64_T:
    case UINT64_T:
    case DOUBLE64_T: {
      size_t bytes = nof_elts * sizeof(uint64_t);
      uint64_t *elts = oml_calloc(nof_elts, sizeof(uint64_t));
      if(mbuf_read(mbuf, (uint8_t*)(elts), nof_elts * sizeof(uint64_t)) == -1) {
        logerror("%s(): failed to unmarshall OML_VECTOR_(U)INT64_VALUE\n", __func__);
        return 0;
      }
      for(i = 0; i < nof_elts; i++)
        elts[i] = ntohll(elts[i]);
      oml_value_set_type(value, oml_type);
      omlc_set_vector_ptr(*v, elts);
      omlc_set_vector_length(*v, bytes);
      omlc_set_vector_size(*v, bytes);
      omlc_set_vector_nof_elts(*v, nof_elts);
      omlc_set_vector_elt_size(*v, sizeof(uint64_t));
      break;
    }
    case BOOL_T: {
      uint8_t y[nof_elts];
      size_t bytes = nof_elts * sizeof(bool);
      bool *elts = oml_calloc(nof_elts, sizeof(bool));
      if(mbuf_read(mbuf, y, nof_elts) == -1) {
        logerror("%s(): failed to unmarshall OML_VECTOR_BOOL_VALUE\n", __func__);
        return 0;
      }
      for(i = 0; i < nof_elts; i++)
        elts[i] = ((BOOL_TRUE_T == y[i]) ? true : false);
      oml_value_set_type(value, oml_type);
      omlc_set_vector_ptr(*v, elts);
      omlc_set_vector_length(*v, bytes);
      omlc_set_vector_size(*v, bytes);
      omlc_set_vector_nof_elts(*v, nof_elts);
      omlc_set_vector_elt_size(*v, sizeof(bool));
      break;
    }
    default:
      logerror("%s(): bad type for array (t=%d)\n", __func__, type);
      break;
    }
    break;
  }

  default:
    logerror("%s: Unsupported value type '%d'\n", __FUNCTION__, type);
    return 0;
  }

  return 1;
}
Beispiel #7
0
END_TEST

START_TEST (test_string)
{
  char *test = "test";
  OmlValue v, v2;
  OmlValueU vu;
  size_t bcount = xmembytes();
  size_t alloc_diff;

  oml_value_init(&v);
  oml_value_init(&v2);

  omlc_zero(vu);

  /* Prepare the OmlValueU to be duplicated in the OmlValue */
  omlc_set_const_string(vu, test);

  oml_value_set(&v, &vu, OML_STRING_VALUE);
  alloc_diff = xmembytes() - bcount - sizeof(size_t);
  bcount = xmembytes();
  fail_if(alloc_diff < strlen(test) + 1,
      "OmlValue string allocated memory not big enough (%d instead of at least %d)",
      alloc_diff, strlen(test) + 1);

  oml_value_duplicate(&v2, &v);
  fail_if(omlc_get_string_ptr(*oml_value_get_value(&v2)) == omlc_get_string_ptr(*oml_value_get_value(&v)),
      "Copied OmlValue string pointer not allocated properly");
  fail_if(strcmp(omlc_get_string_ptr(*oml_value_get_value(&v2)), omlc_get_string_ptr(*oml_value_get_value(&v))),
      "Copied OmlValue string mismatch ('%s' instead of '%s')",
      omlc_get_string_ptr(*oml_value_get_value(&v2)), omlc_get_string_ptr(*oml_value_get_value(&v)));
  fail_unless(omlc_get_string_length(*oml_value_get_value(&v2)) == strlen(omlc_get_string_ptr(*oml_value_get_value(&v2))),
      "Copied OmlValue string length not set properly (%d instead of %d)",
      omlc_get_string_length(*oml_value_get_value(&v2)), strlen(omlc_get_string_ptr(*oml_value_get_value(&v2))) + 1);
  alloc_diff = xmembytes() - bcount - sizeof(size_t); /* oml_malloc() always allocates at least sizeof(size_t) more for bookkeeping */
  bcount = xmembytes();
  fail_if(alloc_diff < strlen(omlc_get_string_ptr(*oml_value_get_value(&v))) + 1,
      "Copied OmlValue string allocated memory not big enough (%d instead of at least %d)",
      alloc_diff, strlen(omlc_get_string_ptr(*oml_value_get_value(&v))) + 1);
  fail_unless(omlc_get_string_size(*oml_value_get_value(&v2)) == oml_malloc_usable_size(omlc_get_string_ptr(*oml_value_get_value(&v2))),
      "Copied OmlValue string allocated size not set properly (%d instead of %d)",
      omlc_get_string_size(*oml_value_get_value(&v2)), oml_malloc_usable_size(omlc_get_string_ptr(*oml_value_get_value(&v2))));
  fail_unless(omlc_get_string_is_const(*oml_value_get_value(&v2)) == 0,
      "Copied OmlValue string should not be constant");

  oml_value_set_type(&v, OML_UINT64_VALUE);
  fail_unless(xmembytes() < bcount,
      "OmlValue string  was not freed after oml_value_set_type() (%d allocated, which is not less than %d)",
      xmembytes(), bcount);
  bcount = xmembytes();

  oml_value_reset(&v2);
  fail_unless(xmembytes() < bcount,
      "OmlValue string  was not freed after oml_value_reset() (%d allocated, which is not less than %d)",
      xmembytes(), bcount);
  bcount = xmembytes();

  oml_value_reset(&v);
  omlc_reset_string(vu);
}
Beispiel #8
0
END_TEST

START_TEST (test_blobU)
{
  OmlValueU v, v2;
  char *str = "this is a string subtly disguised as a blob";
  char *str2 = "this is another string in blob's clothing, except longer";
  void *test = (void*) str;
  void *test2 = (void*) str2;
  size_t len = strlen(str);
  size_t len2 = strlen(str2);
  size_t bcount = xmembytes(), alloc_diff, size;

  omlc_zero(v);
  omlc_zero(v2);

  /* Set blob (copy) */
  omlc_set_blob(v, test, len);
  fail_if(omlc_get_blob_ptr(v) == test,
      "Test blob pointer not allocated properly");
  fail_if(strncmp(test, omlc_get_blob_ptr(v), len),
      "Test blob mismatch");
  fail_unless(omlc_get_blob_length(v) == len,
      "Test blob length not set properly (%d instead of %d)",
      omlc_get_blob_length(v), len);
  alloc_diff = xmembytes() - bcount - sizeof(size_t);
  bcount = xmembytes();
  fail_if(alloc_diff < len,
      "Test blob allocated memory not big enough (%d instead of at least %d)",
      alloc_diff, len);
  fail_unless(omlc_get_blob_size(v) == oml_malloc_usable_size(omlc_get_string_ptr(v)),
      "Test blob allocated size not set properly (%d instead of %d)",
      omlc_get_blob_size(v), oml_malloc_usable_size(omlc_get_string_ptr(v)));

  /* Duplicate blob*/
  omlc_copy_blob(v2, v);
  fail_if(omlc_get_blob_ptr(v2) == omlc_get_blob_ptr(v),
      "Copied blob not allocated properly");
  fail_if(strncmp(omlc_get_blob_ptr(v2), omlc_get_blob_ptr(v), len),
      "Copied allocated blob mismatch");
  fail_unless(omlc_get_blob_length(v2) == omlc_get_blob_length(v),
      "Copied allocated blob length not set properly (%d instead of %d)",
      omlc_get_blob_length(v2), omlc_get_blob_length(v));
  alloc_diff = xmembytes() - bcount - sizeof(size_t);
  bcount = xmembytes();
  fail_if(alloc_diff < len,
      "Copied allocated blob allocated memory not big enough (%d instead of at least %d)",
      alloc_diff, len);
  fail_unless(omlc_get_blob_size(v) == oml_malloc_usable_size(omlc_get_blob_ptr(v2)),
      "Copied allocated blob allocated size not set properly (%d instead of %d)",
      omlc_get_blob_size(v2), oml_malloc_usable_size(omlc_get_blob_ptr(v2)));

  /* Overwrite blob */
  omlc_set_blob(v, test2, len2);
  /* We know omlc_set_blob() already sets properly, we just want to check it does cleanup previously allocated memory */
  fail_if(xmembytes() > bcount + omlc_get_blob_size(v),
      "Overwritten blob did not deallocate memory properly (%d used but expected %d)",
      xmembytes(), bcount + omlc_get_blob_size(v));

  /* Reset blob and clear allocated pointer */
  omlc_reset_blob(v);
  size = omlc_get_blob_size(v);
  omlc_reset_blob(v);
  fail_unless(omlc_get_blob_ptr(v) == NULL,
      "Reset allocated blob pointer not cleared properly");
  fail_unless(omlc_get_blob_length(v) == 0,
      "Reset allocated blob length not cleared properly");
  alloc_diff = bcount - xmembytes() + sizeof(size_t);
  bcount = xmembytes();
  fail_if(alloc_diff <= size,
      "Reset allocated blob didn't free the memory as expected (%d freed instead at least %d)",
      alloc_diff, size);
  fail_unless(omlc_get_blob_size(v) == 0,
      "Reset allocated blob allocated size not cleared properly");

  omlc_reset_blob(v2);
}