From 36712f1d9ad9269638e493ca36a50979fe4da989 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 7 Jun 2017 22:25:48 -0400 Subject: [PATCH] Add bt_graph_add_component(), make bt_component_create() internal MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit With this patch, you can only instantiate a component class through an existing graph. This can guarantee to the user (component class developer) that, when the component class's initialization method is called, the component always belongs to a graph. This simplifies things, now and in the future. For example, it is possible to cancel the graph during the execution of bt_graph_add_component() so that the user method knows if it should retry now or return an error when the graph is canceled. bt_graph_add_component() returns BT_GRAPH_STATUS_CANCELED if the graph is canceled. If the user's initialization method fails, its return component status is converted to the appropriate graph status. Another advantage of adding a component to a graph is that, if you add a "port added" graph listener, it is guaranteed that the listener is called even for the initial ports of a component. This was not possible before. This patch also makes a component's name mandatory, and bt_graph_add_component() ensures that there are components sharing the same name part of a given graph. This is a constraint similar to the fact that all the ports of a component must have a unique name. It should help to the implementation of a function to retrieve a component by name from a graph in the future. We do not check that a graph has or not "loose", disconnected components in bt_graph_consume(). This is not a change because any component can remove all its ports once connected once and become loose. A graph with floating/loose components is said to be disconnected in classical graph theory. This is not a problem for the moment, as the connected components can still interact. The disconnected components should probably be marked and then destroyed in bt_graph_consume() and/or in a dedicated garbage collecting function if needed (bt_graph_remove_disconnected_components() for example). This patch also makes successfully user-initialized components marked as such so that the user's finalization method is not called if its initialization method failed. In other words, the initialization method is responsible for any cleanup if it's about to fail. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- cli/babeltrace.c | 13 +- .../graph/component-filter-internal.h | 2 +- include/babeltrace/graph/component-internal.h | 7 + .../graph/component-sink-internal.h | 2 +- .../graph/component-source-internal.h | 2 +- include/babeltrace/graph/component.h | 16 -- include/babeltrace/graph/graph-internal.h | 2 - include/babeltrace/graph/graph.h | 15 +- include/babeltrace/object-internal.h | 2 +- lib/graph/component.c | 119 +++------- lib/graph/filter.c | 2 +- lib/graph/graph.c | 214 ++++++++++++++---- lib/graph/sink.c | 2 +- lib/graph/source.c | 2 +- tests/lib/test_bt_notification_iterator.c | 13 +- tests/lib/test_graph_topo.c | 106 +++++++-- tests/lib/test_plugin.c | 29 ++- tests/plugins/test-utils-muxer.c | 20 +- 18 files changed, 361 insertions(+), 207 deletions(-) diff --git a/cli/babeltrace.c b/cli/babeltrace.c index b68ddf15..4e35b8b6 100644 --- a/cli/babeltrace.c +++ b/cli/babeltrace.c @@ -1418,6 +1418,11 @@ void graph_port_added_listener(struct bt_port *port, void *data) "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"", comp, comp ? bt_component_get_name(comp) : "", port, bt_port_get_name(port)); + + if (!ctx->connect_ports) { + goto end; + } + if (!comp) { BT_LOGW_STR("Port has no component."); goto end; @@ -1598,9 +1603,9 @@ int cmd_run_ctx_create_components_from_config_components( goto error; } - comp = bt_component_create(comp_cls, - cfg_comp->instance_name->str, cfg_comp->params); - if (!comp) { + ret = bt_graph_add_component(ctx->graph, comp_cls, + cfg_comp->instance_name->str, cfg_comp->params, &comp); + if (ret) { BT_LOGE("Cannot create component: plugin-name=\"%s\", " "comp-cls-name=\"%s\", comp-cls-type=%d, " "comp-name=\"%s\"", @@ -1744,8 +1749,6 @@ const char *bt_graph_status_str(enum bt_graph_status status) return "BT_GRAPH_STATUS_END"; case BT_GRAPH_STATUS_OK: return "BT_GRAPH_STATUS_OK"; - case BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH: - return "BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH"; case BT_GRAPH_STATUS_INVALID: return "BT_GRAPH_STATUS_INVALID"; case BT_GRAPH_STATUS_NO_SINK: diff --git a/include/babeltrace/graph/component-filter-internal.h b/include/babeltrace/graph/component-filter-internal.h index 3bf79a18..38a1a240 100644 --- a/include/babeltrace/graph/component-filter-internal.h +++ b/include/babeltrace/graph/component-filter-internal.h @@ -46,7 +46,7 @@ struct bt_component_filter { */ BT_HIDDEN struct bt_component *bt_component_filter_create( - struct bt_component_class *class, struct bt_value *params); + struct bt_component_class *class); BT_HIDDEN void bt_component_filter_destroy(struct bt_component *component); diff --git a/include/babeltrace/graph/component-internal.h b/include/babeltrace/graph/component-internal.h index f78c468b..35a353a1 100644 --- a/include/babeltrace/graph/component-internal.h +++ b/include/babeltrace/graph/component-internal.h @@ -64,6 +64,8 @@ struct bt_component { /* Array of struct bt_component_destroy_listener */ GArray *destroy_listeners; + + bool initialized; }; static inline @@ -87,6 +89,11 @@ struct bt_graph *bt_component_borrow_graph(struct bt_component *comp) return (void *) comp->base.parent; } +BT_HIDDEN +enum bt_component_status bt_component_create( + struct bt_component_class *component_class, + const char *name, struct bt_component **component); + BT_HIDDEN enum bt_component_status bt_component_accept_port_connection( struct bt_component *component, struct bt_port *self_port, diff --git a/include/babeltrace/graph/component-sink-internal.h b/include/babeltrace/graph/component-sink-internal.h index cffb9a96..c1e7a454 100644 --- a/include/babeltrace/graph/component-sink-internal.h +++ b/include/babeltrace/graph/component-sink-internal.h @@ -49,7 +49,7 @@ struct bt_component_sink { */ BT_HIDDEN struct bt_component *bt_component_sink_create( - struct bt_component_class *class, struct bt_value *params); + struct bt_component_class *class); BT_HIDDEN void bt_component_sink_destroy(struct bt_component *component); diff --git a/include/babeltrace/graph/component-source-internal.h b/include/babeltrace/graph/component-source-internal.h index fde15845..98b523ce 100644 --- a/include/babeltrace/graph/component-source-internal.h +++ b/include/babeltrace/graph/component-source-internal.h @@ -46,7 +46,7 @@ struct bt_component_source { */ BT_HIDDEN struct bt_component *bt_component_source_create( - struct bt_component_class *class, struct bt_value *params); + struct bt_component_class *class); BT_HIDDEN void bt_component_source_destroy(struct bt_component *component); diff --git a/include/babeltrace/graph/component.h b/include/babeltrace/graph/component.h index 31fde560..e9ee5093 100644 --- a/include/babeltrace/graph/component.h +++ b/include/babeltrace/graph/component.h @@ -43,22 +43,6 @@ struct bt_component; struct bt_value; struct bt_port; -/** - * Create an instance of a component from a component class. - * - * @param component_class Component class of which to create an instance - * @param name Name of the new component instance, optional - * @param params A dictionary of component parameters - * @returns Returns a pointer to a new component instance - */ -extern struct bt_component *bt_component_create( - struct bt_component_class *component_class, const char *name, - struct bt_value *params); - -extern struct bt_component *bt_component_create_with_init_method_data( - struct bt_component_class *component_class, const char *name, - struct bt_value *params, void *init_method_data); - /** * Get component's name. * diff --git a/include/babeltrace/graph/graph-internal.h b/include/babeltrace/graph/graph-internal.h index f8f0d1a1..d4186425 100644 --- a/include/babeltrace/graph/graph-internal.h +++ b/include/babeltrace/graph/graph-internal.h @@ -101,8 +101,6 @@ const char *bt_graph_status_string(enum bt_graph_status status) return "BT_GRAPH_STATUS_END"; case BT_GRAPH_STATUS_OK: return "BT_GRAPH_STATUS_OK"; - case BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH: - return "BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH"; case BT_GRAPH_STATUS_INVALID: return "BT_GRAPH_STATUS_INVALID"; case BT_GRAPH_STATUS_NO_SINK: diff --git a/include/babeltrace/graph/graph.h b/include/babeltrace/graph/graph.h index a2dfbd82..a5077c49 100644 --- a/include/babeltrace/graph/graph.h +++ b/include/babeltrace/graph/graph.h @@ -46,8 +46,6 @@ enum bt_graph_status { /** Downstream component does not support multiple inputs. */ BT_GRAPH_STATUS_END = 1, BT_GRAPH_STATUS_OK = 0, - /** Component is already part of another graph. */ - BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH = -2, /** Invalid arguments. */ BT_GRAPH_STATUS_INVALID = -22, /** No sink in graph. */ @@ -71,6 +69,19 @@ typedef void (*bt_graph_ports_disconnected_listener)( extern struct bt_graph *bt_graph_create(void); +extern enum bt_graph_status bt_graph_add_component( + struct bt_graph *graph, + struct bt_component_class *component_class, + const char *name, struct bt_value *params, + struct bt_component **component); + +extern enum bt_graph_status bt_graph_add_component_with_init_method_data( + struct bt_graph *graph, + struct bt_component_class *component_class, + const char *name, struct bt_value *params, + void *init_method_data, + struct bt_component **component); + /** * Creates a connection between two components using the two ports specified * and adds the connection and components (if not already added) to the graph. diff --git a/include/babeltrace/object-internal.h b/include/babeltrace/object-internal.h index 2b368c55..9859e329 100644 --- a/include/babeltrace/object-internal.h +++ b/include/babeltrace/object-internal.h @@ -64,7 +64,7 @@ void bt_object_release(void *ptr) obj->ref_count.count); #endif - if (obj && obj->release && !bt_object_get_ref_count(obj)) { + if (obj && obj->release && bt_object_get_ref_count(obj) == 0) { obj->release(obj); } } diff --git a/lib/graph/component.c b/lib/graph/component.c index 8664e3b4..ee8e9453 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -52,7 +52,7 @@ static struct bt_component * (* const component_create_funcs[])( - struct bt_component_class *, struct bt_value *) = { + 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, @@ -105,10 +105,11 @@ void bt_component_destroy(struct bt_object *obj) component_class = component->class; /* - * User data is destroyed first, followed by the concrete component - * instance. + * User data is destroyed first, followed by the concrete + * component instance. Do not finalize if the component's user + * initialization method failed in the first place. */ - if (component->class->methods.finalize) { + if (component->initialized && component->class->methods.finalize) { BT_LOGD_STR("Calling user's finalization method."); component->class->methods.finalize( bt_private_component_from_component(component)); @@ -240,57 +241,26 @@ int64_t bt_component_get_output_port_count(struct bt_component *comp) return (int64_t) comp->output_ports->len; } -struct bt_component *bt_component_create_with_init_method_data( - struct bt_component_class *component_class, const char *name, - struct bt_value *params, void *init_method_data) +enum bt_component_status bt_component_create( + struct bt_component_class *component_class, + const char *name, struct bt_component **user_component) { - int ret; + enum bt_component_status status = BT_COMPONENT_STATUS_OK; struct bt_component *component = NULL; enum bt_component_class_type type; - bt_get(params); - - if (!component_class) { - BT_LOGW_STR("Invalid parameter: component class is NULL."); - goto end; - } + assert(user_component); + assert(component_class); + assert(name); type = bt_component_class_get_type(component_class); - if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN || - type > BT_COMPONENT_CLASS_TYPE_FILTER) { - BT_LOGW("Invalid parameter: unknown component class type: " - "type=%s", bt_component_class_type_string(type)); - goto end; - } - - BT_LOGD("Creating component from component class: " - "comp-cls-addr=%p, comp-cls-type=%s, name=\"%s\", " - "params-addr=%p, init-method-data-addr=%p", - component_class, bt_component_class_type_string(type), - name, params, init_method_data); - - /* - * Parameters must be a map value, but we create a convenient - * empty one if it's NULL. - */ - if (params) { - if (!bt_value_is_map(params)) { - BT_LOGW("Invalid parameter: initialization parameters must be a map value: " - "type=%s", - bt_value_type_string(bt_value_get_type(params))); - goto end; - } - } else { - params = bt_value_map_create(); - if (!params) { - BT_LOGE_STR("Cannot create map value object."); - goto end; - } - } - - component = component_create_funcs[type](component_class, params); + BT_LOGD("Creating empty component from component class: " + "comp-cls-addr=%p, comp-cls-type=%s, name=\"%s\"", + component_class, bt_component_class_type_string(type), name); + component = component_create_funcs[type](component_class); if (!component) { BT_LOGE_STR("Cannot create specific component object."); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } @@ -300,7 +270,7 @@ struct bt_component *bt_component_create_with_init_method_data( component->name = g_string_new(name); if (!component->name) { BT_LOGE_STR("Failed to allocate one GString."); - BT_PUT(component); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } @@ -308,7 +278,7 @@ struct bt_component *bt_component_create_with_init_method_data( bt_object_release); if (!component->input_ports) { BT_LOGE_STR("Failed to allocate one GPtrArray."); - BT_PUT(component); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } @@ -316,7 +286,7 @@ struct bt_component *bt_component_create_with_init_method_data( bt_object_release); if (!component->output_ports) { BT_LOGE_STR("Failed to allocate one GPtrArray."); - BT_PUT(component); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } @@ -324,44 +294,19 @@ struct bt_component *bt_component_create_with_init_method_data( sizeof(struct bt_component_destroy_listener)); if (!component->destroy_listeners) { BT_LOGE_STR("Failed to allocate one GArray."); - BT_PUT(component); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } - if (component_class->methods.init) { - BT_LOGD_STR("Calling user's initialization method."); - ret = component_class->methods.init( - bt_private_component_from_component(component), params, - init_method_data); - BT_LOGD("User method returned: status=%s", - bt_component_status_string(ret)); - if (ret != BT_COMPONENT_STATUS_OK) { - BT_LOGW_STR("Initialization method failed."); - BT_PUT(component); - goto end; - } - } - - BT_LOGD_STR("Freezing component class."); - bt_component_class_freeze(component->class); - BT_LOGD("Created component from component class: " - "comp-cls-addr=%p, comp-cls-type=%s, name=\"%s\", " - "params-addr=%p, init-method-data-addr=%p, comp-addr=%p", - component_class, bt_component_class_type_string(type), - name, params, init_method_data, component); + BT_LOGD("Created empty component from component class: " + "comp-cls-addr=%p, comp-cls-type=%s, name=\"%s\", comp-addr=%p", + component_class, bt_component_class_type_string(type), name, + component); + BT_MOVE(*user_component, component); end: - bt_put(params); - return component; -} - -struct bt_component *bt_component_create( - struct bt_component_class *component_class, const char *name, - struct bt_value *params) -{ - /* bt_component_create_with_init_method_data() logs details */ - return bt_component_create_with_init_method_data(component_class, name, - params, NULL); + bt_put(component); + return status; } const char *bt_component_get_name(struct bt_component *component) @@ -421,13 +366,7 @@ BT_HIDDEN void bt_component_set_graph(struct bt_component *component, struct bt_graph *graph) { - struct bt_object *parent = bt_object_get_parent(&component->base); - - assert(!parent || parent == &graph->base); - if (!parent) { - bt_object_set_parent(component, &graph->base); - } - bt_put(parent); + bt_object_set_parent(component, graph ? &graph->base : NULL); } struct bt_graph *bt_component_get_graph( diff --git a/lib/graph/filter.c b/lib/graph/filter.c index 78913517..67beb4cd 100644 --- a/lib/graph/filter.c +++ b/lib/graph/filter.c @@ -45,7 +45,7 @@ void bt_component_filter_destroy(struct bt_component *component) BT_HIDDEN struct bt_component *bt_component_filter_create( - struct bt_component_class *class, struct bt_value *params) + struct bt_component_class *class) { struct bt_component_filter *filter = NULL; diff --git a/lib/graph/graph.c b/lib/graph/graph.c index 5b5acae7..e7f8db3f 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -208,8 +210,6 @@ enum bt_graph_status bt_graph_connect_ports(struct bt_graph *graph, struct bt_component *upstream_component = NULL; struct bt_component *downstream_component = NULL; enum bt_component_status component_status; - bt_bool upstream_was_already_in_graph; - bt_bool downstream_was_already_in_graph; if (!graph) { BT_LOGW_STR("Invalid parameter: graph is NULL."); @@ -291,24 +291,6 @@ enum bt_graph_status bt_graph_connect_ports(struct bt_graph *graph, upstream_component, bt_component_get_name(upstream_component), downstream_component, bt_component_get_name(downstream_component)); - /* Ensure the components are not already part of another graph. */ - upstream_graph = bt_component_get_graph(upstream_component); - if (upstream_graph && (graph != upstream_graph)) { - BT_LOGW("Invalid parameter: upstream port's component is already part of another graph: " - "other-graph-addr=%p", upstream_graph); - status = BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH; - goto end; - } - upstream_was_already_in_graph = (graph == upstream_graph); - downstream_graph = bt_component_get_graph(downstream_component); - if (downstream_graph && (graph != downstream_graph)) { - BT_LOGW("Invalid parameter: downstream port's component is already part of another graph: " - "other-graph-addr=%p", downstream_graph); - status = BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH; - goto end; - } - downstream_was_already_in_graph = (graph == downstream_graph); - /* * At this point the ports are not connected yet. Both * components need to accept an eventual connection to their @@ -363,26 +345,6 @@ enum bt_graph_status bt_graph_connect_ports(struct bt_graph *graph, */ g_ptr_array_add(graph->connections, connection); - if (!upstream_was_already_in_graph) { - g_ptr_array_add(graph->components, upstream_component); - bt_component_set_graph(upstream_component, graph); - } - if (!downstream_was_already_in_graph) { - g_ptr_array_add(graph->components, downstream_component); - bt_component_set_graph(downstream_component, graph); - if (bt_component_get_class_type(downstream_component) == - BT_COMPONENT_CLASS_TYPE_SINK) { - g_queue_push_tail(graph->sinks_to_consume, - downstream_component); - } - } - - /* - * The graph is now the parent of these components which - * garantees their existence for the duration of the graph's - * lifetime. - */ - /* * Notify both components that their port is connected. */ @@ -811,3 +773,175 @@ void bt_graph_remove_connection(struct bt_graph *graph, graph, connection); g_ptr_array_remove(graph->connections, connection); } + +enum bt_graph_status bt_graph_add_component_with_init_method_data( + struct bt_graph *graph, + struct bt_component_class *component_class, + const char *name, struct bt_value *params, + void *init_method_data, + struct bt_component **user_component) +{ + enum bt_graph_status graph_status = BT_GRAPH_STATUS_OK; + enum bt_component_status comp_status; + struct bt_component *component = NULL; + enum bt_component_class_type type; + size_t i; + + bt_get(params); + + if (!graph) { + BT_LOGW_STR("Invalid parameter: graph is NULL."); + graph_status = BT_GRAPH_STATUS_INVALID; + goto end; + } + + if (!component_class) { + BT_LOGW_STR("Invalid parameter: component class is NULL."); + graph_status = BT_GRAPH_STATUS_INVALID; + goto end; + } + + type = bt_component_class_get_type(component_class); + BT_LOGD("Adding component to graph: " + "graph-addr=%p, comp-cls-addr=%p, " + "comp-cls-type=%s, name=\"%s\", params-addr=%p, " + "init-method-data-addr=%p", + graph, component_class, bt_component_class_type_string(type), + name, params, init_method_data); + + if (!name) { + BT_LOGW_STR("Invalid parameter: name is NULL."); + graph_status = BT_GRAPH_STATUS_INVALID; + goto end; + } + + if (graph->canceled) { + BT_LOGW_STR("Invalid parameter: graph is canceled."); + graph_status = BT_GRAPH_STATUS_CANCELED; + goto end; + } + + if (type != BT_COMPONENT_CLASS_TYPE_SOURCE && + type != BT_COMPONENT_CLASS_TYPE_FILTER && + type != BT_COMPONENT_CLASS_TYPE_SINK) { + BT_LOGW("Invalid parameter: unknown component class type: " + "type=%d", type); + graph_status = BT_GRAPH_STATUS_INVALID; + goto end; + } + + for (i = 0; i < graph->components->len; i++) { + void *other_comp = graph->components->pdata[i]; + + if (strcmp(name, bt_component_get_name(other_comp)) == 0) { + BT_LOGW("Invalid parameter: another component with the same name already exists in the graph: " + "other-comp-addr=%p, name=\"%s\"", + other_comp, name); + graph_status = BT_GRAPH_STATUS_INVALID; + goto end; + } + } + + /* + * Parameters must be a map value, but we create a convenient + * empty one if it's NULL. + */ + if (params) { + if (!bt_value_is_map(params)) { + BT_LOGW("Invalid parameter: initialization parameters must be a map value: " + "type=%s", + bt_value_type_string(bt_value_get_type(params))); + graph_status = BT_GRAPH_STATUS_INVALID; + goto end; + } + } else { + params = bt_value_map_create(); + if (!params) { + BT_LOGE_STR("Cannot create map value object."); + graph_status = BT_GRAPH_STATUS_NOMEM; + goto end; + } + } + + comp_status = bt_component_create(component_class, name, &component); + if (comp_status != BT_COMPONENT_STATUS_OK) { + BT_LOGE("Cannot create empty component object: status=%s", + bt_component_status_string(comp_status)); + graph_status = bt_graph_status_from_component_status( + comp_status); + goto end; + } + + /* + * The user's initialization method needs to see that this + * component is part of the graph. If the user method fails, we + * immediately remove the component from the graph's components. + */ + g_ptr_array_add(graph->components, component); + bt_component_set_graph(component, graph); + + if (component_class->methods.init) { + BT_LOGD_STR("Calling user's initialization method."); + comp_status = component_class->methods.init( + bt_private_component_from_component(component), params, + init_method_data); + BT_LOGD("User method returned: status=%s", + bt_component_status_string(comp_status)); + if (comp_status != BT_COMPONENT_STATUS_OK) { + BT_LOGW_STR("Initialization method failed."); + graph_status = bt_graph_status_from_component_status( + comp_status); + bt_component_set_graph(component, NULL); + g_ptr_array_remove_fast(graph->components, component); + goto end; + } + } + + /* + * Mark the component as initialized so that its finalization + * method is called when it is destroyed. + */ + component->initialized = true; + + /* + * If it's a sink component, it needs to be part of the graph's + * sink queue to be consumed by bt_graph_consume(). + */ + if (bt_component_is_sink(component)) { + g_queue_push_tail(graph->sinks_to_consume, component); + } + + /* + * Freeze the component class now that it's instantiated at + * least once. + */ + BT_LOGD_STR("Freezing component class."); + bt_component_class_freeze(component->class); + BT_LOGD("Added component to graph: " + "graph-addr=%p, comp-cls-addr=%p, " + "comp-cls-type=%s, name=\"%s\", params-addr=%p, " + "init-method-data-addr=%p, comp-addr=%p", + graph, component_class, bt_component_class_type_string(type), + name, params, init_method_data, component); + + if (user_component) { + /* Move reference to user */ + *user_component = component; + component = NULL; + } + +end: + bt_put(component); + bt_put(params); + return graph_status; +} + +enum bt_graph_status bt_graph_add_component( + struct bt_graph *graph, + struct bt_component_class *component_class, + const char *name, struct bt_value *params, + struct bt_component **component) +{ + return bt_graph_add_component_with_init_method_data(graph, + component_class, name, params, NULL, component); +} diff --git a/lib/graph/sink.c b/lib/graph/sink.c index 9462765f..455ed4ef 100644 --- a/lib/graph/sink.c +++ b/lib/graph/sink.c @@ -43,7 +43,7 @@ void bt_component_sink_destroy(struct bt_component *component) BT_HIDDEN struct bt_component *bt_component_sink_create( - struct bt_component_class *class, struct bt_value *params) + struct bt_component_class *class) { struct bt_component_sink *sink = NULL; diff --git a/lib/graph/source.c b/lib/graph/source.c index 758a1b52..b1a12a5d 100644 --- a/lib/graph/source.c +++ b/lib/graph/source.c @@ -45,7 +45,7 @@ void bt_component_source_destroy(struct bt_component *component) BT_HIDDEN struct bt_component *bt_component_source_create( - struct bt_component_class *class, struct bt_value *params) + struct bt_component_class *class) { struct bt_component_source *source = NULL; diff --git a/tests/lib/test_bt_notification_iterator.c b/tests/lib/test_bt_notification_iterator.c index cbce6b4c..d6ca1973 100644 --- a/tests/lib/test_bt_notification_iterator.c +++ b/tests/lib/test_bt_notification_iterator.c @@ -866,7 +866,7 @@ void sink_finalize(struct bt_private_component *private_component) } static -void create_source_sink(struct bt_component **source, +void create_source_sink(struct bt_graph *graph, struct bt_component **source, struct bt_component **sink) { struct bt_component_class *src_comp_class; @@ -887,8 +887,9 @@ void create_source_sink(struct bt_component **source, ret = bt_component_class_source_set_notification_iterator_finalize_method( src_comp_class, src_iter_finalize); assert(ret == 0); - *source = bt_component_create(src_comp_class, "source", NULL); - assert(*source); + ret = bt_graph_add_component(graph, src_comp_class, "source", NULL, + source); + assert(ret == 0); /* Create sink component */ sink_comp_class = bt_component_class_sink_create("sink", sink_consume); @@ -900,7 +901,9 @@ void create_source_sink(struct bt_component **source, ret = bt_component_class_set_port_connected_method(sink_comp_class, sink_port_connected); assert(ret == 0); - *sink = bt_component_create(sink_comp_class, "sink", NULL); + ret = bt_graph_add_component(graph, sink_comp_class, "sink", NULL, + sink); + assert(ret == 0); bt_put(src_comp_class); bt_put(sink_comp_class); @@ -920,9 +923,9 @@ void do_std_test(enum test test, const char *name, clear_test_events(); current_test = test; diag("test: %s", name); - create_source_sink(&src_comp, &sink_comp); graph = bt_graph_create(); assert(graph); + create_source_sink(graph, &src_comp, &sink_comp); /* Connect source to sink */ upstream_port = bt_component_source_get_output_port_by_name(src_comp, "out"); diff --git a/tests/lib/test_graph_topo.c b/tests/lib/test_graph_topo.c index 058393a2..2efac144 100644 --- a/tests/lib/test_graph_topo.c +++ b/tests/lib/test_graph_topo.c @@ -39,7 +39,7 @@ #include "tap/tap.h" -#define NR_TESTS 69 +#define NR_TESTS 77 enum event_type { COMP_ACCEPT_PORT_CONNECTION, @@ -588,22 +588,26 @@ void fini_test(void) } static -struct bt_component *create_src(void) +struct bt_component *create_src(struct bt_graph *graph) { - struct bt_component *comp = - bt_component_create(src_comp_class, "src-comp", NULL); + struct bt_component *comp; + int ret; - assert(comp); + ret = bt_graph_add_component(graph, src_comp_class, "src-comp", NULL, + &comp); + assert(ret == 0); return comp; } static -struct bt_component *create_sink(void) +struct bt_component *create_sink(struct bt_graph *graph) { - struct bt_component *comp = - bt_component_create(sink_comp_class, "sink-comp", NULL); + struct bt_component *comp; + int ret; - assert(comp); + ret = bt_graph_add_component(graph, sink_comp_class, "sink-comp", + NULL, &comp); + assert(ret == 0); return comp; } @@ -661,9 +665,10 @@ void test_sink_removes_port_in_port_connected_then_src_removes_disconnected_port prepare_test(TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT, "sink removes port in consume, then source removes disconnected port"); - src = create_src(); - sink = create_sink(); graph = create_graph(); + assert(graph); + src = create_src(graph); + sink = create_sink(graph); src_def_port = bt_component_source_get_output_port_by_name(src, "out"); assert(src_def_port); sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in"); @@ -673,8 +678,20 @@ void test_sink_removes_port_in_port_connected_then_src_removes_disconnected_port assert(status == 0); assert(conn); - /* We're supposed to have 5 events so far */ - ok(events->len == 5, "we have the expected number of events (before consume)"); + /* We're supposed to have 7 events so far */ + ok(events->len == 7, "we have the expected number of events (before consume)"); + + /* 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; @@ -825,9 +842,10 @@ void test_sink_removes_port_in_port_connected(void) prepare_test(TEST_SINK_REMOVES_PORT_IN_CONSUME, "sink removes port in consume"); - src = create_src(); - sink = create_sink(); graph = create_graph(); + assert(graph); + src = create_src(graph); + sink = create_sink(graph); src_def_port = bt_component_source_get_output_port_by_name(src, "out"); assert(src_def_port); sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in"); @@ -836,8 +854,20 @@ void test_sink_removes_port_in_port_connected(void) &conn); assert(status == 0); - /* We're supposed to have 5 events so far */ - ok(events->len == 5, "we have the expected number of events (before consume)"); + /* We're supposed to have 7 events so far */ + ok(events->len == 7, "we have the expected number of events (before consume)"); + + /* 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; @@ -970,9 +1000,10 @@ void test_src_adds_port_in_port_connected(void) prepare_test(TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED, "source adds port in port connected"); - src = create_src(); - sink = create_sink(); graph = create_graph(); + assert(graph); + src = create_src(graph); + sink = create_sink(graph); src_def_port = bt_component_source_get_output_port_by_name(src, "out"); assert(src_def_port); sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in"); @@ -984,8 +1015,20 @@ void test_src_adds_port_in_port_connected(void) "hello"); assert(src_hello_port); - /* We're supposed to have 6 events */ - ok(events->len == 6, "we have the expected number of events"); + /* We're supposed to have 8 events */ + ok(events->len == 8, "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; @@ -1077,9 +1120,10 @@ void test_simple(void) size_t graph_ports_connected_pos; prepare_test(TEST_SIMPLE, "simple"); - src = create_src(); - sink = create_sink(); graph = create_graph(); + assert(graph); + src = create_src(graph); + sink = create_sink(graph); src_def_port = bt_component_source_get_output_port_by_name(src, "out"); assert(src_def_port); sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in"); @@ -1088,8 +1132,20 @@ void test_simple(void) &conn); assert(status == 0); - /* We're supposed to have 5 events */ - ok(events->len == 5, "we have the expected number of events"); + /* We're supposed to have 7 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; diff --git a/tests/lib/test_plugin.c b/tests/lib/test_plugin.c index d4390dcb..cec0933e 100644 --- a/tests/lib/test_plugin.c +++ b/tests/lib/test_plugin.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -148,6 +149,7 @@ static void test_sfs(const char *plugin_dir) struct bt_value *results; struct bt_value *object; struct bt_value *res_params; + struct bt_graph *graph; const char *object_str; int ret; @@ -218,20 +220,35 @@ static void test_sfs(const char *plugin_dir) diag("> putting the plugin object here"); BT_PUT(plugin); - sink_component = bt_component_create(sink_comp_class, NULL, NULL); - ok(sink_component, "bt_component_create() still works after the plugin object is destroyed"); + graph = bt_graph_create(); + assert(graph); + ret = bt_graph_add_component(graph, sink_comp_class, "the-sink", NULL, + &sink_component); + ok(ret == 0 && sink_component, + "bt_graph_add_component() still works after the plugin object is destroyed"); BT_PUT(sink_component); BT_PUT(source_comp_class); - sink_component = bt_component_create(sink_comp_class, NULL, NULL); - ok(sink_component, "bt_component_create() still works after the source component class object is destroyed"); + bt_put(graph); + graph = bt_graph_create(); + assert(graph); + ret = bt_graph_add_component(graph, sink_comp_class, "the-sink", NULL, + &sink_component); + ok(ret == 0 && sink_component, + "bt_graph_add_component() still works after the source component class object is destroyed"); BT_PUT(sink_component); BT_PUT(filter_comp_class); - sink_component = bt_component_create(sink_comp_class, NULL, NULL); - ok(sink_component, "bt_component_create() still works after the filter component class object is destroyed"); + bt_put(graph); + graph = bt_graph_create(); + assert(graph); + ret = bt_graph_add_component(graph, sink_comp_class, "the-sink", NULL, + &sink_component); + ok(ret == 0 && sink_component, + "bt_graph_add_component() still works after the filter component class object is destroyed"); BT_PUT(sink_comp_class); BT_PUT(sink_component); free(sfs_path); + bt_put(graph); bt_put(plugin_set); bt_put(object); bt_put(res_params); diff --git a/tests/plugins/test-utils-muxer.c b/tests/plugins/test-utils-muxer.c index 6600a72e..76edfd76 100644 --- a/tests/plugins/test-utils-muxer.c +++ b/tests/plugins/test-utils-muxer.c @@ -912,7 +912,8 @@ void sink_finalize(struct bt_private_component *private_component) } static -void create_source_muxer_sink(struct bt_component **source, +void create_source_muxer_sink(struct bt_graph *graph, + struct bt_component **source, struct bt_component **muxer, struct bt_component **sink) { @@ -935,15 +936,15 @@ void create_source_muxer_sink(struct bt_component **source, ret = bt_component_class_source_set_notification_iterator_finalize_method( src_comp_class, src_iter_finalize); assert(ret == 0); - *source = bt_component_create(src_comp_class, "source", NULL); - assert(*source); + ret = bt_graph_add_component(graph, src_comp_class, "source", NULL, source); + assert(ret == 0); /* Create muxer component */ muxer_comp_class = bt_plugin_find_component_class("utils", "muxer", BT_COMPONENT_CLASS_TYPE_FILTER); assert(muxer_comp_class); - *muxer = bt_component_create(muxer_comp_class, "muxer", NULL); - assert(*muxer); + ret = bt_graph_add_component(graph, muxer_comp_class, "muxer", NULL, muxer); + assert(ret == 0); /* Create sink component */ sink_comp_class = bt_component_class_sink_create("sink", sink_consume); @@ -955,7 +956,8 @@ void create_source_muxer_sink(struct bt_component **source, ret = bt_component_class_set_port_connected_method(sink_comp_class, sink_port_connected); assert(ret == 0); - *sink = bt_component_create(sink_comp_class, "sink", NULL); + ret = bt_graph_add_component(graph, sink_comp_class, "sink", NULL, sink); + assert(ret == 0); bt_put(src_comp_class); bt_put(muxer_comp_class); @@ -980,9 +982,9 @@ void do_std_test(enum test test, const char *name, clear_test_events(); current_test = test; diag("test: %s", name); - create_source_muxer_sink(&src_comp, &muxer_comp, &sink_comp); graph = bt_graph_create(); assert(graph); + create_source_muxer_sink(graph, &src_comp, &muxer_comp, &sink_comp); /* Connect source output ports to muxer input ports */ if (with_upstream) { @@ -1454,9 +1456,9 @@ void test_single_end_then_multiple_full(void) clear_test_events(); current_test = TEST_SINGLE_END_THEN_MULTIPLE_FULL; diag("test: single end then multiple full"); - create_source_muxer_sink(&src_comp, &muxer_comp, &sink_comp); graph = bt_graph_create(); assert(graph); + create_source_muxer_sink(graph, &src_comp, &muxer_comp, &sink_comp); graph_listener_data.graph = graph; graph_listener_data.source = src_comp; graph_listener_data.muxer = muxer_comp; @@ -1582,9 +1584,9 @@ void test_single_again_end_then_multiple_full(void) clear_test_events(); current_test = TEST_SINGLE_AGAIN_END_THEN_MULTIPLE_FULL; diag("test: single again then end then multiple full"); - create_source_muxer_sink(&src_comp, &muxer_comp, &sink_comp); graph = bt_graph_create(); assert(graph); + create_source_muxer_sink(graph, &src_comp, &muxer_comp, &sink_comp); graph_listener_data.graph = graph; graph_listener_data.source = src_comp; graph_listener_data.muxer = muxer_comp; -- 2.34.1