X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Flib%2Ftrace-ir%2Ftrace.c;h=688a113eb77f41862856c9403a7383455e54ba9b;hb=43c59509042845f8d42c3e99ec74d45fa2dc0908;hp=3c0308386c4be8ab0ab6e475334fa1a7884215ef;hpb=c2d9d9cf280189e77453e82e4979c307eef111e7;p=babeltrace.git diff --git a/src/lib/trace-ir/trace.c b/src/lib/trace-ir/trace.c index 3c030838..688a113e 100644 --- a/src/lib/trace-ir/trace.c +++ b/src/lib/trace-ir/trace.c @@ -25,14 +25,13 @@ #include "lib/logging.h" #include "lib/assert-pre.h" +#include "lib/assert-post.h" #include -#include #include #include "ctf-writer/functor.h" #include "ctf-writer/clock.h" #include "compat/compiler.h" #include -#include #include "lib/value.h" #include #include "compat/endian.h" @@ -41,6 +40,7 @@ #include #include #include +#include #include #include "attributes.h" @@ -55,14 +55,16 @@ #include "trace-class.h" #include "trace.h" #include "utils.h" +#include "lib/value.h" +#include "lib/func-status.h" struct bt_trace_destruction_listener_elem { bt_trace_destruction_listener_func func; void *data; }; -#define BT_ASSERT_PRE_TRACE_HOT(_trace) \ - BT_ASSERT_PRE_HOT((_trace), "Trace", ": %!+t", (_trace)) +#define BT_ASSERT_PRE_DEV_TRACE_HOT(_trace) \ + BT_ASSERT_PRE_DEV_HOT((_trace), "Trace", ": %!+t", (_trace)) static void destroy_trace(struct bt_object *obj) @@ -70,6 +72,7 @@ void destroy_trace(struct bt_object *obj) struct bt_trace *trace = (void *) obj; BT_LIB_LOGD("Destroying trace object: %!+t", trace); + BT_OBJECT_PUT_REF_AND_RESET(trace->user_attributes); /* * Call destruction listener functions so that everything else @@ -77,6 +80,8 @@ void destroy_trace(struct bt_object *obj) */ if (trace->destruction_listeners) { uint64_t i; + const struct bt_error *saved_error; + BT_LIB_LOGD("Calling trace destruction listener(s): %!+t", trace); /* @@ -91,6 +96,8 @@ void destroy_trace(struct bt_object *obj) */ trace->base.ref_count++; + saved_error = bt_current_thread_take_error(); + /* Call all the trace destruction listeners */ for (i = 0; i < trace->destruction_listeners->len; i++) { struct bt_trace_destruction_listener_elem elem = @@ -99,16 +106,21 @@ void destroy_trace(struct bt_object *obj) if (elem.func) { elem.func(trace, elem.data); + BT_ASSERT_POST_NO_ERROR(); } /* * The destruction listener should not have kept a * reference to the trace. */ - BT_ASSERT_PRE(trace->base.ref_count == 1, "Destruction listener kept a reference to the trace being destroyed: %![trace-]+t", trace); + BT_ASSERT_POST(trace->base.ref_count == 1, "Destruction listener kept a reference to the trace being destroyed: %![trace-]+t", trace); } g_array_free(trace->destruction_listeners, TRUE); trace->destruction_listeners = NULL; + + if (saved_error) { + BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(saved_error); + } } if (trace->name.str) { @@ -117,6 +129,12 @@ void destroy_trace(struct bt_object *obj) trace->name.value = NULL; } + if (trace->environment) { + BT_LOGD_STR("Destroying environment attributes."); + bt_attributes_destroy(trace->environment); + trace->environment = NULL; + } + if (trace->streams) { BT_LOGD_STR("Destroying streams."); g_ptr_array_free(trace->streams, TRUE); @@ -138,43 +156,58 @@ struct bt_trace *bt_trace_create(struct bt_trace_class *tc) { struct bt_trace *trace = NULL; + BT_ASSERT_PRE_NO_ERROR(); + BT_LIB_LOGD("Creating trace object: %![tc-]+T", tc); trace = g_new0(struct bt_trace, 1); if (!trace) { - BT_LOGE_STR("Failed to allocate one trace."); + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one trace."); goto error; } bt_object_init_shared(&trace->base, destroy_trace); + trace->user_attributes = bt_value_map_create(); + if (!trace->user_attributes) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to create a map value object."); + goto error; + } + trace->streams = g_ptr_array_new_with_free_func( (GDestroyNotify) bt_object_try_spec_release); if (!trace->streams) { - BT_LOGE_STR("Failed to allocate one GPtrArray."); + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GPtrArray."); goto error; } trace->stream_classes_stream_count = g_hash_table_new(g_direct_hash, g_direct_equal); if (!trace->stream_classes_stream_count) { - BT_LOGE_STR("Failed to allocate one GHashTable."); + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GHashTable."); goto error; } trace->name.str = g_string_new(NULL); if (!trace->name.str) { - BT_LOGE_STR("Failed to allocate one GString."); + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GString."); + goto error; + } + + trace->environment = bt_attributes_create(); + if (!trace->environment) { + BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty attributes object."); goto error; } trace->destruction_listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_trace_destruction_listener_elem)); if (!trace->destruction_listeners) { - BT_LOGE_STR("Failed to allocate one GArray."); + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GArray."); goto error; } trace->class = tc; - bt_object_get_no_null_check(trace->class); + bt_object_get_ref_no_null_check(trace->class); BT_LIB_LOGD("Created trace object: %!+t", trace); goto end; @@ -187,32 +220,174 @@ end: const char *bt_trace_get_name(const struct bt_trace *trace) { - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); return trace->name.value; } -enum bt_trace_status bt_trace_set_name(struct bt_trace *trace, const char *name) +enum bt_trace_set_name_status bt_trace_set_name(struct bt_trace *trace, + const char *name) { + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace, "Trace"); BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_TRACE_HOT(trace); + BT_ASSERT_PRE_DEV_TRACE_HOT(trace); g_string_assign(trace->name.str, name); trace->name.value = trace->name.str->str; BT_LIB_LOGD("Set trace's name: %!+t", trace); - return BT_TRACE_STATUS_OK; + return BT_FUNC_STATUS_OK; } -uint64_t bt_trace_get_stream_count(const struct bt_trace *trace) +bt_uuid bt_trace_get_uuid(const struct bt_trace *trace) +{ + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); + return trace->uuid.value; +} + +void bt_trace_set_uuid(struct bt_trace *trace, bt_uuid uuid) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(uuid, "UUID"); + BT_ASSERT_PRE_DEV_TRACE_HOT(trace); + bt_uuid_copy(trace->uuid.uuid, uuid); + trace->uuid.value = trace->uuid.uuid; + BT_LIB_LOGD("Set trace's UUID: %!+t", trace); +} + +static +bool trace_has_environment_entry(const struct bt_trace *trace, const char *name) +{ + BT_ASSERT(trace); + + return bt_attributes_borrow_field_value_by_name( + trace->environment, name); +} + +static +enum bt_trace_set_environment_entry_status set_environment_entry( + struct bt_trace *trace, + const char *name, struct bt_value *value) +{ + int ret; + + BT_ASSERT(trace); + BT_ASSERT(name); + BT_ASSERT(value); + BT_ASSERT_PRE(!trace->frozen || + !trace_has_environment_entry(trace, name), + "Trace is frozen: cannot replace environment entry: " + "%![trace-]+t, entry-name=\"%s\"", trace, name); + ret = bt_attributes_set_field_value(trace->environment, name, + value); + if (ret) { + ret = BT_FUNC_STATUS_MEMORY_ERROR; + BT_LIB_LOGE_APPEND_CAUSE( + "Cannot set trace's environment entry: " + "%![trace-]+t, entry-name=\"%s\"", trace, name); + } else { + bt_value_freeze(value); + BT_LIB_LOGD("Set trace's environment entry: " + "%![trace-]+t, entry-name=\"%s\"", trace, name); + } + + return ret; +} + +enum bt_trace_set_environment_entry_status +bt_trace_set_environment_entry_string( + struct bt_trace *trace, const char *name, const char *value) +{ + int ret; + struct bt_value *value_obj; + + BT_ASSERT_PRE_NO_ERROR(); + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + + value_obj = bt_value_string_create_init(value); + if (!value_obj) { + BT_LIB_LOGE_APPEND_CAUSE( + "Cannot create a string value object."); + ret = -1; + goto end; + } + + /* set_environment_entry() logs errors */ + ret = set_environment_entry(trace, name, value_obj); + +end: + bt_object_put_ref(value_obj); + return ret; +} + +enum bt_trace_set_environment_entry_status +bt_trace_set_environment_entry_integer( + struct bt_trace *trace, const char *name, int64_t value) { + int ret; + struct bt_value *value_obj; + + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + + value_obj = bt_value_integer_signed_create_init(value); + if (!value_obj) { + BT_LIB_LOGE_APPEND_CAUSE( + "Cannot create an integer value object."); + ret = BT_FUNC_STATUS_MEMORY_ERROR; + goto end; + } + + /* set_environment_entry() logs errors */ + ret = set_environment_entry(trace, name, value_obj); + +end: + bt_object_put_ref(value_obj); + return ret; +} + +uint64_t bt_trace_get_environment_entry_count(const struct bt_trace *trace) +{ + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); + return bt_attributes_get_count(trace->environment); +} + +void bt_trace_borrow_environment_entry_by_index_const( + const struct bt_trace *trace, uint64_t index, + const char **name, const struct bt_value **value) +{ + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_DEV_NON_NULL(name, "Name"); + BT_ASSERT_PRE_DEV_NON_NULL(value, "Value"); + BT_ASSERT_PRE_DEV_VALID_INDEX(index, + bt_attributes_get_count(trace->environment)); + *value = bt_attributes_borrow_field_value(trace->environment, index); + BT_ASSERT(*value); + *name = bt_attributes_get_field_name(trace->environment, index); + BT_ASSERT(*name); +} + +const struct bt_value *bt_trace_borrow_environment_entry_value_by_name_const( + const struct bt_trace *trace, const char *name) +{ + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_DEV_NON_NULL(name, "Name"); + return bt_attributes_borrow_field_value_by_name(trace->environment, + name); +} + +uint64_t bt_trace_get_stream_count(const struct bt_trace *trace) +{ + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); return (uint64_t) trace->streams->len; } struct bt_stream *bt_trace_borrow_stream_by_index( struct bt_trace *trace, uint64_t index) { - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_VALID_INDEX(index, trace->streams->len); + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_DEV_VALID_INDEX(index, trace->streams->len); return g_ptr_array_index(trace->streams, index); } @@ -228,7 +403,7 @@ struct bt_stream *bt_trace_borrow_stream_by_id(struct bt_trace *trace, struct bt_stream *stream = NULL; uint64_t i; - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); for (i = 0; i < trace->streams->len; i++) { struct bt_stream *stream_candidate = @@ -250,10 +425,10 @@ const struct bt_stream *bt_trace_borrow_stream_by_id_const( return bt_trace_borrow_stream_by_id((void *) trace, id); } -enum bt_trace_status bt_trace_add_destruction_listener( +enum bt_trace_add_listener_status bt_trace_add_destruction_listener( const struct bt_trace *c_trace, bt_trace_destruction_listener_func listener, - void *data, uint64_t *listener_id) + void *data, bt_listener_id *listener_id) { struct bt_trace *trace = (void *) c_trace; uint64_t i; @@ -262,6 +437,7 @@ enum bt_trace_status bt_trace_add_destruction_listener( .data = data, }; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace, "Trace"); BT_ASSERT_PRE_NON_NULL(listener, "Listener"); @@ -288,25 +464,25 @@ enum bt_trace_status bt_trace_add_destruction_listener( BT_LIB_LOGD("Added destruction listener: " "%![trace-]+t, " "listener-id=%" PRIu64, trace, i); - return BT_TRACE_STATUS_OK; + return BT_FUNC_STATUS_OK; } -BT_ASSERT_PRE_FUNC static bool has_listener_id(const struct bt_trace *trace, uint64_t listener_id) { BT_ASSERT(listener_id < trace->destruction_listeners->len); return (&g_array_index(trace->destruction_listeners, struct bt_trace_destruction_listener_elem, - listener_id))->func != NULL; + listener_id))->func; } -enum bt_trace_status bt_trace_remove_destruction_listener( - const struct bt_trace *c_trace, uint64_t listener_id) +enum bt_trace_remove_listener_status bt_trace_remove_destruction_listener( + const struct bt_trace *c_trace, bt_listener_id listener_id) { struct bt_trace *trace = (void *) c_trace; struct bt_trace_destruction_listener_elem *elem; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace, "Trace"); BT_ASSERT_PRE(has_listener_id(trace, listener_id), "Trace has no such trace destruction listener ID: " @@ -321,7 +497,7 @@ enum bt_trace_status bt_trace_remove_destruction_listener( BT_LIB_LOGD("Removed \"trace destruction listener: " "%![trace-]+t, listener-id=%" PRIu64, trace, listener_id); - return BT_TRACE_STATUS_OK; + return BT_FUNC_STATUS_OK; } BT_HIDDEN @@ -330,6 +506,9 @@ void _bt_trace_freeze(const struct bt_trace *trace) BT_ASSERT(trace); BT_LIB_LOGD("Freezing trace's class: %!+T", trace->class); bt_trace_class_freeze(trace->class); + BT_LIB_LOGD("Freezing trace's user attributes: %!+v", + trace->user_attributes); + bt_value_freeze(trace->user_attributes); BT_LIB_LOGD("Freezing trace: %!+t", trace); ((struct bt_trace *) trace)->frozen = true; } @@ -373,7 +552,7 @@ uint64_t bt_trace_get_automatic_stream_id(const struct bt_trace *trace, struct bt_trace_class *bt_trace_borrow_class(struct bt_trace *trace) { - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); return trace->class; } @@ -383,6 +562,32 @@ const struct bt_trace_class *bt_trace_borrow_class_const( return bt_trace_borrow_class((void *) trace); } +const struct bt_value *bt_trace_borrow_user_attributes_const( + const struct bt_trace *trace) +{ + BT_ASSERT_PRE_DEV_NON_NULL(trace, "Trace"); + return trace->user_attributes; +} + +struct bt_value *bt_trace_borrow_user_attributes(struct bt_trace *trace) +{ + return (void *) bt_trace_borrow_user_attributes_const((void *) trace); +} + +void bt_trace_set_user_attributes( + struct bt_trace *trace, + const struct bt_value *user_attributes) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(user_attributes, "User attributes"); + BT_ASSERT_PRE(user_attributes->type == BT_VALUE_TYPE_MAP, + "User attributes object is not a map value object."); + BT_ASSERT_PRE_DEV_TRACE_HOT(trace); + bt_object_put_ref_no_null_check(trace->user_attributes); + trace->user_attributes = (void *) user_attributes; + bt_object_get_ref_no_null_check(trace->user_attributes); +} + void bt_trace_get_ref(const struct bt_trace *trace) { bt_object_get_ref(trace);