Validate CTF semantics in selected CTF IR functions
[babeltrace.git] / lib / ctf-ir / stream-class.c
index 1cab9590434ef710744e8568dac3de397c4d718e..9a63043acccdc2d01c34d3239124031ae35f24dd 100644 (file)
@@ -26,6 +26,9 @@
  * SOFTWARE.
  */
 
+#define BT_LOG_TAG "STREAM-CLASS"
+#include <babeltrace/lib-logging-internal.h>
+
 #include <babeltrace/ctf-writer/clock.h>
 #include <babeltrace/ctf-writer/clock-internal.h>
 #include <babeltrace/ctf-ir/clock-class-internal.h>
@@ -46,6 +49,7 @@
 #include <babeltrace/endian-internal.h>
 #include <inttypes.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 static
 void bt_ctf_stream_class_destroy(struct bt_object *obj);
@@ -56,15 +60,52 @@ int init_packet_context(struct bt_ctf_stream_class *stream_class);
 
 struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
 {
+       struct bt_ctf_stream_class *stream_class;
        int ret;
+
+       BT_LOGD("Creating default stream class object: name=\"%s\"", name);
+       stream_class = bt_ctf_stream_class_create_empty(name);
+       if (!stream_class) {
+               BT_LOGD_STR("Cannot create empty stream class.");
+               goto error;
+       }
+
+       ret = init_event_header(stream_class);
+       if (ret) {
+               BT_LOGE_STR("Cannot initialize stream class's event header field type.");
+               goto error;
+       }
+
+       ret = init_packet_context(stream_class);
+       if (ret) {
+               BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
+               goto error;
+       }
+
+       BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
+               stream_class, name);
+       return stream_class;
+
+error:
+       BT_PUT(stream_class);
+       return stream_class;
+}
+
+struct bt_ctf_stream_class *bt_ctf_stream_class_create_empty(const char *name)
+{
        struct bt_ctf_stream_class *stream_class = NULL;
 
+       BT_LOGD("Creating empty stream class object: name=\"%s\"", name);
+
        if (name && bt_ctf_validate_identifier(name)) {
+               BT_LOGW("Invalid parameter: stream class's name is not a valid CTF identifier: "
+                       "name=\"%s\"", name);
                goto error;
        }
 
        stream_class = g_new0(struct bt_ctf_stream_class, 1);
        if (!stream_class) {
+               BT_LOGE_STR("Failed to allocate one stream class.");
                goto error;
        }
 
@@ -72,27 +113,42 @@ struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
        stream_class->event_classes = g_ptr_array_new_with_free_func(
                (GDestroyNotify) bt_object_release);
        if (!stream_class->event_classes) {
+               BT_LOGE_STR("Failed to allocate a GPtrArray.");
                goto error;
        }
 
        stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
                        g_int64_equal, g_free, NULL);
+       if (!stream_class->event_classes_ht) {
+               BT_LOGE_STR("Failed to allocate a GHashTable.");
+               goto error;
+       }
 
-       ret = init_event_header(stream_class);
-       if (ret) {
+       stream_class->packet_context_type = bt_ctf_field_type_structure_create();
+       if (!stream_class->packet_context_type) {
+               BT_LOGE_STR("Cannot create stream class's initial packet context field type.");
                goto error;
        }
 
-       ret = init_packet_context(stream_class);
-       if (ret) {
+       stream_class->event_header_type = bt_ctf_field_type_structure_create();
+       if (!stream_class->event_header_type) {
+               BT_LOGE_STR("Cannot create stream class's initial event header field type.");
+               goto error;
+       }
+
+       stream_class->event_context_type = bt_ctf_field_type_structure_create();
+       if (!stream_class->event_context_type) {
+               BT_LOGE_STR("Cannot create stream class's initial event context field type.");
                goto error;
        }
 
        bt_object_init(stream_class, bt_ctf_stream_class_destroy);
+       BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
+               stream_class, name);
        return stream_class;
 
 error:
-        BT_PUT(stream_class);
+       BT_PUT(stream_class);
        return stream_class;
 }
 
