lib: do not allow port to be removed when message iterators are active
[babeltrace.git] / lib / graph / graph.c
index 3ba2321e5572c72a31f49af76469995ba62fb2f0..f28954188a3659764e3c04a6cc0c626ff57944e9 100644 (file)
@@ -1,6 +1,6 @@
 /*
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
  * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,8 @@
 #define BT_LOG_TAG "GRAPH"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/graph/component-internal.h>
 #include <babeltrace/graph/graph.h>
 #include <babeltrace/graph/graph-const.h>
 #include <babeltrace/graph/component-source-const.h>
 #include <babeltrace/graph/component-filter-const.h>
 #include <babeltrace/graph/port-const.h>
-#include <babeltrace/graph/notification-internal.h>
-#include <babeltrace/graph/notification-event-internal.h>
-#include <babeltrace/graph/notification-packet-internal.h>
+#include <babeltrace/graph/message-internal.h>
+#include <babeltrace/graph/message-event-internal.h>
+#include <babeltrace/graph/message-packet-internal.h>
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/common-internal.h>
 #include <babeltrace/types.h>
-#include <babeltrace/values.h>
-#include <babeltrace/values-const.h>
-#include <babeltrace/values-internal.h>
-#include <babeltrace/object.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/value.h>
+#include <babeltrace/value-const.h>
+#include <babeltrace/value-internal.h>
 #include <unistd.h>
 #include <glib.h>
 
@@ -119,21 +118,21 @@ void destroy_graph(struct bt_object *obj)
         * in this situation:
         *
         * 1. We put and destroy a connection.
-        * 2. This connection's destructor finalizes its active
-        *    notification iterators.
-        * 3. A notification iterator's finalization function gets a
-        *    new reference on its component (reference count goes from
-        *    0 to 1).
+        * 2. This connection's destructor finalizes its active message
+        *    iterators.
+        * 3. A message iterator's finalization function gets a new
+        *    reference on its component (reference count goes from 0 to
+        *    1).
         * 4. Since this component's reference count goes to 1, it takes
         *    a reference on its parent (this graph). This graph's
         *    reference count goes from 0 to 1.
-        * 5. The notification iterator's finalization function puts its
+        * 5. The message iterator's finalization function puts its
         *    component reference (reference count goes from 1 to 0).
         * 6. Since this component's reference count goes from 1 to 0,
         *    it puts its parent (this graph). This graph's reference
         *    count goes from 1 to 0.
-        * 7. Since this graph's reference count goes from 1 to 0,
-        *    its destructor is called (this function).
+        * 7. Since this graph's reference count goes from 1 to 0, its
+        *    destructor is called (this function).
         *
         * With the incrementation below, the graph's reference count at
         * step 4 goes from 1 to 2, and from 2 to 1 at step 6. This
@@ -144,7 +143,7 @@ void destroy_graph(struct bt_object *obj)
 
        /*
         * Cancel the graph to disallow some operations, like creating
-        * notification iterators and adding ports to components.
+        * message iterators and adding ports to components.
         */
        (void) bt_graph_cancel((void *) graph);
 
@@ -167,20 +166,24 @@ void destroy_graph(struct bt_object *obj)
                graph->listeners.sink_input_port_removed);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
                graph->listeners.source_filter_ports_connected);
+       CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
+               graph->listeners.filter_filter_ports_connected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
                graph->listeners.source_sink_ports_connected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
                graph->listeners.filter_sink_ports_connected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
                graph->listeners.source_filter_ports_disconnected);
+       CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
+               graph->listeners.filter_filter_ports_disconnected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
                graph->listeners.source_sink_ports_disconnected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
                graph->listeners.filter_sink_ports_disconnected);
 
