bt_component_class_finalize_method finalize;
bt_component_class_query_method query;
bt_component_class_accept_port_connection_method accept_port_connection;
+ bt_component_class_port_connected_method port_connected;
bt_component_class_port_disconnected_method port_disconnected;
} methods;
/* Array of struct bt_component_class_destroy_listener */
struct bt_private_port *self_private_port,
struct bt_port *other_port);
+typedef void (*bt_component_class_port_connected_method)(
+ struct bt_private_component *private_component,
+ struct bt_private_port *self_private_port,
+ struct bt_port *other_port);
+
typedef void (*bt_component_class_port_disconnected_method)(
struct bt_private_component *private_component,
struct bt_private_port *private_port);
struct bt_component_class *component_class,
bt_component_class_accept_port_connection_method accept_port_connection_method);
+extern int bt_component_class_set_port_connected_method(
+ struct bt_component_class *component_class,
+ bt_component_class_port_connected_method port_connected_method);
+
extern int bt_component_class_set_port_disconnected_method(
struct bt_component_class *component_class,
bt_component_class_port_disconnected_method port_disconnected_method);
struct bt_component *component, struct bt_port *self_port,
struct bt_port *other_port);
+BT_HIDDEN
+void bt_component_port_connected(struct bt_component *comp,
+ struct bt_port *self_port, struct bt_port *other_port);
+
BT_HIDDEN
void bt_component_port_disconnected(struct bt_component *comp,
struct bt_port *port);
BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD = 3,
BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD = 4,
BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD = 5,
- BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD = 6,
- BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD = 7,
- BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD = 8,
- BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD = 9,
+ BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD = 7,
+ BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD = 8,
+ BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD = 9,
+ BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD = 10,
+ BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD = 11,
};
/* Component class attribute (internal use) */
/* BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD */
bt_component_class_accept_port_connection_method accept_port_connection_method;
+ /* BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD */
+ bt_component_class_port_connected_method port_connected_method;
+
/* BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD */
bt_component_class_port_disconnected_method port_disconnected_method;
#define BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD_WITH_ID(_id, _comp_class_id, _x) \
__BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE(accept_port_connection_method, BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD, _id, _comp_class_id, sink, _x)
+/*
+ * Defines a port connected method attribute attached to a specific
+ * source component class descriptor.
+ *
+ * _id: Plugin descriptor ID (C identifier).
+ * _comp_class_id: Component class descriptor ID (C identifier).
+ * _x: Port connected method
+ * (bt_component_class_port_connected_method).
+ */
+#define BT_PLUGIN_SOURCE_COMPONENT_CLASS_PORT_CONNECTED_METHOD_WITH_ID(_id, _comp_class_id, _x) \
+ __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE(port_connected_method, BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD, _id, _comp_class_id, source, _x)
+
+/*
+ * Defines a port connected method attribute attached to a specific
+ * filter component class descriptor.
+ *
+ * _id: Plugin descriptor ID (C identifier).
+ * _comp_class_id: Component class descriptor ID (C identifier).
+ * _x: Port connected method
+ * (bt_component_class_port_connected_method).
+ */
+#define BT_PLUGIN_FILTER_COMPONENT_CLASS_PORT_CONNECTED_METHOD_WITH_ID(_id, _comp_class_id, _x) \
+ __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE(port_connected_method, BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD, _id, _comp_class_id, filter, _x)
+
+/*
+ * Defines a port connected method attribute attached to a specific
+ * sink component class descriptor.
+ *
+ * _id: Plugin descriptor ID (C identifier).
+ * _comp_class_id: Component class descriptor ID (C identifier).
+ * _x: Port connected method
+ * (bt_component_class_port_connected_method).
+ */
+#define BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD_WITH_ID(_id, _comp_class_id, _x) \
+ __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE(port_connected_method, BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD, _id, _comp_class_id, sink, _x)
+
/*
* Defines a port disconnected method attribute attached to a specific
* source component class descriptor.
#define BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD(_name, _x) \
BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD_WITH_ID(auto, _name, _x)
+/*
+ * Defines a port connected method attribute attached to a source
+ * component class descriptor which is attached to the automatic plugin
+ * descriptor.
+ *
+ * _name: Component class name (C identifier).
+ * _x: Port connected (bt_component_class_port_connected_method).
+ */
+#define BT_PLUGIN_SOURCE_COMPONENT_CLASS_PORT_CONNECTED_METHOD(_name, _x) \
+ BT_PLUGIN_SOURCE_COMPONENT_CLASS_PORT_CONNECTED_METHOD_WITH_ID(auto, _name, _x)
+
+/*
+ * Defines a port connected method attribute attached to a filter
+ * component class descriptor which is attached to the automatic plugin
+ * descriptor.
+ *
+ * _name: Component class name (C identifier).
+ * _x: Port connected (bt_component_class_port_connected_method).
+ */
+#define BT_PLUGIN_FILTER_COMPONENT_CLASS_PORT_CONNECTED_METHOD(_name, _x) \
+ BT_PLUGIN_FILTER_COMPONENT_CLASS_PORT_CONNECTED_METHOD_WITH_ID(auto, _name, _x)
+
+/*
+ * Defines a port connected method attribute attached to a sink
+ * component class descriptor which is attached to the automatic plugin
+ * descriptor.
+ *
+ * _name: Component class name (C identifier).
+ * _x: Port connected (bt_component_class_port_connected_method).
+ */
+#define BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(_name, _x) \
+ BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD_WITH_ID(auto, _name, _x)
+
/*
* Defines a port disconnected method attribute attached to a source
* component class descriptor which is attached to the automatic plugin
return ret;
}
+int bt_component_class_set_port_connected_method(
+ struct bt_component_class *component_class,
+ bt_component_class_port_connected_method method)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.port_connected = method;
+
+end:
+ return ret;
+}
+
int bt_component_class_set_port_disconnected_method(
struct bt_component_class *component_class,
bt_component_class_port_disconnected_method method)
return status;
}
+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);
+
+ 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);
+ }
+}
+
BT_HIDDEN
void bt_component_port_disconnected(struct bt_component *comp,
struct bt_port *port)
struct bt_graph *downstream_graph = NULL;
struct bt_component *upstream_component = NULL;
struct bt_component *downstream_component = NULL;
- struct bt_connection *existing_conn = NULL;
enum bt_component_status component_status;
bool upstream_was_already_in_graph;
bool downstream_was_already_in_graph;
- int components_to_remove = 0;
- int i;
if (!graph || !upstream_port || !downstream_port) {
goto end;
}
/* Ensure that both ports are currently unconnected. */
- existing_conn = bt_port_get_connection(upstream_port);
- bt_put(existing_conn);
- if (existing_conn) {
+ if (bt_port_is_connected(upstream_port)) {
fprintf(stderr, "Upstream port is already connected\n");
goto end;
}
- existing_conn = bt_port_get_connection(downstream_port);
- bt_put(existing_conn);
- if (existing_conn) {
+ if (bt_port_is_connected(downstream_port)) {
fprintf(stderr, "Downstream port is already connected\n");
goto end;
}
}
downstream_was_already_in_graph = (graph == downstream_graph);
+ /*
+ * At this point the ports are not connected yet. Both
+ * components need to accept an eventual connection to their
+ * port by the other port before we continue.
+ */
+ component_status = bt_component_accept_port_connection(
+ upstream_component, upstream_port, downstream_port);
+ if (component_status != BT_COMPONENT_STATUS_OK) {
+ goto error;
+ }
+ component_status = bt_component_accept_port_connection(
+ downstream_component, downstream_port, upstream_port);
+ if (component_status != BT_COMPONENT_STATUS_OK) {
+ goto error;
+ }
+
connection = bt_connection_create(graph, upstream_port,
downstream_port);
if (!connection) {
}
/*
- * The graph is now the parent of these components which garantees their
- * existence for the duration of the graph's lifetime.
+ * The graph is now the parent of these components which
+ * garantees their existence for the duration of the graph's
+ * lifetime.
*/
/*
- * The components and connection are added to the graph before
- * invoking the `accept_port_connection` method in order to make
- * them visible to the components during the method's
- * invocation.
+ * Notify both components that their port is connected.
*/
- component_status = bt_component_accept_port_connection(
- upstream_component, upstream_port, downstream_port);
- if (component_status != BT_COMPONENT_STATUS_OK) {
- goto error_rollback;
- }
- component_status = bt_component_accept_port_connection(
- downstream_component, downstream_port, upstream_port);
- if (component_status != BT_COMPONENT_STATUS_OK) {
- goto error_rollback;
- }
+ bt_component_port_connected(upstream_component, upstream_port,
+ downstream_port);
+ bt_component_port_connected(downstream_component, downstream_port,
+ upstream_port);
/*
- * Both components accepted the connection. Notify the graph's
- * creator that both ports are connected.
+ * Notify the graph's creator that both ports are connected.
*/
bt_graph_notify_ports_connected(graph, upstream_port, downstream_port);
bt_put(upstream_component);
bt_put(downstream_component);
return connection;
-error_rollback:
- /*
- * Remove newly-added components from the graph, being careful
- * not to remove a component that was already present in the graph
- * and is connected to other components.
- */
- components_to_remove += upstream_was_already_in_graph ? 0 : 1;
- components_to_remove += downstream_was_already_in_graph ? 0 : 1;
- if (!downstream_was_already_in_graph) {
- if (bt_component_get_class_type(downstream_component) ==
- BT_COMPONENT_CLASS_TYPE_SINK) {
- g_queue_pop_tail(graph->sinks_to_consume);
- }
- }
- /* Remove newly created connection. */
- g_ptr_array_set_size(graph->connections,
- graph->connections->len - 1);
-
- /*
- * Remove newly added components.
- *
- * Note that this is a tricky situation. The graph, being the parent
- * of the components, does not hold a reference to them. Normally,
- * components are destroyed right away when the graph is released since
- * the graph, being their parent, bounds their lifetime
- * (see doc/ref-counting.md).
- *
- * In this particular case, we must take a number of steps:
- * 1) unset the components' parent to rollback the initial state of
- * the components being connected.
- * Note that the reference taken by the component on its graph is
- * released by the set_parent call.
- * 2) set the pointer in the components array to NULL so that the
- * destruction function called on the array's resize in invoked on
- * NULL (no effect),
- *
- * NOTE: Point #1 assumes that *something* holds a reference to both
- * components being connected. The fact that a reference is being
- * held to a component means that it must hold a reference to its
- * parent to prevent the parent from being destroyed (again, refer
- * to doc/red-counting.md). This reference to a component is
- * most likely being held *transitively* by the caller which holds
- * a reference to both ports (a port has its component as a
- * parent).
- *
- * This assumes that a graph is not connecting components by
- * itself while not holding a reference to the ports/components
- * being connected (i.e. "cheating" by using internal APIs).
- */
- for (i = 0; i < components_to_remove; i++) {
- struct bt_component *component = g_ptr_array_index(
- graph->components, graph->components->len - 1);
-
- bt_component_set_graph(component, NULL);
- g_ptr_array_index(graph->components,
- graph->components->len - 1) = NULL;
- g_ptr_array_set_size(graph->components,
- graph->components->len - 1);
- }
- /* NOTE: Resizing the ptr_arrays invokes the destruction of the elements. */
- goto end;
error:
BT_PUT(upstream_component);
BT_PUT(downstream_component);
bt_component_class_finalize_method finalize_method;
bt_component_class_query_method query_method;
bt_component_class_accept_port_connection_method accept_port_connection_method;
+ bt_component_class_port_connected_method port_connected_method;
bt_component_class_port_disconnected_method port_disconnected_method;
struct bt_component_class_iterator_methods iterator_methods;
};
cc_full_descr->accept_port_connection_method =
cur_cc_descr_attr->value.accept_port_connection_method;
break;
+ case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD:
+ cc_full_descr->port_connected_method =
+ cur_cc_descr_attr->value.port_connected_method;
+ break;
case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD:
cc_full_descr->port_disconnected_method =
cur_cc_descr_attr->value.port_disconnected_method;
}
}
+ if (cc_full_descr->port_connected_method) {
+ ret = bt_component_class_set_port_connected_method(
+ comp_class, cc_full_descr->port_connected_method);
+ if (ret) {
+ status = BT_PLUGIN_STATUS_ERROR;
+ BT_PUT(comp_class);
+ goto end;
+ }
+ }
+
if (cc_full_descr->port_disconnected_method) {
ret = bt_component_class_set_port_disconnected_method(
comp_class, cc_full_descr->port_disconnected_method);
BT_PLUGIN_SINK_COMPONENT_CLASS(pretty, pretty_consume);
BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(pretty, pretty_init);
BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(pretty, pretty_finalize);
-BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD(pretty,
- pretty_accept_port_connection);
+BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(pretty,
+ pretty_port_connected);
BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(pretty,
"Pretty-printing text output (`text` format of Babeltrace 1)");
}
BT_HIDDEN
-enum bt_component_status pretty_accept_port_connection(
+void pretty_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port)
{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_private_connection *connection;
struct pretty_component *pretty;
bt_private_connection_create_notification_iterator(connection);
if (!pretty->input_iterator) {
- ret = BT_COMPONENT_STATUS_ERROR;
+ pretty->error = true;
}
bt_put(connection);
- return ret;
}
BT_HIDDEN
bt_private_component_get_user_data(component);
enum bt_notification_iterator_status it_ret;
- it = pretty->input_iterator;
+ if (unlikely(pretty->error)) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ it = pretty->input_iterator;
it_ret = bt_notification_iterator_next(it);
+
switch (it_ret) {
case BT_NOTIFICATION_ITERATOR_STATUS_ERROR:
ret = BT_COMPONENT_STATUS_ERROR;
GString *string;
struct bt_value *plugin_opt_map; /* Temporary parameter map. */
bool use_colors;
+ bool error;
uint64_t last_cycles_timestamp;
uint64_t delta_cycles;
enum bt_component_status pretty_consume(struct bt_private_component *component);
BT_HIDDEN
-enum bt_component_status pretty_accept_port_connection(
+void pretty_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port);
#include <babeltrace/graph/component-sink.h>
#include <babeltrace/graph/notification-iterator.h>
#include <babeltrace/graph/notification.h>
+#include <babeltrace/babeltrace-internal.h>
#include <plugins-common.h>
#include <assert.h>
#include "dummy.h"
return ret;
}
-enum bt_component_status dummy_accept_port_connection(
+void dummy_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port)
{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct dummy *dummy;
struct bt_notification_iterator *iterator;
struct bt_private_connection *connection;
dummy = bt_private_component_get_user_data(component);
assert(dummy);
-
connection = bt_private_port_get_private_connection(self_port);
assert(connection);
-
iterator = bt_private_connection_create_notification_iterator(
connection);
if (!iterator) {
- ret = BT_COMPONENT_STATUS_ERROR;
+ dummy->error = true;
goto end;
}
g_ptr_array_add(dummy->iterators, iterator);
+
end:
bt_put(connection);
- return ret;
}
enum bt_component_status dummy_consume(struct bt_private_component *component)
dummy = bt_private_component_get_user_data(component);
assert(dummy);
+ if (unlikely(dummy->error)) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
/* Consume one notification from each iterator. */
for (i = 0; i < dummy->iterators->len; i++) {
struct bt_notification_iterator *it;
#include <babeltrace/graph/private-component.h>
#include <babeltrace/graph/private-port.h>
#include <babeltrace/graph/port.h>
+#include <stdbool.h>
struct dummy {
GPtrArray *iterators;
+ bool error;
};
enum bt_component_status dummy_init(struct bt_private_component *component,
struct bt_value *params, void *init_method_data);
void dummy_finalize(struct bt_private_component *component);
-enum bt_component_status dummy_accept_port_connection(
- struct bt_private_component *component,
+void dummy_port_connected(struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port);
enum bt_component_status dummy_consume(struct bt_private_component *component);
BT_PLUGIN_SINK_COMPONENT_CLASS(dummy, dummy_consume);
BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(dummy, dummy_init);
BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(dummy, dummy_finalize);
-BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD(dummy, dummy_accept_port_connection);
+BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(dummy,
+ dummy_port_connected);
BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(dummy,
"Dummy sink component class: does absolutely nothing!");
}
static
-enum bt_component_status writer_component_accept_port_connection(
+void writer_component_port_connected(
struct bt_private_component *component,
struct bt_private_port *self_port,
struct bt_port *other_port)
{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_private_connection *connection;
struct writer_component *writer;
bt_private_connection_create_notification_iterator(connection);
if (!writer->input_iterator) {
- ret = BT_COMPONENT_STATUS_ERROR;
+ writer->error = true;
}
+
bt_put(connection);
- return ret;
}
static
it = writer_component->input_iterator;
assert(it);
+ if (unlikely(writer_component->error)) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
if (likely(writer_component->processed_first_event)) {
enum bt_notification_iterator_status it_ret;
BT_PLUGIN_LICENSE("MIT");
BT_PLUGIN_SINK_COMPONENT_CLASS(writer, run);
BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(writer, writer_component_init);
-BT_PLUGIN_SINK_COMPONENT_CLASS_ACCEPT_PORT_CONNECTION_METHOD(writer,
- writer_component_accept_port_connection);
+BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(writer,
+ writer_component_port_connected);
BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(writer, finalize_writer_component);
BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(writer, "Formats CTF-IR to CTF.");
FILE *err;
struct bt_notification_iterator *input_iterator;
bool processed_first_event;
+ bool error;
};
BT_HIDDEN