@@ -110,6 +166,7 @@ const char *bt_ctf_stream_class_get_name(
        const char *name = NULL;
 
        if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
                goto end;
        }
 
@@ -123,12 +180,26 @@ int bt_ctf_stream_class_set_name(struct bt_ctf_stream_class *stream_class,
 {
        int ret = 0;
 
-       if (!stream_class || stream_class->frozen) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                ret = -1;
                goto end;
        }
 
        g_string_assign(stream_class->name, name);
+       BT_LOGV("Set stream class's name: "
+               "addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class));
 end:
        return ret;
 }
@@ -138,7 +209,16 @@ struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
 {
        struct bt_ctf_clock *clock = NULL;
 
-       if (!stream_class || !stream_class->clock) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto end;
+       }
+
+       if (!stream_class->clock) {
+               BT_LOGV("Stream class has no clock: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                goto end;
        }
 
@@ -153,38 +233,33 @@ int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
        int ret = 0;
        struct bt_ctf_field_type *timestamp_field = NULL;
 
-       if (!stream_class || !clock || stream_class->frozen) {
+       if (!stream_class || !clock) {
+               BT_LOGW("Invalid parameter: stream class or clock is NULL: "
+                       "stream-class-addr=%p, clock-addr=%p",
+                       stream_class, clock);
                ret = -1;
                goto end;
        }
 
-       /*
-        * Look for a "timestamp" integer field type in the stream
-        * class's event header field type and map the stream class's
-        * clock's class to that field type if there's no current
-        * mapping.
-        */
-       timestamp_field = bt_ctf_field_type_structure_get_field_type_by_name(
-               stream_class->event_header_type, "timestamp");
-       if (timestamp_field) {
-               struct bt_ctf_clock_class *mapped_clock_class =
-                       bt_ctf_field_type_integer_get_mapped_clock_class(
-                               timestamp_field);
-
-               if (!mapped_clock_class) {
-                       ret = bt_ctf_field_type_integer_set_mapped_clock_class(
-                               timestamp_field, clock->clock_class);
-                       if (ret) {
-                               goto end;
-                       }
-               }
-
-               BT_PUT(mapped_clock_class);
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
+               ret = -1;
+               goto end;
        }
 
        /* Replace the current clock of this stream class. */
        bt_put(stream_class->clock);
        stream_class->clock = bt_get(clock);
+       BT_LOGV("Set stream class's clock: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "clock-addr=%p, clock-name=\"%s\"",
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               stream_class->clock,
+               bt_ctf_clock_get_name(stream_class->clock));
 
 end:
        bt_put(timestamp_field);
@@ -195,46 +270,59 @@ int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class *stream_class)
 {
        int64_t ret;
 
-       if (!stream_class || !stream_class->id_set) {
-               ret = -1;
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = (int64_t) -1;
                goto end;
        }
 
-       ret = (int64_t) stream_class->id;
+       if (!stream_class->id_set) {
+               BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
+                       stream_class,
+                       bt_ctf_stream_class_get_name(stream_class));
+               ret = (int64_t) -1;
+               goto end;
+       }
+
+       ret = stream_class->id;
 end:
        return ret;
 }
 
 BT_HIDDEN
-int _bt_ctf_stream_class_set_id(
-               struct bt_ctf_stream_class *stream_class, uint32_t id)
+void _bt_ctf_stream_class_set_id(
+               struct bt_ctf_stream_class *stream_class, int64_t id)
 {
+       assert(stream_class);
        stream_class->id = id;
        stream_class->id_set = 1;
-       return 0;
+       BT_LOGV("Set stream class's ID (internal): "
+               "addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class));
 }
 
-struct event_class_set_stream_id_data {
-       uint32_t stream_id;
+struct event_class_set_stream_class_id_data {
+       int64_t stream_class_id;
        int ret;
 };
 
 static
 void event_class_set_stream_id(gpointer event_class, gpointer data)
 {
-       struct event_class_set_stream_id_data *typed_data = data;
+       struct event_class_set_stream_class_id_data *typed_data = data;
 
        typed_data->ret |= bt_ctf_event_class_set_stream_id(event_class,
-               typed_data->stream_id);
+               typed_data->stream_class_id);
 }
 
 BT_HIDDEN
 int bt_ctf_stream_class_set_id_no_check(
-               struct bt_ctf_stream_class *stream_class, uint32_t id)
+               struct bt_ctf_stream_class *stream_class, int64_t id)
 {
        int ret = 0;
-       struct event_class_set_stream_id_data data =
-               { .stream_id = id, .ret = 0 };
+       struct event_class_set_stream_class_id_data data =
+               { .stream_class_id = id, .ret = 0 };
 
        /*
         * Make sure all event classes have their "stream_id" attribute
@@ -244,28 +332,57 @@ int bt_ctf_stream_class_set_id_no_check(
                event_class_set_stream_id, &data);
        ret = data.ret;
        if (ret) {
+               BT_LOGE("Cannot set the IDs of all stream class's event classes: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                goto end;
        }
 
-       ret = _bt_ctf_stream_class_set_id(stream_class, id);
-       if (ret) {
-               goto end;
-       }
+       _bt_ctf_stream_class_set_id(stream_class, id);
 end:
        return ret;
 }
 
 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
-               uint32_t id)
+               uint64_t id_param)
 {
        int ret = 0;
+       int64_t id = (int64_t) id_param;
 
-       if (!stream_class || stream_class->frozen) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (id < 0) {
+               BT_LOGW("Invalid parameter: invalid stream class's ID: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", id=%" PRIu64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class),
+                       id_param);
                ret = -1;
                goto end;
        }
 
        ret = bt_ctf_stream_class_set_id_no_check(stream_class, id);
+       if (ret == 0) {
+               BT_LOGV("Set stream class's ID: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
+       }
 end:
        return ret;
 }
@@ -283,16 +400,6 @@ void event_class_exists(gpointer element, gpointer query)
                goto end;
        }
 
-       /*
-        * Two event classes cannot share the same name in a given
-        * stream class.
-        */
-       if (!strcmp(bt_ctf_event_class_get_name(event_class_a),
-                       bt_ctf_event_class_get_name(event_class_b))) {
-               search_query->found = 1;
-               goto end;
-       }
-
        /*
         * Two event classes cannot share the same ID in a given
         * stream class.
@@ -306,6 +413,9 @@ void event_class_exists(gpointer element, gpointer query)
        }
 
        if (id_a == id_b) {
+               BT_LOGW("Event class with this ID already exists in the stream class: "
+                       "id=%" PRId64 ", name=\"%s\"",
+                       id_a, bt_ctf_event_class_get_name(event_class_a));
                search_query->found = 1;
                goto end;
        }
@@ -333,10 +443,23 @@ int bt_ctf_stream_class_add_event_class(
                BT_CTF_VALIDATION_FLAG_EVENT;
 
        if (!stream_class || !event_class) {
+               BT_LOGW("Invalid parameter: stream class or event class is NULL: "
+                       "stream-class-addr=%p, event-class-addr=%p",
+                       stream_class, event_class);
                ret = -1;
                goto end;
        }
 
+       BT_LOGD("Adding event class to stream class: "
+               "stream-class-addr=%p, stream-class-name=\"%s\", "
+               "stream-class-id=%" PRId64 ", event-class-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               event_class,
+               bt_ctf_event_class_get_name(event_class),
+               bt_ctf_event_class_get_id(event_class));
+
        trace = bt_ctf_stream_class_get_trace(stream_class);
        if (trace && trace->is_static) {
                ret = -1;
@@ -345,6 +468,7 @@ int bt_ctf_stream_class_add_event_class(
 
        event_id = g_new(int64_t, 1);
        if (!event_id) {
+               BT_LOGE_STR("Failed to allocate one int64_t.");
                ret = -1;
                goto end;
        }
@@ -354,6 +478,7 @@ int bt_ctf_stream_class_add_event_class(
        g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
                &query);
        if (query.found) {
+               BT_LOGW_STR("Another event class part of this stream class has the same ID.");
                ret = -1;
                goto end;
        }
@@ -361,6 +486,13 @@ int bt_ctf_stream_class_add_event_class(
        old_stream_class = bt_ctf_event_class_get_stream_class(event_class);
        if (old_stream_class) {
                /* Event class is already associated to a stream class. */
+               BT_LOGW("Event class is already part of another stream class: "
+                       "event-class-stream-class-addr=%p, "
+                       "event-class-stream-class-name=\"%s\", "
+                       "event-class-stream-class-id=%" PRId64,
+                       old_stream_class,
+                       bt_ctf_stream_class_get_name(old_stream_class),
+                       bt_ctf_stream_class_get_id(old_stream_class));
                ret = -1;
                goto end;
        }
@@ -411,12 +543,16 @@ int bt_ctf_stream_class_add_event_class(
                         * validation process, not that the objects are
                         * invalid.
                         */
+                       BT_LOGE("Failed to validate event class: ret=%d", ret);
                        goto end;
                }
 
                if ((validation_output.valid_flags & validation_flags) !=
                                validation_flags) {
                        /* Invalid event class */
+                       BT_LOGW("Invalid trace, stream class, or event class: "
+                               "valid-flags=0x%x",
+                               validation_output.valid_flags);
                        ret = -1;
                        goto end;
                }
@@ -425,16 +561,24 @@ int bt_ctf_stream_class_add_event_class(
        /* Only set an event ID if none was explicitly set before */
        *event_id = bt_ctf_event_class_get_id(event_class);
        if (*event_id < 0) {
+               BT_LOGV("Event class has no ID: automatically setting it: "
+                       "id=%" PRId64, stream_class->next_event_id);
+
                if (bt_ctf_event_class_set_id(event_class,
-                       stream_class->next_event_id++)) {
+                               stream_class->next_event_id)) {
+                       BT_LOGE("Cannot set event class's ID: id=%" PRId64,
+                               stream_class->next_event_id);
                        ret = -1;
                        goto end;
                }
+               stream_class->next_event_id++;
                *event_id = stream_class->next_event_id;
        }
 
        ret = bt_ctf_event_class_set_stream_id(event_class, stream_class->id);
        if (ret) {
+               BT_LOGE("Cannot set event class's stream class ID attribute: ret=%d",
+                       ret);
                goto end;
        }
 
@@ -474,6 +618,17 @@ int bt_ctf_stream_class_add_event_class(
 
                (void) bt_ctf_trace_object_modification(&obj, trace);
        }
+
+       BT_LOGD("Added event class to stream class: "
+               "stream-class-addr=%p, stream-class-name=\"%s\", "
+               "stream-class-id=%" PRId64 ", event-class-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               event_class,
+               bt_ctf_event_class_get_name(event_class),
+               bt_ctf_event_class_get_id(event_class));
+
 end:
        BT_PUT(trace);
        BT_PUT(old_stream_class);
@@ -495,64 +650,60 @@ int64_t bt_ctf_stream_class_get_event_class_count(
        int64_t ret;
 
        if (!stream_class) {
-               ret = -1;
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = (int64_t) -1;
                goto end;
        }
 
-       ret = (int) stream_class->event_classes->len;
+       ret = (int64_t) stream_class->event_classes->len;
 end:
        return ret;
 }
 
-struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class(
-               struct bt_ctf_stream_class *stream_class, int index)
+struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
+               struct bt_ctf_stream_class *stream_class, uint64_t index)
 {
        struct bt_ctf_event_class *event_class = NULL;
 
-       if (!stream_class || index < 0 ||
-               index >= stream_class->event_classes->len) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
                goto end;
        }
 