-       if (graph->notifications) {
-               g_ptr_array_free(graph->notifications, TRUE);
-               graph->notifications = NULL;
+       if (graph->messages) {
+               g_ptr_array_free(graph->messages, TRUE);
+               graph->messages = NULL;
        }
 
        if (graph->connections) {
@@ -246,6 +249,12 @@ void destroy_graph(struct bt_object *obj)
                graph->listeners.source_filter_ports_connected = NULL;
        }
 
+       if (graph->listeners.filter_filter_ports_connected) {
+               g_array_free(graph->listeners.filter_filter_ports_connected,
+                       TRUE);
+               graph->listeners.filter_filter_ports_connected = NULL;
+       }
+
        if (graph->listeners.source_sink_ports_connected) {
                g_array_free(graph->listeners.source_sink_ports_connected,
                        TRUE);
@@ -270,43 +279,49 @@ void destroy_graph(struct bt_object *obj)
                graph->listeners.source_sink_ports_disconnected = NULL;
        }
 
+       if (graph->listeners.filter_filter_ports_disconnected) {
+               g_array_free(graph->listeners.filter_filter_ports_disconnected,
+                       TRUE);
+               graph->listeners.filter_filter_ports_disconnected = NULL;
+       }
+
        if (graph->listeners.filter_sink_ports_disconnected) {
                g_array_free(graph->listeners.filter_sink_ports_disconnected,
                        TRUE);
                graph->listeners.filter_sink_ports_disconnected = NULL;
        }
 
-       bt_object_pool_finalize(&graph->event_notif_pool);
-       bt_object_pool_finalize(&graph->packet_begin_notif_pool);
-       bt_object_pool_finalize(&graph->packet_end_notif_pool);
+       bt_object_pool_finalize(&graph->event_msg_pool);
+       bt_object_pool_finalize(&graph->packet_begin_msg_pool);
+       bt_object_pool_finalize(&graph->packet_end_msg_pool);
        g_free(graph);
 }
 
 static
-void destroy_notification_event(struct bt_notification *notif,
+void destroy_message_event(struct bt_message *msg,
                struct bt_graph *graph)
 {
-       bt_notification_event_destroy(notif);
+       bt_message_event_destroy(msg);
 }
 
 static
-void destroy_notification_packet_begin(struct bt_notification *notif,
+void destroy_message_packet_begin(struct bt_message *msg,
                struct bt_graph *graph)
 {
-       bt_notification_packet_begin_destroy(notif);
+       bt_message_packet_beginning_destroy(msg);
 }
 
 static
-void destroy_notification_packet_end(struct bt_notification *notif,
+void destroy_message_packet_end(struct bt_message *msg,
                struct bt_graph *graph)
 {
-       bt_notification_packet_end_destroy(notif);
+       bt_message_packet_end_destroy(msg);
 }
 
 static
-void notify_notification_graph_is_destroyed(struct bt_notification *notif)
+void notify_message_graph_is_destroyed(struct bt_message *msg)
 {
-       bt_notification_unlink_graph(notif);
+       bt_message_unlink_graph(msg);
 }
 
 struct bt_graph *bt_graph_create(void)
@@ -421,6 +436,14 @@ struct bt_graph *bt_graph_create(void)
                goto error;
        }
 
+       INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected,
+               graph->listeners.filter_filter_ports_connected);
+
+       if (!graph->listeners.filter_filter_ports_connected) {
+               ret = -1;
+               goto error;
+       }
+
        INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected,
                graph->listeners.filter_sink_ports_connected);
 
@@ -445,6 +468,14 @@ struct bt_graph *bt_graph_create(void)
                goto error;
        }
 
+       INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_disconnected,
+               graph->listeners.filter_filter_ports_disconnected);
+
+       if (!graph->listeners.filter_filter_ports_disconnected) {
+               ret = -1;
+               goto error;
+       }
+
        INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_disconnected,
                graph->listeners.filter_sink_ports_disconnected);
 
@@ -453,38 +484,38 @@ struct bt_graph *bt_graph_create(void)
                goto error;
        }
 
