X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fgraph%2Fcomponent.c;h=0fb9be8195ff5debd33df3e6b6db5e354cf84eae;hb=151a8109923ad34382dca7f284ea28887674a848;hp=e3464f45b646929b43952a78699fb73824d25f92;hpb=544d0515ffa2d011247e4f1d7cad5770b8ec7033;p=babeltrace.git diff --git a/lib/graph/component.c b/lib/graph/component.c index e3464f45..0fb9be81 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -26,6 +26,9 @@ * SOFTWARE. */ +#define BT_LOG_TAG "COMP" +#include + #include #include #include @@ -41,10 +44,15 @@ #include #include #include +#include +#include +#include +#include +#include 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, @@ -57,14 +65,6 @@ void (*component_destroy_funcs[])(struct bt_component *) = { [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_destroy, }; -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, -}; - static void bt_component_destroy(struct bt_object *obj) { @@ -76,9 +76,24 @@ void bt_component_destroy(struct bt_object *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_get() (or anything that causes bt_get() to + * be called) on itself (ref. count goes from 0 to 1), and then + * bt_put(): the reference count would go from 1 to 0 again and + * this function would be called again. + */ + obj->ref_count.count++; component = container_of(obj, struct bt_component, base); + BT_LOGD("Destroying component: addr=%p, name=\"%s\", graph-addr=%p", + component, bt_component_get_name(component), + obj->parent); /* 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, @@ -90,23 +105,28 @@ 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)); } 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); } if (component->output_ports) { + BT_LOGD_STR("Destroying output ports."); g_ptr_array_free(component->output_ports, TRUE); } @@ -114,7 +134,11 @@ void bt_component_destroy(struct bt_object *obj) g_array_free(component->destroy_listeners, TRUE); } - g_string_free(component->name, TRUE); + if (component->name) { + g_string_free(component->name, TRUE); + } + + BT_LOGD("Putting component class."); bt_put(component_class); g_free(component); } @@ -134,35 +158,46 @@ enum bt_component_class_type bt_component_get_class_type( static struct bt_port *bt_component_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) { size_t i; struct bt_port *new_port = NULL; struct bt_graph *graph = NULL; - if (!name || strlen(name) == 0) { + if (!name) { + BT_LOGW_STR("Invalid parameter: name is NULL."); goto end; } + if (strlen(name) == 0) { + BT_LOGW_STR("Invalid parameter: name is an empty string."); + goto end; + } + + BT_LOGD("Adding port to component: comp-addr=%p, comp-name=\"%s\", " + "port-type=%s, port-name=\"%s\"", component, + bt_component_get_name(component), + bt_port_type_string(port_type), name); + /* 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); + struct bt_port *port = g_ptr_array_index(ports, i); port_name = bt_port_get_name(port); - if (!port_name) { - continue; - } + assert(port_name); if (!strcmp(name, port_name)) { /* Port name clash, abort. */ + BT_LOGW("Invalid parameter: another port with the same name already exists in the component: " + "other-port-addr=%p", port); goto end; } } - new_port = bt_port_create(component, port_type, name); + new_port = bt_port_create(component, port_type, name, user_data); if (!new_port) { + BT_LOGE("Cannot create port object."); goto end; } @@ -183,6 +218,11 @@ struct bt_port *bt_component_add_port( BT_PUT(graph); } + BT_LOGD("Created and added port to component: comp-addr=%p, comp-name=\"%s\", " + "port-type=%s, port-name=\"%s\", port-addr=%p", component, + bt_component_get_name(component), + bt_port_type_string(port_type), name, new_port); + end: return new_port; } @@ -191,54 +231,37 @@ BT_HIDDEN int64_t bt_component_get_input_port_count(struct bt_component *comp) { assert(comp); - return comp->input_ports->len; + return (int64_t) comp->input_ports->len; } BT_HIDDEN int64_t bt_component_get_output_port_count(struct bt_component *comp) { assert(comp); - return comp->output_ports->len; + 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) +BT_HIDDEN +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; - struct bt_port *default_port = NULL; - bt_get(params); - - if (!component_class) { - 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) { - 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_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; } @@ -247,90 +270,44 @@ struct bt_component *bt_component_create_with_init_method_data( 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."); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } component->input_ports = g_ptr_array_new_with_free_func( bt_object_release); if (!component->input_ports) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GPtrArray."); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } component->output_ports = g_ptr_array_new_with_free_func( bt_object_release); if (!component->output_ports) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GPtrArray."); + status = BT_COMPONENT_STATUS_NOMEM; goto end; } component->destroy_listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_component_destroy_listener)); if (!component->destroy_listeners) { - BT_PUT(component); + BT_LOGE_STR("Failed to allocate one GArray."); + status = BT_COMPONENT_STATUS_NOMEM; 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_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); - 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); - 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); + bt_put(component); + return status; } const char *bt_component_get_name(struct bt_component *component) @@ -338,25 +315,12 @@ const char *bt_component_get_name(struct bt_component *component) const char *ret = NULL; if (!component) { + BT_LOGW_STR("Invalid parameter: component is NULL."); goto end; } ret = component->name->len == 0 ? NULL : component->name->str; -end: - return ret; -} - -enum bt_component_status bt_component_set_name(struct bt_component *component, - const char *name) -{ - 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; } @@ -384,12 +348,17 @@ enum bt_component_status bt_private_component_set_user_data( bt_component_from_private(private_component); enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - if (!component || !component->initializing) { + if (!component) { + BT_LOGW_STR("Invalid parameter: component is NULL."); ret = BT_COMPONENT_STATUS_INVALID; goto end; } component->user_data = data; + BT_LOGV("Set component's user data: " + "comp-addr=%p, comp-name=\"%s\", user-data-addr=%p", + component, bt_component_get_name(component), data); + end: return ret; } @@ -398,13 +367,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( @@ -414,7 +377,8 @@ struct bt_graph *bt_component_get_graph( } static -struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name) +struct bt_port *bt_component_get_port_by_name(GPtrArray *ports, + const char *name) { size_t i; struct bt_port *ret_port = NULL; @@ -439,29 +403,32 @@ 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, +struct bt_port *bt_component_get_input_port_by_name(struct bt_component *comp, const char *name) { assert(comp); - return bt_component_get_port(comp->input_ports, name); + return bt_component_get_port_by_name(comp->input_ports, name); } BT_HIDDEN -struct bt_port *bt_component_get_output_port(struct bt_component *comp, +struct bt_port *bt_component_get_output_port_by_name(struct bt_component *comp, const char *name) { assert(comp); - return bt_component_get_port(comp->output_ports, name); + return bt_component_get_port_by_name(comp->output_ports, name); } static -struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index) +struct bt_port *bt_component_get_port_by_index(GPtrArray *ports, uint64_t index) { struct bt_port *port = NULL; - if (index < 0 || index >= ports->len) { + if (index >= ports->len) { + BT_LOGW("Invalid parameter: index is out of bounds: " + "index=%" PRIu64 ", count=%u", + index, ports->len); goto end; } @@ -471,41 +438,45 @@ end: } BT_HIDDEN -struct bt_port *bt_component_get_input_port_at_index(struct bt_component *comp, - int index) +struct bt_port *bt_component_get_input_port_by_index(struct bt_component *comp, + uint64_t index) { assert(comp); - return bt_component_get_port_at_index(comp->input_ports, index); + return bt_component_get_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 *bt_component_get_output_port_by_index(struct bt_component *comp, + uint64_t index) { assert(comp); - return bt_component_get_port_at_index(comp->output_ports, index); + return bt_component_get_port_by_index(comp->output_ports, index); } BT_HIDDEN struct bt_port *bt_component_add_input_port( - struct bt_component *component, const char *name) + struct bt_component *component, const char *name, + void *user_data) { + /* bt_component_add_port() logs details */ return bt_component_add_port(component, component->input_ports, - BT_PORT_TYPE_INPUT, name); + BT_PORT_TYPE_INPUT, name, user_data); } BT_HIDDEN struct bt_port *bt_component_add_output_port( - struct bt_component *component, const char *name) + struct bt_component *component, const char *name, + void *user_data) { + /* bt_component_add_port() logs details */ return bt_component_add_port(component, component->output_ports, - BT_PORT_TYPE_OUTPUT, name); + BT_PORT_TYPE_OUTPUT, name, user_data); } static -void bt_component_remove_port_at_index(struct bt_component *component, +void bt_component_remove_port_by_index(struct bt_component *component, GPtrArray *ports, size_t index) { struct bt_port *port; @@ -515,9 +486,15 @@ void bt_component_remove_port_at_index(struct bt_component *component, assert(index < ports->len); port = g_ptr_array_index(ports, index); + BT_LOGD("Removing port from component: " + "comp-addr=%p, comp-name=\"%s\", " + "port-addr=%p, port-name=\"%s\"", + component, bt_component_get_name(component), + port, bt_port_get_name(port)); + /* Disconnect both ports of this port's connection, if any */ if (port->connection) { - bt_connection_disconnect_ports(port->connection); + bt_connection_end(port->connection, true); } /* Remove from parent's array of ports (weak refs) */ @@ -534,6 +511,12 @@ void bt_component_remove_port_at_index(struct bt_component *component, bt_graph_notify_port_removed(graph, component, port); BT_PUT(graph); } + + BT_LOGD("Removed port from component: " + "comp-addr=%p, comp-name=\"%s\", " + "port-addr=%p, port-name=\"%s\"", + component, bt_component_get_name(component), + port, bt_port_get_name(port)); } BT_HIDDEN @@ -544,7 +527,14 @@ enum bt_component_status bt_component_remove_port( enum bt_component_status status = BT_COMPONENT_STATUS_OK; GPtrArray *ports = NULL; - if (!component || !port) { + if (!component) { + BT_LOGW_STR("Invalid parameter: component is NULL."); + status = BT_COMPONENT_STATUS_INVALID; + goto end; + } + + if (!port) { + BT_LOGW_STR("Invalid parameter: port is NULL."); status = BT_COMPONENT_STATUS_INVALID; goto end; } @@ -561,13 +551,19 @@ enum bt_component_status bt_component_remove_port( struct bt_port *cur_port = g_ptr_array_index(ports, i); if (cur_port == port) { - bt_component_remove_port_at_index(component, + bt_component_remove_port_by_index(component, ports, i); goto end; } } status = BT_COMPONENT_STATUS_NOT_FOUND; + BT_LOGW("Port to remove from component was not found: " + "comp-addr=%p, comp-name=\"%s\", " + "port-addr=%p, port-name=\"%s\"", + component, bt_component_get_name(component), + port, bt_port_get_name(port)); + end: return status; } @@ -584,10 +580,19 @@ enum bt_component_status bt_component_accept_port_connection( assert(other_port); if (comp->class->methods.accept_port_connection) { + BT_LOGD("Calling user's \"accept port connection\" method: " + "comp-addr=%p, comp-name=\"%s\", " + "self-port-addr=%p, self-port-name=\"%s\", " + "other-port-addr=%p, other-port-name=\"%s\"", + comp, bt_component_get_name(comp), + self_port, bt_port_get_name(self_port), + other_port, bt_port_get_name(other_port)); status = comp->class->methods.accept_port_connection( bt_private_component_from_component(comp), bt_private_port_from_port(self_port), other_port); + BT_LOGD("User method returned: status=%s", + bt_component_status_string(status)); } return status; @@ -602,6 +607,13 @@ void bt_component_port_connected(struct bt_component *comp, assert(other_port); if (comp->class->methods.port_connected) { + BT_LOGD("Calling user's \"port connected\" method: " + "comp-addr=%p, comp-name=\"%s\", " + "self-port-addr=%p, self-port-name=\"%s\", " + "other-port-addr=%p, other-port-name=\"%s\"", + comp, bt_component_get_name(comp), + self_port, bt_port_get_name(self_port), + other_port, bt_port_get_name(other_port)); comp->class->methods.port_connected( bt_private_component_from_component(comp), bt_private_port_from_port(self_port), other_port); @@ -616,6 +628,11 @@ void bt_component_port_disconnected(struct bt_component *comp, assert(port); if (comp->class->methods.port_disconnected) { + BT_LOGD("Calling user's \"port disconnected\" method: " + "comp-addr=%p, comp-name=\"%s\", " + "port-addr=%p, port-name=\"%s\"", + comp, bt_component_get_name(comp), + port, bt_port_get_name(port)); comp->class->methods.port_disconnected( bt_private_component_from_component(comp), bt_private_port_from_port(port)); @@ -633,6 +650,11 @@ void bt_component_add_destroy_listener(struct bt_component *component, listener.func = func; listener.data = data; g_array_append_val(component->destroy_listeners, listener); + BT_LOGV("Added destroy listener: " + "comp-addr=%p, comp-name=\"%s\", " + "func-addr=%p, data-addr=%p", + component, bt_component_get_name(component), + func, data); } BT_HIDDEN @@ -652,6 +674,11 @@ 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_LOGV("Removed destroy listener: " + "comp-addr=%p, comp-name=\"%s\", " + "func-addr=%p, data-addr=%p", + component, bt_component_get_name(component), + func, data); } } }