From cfe11c58e0fea043bdfa97d732b9d02db13b492a Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Tue, 23 May 2017 20:43:00 -0400 Subject: [PATCH] ir: add stream ID API MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The new bt_ctf_stream_create_with_id() function creates a stream object, just like bt_ctf_stream_create(), but with a numeric ID. You cannot call this function to create a CTF writer stream because CTF writer streams initialize their own unique ID. Use bt_ctf_stream_get_id() to get a stream's ID. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- include/babeltrace/ctf-ir/stream-internal.h | 2 +- include/babeltrace/ctf-ir/stream.h | 54 ++++++++- lib/ctf-ir/stream.c | 128 +++++++++++++++++--- 3 files changed, 166 insertions(+), 18 deletions(-) diff --git a/include/babeltrace/ctf-ir/stream-internal.h b/include/babeltrace/ctf-ir/stream-internal.h index 0b844b8a..87395b10 100644 --- a/include/babeltrace/ctf-ir/stream-internal.h +++ b/include/babeltrace/ctf-ir/stream-internal.h @@ -49,7 +49,7 @@ struct bt_ctf_stream_destroy_listener { struct bt_ctf_stream { struct bt_object base; - uint32_t id; + int64_t id; struct bt_ctf_stream_class *stream_class; GString *name; struct bt_ctf_field *packet_header; diff --git a/include/babeltrace/ctf-ir/stream.h b/include/babeltrace/ctf-ir/stream.h index 510f17dc..140970c5 100644 --- a/include/babeltrace/ctf-ir/stream.h +++ b/include/babeltrace/ctf-ir/stream.h @@ -55,8 +55,9 @@ A CTF IR stream is an instance of a You can obtain a CTF IR stream object in two different modes: -- Normal mode: use bt_ctf_stream_create() with a stream - class having a \link ctfirtraceclass CTF IR trace class\endlink parent +- Normal mode: use bt_ctf_stream_create() or + bt_ctf_stream_create_with_id() with a stream class having a + \link ctfirtraceclass CTF IR trace class\endlink parent \em not created by a \link ctfwriter CTF writer\endlink object to create a default stream. - CTF writer mode: use bt_ctf_stream_create() with @@ -123,11 +124,48 @@ functions documented in this module on it. @prenotnull{stream_class} @pre \p stream_class has a parent trace class. @postsuccessrefcountret1 + +@sa bt_ctf_stream_create_with_id(): Create a CTF IR stream with a + specific ID. */ extern struct bt_ctf_stream *bt_ctf_stream_create( struct bt_ctf_stream_class *stream_class, const char *name); +/** +@brief Creates a default CTF IR stream named \p name with ID \p id + from the CTF IR stream class \p stream_class. + +\p stream_class \em must have a parent +\link ctfirtraceclass CTF IR trace class\endlink. + +You \em must have created the trace class of \p stream class directly +with bt_ctf_trace_create(), not through bt_ctf_writer_create() (use +bt_ctf_stream_create() for this). + +\p id \em must be unique amongst the IDs of all the streams created +from \p stream_class with bt_ctf_stream_create_with_id(). + +\p name can be \c NULL to create an unnamed stream object. + +@param[in] stream_class CTF IR stream class to use to create the + CTF IR stream. +@param[in] name Name of the stream object to create (copied on + success) or \c NULL to create an unnamed stream. +@param[in] id ID of the stream object to create. +@returns Created stream object, or \c NULL on error. + +@prenotnull{stream_class} +@pre \p id is lesser than or equal to 9223372036854775807 (\c INT64_MAX). +@pre \p stream_class has a parent trace class. +@postsuccessrefcountret1 + +@sa bt_ctf_stream_create(): Create a CTF IR stream without an ID. +*/ +extern struct bt_ctf_stream *bt_ctf_stream_create_with_id( + struct bt_ctf_stream_class *stream_class, + const char *name, uint64_t id); + /** @brief Returns the name of the CTF IR stream \p stream. @@ -142,6 +180,18 @@ On success, \p stream remains the sole owner of the returned string. */ extern const char *bt_ctf_stream_get_name(struct bt_ctf_stream *stream); +/** +@brief Returns the numeric ID of the CTF IR stream \p stream. + +@param[in] stream Stream of which to get the numeric ID. +@returns ID of stream \p stream, or a negative value + on error. + +@prenotnull{stream} +@postrefcountsame{stream} +*/ +extern int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream); + /** @brief Returns the parent CTF IR stream class of the CTF IR stream \p stream. diff --git a/lib/ctf-ir/stream.c b/lib/ctf-ir/stream.c index 402597ed..3ff937ac 100644 --- a/lib/ctf-ir/stream.c +++ b/lib/ctf-ir/stream.c @@ -658,7 +658,7 @@ int create_stream_file(struct bt_ctf_writer *writer, g_string_printf(filename, "stream_%" PRId64, ret); } - g_string_append_printf(filename, "_%" PRIu32, stream->id); + g_string_append_printf(filename, "_%" PRId64, stream->id); fd = openat(writer->trace_dir_fd, filename->str, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); @@ -697,9 +697,10 @@ void component_destroy_listener(struct bt_component *component, void *data) g_hash_table_remove(stream->comp_cur_port, component); } -struct bt_ctf_stream *bt_ctf_stream_create( +static +struct bt_ctf_stream *bt_ctf_stream_create_with_id_no_check( struct bt_ctf_stream_class *stream_class, - const char *name) + const char *name, uint64_t id) { int ret; struct bt_ctf_stream *stream = NULL; @@ -712,10 +713,11 @@ struct bt_ctf_stream *bt_ctf_stream_create( } BT_LOGD("Creating stream object: stream-class-addr=%p, " - "stream-class-name=\"%s\", stream-name=\"%s\"", + "stream-class-name=\"%s\", stream-name=\"%s\", " + "stream-id=%" PRIu64, stream_class, bt_ctf_stream_class_get_name(stream_class), - name); - trace = bt_ctf_stream_class_get_trace(stream_class); + name, id); + trace = bt_ctf_stream_class_borrow_trace(stream_class); if (!trace) { BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: " "stream-class-addr=%p, stream-class-name=\"%s\", " @@ -739,6 +741,29 @@ struct bt_ctf_stream *bt_ctf_stream_create( goto error; } + if (id != -1ULL) { + /* + * Validate that the given ID is unique amongst all the + * existing trace's streams created from the same stream + * class. + */ + size_t i; + + for (i = 0; i < trace->streams->len; i++) { + struct bt_ctf_stream *trace_stream = + g_ptr_array_index(trace->streams, i); + + if (trace_stream->stream_class != stream_class) { + continue; + } + + if (trace_stream->id == id) { + BT_LOGW_STR("Invalid parameter: another stream in the same trace already has this ID."); + goto error; + } + } + } + stream = g_new0(struct bt_ctf_stream, 1); if (!stream) { BT_LOGE_STR("Failed to allocate one stream."); @@ -751,9 +776,9 @@ struct bt_ctf_stream *bt_ctf_stream_create( * 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; + stream->id = (int64_t) id; stream->destroy_listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_ctf_stream_destroy_listener)); @@ -774,8 +799,8 @@ struct bt_ctf_stream *bt_ctf_stream_create( if (trace->is_created_by_writer) { int fd; - writer = (struct bt_ctf_writer *) - bt_object_get_parent(trace); + writer = (struct bt_ctf_writer *) bt_object_get_parent(trace); + stream->id = (int64_t) stream_class->next_stream_id++; BT_LOGD("Stream object belongs to a writer's trace: " "writer-addr=%p", writer); @@ -859,18 +884,71 @@ struct bt_ctf_stream *bt_ctf_stream_create( /* Add this stream to the trace's streams */ g_ptr_array_add(trace->streams, stream); - - BT_PUT(trace); - BT_PUT(writer); BT_LOGD("Created stream object: addr=%p", stream); - return stream; + goto end; + error: BT_PUT(stream); - BT_PUT(trace); - BT_PUT(writer); + +end: + bt_put(writer); + return stream; +} + +struct bt_ctf_stream *bt_ctf_stream_create_with_id( + struct bt_ctf_stream_class *stream_class, + const char *name, uint64_t id_param) +{ + struct bt_ctf_trace *trace; + struct bt_ctf_stream *stream = NULL; + int64_t id = (int64_t) id_param; + + if (!stream_class) { + BT_LOGW_STR("Invalid parameter: stream class is NULL."); + goto end; + } + + if (id < 0) { + BT_LOGW("Invalid parameter: invalid stream's ID: " + "name=\"%s\", id=%" PRIu64, + name, id_param); + goto end; + } + + trace = bt_ctf_stream_class_borrow_trace(stream_class); + if (!trace) { + BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: " + "stream-class-addr=%p, stream-class-name=\"%s\", " + "stream-name=\"%s\", stream-id=%" PRIu64, + stream_class, bt_ctf_stream_class_get_name(stream_class), + name, id_param); + goto end; + } + + if (trace->is_created_by_writer) { + BT_LOGW("Invalid parameter: cannot create a CTF writer stream with this function; use bt_ctf_stream_create(): " + "stream-class-addr=%p, stream-class-name=\"%s\", " + "stream-name=\"%s\", stream-id=%" PRIu64, + stream_class, bt_ctf_stream_class_get_name(stream_class), + name, id_param); + goto end; + } + + stream = bt_ctf_stream_create_with_id_no_check(stream_class, + name, id_param); + +end: return stream; } +struct bt_ctf_stream *bt_ctf_stream_create( + struct bt_ctf_stream_class *stream_class, + const char *name) +{ + return bt_ctf_stream_create_with_id_no_check(stream_class, + name, -1ULL); +} + struct bt_ctf_stream_class *bt_ctf_stream_get_class( struct bt_ctf_stream *stream) { @@ -1838,3 +1916,23 @@ void bt_ctf_stream_remove_destroy_listener(struct bt_ctf_stream *stream, } } } + +int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream) +{ + int64_t ret; + + if (!stream) { + BT_LOGW_STR("Invalid parameter: stream is NULL."); + ret = (int64_t) -1; + goto end; + } + + ret = stream->id; + if (ret < 0) { + BT_LOGV("Stream's ID is not set: addr=%p, name=\"%s\"", + stream, bt_ctf_stream_get_name(stream)); + } + +end: + return ret; +} -- 2.34.1