/** 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; }
/** * \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; }
/** 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*) ¶mLength, (int*) ¶mFormat, 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; }
/** 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; }
/** 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; }
/** 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; }
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); }
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); }