+ goto end;
+
+error:
+ if (*header_field) {
+ release_header_field_func(*header_field);
+ }
+
+ if (*stream_event_context_field) {
+ release_field_func(*stream_event_context_field);
+ }
+
+ if (*context_field) {
+ release_field_func(*context_field);
+ }
+
+ if (*payload_field) {
+ release_field_func(*payload_field);
+ }
+
+ ret = -1;
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int _bt_event_common_validate(struct bt_event_common *event)
+{
+ int ret = 0;
+ struct bt_stream_class_common *stream_class;
+
+ BT_ASSERT(event);
+ if (event->header_field) {
+ ret = bt_field_common_validate_recursive(
+ event->header_field->field);
+ if (ret) {
+ BT_ASSERT_PRE_MSG("Invalid event's header field: "
+ "%![event-]+_e, %![field-]+_f",
+ event, event->header_field->field);
+ goto end;
+ }
+ }
+
+ stream_class = bt_event_class_common_borrow_stream_class(event->class);
+
+ /*
+ * We should not have been able to create the event without associating
+ * the event class to a stream class.
+ */
+ BT_ASSERT(stream_class);
+
+ if (stream_class->event_context_field_type) {
+ ret = bt_field_common_validate_recursive(
+ event->stream_event_context_field);
+ if (ret) {
+ BT_ASSERT_PRE_MSG("Invalid event's stream event context field: "
+ "%![event-]+_e, %![field-]+_f",
+ event, event->stream_event_context_field);
+ goto end;
+ }
+ }
+
+ if (event->class->context_field_type) {
+ ret = bt_field_common_validate_recursive(event->context_field);
+ if (ret) {
+ BT_ASSERT_PRE_MSG("Invalid event's payload field: "
+ "%![event-]+_e, %![field-]+_f",
+ event, event->context_field);
+ goto end;
+ }
+ }
+
+ ret = bt_field_common_validate_recursive(event->payload_field);
+ if (ret) {
+ BT_ASSERT_PRE_MSG("Invalid event's payload field: "
+ "%![event-]+_e, %![field-]+_f",
+ event, event->payload_field);
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+void _bt_event_common_freeze(struct bt_event_common *event)
+{
+ BT_ASSERT(event);
+
+ if (event->frozen) {
+ return;
+ }
+
+ BT_LOGD("Freezing event: addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64,
+ event, bt_event_class_common_get_name(event->class),
+ bt_event_class_common_get_id(event->class));
+
+ if (event->header_field) {
+ BT_LOGD_STR("Freezing event's header field.");
+ bt_field_common_set_is_frozen_recursive(
+ event->header_field->field, true);
+ }
+
+ if (event->stream_event_context_field) {
+ BT_LOGD_STR("Freezing event's stream event context field.");
+ bt_field_common_set_is_frozen_recursive(
+ event->stream_event_context_field, true);
+ }
+
+ if (event->context_field) {
+ BT_LOGD_STR("Freezing event's context field.");
+ bt_field_common_set_is_frozen_recursive(event->context_field, true);
+ }
+
+ if (event->payload_field) {
+ BT_LOGD_STR("Freezing event's payload field.");
+ bt_field_common_set_is_frozen_recursive(event->payload_field, true);
+ }
+
+ event->frozen = 1;
+}
+
+BT_HIDDEN
+int bt_event_common_initialize(struct bt_event_common *event,
+ struct bt_event_class_common *event_class,
+ struct bt_clock_class *init_expected_clock_class,
+ bt_object_release_func release_func,
+ bt_validation_flag_copy_field_type_func field_type_copy_func,
+ bool must_be_in_trace,
+ int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
+ struct bt_field_type_common *packet_context_field_type,
+ struct bt_field_type_common *event_header_field_type),
+ void *(*create_field_func)(void *),
+ void (*release_field_func)(void *),
+ void *(*create_header_field_func)(void *, void *),
+ void (*release_header_field_func)(void *))
+{
+ int ret;
+ struct bt_trace_common *trace = NULL;
+ struct bt_stream_class_common *stream_class = NULL;
+ struct bt_field_wrapper *event_header = NULL;
+ struct bt_field_common *stream_event_context = NULL;
+ struct bt_field_common *event_context = NULL;
+ struct bt_field_common *event_payload = NULL;
+ struct bt_validation_output validation_output = { 0 };
+ struct bt_clock_class *expected_clock_class =
+ init_expected_clock_class ? bt_get(init_expected_clock_class) :
+ NULL;
+
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_LOGD("Initializing common event object: event-class-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64,
+ event_class, bt_event_class_common_get_name(event_class),
+ bt_event_class_common_get_id(event_class));
+
+ stream_class = bt_event_class_common_borrow_stream_class(event_class);
+ BT_ASSERT_PRE(stream_class,
+ "Event class is not part of a stream class: %!+_E", event_class);
+
+ /* The event class was frozen when added to its stream class */
+ BT_ASSERT(event_class->frozen);
+ trace = bt_stream_class_common_borrow_trace(stream_class);
+
+ if (must_be_in_trace) {
+ BT_ASSERT_PRE(trace,
+ "Event class's stream class is not part of a trace: "
+ "%![ec-]+_E, %![ec-]+_S", event_class, stream_class);
+ }
+
+ /*
+ * This must be called before anything that can fail because on
+ * failure, the caller releases the reference to `event` to
+ * destroy it.
+ */
+ bt_object_init(event, release_func);
+
+ if (!stream_class->frozen) {
+ /*
+ * Because this function freezes the stream class,
+ * validate that this stream class contains at most a
+ * single clock class so that we set its expected clock
+ * class for future checks.
+ */
+ ret = bt_stream_class_common_validate_single_clock_class(
+ stream_class, &expected_clock_class);
+ if (ret) {
+ BT_LOGW("Event class's 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_common_get_id(stream_class),
+ bt_stream_class_common_get_name(stream_class),
+ expected_clock_class,
+ expected_clock_class ?
+ bt_clock_class_get_name(expected_clock_class) :
+ NULL);
+ goto error;
+ }
+ }
+
+ /* Validate the trace, the stream class, and the event class */
+ ret = bt_event_common_validate_types_for_create(
+ event_class, &validation_output, field_type_copy_func);
+ if (ret) {
+ /* bt_event_common_validate_types_for_create() logs errors */
+ goto error;
+ }
+
+ if (map_clock_classes_func) {
+ /*
+ * Safe to automatically map selected fields to the
+ * stream's clock's class here because the stream class
+ * is about to be frozen.
+ */
+ if (map_clock_classes_func(stream_class,
+ validation_output.packet_context_type,
+ validation_output.event_header_type)) {
+ BT_LOGW_STR("Cannot automatically map selected stream class's "
+ "field types to stream class's clock's class.");
+ goto error;
+ }
+ }
+
+ /*
+ * event does not share a common ancestor with the event class; it has
+ * to guarantee its existence by holding a reference. This reference
+ * shall be released once the event is associated to a stream since,
+ * from that point, the event and its class will share the same
+ * lifetime.
+ */
+ event->class = bt_get(event_class);
+
+ ret = bt_event_common_create_fields(stream_class,
+ &validation_output,
+ create_field_func, release_field_func,
+ create_header_field_func, release_header_field_func,
+ &event_header, &stream_event_context, &event_context,
+ &event_payload);
+ if (ret) {
+ /* bt_event_common_create_fields() logs errors */
+ goto error;
+ }
+