#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/trace.h>
#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/ctf-ir/packet-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/property-internal.h>
#include <inttypes.h>
#include <unistd.h>
-BT_HIDDEN
-void bt_stream_common_finalize(struct bt_stream_common *stream)
-{
- int i;
+#define BT_ASSERT_PRE_STREAM_HOT(_stream) \
+ BT_ASSERT_PRE_HOT((_stream), "Stream", ": %!+s", (_stream))
- BT_LOGD("Finalizing common stream object: addr=%p, name=\"%s\"",
- stream, bt_stream_common_get_name(stream));
-
- /* Call destroy listeners in reverse registration order */
- for (i = stream->destroy_listeners->len - 1; i >= 0; i--) {
- struct bt_stream_common_destroy_listener *listener =
- &g_array_index(stream->destroy_listeners,
- struct bt_stream_common_destroy_listener, i);
+static
+void destroy_stream(struct bt_object *obj)
+{
+ struct bt_stream *stream = (void *) obj;
- BT_LOGD("Calling destroy listener: func=%p, data=%p, index=%d",
- listener->func, listener->data, i);
- listener->func(stream, listener->data);
- }
+ BT_LIB_LOGD("Destroying stream object: %!+s", stream);
- if (stream->name) {
- g_string_free(stream->name, TRUE);
+ if (stream->name.str) {
+ g_string_free(stream->name.str, TRUE);
}
- if (stream->destroy_listeners) {
- g_array_free(stream->destroy_listeners, TRUE);
- }
+ bt_object_pool_finalize(&stream->packet_pool);
+ g_free(stream);
}
static
-void bt_stream_destroy(struct bt_object *obj)
+void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream)
{
- struct bt_stream *stream = (void *) obj;
-
- BT_LOGD("Destroying stream object: addr=%p, name=\"%s\"",
- stream, bt_stream_get_name(stream));
- bt_stream_common_finalize((void *) obj);
- g_free(stream);
+ bt_packet_destroy(packet);
}
-BT_HIDDEN
-int bt_stream_common_initialize(
- struct bt_stream_common *stream,
- struct bt_stream_class_common *stream_class, const char *name,
- uint64_t id, bt_object_release_func release_func)
+BT_ASSERT_PRE_FUNC
+static inline
+bool stream_id_is_unique(struct bt_trace *trace,
+ struct bt_stream_class *stream_class, uint64_t id)
{
- int ret = 0;
- struct bt_trace_common *trace = NULL;
-
- bt_object_init(stream, release_func);
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto error;
- }
-
- BT_LOGD("Initializing common stream object: stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-name=\"%s\", "
- "stream-id=%" PRIu64,
- stream_class, bt_stream_class_common_get_name(stream_class),
- name, id);
- trace = bt_stream_class_common_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_class,
- bt_stream_class_common_get_name(stream_class), name);
- 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;
+ uint64_t i;
+ bool is_unique = true;
- for (i = 0; i < trace->streams->len; i++) {
- struct bt_stream_common *trace_stream =
- g_ptr_array_index(trace->streams, i);
+ for (i = 0; i < trace->streams->len; i++) {
+ struct bt_stream *stream = trace->streams->pdata[i];
- if (trace_stream->stream_class != (void *) 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;
- }
+ if (stream->class != stream_class) {
+ continue;
}
- }
- /*
- * Acquire reference to parent since stream will become publicly
- * reachable; it needs its parent to remain valid.
- */
- bt_object_set_parent(stream, trace);
- stream->stream_class = stream_class;
- stream->id = (int64_t) id;
- stream->destroy_listeners = g_array_new(FALSE, TRUE,
- sizeof(struct bt_stream_common_destroy_listener));
- if (!stream->destroy_listeners) {
- BT_LOGE_STR("Failed to allocate a GArray.");
- goto error;
- }
-
- if (name) {
- stream->name = g_string_new(name);
- if (!stream->name) {
- BT_LOGE_STR("Failed to allocate a GString.");
- goto error;
+ if (stream->id == id) {
+ is_unique = false;
+ goto end;
}
}
- BT_LOGD("Set common stream's trace parent: trace-addr=%p", trace);
-
- /* Add this stream to the trace's streams */
- BT_LOGD("Created common stream object: addr=%p", stream);
- goto end;
-
-error:
- ret = -1;
-
end:
- return ret;
+ return is_unique;
}
static
-struct bt_stream *bt_stream_create_with_id_no_check(
- struct bt_stream_class *stream_class,
- const char *name, uint64_t id)
+struct bt_stream *create_stream_with_id(struct bt_stream_class *stream_class,
+ uint64_t id)
{
int ret;
- struct bt_stream *stream = NULL;
- struct bt_trace *trace = NULL;
-
- BT_LOGD("Creating stream object: stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-name=\"%s\", "
- "stream-id=%" PRIu64,
- stream_class, bt_stream_class_get_name(stream_class),
- name, id);
-
- trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
- BT_TO_COMMON(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_class, bt_stream_class_get_name(stream_class),
- name);
- goto error;
- }
-
- if (bt_trace_is_static(trace)) {
- /*
- * A static trace has the property that all its stream
- * classes, clock classes, and streams are definitive:
- * no more can be added, and each object is also frozen.
- */
- BT_LOGW("Invalid parameter: cannot create stream from a stream class which is part of a static trace: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-name=\"%s\", trace-addr=%p",
- stream_class, bt_stream_class_get_name(stream_class),
- name, trace);
- goto error;
- }
-
+ struct bt_stream *stream;
+ struct bt_trace *trace;
+
+ BT_ASSERT(stream_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
+ BT_ASSERT_PRE(stream_id_is_unique(trace, stream_class, id),
+ "Duplicate stream ID: %![trace-]+t, id=%" PRIu64, trace, id);
+ BT_ASSERT_PRE(!trace->is_static,
+ "Trace is static: %![trace-]+t", trace);
+ BT_LIB_LOGD("Creating stream object: %![trace-]+t, id=%" PRIu64,
+ trace, id);
stream = g_new0(struct bt_stream, 1);
if (!stream) {
BT_LOGE_STR("Failed to allocate one stream.");
goto error;
}
- ret = bt_stream_common_initialize(BT_TO_COMMON(stream),
- BT_TO_COMMON(stream_class), name, id, bt_stream_destroy);
+ bt_object_init_shared_with_parent(&stream->base, destroy_stream);
+ stream->name.str = g_string_new(NULL);
+ if (!stream->name.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ goto error;
+ }
+
+ stream->id = id;
+ ret = bt_object_pool_initialize(&stream->packet_pool,
+ (bt_object_pool_new_object_func) bt_packet_new,
+ (bt_object_pool_destroy_object_func) bt_stream_free_packet,
+ stream);
if (ret) {
- /* bt_stream_common_initialize() logs errors */
+ BT_LOGE("Failed to initialize packet pool: ret=%d", ret);
goto error;
}
- g_ptr_array_add(trace->common.streams, stream);
- BT_LOGD("Created stream object: addr=%p", stream);
+ stream->class = stream_class;
+ bt_trace_add_stream(trace, stream);
+ bt_stream_class_freeze(stream_class);
+ BT_LIB_LOGD("Created stream object: %!+s", stream);
goto end;
error:
return stream;
}
-struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class,
- const char *name, uint64_t id_param)
+struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class)
{
- struct bt_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;
- }
-
- stream = bt_stream_create_with_id_no_check(stream_class,
- name, id_param);
+ uint64_t id;
+
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(stream_class->assigns_automatic_stream_id,
+ "Stream class does not automatically assigns stream IDs: "
+ "%![sc-]+S", stream_class);
+ id = bt_trace_get_automatic_stream_id(
+ bt_stream_class_borrow_trace_inline(stream_class),
+ stream_class);
+ return create_stream_with_id(stream_class, id);
+}
-end:
- return stream;
+struct bt_stream *bt_stream_create_with_id(struct bt_stream_class *stream_class,
+ uint64_t id)
+{
+ BT_ASSERT_PRE(!stream_class->assigns_automatic_stream_id,
+ "Stream class automatically assigns stream IDs: "
+ "%![sc-]+S", stream_class);
+ return create_stream_with_id(stream_class, id);
}
-struct bt_stream_class *bt_stream_get_class(struct bt_stream *stream)
+struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream)
{
- return BT_FROM_COMMON(bt_stream_common_get_class(BT_TO_COMMON(stream)));
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+ return stream->class;
}
const char *bt_stream_get_name(struct bt_stream *stream)
{
- return bt_stream_common_get_name(BT_TO_COMMON(stream));
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream class");
+ return stream->name.value;
}
-int64_t bt_stream_get_id(struct bt_stream *stream)
+int bt_stream_set_name(struct bt_stream *stream, const char *name)
{
- return bt_stream_common_get_id(BT_TO_COMMON(stream));
+ BT_ASSERT_PRE_NON_NULL(stream, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_STREAM_HOT(stream);
+ g_string_assign(stream->name.str, name);
+ stream->name.value = stream->name.str->str;
+ BT_LIB_LOGV("Set stream class's name: %!+S", stream);
+ return 0;
}
-BT_HIDDEN
-void bt_stream_common_add_destroy_listener(struct bt_stream_common *stream,
- bt_stream_common_destroy_listener_func func, void *data)
+uint64_t bt_stream_get_id(struct bt_stream *stream)
{
- struct bt_stream_common_destroy_listener listener;
-
- BT_ASSERT(stream);
- BT_ASSERT(func);
- listener.func = func;
- listener.data = data;
- g_array_append_val(stream->destroy_listeners, listener);
- BT_LOGV("Added stream destroy listener: stream-addr=%p, "
- "stream-name=\"%s\", func=%p, data=%p",
- stream, bt_stream_common_get_name(stream), func, data);
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream class");
+ return stream->id;
}
BT_HIDDEN
-void bt_stream_common_remove_destroy_listener(struct bt_stream_common *stream,
- bt_stream_common_destroy_listener_func func, void *data)
+void _bt_stream_freeze(struct bt_stream *stream)
{
- size_t i;
-
+ /* The field types and default clock class are already frozen */
BT_ASSERT(stream);
- BT_ASSERT(func);
-
- for (i = 0; i < stream->destroy_listeners->len; i++) {
- struct bt_stream_common_destroy_listener *listener =
- &g_array_index(stream->destroy_listeners,
- struct bt_stream_common_destroy_listener, i);
-
- if (listener->func == func && listener->data == data) {
- g_array_remove_index(stream->destroy_listeners, i);
- i--;
- BT_LOGV("Removed stream destroy listener: stream-addr=%p, "
- "stream-name=\"%s\", func=%p, data=%p",
- stream, bt_stream_common_get_name(stream),
- func, data);
- }
- }
+ BT_LIB_LOGD("Freezing stream: %!+s", stream);
+ stream->frozen = true;
}