struct bt_private_port *self_private_port,
struct bt_port *other_port);
-typedef void (*bt_component_class_port_connected_method)(
+typedef enum bt_component_status (*bt_component_class_port_connected_method)(
struct bt_private_component *private_component,
struct bt_private_port *self_private_port,
struct bt_port *other_port);
struct bt_port *other_port);
BT_HIDDEN
-void bt_component_port_connected(struct bt_component *comp,
+enum bt_component_status bt_component_port_connected(
+ struct bt_component *comp,
struct bt_port *self_port, struct bt_port *other_port);
BT_HIDDEN
* created on this connection.
*/
GPtrArray *iterators;
+
+ bool notified_upstream_port_connected;
+ bool notified_downstream_port_connected;
+ bool notified_graph_ports_connected;
};
static inline
}
static
-void colander_port_connected(struct bt_private_component *priv_comp,
+enum bt_component_status colander_port_connected(struct bt_private_component *priv_comp,
struct bt_private_port *self_priv_port,
struct bt_port *other_port)
{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
enum bt_connection_status conn_status;
struct bt_private_connection *priv_conn =
bt_private_port_get_private_connection(self_priv_port);
if (conn_status) {
BT_LOGE("Cannot create notification iterator from connection: "
"comp-addr=%p, conn-addr=%p", priv_comp, priv_conn);
+ status = BT_COMPONENT_STATUS_ERROR;
goto end;
}
end:
bt_put(priv_conn);
+ return status;
}
static
}
BT_HIDDEN
-void bt_component_port_connected(struct bt_component *comp,
+enum bt_component_status bt_component_port_connected(struct bt_component *comp,
struct bt_port *self_port, struct bt_port *other_port)
{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
BT_ASSERT(comp);
BT_ASSERT(self_port);
BT_ASSERT(other_port);
comp, bt_component_get_name(comp),
self_port, bt_port_get_name(self_port),
other_port, bt_port_get_name(other_port));
- comp->class->methods.port_connected(
+ status = comp->class->methods.port_connected(
bt_private_component_from_component(comp),
bt_private_port_from_port(self_port), other_port);
}
+
+ return status;
}
BT_HIDDEN
conn->upstream_port = NULL;
}
- if (downstream_comp) {
+ if (downstream_comp && conn->notified_downstream_port_connected) {
/* bt_component_port_disconnected() logs details */
bt_component_port_disconnected(downstream_comp,
downstream_port);
}
- if (upstream_comp) {
+ if (upstream_comp && conn->notified_upstream_port_connected) {
/* bt_component_port_disconnected() logs details */
bt_component_port_disconnected(upstream_comp, upstream_port);
}
BT_ASSERT(graph);
- /* bt_graph_notify_ports_disconnected() logs details */
- bt_graph_notify_ports_disconnected(graph, upstream_comp,
- downstream_comp, upstream_port, downstream_port);
+
+ if (conn->notified_graph_ports_connected) {
+ /* bt_graph_notify_ports_disconnected() logs details */
+ bt_graph_notify_ports_disconnected(graph, upstream_comp,
+ downstream_comp, upstream_port, downstream_port);
+ }
+
bt_put(downstream_comp);
bt_put(upstream_comp);
* Notify both components that their port is connected.
*/
BT_LOGD_STR("Notifying upstream component that its port is connected.");
- bt_component_port_connected(upstream_component, upstream_port,
- downstream_port);
+ component_status = bt_component_port_connected(upstream_component,
+ upstream_port, downstream_port);
+ if (component_status != BT_COMPONENT_STATUS_OK) {
+ BT_LOGW("Error while notifying upstream component that its port is connected: "
+ "status=%s, graph-addr=%p, "
+ "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
+ "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
+ "upstream-port-addr=%p, upstream-port-name=\"%s\", "
+ "downstream-port-addr=%p, downstream-port-name=\"%s\"",
+ bt_component_status_string(component_status), graph,
+ upstream_component, bt_component_get_name(upstream_component),
+ downstream_component, bt_component_get_name(downstream_component),
+ upstream_port, bt_port_get_name(upstream_port),
+ downstream_port, bt_port_get_name(downstream_port));
+ bt_connection_end(connection, true);
+ status = bt_graph_status_from_component_status(
+ component_status);
+ goto end;
+ }
+
+ connection->notified_upstream_port_connected = true;
BT_LOGD_STR("Notifying downstream component that its port is connected.");
- bt_component_port_connected(downstream_component, downstream_port,
- upstream_port);
+ component_status = bt_component_port_connected(downstream_component,
+ downstream_port, upstream_port);
+ if (component_status != BT_COMPONENT_STATUS_OK) {
+ BT_LOGW("Error while notifying downstream component that its port is connected: "
+ "status=%s, graph-addr=%p, "
+ "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
+ "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
+ "upstream-port-addr=%p, upstream-port-name=\"%s\", "
+ "downstream-port-addr=%p, downstream-port-name=\"%s\"",
+ bt_component_status_string(component_status), graph,
+ upstream_component, bt_component_get_name(upstream_component),
+ downstream_component, bt_component_get_name(downstream_component),
+ upstream_port, bt_port_get_name(upstream_port),
+ downstream_port, bt_port_get_name(downstream_port));
+ bt_connection_end(connection, true);
+ status = bt_graph_status_from_component_status(
+ component_status);
+ goto end;
+ }
+
+ connection->notified_downstream_port_connected = true;
/*
* Notify the graph's creator that both ports are connected.
*/
BT_LOGD_STR("Notifying graph's user that new component ports are connected.");
bt_graph_notify_ports_connected(graph, upstream_port, downstream_port);
+ connection->notified_graph_ports_connected = true;
BT_LOGD("Connected component ports within graph: "
"graph-addr=%p, "
"upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
}
BT_HIDDEN
-void pretty_port_connected(
+enum bt_component_status pretty_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port)
{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
enum bt_connection_status conn_status;
struct bt_private_connection *connection;
struct pretty_component *pretty;
conn_status = bt_private_connection_create_notification_iterator(
connection, &pretty->input_iterator);
if (conn_status != BT_CONNECTION_STATUS_OK) {
- pretty->error = true;
+ status = BT_COMPONENT_STATUS_ERROR;
}
bt_put(connection);
+ return status;
}
BT_HIDDEN
uint64_t count = 0;
uint64_t i = 0;
- if (unlikely(pretty->error)) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
it = pretty->input_iterator;
it_ret = bt_private_connection_notification_iterator_next(it, ¬ifs,
&count);
GString *tmp_string;
struct bt_value *plugin_opt_map; /* Temporary parameter map. */
bool use_colors;
- bool error;
uint64_t last_cycles_timestamp;
uint64_t delta_cycles;
enum bt_component_status pretty_consume(struct bt_private_component *component);
BT_HIDDEN
-void pretty_port_connected(
+enum bt_component_status pretty_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port);
return ret;
}
-void counter_port_connected(
+enum bt_component_status counter_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port)
{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
struct counter *counter;
struct bt_notification_iterator *iterator;
struct bt_private_connection *connection;
conn_status = bt_private_connection_create_notification_iterator(
connection, &iterator);
if (conn_status != BT_CONNECTION_STATUS_OK) {
- counter->error = true;
+ status = BT_COMPONENT_STATUS_ERROR;
goto end;
}
end:
bt_put(connection);
+ return status;
}
enum bt_component_status counter_consume(struct bt_private_component *component)
counter = bt_private_component_get_user_data(component);
BT_ASSERT(counter);
- if (unlikely(counter->error)) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
if (unlikely(!counter->notif_iter)) {
try_print_last(counter);
ret = BT_COMPONENT_STATUS_END;
uint64_t at;
uint64_t step;
bool hide_zero;
- bool error;
};
enum bt_component_status counter_init(struct bt_private_component *component,
struct bt_value *params, void *init_method_data);
void counter_finalize(struct bt_private_component *component);
-void counter_port_connected(struct bt_private_component *component,
+enum bt_component_status counter_port_connected(
+ struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port);
enum bt_component_status counter_consume(struct bt_private_component *component);
return ret;
}
-void dummy_port_connected(
+enum bt_component_status dummy_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port)
{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
struct dummy *dummy;
struct bt_notification_iterator *iterator;
struct bt_private_connection *connection;
conn_status = bt_private_connection_create_notification_iterator(
connection, &iterator);
if (conn_status != BT_CONNECTION_STATUS_OK) {
- dummy->error = true;
+ status = BT_COMPONENT_STATUS_ERROR;
goto end;
}
end:
bt_put(connection);
+ return status;
}
enum bt_component_status dummy_consume(struct bt_private_component *component)
dummy = bt_private_component_get_user_data(component);
BT_ASSERT(dummy);
- if (unlikely(dummy->error)) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
if (unlikely(!dummy->notif_iter)) {
ret = BT_COMPONENT_STATUS_END;
goto end;
struct dummy {
struct bt_notification_iterator *notif_iter;
- bool error;
};
enum bt_component_status dummy_init(struct bt_private_component *component,
struct bt_value *params, void *init_method_data);
void dummy_finalize(struct bt_private_component *component);
-void dummy_port_connected(struct bt_private_component *component,
+enum bt_component_status dummy_port_connected(
+ struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port);
enum bt_component_status dummy_consume(struct bt_private_component *component);
struct bt_private_component *priv_comp;
unsigned int next_port_num;
size_t available_input_ports;
- bool error;
bool initializing_muxer_notif_iter;
bool assume_absolute_clock_classes;
};
"notif-iter-addr=%p",
priv_comp, muxer_comp, muxer_notif_iter, priv_notif_iter);
- /* Are we in an error state set elsewhere? */
- if (unlikely(muxer_comp->error)) {
- BT_LOGE("Muxer component is already in an error state: returning BT_NOTIFICATION_ITERATOR_STATUS_ERROR: "
- "comp-addr=%p, muxer-comp-addr=%p, muxer-notif-iter-addr=%p, "
- "notif-iter-addr=%p",
- priv_comp, muxer_comp, muxer_notif_iter, priv_notif_iter);
- status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
status = muxer_notif_iter_do_next(muxer_comp, muxer_notif_iter,
notifs, capacity, count);
if (status < 0) {
bt_notification_iterator_status_string(status));
}
-end:
bt_put(priv_comp);
return status;
}
BT_HIDDEN
-void muxer_port_connected(
+enum bt_component_status muxer_port_connected(
struct bt_private_component *priv_comp,
struct bt_private_port *self_private_port,
struct bt_port *other_port)
{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
struct bt_port *self_port =
bt_port_borrow_from_private(self_private_port);
struct muxer_comp *muxer_comp =
"port-addr=%p, port-name=\"%s\", "
"muxer-notif-iter-addr=%p", self_port,
bt_port_get_name(self_port), muxer_notif_iter);
- muxer_comp->error = true;
+ status = BT_COMPONENT_STATUS_ERROR;
goto end;
}
BT_LOGE("Cannot ensure that at least one muxer component's input port is available: "
"muxer-comp-addr=%p, status=%s",
muxer_comp, bt_component_status_string(ret));
- muxer_comp->error = true;
+ status = BT_COMPONENT_STATUS_ERROR;
goto end;
}
end:
- return;
+ return status;
}
BT_HIDDEN
uint64_t *count);
BT_HIDDEN
-void muxer_port_connected(
+enum bt_component_status muxer_port_connected(
struct bt_private_component *priv_comp,
struct bt_private_port *self_private_port,
struct bt_port *other_port);
}
static
-void sink_port_connected(struct bt_private_component *private_component,
+enum bt_component_status sink_port_connected(
+ struct bt_private_component *private_component,
struct bt_private_port *self_private_port,
struct bt_port *other_port)
{
priv_conn, &user_data->notif_iter);
BT_ASSERT(conn_status == 0);
bt_put(priv_conn);
+ return BT_COMPONENT_STATUS_OK;
}
static
#include "tap/tap.h"
-#define NR_TESTS 77
+#define NR_TESTS 99
enum event_type {
COMP_ACCEPT_PORT_CONNECTION,
enum test {
TEST_EMPTY_GRAPH,
TEST_SIMPLE,
+ TEST_SRC_PORT_CONNECTED_ERROR,
+ TEST_SINK_PORT_CONNECTED_ERROR,
TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED,
TEST_SINK_REMOVES_PORT_IN_CONSUME,
TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT,
}
static
-void src_port_connected(struct bt_private_component *private_component,
+enum bt_component_status src_port_connected(
+ struct bt_private_component *private_component,
struct bt_private_port *self_private_port,
struct bt_port *other_port)
{
private_component, "hello", NULL, NULL);
BT_ASSERT(ret == 0);
break;
+ case TEST_SRC_PORT_CONNECTED_ERROR:
+ return BT_COMPONENT_STATUS_ERROR;
default:
break;
}
+
+ return BT_COMPONENT_STATUS_OK;
}
static
}
static
-void sink_port_connected(struct bt_private_component *private_component,
+enum bt_component_status sink_port_connected(
+ struct bt_private_component *private_component,
struct bt_private_port *self_private_port,
struct bt_port *other_port)
{
};
append_event(&event);
+
+ if (current_test == TEST_SINK_PORT_CONNECTED_ERROR) {
+ return BT_COMPONENT_STATUS_ERROR;
+ } else {
+ return BT_COMPONENT_STATUS_OK;
+ }
}
static
bt_put(sink_def_port);
}
+static
+void test_src_port_connected_error(void)
+{
+ struct bt_component *src;
+ struct bt_component *sink;
+ struct bt_graph *graph;
+ struct bt_port *src_def_port;
+ struct bt_port *sink_def_port;
+ struct bt_connection *conn = NULL;
+ struct event event;
+ enum bt_graph_status status;
+ size_t src_accept_port_connection_pos;
+ size_t src_port_connected_pos;
+
+ prepare_test(TEST_SRC_PORT_CONNECTED_ERROR, "port connected error: source");
+ graph = create_graph();
+ BT_ASSERT(graph);
+ src = create_src(graph);
+ sink = create_sink(graph);
+ src_def_port = bt_component_source_get_output_port_by_name(src, "out");
+ BT_ASSERT(src_def_port);
+ sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in");
+ BT_ASSERT(sink_def_port);
+ status = bt_graph_connect_ports(graph, src_def_port, sink_def_port,
+ &conn);
+ ok(status != BT_GRAPH_STATUS_OK,
+ "bt_graph_connect_ports() returns an error");
+ ok(!conn, "returned connection is NULL");
+
+ /* We're supposed to have 5 events */
+ ok(events->len == 5, "we have the expected number of events");
+
+ /* Source's port added */
+ event.type = GRAPH_PORT_ADDED;
+ event.data.graph_port_added.comp = src;
+ event.data.graph_port_added.port = src_def_port;
+ ok(has_event(&event), "got the expected graph's port added event (for source, initial)");
+
+ /* Sink's port added */
+ event.type = GRAPH_PORT_ADDED;
+ event.data.graph_port_added.comp = sink;
+ event.data.graph_port_added.port = sink_def_port;
+ ok(has_event(&event), "got the expected graph's port added event (for sink, initial)");
+
+ /* Source's accept port connection */
+ event.type = COMP_ACCEPT_PORT_CONNECTION;
+ event.data.comp_accept_port_connection.comp = src;
+ event.data.comp_accept_port_connection.self_port = src_def_port;
+ event.data.comp_accept_port_connection.other_port = sink_def_port;
+ ok(has_event(&event), "got the expected source's accept port connection event");
+ src_accept_port_connection_pos = event_pos(&event);
+
+ /* Sink's accept port connection */
+ event.type = COMP_ACCEPT_PORT_CONNECTION;
+ event.data.comp_accept_port_connection.comp = sink;
+ event.data.comp_accept_port_connection.self_port = sink_def_port;
+ event.data.comp_accept_port_connection.other_port = src_def_port;
+ ok(has_event(&event), "got the expected sink's accept port connection event");
+
+ /* Source's port connected */
+ event.type = COMP_PORT_CONNECTED;
+ event.data.comp_port_connected.comp = src;
+ event.data.comp_port_connected.self_port = src_def_port;
+ event.data.comp_port_connected.other_port = sink_def_port;
+ ok(has_event(&event), "got the expected source's port connected event");
+ src_port_connected_pos = event_pos(&event);
+
+ /* Order of events */
+ ok(src_accept_port_connection_pos < src_port_connected_pos,
+ "event order is good (1)");
+
+ bt_put(graph);
+ bt_put(sink);
+ bt_put(src);
+ bt_put(conn);
+ bt_put(src_def_port);
+ bt_put(sink_def_port);
+}
+
+static
+void test_sink_port_connected_error(void)
+{
+ struct bt_component *src;
+ struct bt_component *sink;
+ struct bt_graph *graph;
+ struct bt_port *src_def_port;
+ struct bt_port *sink_def_port;
+ struct bt_connection *conn = NULL;
+ struct event event;
+ enum bt_graph_status status;
+ size_t src_accept_port_connection_pos;
+ size_t sink_accept_port_connection_pos;
+ size_t src_port_connected_pos;
+ size_t src_port_disconnected_pos;
+ size_t sink_port_connected_pos;
+
+ prepare_test(TEST_SINK_PORT_CONNECTED_ERROR, "port connected error: sink");
+ graph = create_graph();
+ BT_ASSERT(graph);
+ src = create_src(graph);
+ sink = create_sink(graph);
+ src_def_port = bt_component_source_get_output_port_by_name(src, "out");
+ BT_ASSERT(src_def_port);
+ sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in");
+ BT_ASSERT(sink_def_port);
+ status = bt_graph_connect_ports(graph, src_def_port, sink_def_port,
+ &conn);
+ ok(status != BT_GRAPH_STATUS_OK,
+ "bt_graph_connect_ports() returns an error");
+ ok(!conn, "returned connection is NULL");
+
+ /* We're supposed to have 5 events */
+ ok(events->len == 7, "we have the expected number of events");
+
+ /* Source's port added */
+ event.type = GRAPH_PORT_ADDED;
+ event.data.graph_port_added.comp = src;
+ event.data.graph_port_added.port = src_def_port;
+ ok(has_event(&event), "got the expected graph's port added event (for source, initial)");
+
+ /* Sink's port added */
+ event.type = GRAPH_PORT_ADDED;
+ event.data.graph_port_added.comp = sink;
+ event.data.graph_port_added.port = sink_def_port;
+ ok(has_event(&event), "got the expected graph's port added event (for sink, initial)");
+
+ /* Source's accept port connection */
+ event.type = COMP_ACCEPT_PORT_CONNECTION;
+ event.data.comp_accept_port_connection.comp = src;
+ event.data.comp_accept_port_connection.self_port = src_def_port;
+ event.data.comp_accept_port_connection.other_port = sink_def_port;
+ ok(has_event(&event), "got the expected source's accept port connection event");
+ src_accept_port_connection_pos = event_pos(&event);
+
+ /* Sink's accept port connection */
+ event.type = COMP_ACCEPT_PORT_CONNECTION;
+ event.data.comp_accept_port_connection.comp = sink;
+ event.data.comp_accept_port_connection.self_port = sink_def_port;
+ event.data.comp_accept_port_connection.other_port = src_def_port;
+ ok(has_event(&event), "got the expected sink's accept port connection event");
+ sink_accept_port_connection_pos = event_pos(&event);
+
+ /* Source's port connected */
+ event.type = COMP_PORT_CONNECTED;
+ event.data.comp_port_connected.comp = src;
+ event.data.comp_port_connected.self_port = src_def_port;
+ event.data.comp_port_connected.other_port = sink_def_port;
+ ok(has_event(&event), "got the expected source's port connected event");
+ src_port_connected_pos = event_pos(&event);
+
+ /* Sink's port connected */
+ event.type = COMP_PORT_CONNECTED;
+ event.data.comp_port_connected.comp = sink;
+ event.data.comp_port_connected.self_port = sink_def_port;
+ event.data.comp_port_connected.other_port = src_def_port;
+ ok(has_event(&event), "got the expected sink's port connected event");
+ sink_port_connected_pos = event_pos(&event);
+
+ /* Source's port disconnected */
+ event.type = COMP_PORT_DISCONNECTED;
+ event.data.comp_port_disconnected.comp = src;
+ event.data.comp_port_disconnected.port = src_def_port;
+ ok(has_event(&event), "got the expected source's port disconnected event");
+ src_port_disconnected_pos = event_pos(&event);
+
+ /* Order of events */
+ ok(src_accept_port_connection_pos < src_port_connected_pos,
+ "event order is good (1)");
+ ok(sink_accept_port_connection_pos < sink_port_connected_pos,
+ "event order is good (2)");
+ ok(sink_port_connected_pos < src_port_disconnected_pos,
+ "event order is good (3)");
+
+ bt_put(graph);
+ bt_put(sink);
+ bt_put(src);
+ bt_put(conn);
+ bt_put(src_def_port);
+ bt_put(sink_def_port);
+}
+
static
void test_empty_graph(void)
{
init_test();
test_empty_graph();
test_simple();
+ test_src_port_connected_error();
+ test_sink_port_connected_error();
test_src_adds_port_in_port_connected();
test_sink_removes_port_in_port_connected();
test_sink_removes_port_in_port_connected_then_src_removes_disconnected_port();
}
static
-void sink_port_connected(struct bt_private_component *private_component,
+enum bt_component_status sink_port_connected(
+ struct bt_private_component *private_component,
struct bt_private_port *self_private_port,
struct bt_port *other_port)
{
priv_conn, &user_data->notif_iter);
BT_ASSERT(conn_status == 0);
bt_put(priv_conn);
+ return BT_COMPONENT_STATUS_OK;
}
static