Fix: Check integer signedness in packet header when auto-populating
[babeltrace.git] / formats / ctf / ir / stream.c
index 9b0be90b7b2e97ad96f36e670060cb51192e33a9..45f875ff641ff7a2b0efaedbb1591b9ad4e59432 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * stream.c
  *
- * Babeltrace CTF Writer
+ * Babeltrace CTF IR - Stream
  *
  * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
@@ -67,7 +67,21 @@ struct bt_ctf_stream *bt_ctf_stream_create(
                goto error_destroy;
        }
 
-       /* Initialize events_discarded*/
+       /*
+        * A stream class may not have a stream event context defined
+        * in which case this stream will never have a stream_event_context
+        * member since, after a stream's creation, the parent stream class
+        * is "frozen" (immutable).
+        */
+       if (stream_class->event_context_type) {
+               stream->event_context = bt_ctf_field_create(
+                       stream_class->event_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) {
@@ -80,7 +94,17 @@ struct bt_ctf_stream *bt_ctf_stream_create(
        bt_ctf_stream_class_get(stream_class);
        bt_ctf_stream_class_freeze(stream_class);
        stream->events = g_ptr_array_new_with_free_func(
-               (GDestroyNotify)bt_ctf_event_put);
+               (GDestroyNotify) bt_ctf_event_put);
+       if (!stream->events) {
+               goto error_destroy;
+       }
+       if (stream_class->event_context_type) {
+               stream->event_contexts = g_ptr_array_new_with_free_func(
+                       (GDestroyNotify) bt_ctf_field_put);
+               if (!stream->event_contexts) {
+                       goto error_destroy;
+               }
+       }
 end:
        return stream;
 error_destroy:
@@ -252,17 +276,34 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
 {
        int ret = 0;
        uint64_t timestamp;
+       struct bt_ctf_field *event_context_copy = NULL;
 
        if (!stream || !event) {
                ret = -1;
                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;
+               }
+       }
+
        timestamp = bt_ctf_clock_get_time(stream->stream_class->clock);
        ret = bt_ctf_event_set_timestamp(event, timestamp);
        if (ret) {
@@ -270,7 +311,11 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
        }
 
        bt_ctf_event_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:
        return ret;
 }
@@ -285,10 +330,10 @@ struct bt_ctf_field *bt_ctf_stream_get_packet_context(
        }
 
        packet_context = stream->packet_context;
-end:
        if (packet_context) {
                bt_ctf_field_get(packet_context);
        }
+end:
        return packet_context;
 }
 
@@ -317,6 +362,50 @@ end:
        return ret;
 }
 
+struct bt_ctf_field *bt_ctf_stream_get_event_context(
+               struct bt_ctf_stream *stream)
+{
+       struct bt_ctf_field *event_context = NULL;
+
+       if (!stream) {
+               goto end;
+       }
+
+       event_context = stream->event_context;
+       if (event_context) {
+               bt_ctf_field_get(event_context);
+       }
+end:
+       return event_context;
+}
+
+int bt_ctf_stream_set_event_context(struct bt_ctf_stream *stream,
+               struct bt_ctf_field *field)
+{
+       int ret = 0;
+       struct bt_ctf_field_type *field_type = NULL;
+
+       if (!stream || !field) {
+               ret = -1;
+               goto end;
+       }
+
+       field_type = bt_ctf_field_get_type(field);
+       if (field_type != stream->stream_class->event_context_type) {
+               ret = -1;
+               goto end;
+       }
+
+       bt_ctf_field_get(field);
+       bt_ctf_field_put(stream->event_context);
+       stream->event_context = field;
+end:
+       if (field_type) {
+               bt_ctf_field_type_put(field_type);
+       }
+       return ret;
+}
+
 int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
 {
        int ret = 0;
@@ -326,7 +415,11 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        struct bt_ctf_field *integer = NULL;
        struct ctf_stream_pos packet_context_pos;
 
-       if (!stream) {
+       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;
        }
@@ -428,6 +521,16 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                        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) {
@@ -461,6 +564,9 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        }
 
        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_ctf_field_put(integer);
@@ -506,9 +612,15 @@ void bt_ctf_stream_destroy(struct bt_ctf_ref *ref)
        if (stream->events) {
                g_ptr_array_free(stream->events, TRUE);
        }
+       if (stream->event_contexts) {
+               g_ptr_array_free(stream->event_contexts, TRUE);
+       }
        if (stream->packet_context) {
                bt_ctf_field_put(stream->packet_context);
        }
+       if (stream->event_context) {
+               bt_ctf_field_put(stream->event_context);
+       }
        g_free(stream);
 }
 
@@ -517,6 +629,7 @@ 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);
 
@@ -536,8 +649,31 @@ int set_structure_field_integer(struct bt_ctf_field *structure, char *name,
                goto end;
        }
 
-       ret = bt_ctf_field_unsigned_integer_set_value(integer, value);
+       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_ctf_field_put(integer);
+       if (integer) {
+               bt_ctf_field_put(integer);
+       }
+       if (field_type) {
+               bt_ctf_field_type_put(field_type);
+       }
        return ret;
 }
This page took 0.026616 seconds and 4 git commands to generate.