int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace, struct bt_ctf_stream_class *stream_class) { int ret, i; int64_t stream_id; if (!trace || !stream_class) { ret = -1; goto end; } for (i = 0; i < trace->stream_classes->len; i++) { if (trace->stream_classes->pdata[i] == stream_class) { /* Stream already registered to the trace */ ret = -1; goto end; } } ret = bt_ctf_stream_class_resolve_types(stream_class, trace); if (ret) { goto end; } stream_id = bt_ctf_stream_class_get_id(stream_class); if (stream_id < 0) { stream_id = trace->next_stream_id++; /* Try to assign a new stream id */ for (i = 0; i < trace->stream_classes->len; i++) { if (stream_id == bt_ctf_stream_class_get_id( trace->stream_classes->pdata[i])) { /* Duplicate stream id found */ ret = -1; goto end; } } if (bt_ctf_stream_class_set_id_no_check(stream_class, stream_id)) { /* TODO Should retry with a different stream id */ ret = -1; goto end; } } /* Set weak reference to trace in stream class */ ret = bt_ctf_stream_class_set_trace(stream_class, trace); if (ret) { /* Stream class already part of another trace */ goto end; } bt_get(stream_class); g_ptr_array_add(trace->stream_classes, stream_class); /* * Freeze the trace and its packet header. * * All field type byte orders set as "native" byte ordering can now be * safely set to trace's own endianness, including the stream class'. */ bt_ctf_field_type_set_native_byte_order(trace->packet_header_type, trace->byte_order); ret = bt_ctf_stream_class_set_byte_order(stream_class, trace->byte_order == LITTLE_ENDIAN ? BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN); if (ret) { goto end; } bt_ctf_stream_class_freeze(stream_class); if (!trace->frozen) { ret = bt_ctf_trace_freeze(trace); goto end; } end: if (ret) { (void) bt_ctf_stream_class_set_trace(stream_class, NULL); } return ret; }
struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class) { int ret; enum bt_ctf_validation_flag validation_flags = BT_CTF_VALIDATION_FLAG_STREAM | BT_CTF_VALIDATION_FLAG_EVENT; struct bt_ctf_event *event = NULL; struct bt_ctf_trace *trace = NULL; struct bt_ctf_stream_class *stream_class = NULL; struct bt_ctf_field_type *packet_header_type = NULL; struct bt_ctf_field_type *packet_context_type = NULL; struct bt_ctf_field_type *event_header_type = NULL; struct bt_ctf_field_type *stream_event_ctx_type = NULL; struct bt_ctf_field_type *event_context_type = NULL; struct bt_ctf_field_type *event_payload_type = NULL; struct bt_ctf_field *event_header = NULL; struct bt_ctf_field *stream_event_context = NULL; struct bt_ctf_field *event_context = NULL; struct bt_ctf_field *event_payload = NULL; struct bt_value *environment = NULL; struct bt_ctf_validation_output validation_output = { 0 }; int trace_valid = 0; if (!event_class) { goto error; } stream_class = bt_ctf_event_class_get_stream_class(event_class); /* * We disallow the creation of an event if its event class has not been * associated to a stream class. */ if (!stream_class) { goto error; } /* A stream class should always have an existing event header type */ assert(stream_class->event_header_type); /* The event class was frozen when added to its stream class */ assert(event_class->frozen); /* Validate the trace (if any), the stream class, and the event class */ trace = bt_ctf_stream_class_get_trace(stream_class); if (trace) { packet_header_type = bt_ctf_trace_get_packet_header_type(trace); trace_valid = trace->valid; assert(trace_valid); environment = trace->environment; } packet_context_type = bt_ctf_stream_class_get_packet_context_type( stream_class); event_header_type = bt_ctf_stream_class_get_event_header_type( stream_class); stream_event_ctx_type = bt_ctf_stream_class_get_event_context_type( stream_class); event_context_type = bt_ctf_event_class_get_context_type(event_class); event_payload_type = bt_ctf_event_class_get_payload_type(event_class); ret = bt_ctf_validate_class_types(environment, packet_header_type, packet_context_type, event_header_type, stream_event_ctx_type, event_context_type, event_payload_type, trace_valid, stream_class->valid, event_class->valid, &validation_output, validation_flags); BT_PUT(packet_header_type); BT_PUT(packet_context_type); BT_PUT(event_header_type); BT_PUT(stream_event_ctx_type); BT_PUT(event_context_type); BT_PUT(event_payload_type); if (ret) { /* * This means something went wrong during the validation * process, not that the objects are invalid. */ goto error; } if ((validation_output.valid_flags & validation_flags) != validation_flags) { /* Invalid trace/stream class/event class */ goto error; } /* * At this point we know the trace (if associated to the stream * class), the stream class, and the event class, with their * current types, are valid. We may proceed with creating * the event. */ event = g_new0(struct bt_ctf_event, 1); if (!event) { goto error; } bt_object_init(event, bt_ctf_event_destroy); /* * 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->event_class = bt_get(event_class); event->clock_values = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); event_header = bt_ctf_field_create(validation_output.event_header_type); if (!event_header) { goto error; } if (validation_output.stream_event_ctx_type) { stream_event_context = bt_ctf_field_create( validation_output.stream_event_ctx_type); if (!stream_event_context) { goto error; } } if (validation_output.event_context_type) { event_context = bt_ctf_field_create( validation_output.event_context_type); if (!event_context) { goto error; } } if (validation_output.event_payload_type) { event_payload = bt_ctf_field_create( validation_output.event_payload_type); if (!event_payload) { goto error; } } /* * At this point all the fields are created, potentially from * validated copies of field types, so that the field types and * fields can be replaced in the trace, stream class, * event class, and created event. */ bt_ctf_validation_replace_types(trace, stream_class, event_class, &validation_output, validation_flags); BT_MOVE(event->event_header, event_header); BT_MOVE(event->stream_event_context, stream_event_context); BT_MOVE(event->context_payload, event_context); BT_MOVE(event->fields_payload, event_payload); /* * Put what was not moved in bt_ctf_validation_replace_types(). */ bt_ctf_validation_output_put_types(&validation_output); /* * Freeze the stream class since the event header must not be changed * anymore. */ bt_ctf_stream_class_freeze(stream_class); /* * Mark stream class, and event class as valid since * they're all frozen now. */ stream_class->valid = 1; event_class->valid = 1; /* Put stuff we borrowed from the event class */ BT_PUT(stream_class); BT_PUT(trace); return event; error: bt_ctf_validation_output_put_types(&validation_output); BT_PUT(event); BT_PUT(stream_class); BT_PUT(trace); BT_PUT(event_header); BT_PUT(stream_event_context); BT_PUT(event_context); BT_PUT(event_payload); 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); return event; }