X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=src%2Flib%2Fgraph%2Fgraph.c;h=4290039f0c3179590bb183c21a94328f14fc3aa7;hb=9340eff9237ee05d044f7953495300506e152315;hp=22c4f92f8ec33314cd7f74cec71a5adb0781e3b8;hpb=17f3083a0b4d318d3303c8a5bfa63db6a874ec73;p=babeltrace.git diff --git a/src/lib/graph/graph.c b/src/lib/graph/graph.c index 22c4f92f..4290039f 100644 --- a/src/lib/graph/graph.c +++ b/src/lib/graph/graph.c @@ -1,43 +1,23 @@ /* + * SPDX-License-Identifier: MIT + * * Copyright 2017-2018 Philippe Proulx * Copyright 2017 Jérémie Galarneau - * - * 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 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #define BT_LOG_TAG "LIB/GRAPH" #include "lib/logging.h" #include "common/assert.h" -#include "lib/assert-pre.h" -#include "lib/assert-post.h" +#include "lib/assert-cond.h" #include -#include -#include -#include -#include +#include +#include #include "lib/graph/message/message.h" #include "compat/compiler.h" #include "common/common.h" #include #include -#include #include "lib/value.h" #include #include @@ -55,26 +35,12 @@ typedef enum bt_graph_listener_func_status (*port_added_func_t)(const void *, const void *, void *); -typedef enum bt_graph_listener_func_status -(*ports_connected_func_t)(const void *, const void *, const void *, - const void *, void *); - typedef enum bt_component_class_initialize_method_status (*comp_init_method_t)(const void *, void *, const void *, void *); -struct bt_graph_listener { - bt_graph_listener_removed_func removed; - void *data; -}; - struct bt_graph_listener_port_added { - struct bt_graph_listener base; port_added_func_t func; -}; - -struct bt_graph_listener_ports_connected { - struct bt_graph_listener base; - ports_connected_func_t func; + void *data; }; #define INIT_LISTENERS_ARRAY(_type, _listeners) \ @@ -86,23 +52,6 @@ struct bt_graph_listener_ports_connected { } \ } while (0) -#define CALL_REMOVE_LISTENERS(_type, _listeners) \ - do { \ - size_t i; \ - \ - if (!_listeners) { \ - break; \ - } \ - for (i = 0; i < (_listeners)->len; i++) { \ - _type *listener = \ - &g_array_index((_listeners), _type, i); \ - \ - if (listener->base.removed) { \ - listener->base.removed(listener->base.data); \ - } \ - } \ - } while (0) - static void destroy_graph(struct bt_object *obj) { @@ -138,24 +87,6 @@ void destroy_graph(struct bt_object *obj) obj->ref_count++; graph->config_state = BT_GRAPH_CONFIGURATION_STATE_DESTROYING; - /* Call all remove listeners */ - CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added, - graph->listeners.source_output_port_added); - CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added, - graph->listeners.filter_output_port_added); - CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added, - graph->listeners.filter_input_port_added); - CALL_REMOVE_LISTENERS(struct bt_graph_listener_port_added, - graph->listeners.sink_input_port_added); - 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); - if (graph->messages) { g_ptr_array_free(graph->messages, TRUE); graph->messages = NULL; @@ -206,30 +137,6 @@ void destroy_graph(struct bt_object *obj) graph->listeners.sink_input_port_added = NULL; } - if (graph->listeners.source_filter_ports_connected) { - g_array_free(graph->listeners.source_filter_ports_connected, - TRUE); - 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); - graph->listeners.source_sink_ports_connected = NULL; - } - - if (graph->listeners.filter_sink_ports_connected) { - g_array_free(graph->listeners.filter_sink_ports_connected, - TRUE); - graph->listeners.filter_sink_ports_connected = NULL; - } - 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); @@ -238,21 +145,21 @@ void destroy_graph(struct bt_object *obj) static void destroy_message_event(struct bt_message *msg, - struct bt_graph *graph) + struct bt_graph *graph __attribute__((unused))) { bt_message_event_destroy(msg); } static void destroy_message_packet_begin(struct bt_message *msg, - struct bt_graph *graph) + struct bt_graph *graph __attribute__((unused))) { bt_message_packet_destroy(msg); } static void destroy_message_packet_end(struct bt_message *msg, - struct bt_graph *graph) + struct bt_graph *graph __attribute__((unused))) { bt_message_packet_destroy(msg); } @@ -263,13 +170,15 @@ void notify_message_graph_is_destroyed(struct bt_message *msg) bt_message_unlink_graph(msg); } +BT_EXPORT struct bt_graph *bt_graph_create(uint64_t mip_version) { struct bt_graph *graph; int ret; BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE(mip_version <= bt_get_maximal_mip_version(), + BT_ASSERT_PRE("valid-mip-version", + mip_version <= bt_get_maximal_mip_version(), "Unknown MIP version: mip-version=%" PRIu64 ", " "max-mip-version=%" PRIu64, mip_version, bt_get_maximal_mip_version()); @@ -329,34 +238,6 @@ struct bt_graph *bt_graph_create(uint64_t mip_version) goto error; } - INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected, - graph->listeners.source_filter_ports_connected); - - if (!graph->listeners.source_filter_ports_connected) { - goto error; - } - - INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected, - graph->listeners.source_sink_ports_connected); - - if (!graph->listeners.source_sink_ports_connected) { - goto error; - } - - INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected, - graph->listeners.filter_filter_ports_connected); - - if (!graph->listeners.filter_filter_ports_connected) { - goto error; - } - - INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected, - graph->listeners.filter_sink_ports_connected); - - if (!graph->listeners.filter_sink_ports_connected) { - goto error; - } - graph->interrupters = g_ptr_array_new_with_free_func( (GDestroyNotify) bt_object_put_ref_no_null_check); if (!graph->interrupters) { @@ -417,6 +298,7 @@ error: goto end; } +BT_EXPORT enum bt_graph_connect_ports_status bt_graph_connect_ports( struct bt_graph *graph, const struct bt_port_output *upstream_port_out, @@ -424,7 +306,6 @@ enum bt_graph_connect_ports_status bt_graph_connect_ports( const struct bt_connection **user_connection) { enum bt_graph_connect_ports_status status = BT_FUNC_STATUS_OK; - enum bt_graph_listener_func_status listener_status; struct bt_connection *connection = NULL; struct bt_port *upstream_port = (void *) upstream_port_out; struct bt_port *downstream_port = (void *) downstream_port_in; @@ -434,20 +315,25 @@ enum bt_graph_connect_ports_status bt_graph_connect_ports( bool init_can_consume; BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(graph, "Graph"); - BT_ASSERT_PRE_NON_NULL(upstream_port, "Upstream port"); - BT_ASSERT_PRE_NON_NULL(downstream_port, "Downstream port port"); - BT_ASSERT_PRE( + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_NON_NULL("upstream-port", upstream_port, "Upstream port"); + BT_ASSERT_PRE_NON_NULL("downstream-port", downstream_port, + "Downstream port port"); + BT_ASSERT_PRE("graph-is-not-configured", graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING, "Graph is not in the \"configuring\" state: %!+g", graph); - BT_ASSERT_PRE(!bt_port_is_connected(upstream_port), + BT_ASSERT_PRE("upstream-port-is-not-connected", + !bt_port_is_connected(upstream_port), "Upstream port is already connected: %!+p", upstream_port); - BT_ASSERT_PRE(!bt_port_is_connected(downstream_port), + BT_ASSERT_PRE("downstream-port-is-not-connected", + !bt_port_is_connected(downstream_port), "Downstream port is already connected: %!+p", downstream_port); - BT_ASSERT_PRE(bt_port_borrow_component_inline((void *) upstream_port), + BT_ASSERT_PRE("upstream-port-has-component", + bt_port_borrow_component_inline((void *) upstream_port), "Upstream port does not belong to a component: %!+p", upstream_port); - BT_ASSERT_PRE(bt_port_borrow_component_inline((void *) downstream_port), + BT_ASSERT_PRE("downstream-port-has-component", + bt_port_borrow_component_inline((void *) downstream_port), "Downstream port does not belong to a component: %!+p", downstream_port); init_can_consume = graph->can_consume; @@ -526,27 +412,6 @@ enum bt_graph_connect_ports_status bt_graph_connect_ports( 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."); - listener_status = bt_graph_notify_ports_connected(graph, upstream_port, downstream_port); - if (listener_status != BT_FUNC_STATUS_OK) { - if (listener_status < 0) { - BT_LIB_LOGW_APPEND_CAUSE( - "Graph \"ports connected\" listener failed: " - "status=%d, %![graph-]+g, %![up-comp-]+c, " - "%![down-comp-]+c, %![up-port-]+p, %![down-port-]+p", - listener_status, graph, - upstream_component, downstream_component, - upstream_port, downstream_port); - } - - status = (int) listener_status; - goto end; - } - - connection->notified_graph_ports_connected = true; BT_LIB_LOGI("Connected component ports within graph: " "%![graph-]+g, %![up-comp-]+c, %![down-comp-]+c, " "%![up-port-]+p, %![down-port-]+p", @@ -556,7 +421,6 @@ enum bt_graph_connect_ports_status bt_graph_connect_ports( if (user_connection) { /* Move reference to user */ *user_connection = connection; - connection = NULL; } end: @@ -570,6 +434,8 @@ end: return status; } +#define CONSUME_METHOD_NAME "bt_component_class_sink_consume_method" + static inline int consume_graph_sink(struct bt_component_sink *comp) { @@ -583,14 +449,16 @@ int consume_graph_sink(struct bt_component_sink *comp) consume_status = sink_class->methods.consume((void *) comp); BT_LOGD("User method returned: status=%s", bt_common_func_status_string(consume_status)); - BT_ASSERT_POST_DEV(consume_status == BT_FUNC_STATUS_OK || + BT_ASSERT_POST_DEV(CONSUME_METHOD_NAME, "valid-status", + consume_status == BT_FUNC_STATUS_OK || consume_status == BT_FUNC_STATUS_END || consume_status == BT_FUNC_STATUS_AGAIN || consume_status == BT_FUNC_STATUS_ERROR || consume_status == BT_FUNC_STATUS_MEMORY_ERROR, "Invalid component status returned by consuming method: " "status=%s", bt_common_func_status_string(consume_status)); - BT_ASSERT_POST_DEV_NO_ERROR_IF_NO_ERROR_STATUS(consume_status); + BT_ASSERT_POST_DEV_NO_ERROR_IF_NO_ERROR_STATUS(CONSUME_METHOD_NAME, + consume_status); if (consume_status) { if (consume_status < 0) { BT_LIB_LOGW_APPEND_CAUSE( @@ -643,7 +511,6 @@ end: return status; } -BT_HIDDEN int bt_graph_consume_sink_no_check(struct bt_graph *graph, struct bt_component_sink *sink) { @@ -677,13 +544,14 @@ end: } static inline -int consume_no_check(struct bt_graph *graph) +int consume_no_check(struct bt_graph *graph, const char *api_func) { int status = BT_FUNC_STATUS_OK; struct bt_component *sink; GList *current_node; - BT_ASSERT_PRE_DEV(graph->has_sink, + BT_ASSERT_PRE_DEV_FROM_FUNC(api_func, + "graph-has-at-least-one-sink-component", graph->has_sink, "Graph has no sink component: %!+g", graph); BT_LIB_LOGD("Making next sink component consume: %![graph-]+g", graph); @@ -702,45 +570,127 @@ end: return status; } +#define GRAPH_IS_CONFIGURED_METHOD_NAME \ + "bt_component_class_sink_graph_is_configured_method" + +static +int configure_graph(struct bt_graph *graph, const char *api_func) +{ + int status = BT_FUNC_STATUS_OK; + uint64_t i; + + BT_ASSERT_DBG(graph->config_state != + BT_GRAPH_CONFIGURATION_STATE_FAULTY); + + if (G_LIKELY(graph->config_state == + BT_GRAPH_CONFIGURATION_STATE_CONFIGURED)) { + goto end; + } + + BT_ASSERT_PRE_FROM_FUNC(api_func, + "graph-has-at-least-one-sink-component", + graph->has_sink, "Graph has no sink component: %!+g", graph); + graph->config_state = BT_GRAPH_CONFIGURATION_STATE_PARTIALLY_CONFIGURED; + + for (i = 0; i < graph->components->len; i++) { + struct bt_component *comp = graph->components->pdata[i]; + struct bt_component_sink *comp_sink = (void *) comp; + struct bt_component_class_sink *comp_cls_sink = + (void *) comp->class; + + if (comp->class->type != BT_COMPONENT_CLASS_TYPE_SINK) { + continue; + } + + if (comp_sink->graph_is_configured_method_called) { + continue; + } + + if (comp_cls_sink->methods.graph_is_configured) { + enum bt_component_class_sink_graph_is_configured_method_status comp_status; + + BT_LIB_LOGD("Calling user's \"graph is configured\" method: " + "%![graph-]+g, %![comp-]+c", + graph, comp); + comp_status = comp_cls_sink->methods.graph_is_configured( + (void *) comp_sink); + BT_LIB_LOGD("User method returned: status=%s", + bt_common_func_status_string(comp_status)); + BT_ASSERT_POST(GRAPH_IS_CONFIGURED_METHOD_NAME, + "valid-status", + comp_status == BT_FUNC_STATUS_OK || + comp_status == BT_FUNC_STATUS_ERROR || + comp_status == BT_FUNC_STATUS_MEMORY_ERROR, + "Unexpected returned status: status=%s", + bt_common_func_status_string(comp_status)); + BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS( + GRAPH_IS_CONFIGURED_METHOD_NAME, comp_status); + if (comp_status != BT_FUNC_STATUS_OK) { + if (comp_status < 0) { + BT_LIB_LOGW_APPEND_CAUSE( + "Component's \"graph is configured\" method failed: " + "%![comp-]+c, status=%s", + comp, + bt_common_func_status_string( + comp_status)); + } + + status = comp_status; + goto end; + } + } + + comp_sink->graph_is_configured_method_called = true; + } + + graph->config_state = BT_GRAPH_CONFIGURATION_STATE_CONFIGURED; + +end: + return status; +} + +BT_EXPORT enum bt_graph_run_once_status bt_graph_run_once(struct bt_graph *graph) { enum bt_graph_run_once_status status; BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_DEV_NON_NULL(graph, "Graph"); - BT_ASSERT_PRE_DEV(graph->can_consume, + BT_ASSERT_PRE_DEV_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_DEV("graph-can-consume", graph->can_consume, "Cannot consume graph in its current state: %!+g", graph); - BT_ASSERT_PRE_DEV(graph->config_state != - BT_GRAPH_CONFIGURATION_STATE_FAULTY, + BT_ASSERT_PRE_DEV("graph-is-not-faulty", + 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); + status = configure_graph(graph, __func__); if (G_UNLIKELY(status)) { - /* bt_graph_configure() logs errors */ + /* configure_graph() logs errors */ goto end; } - status = consume_no_check(graph); + status = consume_no_check(graph, __func__); bt_graph_set_can_consume(graph, true); end: return status; } +BT_EXPORT enum bt_graph_run_status bt_graph_run(struct bt_graph *graph) { enum bt_graph_run_status status; BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(graph, "Graph"); - BT_ASSERT_PRE(graph->can_consume, + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE("graph-can-consume", graph->can_consume, "Cannot consume graph in its current state: %!+g", graph); - BT_ASSERT_PRE(graph->config_state != BT_GRAPH_CONFIGURATION_STATE_FAULTY, + BT_ASSERT_PRE("graph-is-not-faulty", + 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); + status = configure_graph(graph, __func__); if (G_UNLIKELY(status)) { - /* bt_graph_configure() logs errors */ + /* configure_graph() logs errors */ goto end; } @@ -760,7 +710,7 @@ enum bt_graph_run_status bt_graph_run(struct bt_graph *graph) goto end; } - status = consume_no_check(graph); + status = consume_no_check(graph, __func__); if (G_UNLIKELY(status == BT_FUNC_STATUS_AGAIN)) { /* * If AGAIN is received and there are multiple @@ -797,29 +747,22 @@ end: return status; } +BT_EXPORT enum bt_graph_add_listener_status bt_graph_add_source_component_output_port_added_listener( struct bt_graph *graph, bt_graph_source_component_output_port_added_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) + void *data, bt_listener_id *out_listener_id) { struct bt_graph_listener_port_added listener = { - .base = { - .removed = listener_removed, - .data = data, - }, .func = (port_added_func_t) func, + .data = data, }; bt_listener_id listener_id; BT_ASSERT_PRE_NO_ERROR(); - 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); + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_LISTENER_FUNC_NON_NULL(func); g_array_append_val(graph->listeners.source_output_port_added, listener); listener_id = graph->listeners.source_output_port_added->len - 1; BT_LIB_LOGD("Added \"source component output port added\" listener to graph: " @@ -833,29 +776,22 @@ bt_graph_add_source_component_output_port_added_listener( return BT_FUNC_STATUS_OK; } +BT_EXPORT enum bt_graph_add_listener_status bt_graph_add_filter_component_output_port_added_listener( struct bt_graph *graph, bt_graph_filter_component_output_port_added_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) + void *data, bt_listener_id *out_listener_id) { struct bt_graph_listener_port_added listener = { - .base = { - .removed = listener_removed, - .data = data, - }, .func = (port_added_func_t) func, + .data = data, }; bt_listener_id listener_id; BT_ASSERT_PRE_NO_ERROR(); - 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); + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_LISTENER_FUNC_NON_NULL(func); g_array_append_val(graph->listeners.filter_output_port_added, listener); listener_id = graph->listeners.filter_output_port_added->len - 1; BT_LIB_LOGD("Added \"filter component output port added\" listener to graph: " @@ -869,29 +805,22 @@ bt_graph_add_filter_component_output_port_added_listener( return BT_FUNC_STATUS_OK; } +BT_EXPORT enum bt_graph_add_listener_status bt_graph_add_filter_component_input_port_added_listener( struct bt_graph *graph, bt_graph_filter_component_input_port_added_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) + void *data, bt_listener_id *out_listener_id) { struct bt_graph_listener_port_added listener = { - .base = { - .removed = listener_removed, - .data = data, - }, .func = (port_added_func_t) func, + .data = data, }; bt_listener_id listener_id; BT_ASSERT_PRE_NO_ERROR(); - 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); + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_LISTENER_FUNC_NON_NULL(func); g_array_append_val(graph->listeners.filter_input_port_added, listener); listener_id = graph->listeners.filter_input_port_added->len - 1; BT_LIB_LOGD("Added \"filter component input port added\" listener to graph: " @@ -905,29 +834,22 @@ bt_graph_add_filter_component_input_port_added_listener( return BT_FUNC_STATUS_OK; } +BT_EXPORT enum bt_graph_add_listener_status bt_graph_add_sink_component_input_port_added_listener( struct bt_graph *graph, bt_graph_sink_component_input_port_added_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) + void *data, bt_listener_id *out_listener_id) { struct bt_graph_listener_port_added listener = { - .base = { - .removed = listener_removed, - .data = data, - }, .func = (port_added_func_t) func, + .data = data, }; bt_listener_id listener_id; BT_ASSERT_PRE_NO_ERROR(); - 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); + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_LISTENER_FUNC_NON_NULL(func); g_array_append_val(graph->listeners.sink_input_port_added, listener); listener_id = graph->listeners.sink_input_port_added->len - 1; BT_LIB_LOGD("Added \"sink component input port added\" listener to graph: " @@ -941,155 +863,6 @@ bt_graph_add_sink_component_input_port_added_listener( return BT_FUNC_STATUS_OK; } -enum bt_graph_add_listener_status -bt_graph_add_source_filter_component_ports_connected_listener( - struct bt_graph *graph, - bt_graph_source_filter_component_ports_connected_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) -{ - struct bt_graph_listener_ports_connected listener = { - .base = { - .removed = listener_removed, - .data = data, - }, - .func = (ports_connected_func_t) func, - }; - bt_listener_id listener_id; - - BT_ASSERT_PRE_NO_ERROR(); - 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.source_filter_ports_connected, - listener); - listener_id = graph->listeners.source_filter_ports_connected->len - 1; - BT_LIB_LOGD("Added \"source 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_FUNC_STATUS_OK; -} - -enum bt_graph_add_listener_status -bt_graph_add_source_sink_component_ports_connected_listener( - struct bt_graph *graph, - bt_graph_source_sink_component_ports_connected_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) -{ - struct bt_graph_listener_ports_connected listener = { - .base = { - .removed = listener_removed, - .data = data, - }, - .func = (ports_connected_func_t) func, - }; - bt_listener_id listener_id; - - BT_ASSERT_PRE_NO_ERROR(); - 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.source_sink_ports_connected, - listener); - listener_id = graph->listeners.source_sink_ports_connected->len - 1; - BT_LIB_LOGD("Added \"source to sink 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_FUNC_STATUS_OK; -} - -enum bt_graph_add_listener_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, - bt_listener_id *out_listener_id) -{ - struct bt_graph_listener_ports_connected listener = { - .base = { - .removed = listener_removed, - .data = data, - }, - .func = (ports_connected_func_t) func, - }; - bt_listener_id listener_id; - - BT_ASSERT_PRE_NO_ERROR(); - 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_LOGD("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_FUNC_STATUS_OK; -} - -enum bt_graph_add_listener_status -bt_graph_add_filter_sink_component_ports_connected_listener( - struct bt_graph *graph, - bt_graph_filter_sink_component_ports_connected_listener_func func, - bt_graph_listener_removed_func listener_removed, void *data, - bt_listener_id *out_listener_id) -{ - struct bt_graph_listener_ports_connected listener = { - .base = { - .removed = listener_removed, - .data = data, - }, - .func = (ports_connected_func_t) func, - }; - bt_listener_id listener_id; - - BT_ASSERT_PRE_NO_ERROR(); - 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_sink_ports_connected, - listener); - listener_id = graph->listeners.filter_sink_ports_connected->len - 1; - BT_LIB_LOGD("Added \"filter to sink 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_FUNC_STATUS_OK; -} - -BT_HIDDEN enum bt_graph_listener_func_status bt_graph_notify_port_added( struct bt_graph *graph, struct bt_port *port) { @@ -1097,6 +870,7 @@ enum bt_graph_listener_func_status bt_graph_notify_port_added( GArray *listeners; struct bt_component *comp; enum bt_graph_listener_func_status status = BT_FUNC_STATUS_OK; + const char *func_name; BT_ASSERT(graph); BT_ASSERT(port); @@ -1111,6 +885,7 @@ enum bt_graph_listener_func_status bt_graph_notify_port_added( switch (port->type) { case BT_PORT_TYPE_OUTPUT: listeners = graph->listeners.source_output_port_added; + func_name = "bt_graph_source_component_output_port_added_listener_func"; break; default: bt_common_abort(); @@ -1123,9 +898,11 @@ enum bt_graph_listener_func_status bt_graph_notify_port_added( switch (port->type) { case BT_PORT_TYPE_INPUT: listeners = graph->listeners.filter_input_port_added; + func_name = "bt_graph_filter_component_input_port_added_listener_func"; break; case BT_PORT_TYPE_OUTPUT: listeners = graph->listeners.filter_output_port_added; + func_name = "bt_graph_filter_component_output_port_added_listener_func"; break; default: bt_common_abort(); @@ -1138,6 +915,7 @@ enum bt_graph_listener_func_status bt_graph_notify_port_added( switch (port->type) { case BT_PORT_TYPE_INPUT: listeners = graph->listeners.sink_input_port_added; + func_name = "bt_graph_sink_component_input_port_added_listener_func"; break; default: bt_common_abort(); @@ -1151,92 +929,13 @@ enum bt_graph_listener_func_status bt_graph_notify_port_added( for (i = 0; i < listeners->len; i++) { struct bt_graph_listener_port_added *listener = - &g_array_index(listeners, + &bt_g_array_index(listeners, struct bt_graph_listener_port_added, i); BT_ASSERT(listener->func); - status = listener->func(comp, port, listener->base.data); - BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(status); - if (status != BT_FUNC_STATUS_OK) { - goto end; - } - } - -end: - return status; -} - -BT_HIDDEN -enum bt_graph_listener_func_status bt_graph_notify_ports_connected( - struct bt_graph *graph, struct bt_port *upstream_port, - struct bt_port *downstream_port) -{ - uint64_t i; - GArray *listeners; - struct bt_component *upstream_comp; - struct bt_component *downstream_comp; - enum bt_graph_listener_func_status status = BT_FUNC_STATUS_OK; - - BT_ASSERT(graph); - BT_ASSERT(upstream_port); - BT_ASSERT(downstream_port); - BT_LIB_LOGD("Notifying graph listeners that ports were connected: " - "%![graph-]+g, %![up-port-]+p, %![down-port-]+p", - graph, upstream_port, downstream_port); - upstream_comp = bt_port_borrow_component_inline(upstream_port); - BT_ASSERT(upstream_comp); - downstream_comp = bt_port_borrow_component_inline(downstream_port); - BT_ASSERT(downstream_comp); - - switch (upstream_comp->class->type) { - case BT_COMPONENT_CLASS_TYPE_SOURCE: - { - switch (downstream_comp->class->type) { - case BT_COMPONENT_CLASS_TYPE_FILTER: - listeners = - graph->listeners.source_filter_ports_connected; - break; - case BT_COMPONENT_CLASS_TYPE_SINK: - listeners = - graph->listeners.source_sink_ports_connected; - break; - default: - bt_common_abort(); - } - - break; - } - 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; - break; - default: - bt_common_abort(); - } - - break; - } - default: - bt_common_abort(); - } - - for (i = 0; i < listeners->len; i++) { - struct bt_graph_listener_ports_connected *listener = - &g_array_index(listeners, - struct bt_graph_listener_ports_connected, i); - - BT_ASSERT(listener->func); - status = listener->func(upstream_comp, downstream_comp, - upstream_port, downstream_port, listener->base.data); - BT_ASSERT_POST_DEV_NO_ERROR_IF_NO_ERROR_STATUS(status); + status = listener->func(comp, port, listener->data); + BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(func_name, status); if (status != BT_FUNC_STATUS_OK) { goto end; } @@ -1246,7 +945,6 @@ end: return status; } -BT_HIDDEN void bt_graph_remove_connection(struct bt_graph *graph, struct bt_connection *connection) { @@ -1267,7 +965,7 @@ bool component_name_exists(struct bt_graph *graph, const char *name) struct bt_component *other_comp = graph->components->pdata[i]; if (strcmp(name, bt_component_get_name(other_comp)) == 0) { - BT_ASSERT_PRE_MSG("Another component with the same name already exists in the graph: " + BT_ASSERT_COND_MSG("Another component with the same name already exists in the graph: " "%![other-comp-]+c, name=\"%s\"", other_comp, name); exists = true; @@ -1286,7 +984,9 @@ int add_component_with_init_method_data( comp_init_method_t init_method, const char *name, const struct bt_value *params, void *init_method_data, bt_logging_level log_level, - const struct bt_component **user_component) + const struct bt_component **user_component, + const char *api_func, + const char *init_method_name) { int status = BT_FUNC_STATUS_OK; enum bt_component_class_initialize_method_status init_status; @@ -1296,15 +996,15 @@ int add_component_with_init_method_data( struct bt_value *new_params = NULL; BT_ASSERT(comp_cls); - BT_ASSERT_PRE_NON_NULL(graph, "Graph"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE( + BT_ASSERT_PRE_GRAPH_NON_NULL_FROM_FUNC(api_func, graph); + BT_ASSERT_PRE_NAME_NON_NULL_FROM_FUNC(api_func, name); + BT_ASSERT_PRE_FROM_FUNC(api_func, "graph-is-not-configured", graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING, "Graph is not in the \"configuring\" state: %!+g", graph); - BT_ASSERT_PRE(!component_name_exists(graph, name), + BT_ASSERT_PRE_FROM_FUNC(api_func, "component-name-is-unique", + !component_name_exists(graph, name), "Duplicate component name: %!+g, name=\"%s\"", graph, name); - BT_ASSERT_PRE(!params || bt_value_is_map(params), - "Parameter value is not a map value: %!+v", params); + BT_ASSERT_PRE_PARAM_VALUE_IS_MAP_FROM_FUNC(api_func, params); init_can_consume = graph->can_consume; bt_graph_set_can_consume(graph, false); BT_LIB_LOGI("Adding component to graph: " @@ -1353,7 +1053,8 @@ int add_component_with_init_method_data( init_status = init_method(component, NULL, params, init_method_data); BT_LOGD("User method returned: status=%s", bt_common_func_status_string(init_status)); - BT_ASSERT_POST_DEV_NO_ERROR_IF_NO_ERROR_STATUS(init_status); + BT_ASSERT_POST_DEV_NO_ERROR_IF_NO_ERROR_STATUS(init_method_name, + init_status); if (init_status != BT_FUNC_STATUS_OK) { if (init_status < 0) { BT_LIB_LOGW_APPEND_CAUSE( @@ -1402,7 +1103,6 @@ int add_component_with_init_method_data( if (user_component) { /* Move reference to user */ *user_component = component; - component = NULL; } end: @@ -1417,21 +1117,38 @@ end: return status; } +static enum bt_graph_add_component_status -bt_graph_add_source_component_with_initialize_method_data( +add_source_component_with_initialize_method_data( struct bt_graph *graph, const struct bt_component_class_source *comp_cls, const char *name, const struct bt_value *params, void *init_method_data, bt_logging_level log_level, - const struct bt_component_source **component) + const struct bt_component_source **component, + const char *api_func) { - BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class"); + BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func); + BT_ASSERT_PRE_COMP_CLS_NON_NULL_FROM_FUNC(api_func, comp_cls); return add_component_with_init_method_data(graph, (void *) comp_cls, (comp_init_method_t) comp_cls->methods.init, - name, params, init_method_data, log_level, (void *) component); + name, params, init_method_data, log_level, (void *) component, + api_func, "bt_component_class_source_initialize_method"); } +BT_EXPORT +enum bt_graph_add_component_status +bt_graph_add_source_component_with_initialize_method_data( + struct bt_graph *graph, + const struct bt_component_class_source *comp_cls, + const char *name, const struct bt_value *params, + void *init_method_data, bt_logging_level log_level, + const struct bt_component_source **component) +{ + return add_source_component_with_initialize_method_data(graph, comp_cls, + name, params, init_method_data, log_level, component, __func__); +} + +BT_EXPORT enum bt_graph_add_component_status bt_graph_add_source_component( struct bt_graph *graph, const struct bt_component_class_source *comp_cls, @@ -1439,26 +1156,42 @@ enum bt_graph_add_component_status bt_graph_add_source_component( enum bt_logging_level log_level, const struct bt_component_source **component) { - BT_ASSERT_PRE_NO_ERROR(); - return bt_graph_add_source_component_with_initialize_method_data( - graph, comp_cls, name, params, NULL, log_level, component); + return add_source_component_with_initialize_method_data(graph, comp_cls, + name, params, NULL, log_level, component, __func__); } +static enum bt_graph_add_component_status -bt_graph_add_filter_component_with_initialize_method_data( +add_filter_component_with_initialize_method_data( struct bt_graph *graph, const struct bt_component_class_filter *comp_cls, const char *name, const struct bt_value *params, - void *init_method_data, enum bt_logging_level log_level, - const struct bt_component_filter **component) + void *init_method_data, bt_logging_level log_level, + const struct bt_component_filter **component, + const char *api_func) { - BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class"); + BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func); + BT_ASSERT_PRE_COMP_CLS_NON_NULL_FROM_FUNC(api_func, comp_cls); return add_component_with_init_method_data(graph, (void *) comp_cls, (comp_init_method_t) comp_cls->methods.init, - name, params, init_method_data, log_level, (void *) component); + name, params, init_method_data, log_level, (void *) component, + api_func, "bt_component_class_filter_initialize_method"); } +BT_EXPORT +enum bt_graph_add_component_status +bt_graph_add_filter_component_with_initialize_method_data( + struct bt_graph *graph, + const struct bt_component_class_filter *comp_cls, + const char *name, const struct bt_value *params, + void *init_method_data, bt_logging_level log_level, + const struct bt_component_filter **component) +{ + return add_filter_component_with_initialize_method_data(graph, comp_cls, + name, params, init_method_data, log_level, component, __func__); +} + +BT_EXPORT enum bt_graph_add_component_status bt_graph_add_filter_component( struct bt_graph *graph, const struct bt_component_class_filter *comp_cls, @@ -1466,26 +1199,43 @@ enum bt_graph_add_component_status bt_graph_add_filter_component( enum bt_logging_level log_level, const struct bt_component_filter **component) { - BT_ASSERT_PRE_NO_ERROR(); - return bt_graph_add_filter_component_with_initialize_method_data( - graph, comp_cls, name, params, NULL, log_level, component); + return add_filter_component_with_initialize_method_data(graph, comp_cls, + name, params, NULL, log_level, component, __func__); +} + +static +enum bt_graph_add_component_status +add_sink_component_with_initialize_method_data( + struct bt_graph *graph, + const struct bt_component_class_sink *comp_cls, + const char *name, const struct bt_value *params, + void *init_method_data, bt_logging_level log_level, + const struct bt_component_sink **component, + const char *api_func) +{ + BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func); + BT_ASSERT_PRE_COMP_CLS_NON_NULL_FROM_FUNC(api_func, comp_cls); + return add_component_with_init_method_data(graph, + (void *) comp_cls, (comp_init_method_t) comp_cls->methods.init, + name, params, init_method_data, log_level, (void *) component, + api_func, "bt_component_class_sink_initialize_method"); } +BT_EXPORT enum bt_graph_add_component_status bt_graph_add_sink_component_with_initialize_method_data( struct bt_graph *graph, const struct bt_component_class_sink *comp_cls, const char *name, const struct bt_value *params, - void *init_method_data, enum bt_logging_level log_level, + void *init_method_data, bt_logging_level log_level, const struct bt_component_sink **component) { - BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class"); - return add_component_with_init_method_data(graph, - (void *) comp_cls, (comp_init_method_t) comp_cls->methods.init, - name, params, init_method_data, log_level, (void *) component); + return add_sink_component_with_initialize_method_data(graph, comp_cls, + name, params, init_method_data, log_level, component, + __func__); } +BT_EXPORT enum bt_graph_add_component_status bt_graph_add_sink_component( struct bt_graph *graph, const struct bt_component_class_sink *comp_cls, @@ -1493,11 +1243,11 @@ enum bt_graph_add_component_status bt_graph_add_sink_component( enum bt_logging_level log_level, const struct bt_component_sink **component) { - BT_ASSERT_PRE_NO_ERROR(); - return bt_graph_add_sink_component_with_initialize_method_data( - graph, comp_cls, name, params, NULL, log_level, component); + return add_sink_component_with_initialize_method_data(graph, comp_cls, + name, params, NULL, log_level, component, __func__); } +BT_EXPORT enum bt_graph_add_component_status bt_graph_add_simple_sink_component(struct bt_graph *graph, const char *name, bt_graph_simple_sink_component_initialize_func init_func, @@ -1518,9 +1268,10 @@ bt_graph_add_simple_sink_component(struct bt_graph *graph, const char *name, /* * Other preconditions are checked by - * bt_graph_add_sink_component_with_init_method_data(). + * add_sink_component_with_initialize_method_data(). */ - BT_ASSERT_PRE_NON_NULL(consume_func, "Consume function"); + BT_ASSERT_PRE_NON_NULL("consume-function", consume_func, + "Consume function"); comp_cls = bt_component_class_sink_simple_borrow(); if (!comp_cls) { @@ -1530,15 +1281,14 @@ bt_graph_add_simple_sink_component(struct bt_graph *graph, const char *name, goto end; } - status = bt_graph_add_sink_component_with_initialize_method_data(graph, + status = add_sink_component_with_initialize_method_data(graph, comp_cls, name, NULL, &init_method_data, - BT_LOGGING_LEVEL_NONE, component); + BT_LOGGING_LEVEL_NONE, component, __func__); end: return status; } -BT_HIDDEN void bt_graph_add_message(struct bt_graph *graph, struct bt_message *msg) { @@ -1556,19 +1306,19 @@ void bt_graph_add_message(struct bt_graph *graph, g_ptr_array_add(graph->messages, msg); } -BT_HIDDEN bool bt_graph_is_interrupted(const struct bt_graph *graph) { BT_ASSERT_DBG(graph); return bt_interrupter_array_any_is_set(graph->interrupters); } +BT_EXPORT enum bt_graph_add_interrupter_status bt_graph_add_interrupter( struct bt_graph *graph, const struct bt_interrupter *intr) { BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(graph, "Graph"); - BT_ASSERT_PRE_NON_NULL(intr, "Interrupter"); + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + BT_ASSERT_PRE_INTR_NON_NULL(intr); g_ptr_array_add(graph->interrupters, (void *) intr); bt_object_get_ref_no_null_check(intr); BT_LIB_LOGD("Added interrupter to graph: %![graph-]+g, %![intr-]+z", @@ -1576,18 +1326,20 @@ enum bt_graph_add_interrupter_status bt_graph_add_interrupter( return BT_FUNC_STATUS_OK; } -void bt_graph_interrupt(struct bt_graph *graph) +BT_EXPORT +struct bt_interrupter *bt_graph_borrow_default_interrupter(bt_graph *graph) { - BT_ASSERT_PRE_NON_NULL(graph, "Graph"); - bt_interrupter_set(graph->default_interrupter); - BT_LIB_LOGI("Interrupted graph: %!+g", graph); + BT_ASSERT_PRE_GRAPH_NON_NULL(graph); + return graph->default_interrupter; } +BT_EXPORT void bt_graph_get_ref(const struct bt_graph *graph) { bt_object_get_ref(graph); } +BT_EXPORT void bt_graph_put_ref(const struct bt_graph *graph) { bt_object_put_ref(graph);