lib: replace trace is_static with destruction listeners
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Tue, 26 Feb 2019 23:45:02 +0000 (18:45 -0500)
committerFrancis Deslauriers <francis.deslauriers@efficios.com>
Thu, 2 May 2019 20:50:15 +0000 (20:50 +0000)
General idea
------------
Replace bt_trace is_static infrastructure with the concept of
destruction listener and extend it for the bt_trace_class object.

This allows for downstream components to ask to be notify of the
destruction of those objects. This notification is useful for component
that keep data related trace IR objects that should be deallocated when
the trace and/or trace class are destroyed.

This feature is mostly useful to handle sources which could create and
release lots of trace class and trace objects. In this case, when the
source message iterator is done with the stream objects (emitted all the
relevant stream end messages), it puts the stream, trace, and trace
class references. Then downstream users are notified that specific
external objects are about to be destroyed, so they release/close any
associated resource.

The flt.lttng-utils.debug-info component will make use of this
capability to cleanup the mapping between input and output objects it
needs to manage to do its function.

Implementation
--------------
Both trace class and trace offer the same interface and are implemented
in the exact same way.

Destruction listener callbacks and their associated private pointer are
stored in an array and are all called at the execution of the destroy
functions. Destruction listeners are registered using the following
functions:

  bt_trace_status bt_trace_add_destruction_listener(
          const bt_trace *trace,
          bt_trace_destruction_listener_func listener,
          void *data,
          uint64_t *listener_id);

  bt_trace_class_status bt_trace_class_add_destruction_listener(
          const bt_trace_class *trace,
          bt_trace_class_destruction_listener_func listener,
          void *data,
          uint64_t *listener_id);

It's possible to remove a destruction listener using the destruction
listener id received when register it initially used the following
functions:

  bt_trace_status bt_trace_remove_destruction_listener(
          const bt_trace *trace,
          uint64_t listener_id);

  bt_trace_class_status bt_trace_class_remove_destruction_listener(
          const bt_trace_class *trace_class,
          uint64_t listener_id);

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
include/babeltrace/trace-ir/trace-class-const.h
include/babeltrace/trace-ir/trace-class-internal.h
include/babeltrace/trace-ir/trace-const.h
include/babeltrace/trace-ir/trace-internal.h
include/babeltrace/trace-ir/trace.h
lib/lib-logging.c
lib/trace-ir/stream.c
lib/trace-ir/trace-class.c
lib/trace-ir/trace.c
plugins/ctf/fs-src/fs.c
plugins/text/dmesg/dmesg.c

index 0f80f304f1143cf78e8f931bed209ae08046ed00..839463de4ea3251dddc04657e608991d048303a6 100644 (file)
@@ -44,6 +44,9 @@ typedef enum bt_trace_class_status {
        BT_TRACE_CLASS_STATUS_NOMEM = -12,
 } bt_trace_class_status;
 
+typedef void (* bt_trace_class_destruction_listener_func)(
+               const bt_trace_class *trace_class, void *data);
+
 extern bt_bool bt_trace_class_assigns_automatic_stream_class_id(
                const bt_trace_class *trace_class);
 
