X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fgraph%2Fcomponent.c;h=641ee78b4307a9465525fbca763edb28403fca2a;hb=9b24b6aa4258079f2b59fa156dd3e070969f6f2a;hp=84a850100a91d505a18690d80d8e544f509ff8fd;hpb=398454ed067b95215c7affbe265fd36edab931ee;p=babeltrace.git diff --git a/lib/graph/component.c b/lib/graph/component.c index 84a85010..641ee78b 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 @@ -25,8 +24,13 @@ #define BT_LOG_TAG "COMP" #include +#include +#include #include -#include +#include +#include +#include +#include #include #include #include @@ -34,22 +38,19 @@ #include #include #include -#include +#include #include #include #include -#include #include -#include -#include -#include -#include +#include +#include #include #include static struct bt_component * (* const component_create_funcs[])( - struct bt_component_class *) = { + const 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, @@ -182,19 +183,21 @@ void destroy_component(struct bt_object *obj) } enum bt_component_class_type bt_component_get_class_type( - struct bt_component *component) + const struct bt_component *component) { BT_ASSERT_PRE_NON_NULL(component, "Component"); return component->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"); @@ -203,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. @@ -213,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; } /* @@ -227,29 +235,45 @@ 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 -uint64_t bt_component_get_input_port_count(struct bt_component *comp) +uint64_t bt_component_get_input_port_count(const struct bt_component *comp) { BT_ASSERT_PRE_NON_NULL(comp, "Component"); return (uint64_t) comp->input_ports->len; } BT_HIDDEN -uint64_t bt_component_get_output_port_count(struct bt_component *comp) +uint64_t bt_component_get_output_port_count(const struct bt_component *comp) { BT_ASSERT_PRE_NON_NULL(comp, "Component"); return (uint64_t) comp->output_ports->len; @@ -266,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); @@ -277,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]; @@ -322,20 +344,20 @@ end: return ret; } -const char *bt_component_get_name(struct bt_component *component) +const char *bt_component_get_name(const struct bt_component *component) { BT_ASSERT_PRE_NON_NULL(component, "Component"); return component->name->str; } -struct bt_component_class *bt_component_borrow_class( - struct bt_component *component) +const struct bt_component_class *bt_component_borrow_class_const( + const struct bt_component *component) { BT_ASSERT_PRE_NON_NULL(component, "Component"); return component->class; } -void *bt_self_component_get_data(struct bt_self_component *self_comp) +void *bt_self_component_get_data(const struct bt_self_component *self_comp) { struct bt_component *component = (void *) self_comp; @@ -361,7 +383,7 @@ void bt_component_set_graph(struct bt_component *component, graph ? &graph->base : NULL); } -bt_bool bt_component_graph_is_canceled(struct bt_component *component) +bt_bool bt_component_graph_is_canceled(const struct bt_component *component) { return bt_graph_is_canceled( (void *) bt_object_borrow_parent(&component->base)); @@ -433,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 - * private 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 @@ -565,7 +480,7 @@ enum bt_self_component_status bt_component_accept_port_connection( struct bt_port *other_port) { typedef enum bt_self_component_status (*method_t)( - void *, void *, void *); + void *, void *, const void *); enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK; method_t method = NULL; @@ -628,7 +543,7 @@ enum bt_self_component_status bt_component_accept_port_connection( BT_LIB_LOGD("Calling user's \"accept port connection\" method: " "%![comp-]+c, %![self-port-]+p, %![other-port-]+p", comp, self_port, other_port); - status = method(comp, self_port, other_port); + status = method(comp, self_port, (void *) other_port); BT_LOGD("User method returned: status=%s", bt_self_component_status_string(status)); } @@ -642,7 +557,7 @@ enum bt_self_component_status bt_component_port_connected( struct bt_port *other_port) { typedef enum bt_self_component_status (*method_t)( - void *, void *, void *); + void *, void *, const void *); enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK; method_t method = NULL; @@ -705,82 +620,19 @@ enum bt_self_component_status bt_component_port_connected( BT_LIB_LOGD("Calling user's \"port connected\" method: " "%![comp-]+c, %![self-port-]+p, %![other-port-]+p", comp, self_port, other_port); - status = method(comp, self_port, other_port); + 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) @@ -820,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); +}