static
int bt_ctf_field_sequence_validate(struct bt_ctf_field *field);
+static
+int bt_ctf_field_generic_reset(struct bt_ctf_field *field);
+static
+int bt_ctf_field_structure_reset(struct bt_ctf_field *field);
+static
+int bt_ctf_field_variant_reset(struct bt_ctf_field *field);
+static
+int bt_ctf_field_enumeration_reset(struct bt_ctf_field *field);
+static
+int bt_ctf_field_array_reset(struct bt_ctf_field *field);
+static
+int bt_ctf_field_sequence_reset(struct bt_ctf_field *field);
+static
+int bt_ctf_field_string_reset(struct bt_ctf_field *field);
+
static
int bt_ctf_field_integer_serialize(struct bt_ctf_field *,
struct ctf_stream_pos *);
[CTF_TYPE_STRING] = bt_ctf_field_generic_validate,
};
+static
+int (*field_reset_funcs[])(struct bt_ctf_field *) = {
+ [CTF_TYPE_INTEGER] = bt_ctf_field_generic_reset,
+ [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_reset,
+ [CTF_TYPE_FLOAT] = bt_ctf_field_generic_reset,
+ [CTF_TYPE_STRUCT] = bt_ctf_field_structure_reset,
+ [CTF_TYPE_VARIANT] = bt_ctf_field_variant_reset,
+ [CTF_TYPE_ARRAY] = bt_ctf_field_array_reset,
+ [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_reset,
+ [CTF_TYPE_STRING] = bt_ctf_field_string_reset,
+};
+
static
int (*field_serialize_funcs[])(struct bt_ctf_field *,
struct ctf_stream_pos *) = {
return ret;
}
+BT_HIDDEN
+int bt_ctf_field_reset(struct bt_ctf_field *field)
+{
+ int ret = 0;
+ enum ctf_type_id type_id;
+
+ if (!field) {
+ ret = -1;
+ goto end;
+ }
+
+ type_id = bt_ctf_field_type_get_type_id(field->type);
+ if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = field_reset_funcs[type_id](field);
+end:
+ return ret;
+}
+
BT_HIDDEN
int bt_ctf_field_serialize(struct bt_ctf_field *field,
struct ctf_stream_pos *pos)
return ret;
}
+static
+int bt_ctf_field_generic_reset(struct bt_ctf_field *field)
+{
+ int ret = 0;
+
+ if (!field) {
+ ret = -1;
+ goto end;
+ }
+
+ field->payload_set = 0;
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_enumeration_reset(struct bt_ctf_field *field)
+{
+ int ret = 0;
+ 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) {
+ goto end;
+ }
+
+ ret = bt_ctf_field_reset(enumeration->payload);
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_structure_reset(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++) {
+ struct bt_ctf_field *member = structure->fields->pdata[i];
+
+ if (!member) {
+ /*
+ * Structure members are lazily initialized; skip if
+ * this member has not been allocated yet.
+ */
+ continue;
+ }
+
+ ret = bt_ctf_field_reset(member);
+ if (ret) {
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_variant_reset(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);
+ if (variant->payload) {
+ ret = bt_ctf_field_reset(variant->payload);
+ }
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_array_reset(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++) {
+ struct bt_ctf_field *member = array->elements->pdata[i];
+
+ if (!member) {
+ /*
+ * Array elements are lazily initialized; skip if
+ * this member has not been allocated yet.
+ */
+ continue;
+ }
+
+ ret = bt_ctf_field_reset(member);
+ if (ret) {
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_sequence_reset(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++) {
+ struct bt_ctf_field *member = sequence->elements->pdata[i];
+
+ if (!member) {
+ /*
+ * Sequence elements are lazily initialized; skip if
+ * this member has not been allocated yet.
+ */
+ continue;
+ }
+
+ ret = bt_ctf_field_reset(member);
+ if (ret) {
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_string_reset(struct bt_ctf_field *field)
+{
+ int ret = 0;
+ struct bt_ctf_field_string *string;
+
+ if (!field) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_generic_reset(field);
+ if (ret) {
+ goto end;
+ }
+
+ string = container_of(field, struct bt_ctf_field_string, parent);
+ if (string->payload) {
+ g_string_truncate(string->payload, 0);
+ }
+end:
+ return ret;
+}
+
static
int bt_ctf_field_integer_serialize(struct bt_ctf_field *field,
struct ctf_stream_pos *pos)
struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
{
+ int ret;
struct bt_ctf_stream_class *stream_class = NULL;
if (!name || !strlen(name)) {
goto error_destroy;
}
+ ret = init_packet_context(stream_class, BT_CTF_BYTE_ORDER_NATIVE);
+ if (ret) {
+ goto error_destroy;
+ }
+
bt_ctf_ref_init(&stream_class->ref_count);
return stream_class;
return event_class;
}
+struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
+ struct bt_ctf_stream_class *stream_class)
+{
+ struct bt_ctf_field_type *ret = NULL;
+
+ if (!stream_class) {
+ goto end;
+ }
+
+ assert(stream_class->packet_context_type);
+ bt_ctf_field_type_get(stream_class->packet_context_type);
+ ret = stream_class->packet_context_type;
+end:
+ return ret;
+}
+
+int bt_ctf_stream_class_set_packet_context_type(
+ struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_field_type *packet_context_type)
+{
+ int ret = 0;
+
+ if (!stream_class || !packet_context_type) {
+ ret = -1;
+ goto end;
+ }
+
+ assert(stream_class->packet_context_type);
+ if (bt_ctf_field_type_get_type_id(stream_class->packet_context_type) !=
+ CTF_TYPE_STRUCT) {
+ /* A packet context must be a structure */
+ ret = -1;
+ goto end;
+ }
+
+ bt_ctf_field_type_put(stream_class->packet_context_type);
+ bt_ctf_field_type_get(packet_context_type);
+ stream_class->packet_context_type = packet_context_type;
+end:
+ return ret;
+}
+
void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
{
if (!stream_class) {
}
stream_class->frozen = 1;
+ bt_ctf_field_type_freeze(stream_class->packet_context_type);
bt_ctf_clock_freeze(stream_class->clock);
g_ptr_array_foreach(stream_class->event_classes,
(GFunc)bt_ctf_event_class_freeze, NULL);
{
int ret = 0;
- ret = init_packet_context(stream_class, byte_order);
- if (ret) {
- goto end;
- }
-
ret = init_event_header(stream_class, byte_order);
if (ret) {
goto end;
bt_ctf_field_type_put(stream_class->event_header_type);
bt_ctf_field_put(stream_class->event_header);
bt_ctf_field_type_put(stream_class->packet_context_type);
- bt_ctf_field_put(stream_class->packet_context);
bt_ctf_field_type_put(stream_class->event_context_type);
bt_ctf_field_put(stream_class->event_context);
g_free(stream_class);
}
stream_class->packet_context_type = packet_context_type;
- stream_class->packet_context = bt_ctf_field_create(packet_context_type);
- if (!stream_class->packet_context) {
- ret = -1;
- }
end:
if (ret) {
bt_ctf_field_type_put(packet_context_type);
struct bt_ctf_stream *bt_ctf_stream_create(
struct bt_ctf_stream_class *stream_class)
{
+ int ret;
struct bt_ctf_stream *stream = NULL;
if (!stream_class) {
}
bt_ctf_ref_init(&stream->ref_count);
+ stream->packet_context = bt_ctf_field_create(
+ stream_class->packet_context_type);
+ if (!stream->packet_context) {
+ goto error_destroy;
+ }
+
+ /* Initialize events_discarded*/
+ ret = set_structure_field_integer(stream->packet_context,
+ "events_discarded", 0);
+ if (ret) {
+ goto error_destroy;
+ }
+
stream->pos.fd = -1;
stream->id = stream_class->next_stream_id++;
stream->stream_class = stream_class;
(GDestroyNotify)bt_ctf_event_put);
end:
return stream;
+error_destroy:
+ bt_ctf_stream_destroy(&stream->ref_count);
+ return NULL;
}
BT_HIDDEN
struct bt_ctf_stream *stream, uint64_t *count)
{
int64_t ret = 0;
+ int field_signed;
+ struct bt_ctf_field *events_discarded_field = NULL;
+ struct bt_ctf_field_type *events_discarded_field_type = NULL;
- if (!stream || !count) {
+ if (!stream || !count || !stream->packet_context) {
ret = -1;
goto end;
}
- *count = stream->events_discarded;
+ events_discarded_field = bt_ctf_field_structure_get_field(
+ stream->packet_context, "events_discarded");
+ if (!events_discarded_field) {
+ ret = -1;
+ goto end;
+ }
+
+ events_discarded_field_type = bt_ctf_field_get_type(
+ events_discarded_field);
+ if (!events_discarded_field_type) {
+ ret = -1;
+ goto end;
+ }
+
+ field_signed = bt_ctf_field_type_integer_get_signed(
+ events_discarded_field_type);
+ if (field_signed < 0) {
+ ret = field_signed;
+ goto end;
+ }
+
+ if (field_signed) {
+ int64_t signed_count;
+
+ ret = bt_ctf_field_signed_integer_get_value(
+ events_discarded_field, &signed_count);
+ if (ret) {
+ goto end;
+ }
+ if (signed_count < 0) {
+ /* Invalid value */
+ ret = -1;
+ goto end;
+ }
+ *count = (uint64_t) signed_count;
+ } else {
+ ret = bt_ctf_field_unsigned_integer_get_value(
+ events_discarded_field, count);
+ if (ret) {
+ goto end;
+ }
+ }
end:
+ if (events_discarded_field) {
+ bt_ctf_field_put(events_discarded_field);
+ }
+ if (events_discarded_field_type) {
+ bt_ctf_field_type_put(events_discarded_field_type);
+ }
return ret;
}
void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
uint64_t event_count)
{
- if (!stream) {
- return;
+ int ret;
+ int field_signed;
+ uint64_t previous_count;
+ uint64_t new_count;
+ struct bt_ctf_field *events_discarded_field = NULL;
+ struct bt_ctf_field_type *events_discarded_field_type = NULL;
+
+ if (!stream || !stream->packet_context) {
+ goto end;
+ }
+
+ ret = bt_ctf_stream_get_discarded_events_count(stream,
+ &previous_count);
+ if (ret) {
+ goto end;
+ }
+
+ events_discarded_field = bt_ctf_field_structure_get_field(
+ stream->packet_context, "events_discarded");
+ if (!events_discarded_field) {
+ goto end;
+ }
+
+ events_discarded_field_type = bt_ctf_field_get_type(
+ events_discarded_field);
+ if (!events_discarded_field_type) {
+ goto end;
+ }
+
+ field_signed = bt_ctf_field_type_integer_get_signed(
+ events_discarded_field_type);
+ if (field_signed < 0) {
+ goto end;
}
- stream->events_discarded += event_count;
+ new_count = previous_count + event_count;
+ if (field_signed) {
+ ret = bt_ctf_field_signed_integer_set_value(
+ events_discarded_field, (int64_t) new_count);
+ if (ret) {
+ goto end;
+ }
+ } else {
+ ret = bt_ctf_field_unsigned_integer_set_value(
+ events_discarded_field, new_count);
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ if (events_discarded_field) {
+ bt_ctf_field_put(events_discarded_field);
+ }
+ if (events_discarded_field_type) {
+ bt_ctf_field_type_put(events_discarded_field_type);
+ }
}
int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
return ret;
}
+struct bt_ctf_field *bt_ctf_stream_get_packet_context(
+ struct bt_ctf_stream *stream)
+{
+ struct bt_ctf_field *packet_context = NULL;
+
+ if (!stream) {
+ goto end;
+ }
+
+ packet_context = stream->packet_context;
+end:
+ if (packet_context) {
+ bt_ctf_field_get(packet_context);
+ }
+ return packet_context;
+}
+
+int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
+ struct bt_ctf_field *field)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *field_type;
+
+ if (!stream || !field) {
+ ret = -1;
+ goto end;
+ }
+
+ field_type = bt_ctf_field_get_type(field);
+ if (field_type != stream->stream_class->packet_context_type) {
+ ret = -1;
+ goto end;
+ }
+
+ bt_ctf_field_type_put(field_type);
+ bt_ctf_field_get(field);
+ bt_ctf_field_put(stream->packet_context);
+ stream->packet_context = field;
+end:
+ return ret;
+}
+
int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
{
int ret = 0;
size_t i;
- uint64_t timestamp_begin, timestamp_end;
+ uint64_t timestamp_begin, timestamp_end, events_discarded;
struct bt_ctf_stream_class *stream_class;
struct bt_ctf_field *integer = NULL;
struct ctf_stream_pos packet_context_pos;
stream->events, 0))->timestamp;
timestamp_end = ((struct bt_ctf_event *) g_ptr_array_index(
stream->events, stream->events->len - 1))->timestamp;
- ret = set_structure_field_integer(stream_class->packet_context,
+
+ /* Set the default context attributes if present and unset. */
+ ret = set_structure_field_integer(stream->packet_context,
"timestamp_begin", timestamp_begin);
if (ret) {
goto end;
}
- ret = set_structure_field_integer(stream_class->packet_context,
+ ret = set_structure_field_integer(stream->packet_context,
"timestamp_end", timestamp_end);
if (ret) {
goto end;
}
- ret = set_structure_field_integer(stream_class->packet_context,
- "events_discarded", stream->events_discarded);
- if (ret) {
- goto end;
- }
-
- ret = set_structure_field_integer(stream_class->packet_context,
+ ret = set_structure_field_integer(stream->packet_context,
"content_size", UINT64_MAX);
if (ret) {
goto end;
}
- ret = set_structure_field_integer(stream_class->packet_context,
+ 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_class->packet_context,
+ 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);
event->event_class);
uint64_t timestamp = bt_ctf_event_get_timestamp(event);
+ ret = bt_ctf_field_reset(stream_class->event_header);
+ if (ret) {
+ goto end;
+ }
+
ret = set_structure_field_integer(stream_class->event_header,
"id", event_id);
if (ret) {
* packet is resized).
*/
packet_context_pos.base_mma = stream->pos.base_mma;
- ret = set_structure_field_integer(stream_class->packet_context,
+ ret = set_structure_field_integer(stream->packet_context,
"content_size", stream->pos.offset);
if (ret) {
goto end;
}
- ret = set_structure_field_integer(stream_class->packet_context,
+ ret = set_structure_field_integer(stream->packet_context,
"packet_size", stream->pos.packet_size);
if (ret) {
goto end;
}
- ret = bt_ctf_field_serialize(stream_class->packet_context,
+ ret = bt_ctf_field_serialize(stream->packet_context,
&packet_context_pos);
if (ret) {
goto end;
if (close(stream->pos.fd)) {
perror("close");
}
- bt_ctf_stream_class_put(stream->stream_class);
- g_ptr_array_free(stream->events, TRUE);
+
+ if (stream->stream_class) {
+ bt_ctf_stream_class_put(stream->stream_class);
+ }
+ if (stream->events) {
+ g_ptr_array_free(stream->events, TRUE);
+ }
+ if (stream->packet_context) {
+ bt_ctf_field_put(stream->packet_context);
+ }
g_free(stream);
}
uint64_t value)
{
int ret = 0;
-
struct bt_ctf_field *integer =
bt_ctf_field_structure_get_field(structure, name);
- if (!integer) {
+
+ 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;
+ }
+
ret = bt_ctf_field_unsigned_integer_set_value(integer, value);
end:
bt_ctf_field_put(integer);
goto error;
}
+ ret = bt_ctf_stream_class_set_byte_order(stream_class,
+ writer->byte_order == LITTLE_ENDIAN ?
+ BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN);
+ if (ret) {
+ goto error;
+ }
+
stream = bt_ctf_stream_create(stream_class);
if (!stream) {
goto error;
bt_ctf_stream_set_flush_callback(stream, (flush_func)stream_flush_cb,
writer);
- ret = bt_ctf_stream_class_set_byte_order(stream->stream_class,
- writer->byte_order == LITTLE_ENDIAN ?
- BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN);
- if (ret) {
- goto error;
- }
-
for (i = 0; i < writer->stream_classes->len; i++) {
if (writer->stream_classes->pdata[i] == stream->stream_class) {
int bt_ctf_field_structure_set_field(struct bt_ctf_field *structure,
const char *name, struct bt_ctf_field *value);
+/* Validate that the field's payload is set. */
BT_HIDDEN
int bt_ctf_field_validate(struct bt_ctf_field *field);
+/* Mark field payload as unset. */
+BT_HIDDEN
+int bt_ctf_field_reset(struct bt_ctf_field *field);
+
BT_HIDDEN
int bt_ctf_field_serialize(struct bt_ctf_field *field,
struct ctf_stream_pos *pos);
struct bt_ctf_field_type *event_header_type;
struct bt_ctf_field *event_header;
struct bt_ctf_field_type *packet_context_type;
- struct bt_ctf_field *packet_context;
struct bt_ctf_field_type *event_context_type;
struct bt_ctf_field *event_context;
int frozen;
* Allocate a new stream class of the given name. The creation of an event class
* sets its reference count to 1.
*
+ * A stream class' packet context is a structure initialized with the following
+ * fields:
+ * - uint64_t timestamp_begin
+ * - uint64_t timestamp_end
+ * - uint64_t content_size
+ * - uint64_t packet_size
+ * - uint64_t events_discarded
+ *
* @param name Stream name.
*
* Returns an allocated stream class on success, NULL on error.
extern struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_name(
struct bt_ctf_stream_class *stream_class, const char *name);
+/*
+ * bt_ctf_stream_class_get_packet_context_type: get the stream class' packet
+ * context type.
+ *
+ * @param stream_class Stream class.
+ *
+ * Returns the packet context's type, NULL on error.
+ */
+extern struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
+ struct bt_ctf_stream_class *stream_class);
+
+/*
+ * bt_ctf_stream_class_set_packet_context_type: set the stream class' packet
+ * context type.
+ *
+ * @param stream_class Stream class.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_stream_class_set_packet_context_type(
+ struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_field_type *packet_context_type);
+
/*
* bt_ctf_stream_class_get and bt_ctf_stream_class_put: increment and
* decrement the stream class' reference count.
GPtrArray *events;
struct ctf_stream_pos pos;
unsigned int flushed_packet_count;
- uint64_t events_discarded;
+ struct bt_ctf_field *packet_context;
};
BT_HIDDEN
* bt_ctf_stream_get_discarded_events_count: get the number of discarded
* events associated with this stream.
*
+ * Note that discarded events are not stored if the stream's packet
+ * context has no "events_discarded" field. An error will be returned
+ * in that case.
+ *
* @param stream Stream instance.
*
* Returns the number of discarded events, a negative value on error.
/*
* bt_ctf_stream_append_discarded_events: increment discarded events count.
*
- * Increase the current packet's discarded event count.
+ * Increase the current packet's discarded event count. Has no effect if the
+ * stream class' packet context has no "events_discarded" field.
*
* @param stream Stream instance.
* @param event_count Number of discarded events to add to the stream's current
extern int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
struct bt_ctf_event *event);
+/*
+ * bt_ctf_stream_get_packet_context: get a stream's packet context.
+ *
+ * @param stream Stream instance.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern struct bt_ctf_field *bt_ctf_stream_get_packet_context(
+ struct bt_ctf_stream *stream);
+
+/*
+ * bt_ctf_stream_set_packet_context: set a stream's packet context.
+ *
+ * The packet context's type must match the stream class' packet
+ * context type.
+ *
+ * @param stream Stream instance.
+ * @param packet_context Packet context field instance.
+ *
+ * Returns a field instance on success, NULL on error.
+ */
+extern int bt_ctf_stream_set_packet_context(
+ struct bt_ctf_stream *stream,
+ struct bt_ctf_field *packet_context);
+
/*
* bt_ctf_stream_flush: flush a stream.
*
- * The stream's current packet's events will be flushed to disk. Events
- * subsequently appended to the stream will be added to a new packet.
+ * The stream's current packet's events will be flushed, thus closing the
+ * current packet. Events subsequently appended to the stream will be
+ * added to a new packet.
+ *
+ * Flushing will also set the packet context's default attributes if
+ * they remained unset while populating the current packet. These default
+ * attributes, along with their expected types, are detailed in stream-class.h.
*
* @param stream Stream instance.
*
uint64_t ret_range_start_uint64_t, ret_range_end_uint64_t;
struct bt_ctf_clock *ret_clock;
struct bt_ctf_event_class *ret_event_class;
+ struct bt_ctf_field *packet_context;
+ struct bt_ctf_field *packet_context_field;
ok(uint_12_type, "Create an unsigned integer type");
ok(bt_ctf_stream_append_event(stream, simple_event) == 0,
"Append simple event to trace stream");
+ ok(bt_ctf_stream_get_packet_context(NULL) == NULL,
+ "bt_ctf_stream_get_packet_context handles NULL correctly");
+ packet_context = bt_ctf_stream_get_packet_context(stream);
+ ok(packet_context,
+ "bt_ctf_stream_get_packet_context returns a packet context");
+
+ packet_context_field = bt_ctf_field_structure_get_field(packet_context,
+ "packet_size");
+ ok(packet_context_field,
+ "Packet context contains the default packet_size field.");
+ bt_ctf_field_put(packet_context_field);
+ packet_context_field = bt_ctf_field_structure_get_field(packet_context,
+ "custom_field");
+ ok(bt_ctf_field_unsigned_integer_set_value(packet_context_field, 8) == 0,
+ "Custom packet context field value successfully set.");
+
+ ok(bt_ctf_stream_set_packet_context(NULL, packet_context_field) < 0,
+ "bt_ctf_stream_set_packet_context handles a NULL stream correctly");
+ ok(bt_ctf_stream_set_packet_context(stream, NULL) < 0,
+ "bt_ctf_stream_set_packet_context handles a NULL packet context correctly");
+ ok(bt_ctf_stream_set_packet_context(stream, packet_context) == 0,
+ "Successfully set a stream's packet context");
+
ok(bt_ctf_stream_flush(stream) == 0,
"Flush trace stream with one event");
bt_ctf_field_put(enum_field_unsigned);
bt_ctf_field_put(enum_container_field);
bt_ctf_field_put(enum_container_field_unsigned);
+ bt_ctf_field_put(packet_context);
+ bt_ctf_field_put(packet_context_field);
}
void append_complex_event(struct bt_ctf_stream_class *stream_class,
size_t ret_size_t;
struct bt_ctf_stream_class *ret_stream_class;
struct bt_ctf_event_class *ret_event_class;
+ struct bt_ctf_field *packet_context, *packet_context_field;
bt_ctf_field_type_set_alignment(int_16_type, 32);
bt_ctf_field_type_integer_set_signed(int_16_type, 1);
bt_ctf_clock_set_time(clock, ++current_time);
ok(bt_ctf_stream_append_event(stream, event) == 0,
"Append a complex event to a stream");
+
+ /*
+ * Populate the custom packet context field with a dummy value
+ * otherwise flush will fail.
+ */
+ packet_context = bt_ctf_stream_get_packet_context(stream);
+ packet_context_field = bt_ctf_field_structure_get_field(packet_context,
+ "custom_field");
+ bt_ctf_field_unsigned_integer_set_value(packet_context_field, 1);
+
ok(bt_ctf_stream_flush(stream) == 0,
"Flush a stream containing a complex event");
bt_ctf_field_put(enum_container_field);
bt_ctf_field_put(variant_field);
bt_ctf_field_put(ret_field);
+ bt_ctf_field_put(packet_context_field);
+ bt_ctf_field_put(packet_context);
bt_ctf_field_type_put(uint_35_type);
bt_ctf_field_type_put(int_16_type);
bt_ctf_field_type_put(string_type);
struct bt_ctf_field *ret_field;
struct bt_ctf_field_type *ret_field_type;
uint64_t ret_uint64;
+ int events_appended = 0;
+ struct bt_ctf_field *packet_context, *packet_context_field;
ret |= bt_ctf_event_class_add_field(event_class, integer_type,
"field_1");
break;
}
}
-
+
+ events_appended = 1;
ok(bt_ctf_stream_get_discarded_events_count(NULL, &ret_uint64) == -1,
"bt_ctf_stream_get_discarded_events_count handles a NULL stream correctly");
ok(bt_ctf_stream_get_discarded_events_count(stream, NULL) == -1,
"bt_ctf_stream_get_discarded_events_count returns a correct number of discarded events when some were discarded");
end:
- ok(ret == 0, "Append 100 000 events to a stream");
+ ok(events_appended, "Append 100 000 events to a stream");
+
+ /*
+ * Populate the custom packet context field with a dummy value
+ * otherwise flush will fail.
+ */
+ packet_context = bt_ctf_stream_get_packet_context(stream);
+ packet_context_field = bt_ctf_field_structure_get_field(packet_context,
+ "custom_field");
+ bt_ctf_field_unsigned_integer_set_value(packet_context_field, 2);
+
ok(bt_ctf_stream_flush(stream) == 0,
"Flush a stream that forces a packet resize");
ret = bt_ctf_stream_get_discarded_events_count(stream, &ret_uint64);
"bt_ctf_stream_get_discarded_events_count returns a correct number of discarded events after a flush");
bt_ctf_field_type_put(integer_type);
bt_ctf_field_type_put(string_type);
+ bt_ctf_field_put(packet_context);
+ bt_ctf_field_put(packet_context_field);
bt_ctf_event_class_put(event_class);
}
struct bt_ctf_stream_class *stream_class;
struct bt_ctf_stream *stream1;
const char *ret_string;
+ struct bt_ctf_field_type *packet_context_type, *packet_context_field_type;
+ int ret;
if (argc < 3) {
printf("Usage: tests-ctf-writer path_to_ctf_parser_test path_to_babeltrace\n");
"bt_ctf_stream_class_get_name handles NULL correctly");
ret_string = bt_ctf_stream_class_get_name(stream_class);
ok(!strcmp(ret_string, "test_stream"),
- "bt_ctf_stream_class_get_name returns a correct stream class name");
+ "bt_ctf_stream_class_get_name returns a correct stream class name");
ok(bt_ctf_stream_class_get_clock(stream_class) == NULL,
"bt_ctf_stream_class_get_clock returns NULL when a clock was not set");
ok(bt_ctf_stream_class_get_id(stream_class) == 123,
"bt_ctf_stream_class_get_id returns the correct value");
+ /* Create a "uint5_t" equivalent custom packet context field */
+ packet_context_field_type = bt_ctf_field_type_integer_create(5);
+
+ ok(bt_ctf_stream_class_get_packet_context_type(NULL) == NULL,
+ "bt_ctf_stream_class_get_packet_context_type handles NULL correctly");
+
+ /* Add a custom field to the stream class' packet context */
+ packet_context_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
+ ok(packet_context_type,
+ "bt_ctf_stream_class_get_packet_context_type returns a packet context type.");
+ ok(bt_ctf_field_type_get_type_id(packet_context_type) == CTF_TYPE_STRUCT,
+ "Packet context is a structure");
+
+ ok(bt_ctf_stream_class_set_packet_context_type(NULL, packet_context_type),
+ "bt_ctf_stream_class_set_packet_context_type handles a NULL stream class correctly");
+ ok(bt_ctf_stream_class_set_packet_context_type(stream_class, NULL),
+ "bt_ctf_stream_class_set_packet_context_type handles a NULL packet context type correctly");
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ packet_context_field_type, "custom_field");
+ ok(ret == 0, "Packet context field added successfully");
+
+
/* Instantiate a stream and append events */
stream1 = bt_ctf_writer_create_stream(writer, stream_class);
ok(stream1, "Instanciate a stream class from writer");
+ /*
+ * Try to modify the packet context type after a stream has been
+ * created.
+ */
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ packet_context_field_type, "should_fail");
+ ok(ret < 0,
+ "Packet context type can't be modified once a stream class has been instanciated");
+
/* Should fail after instanciating a stream (locked)*/
ok(bt_ctf_stream_class_set_clock(stream_class, clock),
"Changes to a stream class that was already instantiated fail");
bt_ctf_stream_class_put(stream_class);
bt_ctf_writer_put(writer);
bt_ctf_stream_put(stream1);
+ bt_ctf_field_type_put(packet_context_type);
+ bt_ctf_field_type_put(packet_context_field_type);
free(metadata_string);
/* Remove all trace files and delete temporary trace directory */