Add stream packet header accessors
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 29 Jul 2014 20:51:51 +0000 (16:51 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 29 Jul 2014 21:52:28 +0000 (17:52 -0400)
Stream packet contexts may now be modified to contain custom
fields. The events_discarded field is now handled like a generic
packet context field.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
formats/ctf/ir/event-fields.c
formats/ctf/ir/stream-class.c
formats/ctf/ir/stream.c
formats/ctf/writer/writer.c
include/babeltrace/ctf-ir/event-fields-internal.h
include/babeltrace/ctf-ir/stream-class-internal.h
include/babeltrace/ctf-ir/stream-class.h
include/babeltrace/ctf-ir/stream-internal.h
include/babeltrace/ctf-ir/stream.h
tests/lib/test_ctf_writer.c

index ed2cf489fc4e82b535c27885793afe8ecb30ee57..14fade72cb41d88e8f4c231e6dfcf8fb153f7c49 100644 (file)
@@ -88,6 +88,21 @@ int bt_ctf_field_array_validate(struct bt_ctf_field *field);
 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 *);
@@ -155,6 +170,18 @@ int (*field_validate_funcs[])(struct bt_ctf_field *) = {
        [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 *) = {
@@ -883,6 +910,28 @@ end:
        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)
@@ -1297,6 +1346,185 @@ end:
        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)
index 5cd572fe659bd3ea329296fc4fdb871f0e98090e..10095a2ce6053b9accc6998e3b8b00074caa50fa 100644 (file)
@@ -49,6 +49,7 @@ int init_packet_context(struct bt_ctf_stream_class *stream_class,
 
 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)) {
@@ -67,6 +68,11 @@ struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *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;
 
@@ -257,6 +263,48 @@ end:
        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) {
@@ -283,6 +331,7 @@ void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *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);
@@ -294,11 +343,6 @@ int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
 {
        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;
@@ -395,7 +439,6 @@ void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref)
        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);
@@ -511,10 +554,6 @@ int init_packet_context(struct bt_ctf_stream_class *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);
index e618251e577a3d6e5614b475faa8b1d30c926385..9b0be90b7b2e97ad96f36e670060cb51192e33a9 100644 (file)
@@ -48,6 +48,7 @@ BT_HIDDEN
 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) {
@@ -60,6 +61,19 @@ struct bt_ctf_stream *bt_ctf_stream_create(
        }
 
        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;
@@ -69,6 +83,9 @@ struct bt_ctf_stream *bt_ctf_stream_create(
                (GDestroyNotify)bt_ctf_event_put);
 end:
        return stream;
+error_destroy:
+       bt_ctf_stream_destroy(&stream->ref_count);
+       return NULL;
 }
 
 BT_HIDDEN
@@ -107,25 +124,127 @@ int bt_ctf_stream_get_discarded_events_count(
                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,
@@ -156,11 +275,53 @@ end:
        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;
@@ -183,31 +344,27 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                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;
@@ -216,12 +373,31 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        /* 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);
@@ -229,6 +405,11 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                        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) {
@@ -261,19 +442,19 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
         * 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;
@@ -318,8 +499,16 @@ void bt_ctf_stream_destroy(struct bt_ctf_ref *ref)
        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);
 }
 
@@ -328,14 +517,25 @@ int set_structure_field_integer(struct bt_ctf_field *structure, char *name,
                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);
index a1605fcee198fd2561fb9d0ec1f4d5c7c9908a45..460ac81c9c4f158c46dc32e3ed1fb645a1553139 100644 (file)
@@ -215,6 +215,13 @@ struct bt_ctf_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
                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;
@@ -227,13 +234,6 @@ struct bt_ctf_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
 
        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) {
index b79a428828ac55d2486b09e533e7d742014e70fb..89b9496b3b9eb2043b36926028ef38265eaa08fa 100644 (file)
@@ -90,9 +90,14 @@ BT_HIDDEN
 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);
index c53823d1beac5f4bca63bc963cd565759085740e..67a9d17b487b565e0f4de4959ac062cc70910880 100644 (file)
@@ -47,7 +47,6 @@ struct bt_ctf_stream_class {
        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;
index ef6bc778d535c94724fe8a6e7949068fe970208a..5c5918d11094e23beb381281bd85b00989c44a72 100644 (file)
@@ -44,6 +44,14 @@ struct bt_ctf_clock;
  * 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.
@@ -162,6 +170,29 @@ extern struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class(
 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.
index daaa430b36572d3680b437a73d046800c2eaea5e..9214abb82139fee93fb9ffa27f0a653260f43a2f 100644 (file)
@@ -51,7 +51,7 @@ struct bt_ctf_stream {
        GPtrArray *events;
        struct ctf_stream_pos pos;
        unsigned int flushed_packet_count;
-       uint64_t events_discarded;
+       struct bt_ctf_field *packet_context;
 };
 
 BT_HIDDEN
index abf50904a1cbb7ac29760fb72bf63c422c381edb..d9e2bc26e3a00b4b749801904ef3571acbfbc624 100644 (file)
@@ -43,6 +43,10 @@ struct bt_ctf_stream;
  * 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.
@@ -53,7 +57,8 @@ extern int bt_ctf_stream_get_discarded_events_count(
 /*
  * 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
@@ -79,11 +84,41 @@ extern void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
 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.
  *
index bbe354f2fe0ce938a9638b9f2151450ede48540c..c6429331b0d4e29e5a579d084b885f7fcbb98a66 100644 (file)
@@ -287,6 +287,8 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class,
        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");
 
@@ -517,6 +519,29 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class,
        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");
 
@@ -534,6 +559,8 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class,
        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,
@@ -574,6 +601,7 @@ 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);
@@ -921,6 +949,16 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class,
        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");
 
@@ -934,6 +972,8 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class,
        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);
@@ -1262,6 +1302,8 @@ void packet_resize_test(struct bt_ctf_stream_class *stream_class,
        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");
@@ -1310,7 +1352,8 @@ void packet_resize_test(struct bt_ctf_stream_class *stream_class,
                        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,
@@ -1324,7 +1367,17 @@ void packet_resize_test(struct bt_ctf_stream_class *stream_class,
                "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);
@@ -1332,6 +1385,8 @@ end:
                "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);
 }
 
@@ -1356,6 +1411,8 @@ int main(int argc, char **argv)
        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");
@@ -1518,7 +1575,7 @@ int main(int argc, char **argv)
                "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");
@@ -1547,10 +1604,41 @@ int main(int argc, char **argv)
        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");
@@ -1572,6 +1660,8 @@ int main(int argc, char **argv)
        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 */
This page took 0.039116 seconds and 4 git commands to generate.