lib: rename include dir to babeltrace2
[babeltrace.git] / lib / trace-ir / trace-class.c
index 265aa73a137027107482413d7213bc888411edbb..51cc66914d4ce970dc4c38de63b9d16e5f69eeec 100644 (file)
  */
 
 #define BT_LOG_TAG "TRACE"
-#include <babeltrace/lib-logging-internal.h>
-
-#include <babeltrace/assert-pre-internal.h>
-#include <babeltrace/trace-ir/trace-class.h>
-#include <babeltrace/trace-ir/trace-class-const.h>
-#include <babeltrace/trace-ir/trace-internal.h>
-#include <babeltrace/trace-ir/clock-class-internal.h>
-#include <babeltrace/trace-ir/stream-internal.h>
-#include <babeltrace/trace-ir/stream-class-internal.h>
-#include <babeltrace/trace-ir/event-internal.h>
-#include <babeltrace/trace-ir/event-class.h>
-#include <babeltrace/trace-ir/event-class-internal.h>
-#include <babeltrace/ctf-writer/functor-internal.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
-#include <babeltrace/trace-ir/field-wrapper-internal.h>
-#include <babeltrace/trace-ir/field-class-internal.h>
-#include <babeltrace/trace-ir/attributes-internal.h>
-#include <babeltrace/trace-ir/utils-internal.h>
-#include <babeltrace/trace-ir/resolve-field-path-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/value.h>
-#include <babeltrace/value-const.h>
-#include <babeltrace/value-internal.h>
-#include <babeltrace/types.h>
-#include <babeltrace/endian-internal.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/compat/glib-internal.h>
+#include <babeltrace2/lib-logging-internal.h>
+
+#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/trace-ir/trace-class.h>
+#include <babeltrace2/trace-ir/trace-class-const.h>
+#include <babeltrace2/trace-ir/trace-internal.h>
+#include <babeltrace2/trace-ir/clock-class-internal.h>
+#include <babeltrace2/trace-ir/stream-internal.h>
+#include <babeltrace2/trace-ir/stream-class-internal.h>
+#include <babeltrace2/trace-ir/event-internal.h>
+#include <babeltrace2/trace-ir/event-class.h>
+#include <babeltrace2/trace-ir/event-class-internal.h>
+#include <babeltrace2/ctf-writer/functor-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/trace-ir/field-wrapper-internal.h>
+#include <babeltrace2/trace-ir/field-class-internal.h>
+#include <babeltrace2/trace-ir/attributes-internal.h>
+#include <babeltrace2/trace-ir/utils-internal.h>
+#include <babeltrace2/trace-ir/resolve-field-path-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/value.h>
+#include <babeltrace2/value-const.h>
+#include <babeltrace2/value-internal.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compat/glib-internal.h>
 #include <inttypes.h>
 #include <stdint.h>
 #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))
 
@@ -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;
This page took 0.027933 seconds and 4 git commands to generate.