-       event_class = g_ptr_array_index(stream_class->event_classes, index);
-       bt_get(event_class);
-end:
-       return event_class;
-}
-
-struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_name(
-               struct bt_ctf_stream_class *stream_class, const char *name)
-{
-       size_t i;
-       struct bt_ctf_event_class *event_class = NULL;
-
-       if (!stream_class || !name) {
+       if (index >= stream_class->event_classes->len) {
+               BT_LOGW("Invalid parameter: index is out of bounds: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "index=%" PRIu64 ", count=%u",
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class),
+                       index, stream_class->event_classes->len);
                goto end;
        }
 
-       for (i = 0; i < stream_class->event_classes->len; i++) {
-               struct bt_ctf_event_class *cur_event_class =
-                       g_ptr_array_index(stream_class->event_classes, i);
-               const char *cur_event_class_name =
-                       bt_ctf_event_class_get_name(cur_event_class);
-
-               if (!strcmp(name, cur_event_class_name)) {
-                       event_class = cur_event_class;
-                       bt_get(event_class);
-                       goto end;
-               }
-       }
+       event_class = g_ptr_array_index(stream_class->event_classes, index);
+       bt_get(event_class);
 end:
        return event_class;
 }
 
 struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
-               struct bt_ctf_stream_class *stream_class, uint32_t id)
+               struct bt_ctf_stream_class *stream_class, uint64_t id)
 {
-       int64_t id_key = id;
+       int64_t id_key = (int64_t) id;
        struct bt_ctf_event_class *event_class = NULL;
 
        if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto end;
+       }
+
+       if (id_key < 0) {
+               BT_LOGW("Invalid parameter: invalid event class's ID: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", event-class-id=%" PRIu64,
+                       stream_class,
+                       bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class), id);
                goto end;
        }
 
