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); }
/** 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 int process( OmlFilter* f, OmlWriter* writer //! Write results of filter to this function ) { InstanceData* self = (InstanceData*)f->instance_data; omlc_set_double(*oml_value_get_value(&self->result[0]), (self->current - self->previous)); omlc_set_double(*oml_value_get_value(&self->result[1]), self->current); writer->out(writer, self->result, f->output_count); return 0; }
static int process( OmlFilter* f, OmlWriter* writer //! Write results of filter to this function ) { InstanceData* self = (InstanceData*)f->instance_data; omlc_set_double(*oml_value_get_value(&self->result[0]), 1.0 * self->sample_sum / self->sample_count); omlc_set_double(*oml_value_get_value(&self->result[1]), self->sample_min); omlc_set_double(*oml_value_get_value(&self->result[2]), self->sample_max); writer->out(writer, self->result, 3); return 0; }
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; }
static int sample( OmlFilter* f, OmlValue* value //! values of sample ) { InstanceData* self = (InstanceData*)f->instance_data; OmlValueU* v = oml_value_get_value(value);; OmlValueT type = oml_value_get_type(value);; double val; switch (type) { case OML_LONG_VALUE: val = v->longValue; break; case OML_DOUBLE_VALUE: val = v->doubleValue; break; default: // raise error; return -1; } if (isnan(self->sample_sum)) { self->sample_sum = val; } else { self->sample_sum += val; } if (val < self->sample_min || isnan(self->sample_min)) self->sample_min = val; if (val > self->sample_max || isnan(self->sample_max)) self->sample_max = val; self->sample_count++; 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); }
/** Convert data stored in an OmlValue 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 * \see oml_value_ut_to_s */ char* oml_value_to_s(OmlValue *value, char *buf, size_t size) { OmlValueU* v = oml_value_get_value(value); OmlValueT type = oml_value_get_type(value); return oml_value_ut_to_s(v, type, buf, size); }
static int output ( OmlFilter* f, OmlWriter* writer ) { InstanceData* self = (InstanceData*)f->instance_data; if (self->sample_count <= 0) return 1; omlc_set_double(*oml_value_get_value(&self->result[1]), 1.0 * self->s / (self->sample_count - 1)); omlc_set_double(*oml_value_get_value(&self->result[0]), sqrt (omlc_get_double(*oml_value_get_value(&self->result[1])))); self->m = 0; self->s = 0; self->sample_count = 0; writer->out (writer, self->result, f->output_count); return 0; }
static int process(OmlFilter* f, OmlWriter* writer) { InstanceData* self = (InstanceData*)f->instance_data; if (self->sample_count <= 0) return 1; omlc_set_double(*oml_value_get_value(&self->result[0]), self->sample_sum); writer->out(writer, self->result, f->output_count); self->sample_sum = 0.; self->sample_count = 0; 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; }
/** 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; }
static int sample( OmlFilter* f, OmlValue * value //! values of sample ) { InstanceData* self = (InstanceData*)f->instance_data; OmlValueU* v = oml_value_get_value(value);; OmlValueT type = oml_value_get_type(value);; if (type != self->result[0].type) { logwarn ("%s filter: Discarding sample type (%s) different from initial definition (%s)\n", FILTER_NAME, oml_type_to_s(type), oml_type_to_s(self->result[0].type)); return 0; } self->sample_count++; /* Overwrite previously stored value */ return oml_value_set(&self->result[0], v, type); }
/** Cast the data contained in an OmlValue to an int. * * \param value pointer to OmlValue containing the data to cast * \return an integer, which defaults to 0 on error */ int oml_value_to_int (OmlValue *value) { OmlValueU *v = oml_value_get_value(value); OmlValueT type = oml_value_get_type(value); switch (type) { case OML_LONG_VALUE: logwarn("%s(): OML_LONG_VALUE is deprecated, please use OML_INT32_VALUE instead\n", __FUNCTION__); return (int) omlc_get_long(*v); case OML_INT32_VALUE: return (int) omlc_get_int32(*v); case OML_UINT32_VALUE: return (int) omlc_get_uint32(*v); case OML_INT64_VALUE: return (int) omlc_get_int64(*v); case OML_UINT64_VALUE: return (int) omlc_get_uint64(*v); case OML_DOUBLE_VALUE: return (int) omlc_get_double(*v); default: logerror("%s() for type '%d' not implemented'\n", __FUNCTION__, type); return 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; }
/** 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; }
/** Read the marshalling header information contained in an MBuffer. * * \param mbuf MBuffer to read from * \param header pointer to an OmlBinaryHeader into which the data from the * mbuf should be unmarshalled * \return 1 on success, the size of the missing section as a negative number * if the buffer is too short, or 0 if something failed */ int unmarshal_init(MBuffer* mbuf, OmlBinaryHeader* header) { uint8_t header_str[PACKET_HEADER_SIZE + 2]; uint8_t stream_header_str[STREAM_HEADER_SIZE]; int result, n; OmlValue seqno; OmlValue timestamp; oml_value_init(&seqno); oml_value_init(×tamp); result = mbuf_begin_read (mbuf); if (result == -1) { logerror("Couldn't start unmarshalling packet (mbuf_begin_read())\n"); return 0; } result = mbuf_read (mbuf, header_str, 3); if (result == -1) { return mbuf_rd_remaining (mbuf) - 3; } if (! (header_str[0] == SYNC_BYTE && header_str[1] == SYNC_BYTE)) { logdebug("Cannot find sync bytes in binary stream, out of sync; first 3 bytes: %#0x %#0x %#0x\n", header_str[0], header_str[1], header_str[2]); return 0; } header->type = (OmlBinMsgType)header_str[2]; if (header->type == OMB_DATA_P) { // Read 2 more bytes of the length field uint16_t nv16 = 0; result = mbuf_read (mbuf, (uint8_t*)&nv16, sizeof (uint16_t)); if (result == -1) { n = mbuf_rd_remaining (mbuf) - 2; mbuf_reset_read (mbuf); return n; } header->length = (int)ntohs (nv16); } else if (header->type == OMB_LDATA_P) { // Read 4 more bytes of the length field uint32_t nv32 = 0; result = mbuf_read (mbuf, (uint8_t*)&nv32, sizeof (uint32_t)); if (result == -1) { n = mbuf_rd_remaining (mbuf) - 4; mbuf_reset_read (mbuf); return n; } header->length = (int)ntohl (nv32); } else { logwarn ("Unknown packet type %d\n", (int)header->type); return 0; } int extra = mbuf_rd_remaining (mbuf) - header->length; if (extra < 0) { mbuf_reset_read (mbuf); return extra; } result = mbuf_read (mbuf, stream_header_str, LENGTH (stream_header_str)); if (result == -1) { n = mbuf_rd_remaining (mbuf) - LENGTH (stream_header_str); mbuf_reset_read (mbuf); return n; } header->values = (int)stream_header_str[0]; header->stream = (int)stream_header_str[1]; if (unmarshal_typed_value (mbuf, "seq-no", OML_INT32_VALUE, &seqno) == -1) return 0; if (unmarshal_typed_value (mbuf, "timestamp", OML_DOUBLE_VALUE, ×tamp) == -1) return 0; header->seqno = omlc_get_int32(*oml_value_get_value(&seqno)); header->timestamp = omlc_get_double(*oml_value_get_value(×tamp)); oml_value_reset(&seqno); oml_value_reset(×tamp); return 1; }
/** Deep copy an OmlValue. * * \param dst OmlValue to copy to * \param src OmlValue to copy * \return 0 on success, -1 otherwise * \see oml_value_init, oml_value_set, oml_value_get_value, oml_value_get_type */ int oml_value_duplicate(OmlValue* dst, OmlValue* src) { return oml_value_set(dst, oml_value_get_value(src), oml_value_get_type(src)); }
/** Try to convert a string to the current type of OmlValue, and store it there. * * \param value pointer to output OmlValue * \param value_s input string * \return 0 on success, -1 otherwise * \see oml_value_init, oml_value_ut_from_s */ int oml_value_from_s (OmlValue *value, const char *value_s) { return oml_value_ut_from_s(oml_value_get_value(value), oml_value_get_type(value), value_s); }
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); }