X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Flib%2Fgraph%2Fgraph.c;h=c3980d6d398bdc919f0993f3c12cf944aab77677;hb=79545cc9503203b8508867244ef0265257fd3e84;hp=8416b1f6bbe1c6c06d788463d616fdbdd14e040b;hpb=2945edfe752782d2528af21bdbd3bbfef4cd51ca;p=babeltrace.git diff --git a/src/lib/graph/graph.c b/src/lib/graph/graph.c index 8416b1f6..c3980d6d 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 @@ -58,14 +38,9 @@ typedef enum bt_graph_listener_func_status 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; + void *data; }; #define INIT_LISTENERS_ARRAY(_type, _listeners) \ @@ -77,23 +52,6 @@ struct bt_graph_listener_port_added { } \ } 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) { @@ -129,16 +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); - if (graph->messages) { g_ptr_array_free(graph->messages, TRUE); graph->messages = NULL; @@ -465,7 +413,6 @@ enum bt_graph_connect_ports_status bt_graph_connect_ports( if (user_connection) { /* Move reference to user */ *user_connection = connection; - connection = NULL; } end: @@ -611,6 +558,77 @@ end: return status; } +static +int configure_graph(struct bt_graph *graph) +{ + 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(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(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(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; +} + enum bt_graph_run_once_status bt_graph_run_once(struct bt_graph *graph) { enum bt_graph_run_once_status status; @@ -623,9 +641,9 @@ enum bt_graph_run_once_status bt_graph_run_once(struct bt_graph *graph) 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); if (G_UNLIKELY(status)) { - /* bt_graph_configure() logs errors */ + /* configure_graph() logs errors */ goto end; } @@ -647,9 +665,9 @@ enum bt_graph_run_status bt_graph_run(struct bt_graph *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); + status = configure_graph(graph); if (G_UNLIKELY(status)) { - /* bt_graph_configure() logs errors */ + /* configure_graph() logs errors */ goto end; } @@ -710,25 +728,17 @@ 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); 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: " @@ -746,25 +756,17 @@ 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); 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: " @@ -782,25 +784,17 @@ 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); 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: " @@ -818,25 +812,17 @@ 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); 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: " @@ -917,7 +903,7 @@ enum bt_graph_listener_func_status bt_graph_notify_port_added( BT_ASSERT(listener->func); - status = listener->func(comp, port, listener->base.data); + status = listener->func(comp, port, listener->data); BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(status); if (status != BT_FUNC_STATUS_OK) { goto end; @@ -949,7 +935,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; @@ -1084,7 +1070,6 @@ int add_component_with_init_method_data( if (user_component) { /* Move reference to user */ *user_component = component; - component = NULL; } end: @@ -1258,11 +1243,10 @@ enum bt_graph_add_interrupter_status bt_graph_add_interrupter( return BT_FUNC_STATUS_OK; } -void bt_graph_interrupt(struct bt_graph *graph) +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); + return graph->default_interrupter; } void bt_graph_get_ref(const struct bt_graph *graph)