@@ -569,6 +720,7 @@ struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
        struct bt_ctf_field_type *ret = NULL;
 
        if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
                goto end;
        }
 
@@ -584,7 +736,17 @@ int bt_ctf_stream_class_set_packet_context_type(
 {
        int ret = 0;
 
-       if (!stream_class || stream_class->frozen) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                ret = -1;
                goto end;
        }
@@ -593,6 +755,14 @@ int bt_ctf_stream_class_set_packet_context_type(
                        bt_ctf_field_type_get_type_id(packet_context_type) !=
                                BT_CTF_FIELD_TYPE_ID_STRUCT) {
                /* A packet context must be a structure. */
+               BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "packet-context-ft-addr=%p, packet-context-ft-id=%s",
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class),
+                       packet_context_type,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_field_type_get_type_id(packet_context_type)));
                ret = -1;
                goto end;
        }
@@ -600,6 +770,13 @@ int bt_ctf_stream_class_set_packet_context_type(
        bt_put(stream_class->packet_context_type);
        bt_get(packet_context_type);
        stream_class->packet_context_type = packet_context_type;
+       BT_LOGV("Set stream class's packet context field type: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "packet-context-ft-addr=%p",
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               packet_context_type);
+
 end:
        return ret;
 }
@@ -609,7 +786,16 @@ struct bt_ctf_field_type *bt_ctf_stream_class_get_event_header_type(
 {
        struct bt_ctf_field_type *ret = NULL;
 
-       if (!stream_class || !stream_class->event_header_type) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto end;
+       }
+
+       if (!stream_class->event_header_type) {
+               BT_LOGV("Stream class has no event header field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                goto end;
        }
 
@@ -625,7 +811,17 @@ int bt_ctf_stream_class_set_event_header_type(
 {
        int ret = 0;
 
-       if (!stream_class || stream_class->frozen) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                ret = -1;
                goto end;
        }
@@ -634,12 +830,26 @@ int bt_ctf_stream_class_set_event_header_type(
                        bt_ctf_field_type_get_type_id(event_header_type) !=
                                BT_CTF_FIELD_TYPE_ID_STRUCT) {
                /* An event header must be a structure. */
+               BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "event-header-ft-addr=%p, event-header-ft-id=%s",
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class),
+                       event_header_type,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_field_type_get_type_id(event_header_type)));
                ret = -1;
                goto end;
        }
 
        bt_put(stream_class->event_header_type);
        stream_class->event_header_type = bt_get(event_header_type);
