X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Ftrace-ir%2Ftrace-class.c;h=51cc66914d4ce970dc4c38de63b9d16e5f69eeec;hb=3fadfbc0c91f82c46bd36e6e0657ea93570c9db1;hp=265aa73a137027107482413d7213bc888411edbb;hpb=c5b9b4417bedfbec9b5dd23b8395ccdd4eeffc44;p=babeltrace.git diff --git a/lib/trace-ir/trace-class.c b/lib/trace-ir/trace-class.c index 265aa73a..51cc6691 100644 --- a/lib/trace-ir/trace-class.c +++ b/lib/trace-ir/trace-class.c @@ -22,38 +22,43 @@ */ #define BT_LOG_TAG "TRACE" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include +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)) @@ -63,7 +68,45 @@ void destroy_trace_class(struct bt_object *obj) 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); + + /* + * The trace class' reference count is 0 if we're here. Increment + * it to avoid a double-destroy (possibly infinitely recursive). + * This could happen for example if a destruction listener did + * bt_object_get_ref() (or anything that causes + * bt_object_get_ref() to be called) on the trace class (ref. + * count goes from 0 to 1), and then bt_object_put_ref(): the + * reference count would go from 1 to 0 again and this function + * would be called again. + */ + tc->base.ref_count++; + + /* 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); + } + + /* + * The destruction listener should not have kept a + * reference to the trace class. + */ + BT_ASSERT_PRE(tc->base.ref_count == 1, "Destruction listener kept a reference to the trace class being destroyed: %![tc-]+T", tc); + } + g_array_free(tc->destruction_listeners, TRUE); + tc->destruction_listeners = NULL; + } if (tc->environment) { BT_LOGD_STR("Destroying environment attributes."); @@ -83,24 +126,14 @@ void destroy_trace_class(struct bt_object *obj) 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) { @@ -129,17 +162,14 @@ struct bt_trace_class *bt_trace_class_create(void) 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; @@ -156,7 +186,8 @@ const char *bt_trace_class_get_name(const struct bt_trace_class *tc) 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"); @@ -164,7 +195,7 @@ int bt_trace_class_set_name(struct bt_trace_class *tc, const char *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) @@ -183,6 +214,80 @@ void bt_trace_class_set_uuid(struct bt_trace_class *tc, bt_uuid uuid) 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) @@ -194,8 +299,8 @@ bool trace_has_environment_entry(const struct bt_trace_class *tc, const char *na } 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; @@ -208,11 +313,12 @@ int set_environment_entry(struct bt_trace_class *tc, const char *name, "%![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); } @@ -220,7 +326,7 @@ int set_environment_entry(struct bt_trace_class *tc, const char *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; @@ -243,17 +349,17 @@ end: 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; } @@ -350,54 +456,9 @@ bt_trace_class_borrow_stream_class_by_id_const( 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;