#include <string.h>
#include <stdlib.h>
+struct bt_trace_class_destruction_listener_elem {
+ bt_trace_class_destruction_listener_func func;
+ void *data;
+};
+
#define BT_ASSERT_PRE_TRACE_CLASS_HOT(_tc) \
BT_ASSERT_PRE_HOT((_tc), "Trace class", ": %!+T", (_tc))
struct bt_trace_class *tc = (void *) obj;
BT_LIB_LOGD("Destroying trace class object: %!+T", tc);
- bt_object_pool_finalize(&tc->packet_header_field_pool);
+ /*
+ * Call destruction listener functions so that everything else
+ * still exists in the trace class.
+ */
+ if (tc->destruction_listeners) {
+ uint64_t i;
+ BT_LIB_LOGV("Calling trace class destruction listener(s): %!+T", tc);
+ /* Call all the trace class destruction listeners */
+ for (i = 0; i < tc->destruction_listeners->len; i++) {
+ struct bt_trace_class_destruction_listener_elem elem =
+ g_array_index(tc->destruction_listeners,
+ struct bt_trace_class_destruction_listener_elem, i);
+
+ if (elem.func) {
+ elem.func(tc, elem.data);
+ }
+ }
+ g_array_free(tc->destruction_listeners, TRUE);
+ tc->destruction_listeners = NULL;
+ }
if (tc->environment) {
BT_LOGD_STR("Destroying environment attributes.");
tc->stream_classes = NULL;
}
- BT_LOGD_STR("Putting packet header field class.");
- bt_object_put_ref(tc->packet_header_fc);
- tc->packet_header_fc = NULL;
g_free(tc);
}
-static
-void free_packet_header_field(struct bt_field_wrapper *field_wrapper,
- struct bt_trace_class *tc)
-{
- bt_field_wrapper_destroy(field_wrapper);
-}
-
-struct bt_trace_class *bt_trace_class_create(void)
+struct bt_trace_class *bt_trace_class_create(bt_self_component *self_comp)
{
struct bt_trace_class *tc = NULL;
- int ret;
+ BT_ASSERT_PRE_NON_NULL(self_comp, "Self component");
BT_LOGD_STR("Creating default trace class object.");
tc = g_new0(struct bt_trace_class, 1);
if (!tc) {
goto error;
}
- tc->assigns_automatic_stream_class_id = true;
- ret = bt_object_pool_initialize(&tc->packet_header_field_pool,
- (bt_object_pool_new_object_func) bt_field_wrapper_new,
- (bt_object_pool_destroy_object_func) free_packet_header_field,
- tc);
- if (ret) {
- BT_LOGE("Failed to initialize packet header field pool: ret=%d",
- ret);
+ tc->destruction_listeners = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_trace_class_destruction_listener_elem));
+ if (!tc->destruction_listeners) {
+ BT_LOGE_STR("Failed to allocate one GArray.");
goto error;
}
+ tc->assigns_automatic_stream_class_id = true;
BT_LIB_LOGD("Created trace class object: %!+T", tc);
goto end;
return tc->name.value;
}
-int bt_trace_class_set_name(struct bt_trace_class *tc, const char *name)
+enum bt_trace_class_status bt_trace_class_set_name(
+ struct bt_trace_class *tc, const char *name)
{
BT_ASSERT_PRE_NON_NULL(tc, "Trace class");
BT_ASSERT_PRE_NON_NULL(name, "Name");
g_string_assign(tc->name.str, name);
tc->name.value = tc->name.str->str;
BT_LIB_LOGV("Set trace class's name: %!+T", tc);
- return 0;
+ return BT_TRACE_CLASS_STATUS_OK;
}
bt_uuid bt_trace_class_get_uuid(const struct bt_trace_class *tc)
BT_LIB_LOGV("Set trace class's UUID: %!+T", tc);
}
+enum bt_trace_class_status bt_trace_class_add_destruction_listener(
+ const struct bt_trace_class *_tc,
+ bt_trace_class_destruction_listener_func listener,
+ void *data, uint64_t *listener_id)
+{
+ struct bt_trace_class *tc = (void *) _tc;
+ uint64_t i;
+ struct bt_trace_class_destruction_listener_elem new_elem = {
+ .func = listener,
+ .data = data,
+ };
+
+ BT_ASSERT_PRE_NON_NULL(tc, "Trace class");
+ BT_ASSERT_PRE_NON_NULL(listener, "Listener");
+
+ /* Find the next available spot */
+ for (i = 0; i < tc->destruction_listeners->len; i++) {
+ struct bt_trace_class_destruction_listener_elem elem =
+ g_array_index(tc->destruction_listeners,
+ struct bt_trace_class_destruction_listener_elem, i);
+
+ if (!elem.func) {
+ break;
+ }
+ }
+
+ if (i == tc->destruction_listeners->len) {
+ g_array_append_val(tc->destruction_listeners, new_elem);
+ } else {
+ g_array_insert_val(tc->destruction_listeners, i, new_elem);
+ }
+
+ if (listener_id) {
+ *listener_id = i;
+ }
+
+ BT_LIB_LOGV("Added trace class destruction listener: %![tc-]+T, "
+ "listener-id=%" PRIu64, tc, i);
+ return BT_TRACE_CLASS_STATUS_OK;
+}
+
+BT_ASSERT_PRE_FUNC
+static
+bool has_listener_id(const struct bt_trace_class *tc, uint64_t listener_id)
+{
+ BT_ASSERT(listener_id < tc->destruction_listeners->len);
+ return (&g_array_index(tc->destruction_listeners,
+ struct bt_trace_class_destruction_listener_elem,
+ listener_id))->func != NULL;
+}
+
+enum bt_trace_class_status bt_trace_class_remove_destruction_listener(
+ const struct bt_trace_class *_tc, uint64_t listener_id)
+{
+ struct bt_trace_class *tc = (void *) _tc;
+ struct bt_trace_class_destruction_listener_elem *elem;
+
+ BT_ASSERT_PRE_NON_NULL(tc, "Trace class");
+ BT_ASSERT_PRE(has_listener_id(tc, listener_id),
+ "Trace class has no such trace class destruction listener ID: "
+ "%![tc-]+T, %" PRIu64, tc, listener_id);
+ elem = &g_array_index(tc->destruction_listeners,
+ struct bt_trace_class_destruction_listener_elem,
+ listener_id);
+ BT_ASSERT(elem->func);
+
+ elem->func = NULL;
+ elem->data = NULL;
+ BT_LIB_LOGV("Removed trace class destruction listener: "
+ "%![tc-]+T, listener-id=%" PRIu64,
+ tc, listener_id);
+ return BT_TRACE_CLASS_STATUS_OK;
+}
+
BT_ASSERT_FUNC
static
bool trace_has_environment_entry(const struct bt_trace_class *tc, const char *name)
}
static
-int set_environment_entry(struct bt_trace_class *tc, const char *name,
- struct bt_value *value)
+enum bt_trace_class_status set_environment_entry(struct bt_trace_class *tc,
+ const char *name, struct bt_value *value)
{
int ret;
"%![tc-]+T, entry-name=\"%s\"", tc, name);
ret = bt_attributes_set_field_value(tc->environment, name,
value);
- bt_value_freeze(value);
if (ret) {
+ ret = BT_TRACE_CLASS_STATUS_NOMEM;
BT_LIB_LOGE("Cannot set trace class's environment entry: "
"%![tc-]+T, entry-name=\"%s\"", tc, name);
} else {
+ bt_value_freeze(value);
BT_LIB_LOGV("Set trace class's environment entry: "
"%![tc-]+T, entry-name=\"%s\"", tc, name);
}
return ret;
}
-int bt_trace_class_set_environment_entry_string(
+enum bt_trace_class_status bt_trace_class_set_environment_entry_string(
struct bt_trace_class *tc, const char *name, const char *value)
{
int ret;
return ret;
}
-int bt_trace_class_set_environment_entry_integer(struct bt_trace_class *tc,
- const char *name, int64_t value)
+enum bt_trace_class_status bt_trace_class_set_environment_entry_integer(
+ struct bt_trace_class *tc, const char *name, int64_t value)
{
int ret;
struct bt_value *value_obj;
BT_ASSERT_PRE_NON_NULL(tc, "Trace class");
BT_ASSERT_PRE_NON_NULL(name, "Name");
- value_obj = bt_value_integer_create_init(value);
+ value_obj = bt_value_signed_integer_create_init(value);
if (!value_obj) {
BT_LOGE_STR("Cannot create an integer value object.");
- ret = -1;
+ ret = BT_TRACE_CLASS_STATUS_NOMEM;
goto end;
}
return bt_trace_class_borrow_stream_class_by_id((void *) tc, id);
}
-const struct bt_field_class *bt_trace_class_borrow_packet_header_field_class_const(
- const struct bt_trace_class *tc)
-{
- BT_ASSERT_PRE_NON_NULL(tc, "Trace class");
- return tc->packet_header_fc;
-}
-
-int bt_trace_class_set_packet_header_field_class(
- struct bt_trace_class *tc,
- struct bt_field_class *field_class)
-{
- int ret;
- struct bt_resolve_field_path_context resolve_ctx = {
- .packet_header = field_class,
- .packet_context = NULL,
- .event_header = NULL,
- .event_common_context = NULL,
- .event_specific_context = NULL,
- .event_payload = NULL,
- };
-
- BT_ASSERT_PRE_NON_NULL(tc, "Trace class");
- BT_ASSERT_PRE_NON_NULL(field_class, "Field class");
- BT_ASSERT_PRE_TRACE_CLASS_HOT(tc);
- BT_ASSERT_PRE(bt_field_class_get_type(field_class) ==
- BT_FIELD_CLASS_TYPE_STRUCTURE,
- "Packet header field class is not a structure field class: %!+F",
- field_class);
- ret = bt_resolve_field_paths(field_class, &resolve_ctx);
- if (ret) {
- goto end;
- }
-
- bt_field_class_make_part_of_trace_class(field_class);
- bt_object_put_ref(tc->packet_header_fc);
- tc->packet_header_fc = field_class;
- bt_object_get_no_null_check(tc->packet_header_fc);
- bt_field_class_freeze(field_class);
- BT_LIB_LOGV("Set trace class's packet header field class: %!+T", tc);
-
-end:
- return ret;
-}
-
BT_HIDDEN
void _bt_trace_class_freeze(const struct bt_trace_class *tc)
{
- /* The packet header field class is already frozen */
BT_ASSERT(tc);
BT_LIB_LOGD("Freezing trace class: %!+T", tc);
((struct bt_trace_class *) tc)->frozen = true;