tap-driver.sh: flush stdout after each test result
[babeltrace.git] / lib / graph / component.c
index 84a850100a91d505a18690d80d8e544f509ff8fd..6494f64883128ccb3ce0d81c5e1ac7ab305ed3bc 100644 (file)
@@ -1,8 +1,7 @@
 /*
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
  * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * Author: Jérémie Galarneau <jeremie.galarneau@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
  * in the Software without restriction, including without limitation the rights
  */
 
 #define BT_LOG_TAG "COMP"
-#include <babeltrace/lib-logging-internal.h>
-
-#include <babeltrace/graph/self-component.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/component-class-internal.h>
-#include <babeltrace/graph/component-source-internal.h>
-#include <babeltrace/graph/component-filter-internal.h>
-#include <babeltrace/graph/component-sink-internal.h>
-#include <babeltrace/graph/connection-internal.h>
-#include <babeltrace/graph/graph-internal.h>
-#include <babeltrace/graph/notification-iterator-internal.h>
-#include <babeltrace/graph/port-internal.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/object.h>
-#include <babeltrace/types.h>
-#include <babeltrace/values.h>
-#include <babeltrace/values-internal.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace2/lib-logging-internal.h>
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/graph/self-component.h>
+#include <babeltrace2/graph/component-const.h>
+#include <babeltrace2/graph/component-source-const.h>
+#include <babeltrace2/graph/component-filter-const.h>
+#include <babeltrace2/graph/component-sink-const.h>
+#include <babeltrace2/graph/component-internal.h>
+#include <babeltrace2/graph/component-class-internal.h>
+#include <babeltrace2/graph/component-source-internal.h>
+#include <babeltrace2/graph/component-filter-internal.h>
+#include <babeltrace2/graph/component-sink-internal.h>
+#include <babeltrace2/graph/connection-internal.h>
+#include <babeltrace2/graph/graph-internal.h>
+#include <babeltrace2/graph/message-iterator-internal.h>
+#include <babeltrace2/graph/port-internal.h>
+#include <babeltrace2/babeltrace-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/value.h>
+#include <babeltrace2/value-internal.h>
 #include <stdint.h>
 #include <inttypes.h>
 
 static
 struct bt_component * (* const component_create_funcs[])(
-               struct bt_component_class *) = {
+               const struct bt_component_class *) = {
        [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_create,
        [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_create,
        [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_create,
@@ -182,19 +183,21 @@ void destroy_component(struct bt_object *obj)
 }
 
 enum bt_component_class_type bt_component_get_class_type(
-               struct bt_component *component)
+               const struct bt_component *component)
 {
        BT_ASSERT_PRE_NON_NULL(component, "Component");
        return component->class->type;
 }
 
 static
-struct bt_port *add_port(
+enum bt_self_component_status add_port(
                struct bt_component *component, GPtrArray *ports,
-               enum bt_port_type port_type, const char *name, void *user_data)
+               enum bt_port_type port_type, const char *name, void *user_data,
+               struct bt_port **port)
 {
        struct bt_port *new_port = NULL;
        struct bt_graph *graph = NULL;
+       enum bt_self_component_status status;
 
        BT_ASSERT_PRE_NON_NULL(component, "Component");
        BT_ASSERT_PRE_NON_NULL(name, "Name");
@@ -203,6 +206,10 @@ struct bt_port *add_port(
        BT_ASSERT_PRE(graph && !bt_graph_is_canceled(graph),
                "Component's graph is canceled: %![comp-]+c, %![graph-]+g",
                component, graph);
+       BT_ASSERT_PRE(
+               graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
+               "Component's graph is already configured: "
+               "%![comp-]+c, %![graph-]+g", component, graph);
 
        // TODO: Validate that the name is not already used.
 
@@ -213,7 +220,8 @@ struct bt_port *add_port(
        new_port = bt_port_create(component, port_type, name, user_data);
        if (!new_port) {
                BT_LOGE_STR("Cannot create port object.");
-               goto end;
+               status = BT_SELF_COMPONENT_STATUS_NOMEM;
+               goto error;
        }
 
        /*
@@ -227,29 +235,45 @@ struct bt_port *add_port(
        /*
         * Notify the graph's creator that a new port was added.
         */
-       bt_object_get_ref(bt_component_borrow_graph(component));
        graph = bt_component_borrow_graph(component);
        if (graph) {
-               bt_graph_notify_port_added(graph, new_port);
-               BT_OBJECT_PUT_REF_AND_RESET(graph);
+               enum bt_graph_listener_status listener_status;
+
+               listener_status = bt_graph_notify_port_added(graph, new_port);
+               if (listener_status != BT_GRAPH_LISTENER_STATUS_OK) {
+                       bt_graph_make_faulty(graph);
+                       status = listener_status;
+                       goto error;
+               }
        }
 
        BT_LIB_LOGD("Created and added port to component: "
                "%![comp-]+c, %![port-]+p", component, new_port);
 
+       *port = new_port;
+       status = BT_SELF_COMPONENT_STATUS_OK;
+
+       goto end;
+error:
+       /*
+        * We need to release the reference that we would otherwise have
+        * returned to the caller.
+        */
+       BT_PORT_PUT_REF_AND_RESET(new_port);
+
 end:
-       return new_port;
+       return status;
 }
 
 BT_HIDDEN
-uint64_t bt_component_get_input_port_count(struct bt_component *comp)
+uint64_t bt_component_get_input_port_count(const struct bt_component *comp)
 {
        BT_ASSERT_PRE_NON_NULL(comp, "Component");
        return (uint64_t) comp->input_ports->len;
 }
 
 BT_HIDDEN
-uint64_t bt_component_get_output_port_count(struct bt_component *comp)
+uint64_t bt_component_get_output_port_count(const struct bt_component *comp)
 {
        BT_ASSERT_PRE_NON_NULL(comp, "Component");
        return (uint64_t) comp->output_ports->len;
@@ -266,7 +290,6 @@ int bt_component_create(struct bt_component_class *component_class,
        BT_ASSERT(user_component);
        BT_ASSERT(component_class);
        BT_ASSERT(name);
-
        type = bt_component_class_get_type(component_class);
        BT_LIB_LOGD("Creating empty component from component class: %![cc-]+C, "
                "comp-name=\"%s\"", component_class, name);
@@ -277,8 +300,7 @@ int bt_component_create(struct bt_component_class *component_class,
                goto end;
        }
 
-       bt_object_init_shared_with_parent(&component->base,
-               destroy_component);
+       bt_object_init_shared_with_parent(&component->base, destroy_component);
        component->class = component_class;
        bt_object_get_no_null_check(component->class);
        component->destroy = component_destroy_funcs[type];
@@ -322,20 +344,20 @@ end:
        return ret;
 }
 
-const char *bt_component_get_name(struct bt_component *component)
+const char *bt_component_get_name(const struct bt_component *component)
 {
        BT_ASSERT_PRE_NON_NULL(component, "Component");
        return component->name->str;
 }
 
-struct bt_component_class *bt_component_borrow_class(
-               struct bt_component *component)
+const struct bt_component_class *bt_component_borrow_class_const(
+               const struct bt_component *component)
 {
        BT_ASSERT_PRE_NON_NULL(component, "Component");
        return component->class;
 }
 
-void *bt_self_component_get_data(struct bt_self_component *self_comp)
+void *bt_self_component_get_data(const struct bt_self_component *self_comp)
 {
        struct bt_component *component = (void *) self_comp;
 
@@ -361,7 +383,7 @@ void bt_component_set_graph(struct bt_component *component,
                graph ? &graph->base : NULL);
 }
 
-bt_bool bt_component_graph_is_canceled(struct bt_component *component)
+bt_bool bt_component_graph_is_canceled(const struct bt_component *component)
 {
        return bt_graph_is_canceled(
                (void *) bt_object_borrow_parent(&component->base));
@@ -433,130 +455,23 @@ struct bt_port_output *bt_component_borrow_output_port_by_index(
 }
 
 BT_HIDDEN
-struct bt_port_input *bt_component_add_input_port(
+enum bt_self_component_status bt_component_add_input_port(
                struct bt_component *component, const char *name,
-               void *user_data)
+               void *user_data, struct bt_port **port)
 {
        /* add_port() logs details */
-       return (void *)
-               add_port(component, component->input_ports,
-                       BT_PORT_TYPE_INPUT, name, user_data);
+       return add_port(component, component->input_ports,
+               BT_PORT_TYPE_INPUT, name, user_data, port);
 }
 
 BT_HIDDEN
-struct bt_port_output *bt_component_add_output_port(
+enum bt_self_component_status bt_component_add_output_port(
                struct bt_component *component, const char *name,
-               void *user_data)
+               void *user_data, struct bt_port **port)
 {
        /* add_port() logs details */
-       return (void *)
-               add_port(component, component->output_ports,
-                       BT_PORT_TYPE_OUTPUT, name, user_data);
-}
-
-static
-void remove_port_by_index(struct bt_component *component,
-               GPtrArray *ports, uint64_t index)
-{
-       struct bt_port *port;
-       struct bt_graph *graph;
-
-       BT_ASSERT(ports);
-       BT_ASSERT(index < ports->len);
-       port = g_ptr_array_index(ports, index);
-       BT_LIB_LOGD("Removing port from component: %![comp-]+c, %![port-]+p",
-               component, port);
-
-       /* Disconnect both ports of this port's connection, if any */
-       if (port->connection) {
-               bt_connection_end(port->connection, true);
-       }
-
-       /*
-        * The port's current reference count can be 0 at this point,
-        * which means its parent (component) keeps it alive. We are
-        * about to remove the port from its parent's container (with
-        * the g_ptr_array_remove_index() call below), which in this
-        * case would destroy it. This is not good because we still
-        * need the port for the bt_graph_notify_port_removed() call
-        * below (in which its component is `NULL` as expected because
-        * of the bt_object_set_parent() call below).
-        *
-        * To avoid a destroyed port during the notification callback,
-        * get a reference now, and put it (destroying the port if its
-        * reference count is 0 at this point) after notifying the
-        * private graph's user.
-        */
-       bt_object_get_no_null_check(&port->base);
-
-       /*
-        * Remove from parent's array of ports (weak refs). This never
-        * destroys the port object because its reference count is at
-        * least 1 thanks to the bt_object_get_no_null_check() call
-        * above.
-        */
-       g_ptr_array_remove_index(ports, index);
-
-       /* Detach port from its component parent */
-       bt_object_set_parent(&port->base, NULL);
-
-       /*
-        * Notify the graph's creator that a port is removed.
-        */
-       graph = bt_component_borrow_graph(component);
-       if (graph) {
-               bt_graph_notify_port_removed(graph, component, port);
-       }
-
-       BT_LIB_LOGD("Removed port from component: %![comp-]+c, %![port-]+p",
-               component, port);
-
-       /*
-        * Put the local reference. If this port's reference count was 0
-        * when entering this function, it is 1 now, so it is destroyed
-        * immediately.
-        */
-       bt_object_put_no_null_check(&port->base);
-}
-
-BT_HIDDEN
-void bt_component_remove_port(struct bt_component *component,
-               struct bt_port *port)
-{
-       uint64_t i;
-       GPtrArray *ports = NULL;
-
-       BT_ASSERT(component);
-       BT_ASSERT(port);
-
-       switch (port->type) {
-       case BT_PORT_TYPE_INPUT:
-               ports = component->input_ports;
-               break;
-       case BT_PORT_TYPE_OUTPUT:
-               ports = component->output_ports;
-               break;
-       default:
-               abort();
-       }
-
-       BT_ASSERT(ports);
-
-       for (i = 0; i < ports->len; i++) {
-               struct bt_port *cur_port = g_ptr_array_index(ports, i);
-
-               if (cur_port == port) {
-                       remove_port_by_index(component,
-                               ports, i);
-                       goto end;
-               }
-       }
-
-       BT_LIB_LOGW("Port to remove from component was not found: "
-               "%![comp-]+c, %![port-]+p", component, port);
-
-end:
-       return;
+       return add_port(component, component->output_ports,
+               BT_PORT_TYPE_OUTPUT, name, user_data, port);
 }
 
 BT_HIDDEN
@@ -565,7 +480,7 @@ enum bt_self_component_status bt_component_accept_port_connection(
                struct bt_port *other_port)
 {
        typedef enum bt_self_component_status (*method_t)(
-               void *, void *, void *);
+               void *, void *, const void *);
 
        enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
        method_t method = NULL;
@@ -628,7 +543,7 @@ enum bt_self_component_status bt_component_accept_port_connection(
                BT_LIB_LOGD("Calling user's \"accept port connection\" method: "
                        "%![comp-]+c, %![self-port-]+p, %![other-port-]+p",
                        comp, self_port, other_port);
-               status = method(comp, self_port, other_port);
+               status = method(comp, self_port, (void *) other_port);
                BT_LOGD("User method returned: status=%s",
                        bt_self_component_status_string(status));
        }
@@ -642,7 +557,7 @@ enum bt_self_component_status bt_component_port_connected(
                struct bt_port *other_port)
 {
        typedef enum bt_self_component_status (*method_t)(
-               void *, void *, void *);
+               void *, void *, const void *);
 
        enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
        method_t method = NULL;
@@ -705,82 +620,19 @@ enum bt_self_component_status bt_component_port_connected(
                BT_LIB_LOGD("Calling user's \"port connected\" method: "
                        "%![comp-]+c, %![self-port-]+p, %![other-port-]+p",
                        comp, self_port, other_port);
-               status = method(comp, self_port, other_port);
+               status = method(comp, self_port, (void *) other_port);
                BT_LOGD("User method returned: status=%s",
                        bt_self_component_status_string(status));
+               BT_ASSERT_PRE(status == BT_SELF_COMPONENT_STATUS_OK ||
+                       status == BT_SELF_COMPONENT_STATUS_ERROR ||
+                       status == BT_SELF_COMPONENT_STATUS_NOMEM,
+                       "Unexpected returned component status: status=%s",
+                       bt_self_component_status_string(status));
        }
 
        return status;
 }
 
-BT_HIDDEN
-void bt_component_port_disconnected(struct bt_component *comp,
-               struct bt_port *port)
-{
-       typedef void (*method_t)(void *, void *);
-
-       method_t method = NULL;
-
-       BT_ASSERT(comp);
-       BT_ASSERT(port);
-
-       switch (comp->class->type) {
-       case BT_COMPONENT_CLASS_TYPE_SOURCE:
-       {
-               struct bt_component_class_source *src_cc = (void *) comp->class;
-
-               switch (port->type) {
-               case BT_PORT_TYPE_OUTPUT:
-                       method = (method_t) src_cc->methods.output_port_disconnected;
-                       break;
-               default:
-                       abort();
-               }
-
-               break;
-       }
-       case BT_COMPONENT_CLASS_TYPE_FILTER:
-       {
-               struct bt_component_class_filter *flt_cc = (void *) comp->class;
-
-               switch (port->type) {
-               case BT_PORT_TYPE_INPUT:
-                       method = (method_t) flt_cc->methods.input_port_disconnected;
-                       break;
-               case BT_PORT_TYPE_OUTPUT:
-                       method = (method_t) flt_cc->methods.output_port_disconnected;
-                       break;
-               default:
-                       abort();
-               }
-
-               break;
-       }
-       case BT_COMPONENT_CLASS_TYPE_SINK:
-       {
-               struct bt_component_class_sink *sink_cc = (void *) comp->class;
-
-               switch (port->type) {
-               case BT_PORT_TYPE_INPUT:
-                       method = (method_t) sink_cc->methods.input_port_disconnected;
-                       break;
-               default:
-                       abort();
-               }
-
-               break;
-       }
-       default:
-               abort();
-       }
-
-       if (method) {
-               BT_LIB_LOGD("Calling user's \"port disconnected\" method: "
-                       "%![comp-]+c, %![port-]+p", comp, port);
-               method(comp, port);
-       }
-}
-
 BT_HIDDEN
 void bt_component_add_destroy_listener(struct bt_component *component,
                bt_component_destroy_listener_func func, void *data)
@@ -820,3 +672,13 @@ void bt_component_remove_destroy_listener(struct bt_component *component,
                }
        }
 }
+
+void bt_component_get_ref(const struct bt_component *component)
+{
+       bt_object_get_ref(component);
+}
+
+void bt_component_put_ref(const struct bt_component *component)
+{
+       bt_object_put_ref(component);
+}
This page took 0.029433 seconds and 4 git commands to generate.