+       BT_LOGV("Set stream class's event header field type: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "event-header-ft-addr=%p",
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               event_header_type);
 end:
        return ret;
 }
@@ -649,7 +859,12 @@ struct bt_ctf_field_type *bt_ctf_stream_class_get_event_context_type(
 {
        struct bt_ctf_field_type *ret = NULL;
 
-       if (!stream_class || !stream_class->event_context_type) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto end;
+       }
+
+       if (!stream_class->event_context_type) {
                goto end;
        }
 
@@ -665,7 +880,17 @@ int bt_ctf_stream_class_set_event_context_type(
 {
        int ret = 0;
 
-       if (!stream_class || stream_class->frozen) {
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
                ret = -1;
                goto end;
        }
@@ -674,21 +899,37 @@ int bt_ctf_stream_class_set_event_context_type(
                        bt_ctf_field_type_get_type_id(event_context_type) !=
                                BT_CTF_FIELD_TYPE_ID_STRUCT) {
                /* A packet context must be a structure. */
+               BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "event-context-ft-addr=%p, event-context-ft-id=%s",
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class),
+                       event_context_type,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_field_type_get_type_id(event_context_type)));
                ret = -1;
                goto end;
        }
 
        bt_put(stream_class->event_context_type);
        stream_class->event_context_type = bt_get(event_context_type);
