X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fcomponent%2Fcomponent.c;h=7a72fe797f02713acf1451f5f242c0f87676d2c3;hb=72b913fbad1753b5b122bfb54c1e7936eaf9d0ef;hp=d82ee0d8fd78d284ef7624fe357689e76b61ff2c;hpb=d3e4dcd8e7a601e0aa063455147f29fbe051582b;p=babeltrace.git diff --git a/lib/component/component.c b/lib/component/component.c index d82ee0d8..7a72fe79 100644 --- a/lib/component/component.c +++ b/lib/component/component.c @@ -29,10 +29,12 @@ #include #include #include -#include -#include +#include +#include +#include +#include +#include #include -#include #include #include #include @@ -45,6 +47,13 @@ struct bt_component * (* const component_create_funcs[])( [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_create, }; +static +void (*component_destroy_funcs[])(struct bt_component *) = { + [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_destroy, + [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_destroy, + [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_destroy, +}; + static enum bt_component_status (* const component_validation_funcs[])( struct bt_component *) = { @@ -78,25 +87,17 @@ void bt_component_destroy(struct bt_object *obj) component->destroy(component); } - g_string_free(component->name, TRUE); - bt_put(component_class); - g_free(component); -} - -BT_HIDDEN -enum bt_component_status bt_component_init(struct bt_component *component, - bt_component_class_destroy_method destroy) -{ - enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + if (component->input_ports) { + g_ptr_array_free(component->input_ports, TRUE); + } - if (!component) { - ret = BT_COMPONENT_STATUS_INVALID; - goto end; + if (component->output_ports) { + g_ptr_array_free(component->output_ports, TRUE); } - component->destroy = destroy; -end: - return ret; + g_string_free(component->name, TRUE); + bt_put(component_class); + g_free(component); } enum bt_component_class_type bt_component_get_class_type( @@ -107,7 +108,7 @@ enum bt_component_class_type bt_component_get_class_type( BT_HIDDEN struct bt_notification_iterator *bt_component_create_iterator( - struct bt_component *component) + struct bt_component *component, void *init_method_data) { enum bt_notification_iterator_status ret_iterator; enum bt_component_class_type type; @@ -134,30 +135,32 @@ struct bt_notification_iterator *bt_component_create_iterator( case BT_COMPONENT_CLASS_TYPE_SOURCE: { struct bt_component_class_source *source_class; - enum bt_component_status ret_component; + enum bt_notification_iterator_status status; source_class = container_of(class, struct bt_component_class_source, parent); - assert(source_class->methods.init_iterator); - ret_component = - source_class->methods.init_iterator(component, iterator); - if (ret_component != BT_COMPONENT_STATUS_OK) { - goto error; - } - break; + if (source_class->methods.iterator.init) { + status = source_class->methods.iterator.init(component, + iterator, init_method_data); + if (status < 0) { + goto error; + } + } break; } case BT_COMPONENT_CLASS_TYPE_FILTER: { struct bt_component_class_filter *filter_class; - enum bt_component_status ret_component; + enum bt_notification_iterator_status status; filter_class = container_of(class, struct bt_component_class_filter, parent); - assert(filter_class->methods.init_iterator); - ret_component = - filter_class->methods.init_iterator(component, iterator); - if (ret_component != BT_COMPONENT_STATUS_OK) { - goto error; + + if (filter_class->methods.iterator.init) { + status = filter_class->methods.iterator.init(component, + iterator, init_method_data); + if (status < 0) { + goto error; + } } break; } @@ -177,19 +180,78 @@ error: return iterator; } -struct bt_component *bt_component_create( +static +struct bt_port *bt_component_add_port( + struct bt_component *component, GPtrArray *ports, + enum bt_port_type port_type, const char *name) +{ + size_t i; + struct bt_port *new_port = 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); + if (!new_port) { + goto end; + } + + /* + * No name clash, add the port. + * The component is now the port's parent; it should _not_ + * hold a reference to the port since the port's lifetime + * is now protected by the component's own lifetime. + */ + g_ptr_array_add(ports, new_port); +end: + return new_port; +} + +BT_HIDDEN +uint64_t bt_component_get_input_port_count(struct bt_component *comp) +{ + assert(comp); + return comp->input_ports->len; +} + +BT_HIDDEN +uint64_t bt_component_get_output_port_count(struct bt_component *comp) +{ + assert(comp); + return 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) + struct bt_value *params, void *init_method_data) { int ret; struct bt_component *component = NULL; enum bt_component_class_type type; + struct bt_port *default_port = NULL; if (!component_class) { goto end; } - type = bt_component_class_get_type(component_class); if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN || type > BT_COMPONENT_CLASS_TYPE_FILTER) { @@ -202,16 +264,59 @@ struct bt_component *bt_component_create( } bt_object_init(component, bt_component_destroy); + component->class = bt_get(component_class); + component->destroy = component_destroy_funcs[type]; component->name = g_string_new(name); if (!component->name) { BT_PUT(component); goto end; } + component->input_ports = g_ptr_array_new_with_free_func( + bt_object_release); + if (!component->input_ports) { + BT_PUT(component); + goto end; + } + + component->output_ports = g_ptr_array_new_with_free_func( + bt_object_release); + if (!component->output_ports) { + 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(component, params); + ret = component_class->methods.init(component, params, + init_method_data); component->initializing = false; if (ret != BT_COMPONENT_STATUS_OK) { BT_PUT(component); @@ -225,10 +330,21 @@ struct bt_component *bt_component_create( BT_PUT(component); goto end; } + + bt_component_class_freeze(component->class); end: + 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; @@ -237,7 +353,7 @@ const char *bt_component_get_name(struct bt_component *component) goto end; } - ret = component->name->str; + ret = component->name->len == 0 ? NULL : component->name->str; end: return ret; } @@ -283,3 +399,202 @@ bt_component_set_private_data(struct bt_component *component, end: return ret; } + +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); +} + +struct bt_graph *bt_component_get_graph( + struct bt_component *component) +{ + return (struct bt_graph *) bt_object_get_parent(&component->base); +} + +static +struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name) +{ + size_t i; + struct bt_port *ret_port = NULL; + + 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); + break; + } + } + + return ret_port; +} + +BT_HIDDEN +struct bt_port *bt_component_get_input_port(struct bt_component *comp, + const char *name) +{ + assert(comp); + + return bt_component_get_port(comp->input_ports, name); +} + +BT_HIDDEN +struct bt_port *bt_component_get_output_port(struct bt_component *comp, + const char *name) +{ + assert(comp); + + return bt_component_get_port(comp->output_ports, name); +} + +static +struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int 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_HIDDEN +struct bt_port *bt_component_get_input_port_at_index(struct bt_component *comp, + int index) +{ + assert(comp); + + return bt_component_get_port_at_index(comp->input_ports, index); +} + +BT_HIDDEN +struct bt_port *bt_component_get_output_port_at_index(struct bt_component *comp, + int index) +{ + assert(comp); + + return bt_component_get_port_at_index(comp->output_ports, index); +} + +BT_HIDDEN +struct bt_port *bt_component_add_input_port( + struct bt_component *component, const char *name) +{ + return bt_component_add_port(component, component->input_ports, + BT_PORT_TYPE_INPUT, name); +} + +BT_HIDDEN +struct bt_port *bt_component_add_output_port( + struct bt_component *component, const char *name) +{ + return bt_component_add_port(component, component->output_ports, + BT_PORT_TYPE_OUTPUT, name); +} + +static +void bt_component_remove_port_at_index(struct bt_component *component, + GPtrArray *ports, size_t index) +{ + struct bt_port *port; + + assert(ports); + assert(index < ports->len); + port = g_ptr_array_index(ports, index); + + /* Disconnect both ports of this port's connection, if any */ + if (port->connection) { + bt_connection_disconnect_ports(port->connection, component); + } + + /* Remove from parent's array of ports (weak refs) */ + g_ptr_array_remove_index(ports, index); + + /* Detach port from its component parent */ + BT_PUT(port->base.parent); + + // TODO: notify graph user: component's port removed +} + +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; + } + + 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; + } + + assert(ports); + + for (i = 0; i < ports->len; i++) { + struct bt_port *cur_port = g_ptr_array_index(ports, i); + + if (cur_port == port) { + bt_component_remove_port_at_index(component, + ports, i); + goto end; + } + } + + status = BT_COMPONENT_STATUS_NOT_FOUND; +end: + return status; +} + +BT_HIDDEN +enum bt_component_status bt_component_accept_port_connection( + struct bt_component *comp, struct bt_port *port) +{ + enum bt_component_status status = BT_COMPONENT_STATUS_OK; + + assert(comp); + assert(port); + + if (comp->class->methods.accept_port_connection) { + status = comp->class->methods.accept_port_connection( + comp, port); + } + + return status; +} + +BT_HIDDEN +void bt_component_port_disconnected(struct bt_component *comp, + struct bt_port *port) +{ + assert(comp); + assert(port); + + if (comp->class->methods.port_disconnected) { + comp->class->methods.port_disconnected(comp, port); + } +}