#include <babeltrace/component/component.h>
#include <babeltrace/component/component-internal.h>
-#include <babeltrace/component/source-internal.h>
-#include <babeltrace/component/filter-internal.h>
+#include <babeltrace/component/component-class-internal.h>
+#include <babeltrace/component/component-source-internal.h>
+#include <babeltrace/component/component-filter-internal.h>
+#include <babeltrace/component/component-sink-internal.h>
+#include <babeltrace/component/graph-internal.h>
#include <babeltrace/component/notification/iterator-internal.h>
-#include <babeltrace/component/sink-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/compiler.h>
#include <babeltrace/ref.h>
static
struct bt_component * (* const component_create_funcs[])(
struct bt_component_class *, struct bt_value *) = {
- [BT_COMPONENT_TYPE_SOURCE] = bt_component_source_create,
- [BT_COMPONENT_TYPE_SINK] = bt_component_sink_create,
- [BT_COMPONENT_TYPE_FILTER] = bt_component_filter_create,
+ [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,
};
static
enum bt_component_status (* const component_validation_funcs[])(
struct bt_component *) = {
- [BT_COMPONENT_TYPE_SOURCE] = bt_component_source_validate,
- [BT_COMPONENT_TYPE_SINK] = bt_component_sink_validate,
- [BT_COMPONENT_TYPE_FILTER] = bt_component_filter_validate,
+ [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
* User data is destroyed first, followed by the concrete component
* instance.
*/
- if (component->user_destroy) {
- component->user_destroy(component);
+ if (component->class->methods.destroy) {
+ component->class->methods.destroy(component);
}
if (component->destroy) {
BT_HIDDEN
enum bt_component_status bt_component_init(struct bt_component *component,
- bt_component_destroy_cb destroy)
+ bt_component_class_destroy_method destroy)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
goto end;
}
+ component->initializing = true;
component->destroy = destroy;
end:
return ret;
}
-BT_HIDDEN
-enum bt_component_type bt_component_get_type(struct bt_component *component)
+enum bt_component_class_type bt_component_get_class_type(
+ struct bt_component *component)
{
- return component ? component->class->type : BT_COMPONENT_TYPE_UNKNOWN;
+ return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
}
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_type component_type;
+ enum bt_component_class_type type;
struct bt_notification_iterator *iterator = NULL;
+ struct bt_component_class *class = component->class;
if (!component) {
goto error;
}
- component_type = bt_component_get_type(component);
- if (component_type != BT_COMPONENT_TYPE_SOURCE &&
- component_type != BT_COMPONENT_TYPE_FILTER) {
+ type = bt_component_get_class_type(component);
+ if (type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
+ type != BT_COMPONENT_CLASS_TYPE_FILTER) {
/* Unsupported operation. */
goto error;
}
goto error;
}
- switch (component_type) {
- case BT_COMPONENT_TYPE_SOURCE:
+ switch (type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
{
- struct bt_component_source *source;
- enum bt_component_status ret_component;
-
- source = container_of(component, struct bt_component_source, parent);
- assert(source->init_iterator);
- ret_component = source->init_iterator(component, iterator);
- if (ret_component != BT_COMPONENT_STATUS_OK) {
- goto error;
- }
- break;
+ struct bt_component_class_source *source_class;
+ enum bt_notification_iterator_status status;
+ source_class = container_of(class, struct bt_component_class_source, parent);
+
+ 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_TYPE_FILTER:
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
{
- struct bt_component_filter *filter;
- enum bt_component_status ret_component;
-
- filter = container_of(component, struct bt_component_filter, parent);
- assert(filter->init_iterator);
- ret_component = filter->init_iterator(component, iterator);
- if (ret_component != BT_COMPONENT_STATUS_OK) {
- goto error;
+ struct bt_component_class_filter *filter_class;
+ enum bt_notification_iterator_status status;
+
+ filter_class = container_of(class, struct bt_component_class_filter, parent);
+
+ if (filter_class->methods.iterator.init) {
+ status = filter_class->methods.iterator.init(component,
+ iterator, init_method_data);
+ if (status < 0) {
+ goto error;
+ }
}
break;
}
return iterator;
}
-struct bt_component *bt_component_create(
+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_type type;
+ enum bt_component_class_type type;
if (!component_class) {
goto end;
}
type = bt_component_class_get_type(component_class);
- if (type <= BT_COMPONENT_TYPE_UNKNOWN ||
- type > BT_COMPONENT_TYPE_FILTER) {
+ if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
+ type > BT_COMPONENT_CLASS_TYPE_FILTER) {
goto end;
}
goto end;
}
- component->initializing = true;
- ret = component_class->init(component, params);
- component->initializing = false;
- if (ret != BT_COMPONENT_STATUS_OK) {
- BT_PUT(component);
- goto end;
+ if (component_class->methods.init) {
+ ret = component_class->methods.init(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:
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;
goto end;
}
- ret = component->name->str;
+ ret = component->name->len == 0 ? NULL : component->name->str;
end:
return ret;
}
return ret;
}
-enum bt_component_status bt_component_set_destroy_cb(
- struct bt_component *component, bt_component_destroy_cb destroy)
+BT_HIDDEN
+void bt_component_set_graph(struct bt_component *component,
+ struct bt_graph *graph)
{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_object *parent = bt_object_get_parent(&component->base);
- if (!component || !component->initializing) {
- ret = BT_COMPONENT_STATUS_INVALID;
+ 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);
+}
+
+BT_HIDDEN
+int bt_component_init_input_ports(struct bt_component *component,
+ GPtrArray **input_ports)
+{
+ int ret = 0;
+ struct bt_port *default_port;
+
+ *input_ports = g_ptr_array_new_with_free_func(bt_object_release);
+ if (!*input_ports) {
+ ret = -1;
goto end;
}
- component->user_destroy = destroy;
+ default_port = bt_component_add_port(component, *input_ports,
+ BT_PORT_TYPE_INPUT, DEFAULT_INPUT_PORT_NAME);
+ if (!default_port) {
+ ret = -1;
+ goto end;
+ }
+ bt_put(default_port);
end:
return ret;
}
+
+BT_HIDDEN
+int bt_component_init_output_ports(struct bt_component *component,
+ GPtrArray **output_ports)
+{
+ int ret = 0;
+ struct bt_port *default_port;
+
+ *output_ports = g_ptr_array_new_with_free_func(bt_object_release);
+ if (!*output_ports) {
+ ret = -1;
+ goto end;
+ }
+
+ default_port = bt_component_add_port(component, *output_ports,
+ BT_PORT_TYPE_OUTPUT, DEFAULT_OUTPUT_PORT_NAME);
+ if (!default_port) {
+ ret = -1;
+ goto end;
+ }
+ bt_put(default_port);
+end:
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
+{
+ size_t i;
+ struct bt_port *ret_port = NULL;
+
+ 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_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_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 (!component->initializing || !name || *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
+enum bt_component_status bt_component_remove_port(
+ struct bt_component *component, GPtrArray *ports,
+ const char *name)
+{
+ size_t i;
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ if (!component->initializing || !name) {
+ status = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ 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)) {
+ g_ptr_array_remove_index(ports, i);
+ goto end;
+ }
+ }
+ status = BT_COMPONENT_STATUS_NOT_FOUND;
+end:
+ return status;
+}
+
+BT_HIDDEN
+enum bt_component_status bt_component_new_connection(
+ struct bt_component *component, struct bt_port *own_port,
+ struct bt_connection *connection)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ if (component->class->methods.new_connection_method) {
+ status = component->class->methods.new_connection_method(
+ own_port, connection);
+ }
+
+ return status;
+}