+       BT_LOGV("Set stream class's event context field type: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "event-context-ft-addr=%p",
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               event_context_type);
 end:
        return ret;
 }
 
+/* Pre-2.0 CTF writer backward compatibility */
 void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
 {
        bt_get(stream_class);
 }
 
+/* Pre-2.0 CTF writer backward compatibility */
 void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
 {
        bt_put(stream_class);
@@ -704,7 +945,7 @@ int64_t get_event_class_count(void *element)
 static
 void *get_event_class(void *element, int i)
 {
-       return bt_ctf_stream_class_get_event_class(
+       return bt_ctf_stream_class_get_event_class_by_index(
                        (struct bt_ctf_stream_class *) element, i);
 }
 
@@ -727,6 +968,9 @@ int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
                        .type = BT_CTF_OBJECT_TYPE_STREAM_CLASS };
 
        if (!stream_class || !visitor) {
+               BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
+                       "stream-class-addr=%p, visitor=%p",
+                       stream_class, visitor);
                ret = -1;
                goto end;
        }
@@ -734,6 +978,7 @@ int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
        ret = visitor_helper(&obj, get_event_class_count,
                        get_event_class,
                        visit_event_class, visitor, data);
+       BT_LOGV("visitor_helper() returned: ret=%d", ret);
 end:
        return ret;
 }
@@ -741,10 +986,13 @@ end:
 BT_HIDDEN
 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
 {
-       if (!stream_class) {
+       if (!stream_class || stream_class->frozen) {
                return;
        }
 
+       BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class));
        stream_class->frozen = 1;
        bt_ctf_field_type_freeze(stream_class->event_header_type);
        bt_ctf_field_type_freeze(stream_class->packet_context_type);
@@ -759,50 +1007,78 @@ BT_HIDDEN
 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
                struct metadata_context *context)
 {
-       int64_t ret = 0;
+       int ret = 0;
        size_t i;
 
+       BT_LOGD("Serializing stream class's metadata: "
+               "stream-class-addr=%p, stream-class-name=\"%s\", "
+               "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class), context);
        g_string_assign(context->field_name, "");
        context->current_indentation_level = 1;
        if (!stream_class->id_set) {
+               BT_LOGW_STR("Stream class's ID is not set.");
                ret = -1;
                goto end;
        }
 
        g_string_append_printf(context->string,
-               "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
-               stream_class->id);
-       ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
-               context);
-       if (ret) {
-               goto end;
+               "stream {\n\tid = %" PRId64 ";\n", stream_class->id);
+       if (stream_class->event_header_type) {
+               BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
+               g_string_append(context->string, "\tevent.header := ");
+               ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
+                       context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+               g_string_append(context->string, ";");
        }
 
+
        if (stream_class->packet_context_type) {
-               g_string_append(context->string, ";\n\n\tpacket.context := ");
+               BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
+               g_string_append(context->string, "\n\n\tpacket.context := ");
                ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
                        context);
                if (ret) {
+                       BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
+                               "ret=%d", ret);
                        goto end;
                }