@@ -74,6 +77,14 @@ bt_trace_class_borrow_stream_class_by_index_const(
 extern const bt_stream_class *bt_trace_class_borrow_stream_class_by_id_const(
                const bt_trace_class *trace_class, uint64_t id);
 
+extern bt_trace_class_status bt_trace_class_add_destruction_listener(
+        const bt_trace_class *trace_class,
+        bt_trace_class_destruction_listener_func listener,
+        void *data, uint64_t *listener_id);
+
+extern bt_trace_class_status bt_trace_class_remove_destruction_listener(
+        const bt_trace_class *trace_class, uint64_t listener_id);
+
 extern void bt_trace_class_get_ref(const bt_trace_class *trace_class);
 
 extern void bt_trace_class_put_ref(const bt_trace_class *trace_class);
index 2ffa3a3c4cd217364ef85702d6507a07614eac65..5afd3920faf4767b21745e35eddc7cd5f0497fff 100644 (file)
@@ -63,6 +63,7 @@ struct bt_trace_class {
        GPtrArray *stream_classes;
 
        bool assigns_automatic_stream_class_id;
+       GArray *destruction_listeners;
        bool frozen;
 };
 
index adb382401c964af440ab27cecc96f94af53fdfa7..15031029d9836a55e0e98da8f61f8bd620459727 100644 (file)
@@ -44,11 +44,8 @@ typedef enum bt_trace_status {
        BT_TRACE_STATUS_NOMEM = -12,
 } bt_trace_status;
 
-typedef void (* bt_trace_is_static_listener_func)(const bt_trace *trace,
-               void *data);
-
-typedef void (* bt_trace_listener_removed_func)(const bt_trace *trace,
-               void *data);
+typedef void (* bt_trace_destruction_listener_func)(
+               const bt_trace *trace, void *data);
 
 extern const bt_trace_class *bt_trace_borrow_class_const(
                const bt_trace *trace);
@@ -63,15 +60,12 @@ extern const bt_stream *bt_trace_borrow_stream_by_index_const(
 extern const bt_stream *bt_trace_borrow_stream_by_id_const(
                const bt_trace *trace, uint64_t id);
 
-extern bt_bool bt_trace_is_static(const bt_trace *trace);
-
-extern bt_trace_status bt_trace_add_is_static_listener(
+extern bt_trace_status bt_trace_add_destruction_listener(
                const bt_trace *trace,
-               bt_trace_is_static_listener_func listener,
-               bt_trace_listener_removed_func listener_removed, void *data,
-               uint64_t *listener_id);
+               bt_trace_destruction_listener_func listener,
+               void *data, uint64_t *listener_id);
 
-extern bt_trace_status bt_trace_remove_is_static_listener(
+extern bt_trace_status bt_trace_remove_destruction_listener(
                const bt_trace *trace, uint64_t listener_id);
 
 extern void bt_trace_get_ref(const bt_trace *trace);
index aa4cee514c3ab7f363436ba060d0ce8131bc46e7..16076673e09178fd5d8185281a1a57b91d14c071 100644 (file)
@@ -64,9 +64,7 @@ struct bt_trace {
         */
        GHashTable *stream_classes_stream_count;
 
-       GArray *is_static_listeners;
-       bool is_static;
-       bool in_remove_listener;
+       GArray *destruction_listeners;
        bool frozen;
 };
 
index 0ae25f9ae401d8af9ed3679835dde3a374e00101..36565dfc5e1e0b0bded876e1c11e8ca4f4905b9f 100644 (file)
@@ -52,8 +52,6 @@ extern bt_stream *bt_trace_borrow_stream_by_index(bt_trace *trace,
 extern bt_stream *bt_trace_borrow_stream_by_id(bt_trace *trace,
                uint64_t id);
 
-extern bt_trace_status bt_trace_make_static(bt_trace *trace);
-
 #ifdef __cplusplus
 }
 #endif
index 4b5557aa02cc1b7d41d67e0a6b966bf7a0c8bb03..111876489d78e81304bc435b6112c6d71032f9f5 100644 (file)
@@ -479,8 +479,6 @@ static inline void format_trace(char **buf_ch, bool extended,
                        PRFIELD(trace->streams->len));
        }
 
-       BUF_APPEND(", %sis-static=%d", PRFIELD(trace->is_static));
-
        if (!trace->class) {
                return;
        }
index ced7d81f79ebf44d7e33ce1487c88bf1b23e334e..5ae914ca82c45ffab6ccbf84123f08e3ed65bb7a 100644 (file)
@@ -108,8 +108,6 @@ struct bt_stream *create_stream_with_id(struct bt_stream_class *stream_class,
                "%![sc-]+S, %![trace-]+t", stream_class, trace);
        BT_ASSERT_PRE(stream_id_is_unique(trace, stream_class, id),
                "Duplicate stream ID: %![trace-]+t, id=%" PRIu64, trace, id);
-       BT_ASSERT_PRE(!trace->is_static,
-               "Trace is static: %![trace-]+t", trace);
        BT_LIB_LOGD("Creating stream object: %![trace-]+t, id=%" PRIu64,
                trace, id);
        stream = g_new0(struct bt_stream, 1);
index 7fa6a2f515b62ed2fda8f977e1b1a6cc474afdd0..3aa398fb94904744f0906925bfdbbe457c3ea76a 100644 (file)
 #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,6 +68,26 @@ void destroy_trace_class(struct bt_object *obj)
        struct bt_trace_class *tc = (void *) obj;
 
        BT_LIB_LOGD("Destroying trace class object: %!+T", tc);
+       /*
+        * 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.");
@@ -118,6 +143,13 @@ struct bt_trace_class *bt_trace_class_create(bt_self_component *self_comp)
                goto error;
        }
 
+       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;
@@ -163,6 +195,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)
index 2ef2b6f1301caffe4fd2508f6d9362a8405ce818..792d89f73389d427aed273ec92c8b3ebcca5636e 100644 (file)
@@ -55,9 +55,8 @@
 #include <string.h>
 #include <stdlib.h>
 
-struct bt_trace_is_static_listener_elem {
-       bt_trace_is_static_listener_func func;
-       bt_trace_listener_removed_func removed;
+struct bt_trace_destruction_listener_elem {
+       bt_trace_destruction_listener_func func;
        void *data;
 };
 
@@ -72,24 +71,24 @@ void destroy_trace(struct bt_object *obj)
        BT_LIB_LOGD("Destroying trace object: %!+t", trace);
 
        /*
-        * Call remove listeners first so that everything else still
-        * exists in the trace.
+        * Call destruction listener functions so that everything else
+        * still exists in the trace.
         */
-       if (trace->is_static_listeners) {
-               size_t i;
-
-               for (i = 0; i < trace->is_static_listeners->len; i++) {
-                       struct bt_trace_is_static_listener_elem elem =
-                               g_array_index(trace->is_static_listeners,
-                                       struct bt_trace_is_static_listener_elem, i);
-
-                       if (elem.removed) {
-                               elem.removed((void *) trace, elem.data);
+       if (trace->destruction_listeners) {
+               uint64_t i;
+               BT_LIB_LOGV("Calling trace destruction listener(s): %!+t", trace);
+               /* Call all the trace destruction listeners */
+               for (i = 0; i < trace->destruction_listeners->len; i++) {
+                       struct bt_trace_destruction_listener_elem elem =
+                               g_array_index(trace->destruction_listeners,
+                                               struct bt_trace_destruction_listener_elem, i);
+
+                       if (elem.func) {
+                               elem.func(trace, elem.data);
                        }
                }
-
-               g_array_free(trace->is_static_listeners, TRUE);
-               trace->is_static_listeners = NULL;
+               g_array_free(trace->destruction_listeners, TRUE);
+               trace->destruction_listeners = NULL;
        }
 
        if (trace->name.str) {
@@ -147,9 +146,9 @@ struct bt_trace *bt_trace_create(struct bt_trace_class *tc)
                goto error;
        }
 
-       trace->is_static_listeners = g_array_new(FALSE, TRUE,
-               sizeof(struct bt_trace_is_static_listener_elem));
-       if (!trace->is_static_listeners) {
+       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.");
                goto error;
        }
@@ -231,79 +230,44 @@ const struct bt_stream *bt_trace_borrow_stream_by_id_const(
        return bt_trace_borrow_stream_by_id((void *) trace, id);
 }
 
-bt_bool bt_trace_is_static(const struct bt_trace *trace)
-{
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return (bt_bool) trace->is_static;
-}
-
-enum bt_trace_status bt_trace_make_static(struct bt_trace *trace)
-{      uint64_t i;
-
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       trace->is_static = true;
-       bt_trace_freeze(trace);
-       BT_LIB_LOGV("Trace is now static: %!+t", trace);
-
-       /* Call all the "trace is static" listeners */
-       for (i = 0; i < trace->is_static_listeners->len; i++) {
-               struct bt_trace_is_static_listener_elem elem =
-                       g_array_index(trace->is_static_listeners,
-                               struct bt_trace_is_static_listener_elem, i);
-
-               if (elem.func) {
-                       elem.func((void *) trace, elem.data);
-               }
-       }
-
-       return BT_TRACE_STATUS_OK;
-}
-
-enum bt_trace_status bt_trace_add_is_static_listener(
+enum bt_trace_status bt_trace_add_destruction_listener(
                const struct bt_trace *c_trace,
-               bt_trace_is_static_listener_func listener,
-               bt_trace_listener_removed_func listener_removed, void *data,
-               uint64_t *listener_id)
+               bt_trace_destruction_listener_func listener,
+               void *data, uint64_t *listener_id)
 {
        struct bt_trace *trace = (void *) c_trace;
        uint64_t i;
-       struct bt_trace_is_static_listener_elem new_elem = {
+       struct bt_trace_destruction_listener_elem new_elem = {
                .func = listener,
-               .removed = listener_removed,
                .data = data,
        };
 
        BT_ASSERT_PRE_NON_NULL(trace, "Trace");
        BT_ASSERT_PRE_NON_NULL(listener, "Listener");
-       BT_ASSERT_PRE(!trace->is_static,
-               "Trace is already static: %!+t", trace);
-       BT_ASSERT_PRE(trace->in_remove_listener,
-               "Cannot call this function while executing a "
-               "remove listener: %!+t", trace);
 
        /* Find the next available spot */
-       for (i = 0; i < trace->is_static_listeners->len; i++) {
-               struct bt_trace_is_static_listener_elem elem =
-                       g_array_index(trace->is_static_listeners,
-                               struct bt_trace_is_static_listener_elem, i);
+       for (i = 0; i < trace->destruction_listeners->len; i++) {
+               struct bt_trace_destruction_listener_elem elem =
+                       g_array_index(trace->destruction_listeners,
+                               struct bt_trace_destruction_listener_elem, i);
 
                if (!elem.func) {
                        break;
                }
        }
 
-       if (i == trace->is_static_listeners->len) {
-               g_array_append_val(trace->is_static_listeners, new_elem);
+       if (i == trace->destruction_listeners->len) {
+               g_array_append_val(trace->destruction_listeners, new_elem);
        } else {
-               g_array_insert_val(trace->is_static_listeners, i, new_elem);
+               g_array_insert_val(trace->destruction_listeners, i, new_elem);
        }
 
        if (listener_id) {
                *listener_id = i;
        }
 
-       BT_LIB_LOGV("Added \"trace is static\" listener: "
-               "%![trace-]+t, listener-id=%" PRIu64, trace, i);
+       BT_LIB_LOGV("Added destruction listener: " "%![trace-]+t, "
+                       "listener-id=%" PRIu64, trace, i);
        return BT_TRACE_STATUS_OK;
 }
 
@@ -311,46 +275,30 @@ BT_ASSERT_PRE_FUNC
 static
 bool has_listener_id(const struct bt_trace *trace, uint64_t listener_id)
 {
-       BT_ASSERT(listener_id < trace->is_static_listeners->len);
-       return (&g_array_index(trace->is_static_listeners,
-                       struct bt_trace_is_static_listener_elem,
+       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;
 }
 
-enum bt_trace_status bt_trace_remove_is_static_listener(
+enum bt_trace_status bt_trace_remove_destruction_listener(
                const struct bt_trace *c_trace, uint64_t listener_id)
 {
        struct bt_trace *trace = (void *) c_trace;
-       struct bt_trace_is_static_listener_elem *elem;
+       struct bt_trace_destruction_listener_elem *elem;
 
        BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE(!trace->is_static,
-               "Trace is already static: %!+t", trace);
-       BT_ASSERT_PRE(trace->in_remove_listener,
-               "Cannot call this function while executing a "
-               "remove listener: %!+t", trace);
        BT_ASSERT_PRE(has_listener_id(trace, listener_id),
-               "Trace has no such \"trace is static\" listener ID: "
+               "Trace has no such trace destruction listener ID: "
                "%![trace-]+t, %" PRIu64, trace, listener_id);
-       elem = &g_array_index(trace->is_static_listeners,
-                       struct bt_trace_is_static_listener_elem,
+       elem = &g_array_index(trace->destruction_listeners,
+                       struct bt_trace_destruction_listener_elem,
                        listener_id);
        BT_ASSERT(elem->func);
 
-       if (elem->removed) {
-               /* Call remove listener */
-               BT_LIB_LOGV("Calling remove listener: "
-                       "%![trace-]+t, listener-id=%" PRIu64,
-                       trace, listener_id);
-               trace->in_remove_listener = true;
-               elem->removed((void *) trace, elem->data);
-               trace->in_remove_listener = false;
-       }
-
        elem->func = NULL;
-       elem->removed = NULL;
        elem->data = NULL;
-       BT_LIB_LOGV("Removed \"trace is static\" listener: "
+       BT_LIB_LOGV("Removed \"trace destruction listener: "
                "%![trace-]+t, listener-id=%" PRIu64,
                trace, listener_id);
        return BT_TRACE_STATUS_OK;
index 6260a24899b99cdb0f8f9aff8b690fcaeb20e750..901c495635dc94edd9e47f780533d17e9eb4d5be 100644 (file)
@@ -1023,15 +1023,6 @@ struct ctf_fs_trace *ctf_fs_trace_create(bt_self_component_source *self_comp,
                goto error;
        }
 
-       /*
-        * create_ds_file_groups() created all the streams that this
-        * trace needs. There won't be any more. Therefore it is safe to
-        * make this trace static.
-        */
-       if (ctf_fs_trace->trace) {
-               (void) bt_trace_make_static(ctf_fs_trace->trace);
-       }
-
        goto end;
 
 error:
index d8afa858c4af47006a1d8d2a51603c0cb4de0c76..c93fa78ef46aa4fc856cdc851a9b35c325b43e55 100644 (file)
@@ -299,12 +299,6 @@ int create_packet_and_stream_and_trace(struct dmesg_component *dmesg_comp)
                goto error;
        }
 
-       ret = bt_trace_make_static(dmesg_comp->trace);
-       if (ret) {
-               BT_LOGE_STR("Cannot make trace static.");
-               goto error;
-       }
-
        goto end;
 
 error:
This page took 0.034641 seconds and 4 git commands to generate.