lib: mark graph as faulty when adding a comp. or connecting ports fails
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 19 Mar 2019 18:51:38 +0000 (14:51 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 3 May 2019 22:19:38 +0000 (18:19 -0400)
This patch makes the graph's state become
`BT_GRAPH_CONFIGURATION_STATE_FAULTY` when there's a configuration
error, that is, when one of the bt_graph_add_*_component*() functions or
the bt_graph_connect_ports() fail.

When a graph is faulty, it becomes impossible to use it in any way,
either to continue configuring it or to run it.

This new state makes it invalid to do anything with a graph when it
failed one of its configuration steps, so that each step must succeed in
order to get a valid, useable, configured graph. This fixes the issue
where in bt_graph_connect_ports(), one of the "port connected" method
would succeed but the other would fail: in this scenario, the connection
ends immediately (disconnecting each port), but one component still
believes that its port was successfully connected (as there's no "port
disconnected" method, because we don't need it for anything else). With
this patch, the component's "port connected" is still called and
successful, but the component will never be used anyway, so there's less
danger for errors. bt_port_is_connected() will indeed return `BT_FALSE`
for this port in the component's finalization method, for example.

The alternative would be to add an optional component method to indicate
that a port which was just connected is in fact not connected because
the other component's "port connected" method failed. This is possible,
but what can a graph's user do with a failing bt_graph_connect_ports()
anyway? If the intention was to connect two ports, and this operation
fails, then there's probably no plan B: retrying the exact same port
connection would probably fail again.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
include/babeltrace/graph/graph-internal.h
lib/graph/graph.c

index 97289cf0f168e4b36d349845a5b0de199e46e34f..83812e7b51e7dda437d4a8aa6cc8710aa1c61347 100644 (file)
@@ -43,6 +43,7 @@ enum bt_graph_configuration_state {
        BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
        BT_GRAPH_CONFIGURATION_STATE_PARTIALLY_CONFIGURED,
        BT_GRAPH_CONFIGURATION_STATE_CONFIGURED,
+       BT_GRAPH_CONFIGURATION_STATE_FAULTY,
 };
 
 struct bt_graph {
@@ -211,6 +212,8 @@ enum bt_graph_status bt_graph_configure(struct bt_graph *graph)
        enum bt_graph_status status = BT_GRAPH_STATUS_OK;
        uint64_t i;
 
+       BT_ASSERT(graph->config_state != BT_GRAPH_CONFIGURATION_STATE_FAULTY);
+
        if (likely(graph->config_state ==
                        BT_GRAPH_CONFIGURATION_STATE_CONFIGURED)) {
                goto end;
index 49933d54931588dbd88ad7f6eddbc8f35bd6c38f..29ebee34d545a49f7bfacb52c558233c05c375ce 100644 (file)
@@ -408,7 +408,7 @@ enum bt_graph_status bt_graph_connect_ports(
        BT_ASSERT_PRE(!graph->canceled, "Graph is canceled: %!+g", graph);
        BT_ASSERT_PRE(
                graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
-               "Graph is already configured: %!+g", graph);
+               "Graph is not in the \"configuring\" state: %!+g", graph);
        BT_ASSERT_PRE(!bt_port_is_connected(upstream_port),
                "Upstream port is already connected: %!+p", upstream_port);
        BT_ASSERT_PRE(!bt_port_is_connected(downstream_port),
@@ -543,6 +543,10 @@ enum bt_graph_status bt_graph_connect_ports(
        }
 
 end:
+       if (status != BT_GRAPH_STATUS_OK) {
+               graph->config_state = BT_GRAPH_CONFIGURATION_STATE_FAULTY;
+       }
+
        bt_object_put_ref(connection);
        (void) init_can_consume;
        bt_graph_set_can_consume(graph, init_can_consume);
@@ -680,6 +684,8 @@ enum bt_graph_status bt_graph_consume(struct bt_graph *graph)
        BT_ASSERT_PRE(!graph->canceled, "Graph is canceled: %!+g", graph);
        BT_ASSERT_PRE(graph->can_consume,
                "Cannot consume graph in its current state: %!+g", graph);
+       BT_ASSERT_PRE(graph->config_state != BT_GRAPH_CONFIGURATION_STATE_FAULTY,
+               "Graph is in a faulty state: %!+g", graph);
        bt_graph_set_can_consume(graph, false);
        status = bt_graph_configure(graph);
        if (status) {
@@ -702,6 +708,8 @@ enum bt_graph_status bt_graph_run(struct bt_graph *graph)
        BT_ASSERT_PRE(!graph->canceled, "Graph is canceled: %!+g", graph);
        BT_ASSERT_PRE(graph->can_consume,
                "Cannot consume graph in its current state: %!+g", graph);
+       BT_ASSERT_PRE(graph->config_state != BT_GRAPH_CONFIGURATION_STATE_FAULTY,
+               "Graph is in a faulty state: %!+g", graph);
        bt_graph_set_can_consume(graph, false);
        status = bt_graph_configure(graph);
        if (status) {
@@ -1249,7 +1257,7 @@ enum bt_graph_status add_component_with_init_method_data(
        BT_ASSERT_PRE(!graph->canceled, "Graph is canceled: %!+g", graph);
        BT_ASSERT_PRE(
                graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
-               "Graph is already configured: %!+g", graph);
+               "Graph is not in the \"configuring\" state: %!+g", graph);
        BT_ASSERT_PRE(!component_name_exists(graph, name),
                "Duplicate component name: %!+g, name=\"%s\"", graph, name);
        BT_ASSERT_PRE(!params || bt_value_is_map(params),
@@ -1335,6 +1343,10 @@ enum bt_graph_status add_component_with_init_method_data(
        }
 
 end:
+       if (graph_status != BT_GRAPH_STATUS_OK) {
+               graph->config_state = BT_GRAPH_CONFIGURATION_STATE_FAULTY;
+       }
+
        bt_object_put_ref(component);
        bt_object_put_ref(new_params);
        (void) init_can_consume;
This page took 0.027626 seconds and 4 git commands to generate.