X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fgraph%2Fcomponent.c;h=6494f64883128ccb3ce0d81c5e1ac7ab305ed3bc;hb=68b66a256a54d32992dfefeaad11eea88b7df234;hp=2d3460a0f44fee820fb92ae7cf50a073423db27a;hpb=0d72b8c329ad51d14ab4e83330b38c2c8da69dd4;p=babeltrace.git diff --git a/lib/graph/component.c b/lib/graph/component.c index 2d3460a0..6494f648 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -1,8 +1,7 @@ /* + * Copyright 2017-2018 Philippe Proulx * Copyright 2015 Jérémie Galarneau * - * Author: 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 @@ -23,30 +22,29 @@ */ #define BT_LOG_TAG "COMP" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -192,12 +190,14 @@ enum bt_component_class_type bt_component_get_class_type( } static -struct bt_port *add_port( +enum bt_self_component_status add_port( struct bt_component *component, GPtrArray *ports, - enum bt_port_type port_type, const char *name, void *user_data) + enum bt_port_type port_type, const char *name, void *user_data, + struct bt_port **port) { struct bt_port *new_port = NULL; struct bt_graph *graph = NULL; + enum bt_self_component_status status; BT_ASSERT_PRE_NON_NULL(component, "Component"); BT_ASSERT_PRE_NON_NULL(name, "Name"); @@ -206,6 +206,10 @@ struct bt_port *add_port( BT_ASSERT_PRE(graph && !bt_graph_is_canceled(graph), "Component's graph is canceled: %![comp-]+c, %![graph-]+g", component, graph); + BT_ASSERT_PRE( + graph->config_state == BT_GRAPH_CONFIGURATION_STATE_CONFIGURING, + "Component's graph is already configured: " + "%![comp-]+c, %![graph-]+g", component, graph); // TODO: Validate that the name is not already used. @@ -216,7 +220,8 @@ struct bt_port *add_port( new_port = bt_port_create(component, port_type, name, user_data); if (!new_port) { BT_LOGE_STR("Cannot create port object."); - goto end; + status = BT_SELF_COMPONENT_STATUS_NOMEM; + goto error; } /* @@ -230,18 +235,34 @@ struct bt_port *add_port( /* * Notify the graph's creator that a new port was added. */ - bt_object_get_ref(bt_component_borrow_graph(component)); graph = bt_component_borrow_graph(component); if (graph) { - bt_graph_notify_port_added(graph, new_port); - BT_OBJECT_PUT_REF_AND_RESET(graph); + enum bt_graph_listener_status listener_status; + + listener_status = bt_graph_notify_port_added(graph, new_port); + if (listener_status != BT_GRAPH_LISTENER_STATUS_OK) { + bt_graph_make_faulty(graph); + status = listener_status; + goto error; + } } BT_LIB_LOGD("Created and added port to component: " "%![comp-]+c, %![port-]+p", component, new_port); + *port = new_port; + status = BT_SELF_COMPONENT_STATUS_OK; + + goto end; +error: + /* + * We need to release the reference that we would otherwise have + * returned to the caller. + */ + BT_PORT_PUT_REF_AND_RESET(new_port); + end: - return new_port; + return status; } BT_HIDDEN @@ -269,7 +290,6 @@ int bt_component_create(struct bt_component_class *component_class, BT_ASSERT(user_component); BT_ASSERT(component_class); BT_ASSERT(name); - type = bt_component_class_get_type(component_class); BT_LIB_LOGD("Creating empty component from component class: %![cc-]+C, " "comp-name=\"%s\"", component_class, name); @@ -280,8 +300,7 @@ int bt_component_create(struct bt_component_class *component_class, goto end; } - bt_object_init_shared_with_parent(&component->base, - destroy_component); + bt_object_init_shared_with_parent(&component->base, destroy_component); component->class = component_class; bt_object_get_no_null_check(component->class); component->destroy = component_destroy_funcs[type]; @@ -331,7 +350,7 @@ const char *bt_component_get_name(const struct bt_component *component) return component->name->str; } -struct bt_component_class *bt_component_borrow_class( +const struct bt_component_class *bt_component_borrow_class_const( const struct bt_component *component) { BT_ASSERT_PRE_NON_NULL(component, "Component"); @@ -436,130 +455,23 @@ struct bt_port_output *bt_component_borrow_output_port_by_index( } BT_HIDDEN -struct bt_port_input *bt_component_add_input_port( +enum bt_self_component_status bt_component_add_input_port( struct bt_component *component, const char *name, - void *user_data) + void *user_data, struct bt_port **port) { /* add_port() logs details */ - return (void *) - add_port(component, component->input_ports, - BT_PORT_TYPE_INPUT, name, user_data); + return add_port(component, component->input_ports, + BT_PORT_TYPE_INPUT, name, user_data, port); } BT_HIDDEN -struct bt_port_output *bt_component_add_output_port( +enum bt_self_component_status bt_component_add_output_port( struct bt_component *component, const char *name, - void *user_data) + void *user_data, struct bt_port **port) { /* add_port() logs details */ - return (void *) - add_port(component, component->output_ports, - BT_PORT_TYPE_OUTPUT, name, user_data); -} - -static -void remove_port_by_index(struct bt_component *component, - GPtrArray *ports, uint64_t index) -{ - struct bt_port *port; - struct bt_graph *graph; - - BT_ASSERT(ports); - BT_ASSERT(index < ports->len); - port = g_ptr_array_index(ports, index); - BT_LIB_LOGD("Removing port from component: %![comp-]+c, %![port-]+p", - component, port); - - /* Disconnect both ports of this port's connection, if any */ - if (port->connection) { - bt_connection_end(port->connection, true); - } - - /* - * The port's current reference count can be 0 at this point, - * which means its parent (component) keeps it alive. We are - * about to remove the port from its parent's container (with - * the g_ptr_array_remove_index() call below), which in this - * case would destroy it. This is not good because we still - * need the port for the bt_graph_notify_port_removed() call - * below (in which its component is `NULL` as expected because - * of the bt_object_set_parent() call below). - * - * To avoid a destroyed port during the notification callback, - * get a reference now, and put it (destroying the port if its - * reference count is 0 at this point) after notifying the - * graph's user. - */ - bt_object_get_no_null_check(&port->base); - - /* - * Remove from parent's array of ports (weak refs). This never - * destroys the port object because its reference count is at - * least 1 thanks to the bt_object_get_no_null_check() call - * above. - */ - g_ptr_array_remove_index(ports, index); - - /* Detach port from its component parent */ - bt_object_set_parent(&port->base, NULL); - - /* - * Notify the graph's creator that a port is removed. - */ - graph = bt_component_borrow_graph(component); - if (graph) { - bt_graph_notify_port_removed(graph, component, port); - } - - BT_LIB_LOGD("Removed port from component: %![comp-]+c, %![port-]+p", - component, port); - - /* - * Put the local reference. If this port's reference count was 0 - * when entering this function, it is 1 now, so it is destroyed - * immediately. - */ - bt_object_put_no_null_check(&port->base); -} - -BT_HIDDEN -void bt_component_remove_port(struct bt_component *component, - struct bt_port *port) -{ - uint64_t i; - GPtrArray *ports = NULL; - - BT_ASSERT(component); - BT_ASSERT(port); - - switch (port->type) { - case BT_PORT_TYPE_INPUT: - ports = component->input_ports; - break; - case BT_PORT_TYPE_OUTPUT: - ports = component->output_ports; - break; - default: - abort(); - } - - BT_ASSERT(ports); - - for (i = 0; i < ports->len; i++) { - struct bt_port *cur_port = g_ptr_array_index(ports, i); - - if (cur_port == port) { - remove_port_by_index(component, - ports, i); - goto end; - } - } - - BT_LIB_LOGW("Port to remove from component was not found: " - "%![comp-]+c, %![port-]+p", component, port); - -end: - return; + return add_port(component, component->output_ports, + BT_PORT_TYPE_OUTPUT, name, user_data, port); } BT_HIDDEN @@ -711,79 +623,16 @@ enum bt_self_component_status bt_component_port_connected( status = method(comp, self_port, (void *) other_port); BT_LOGD("User method returned: status=%s", bt_self_component_status_string(status)); + BT_ASSERT_PRE(status == BT_SELF_COMPONENT_STATUS_OK || + status == BT_SELF_COMPONENT_STATUS_ERROR || + status == BT_SELF_COMPONENT_STATUS_NOMEM, + "Unexpected returned component status: status=%s", + bt_self_component_status_string(status)); } return status; } -BT_HIDDEN -void bt_component_port_disconnected(struct bt_component *comp, - struct bt_port *port) -{ - typedef void (*method_t)(void *, void *); - - method_t method = NULL; - - BT_ASSERT(comp); - BT_ASSERT(port); - - switch (comp->class->type) { - case BT_COMPONENT_CLASS_TYPE_SOURCE: - { - struct bt_component_class_source *src_cc = (void *) comp->class; - - switch (port->type) { - case BT_PORT_TYPE_OUTPUT: - method = (method_t) src_cc->methods.output_port_disconnected; - break; - default: - abort(); - } - - break; - } - case BT_COMPONENT_CLASS_TYPE_FILTER: - { - struct bt_component_class_filter *flt_cc = (void *) comp->class; - - switch (port->type) { - case BT_PORT_TYPE_INPUT: - method = (method_t) flt_cc->methods.input_port_disconnected; - break; - case BT_PORT_TYPE_OUTPUT: - method = (method_t) flt_cc->methods.output_port_disconnected; - break; - default: - abort(); - } - - break; - } - case BT_COMPONENT_CLASS_TYPE_SINK: - { - struct bt_component_class_sink *sink_cc = (void *) comp->class; - - switch (port->type) { - case BT_PORT_TYPE_INPUT: - method = (method_t) sink_cc->methods.input_port_disconnected; - break; - default: - abort(); - } - - break; - } - default: - abort(); - } - - if (method) { - BT_LIB_LOGD("Calling user's \"port disconnected\" method: " - "%![comp-]+c, %![port-]+p", comp, port); - method(comp, port); - } -} - BT_HIDDEN void bt_component_add_destroy_listener(struct bt_component *component, bt_component_destroy_listener_func func, void *data) @@ -823,3 +672,13 @@ void bt_component_remove_destroy_listener(struct bt_component *component, } } } + +void bt_component_get_ref(const struct bt_component *component) +{ + bt_object_get_ref(component); +} + +void bt_component_put_ref(const struct bt_component *component) +{ + bt_object_put_ref(component); +}