* SOFTWARE.
*/
+#define BT_LOG_TAG "STREAM-CLASS"
+#include <babeltrace/lib-logging-internal.h>
+
#include <babeltrace/ctf-writer/clock.h>
#include <babeltrace/ctf-writer/clock-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <babeltrace/endian-internal.h>
#include <inttypes.h>
#include <stdint.h>
+#include <stdbool.h>
static
void bt_ctf_stream_class_destroy(struct bt_object *obj);
struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
{
+ struct bt_ctf_stream_class *stream_class;
int ret;
- struct bt_ctf_stream_class *stream_class = NULL;
- if (name && bt_ctf_validate_identifier(name)) {
+ BT_LOGD("Creating default stream class object: name=\"%s\"", name);
+ stream_class = bt_ctf_stream_class_create_empty(name);
+ if (!stream_class) {
+ BT_LOGD_STR("Cannot create empty stream class.");
+ goto error;
+ }
+
+ ret = init_event_header(stream_class);
+ if (ret) {
+ BT_LOGE_STR("Cannot initialize stream class's event header field type.");
+ goto error;
+ }
+
+ ret = init_packet_context(stream_class);
+ if (ret) {
+ BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
goto error;
}
+ BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
+ stream_class, name);
+ return stream_class;
+
+error:
+ BT_PUT(stream_class);
+ return stream_class;
+}
+
+struct bt_ctf_stream_class *bt_ctf_stream_class_create_empty(const char *name)
+{
+ struct bt_ctf_stream_class *stream_class = NULL;
+
+ BT_LOGD("Creating empty stream class object: name=\"%s\"", name);
+
stream_class = g_new0(struct bt_ctf_stream_class, 1);
if (!stream_class) {
+ BT_LOGE_STR("Failed to allocate one stream class.");
goto error;
}
stream_class->event_classes = g_ptr_array_new_with_free_func(
(GDestroyNotify) bt_object_release);
if (!stream_class->event_classes) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
goto error;
}
stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
g_int64_equal, g_free, NULL);
-
- ret = init_event_header(stream_class);
- if (ret) {
- goto error;
- }
-
- ret = init_packet_context(stream_class);
- if (ret) {
+ if (!stream_class->event_classes_ht) {
+ BT_LOGE_STR("Failed to allocate a GHashTable.");
goto error;
}
bt_object_init(stream_class, bt_ctf_stream_class_destroy);
+ BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
+ stream_class, name);
return stream_class;
error:
- BT_PUT(stream_class);
+ BT_PUT(stream_class);
return stream_class;
}
const char *name = NULL;
if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
goto end;
}
{
int ret = 0;
- if (!stream_class || stream_class->frozen) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
ret = -1;
goto end;
}
g_string_assign(stream_class->name, name);
+ BT_LOGV("Set stream class's name: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
end:
return ret;
}
{
struct bt_ctf_clock *clock = NULL;
- if (!stream_class || !stream_class->clock) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ goto end;
+ }
+
+ if (!stream_class->clock) {
+ BT_LOGV("Stream class has no clock: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
goto end;
}
int ret = 0;
struct bt_ctf_field_type *timestamp_field = NULL;
- if (!stream_class || !clock || stream_class->frozen) {
+ if (!stream_class || !clock) {
+ BT_LOGW("Invalid parameter: stream class or clock is NULL: "
+ "stream-class-addr=%p, clock-addr=%p",
+ stream_class, clock);
ret = -1;
goto end;
}
- /*
- * Look for a "timestamp" integer field type in the stream
- * class's event header field type and map the stream class's
- * clock's class to that field type if there's no current
- * mapping.
- */
- timestamp_field = bt_ctf_field_type_structure_get_field_type_by_name(
- stream_class->event_header_type, "timestamp");
- if (timestamp_field) {
- struct bt_ctf_clock_class *mapped_clock_class =
- bt_ctf_field_type_integer_get_mapped_clock_class(
- timestamp_field);
-
- if (!mapped_clock_class) {
- ret = bt_ctf_field_type_integer_set_mapped_clock_class(
- timestamp_field, clock->clock_class);
- if (ret) {
- goto end;
- }
- }
-
- BT_PUT(mapped_clock_class);
+ if (stream_class->frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
+ ret = -1;
+ goto end;
}
/* Replace the current clock of this stream class. */
bt_put(stream_class->clock);
stream_class->clock = bt_get(clock);
+ BT_LOGV("Set stream class's clock: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "clock-addr=%p, clock-name=\"%s\"",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ stream_class->clock,
+ bt_ctf_clock_get_name(stream_class->clock));
end:
bt_put(timestamp_field);
{
int64_t ret;
- if (!stream_class || !stream_class->id_set) {
- ret = -1;
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = (int64_t) -1;
+ goto end;
+ }
+
+ if (!stream_class->id_set) {
+ BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class));
+ ret = (int64_t) -1;
goto end;
}
- ret = (int64_t) stream_class->id;
+ ret = stream_class->id;
end:
return ret;
}
BT_HIDDEN
-int _bt_ctf_stream_class_set_id(
- struct bt_ctf_stream_class *stream_class, uint32_t id)
+void _bt_ctf_stream_class_set_id(
+ struct bt_ctf_stream_class *stream_class, int64_t id)
{
+ assert(stream_class);
stream_class->id = id;
stream_class->id_set = 1;
- return 0;
+ BT_LOGV("Set stream class's ID (internal): "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
}
-struct event_class_set_stream_id_data {
- uint32_t stream_id;
+struct event_class_set_stream_class_id_data {
+ int64_t stream_class_id;
int ret;
};
static
void event_class_set_stream_id(gpointer event_class, gpointer data)
{
- struct event_class_set_stream_id_data *typed_data = data;
+ struct event_class_set_stream_class_id_data *typed_data = data;
typed_data->ret |= bt_ctf_event_class_set_stream_id(event_class,
- typed_data->stream_id);
+ typed_data->stream_class_id);
}
BT_HIDDEN
int bt_ctf_stream_class_set_id_no_check(
- struct bt_ctf_stream_class *stream_class, uint32_t id)
+ struct bt_ctf_stream_class *stream_class, int64_t id)
{
int ret = 0;
- struct event_class_set_stream_id_data data =
- { .stream_id = id, .ret = 0 };
+ struct event_class_set_stream_class_id_data data =
+ { .stream_class_id = id, .ret = 0 };
/*
* Make sure all event classes have their "stream_id" attribute
event_class_set_stream_id, &data);
ret = data.ret;
if (ret) {
+ BT_LOGE("Cannot set the IDs of all stream class's event classes: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
goto end;
}
- ret = _bt_ctf_stream_class_set_id(stream_class, id);
- if (ret) {
- goto end;
- }
+ _bt_ctf_stream_class_set_id(stream_class, id);
end:
return ret;
}
int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
- uint32_t id)
+ uint64_t id_param)
{
int ret = 0;
+ int64_t id = (int64_t) id_param;
- if (!stream_class || stream_class->frozen) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
+ ret = -1;
+ goto end;
+ }
+
+ if (id < 0) {
+ BT_LOGW("Invalid parameter: invalid stream class's ID: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", id=%" PRIu64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ id_param);
ret = -1;
goto end;
}
ret = bt_ctf_stream_class_set_id_no_check(stream_class, id);
+ if (ret == 0) {
+ BT_LOGV("Set stream class's ID: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
+ }
end:
return ret;
}
goto end;
}
- /*
- * Two event classes cannot share the same name in a given
- * stream class.
- */
- if (!strcmp(bt_ctf_event_class_get_name(event_class_a),
- bt_ctf_event_class_get_name(event_class_b))) {
- search_query->found = 1;
- goto end;
- }
-
/*
* Two event classes cannot share the same ID in a given
* stream class.
}
if (id_a == id_b) {
+ BT_LOGW("Event class with this ID already exists in the stream class: "
+ "id=%" PRId64 ", name=\"%s\"",
+ id_a, bt_ctf_event_class_get_name(event_class_a));
search_query->found = 1;
goto end;
}
BT_CTF_VALIDATION_FLAG_EVENT;
if (!stream_class || !event_class) {
+ BT_LOGW("Invalid parameter: stream class or event class is NULL: "
+ "stream-class-addr=%p, event-class-addr=%p",
+ stream_class, event_class);
ret = -1;
goto end;
}
+ BT_LOGD("Adding event class to stream class: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", event-class-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ event_class,
+ bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+
trace = bt_ctf_stream_class_get_trace(stream_class);
if (trace && trace->is_static) {
ret = -1;
event_id = g_new(int64_t, 1);
if (!event_id) {
+ BT_LOGE_STR("Failed to allocate one int64_t.");
ret = -1;
goto end;
}
g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
&query);
if (query.found) {
+ BT_LOGW_STR("Another event class part of this stream class has the same ID.");
ret = -1;
goto end;
}
old_stream_class = bt_ctf_event_class_get_stream_class(event_class);
if (old_stream_class) {
/* Event class is already associated to a stream class. */
+ BT_LOGW("Event class is already part of another stream class: "
+ "event-class-stream-class-addr=%p, "
+ "event-class-stream-class-name=\"%s\", "
+ "event-class-stream-class-id=%" PRId64,
+ old_stream_class,
+ bt_ctf_stream_class_get_name(old_stream_class),
+ bt_ctf_stream_class_get_id(old_stream_class));
ret = -1;
goto end;
}
* validation process, not that the objects are
* invalid.
*/
+ BT_LOGE("Failed to validate event class: ret=%d", ret);
goto end;
}
if ((validation_output.valid_flags & validation_flags) !=
validation_flags) {
/* Invalid event class */
+ BT_LOGW("Invalid trace, stream class, or event class: "
+ "valid-flags=0x%x",
+ validation_output.valid_flags);
ret = -1;
goto end;
}
/* Only set an event ID if none was explicitly set before */
*event_id = bt_ctf_event_class_get_id(event_class);
if (*event_id < 0) {
+ BT_LOGV("Event class has no ID: automatically setting it: "
+ "id=%" PRId64, stream_class->next_event_id);
+
if (bt_ctf_event_class_set_id(event_class,
- stream_class->next_event_id++)) {
+ stream_class->next_event_id)) {
+ BT_LOGE("Cannot set event class's ID: id=%" PRId64,
+ stream_class->next_event_id);
ret = -1;
goto end;
}
+ stream_class->next_event_id++;
*event_id = stream_class->next_event_id;
}
ret = bt_ctf_event_class_set_stream_id(event_class, stream_class->id);
if (ret) {
+ BT_LOGE("Cannot set event class's stream class ID attribute: ret=%d",
+ ret);
goto end;
}
(void) bt_ctf_trace_object_modification(&obj, trace);
}
+
+ BT_LOGD("Added event class to stream class: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", event-class-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ event_class,
+ bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+
end:
BT_PUT(trace);
BT_PUT(old_stream_class);
int64_t ret;
if (!stream_class) {
- ret = -1;
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = (int64_t) -1;
goto end;
}
- ret = (int) stream_class->event_classes->len;
+ ret = (int64_t) stream_class->event_classes->len;
end:
return ret;
}
-struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class(
- struct bt_ctf_stream_class *stream_class, int index)
+struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
+ struct bt_ctf_stream_class *stream_class, uint64_t index)
{
struct bt_ctf_event_class *event_class = NULL;
- if (!stream_class || index < 0 ||
- index >= stream_class->event_classes->len) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
goto end;
}
- event_class = g_ptr_array_index(stream_class->event_classes, index);
- bt_get(event_class);
-end:
- return event_class;
-}
-
-struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_name(
- struct bt_ctf_stream_class *stream_class, const char *name)
-{
- size_t i;
- struct bt_ctf_event_class *event_class = NULL;
-
- if (!stream_class || !name) {
+ if (index >= stream_class->event_classes->len) {
+ BT_LOGW("Invalid parameter: index is out of bounds: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "index=%" PRIu64 ", count=%u",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ index, stream_class->event_classes->len);
goto end;
}
- for (i = 0; i < stream_class->event_classes->len; i++) {
- struct bt_ctf_event_class *cur_event_class =
- g_ptr_array_index(stream_class->event_classes, i);
- const char *cur_event_class_name =
- bt_ctf_event_class_get_name(cur_event_class);
-
- if (!strcmp(name, cur_event_class_name)) {
- event_class = cur_event_class;
- bt_get(event_class);
- goto end;
- }
- }
+ event_class = g_ptr_array_index(stream_class->event_classes, index);
+ bt_get(event_class);
end:
return event_class;
}
struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
- struct bt_ctf_stream_class *stream_class, uint32_t id)
+ struct bt_ctf_stream_class *stream_class, uint64_t id)
{
- int64_t id_key = id;
+ int64_t id_key = (int64_t) id;
struct bt_ctf_event_class *event_class = NULL;
if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ goto end;
+ }
+
+ if (id_key < 0) {
+ BT_LOGW("Invalid parameter: invalid event class's ID: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", event-class-id=%" PRIu64,
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), id);
goto end;
}
struct bt_ctf_field_type *ret = NULL;
if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
goto end;
}
{
int ret = 0;
- if (!stream_class || stream_class->frozen) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
ret = -1;
goto end;
}
bt_ctf_field_type_get_type_id(packet_context_type) !=
BT_CTF_FIELD_TYPE_ID_STRUCT) {
/* A packet context must be a structure. */
+ BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "packet-context-ft-addr=%p, packet-context-ft-id=%s",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ packet_context_type,
+ bt_ctf_field_type_id_string(
+ bt_ctf_field_type_get_type_id(packet_context_type)));
ret = -1;
goto end;
}
bt_put(stream_class->packet_context_type);
bt_get(packet_context_type);
stream_class->packet_context_type = packet_context_type;
+ BT_LOGV("Set stream class's packet context field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "packet-context-ft-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ packet_context_type);
+
end:
return ret;
}
{
struct bt_ctf_field_type *ret = NULL;
- if (!stream_class || !stream_class->event_header_type) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ goto end;
+ }
+
+ if (!stream_class->event_header_type) {
+ BT_LOGV("Stream class has no event header field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
goto end;
}
{
int ret = 0;
- if (!stream_class || stream_class->frozen) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
ret = -1;
goto end;
}
bt_ctf_field_type_get_type_id(event_header_type) !=
BT_CTF_FIELD_TYPE_ID_STRUCT) {
/* An event header must be a structure. */
+ BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "event-header-ft-addr=%p, event-header-ft-id=%s",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ event_header_type,
+ bt_ctf_field_type_id_string(
+ bt_ctf_field_type_get_type_id(event_header_type)));
ret = -1;
goto end;
}
bt_put(stream_class->event_header_type);
stream_class->event_header_type = bt_get(event_header_type);
+ BT_LOGV("Set stream class's event header field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "event-header-ft-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ event_header_type);
end:
return ret;
}
{
struct bt_ctf_field_type *ret = NULL;
- if (!stream_class || !stream_class->event_context_type) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ goto end;
+ }
+
+ if (!stream_class->event_context_type) {
goto end;
}
{
int ret = 0;
- if (!stream_class || stream_class->frozen) {
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
ret = -1;
goto end;
}
bt_ctf_field_type_get_type_id(event_context_type) !=
BT_CTF_FIELD_TYPE_ID_STRUCT) {
/* A packet context must be a structure. */
+ BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "event-context-ft-addr=%p, event-context-ft-id=%s",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ event_context_type,
+ bt_ctf_field_type_id_string(
+ bt_ctf_field_type_get_type_id(event_context_type)));
ret = -1;
goto end;
}
bt_put(stream_class->event_context_type);
stream_class->event_context_type = bt_get(event_context_type);
+ BT_LOGV("Set stream class's event context field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "event-context-ft-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ event_context_type);
end:
return ret;
}
+/* Pre-2.0 CTF writer backward compatibility */
void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
{
bt_get(stream_class);
}
+/* Pre-2.0 CTF writer backward compatibility */
void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
{
bt_put(stream_class);
static
void *get_event_class(void *element, int i)
{
- return bt_ctf_stream_class_get_event_class(
+ return bt_ctf_stream_class_get_event_class_by_index(
(struct bt_ctf_stream_class *) element, i);
}
.type = BT_CTF_OBJECT_TYPE_STREAM_CLASS };
if (!stream_class || !visitor) {
+ BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
+ "stream-class-addr=%p, visitor=%p",
+ stream_class, visitor);
ret = -1;
goto end;
}
ret = visitor_helper(&obj, get_event_class_count,
get_event_class,
visit_event_class, visitor, data);
+ BT_LOGV("visitor_helper() returned: ret=%d", ret);
end:
return ret;
}
BT_HIDDEN
void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
{
- if (!stream_class) {
+ if (!stream_class || stream_class->frozen) {
return;
}
+ BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
stream_class->frozen = 1;
bt_ctf_field_type_freeze(stream_class->event_header_type);
bt_ctf_field_type_freeze(stream_class->packet_context_type);
int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
struct metadata_context *context)
{
- int64_t ret = 0;
+ int ret = 0;
size_t i;
+ struct bt_ctf_trace *trace;
+ struct bt_ctf_field_type *packet_header_type = NULL;
+ BT_LOGD("Serializing stream class's metadata: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), context);
g_string_assign(context->field_name, "");
context->current_indentation_level = 1;
if (!stream_class->id_set) {
+ BT_LOGW_STR("Stream class's ID is not set.");
ret = -1;
goto end;
}
- g_string_append_printf(context->string,
- "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
- stream_class->id);
- ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
- context);
- if (ret) {
- goto end;
+ g_string_append(context->string, "stream {\n");
+
+ /*
+ * The reference to the trace is only borrowed since the
+ * serialization of the stream class might have been triggered
+ * by the trace's destruction. In such a case, the trace's
+ * reference count would, unexepectedly, go through the sequence
+ * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
+ * and serialization.
+ */
+ trace = bt_ctf_stream_class_borrow_trace(stream_class);
+ assert(trace);
+ packet_header_type = bt_ctf_trace_get_packet_header_type(trace);
+ trace = NULL;
+ if (packet_header_type) {
+ struct bt_ctf_field_type *stream_id_type;
+
+ stream_id_type =
+ bt_ctf_field_type_structure_get_field_type_by_name(
+ packet_header_type, "stream_id");
+ if (stream_id_type) {
+ /*
+ * Only set the stream's id if the trace's packet header
+ * contains a stream_id field. This field is only
+ * needed if the trace contains only one stream
+ * class.
+ */
+ g_string_append_printf(context->string,
+ "\tid = %" PRId64 ";\n", stream_class->id);
+ }
+ bt_put(stream_id_type);
}
+ if (stream_class->event_header_type) {
+ BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
+ g_string_append(context->string, "\tevent.header := ");
+ ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
+ context);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
+ "ret=%d", ret);
+ goto end;
+ }
+ g_string_append(context->string, ";");
+ }
+
if (stream_class->packet_context_type) {
- g_string_append(context->string, ";\n\n\tpacket.context := ");
+ BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
+ g_string_append(context->string, "\n\n\tpacket.context := ");
ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
context);
if (ret) {
+ BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
+ "ret=%d", ret);
goto end;
}
+ g_string_append(context->string, ";");
}
if (stream_class->event_context_type) {
- g_string_append(context->string, ";\n\n\tevent.context := ");
+ BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
+ g_string_append(context->string, "\n\n\tevent.context := ");
ret = bt_ctf_field_type_serialize(
stream_class->event_context_type, context);
if (ret) {
+ BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
+ "ret=%d", ret);
goto end;
}
+ g_string_append(context->string, ";");
}
- g_string_append(context->string, ";\n};\n\n");
+ g_string_append(context->string, "\n};\n\n");
+
for (i = 0; i < stream_class->event_classes->len; i++) {
struct bt_ctf_event_class *event_class =
stream_class->event_classes->pdata[i];
ret = bt_ctf_event_class_serialize(event_class, context);
if (ret) {
+ BT_LOGW("Cannot serialize event class's metadata: "
+ "event-class-addr=%p, event-class-name=\"%s\", "
+ "event-class-id=%" PRId64,
+ event_class,
+ bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
goto end;
}
}
end:
+ bt_put(packet_header_type);
context->current_indentation_level = 0;
return ret;
}
struct bt_ctf_stream_class *stream_class;
stream_class = container_of(obj, struct bt_ctf_stream_class, base);
+ BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
bt_put(stream_class->clock);
if (stream_class->event_classes_ht) {
g_hash_table_destroy(stream_class->event_classes_ht);
}
if (stream_class->event_classes) {
+ BT_LOGD_STR("Destroying event classes.");
g_ptr_array_free(stream_class->event_classes, TRUE);
}
g_string_free(stream_class->name, TRUE);
}
+ BT_LOGD_STR("Putting event header field type.");
bt_put(stream_class->event_header_type);
+ BT_LOGD_STR("Putting packet context field type.");
bt_put(stream_class->packet_context_type);
+ BT_LOGD_STR("Putting event context field type.");
bt_put(stream_class->event_context_type);
g_free(stream_class);
}
get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
if (!event_header_type) {
+ BT_LOGE_STR("Cannot create empty structure field type.");
ret = -1;
goto end;
}
ret = bt_ctf_field_type_structure_add_field(event_header_type,
_uint32_t, "id");
if (ret) {
+ BT_LOGE_STR("Cannot add `id` field to event header field type.");
goto end;
}
ret = bt_ctf_field_type_structure_add_field(event_header_type,
_uint64_t, "timestamp");
if (ret) {
+ BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
goto end;
}
- if (stream_class->event_header_type) {
- bt_put(stream_class->event_header_type);
- }
- stream_class->event_header_type = event_header_type;
+ BT_MOVE(stream_class->event_header_type, event_header_type);
end:
if (ret) {
bt_put(event_header_type);
bt_ctf_field_type_structure_create();
struct bt_ctf_field_type *_uint64_t =
get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
+ struct bt_ctf_field_type *ts_begin_end_uint64_t;
if (!packet_context_type) {
+ BT_LOGE_STR("Cannot create empty structure field type.");
+ ret = -1;
+ goto end;
+ }
+
+ ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
+ if (!ts_begin_end_uint64_t) {
+ BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
ret = -1;
goto end;
}
* specification.
*/
ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- _uint64_t, "timestamp_begin");
+ ts_begin_end_uint64_t, "timestamp_begin");
if (ret) {
+ BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
goto end;
}
ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- _uint64_t, "timestamp_end");
+ ts_begin_end_uint64_t, "timestamp_end");
if (ret) {
+ BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
goto end;
}
ret = bt_ctf_field_type_structure_add_field(packet_context_type,
_uint64_t, "content_size");
if (ret) {
+ BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
goto end;
}
ret = bt_ctf_field_type_structure_add_field(packet_context_type,
_uint64_t, "packet_size");
if (ret) {
+ BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
goto end;
}
ret = bt_ctf_field_type_structure_add_field(packet_context_type,
_uint64_t, "events_discarded");
if (ret) {
+ BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
goto end;
}
- bt_put(stream_class->packet_context_type);
- stream_class->packet_context_type = packet_context_type;
+ BT_MOVE(stream_class->packet_context_type, packet_context_type);
end:
if (ret) {
bt_put(packet_context_type);
}
bt_put(_uint64_t);
+ bt_put(ts_begin_end_uint64_t);
+ return ret;
+}
+
+static
+int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_field_type *ft)
+{
+ struct bt_ctf_clock_class *mapped_clock_class = NULL;
+ int ret = 0;
+
+ if (!ft) {
+ /* Field does not exist: not an error */
+ goto end;
+ }
+
+ assert(bt_ctf_field_type_is_integer(ft));
+ mapped_clock_class =
+ bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+ if (!mapped_clock_class) {
+ if (!stream_class->clock) {
+ BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", ft-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), ft);
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_integer_set_mapped_clock_class_no_check(
+ ft, stream_class->clock->clock_class);
+ if (ret) {
+ BT_LOGW("Cannot set field type's mapped clock class: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", ft-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), ft);
+ goto end;
+ }
+
+ BT_LOGV("Automatically mapped field type to stream class's clock class: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", ft-addr=%p",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), ft);
+ }
+
+end:
+ bt_put(mapped_clock_class);
+ return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_map_clock_class(
+ struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_field_type *packet_context_type,
+ struct bt_ctf_field_type *event_header_type)
+{
+ struct bt_ctf_field_type *ft = NULL;
+ int ret = 0;
+
+ assert(stream_class);
+
+ if (packet_context_type) {
+ ft = bt_ctf_field_type_structure_get_field_type_by_name(
+ packet_context_type, "timestamp_begin");
+ if (try_map_clock_class(stream_class, ft)) {
+ BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
+ ret = -1;
+ goto end;
+ }
+
+ bt_put(ft);
+ ft = bt_ctf_field_type_structure_get_field_type_by_name(
+ packet_context_type, "timestamp_end");
+ if (try_map_clock_class(stream_class, ft)) {
+ BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
+ ret = -1;
+ goto end;
+ }
+
+ BT_PUT(ft);
+ }
+
+ if (event_header_type) {
+ ft = bt_ctf_field_type_structure_get_field_type_by_name(
+ event_header_type, "timestamp");
+ if (try_map_clock_class(stream_class, ft)) {
+ BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
+ ret = -1;
+ goto end;
+ }
+
+ BT_PUT(ft);
+ }
+
+end:
return ret;
}