int text_read_msg_start (struct oml_message *msg, MBuffer *mbuf) { int len = mbuf_find (mbuf, '\n'); // Find length of line OmlValue value; int bytes = 0; oml_value_init(&value); if (len == -1) return 0; // Haven't got a full line msg->length = (uint32_t)len + 1; /* Read the timestamp first */ oml_value_set_type(&value, OML_DOUBLE_VALUE); bytes = text_read_value (mbuf, &value, len); if (bytes == -1) return -1; else len -= bytes; msg->timestamp = omlc_get_double(*oml_value_get_value(&value)); /* Read the stream index */ oml_value_set_type(&value, OML_UINT32_VALUE); bytes = text_read_value (mbuf, &value, len); if (bytes == -1) return -1; else len -= bytes; msg->stream = omlc_get_uint32(*oml_value_get_value(&value)); /* Read the sequence number */ oml_value_set_type(&value, OML_UINT32_VALUE); bytes = text_read_value (mbuf, &value, len); if (bytes == -1) return -1; else len -= bytes; msg->seqno = omlc_get_uint32(*oml_value_get_value(&value)); oml_value_reset(&value); return msg->length; }
/** * @brief Read a vector of values matching schema from mbuf. * * Reads as many values as required to match the schema from the * mbuf, and stores them in the values vector. * */ int text_read_msg_values (struct oml_message *msg, MBuffer *mbuf, struct schema *schema, OmlValue *values) { int length = msg->length; int index = mbuf_message_index (mbuf); int msg_remaining = length - index; int i = 0; length = msg_remaining; for (i = 0; i < schema->nfields; i++) { int bytes; oml_value_set_type(&values[i], schema->fields[i].type); bytes = text_read_value (mbuf, &values[i], length); if (bytes == -1) return -1; else length -= bytes; } msg->count = schema->nfields; // rdptr now points to start of next line/message mbuf_consume_message (mbuf); return 0; }
/** Try to convert a string to the type represented by the given string, and store it an OmlValue. * * \param value pointer to output OmlValue * \param type_s string representing an OmlValueT * \param value_s input string * \return 0 on success, -1 otherwise * \see oml_value_init, oml_value_ut_from_s, oml_type_from_s */ int oml_value_from_typed_s (OmlValue *value, const char *type_s, const char *value_s) { OmlValueT type = oml_type_from_s (type_s); oml_value_set_type(value, type); return oml_value_ut_from_s(oml_value_get_value(value), type, value_s); }
END_TEST START_TEST (test_blob) { char *str = "this is a string subtly disguised as a blob"; OmlValue v, v2; OmlValueU vu; size_t len = strlen(str); void *test = (void*)str; size_t bcount; 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_blob(vu, test, len); bcount = xmembytes(); oml_value_set(&v, &vu, OML_BLOB_VALUE); alloc_diff = xmembytes() - bcount - sizeof(size_t); bcount = xmembytes(); fail_if(alloc_diff < len, "OmlValue blob allocated memory not big enough (%d instead of at least %d)", alloc_diff, len); oml_value_duplicate(&v2, &v); fail_if(omlc_get_blob_ptr(*oml_value_get_value(&v2)) == omlc_get_blob_ptr(*oml_value_get_value(&v)), "Copied OmlValue blob pointer not allocated properly"); fail_if(strncmp(omlc_get_blob_ptr(*oml_value_get_value(&v2)), omlc_get_blob_ptr(*oml_value_get_value(&v)), len), "Copied OmlValue blob mismatch"); fail_unless(omlc_get_blob_length(*oml_value_get_value(&v2)) == omlc_get_blob_length(*oml_value_get_value(&v)), "Copied OmlValue blob length not set properly (%d instead of %d)", omlc_get_blob_length(*oml_value_get_value(&v2)), omlc_get_blob_length(*oml_value_get_value(&v2))); 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 < len, "Copied OmlValue blob allocated memory not big enough (%d instead of at least %d)", alloc_diff, len); fail_unless(omlc_get_blob_size(*oml_value_get_value(&v2)) == oml_malloc_usable_size(omlc_get_blob_ptr(*oml_value_get_value(&v2))), "Copied OmlValue blob allocated size not set properly (%d instead of %d)", omlc_get_blob_size(*oml_value_get_value(&v2)), oml_malloc_usable_size(omlc_get_blob_ptr(*oml_value_get_value(&v2)))); oml_value_set_type(&v, OML_UINT64_VALUE); fail_unless(xmembytes() < bcount, "OmlValue blob 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 blob 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_blob(vu); }
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); }
/** 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; }
static OmlValue* create_filter_result_vector (OmlFilterDef* def, OmlValueT type, int count) { OmlValue* result = (OmlValue*)oml_malloc(count * sizeof(OmlValue)); if (!result) { logerror ("Failed to allocate memory for filter result vector\n"); return NULL; } oml_value_array_init(result, count); int i = 0; for (i = 0; i < count; i++) { if (def[i].type == OML_INPUT_VALUE) oml_value_set_type(&result[i], type); else oml_value_set_type(&result[i], def[i].type); } return result; }
/** 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; }