#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
#include <inttypes.h>
+#include <unistd.h>
static
void bt_ctf_stream_destroy(struct bt_object *obj);
goto end;
}
- ret = bt_ctf_field_unsigned_integer_set_value(field,
- stream->discarded_events);
- if (ret) {
- BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, stream->discarded_events);
+ /*
+ * If the field is set by the user, make sure that the value is
+ * greater than or equal to the stream's current count of
+ * discarded events. We do not allow wrapping here. If it's
+ * valid, update the stream's current count.
+ */
+ if (bt_ctf_field_is_set(field)) {
+ uint64_t user_val;
+
+ ret = bt_ctf_field_unsigned_integer_get_value(field,
+ &user_val);
+ if (ret) {
+ BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), field);
+ goto end;
+ }
+
+ if (user_val < stream->discarded_events) {
+ BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
+ "value is lesser than the stream's current discarded events count: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
+ "value=%" PRIu64 ", "
+ "stream-discarded-events-count=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream), field,
+ user_val, stream->discarded_events);
+ goto end;
+ }
+
+ stream->discarded_events = user_val;
} else {
- BT_LOGV("Set packet context field's `events_discarded` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, stream->discarded_events);
+ ret = bt_ctf_field_unsigned_integer_set_value(field,
+ stream->discarded_events);
+ if (ret) {
+ BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, stream->discarded_events);
+ } else {
+ BT_LOGV("Set packet context field's `events_discarded` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, stream->discarded_events);
+ }
}
end:
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);
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;
}
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\", "
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.");
* 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));
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);
/* 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)
{
return stream_class;
}
-int64_t bt_ctf_stream_get_discarded_events_count(
+int bt_ctf_stream_get_discarded_events_count(
struct bt_ctf_stream *stream, uint64_t *count)
{
- int64_t ret = 0;
+ int ret = 0;
if (!stream) {
BT_LOGW_STR("Invalid parameter: stream is NULL.");
- ret = (int64_t) -1;
+ ret = -1;
goto end;
}
if (!count) {
BT_LOGW_STR("Invalid parameter: count is NULL.");
- ret = (int64_t) -1;
+ ret = -1;
goto end;
}
BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
"stream-addr=%p, stream-name=\"%s\"",
stream, bt_ctf_stream_get_name(stream));
- ret = (int64_t) -1;
+ ret = -1;
goto end;
}
reset_structure_field(stream->packet_context, "timestamp_end");
reset_structure_field(stream->packet_context, "packet_size");
reset_structure_field(stream->packet_context, "content_size");
+ reset_structure_field(stream->packet_context, "events_discarded");
if (ret < 0) {
/*
* listener so that we remove this hash table entry when we know
* the component is destroyed.
*/
- bt_component_add_destroy_listener(comp, component_destroy_listener,
- stream);
- g_hash_table_insert(stream->comp_cur_port, comp, port);
- BT_LOGV("Mapped component to port for stream: stream-addr=%p, "
- "stream-name=\"%s\", comp-addr=%p, comp-name=\"%s\", "
- "port-addr=%p, port-name=\"%s\"",
+ BT_LOGV("Adding component's destroy listener for stream: "
+ "stream-addr=%p, stream-name=\"%s\", comp-addr=%p, "
+ "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"",
stream, bt_ctf_stream_get_name(stream),
comp, bt_component_get_name(comp), port,
bt_port_get_name(port));
+ bt_component_add_destroy_listener(comp, component_destroy_listener,
+ stream);
+ g_hash_table_insert(stream->comp_cur_port, comp, port);
+ BT_LOGV_STR("Mapped component to port for stream.");
}
BT_HIDDEN
}
}
}
+
+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;
+}