* SOFTWARE.
*/
+#define BT_LOG_TAG "COMP"
+#include <babeltrace/lib-logging-internal.h>
+
#include <babeltrace/graph/private-component.h>
#include <babeltrace/graph/component.h>
#include <babeltrace/graph/component-internal.h>
#include <babeltrace/graph/connection-internal.h>
#include <babeltrace/graph/graph-internal.h>
#include <babeltrace/graph/notification-iterator-internal.h>
-#include <babeltrace/graph/private-notification-iterator.h>
+#include <babeltrace/graph/private-connection-private-notification-iterator.h>
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/ref.h>
+#include <babeltrace/types.h>
+#include <babeltrace/values.h>
+#include <babeltrace/values-internal.h>
+#include <babeltrace/assert-internal.h>
#include <stdint.h>
+#include <inttypes.h>
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,
[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)
{
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++;
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,
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);
}
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);
}
-struct bt_component *bt_component_from_private_component(
+struct bt_component *bt_component_borrow_from_private(
struct bt_private_component *private_component)
{
- return bt_get(bt_component_from_private(private_component));
+ return (void *) private_component;
}
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;
- }
+ BT_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;
}
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;
}
BT_HIDDEN
int64_t bt_component_get_input_port_count(struct bt_component *comp)
{
- assert(comp);
+ BT_ASSERT(comp);
return (int64_t) comp->input_ports->len;
}
BT_HIDDEN
int64_t bt_component_get_output_port_count(struct bt_component *comp)
{
- assert(comp);
+ BT_ASSERT(comp);
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;
- }
+ 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_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;
}
- bt_object_init(component, bt_component_destroy);
+ bt_object_init_shared_with_parent(&component->base,
+ 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);
+ 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);
+ (GDestroyNotify) bt_object_try_spec_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);
+ (GDestroyNotify) bt_object_try_spec_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_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_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_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)
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;
}
struct bt_private_component *private_component)
{
struct bt_component *component =
- bt_component_from_private(private_component);
+ bt_component_borrow_from_private(private_component);
return component ? component->user_data : NULL;
}
void *data)
{
struct bt_component *component =
- bt_component_from_private(private_component);
+ bt_component_borrow_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;
}
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)
+struct bt_graph *bt_component_borrow_graph(struct bt_component *component)
{
- return (struct bt_graph *) bt_object_get_parent(&component->base);
+ return (struct bt_graph *) bt_object_borrow_parent(&component->base);
}
static
size_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);
struct bt_port *bt_component_get_input_port_by_name(struct bt_component *comp,
const char *name)
{
- assert(comp);
+ BT_ASSERT(comp);
return bt_component_get_port_by_name(comp->input_ports, name);
}
struct bt_port *bt_component_get_output_port_by_name(struct bt_component *comp,
const char *name)
{
- assert(comp);
+ BT_ASSERT(comp);
return bt_component_get_port_by_name(comp->output_ports, name);
}
struct bt_port *port = NULL;
if (index >= ports->len) {
+ BT_LOGW("Invalid parameter: index is out of bounds: "
+ "index=%" PRIu64 ", count=%u",
+ index, ports->len);
goto end;
}
struct bt_port *bt_component_get_input_port_by_index(struct bt_component *comp,
uint64_t index)
{
- assert(comp);
+ BT_ASSERT(comp);
return bt_component_get_port_by_index(comp->input_ports, index);
}
struct bt_port *bt_component_get_output_port_by_index(struct bt_component *comp,
uint64_t index)
{
- assert(comp);
+ BT_ASSERT(comp);
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
struct bt_port *port;
struct bt_graph *graph;
- assert(ports);
- assert(index < ports->len);
+ BT_ASSERT(ports);
+ BT_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) */
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
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;
}
ports = component->output_ports;
}
- assert(ports);
+ BT_ASSERT(ports);
for (i = 0; i < ports->len; i++) {
struct bt_port *cur_port = g_ptr_array_index(ports, i);
}
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;
}
{
enum bt_component_status status = BT_COMPONENT_STATUS_OK;
- assert(comp);
- assert(self_port);
- assert(other_port);
+ BT_ASSERT(comp);
+ BT_ASSERT(self_port);
+ BT_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;
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);
+ BT_ASSERT(comp);
+ BT_ASSERT(self_port);
+ BT_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);
void bt_component_port_disconnected(struct bt_component *comp,
struct bt_port *port)
{
- assert(comp);
- assert(port);
+ BT_ASSERT(comp);
+ BT_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));
{
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_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
{
size_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 =
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);
}
}
}