X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fgraph%2Fcomponent.c;h=6494f64883128ccb3ce0d81c5e1ac7ab305ed3bc;hb=68b66a256a54d32992dfefeaad11eea88b7df234;hp=8837c0d1fa50dad479c6a36cbbd17db8a6acd3c8;hpb=3230ee6b4f3a704958b761daecae835c56938bc9;p=babeltrace.git diff --git a/lib/graph/component.c b/lib/graph/component.c index 8837c0d1..6494f648 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -1,12 +1,7 @@ /* - * component.c - * - * Babeltrace Plugin Component - * + * 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 @@ -26,25 +21,36 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#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 static struct bt_component * (* const component_create_funcs[])( - struct bt_component_class *, struct bt_value *) = { + 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, @@ -58,27 +64,75 @@ void (*component_destroy_funcs[])(struct bt_component *) = { }; static -enum bt_component_status (* const component_validation_funcs[])( - struct bt_component *) = { - [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_validate, - [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_validate, - [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_validate, -}; +void finalize_component(struct bt_component *comp) +{ + typedef void (*method_t)(void *); + + method_t method = NULL; + + BT_ASSERT(comp); + + switch (comp->class->type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + { + struct bt_component_class_source *src_cc = (void *) comp->class; + + method = (method_t) src_cc->methods.finalize; + break; + } + case BT_COMPONENT_CLASS_TYPE_FILTER: + { + struct bt_component_class_filter *flt_cc = (void *) comp->class; + + method = (method_t) flt_cc->methods.finalize; + break; + } + case BT_COMPONENT_CLASS_TYPE_SINK: + { + struct bt_component_class_sink *sink_cc = (void *) comp->class; + + method = (method_t) sink_cc->methods.finalize; + break; + } + default: + abort(); + } + + if (method) { + BT_LIB_LOGD("Calling user's finalization method: " + "%![comp-]+c", comp); + method(comp); + } +} static -void bt_component_destroy(struct bt_object *obj) +void destroy_component(struct bt_object *obj) { struct bt_component *component = NULL; - struct bt_component_class *component_class = NULL; int i; if (!obj) { return; } + /* + * The component's reference count is 0 if we're here. Increment + * it to avoid a double-destroy (possibly infinitely recursive). + * This could happen for example if the component's finalization + * function does bt_object_get_ref() (or anything that causes + * bt_object_get_ref() to be called) on itself (ref. count goes + * from 0 to 1), and then bt_object_put_ref(): the reference + * count would go from 1 to 0 again and this function would be + * called again. + */ + obj->ref_count++; component = container_of(obj, struct bt_component, base); + BT_LIB_LOGD("Destroying component: %![comp-]+c, %![graph-]+g", + component, bt_component_borrow_graph(component)); /* Call destroy listeners in reverse registration order */ + BT_LOGD_STR("Calling destroy listeners."); + for (i = component->destroy_listeners->len - 1; i >= 0; i--) { struct bt_component_destroy_listener *listener = &g_array_index(component->destroy_listeners, @@ -87,83 +141,87 @@ void bt_component_destroy(struct bt_object *obj) listener->func(component, listener->data); } - 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) { - component->class->methods.finalize( - bt_private_component_from_component(component)); + if (component->initialized) { + finalize_component(component); } if (component->destroy) { + BT_LOGD_STR("Destroying type-specific data."); component->destroy(component); } if (component->input_ports) { + BT_LOGD_STR("Destroying input ports."); g_ptr_array_free(component->input_ports, TRUE); + component->input_ports = NULL; } if (component->output_ports) { + BT_LOGD_STR("Destroying output ports."); g_ptr_array_free(component->output_ports, TRUE); + component->output_ports = NULL; } if (component->destroy_listeners) { g_array_free(component->destroy_listeners, TRUE); + component->destroy_listeners = NULL; } - g_string_free(component->name, TRUE); - bt_put(component_class); - g_free(component); -} + if (component->name) { + g_string_free(component->name, TRUE); + component->name = NULL; + } -struct bt_component *bt_component_from_private_component( - struct bt_private_component *private_component) -{ - return bt_get(bt_component_from_private(private_component)); + BT_LOGD_STR("Putting component class."); + BT_OBJECT_PUT_REF_AND_RESET(component->class); + g_free(component); } enum bt_component_class_type bt_component_get_class_type( - struct bt_component *component) + const struct bt_component *component) { - return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->class->type; } static -struct bt_port *bt_component_add_port( +enum bt_self_component_status add_port( struct bt_component *component, GPtrArray *ports, - enum bt_port_type port_type, const char *name) + enum bt_port_type port_type, const char *name, void *user_data, + struct bt_port **port) { - size_t i; struct bt_port *new_port = NULL; struct bt_graph *graph = NULL; - - if (!name || strlen(name) == 0) { - goto end; - } - - /* Look for a port having the same name. */ - for (i = 0; i < ports->len; i++) { - const char *port_name; - struct bt_port *port = g_ptr_array_index( - ports, i); - - port_name = bt_port_get_name(port); - if (!port_name) { - continue; - } - - if (!strcmp(name, port_name)) { - /* Port name clash, abort. */ - goto end; - } - } - - new_port = bt_port_create(component, port_type, name); + enum bt_self_component_status status; + + BT_ASSERT_PRE_NON_NULL(component, "Component"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE(strlen(name) > 0, "Name is empty"); + graph = bt_component_borrow_graph(component); + 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. + + BT_LIB_LOGD("Adding port to component: %![comp-]+c, " + "port-type=%s, port-name=\"%s\"", component, + bt_port_type_string(port_type), name); + + new_port = bt_port_create(component, port_type, name, user_data); if (!new_port) { - goto end; + BT_LOGE_STR("Cannot create port object."); + status = BT_SELF_COMPONENT_STATUS_NOMEM; + goto error; } /* @@ -177,260 +235,174 @@ struct bt_port *bt_component_add_port( /* * Notify the graph's creator that a new port was added. */ - graph = bt_component_get_graph(component); + graph = bt_component_borrow_graph(component); if (graph) { - bt_graph_notify_port_added(graph, new_port); - BT_PUT(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) { - assert(comp); - return comp->input_ports->len; + 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) { - assert(comp); - return comp->output_ports->len; + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + return (uint64_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) +BT_HIDDEN +int bt_component_create(struct bt_component_class *component_class, + const char *name, struct bt_component **user_component) { - int ret; + int ret = 0; struct bt_component *component = NULL; enum bt_component_class_type type; - struct bt_port *default_port = NULL; - - bt_get(params); - - if (!component_class) { - goto end; - } + BT_ASSERT(user_component); + BT_ASSERT(component_class); + BT_ASSERT(name); type = bt_component_class_get_type(component_class); - if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN || - type > BT_COMPONENT_CLASS_TYPE_FILTER) { - 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)) { - goto end; - } - } else { - params = bt_value_map_create(); - if (!params) { - goto end; - } - } - - component = component_create_funcs[type](component_class, params); + BT_LIB_LOGD("Creating empty component from component class: %![cc-]+C, " + "comp-name=\"%s\"", component_class, name); + component = component_create_funcs[type](component_class); if (!component) { + BT_LOGE_STR("Cannot create specific component object."); + ret = -1; goto end; } - bt_object_init(component, bt_component_destroy); - component->class = bt_get(component_class); + 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]; component->name = g_string_new(name); if (!component->name) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GString."); + ret = -1; goto end; } component->input_ports = g_ptr_array_new_with_free_func( - bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!component->input_ports) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GPtrArray."); + ret = -1; goto end; } component->output_ports = g_ptr_array_new_with_free_func( - bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!component->output_ports) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GPtrArray."); + ret = -1; goto end; } component->destroy_listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_component_destroy_listener)); if (!component->destroy_listeners) { - BT_PUT(component); - goto end; - } - - if (type == BT_COMPONENT_CLASS_TYPE_SOURCE || - type == BT_COMPONENT_CLASS_TYPE_FILTER) { - default_port = bt_component_add_port(component, - component->output_ports, BT_PORT_TYPE_OUTPUT, - DEFAULT_OUTPUT_PORT_NAME); - if (!default_port) { - BT_PUT(component); - goto end; - } - - BT_PUT(default_port); - } - - if (type == BT_COMPONENT_CLASS_TYPE_FILTER || - type == BT_COMPONENT_CLASS_TYPE_SINK) { - default_port = bt_component_add_port(component, - component->input_ports, BT_PORT_TYPE_INPUT, - DEFAULT_INPUT_PORT_NAME); - if (!default_port) { - BT_PUT(component); - goto end; - } - - BT_PUT(default_port); - } - - component->initializing = true; - - if (component_class->methods.init) { - ret = component_class->methods.init( - bt_private_component_from_component(component), params, - init_method_data); - component->initializing = false; - if (ret != BT_COMPONENT_STATUS_OK) { - BT_PUT(component); - goto end; - } - } - - component->initializing = false; - ret = component_validation_funcs[type](component); - if (ret != BT_COMPONENT_STATUS_OK) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GArray."); + ret = -1; goto end; } - bt_component_class_freeze(component->class); -end: - bt_put(params); - bt_put(default_port); - return component; -} - -struct bt_component *bt_component_create( - struct bt_component_class *component_class, const char *name, - struct bt_value *params) -{ - return bt_component_create_with_init_method_data(component_class, name, - params, NULL); -} - -const char *bt_component_get_name(struct bt_component *component) -{ - const char *ret = NULL; - - if (!component) { - goto end; - } + BT_LIB_LOGD("Created empty component from component class: " + "%![cc-]+C, %![comp-]+c", component_class, component); + BT_OBJECT_MOVE_REF(*user_component, component); - ret = component->name->len == 0 ? NULL : component->name->str; end: + bt_object_put_ref(component); return ret; } -enum bt_component_status bt_component_set_name(struct bt_component *component, - const char *name) +const char *bt_component_get_name(const struct bt_component *component) { - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - - if (!component || !name || name[0] == '\0') { - ret = BT_COMPONENT_STATUS_INVALID; - goto end; - } - - g_string_assign(component->name, name); -end: - return ret; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->name->str; } -struct bt_component_class *bt_component_get_class( - struct bt_component *component) +const struct bt_component_class *bt_component_borrow_class_const( + const struct bt_component *component) { - return component ? bt_get(component->class) : NULL; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->class; } -void *bt_private_component_get_user_data( - struct bt_private_component *private_component) +void *bt_self_component_get_data(const struct bt_self_component *self_comp) { - struct bt_component *component = - bt_component_from_private(private_component); + struct bt_component *component = (void *) self_comp; - return component ? component->user_data : NULL; + BT_ASSERT_PRE_NON_NULL(component, "Component"); + return component->user_data; } -enum bt_component_status bt_private_component_set_user_data( - struct bt_private_component *private_component, +void bt_self_component_set_data(struct bt_self_component *self_comp, void *data) { - struct bt_component *component = - bt_component_from_private(private_component); - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - - if (!component || !component->initializing) { - ret = BT_COMPONENT_STATUS_INVALID; - goto end; - } + struct bt_component *component = (void *) self_comp; + BT_ASSERT_PRE_NON_NULL(component, "Component"); component->user_data = data; -end: - return ret; + BT_LIB_LOGV("Set component's user data: %!+c", component); } 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->base, + graph ? &graph->base : NULL); } -struct bt_graph *bt_component_get_graph( - struct bt_component *component) +bt_bool bt_component_graph_is_canceled(const struct bt_component *component) { - return (struct bt_graph *) bt_object_get_parent(&component->base); + return bt_graph_is_canceled( + (void *) bt_object_borrow_parent(&component->base)); } static -struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name) +struct bt_port *borrow_port_by_name(GPtrArray *ports, + const char *name) { - size_t i; + uint64_t i; struct bt_port *ret_port = NULL; - assert(name); + BT_ASSERT(name); for (i = 0; i < ports->len; i++) { struct bt_port *port = g_ptr_array_index(ports, i); - const char *port_name = bt_port_get_name(port); - if (!port_name) { - continue; - } - - if (!strcmp(name, port_name)) { - ret_port = bt_get(port); + if (!strcmp(name, port->name->str)) { + ret_port = port; break; } } @@ -439,187 +411,226 @@ struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name) } BT_HIDDEN -struct bt_port *bt_component_get_input_port(struct bt_component *comp, - const char *name) +struct bt_port_input *bt_component_borrow_input_port_by_name( + struct bt_component *comp, const char *name) { - assert(comp); - - return bt_component_get_port(comp->input_ports, name); + BT_ASSERT(comp); + return (void *) borrow_port_by_name(comp->input_ports, name); } BT_HIDDEN -struct bt_port *bt_component_get_output_port(struct bt_component *comp, - const char *name) +struct bt_port_output *bt_component_borrow_output_port_by_name( + struct bt_component *comp, const char *name) { - assert(comp); - - return bt_component_get_port(comp->output_ports, name); + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + return (void *) + borrow_port_by_name(comp->output_ports, name); } static -struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index) +struct bt_port *borrow_port_by_index(GPtrArray *ports, uint64_t index) { - struct bt_port *port = NULL; - - if (index < 0 || index >= ports->len) { - goto end; - } - - port = bt_get(g_ptr_array_index(ports, index)); -end: - return port; + BT_ASSERT(index < ports->len); + return g_ptr_array_index(ports, index); } BT_HIDDEN -struct bt_port *bt_component_get_input_port_at_index(struct bt_component *comp, - int index) +struct bt_port_input *bt_component_borrow_input_port_by_index( + struct bt_component *comp, uint64_t index) { - assert(comp); - - return bt_component_get_port_at_index(comp->input_ports, index); + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + BT_ASSERT_PRE_VALID_INDEX(index, comp->input_ports->len); + return (void *) + borrow_port_by_index(comp->input_ports, index); } BT_HIDDEN -struct bt_port *bt_component_get_output_port_at_index(struct bt_component *comp, - int index) +struct bt_port_output *bt_component_borrow_output_port_by_index( + struct bt_component *comp, uint64_t index) { - assert(comp); - - return bt_component_get_port_at_index(comp->output_ports, index); + BT_ASSERT_PRE_NON_NULL(comp, "Component"); + BT_ASSERT_PRE_VALID_INDEX(index, comp->output_ports->len); + return (void *) + borrow_port_by_index(comp->output_ports, index); } BT_HIDDEN -struct bt_port *bt_component_add_input_port( - struct bt_component *component, const char *name) +enum bt_self_component_status bt_component_add_input_port( + struct bt_component *component, const char *name, + void *user_data, struct bt_port **port) { - return bt_component_add_port(component, component->input_ports, - BT_PORT_TYPE_INPUT, name); + /* add_port() logs details */ + return add_port(component, component->input_ports, + BT_PORT_TYPE_INPUT, name, user_data, port); } BT_HIDDEN -struct bt_port *bt_component_add_output_port( - struct bt_component *component, const char *name) +enum bt_self_component_status bt_component_add_output_port( + struct bt_component *component, const char *name, + void *user_data, struct bt_port **port) { - return bt_component_add_port(component, component->output_ports, - BT_PORT_TYPE_OUTPUT, name); + /* add_port() logs details */ + return add_port(component, component->output_ports, + BT_PORT_TYPE_OUTPUT, name, user_data, port); } -static -void bt_component_remove_port_at_index(struct bt_component *component, - GPtrArray *ports, size_t index) +BT_HIDDEN +enum bt_self_component_status bt_component_accept_port_connection( + struct bt_component *comp, struct bt_port *self_port, + struct bt_port *other_port) { - struct bt_port *port; - struct bt_graph *graph; + typedef enum bt_self_component_status (*method_t)( + void *, void *, const void *); - assert(ports); - assert(index < ports->len); - port = g_ptr_array_index(ports, index); + enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK; + method_t method = NULL; - /* Disconnect both ports of this port's connection, if any */ - if (port->connection) { - bt_connection_disconnect_ports(port->connection); - } + BT_ASSERT(comp); + BT_ASSERT(self_port); + BT_ASSERT(other_port); - /* Remove from parent's array of ports (weak refs) */ - g_ptr_array_remove_index(ports, index); + switch (comp->class->type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + { + struct bt_component_class_source *src_cc = (void *) comp->class; - /* Detach port from its component parent */ - BT_PUT(port->base.parent); + switch (self_port->type) { + case BT_PORT_TYPE_OUTPUT: + method = (method_t) src_cc->methods.accept_output_port_connection; + break; + default: + abort(); + } - /* - * Notify the graph's creator that a port is removed. - */ - graph = bt_component_get_graph(component); - if (graph) { - bt_graph_notify_port_removed(graph, component, port); - BT_PUT(graph); + break; } -} + case BT_COMPONENT_CLASS_TYPE_FILTER: + { + struct bt_component_class_filter *flt_cc = (void *) comp->class; -BT_HIDDEN -enum bt_component_status bt_component_remove_port( - struct bt_component *component, struct bt_port *port) -{ - size_t i; - enum bt_component_status status = BT_COMPONENT_STATUS_OK; - GPtrArray *ports = NULL; - - if (!component || !port) { - status = BT_COMPONENT_STATUS_INVALID; - goto end; - } + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) flt_cc->methods.accept_input_port_connection; + break; + case BT_PORT_TYPE_OUTPUT: + method = (method_t) flt_cc->methods.accept_output_port_connection; + break; + default: + abort(); + } - if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) { - ports = component->input_ports; - } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) { - ports = component->output_ports; + break; } + case BT_COMPONENT_CLASS_TYPE_SINK: + { + struct bt_component_class_sink *sink_cc = (void *) comp->class; - assert(ports); + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) sink_cc->methods.accept_input_port_connection; + break; + default: + abort(); + } - for (i = 0; i < ports->len; i++) { - struct bt_port *cur_port = g_ptr_array_index(ports, i); + break; + } + default: + abort(); + } - if (cur_port == port) { - bt_component_remove_port_at_index(component, - ports, i); - goto end; - } + if (method) { + 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, (void *) other_port); + BT_LOGD("User method returned: status=%s", + bt_self_component_status_string(status)); } - status = BT_COMPONENT_STATUS_NOT_FOUND; -end: return status; } BT_HIDDEN -enum bt_component_status bt_component_accept_port_connection( +enum bt_self_component_status bt_component_port_connected( struct bt_component *comp, struct bt_port *self_port, struct bt_port *other_port) { - enum bt_component_status status = BT_COMPONENT_STATUS_OK; + typedef enum bt_self_component_status (*method_t)( + void *, void *, const void *); - assert(comp); - assert(self_port); - assert(other_port); + enum bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK; + method_t method = NULL; - if (comp->class->methods.accept_port_connection) { - status = comp->class->methods.accept_port_connection( - bt_private_component_from_component(comp), - bt_private_port_from_port(self_port), - other_port); - } + BT_ASSERT(comp); + BT_ASSERT(self_port); + BT_ASSERT(other_port); - return status; -} + switch (comp->class->type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + { + struct bt_component_class_source *src_cc = (void *) comp->class; -BT_HIDDEN -void bt_component_port_connected(struct bt_component *comp, - struct bt_port *self_port, struct bt_port *other_port) -{ - assert(comp); - assert(self_port); - assert(other_port); + switch (self_port->type) { + case BT_PORT_TYPE_OUTPUT: + method = (method_t) src_cc->methods.output_port_connected; + break; + default: + abort(); + } - if (comp->class->methods.port_connected) { - comp->class->methods.port_connected( - bt_private_component_from_component(comp), - bt_private_port_from_port(self_port), other_port); + break; } -} + case BT_COMPONENT_CLASS_TYPE_FILTER: + { + struct bt_component_class_filter *flt_cc = (void *) comp->class; -BT_HIDDEN -void bt_component_port_disconnected(struct bt_component *comp, - struct bt_port *port) -{ - assert(comp); - assert(port); + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) flt_cc->methods.input_port_connected; + break; + case BT_PORT_TYPE_OUTPUT: + method = (method_t) flt_cc->methods.output_port_connected; + break; + default: + abort(); + } - if (comp->class->methods.port_disconnected) { - comp->class->methods.port_disconnected( - bt_private_component_from_component(comp), - bt_private_port_from_port(port)); + break; + } + case BT_COMPONENT_CLASS_TYPE_SINK: + { + struct bt_component_class_sink *sink_cc = (void *) comp->class; + + switch (self_port->type) { + case BT_PORT_TYPE_INPUT: + method = (method_t) sink_cc->methods.input_port_connected; + break; + default: + abort(); + } + + break; + } + default: + abort(); } + + if (method) { + 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, (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 @@ -628,21 +639,24 @@ void bt_component_add_destroy_listener(struct bt_component *component, { struct bt_component_destroy_listener listener; - assert(component); - assert(func); + BT_ASSERT(component); + BT_ASSERT(func); listener.func = func; listener.data = data; g_array_append_val(component->destroy_listeners, listener); + BT_LIB_LOGV("Added destroy listener: %![comp-]+c, " + "func-addr=%p, data-addr=%p", + component, func, data); } BT_HIDDEN void bt_component_remove_destroy_listener(struct bt_component *component, bt_component_destroy_listener_func func, void *data) { - size_t i; + uint64_t i; - assert(component); - assert(func); + BT_ASSERT(component); + BT_ASSERT(func); for (i = 0; i < component->destroy_listeners->len; i++) { struct bt_component_destroy_listener *listener = @@ -652,6 +666,19 @@ void bt_component_remove_destroy_listener(struct bt_component *component, if (listener->func == func && listener->data == data) { g_array_remove_index(component->destroy_listeners, i); i--; + BT_LIB_LOGV("Removed destroy listener: %![comp-]+c, " + "func-addr=%p, data-addr=%p", + component, func, data); } } } + +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); +}