-       ret = bt_object_pool_initialize(&graph->event_notif_pool,
-               (bt_object_pool_new_object_func) bt_notification_event_new,
-               (bt_object_pool_destroy_object_func) destroy_notification_event,
+       ret = bt_object_pool_initialize(&graph->event_msg_pool,
+               (bt_object_pool_new_object_func) bt_message_event_new,
+               (bt_object_pool_destroy_object_func) destroy_message_event,
                graph);
        if (ret) {
-               BT_LOGE("Failed to initialize event notification pool: ret=%d",
+               BT_LOGE("Failed to initialize event message pool: ret=%d",
                        ret);
                goto error;
        }
 
-       ret = bt_object_pool_initialize(&graph->packet_begin_notif_pool,
-               (bt_object_pool_new_object_func) bt_notification_packet_begin_new,
-               (bt_object_pool_destroy_object_func) destroy_notification_packet_begin,
+       ret = bt_object_pool_initialize(&graph->packet_begin_msg_pool,
+               (bt_object_pool_new_object_func) bt_message_packet_beginning_new,
+               (bt_object_pool_destroy_object_func) destroy_message_packet_begin,
                graph);
        if (ret) {
-               BT_LOGE("Failed to initialize packet beginning notification pool: ret=%d",
+               BT_LOGE("Failed to initialize packet beginning message pool: ret=%d",
                        ret);
                goto error;
        }
 
-       ret = bt_object_pool_initialize(&graph->packet_end_notif_pool,
-               (bt_object_pool_new_object_func) bt_notification_packet_end_new,
-               (bt_object_pool_destroy_object_func) destroy_notification_packet_end,
+       ret = bt_object_pool_initialize(&graph->packet_end_msg_pool,
+               (bt_object_pool_new_object_func) bt_message_packet_end_new,
+               (bt_object_pool_destroy_object_func) destroy_message_packet_end,
                graph);
        if (ret) {
-               BT_LOGE("Failed to initialize packet end notification pool: ret=%d",
+               BT_LOGE("Failed to initialize packet end message pool: ret=%d",
                        ret);
                goto error;
        }
 
-       graph->notifications = g_ptr_array_new_with_free_func(
-               (GDestroyNotify) notify_notification_graph_is_destroyed);
+       graph->messages = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) notify_message_graph_is_destroyed);
        BT_LIB_LOGD("Created graph object: %!+g", graph);
 
 end:
@@ -1201,6 +1232,42 @@ bt_graph_add_source_sink_component_ports_connected_listener(
        return BT_GRAPH_STATUS_OK;
 }
 
+enum bt_graph_status
+bt_graph_add_filter_filter_component_ports_connected_listener(
+               struct bt_graph *graph,
+               bt_graph_filter_filter_component_ports_connected_listener_func func,
+               bt_graph_listener_removed_func listener_removed, void *data,
+               int *out_listener_id)
+{
+       struct bt_graph_listener_ports_connected listener = {
+               .base = {
+                       .removed = listener_removed,
+                       .data = data,
+               },
+               .func = (ports_connected_func_t) func,
+       };
+       int listener_id;
+
+       BT_ASSERT_PRE_NON_NULL(graph, "Graph");
+       BT_ASSERT_PRE_NON_NULL(func, "Listener");
+       BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
+       BT_ASSERT_PRE(!graph->in_remove_listener,
+               "Graph currently executing a \"listener removed\" listener: "
+               "%!+g", graph);
+       g_array_append_val(graph->listeners.filter_filter_ports_connected,
+               listener);
+       listener_id = graph->listeners.filter_filter_ports_connected->len - 1;
+       BT_LIB_LOGV("Added \"filter to filter component ports connected\" listener to graph: "
+               "%![graph-]+g, listener-addr=%p, id=%d", graph, listener,
+               listener_id);
+
+       if (listener_id) {
+               *out_listener_id = listener_id;
+       }
+
+       return BT_GRAPH_STATUS_OK;
+}
+
 enum bt_graph_status
 bt_graph_add_filter_sink_component_ports_connected_listener(
                struct bt_graph *graph,
@@ -1309,6 +1376,42 @@ bt_graph_add_source_sink_component_ports_disconnected_listener(
        return BT_GRAPH_STATUS_OK;
 }
 
+enum bt_graph_status
+bt_graph_add_filter_filter_component_ports_disconnected_listener(
+               struct bt_graph *graph,
+               bt_graph_filter_filter_component_ports_disconnected_listener_func func,
+               bt_graph_listener_removed_func listener_removed, void *data,
+               int *out_listener_id)
+{
+       struct bt_graph_listener_ports_disconnected listener = {
+               .base = {
+                       .removed = listener_removed,
+                       .data = data,
+               },
+               .func = (ports_disconnected_func_t) func,
+       };
+       int listener_id;
+
+       BT_ASSERT_PRE_NON_NULL(graph, "Graph");
+       BT_ASSERT_PRE_NON_NULL(func, "Listener");
+       BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
+       BT_ASSERT_PRE(!graph->in_remove_listener,
+               "Graph currently executing a \"listener removed\" listener: "
+               "%!+g", graph);
+       g_array_append_val(graph->listeners.filter_filter_ports_disconnected,
+               listener);
+       listener_id = graph->listeners.filter_filter_ports_disconnected->len - 1;
+       BT_LIB_LOGV("Added \"filter to filter component ports disconnected\" listener to graph: "
+               "%![graph-]+g, listener-addr=%p, id=%d", graph, listener,
+               listener_id);
+
+       if (listener_id) {
+               *out_listener_id = listener_id;
+       }
+
+       return BT_GRAPH_STATUS_OK;
+}
+
 enum bt_graph_status
 bt_graph_add_filter_sink_component_ports_disconnected_listener(
                struct bt_graph *graph,
@@ -1520,6 +1623,10 @@ void bt_graph_notify_ports_connected(struct bt_graph *graph,
        case BT_COMPONENT_CLASS_TYPE_FILTER:
        {
                switch (downstream_comp->class->type) {
+               case BT_COMPONENT_CLASS_TYPE_FILTER:
+                       listeners =
+                               graph->listeners.filter_filter_ports_connected;
+                       break;
                case BT_COMPONENT_CLASS_TYPE_SINK:
                        listeners =
                                graph->listeners.filter_sink_ports_connected;
@@ -1587,6 +1694,10 @@ void bt_graph_notify_ports_disconnected(struct bt_graph *graph,
        case BT_COMPONENT_CLASS_TYPE_FILTER:
        {
                switch (downstream_comp->class->type) {
+               case BT_COMPONENT_CLASS_TYPE_FILTER:
+                       listeners =
+                               graph->listeners.filter_filter_ports_disconnected;
+                       break;
                case BT_COMPONENT_CLASS_TYPE_SINK:
                        listeners =
                                graph->listeners.filter_sink_ports_disconnected;
@@ -1921,19 +2032,29 @@ end:
 }
 
 BT_HIDDEN
-void bt_graph_add_notification(struct bt_graph *graph,
-               struct bt_notification *notif)
+void bt_graph_add_message(struct bt_graph *graph,
+               struct bt_message *msg)
 {
        BT_ASSERT(graph);
-       BT_ASSERT(notif);
+       BT_ASSERT(msg);
 
        /*
         * It's okay not to take a reference because, when a
-        * notification's reference count drops to 0, either:
+        * message's reference count drops to 0, either:
         *
         * * It is recycled back to one of this graph's pool.
         * * It is destroyed because it doesn't have any link to any
         *   graph, which means the original graph is already destroyed.
         */
-       g_ptr_array_add(graph->notifications, notif);
+       g_ptr_array_add(graph->messages, msg);
+}
+
+void bt_graph_get_ref(const struct bt_graph *graph)
+{
+       bt_object_get_ref(graph);
+}
+
+void bt_graph_put_ref(const struct bt_graph *graph)
+{
+       bt_object_put_ref(graph);
 }
This page took 0.028954 seconds and 4 git commands to generate.