+               g_string_append(context->string, ";");
        }
 
        if (stream_class->event_context_type) {
-               g_string_append(context->string, ";\n\n\tevent.context := ");
+               BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
+               g_string_append(context->string, "\n\n\tevent.context := ");
                ret = bt_ctf_field_type_serialize(
                        stream_class->event_context_type, context);
                if (ret) {
+                       BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
+                               "ret=%d", ret);
                        goto end;
                }
+               g_string_append(context->string, ";");
        }
 
-       g_string_append(context->string, ";\n};\n\n");
+       g_string_append(context->string, "\n};\n\n");
+
        for (i = 0; i < stream_class->event_classes->len; i++) {
                struct bt_ctf_event_class *event_class =
                        stream_class->event_classes->pdata[i];
 
                ret = bt_ctf_event_class_serialize(event_class, context);
                if (ret) {
+                       BT_LOGW("Cannot serialize event class's metadata: "
+                               "event-class-addr=%p, event-class-name=\"%s\", "
+                               "event-class-id=%" PRId64,
+                               event_class,
+                               bt_ctf_event_class_get_name(event_class),
+                               bt_ctf_event_class_get_id(event_class));
                        goto end;
                }
        }
@@ -817,6 +1093,9 @@ void bt_ctf_stream_class_destroy(struct bt_object *obj)
        struct bt_ctf_stream_class *stream_class;
 
        stream_class = container_of(obj, struct bt_ctf_stream_class, base);
+       BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class));
        bt_put(stream_class->clock);
 
        if (stream_class->event_classes_ht) {
@@ -848,6 +1127,7 @@ int init_event_header(struct bt_ctf_stream_class *stream_class)
                get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
 
        if (!event_header_type) {
+               BT_LOGE_STR("Cannot create empty structure field type.");
                ret = -1;
                goto end;
        }
@@ -855,19 +1135,18 @@ int init_event_header(struct bt_ctf_stream_class *stream_class)
        ret = bt_ctf_field_type_structure_add_field(event_header_type,
                _uint32_t, "id");
        if (ret) {
+               BT_LOGE_STR("Cannot add `id` field to event header field type.");
                goto end;
        }
 
        ret = bt_ctf_field_type_structure_add_field(event_header_type,
                _uint64_t, "timestamp");
        if (ret) {
+               BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
                goto end;
        }
 
-       if (stream_class->event_header_type) {
-               bt_put(stream_class->event_header_type);
-       }
-       stream_class->event_header_type = event_header_type;
+       BT_MOVE(stream_class->event_header_type, event_header_type);
 end:
        if (ret) {
                bt_put(event_header_type);
@@ -886,8 +1165,17 @@ int init_packet_context(struct bt_ctf_stream_class *stream_class)
                bt_ctf_field_type_structure_create();
        struct bt_ctf_field_type *_uint64_t =
                get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
+       struct bt_ctf_field_type *ts_begin_end_uint64_t;
 
        if (!packet_context_type) {
+               BT_LOGE_STR("Cannot create empty structure field type.");
+               ret = -1;
+               goto end;
+       }
+
+       ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
+       if (!ts_begin_end_uint64_t) {
+               BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
                ret = -1;
                goto end;
        }
@@ -897,37 +1185,41 @@ int init_packet_context(struct bt_ctf_stream_class *stream_class)
         * specification.
         */
        ret = bt_ctf_field_type_structure_add_field(packet_context_type,
-               _uint64_t, "timestamp_begin");
+               ts_begin_end_uint64_t, "timestamp_begin");
        if (ret) {
+               BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
                goto end;
        }
 
        ret = bt_ctf_field_type_structure_add_field(packet_context_type,
-               _uint64_t, "timestamp_end");
+               ts_begin_end_uint64_t, "timestamp_end");
        if (ret) {
+               BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
                goto end;
        }
 
        ret = bt_ctf_field_type_structure_add_field(packet_context_type,
                _uint64_t, "content_size");
        if (ret) {
+               BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
                goto end;
        }
 
        ret = bt_ctf_field_type_structure_add_field(packet_context_type,
                _uint64_t, "packet_size");
        if (ret) {
+               BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
                goto end;
        }
 
        ret = bt_ctf_field_type_structure_add_field(packet_context_type,
                _uint64_t, "events_discarded");
        if (ret) {
+               BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
                goto end;
        }
 
