Replace assert() -> BT_ASSERT() and some preconditions with BT_ASSERT_PRE()
[deliverable/babeltrace.git] / lib / ctf-ir / trace.c
index 4a3027b48ec76517c055b5312e59f91c185a2bfa..1b1e5f82a3bfc0207d9deb89b526a8ca8a138dc7 100644 (file)
 #include <babeltrace/ctf-ir/validation-internal.h>
 #include <babeltrace/ctf-ir/visitor-internal.h>
 #include <babeltrace/ctf-ir/utils.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/values.h>
 #include <babeltrace/values-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/types.h>
 #include <babeltrace/endian-internal.h>
+#include <babeltrace/assert-internal.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <string.h>
@@ -350,7 +352,7 @@ int bt_trace_set_environment_field(struct bt_trace *trace,
                goto end;
        }
 
-       if (bt_identifier_is_valid(name)) {
+       if (!bt_identifier_is_valid(name)) {
                BT_LOGW("Invalid parameter: environment field's name is not a valid CTF identifier: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "env-name=\"%s\"",
@@ -480,7 +482,7 @@ int64_t bt_trace_get_environment_field_count(struct bt_trace *trace)
        }
 
        ret = bt_attributes_get_count(trace->environment);
-       assert(ret >= 0);
+       BT_ASSERT(ret >= 0);
 
 end:
        return ret;
@@ -706,7 +708,7 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
 
                ret = bt_field_type_structure_get_field_by_index(
                        packet_header_type, &field_name, NULL, 0);
-               assert(ret == 0);
+               BT_ASSERT(ret == 0);
 
                if (strcmp(field_name, "magic") != 0) {
                        BT_LOGW("Invalid packet header field type: `magic` field must be the first field: "
@@ -744,7 +746,7 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
                }
 
                elem_ft = bt_field_type_array_get_element_type(field_type);
-               assert(elem_ft);
+               BT_ASSERT(elem_ft);
 
                if (!bt_field_type_is_integer(elem_ft)) {
                        BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an integer field type: "
@@ -1087,7 +1089,7 @@ bool event_header_field_type_is_valid(struct bt_trace *trace,
                        goto invalid;
                }
 
-               assert(int_ft);
+               BT_ASSERT(int_ft);
                if (bt_field_type_integer_is_signed(int_ft)) {
                        BT_LOGW("Invalid event header field type: `id` field must be an unsigned integer or enumeration field type: "
                                "id-ft-addr=%p", int_ft);
@@ -1108,6 +1110,34 @@ end:
        return is_valid;
 }
 
+static
+int check_packet_header_type_has_no_clock_class(struct bt_trace *trace)
+{
+       int ret = 0;
+
+       if (trace->packet_header_type) {
+               struct bt_clock_class *clock_class = NULL;
+
+               ret = bt_validate_single_clock_class(trace->packet_header_type,
+                       &clock_class);
+               bt_put(clock_class);
+               if (ret || clock_class) {
+                       BT_LOGW("Trace's packet header field type cannot "
+                               "contain a field type which is mapped to "
+                               "a clock class: "
+                               "trace-addr=%p, trace-name=\"%s\", "
+                               "clock-class-name=\"%s\"",
+                               trace, bt_trace_get_name(trace),
+                               clock_class ?
+                                       bt_clock_class_get_name(clock_class) :
+                                       NULL);
+                       ret = -1;
+               }
+       }
+
+       return ret;
+}
+
 int bt_trace_add_stream_class(struct bt_trace *trace,
                struct bt_stream_class *stream_class)
 {
@@ -1127,6 +1157,7 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
        struct bt_field_type *stream_event_ctx_type = NULL;
        int64_t event_class_count;
        struct bt_trace *current_parent_trace = NULL;
+       struct bt_clock_class *expected_clock_class = NULL;
 
        if (!trace) {
                BT_LOGW_STR("Invalid parameter: trace is NULL.");
@@ -1168,7 +1199,7 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
 
        event_class_count =
                bt_stream_class_get_event_class_count(stream_class);
-       assert(event_class_count >= 0);
+       BT_ASSERT(event_class_count >= 0);
 
        if (stream_class->clock) {
                struct bt_clock_class *stream_clock_class =
@@ -1214,6 +1245,85 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                        ret = -1;
                        goto end;
                }
+
+               if (stream_class->clock_class &&
+                               stream_class->clock_class !=
+                               stream_class->clock->clock_class) {
+                       /*
+                        * Stream class already has an expected clock
+                        * class, but it does not match its clock's
+                        * class.
+                        */
+                       BT_LOGW("Invalid parameter: stream class's clock's "
+                               "class does not match stream class's "
+                               "expected clock class: "
+                               "stream-class-addr=%p, "
+                               "stream-class-id=%" PRId64 ", "
+                               "stream-class-name=\"%s\", "
+                               "expected-clock-class-addr=%p, "
+                               "expected-clock-class-name=\"%s\"",
+                               stream_class,
+                               bt_stream_class_get_id(stream_class),
+                               bt_stream_class_get_name(stream_class),
+                               expected_clock_class,
+                               bt_clock_class_get_name(expected_clock_class));
+               } else if (!stream_class->clock_class) {
+                       /*
+                        * Set expected clock class to stream class's
+                        * clock's class.
+                        */
+                       expected_clock_class =
+                               bt_get(stream_class->clock->clock_class);
+               }
+       }
+
+       if (!stream_class->frozen) {
+               /*
+                * Stream class is not frozen yet. Validate that the
+                * stream class contains at most a single clock class
+                * because the previous
+                * bt_stream_class_add_event_class() calls did not make
+                * this validation since the stream class's direct field
+                * types (packet context, event header, event context)
+                * could change afterwards. This stream class is about
+                * to be frozen and those field types won't be changed
+                * if this function succeeds.
+                *
+                * At this point we're also sure that the stream class's
+                * clock, if any, has the same class as the stream
+                * class's expected clock class, if any. This is why, if
+                * bt_stream_class_validate_single_clock_class()
+                * succeeds below, the call to
+                * bt_stream_class_map_clock_class() at the end of this
+                * function is safe because it maps to the same, single
+                * clock class.
+                */
+               ret = bt_stream_class_validate_single_clock_class(stream_class,
+                       &expected_clock_class);
+               if (ret) {
+                       BT_LOGW("Invalid parameter: stream class or one of its "
+                               "event classes contains a field type which is "
+                               "not recursively mapped to the expected "
+                               "clock class: "
+                               "stream-class-addr=%p, "
+                               "stream-class-id=%" PRId64 ", "
+                               "stream-class-name=\"%s\", "
+                               "expected-clock-class-addr=%p, "
+                               "expected-clock-class-name=\"%s\"",
+                               stream_class, bt_stream_class_get_id(stream_class),
+                               bt_stream_class_get_name(stream_class),
+                               expected_clock_class,
+                               expected_clock_class ?
+                                       bt_clock_class_get_name(expected_clock_class) :
+                                       NULL);
+                       goto end;
+               }
+       }
+
+       ret = check_packet_header_type_has_no_clock_class(trace);
+       if (ret) {
+               /* check_packet_header_type_has_no_clock_class() logs errors */
+               goto end;
        }
 
        /*
@@ -1451,6 +1561,14 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
        bt_stream_class_freeze(stream_class);
        bt_trace_freeze(trace);
 
+       /*
+        * It is safe to set the stream class's unique clock class
+        * now because the stream class is frozen.
+        */
+       if (expected_clock_class) {
+               BT_MOVE(stream_class->clock_class, expected_clock_class);
+       }
+
        /* Notifiy listeners of the trace's schema modification. */
        bt_stream_class_visit(stream_class,
                        bt_trace_object_modification, trace);
@@ -1477,10 +1595,11 @@ end:
        g_free(ec_validation_outputs);
        bt_validation_output_put_types(&trace_sc_validation_output);
        bt_put(current_parent_trace);
-       assert(!packet_header_type);
-       assert(!packet_context_type);
-       assert(!event_header_type);
-       assert(!stream_event_ctx_type);
+       bt_put(expected_clock_class);
+       BT_ASSERT(!packet_header_type);
+       BT_ASSERT(!packet_context_type);
+       BT_ASSERT(!event_header_type);
+       BT_ASSERT(!stream_event_ctx_type);
        return ret;
 }
 
@@ -1645,8 +1764,8 @@ bt_bool bt_trace_has_clock_class(struct bt_trace *trace,
 {
        struct search_query query = { .value = clock_class, .found = 0 };
 
-       assert(trace);
-       assert(clock_class);
+       BT_ASSERT(trace);
+       BT_ASSERT(clock_class);
 
        g_ptr_array_foreach(trace->clocks, value_exists, &query);
        return query.found;
@@ -1694,7 +1813,7 @@ int append_trace_metadata(struct bt_trace *trace,
        g_string_append(context->string, "trace {\n");
        g_string_append(context->string, "\tmajor = 1;\n");
        g_string_append(context->string, "\tminor = 8;\n");
-       assert(trace->native_byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN ||
+       BT_ASSERT(trace->native_byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN ||
                trace->native_byte_order == BT_BYTE_ORDER_BIG_ENDIAN ||
                trace->native_byte_order == BT_BYTE_ORDER_NETWORK);
 
@@ -1751,8 +1870,8 @@ void append_env_metadata(struct bt_trace *trace,
                env_field_value_obj = bt_attributes_get_field_value(
                        trace->environment, i);
 
-               assert(entry_name);
-               assert(env_field_value_obj);
+               BT_ASSERT(entry_name);
+               BT_ASSERT(env_field_value_obj);
 
                switch (bt_value_get_type(env_field_value_obj)) {
                case BT_VALUE_TYPE_INTEGER:
@@ -1762,7 +1881,7 @@ void append_env_metadata(struct bt_trace *trace,
 
                        ret = bt_value_integer_get(env_field_value_obj,
                                &int_value);
-                       assert(ret == 0);
+                       BT_ASSERT(ret == 0);
                        g_string_append_printf(context->string,
                                "\t%s = %" PRId64 ";\n", entry_name,
                                int_value);
@@ -1776,7 +1895,7 @@ void append_env_metadata(struct bt_trace *trace,
 
                        ret = bt_value_string_get(env_field_value_obj,
                                &str_value);
-                       assert(ret == 0);
+                       BT_ASSERT(ret == 0);
                        escaped_str = g_strescape(str_value, NULL);
                        if (!escaped_str) {
                                BT_LOGE("Cannot escape string: string=\"%s\"",
@@ -2069,8 +2188,8 @@ int bt_trace_object_modification(struct bt_visitor_object *object,
        size_t i;
        struct bt_trace *trace = trace_ptr;
 
-       assert(trace);
-       assert(object);
+       BT_ASSERT(trace);
+       BT_ASSERT(object);
 
        if (trace->listeners->len == 0) {
                goto end;
@@ -2164,6 +2283,12 @@ int bt_trace_set_is_static(struct bt_trace *trace)
                goto end;
        }
 
+       ret = check_packet_header_type_has_no_clock_class(trace);
+       if (ret) {
+               /* check_packet_header_type_has_no_clock_class() logs errors */
+               goto end;
+       }
+
        trace->is_static = BT_TRUE;
        bt_trace_freeze(trace);
        BT_LOGV("Set trace static: addr=%p, name=\"%s\"",
This page took 0.028007 seconds and 5 git commands to generate.