struct bt_ctf_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer, struct bt_ctf_stream_class *stream_class) { int ret; int stream_class_found = 0; size_t i; int stream_fd; struct bt_ctf_stream *stream = NULL; if (!writer || !stream_class) { goto error; } ret = bt_ctf_stream_class_set_byte_order(stream_class, writer->byte_order == LITTLE_ENDIAN ? BT_CTF_BYTE_ORDER_LITTLE_ENDIAN : BT_CTF_BYTE_ORDER_BIG_ENDIAN); if (ret) { goto error; } stream = bt_ctf_stream_create(stream_class); if (!stream) { goto error; } stream_fd = create_stream_file(writer, stream); if (stream_fd < 0 || bt_ctf_stream_set_fd(stream, stream_fd)) { goto error; } bt_ctf_stream_set_flush_callback(stream, (flush_func)stream_flush_cb, writer); for (i = 0; i < writer->stream_classes->len; i++) { if (writer->stream_classes->pdata[i] == stream->stream_class) { stream_class_found = 1; } } if (!stream_class_found) { int64_t stream_id = bt_ctf_stream_class_get_id(stream_class); if (stream_id < 0) { if (bt_ctf_stream_class_set_id(stream->stream_class, writer->next_stream_id++)) { goto error; } } for (i = 0; i < writer->stream_classes->len; i++) { if (stream_id == bt_ctf_stream_class_get_id( writer->stream_classes->pdata[i])) { /* Duplicate stream id found */ goto error; } } bt_ctf_stream_class_get(stream->stream_class); g_ptr_array_add(writer->stream_classes, stream->stream_class); } bt_ctf_stream_get(stream); g_ptr_array_add(writer->streams, stream); writer->frozen = 1; return stream; error: bt_ctf_stream_put(stream); return NULL; }
struct bt_ctf_stream *bt_ctf_stream_create( struct bt_ctf_stream_class *stream_class, const char *name) { int ret; struct bt_ctf_stream *stream = NULL; struct bt_ctf_trace *trace = NULL; struct bt_ctf_writer *writer = NULL; if (!stream_class) { goto error; } trace = bt_ctf_stream_class_get_trace(stream_class); if (!trace) { goto error; } stream = g_new0(struct bt_ctf_stream, 1); if (!stream) { goto error; } bt_object_init(stream, bt_ctf_stream_destroy); /* * Acquire reference to parent since stream will become publicly * reachable; it needs its parent to remain valid. */ bt_object_set_parent(stream, trace); stream->id = stream_class->next_stream_id++; stream->stream_class = stream_class; stream->pos.fd = -1; if (name) { stream->name = g_string_new(name); if (!stream->name) { goto error; } } if (trace->is_created_by_writer) { int fd; writer = (struct bt_ctf_writer *) bt_object_get_parent(trace); assert(writer); stream->packet_context = bt_ctf_field_create( stream_class->packet_context_type); if (!stream->packet_context) { goto error; } /* Initialize events_discarded */ ret = set_structure_field_integer(stream->packet_context, "events_discarded", 0); if (ret) { goto error; } stream->events = g_ptr_array_new_with_free_func( (GDestroyNotify) release_event); if (!stream->events) { goto error; } /* A trace is not allowed to have a NULL packet header */ assert(trace->packet_header_type); stream->packet_header = bt_ctf_field_create(trace->packet_header_type); if (!stream->packet_header) { goto error; } /* * Attempt to populate the default trace packet header fields * (magic, uuid and stream_id). This will _not_ fail shall the * fields not be found or be of an incompatible type; they will * simply not be populated automatically. The user will have to * make sure to set the trace packet header fields himself * before flushing. */ ret = set_packet_header(stream); if (ret) { goto error; } /* Create file associated with this stream */ fd = create_stream_file(writer, stream); if (fd < 0) { goto error; } ret = set_stream_fd(stream, fd); if (ret) { goto error; } /* Freeze the writer */ bt_ctf_writer_freeze(writer); } else { /* Non-writer stream indicated by a negative FD */ ret = set_stream_fd(stream, -1); if (ret) { goto error; } stream->clock_values = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); } /* Add this stream to the trace's streams */ g_ptr_array_add(trace->streams, stream); BT_PUT(trace); BT_PUT(writer); return stream; error: BT_PUT(stream); BT_PUT(trace); BT_PUT(writer); return stream; }