-       bt_put(stream_class->packet_context_type);
-       stream_class->packet_context_type = packet_context_type;
+       BT_MOVE(stream_class->packet_context_type, packet_context_type);
 end:
        if (ret) {
                bt_put(packet_context_type);
@@ -935,5 +1227,103 @@ end:
        }
 
        bt_put(_uint64_t);
+       bt_put(ts_begin_end_uint64_t);
+       return ret;
+}
+
+static
+int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *ft)
+{
+       struct bt_ctf_clock_class *mapped_clock_class = NULL;
+       int ret = 0;
+
+       if (!ft) {
+               /* Field does not exist: not an error */
+               goto end;
+       }
+
+       assert(bt_ctf_field_type_is_integer(ft));
+       mapped_clock_class =
+               bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+       if (!mapped_clock_class) {
+               if (!stream_class->clock) {
+                       BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
+                               "stream-class-addr=%p, stream-class-name=\"%s\", "
+                               "stream-class-id=%" PRId64 ", ft-addr=%p",
+                               stream_class, bt_ctf_stream_class_get_name(stream_class),
+                               bt_ctf_stream_class_get_id(stream_class), ft);
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
+                       ft, stream_class->clock->clock_class);
+               if (ret) {
+                       BT_LOGW("Cannot set field type's mapped clock class: "
+                               "stream-class-addr=%p, stream-class-name=\"%s\", "
+                               "stream-class-id=%" PRId64 ", ft-addr=%p",
+                               stream_class, bt_ctf_stream_class_get_name(stream_class),
+                               bt_ctf_stream_class_get_id(stream_class), ft);
+                       goto end;
+               }
+
+               BT_LOGV("Automatically mapped field type to stream class's clock class: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", ft-addr=%p",
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class), ft);
+       }
+
+end:
+       bt_put(mapped_clock_class);
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_map_clock_class(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *packet_context_type,
+               struct bt_ctf_field_type *event_header_type)
+{
+       struct bt_ctf_field_type *ft = NULL;
+       int ret = 0;
+
+       assert(stream_class);
+
+       if (packet_context_type) {
+               ft = bt_ctf_field_type_structure_get_field_type_by_name(
+                       packet_context_type, "timestamp_begin");
+               if (try_map_clock_class(stream_class, ft)) {
+                       BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
+                       ret = -1;
+                       goto end;
+               }
+
+               bt_put(ft);
+               ft = bt_ctf_field_type_structure_get_field_type_by_name(
+                       packet_context_type, "timestamp_end");
+               if (try_map_clock_class(stream_class, ft)) {
+                       BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
+                       ret = -1;
+                       goto end;
+               }
+
+               BT_PUT(ft);
+       }
+
+       if (event_header_type) {
+               ft = bt_ctf_field_type_structure_get_field_type_by_name(
+                       event_header_type, "timestamp");
+               if (try_map_clock_class(stream_class, ft)) {
+                       BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
+                       ret = -1;
+                       goto end;
+               }
+
+               BT_PUT(ft);
+       }
+
+end:
        return ret;
 }
This page took 0.042545 seconds and 4 git commands to generate.