struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field, struct bt_ctf_field *tag_field) { struct bt_ctf_field *new_field = NULL; struct bt_ctf_field_variant *variant; struct bt_ctf_field_type_variant *variant_type; struct bt_ctf_field_type *field_type; struct bt_ctf_field *tag_enum = NULL; struct bt_ctf_field_integer *tag_enum_integer; int64_t tag_enum_value; if (!field || !tag_field || bt_ctf_field_type_get_type_id(field->type) != CTF_TYPE_VARIANT || bt_ctf_field_type_get_type_id(tag_field->type) != CTF_TYPE_ENUM) { goto end; } variant = container_of(field, struct bt_ctf_field_variant, parent); variant_type = container_of(field->type, struct bt_ctf_field_type_variant, parent); tag_enum = bt_ctf_field_enumeration_get_container(tag_field); if (!tag_enum) { goto end; } tag_enum_integer = container_of(tag_enum, struct bt_ctf_field_integer, parent); if (!bt_ctf_field_validate(variant->tag)) { goto end; } tag_enum_value = tag_enum_integer->definition.value._signed; field_type = bt_ctf_field_type_variant_get_field_type_signed( variant_type, tag_enum_value); if (!field_type) { goto end; } new_field = bt_ctf_field_create(field_type); if (!new_field) { goto end; } bt_ctf_field_put(variant->tag); bt_ctf_field_put(variant->payload); bt_ctf_field_get(new_field); bt_ctf_field_get(tag_field); variant->tag = tag_field; variant->payload = new_field; end: bt_ctf_field_put(tag_enum); return new_field; }
int bt_ctf_stream_append_event(struct bt_ctf_stream *stream, struct bt_ctf_event *event) { int ret = 0; struct bt_ctf_field *event_context_copy = NULL; if (!stream || !event) { ret = -1; goto end; } ret = bt_ctf_event_set_stream(event, stream); if (ret) { /* Event was already associated to a stream */ ret = -1; goto end; } ret = bt_ctf_event_populate_event_header(event); if (ret) { goto end; } /* Make sure the event's payload is set */ ret = bt_ctf_event_validate(event); if (ret) { goto end; } /* Sample the current stream event context by copying it */ if (stream->event_context) { /* Make sure the event context's payload is set */ ret = bt_ctf_field_validate(stream->event_context); if (ret) { goto end; } event_context_copy = bt_ctf_field_copy(stream->event_context); if (!event_context_copy) { ret = -1; goto end; } } bt_get(event); /* Save the new event along with its associated stream event context */ g_ptr_array_add(stream->events, event); if (event_context_copy) { g_ptr_array_add(stream->event_contexts, event_context_copy); } end: if (ret) { (void) bt_ctf_event_set_stream(event, NULL); } return ret; }
BT_HIDDEN int bt_ctf_event_validate(struct bt_ctf_event *event) { /* Make sure each field's payload has been set */ int ret; struct bt_ctf_stream_class *stream_class = NULL; assert(event); ret = bt_ctf_field_validate(event->event_header); if (ret) { goto end; } stream_class = bt_ctf_event_class_get_stream_class(event->event_class); /* * We should not have been able to create the event without associating * the event class to a stream class. */ assert(stream_class); if (stream_class->event_context_type) { ret = bt_ctf_field_validate(event->stream_event_context); if (ret) { goto end; } } ret = bt_ctf_field_validate(event->fields_payload); if (ret) { goto end; } if (event->event_class->context) { ret = bt_ctf_field_validate(event->context_payload); } end: bt_put(stream_class); return ret; }
static int set_structure_field_integer(struct bt_ctf_field *structure, char *name, uint64_t value) { int ret = 0; struct bt_ctf_field_type *field_type = NULL; struct bt_ctf_field *integer = bt_ctf_field_structure_get_field(structure, name); if (!structure || !name) { ret = -1; goto end; } if (!integer) { /* Field not found, not an error. */ goto end; } /* Make sure the payload has not already been set. */ if (!bt_ctf_field_validate(integer)) { /* Payload already set, not an error */ goto end; } field_type = bt_ctf_field_get_type(integer); /* Something is serioulsly wrong */ assert(field_type); if (bt_ctf_field_type_get_type_id(field_type) != CTF_TYPE_INTEGER) { /* * The user most likely meant for us to populate this field * automatically. However, we can only do this if the field * is an integer. Return an error. */ ret = -1; goto end; } if (bt_ctf_field_type_integer_get_signed(field_type)) { ret = bt_ctf_field_signed_integer_set_value(integer, (int64_t) value); } else { ret = bt_ctf_field_unsigned_integer_set_value(integer, value); } end: bt_put(integer); bt_put(field_type); return ret; }
static int set_packet_header_magic(struct bt_ctf_stream *stream) { int ret = 0; struct bt_ctf_field_type *magic_field_type = NULL; struct bt_ctf_field *magic_field = bt_ctf_field_structure_get_field( stream->packet_header, "magic"); if (!magic_field) { /* No magic field found. Not an error, skip. */ goto end; } if (!bt_ctf_field_validate(magic_field)) { /* Value already set. Not an error, skip. */ goto end; } magic_field_type = bt_ctf_field_get_type(magic_field); assert(magic_field_type); if (bt_ctf_field_type_get_type_id(magic_field_type) != CTF_TYPE_INTEGER) { /* Magic field is not an integer. Not an error, skip. */ goto end; } if (bt_ctf_field_type_integer_get_size(magic_field_type) != 32) { /* * Magic field is not of the expected size. * Not an error, skip. */ goto end; } ret = bt_ctf_field_type_integer_get_signed(magic_field_type); assert(ret >= 0); if (ret) { ret = bt_ctf_field_signed_integer_set_value(magic_field, (int64_t) 0xC1FC1FC1); } else { ret = bt_ctf_field_unsigned_integer_set_value(magic_field, (uint64_t) 0xC1FC1FC1); } end: bt_put(magic_field); bt_put(magic_field_type); return ret; }
static int bt_ctf_field_variant_validate(struct bt_ctf_field *field) { int ret = 0; struct bt_ctf_field_variant *variant; if (!field) { ret = -1; goto end; } variant = container_of(field, struct bt_ctf_field_variant, parent); ret = bt_ctf_field_validate(variant->payload); end: return ret; }
static int set_integer_field_value(struct bt_ctf_field* field, uint64_t value) { int ret = 0; struct bt_ctf_field_type *field_type = NULL; if (!field) { ret = -1; goto end; } if (!bt_ctf_field_validate(field)) { /* Payload already set, skip! (not an error) */ goto end; } field_type = bt_ctf_field_get_type(field); assert(field_type); if (bt_ctf_field_type_get_type_id(field_type) != CTF_TYPE_INTEGER) { /* Not an integer and the value is unset, error. */ ret = -1; goto end; } if (bt_ctf_field_type_integer_get_signed(field_type)) { ret = bt_ctf_field_signed_integer_set_value(field, (int64_t) value); if (ret) { /* Value is out of range, error. */ goto end; } } else { ret = bt_ctf_field_unsigned_integer_set_value(field, value); if (ret) { /* Value is out of range, error. */ goto end; } } end: bt_put(field_type); return ret; }
static int set_packet_header_stream_id(struct bt_ctf_stream *stream) { int ret = 0; uint32_t stream_id; struct bt_ctf_field_type *stream_id_field_type = NULL; struct bt_ctf_field *stream_id_field = bt_ctf_field_structure_get_field( stream->packet_header, "stream_id"); if (!stream_id_field) { /* No stream_id field found. Not an error, skip. */ goto end; } if (!bt_ctf_field_validate(stream_id_field)) { /* Value already set. Not an error, skip. */ goto end; } stream_id_field_type = bt_ctf_field_get_type(stream_id_field); assert(stream_id_field_type); if (bt_ctf_field_type_get_type_id(stream_id_field_type) != CTF_TYPE_INTEGER) { /* stream_id field is not an integer. Not an error, skip. */ goto end; } stream_id = stream->stream_class->id; ret = bt_ctf_field_type_integer_get_signed(stream_id_field_type); assert(ret >= 0); if (ret) { ret = bt_ctf_field_signed_integer_set_value(stream_id_field, (int64_t) stream_id); } else { ret = bt_ctf_field_unsigned_integer_set_value(stream_id_field, (uint64_t) stream_id); } end: bt_put(stream_id_field); bt_put(stream_id_field_type); return ret; }
static int bt_ctf_field_sequence_validate(struct bt_ctf_field *field) { size_t i; int ret = 0; struct bt_ctf_field_sequence *sequence; if (!field) { ret = -1; goto end; } sequence = container_of(field, struct bt_ctf_field_sequence, parent); for (i = 0; i < sequence->elements->len; i++) { ret = bt_ctf_field_validate(sequence->elements->pdata[i]); if (ret) { goto end; } } end: return ret; }
static int bt_ctf_field_array_validate(struct bt_ctf_field *field) { size_t i; int ret = 0; struct bt_ctf_field_array *array; if (!field) { ret = -1; goto end; } array = container_of(field, struct bt_ctf_field_array, parent); for (i = 0; i < array->elements->len; i++) { ret = bt_ctf_field_validate(array->elements->pdata[i]); if (ret) { goto end; } } end: return ret; }
static int bt_ctf_field_structure_validate(struct bt_ctf_field *field) { size_t i; int ret = 0; struct bt_ctf_field_structure *structure; if (!field) { ret = -1; goto end; } structure = container_of(field, struct bt_ctf_field_structure, parent); for (i = 0; i < structure->fields->len; i++) { ret = bt_ctf_field_validate(structure->fields->pdata[i]); if (ret) { goto end; } } end: return ret; }
static int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field) { int ret; struct bt_ctf_field_enumeration *enumeration; if (!field) { ret = -1; goto end; } enumeration = container_of(field, struct bt_ctf_field_enumeration, parent); if (!enumeration->payload) { ret = -1; goto end; } ret = bt_ctf_field_validate(enumeration->payload); end: return ret; }
static int set_packet_header_uuid(struct bt_ctf_stream *stream) { int i, ret = 0; struct bt_ctf_field_type *uuid_field_type = NULL; struct bt_ctf_field_type *element_field_type = NULL; struct bt_ctf_field *uuid_field = bt_ctf_field_structure_get_field( stream->packet_header, "uuid"); if (!uuid_field) { /* No uuid field found. Not an error, skip. */ goto end; } if (!bt_ctf_field_validate(uuid_field)) { /* Value already set. Not an error, skip. */ goto end; } uuid_field_type = bt_ctf_field_get_type(uuid_field); assert(uuid_field_type); if (bt_ctf_field_type_get_type_id(uuid_field_type) != CTF_TYPE_ARRAY) { /* UUID field is not an array. Not an error, skip. */ goto end; } if (bt_ctf_field_type_array_get_length(uuid_field_type) != 16) { /* * UUID field is not of the expected size. * Not an error, skip. */ goto end; } element_field_type = bt_ctf_field_type_array_get_element_type( uuid_field_type); assert(element_field_type); if (bt_ctf_field_type_get_type_id(element_field_type) != CTF_TYPE_INTEGER) { /* UUID array elements are not integers. Not an error, skip */ goto end; } for (i = 0; i < 16; i++) { struct bt_ctf_field *uuid_element = bt_ctf_field_array_get_field(uuid_field, i); ret = bt_ctf_field_type_integer_get_signed(element_field_type); assert(ret >= 0); if (ret) { ret = bt_ctf_field_signed_integer_set_value( uuid_element, (int64_t) stream->trace->uuid[i]); } else { ret = bt_ctf_field_unsigned_integer_set_value( uuid_element, (uint64_t) stream->trace->uuid[i]); } bt_put(uuid_element); if (ret) { goto end; } } end: bt_put(uuid_field); bt_put(uuid_field_type); bt_put(element_field_type); return ret; }
int bt_ctf_stream_flush(struct bt_ctf_stream *stream) { int ret = 0; size_t i; uint64_t timestamp_begin, timestamp_end, events_discarded; struct bt_ctf_field *integer = NULL; struct ctf_stream_pos packet_context_pos; if (!stream || stream->pos.fd < 0) { /* * Stream does not have an associated fd. It is, * therefore, not a stream being used to write events. */ ret = -1; goto end; } if (!stream->events->len) { goto end; } ret = bt_ctf_field_validate(stream->packet_header); if (ret) { goto end; } /* mmap the next packet */ ctf_packet_seek(&stream->pos.parent, 0, SEEK_CUR); ret = bt_ctf_field_serialize(stream->packet_header, &stream->pos); if (ret) { goto end; } /* Set the default context attributes if present and unset. */ if (!get_event_header_timestamp( ((struct bt_ctf_event *) g_ptr_array_index( stream->events, 0))->event_header, ×tamp_begin)) { ret = set_structure_field_integer(stream->packet_context, "timestamp_begin", timestamp_begin); if (ret) { goto end; } } if (!get_event_header_timestamp( ((struct bt_ctf_event *) g_ptr_array_index( stream->events, stream->events->len - 1))->event_header, ×tamp_end)) { ret = set_structure_field_integer(stream->packet_context, "timestamp_end", timestamp_end); if (ret) { goto end; } } ret = set_structure_field_integer(stream->packet_context, "content_size", UINT64_MAX); if (ret) { goto end; } ret = set_structure_field_integer(stream->packet_context, "packet_size", UINT64_MAX); if (ret) { goto end; } /* Write packet context */ memcpy(&packet_context_pos, &stream->pos, sizeof(struct ctf_stream_pos)); ret = bt_ctf_field_serialize(stream->packet_context, &stream->pos); if (ret) { goto end; } ret = bt_ctf_stream_get_discarded_events_count(stream, &events_discarded); if (ret) { goto end; } /* Unset the packet context's fields. */ ret = bt_ctf_field_reset(stream->packet_context); if (ret) { goto end; } /* Set the previous number of discarded events. */ ret = set_structure_field_integer(stream->packet_context, "events_discarded", events_discarded); if (ret) { goto end; } for (i = 0; i < stream->events->len; i++) { struct bt_ctf_event *event = g_ptr_array_index( stream->events, i); ret = bt_ctf_field_reset(event->event_header); if (ret) { goto end; } /* Write event header */ ret = bt_ctf_field_serialize(event->event_header, &stream->pos); if (ret) { goto end; } /* Write stream event context */ if (stream->event_contexts) { ret = bt_ctf_field_serialize( g_ptr_array_index(stream->event_contexts, i), &stream->pos); if (ret) { goto end; } } /* Write event content */ ret = bt_ctf_event_serialize(event, &stream->pos); if (ret) { goto end; } } /* * Update the packet total size and content size and overwrite the * packet context. * Copy base_mma as the packet may have been remapped (e.g. when a * packet is resized). */ packet_context_pos.base_mma = stream->pos.base_mma; ret = set_structure_field_integer(stream->packet_context, "content_size", stream->pos.offset); if (ret) { goto end; } ret = set_structure_field_integer(stream->packet_context, "packet_size", stream->pos.packet_size); if (ret) { goto end; } ret = bt_ctf_field_serialize(stream->packet_context, &packet_context_pos); if (ret) { goto end; } g_ptr_array_set_size(stream->events, 0); if (stream->event_contexts) { g_ptr_array_set_size(stream->event_contexts, 0); } stream->flushed_packet_count++; end: bt_put(integer); return ret; }