#include <babeltrace/ctf-ir/visitor-internal.h>
#include <babeltrace/ctf-writer/functor-internal.h>
#include <babeltrace/ctf-ir/utils.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
#include <babeltrace/endian-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
struct bt_trace *bt_stream_class_get_trace(
struct bt_stream_class *stream_class)
{
- return stream_class ?
- bt_get(bt_stream_class_borrow_trace(stream_class)) :
- NULL;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return bt_get(bt_stream_class_borrow_trace(stream_class));
}
const char *bt_stream_class_get_name(
struct bt_stream_class *stream_class)
{
- const char *name = NULL;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
-
- name = stream_class->name->len > 0 ? stream_class->name->str : NULL;
-end:
- return name;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return stream_class->name->len > 0 ? stream_class->name->str : NULL;
}
int bt_stream_class_set_name(struct bt_stream_class *stream_class,
{
int64_t ret;
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = (int64_t) -1;
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
if (!stream_class->id_set) {
BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
}
ret = stream_class->id;
+
end:
return ret;
}
void _bt_stream_class_set_id(
struct bt_stream_class *stream_class, int64_t id)
{
- assert(stream_class);
+ BT_ASSERT(stream_class);
stream_class->id = id;
stream_class->id_set = 1;
BT_LOGV("Set stream class's ID (internal): "
struct bt_field_type *event_payload_type = NULL;
const enum bt_validation_flag validation_flags =
BT_VALIDATION_FLAG_EVENT;
+ struct bt_clock_class *expected_clock_class = NULL;
if (!stream_class || !event_class) {
BT_LOGW("Invalid parameter: stream class or event class is NULL: "
trace = bt_stream_class_get_trace(stream_class);
if (trace && trace->is_static) {
+ BT_LOGW("Invalid parameter: stream class's trace is static: "
+ "trace-addr=%p, trace-name=\"%s\"",
+ trace, bt_trace_get_name(trace));
ret = -1;
goto end;
}
+ if (stream_class->frozen) {
+ /*
+ * We only check that the event class to be added has a
+ * single class which matches the stream class's
+ * expected clock class if the stream class is frozen.
+ * If it's not, then this event class is added "as is"
+ * and the validation will be performed when calling
+ * either bt_trace_add_stream_class() or
+ * bt_event_create(). This is because the stream class's
+ * field types (packet context, event header, event
+ * context) could change before the next call to one of
+ * those two functions.
+ */
+ expected_clock_class = bt_get(stream_class->clock_class);
+
+ /*
+ * At this point, `expected_clock_class` can be NULL,
+ * and bt_event_class_validate_single_clock_class()
+ * below can set it.
+ */
+ ret = bt_event_class_validate_single_clock_class(
+ event_class, &expected_clock_class);
+ if (ret) {
+ BT_LOGW("Event class contains a field type which is not "
+ "recursively mapped to its 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,
+ expected_clock_class ?
+ bt_clock_class_get_name(expected_clock_class) :
+ NULL);
+ goto end;
+ }
+ }
+
event_id = g_new(int64_t, 1);
if (!event_id) {
BT_LOGE_STR("Failed to allocate one int64_t.");
* The trace and stream class should be valid at this
* point.
*/
- assert(trace->valid);
- assert(stream_class->valid);
+ BT_ASSERT(trace->valid);
+ BT_ASSERT(stream_class->valid);
packet_header_type =
bt_trace_get_packet_header_type(trace);
packet_context_type =
/* Freeze the event class */
bt_event_class_freeze(event_class);
+ /*
+ * It is safe to set the stream class's unique clock class
+ * now if the stream class is frozen.
+ */
+ if (stream_class->frozen && expected_clock_class) {
+ BT_ASSERT(!stream_class->clock_class ||
+ stream_class->clock_class == expected_clock_class);
+ BT_MOVE(stream_class->clock_class, expected_clock_class);
+ }
+
/* Notifiy listeners of the trace's schema modification. */
if (trace) {
struct bt_visitor_object obj = { .object = event_class,
BT_PUT(trace);
BT_PUT(old_stream_class);
bt_validation_output_put_types(&validation_output);
- assert(!packet_header_type);
- assert(!packet_context_type);
- assert(!event_header_type);
- assert(!stream_event_ctx_type);
- assert(!event_context_type);
- assert(!event_payload_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);
+ BT_ASSERT(!event_context_type);
+ BT_ASSERT(!event_payload_type);
g_free(event_id);
return ret;
struct bt_event_class *bt_stream_class_get_event_class_by_index(
struct bt_stream_class *stream_class, uint64_t index)
{
- struct bt_event_class *event_class = NULL;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
-
- 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_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- index, stream_class->event_classes->len);
- goto end;
- }
-
- event_class = g_ptr_array_index(stream_class->event_classes, index);
- bt_get(event_class);
-end:
- return event_class;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(index < stream_class->event_classes->len,
+ "Index is out of bounds: index=%" PRIu64 ", "
+ "count=%u",
+ index, stream_class->event_classes->len);
+ return bt_get(g_ptr_array_index(stream_class->event_classes, index));
}
struct bt_event_class *bt_stream_class_get_event_class_by_id(
struct bt_stream_class *stream_class, uint64_t id)
{
int64_t id_key = (int64_t) id;
- struct bt_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_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class), id);
- goto end;
- }
-
- event_class = g_hash_table_lookup(stream_class->event_classes_ht,
- &id_key);
- bt_get(event_class);
-end:
- return event_class;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(id_key >= 0,
+ "Invalid event class ID: %" PRIu64, id);
+ return bt_get(g_hash_table_lookup(stream_class->event_classes_ht,
+ &id_key));
}
struct bt_field_type *bt_stream_class_get_packet_context_type(
struct bt_stream_class *stream_class)
{
- struct bt_field_type *ret = NULL;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
-
- bt_get(stream_class->packet_context_type);
- ret = stream_class->packet_context_type;
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return bt_get(stream_class->packet_context_type);
}
int bt_stream_class_set_packet_context_type(
{
struct bt_field_type *ret = NULL;
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
if (!stream_class->event_header_type) {
BT_LOGV("Stream class has no event header field type: "
goto end;
}
- bt_get(stream_class->event_header_type);
- ret = stream_class->event_header_type;
+ ret = bt_get(stream_class->event_header_type);
+
end:
return ret;
}
{
struct bt_field_type *ret = NULL;
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
if (!stream_class->event_context_type) {
goto end;
}
- bt_get(stream_class->event_context_type);
- ret = stream_class->event_context_type;
+ ret = bt_get(stream_class->event_context_type);
+
end:
return ret;
}
* and serialization.
*/
trace = bt_stream_class_borrow_trace(stream_class);
- assert(trace);
+ BT_ASSERT(trace);
packet_header_type = bt_trace_get_packet_header_type(trace);
trace = NULL;
if (packet_header_type) {
stream_class, bt_stream_class_get_name(stream_class),
bt_stream_class_get_id(stream_class));
bt_put(stream_class->clock);
+ bt_put(stream_class->clock_class);
if (stream_class->event_classes_ht) {
g_hash_table_destroy(stream_class->event_classes_ht);
static
int try_map_clock_class(struct bt_stream_class *stream_class,
- struct bt_field_type *ft)
+ struct bt_field_type *parent_ft, const char *field_name)
{
struct bt_clock_class *mapped_clock_class = NULL;
int ret = 0;
+ struct bt_field_type *ft =
+ bt_field_type_structure_get_field_type_by_name(parent_ft,
+ field_name);
+
+ BT_ASSERT(stream_class->clock);
if (!ft) {
/* Field does not exist: not an error */
goto end;
}
- assert(bt_field_type_is_integer(ft));
+ BT_ASSERT(bt_field_type_is_integer(ft));
mapped_clock_class =
bt_field_type_integer_get_mapped_clock_class(ft);
if (!mapped_clock_class) {
+ struct bt_field_type *ft_copy;
+
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\", "
goto end;
}
- ret = bt_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_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class), ft);
- goto end;
+ ft_copy = bt_field_type_copy(ft);
+ if (!ft_copy) {
+ BT_LOGE("Failed to copy integer field type: ft-addr=%p",
+ ft);
}
+ ret = bt_field_type_integer_set_mapped_clock_class_no_check(
+ ft_copy, stream_class->clock->clock_class);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_replace_field(parent_ft,
+ field_name, ft_copy);
+ bt_put(ft_copy);
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-id=%" PRId64 ", ft-addr=%p, "
+ "ft-copy-addr=%p",
stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class), ft);
+ bt_stream_class_get_id(stream_class), ft, ft_copy);
}
end:
+ bt_put(ft);
bt_put(mapped_clock_class);
return ret;
}
struct bt_field_type *packet_context_type,
struct bt_field_type *event_header_type)
{
- struct bt_field_type *ft = NULL;
int ret = 0;
- assert(stream_class);
+ BT_ASSERT(stream_class);
+
+ if (!stream_class->clock) {
+ /* No clock class to map to */
+ goto end;
+ }
if (packet_context_type) {
- ft = bt_field_type_structure_get_field_type_by_name(
- packet_context_type, "timestamp_begin");
- if (try_map_clock_class(stream_class, ft)) {
+ if (try_map_clock_class(stream_class, packet_context_type,
+ "timestamp_begin")) {
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_field_type_structure_get_field_type_by_name(
- packet_context_type, "timestamp_end");
- if (try_map_clock_class(stream_class, ft)) {
+ if (try_map_clock_class(stream_class, packet_context_type,
+ "timestamp_end")) {
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_field_type_structure_get_field_type_by_name(
- event_header_type, "timestamp");
- if (try_map_clock_class(stream_class, ft)) {
+ if (try_map_clock_class(stream_class, event_header_type,
+ "timestamp")) {
BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
ret = -1;
goto end;
}
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int bt_stream_class_validate_single_clock_class(
+ struct bt_stream_class *stream_class,
+ struct bt_clock_class **expected_clock_class)
+{
+ int ret;
+ uint64_t i;
+
+ BT_ASSERT(stream_class);
+ BT_ASSERT(expected_clock_class);
+ ret = bt_validate_single_clock_class(stream_class->packet_context_type,
+ expected_clock_class);
+ if (ret) {
+ BT_LOGW("Stream class's packet context field type "
+ "is not recursively mapped to the "
+ "expected clock class: "
+ "stream-class-addr=%p, "
+ "stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", "
+ "ft-addr=%p",
+ stream_class,
+ bt_stream_class_get_name(stream_class),
+ stream_class->id,
+ stream_class->packet_context_type);
+ goto end;
+ }
+
+ ret = bt_validate_single_clock_class(stream_class->event_header_type,
+ expected_clock_class);
+ if (ret) {
+ BT_LOGW("Stream class's event header field type "
+ "is not recursively mapped to the "
+ "expected clock class: "
+ "stream-class-addr=%p, "
+ "stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", "
+ "ft-addr=%p",
+ stream_class,
+ bt_stream_class_get_name(stream_class),
+ stream_class->id,
+ stream_class->event_header_type);
+ goto end;
+ }
- BT_PUT(ft);
+ ret = bt_validate_single_clock_class(stream_class->event_context_type,
+ expected_clock_class);
+ if (ret) {
+ BT_LOGW("Stream class's event context field type "
+ "is not recursively mapped to the "
+ "expected clock class: "
+ "stream-class-addr=%p, "
+ "stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", "
+ "ft-addr=%p",
+ stream_class,
+ bt_stream_class_get_name(stream_class),
+ stream_class->id,
+ stream_class->event_context_type);
+ goto end;
+ }
+
+ for (i = 0; i < stream_class->event_classes->len; i++) {
+ struct bt_event_class *event_class =
+ g_ptr_array_index(stream_class->event_classes, i);
+
+ BT_ASSERT(event_class);
+ ret = bt_event_class_validate_single_clock_class(event_class,
+ expected_clock_class);
+ if (ret) {
+ BT_LOGW("Stream class's event class contains a "
+ "field type which is not recursively mapped to "
+ "the expected clock class: "
+ "stream-class-addr=%p, "
+ "stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64,
+ stream_class,
+ bt_stream_class_get_name(stream_class),
+ stream_class->id);
+ goto end;
+ }
}
end: