lib/Makefile
lib/prio_heap/Makefile
lib/plugin/Makefile
- lib/component/Makefile
- lib/component/notification/Makefile
+ lib/graph/Makefile
+ lib/graph/notification/Makefile
lib/ctf-ir/Makefile
lib/ctf-writer/Makefile
include/Makefile
-SUBDIRS = ctf-ir ctf-writer prio_heap plugin component .
+SUBDIRS = ctf-ir ctf-writer prio_heap plugin graph .
AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
libbabeltrace_la_LIBADD = \
prio_heap/libprio_heap.la \
$(top_builddir)/compat/libcompat.la \
- component/libcomponent.la \
+ graph/libgraph.la \
plugin/libplugin.la \
$(top_builddir)/common/libbabeltrace-common.la \
ctf-ir/libctf-ir.la \
+++ /dev/null
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
-
-SUBDIRS = notification
-
-noinst_LTLIBRARIES = libcomponent.la
-
-# Plug-in system library
-libcomponent_la_SOURCES = \
- clock-class-priority-map.c \
- component.c \
- component-class.c \
- graph.c \
- connection.c \
- port.c \
- source.c \
- sink.c \
- filter.c \
- iterator.c
-
-libcomponent_la_LIBADD = \
- notification/libcomponent-notification.la
+++ /dev/null
-/*
- * clock-class-priority-map.c
- *
- * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/graph/clock-class-priority-map.h>
-#include <babeltrace/graph/clock-class-priority-map-internal.h>
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/ctf-ir/clock-class-internal.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/ref.h>
-#include <glib.h>
-
-static
-void bt_clock_class_priority_map_destroy(struct bt_object *obj)
-{
- struct bt_clock_class_priority_map *cc_prio_map = (void *) obj;
-
- if (!cc_prio_map) {
- return;
- }
-
- if (cc_prio_map->entries) {
- g_ptr_array_free(cc_prio_map->entries, TRUE);
- }
-
- if (cc_prio_map->prios) {
- g_hash_table_destroy(cc_prio_map->prios);
- }
-
- g_free(cc_prio_map);
-}
-
-struct bt_clock_class_priority_map *bt_clock_class_priority_map_create()
-{
- struct bt_clock_class_priority_map *cc_prio_map = NULL;
-
- cc_prio_map = g_new0(struct bt_clock_class_priority_map, 1);
- if (!cc_prio_map) {
- goto error;
- }
-
- bt_object_init(cc_prio_map, bt_clock_class_priority_map_destroy);
- cc_prio_map->entries = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_put);
- if (!cc_prio_map->entries) {
- goto error;
- }
-
- cc_prio_map->prios = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) g_free);
- if (!cc_prio_map->entries) {
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(cc_prio_map);
-
-end:
- return cc_prio_map;
-}
-
-int bt_clock_class_priority_map_get_clock_class_count(
- struct bt_clock_class_priority_map *cc_prio_map)
-{
- int ret = -1;
-
- if (!cc_prio_map) {
- goto end;
- }
-
- ret = (int) cc_prio_map->entries->len;
-
-end:
- return ret;
-}
-
-struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class(
- struct bt_clock_class_priority_map *cc_prio_map,
- unsigned int index)
-{
- struct bt_ctf_clock_class *clock_class = NULL;
-
- if (!cc_prio_map || index >= cc_prio_map->entries->len) {
- goto end;
- }
-
- clock_class = g_ptr_array_index(cc_prio_map->entries, index);
- bt_get(clock_class);
-
-end:
- return clock_class;
-}
-
-struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class_by_name(
- struct bt_clock_class_priority_map *cc_prio_map,
- const char *name)
-{
- size_t i;
- struct bt_ctf_clock_class *clock_class = NULL;
-
- if (!cc_prio_map || !name) {
- goto end;
- }
-
- for (i = 0; i < cc_prio_map->entries->len; i++) {
- struct bt_ctf_clock_class *cur_cc =
- g_ptr_array_index(cc_prio_map->entries, i);
- // FIXME when available: use bt_ctf_clock_class_get_name()
- const char *cur_cc_name =
- cur_cc->name ? cur_cc->name->str : NULL;
-
- if (!cur_cc_name) {
- goto end;
- }
-
- if (strcmp(cur_cc_name, name) == 0) {
- clock_class = bt_get(cur_cc);
- goto end;
- }
- }
-
-end:
- return clock_class;
-}
-
-
-struct clock_class_prio {
- uint64_t prio;
- struct bt_ctf_clock_class *clock_class;
-};
-
-static
-void current_highest_prio_gh_func(gpointer key, gpointer value,
- gpointer user_data)
-{
- struct clock_class_prio *func_data = user_data;
- uint64_t *prio = value;
-
- if (*prio <= func_data->prio) {
- func_data->prio = *prio;
- func_data->clock_class = key;
- }
-}
-
-static
-struct clock_class_prio bt_ctf_clock_class_priority_map_current_highest_prio(
- struct bt_clock_class_priority_map *cc_prio_map)
-{
- struct clock_class_prio func_data = {
- .prio = -1ULL,
- .clock_class = NULL,
- };
-
- g_hash_table_foreach(cc_prio_map->prios, current_highest_prio_gh_func,
- &func_data);
- return func_data;
-}
-
-struct bt_ctf_clock_class *
-bt_clock_class_priority_map_get_highest_priority_clock_class(
- struct bt_clock_class_priority_map *cc_prio_map)
-{
- struct bt_ctf_clock_class *clock_class = NULL;
-
- if (!cc_prio_map) {
- goto end;
- }
-
- clock_class = bt_get(cc_prio_map->highest_prio_cc);
-
-end:
- return clock_class;
-}
-
-int bt_clock_class_priority_map_get_clock_class_priority(
- struct bt_clock_class_priority_map *cc_prio_map,
- struct bt_ctf_clock_class *clock_class, uint64_t *priority)
-{
- int ret = 0;
- uint64_t *prio;
-
- if (!cc_prio_map || !clock_class || !priority) {
- ret = -1;
- goto end;
- }
-
- prio = g_hash_table_lookup(cc_prio_map->prios, clock_class);
- if (!prio) {
- ret = -1;
- goto end;
- }
-
- *priority = *prio;
-
-end:
- return ret;
-}
-
-int bt_clock_class_priority_map_add_clock_class(
- struct bt_clock_class_priority_map *cc_prio_map,
- struct bt_ctf_clock_class *clock_class, uint64_t priority)
-{
- int ret = 0;
- uint64_t *prio_ptr = NULL;
- struct clock_class_prio cc_prio;
-
- // FIXME when available: check
- // bt_ctf_clock_class_is_valid(clock_class)
- if (!cc_prio_map) {
- ret = -1;
- goto end;
- }
-
- /* Check for duplicate clock classes */
- prio_ptr = g_hash_table_lookup(cc_prio_map->prios, clock_class);
- if (prio_ptr) {
- prio_ptr = NULL;
- ret = -1;
- goto end;
- }
-
- prio_ptr = g_new(uint64_t, 1);
- if (!prio_ptr) {
- ret = -1;
- goto end;
- }
-
- *prio_ptr = priority;
- bt_get(clock_class);
- g_ptr_array_add(cc_prio_map->entries, clock_class);
- g_hash_table_insert(cc_prio_map->prios, clock_class, prio_ptr);
- prio_ptr = NULL;
- cc_prio = bt_ctf_clock_class_priority_map_current_highest_prio(
- cc_prio_map);
- assert(cc_prio.clock_class);
- cc_prio_map->highest_prio_cc = cc_prio.clock_class;
-
-end:
- if (prio_ptr) {
- g_free(prio_ptr);
- }
-
- return ret;
-}
+++ /dev/null
-/*
- * component-class.c
- *
- * Babeltrace Plugin Component Class
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/graph/component-class-internal.h>
-#include <babeltrace/ref.h>
-#include <stdbool.h>
-#include <glib.h>
-
-static
-void bt_component_class_destroy(struct bt_object *obj)
-{
- struct bt_component_class *class;
- int i;
-
- assert(obj);
- class = container_of(obj, struct bt_component_class, base);
-
- /* Call destroy listeners in reverse registration order */
- for (i = class->destroy_listeners->len - 1; i >= 0; i--) {
- struct bt_component_class_destroy_listener *listener =
- &g_array_index(class->destroy_listeners,
- struct bt_component_class_destroy_listener,
- i);
-
- listener->func(class, listener->data);
- }
-
- if (class->name) {
- g_string_free(class->name, TRUE);
- }
- if (class->description) {
- g_string_free(class->description, TRUE);
- }
- if (class->help) {
- g_string_free(class->help, TRUE);
- }
- if (class->destroy_listeners) {
- g_array_free(class->destroy_listeners, TRUE);
- }
-
- g_free(class);
-}
-
-static
-int bt_component_class_init(struct bt_component_class *class,
- enum bt_component_class_type type, const char *name)
-{
- int ret = 0;
-
- bt_object_init(class, bt_component_class_destroy);
- class->type = type;
- class->name = g_string_new(name);
- if (!class->name) {
- goto error;
- }
-
- class->description = g_string_new(NULL);
- if (!class->description) {
- goto error;
- }
-
- class->help = g_string_new(NULL);
- if (!class->help) {
- goto error;
- }
-
- class->destroy_listeners = g_array_new(FALSE, TRUE,
- sizeof(struct bt_component_class_destroy_listener));
- if (!class->destroy_listeners) {
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(class);
- ret = -1;
-
-end:
- return ret;
-}
-
-struct bt_component_class *bt_component_class_source_create(const char *name,
- bt_component_class_notification_iterator_next_method notification_iterator_next_method)
-{
- struct bt_component_class_source *source_class = NULL;
- int ret;
-
- if (!name || !notification_iterator_next_method) {
- goto end;
- }
-
- source_class = g_new0(struct bt_component_class_source, 1);
- if (!source_class) {
- goto end;
- }
-
- ret = bt_component_class_init(&source_class->parent,
- BT_COMPONENT_CLASS_TYPE_SOURCE, name);
- if (ret) {
- /*
- * If bt_component_class_init() fails, the component
- * class is put, therefore its memory is already
- * freed.
- */
- source_class = NULL;
- goto end;
- }
-
- source_class->methods.iterator.next = notification_iterator_next_method;
-
-end:
- return &source_class->parent;
-}
-
-struct bt_component_class *bt_component_class_filter_create(const char *name,
- bt_component_class_notification_iterator_next_method notification_iterator_next_method)
-{
- struct bt_component_class_filter *filter_class = NULL;
- int ret;
-
- if (!name || !notification_iterator_next_method) {
- goto end;
- }
-
- filter_class = g_new0(struct bt_component_class_filter, 1);
- if (!filter_class) {
- goto end;
- }
-
- ret = bt_component_class_init(&filter_class->parent,
- BT_COMPONENT_CLASS_TYPE_FILTER, name);
- if (ret) {
- /*
- * If bt_component_class_init() fails, the component
- * class is put, therefore its memory is already
- * freed.
- */
- filter_class = NULL;
- goto end;
- }
-
- filter_class->methods.iterator.next = notification_iterator_next_method;
-
-end:
- return &filter_class->parent;
-}
-
-struct bt_component_class *bt_component_class_sink_create(const char *name,
- bt_component_class_sink_consume_method consume_method)
-{
- struct bt_component_class_sink *sink_class = NULL;
- int ret;
-
- if (!name || !consume_method) {
- goto end;
- }
-
- sink_class = g_new0(struct bt_component_class_sink, 1);
- if (!sink_class) {
- goto end;
- }
-
- ret = bt_component_class_init(&sink_class->parent,
- BT_COMPONENT_CLASS_TYPE_SINK, name);
- if (ret) {
- /*
- * If bt_component_class_init() fails, the component
- * class is put, therefore its memory is already
- * freed.
- */
- sink_class = NULL;
- goto end;
- }
-
- sink_class->methods.consume = consume_method;
-
-end:
- return &sink_class->parent;
-}
-
-int bt_component_class_set_init_method(
- struct bt_component_class *component_class,
- bt_component_class_init_method init_method)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !init_method) {
- ret = -1;
- goto end;
- }
-
- component_class->methods.init = init_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_set_query_method(
- struct bt_component_class *component_class,
- bt_component_class_query_method query_method)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !query_method) {
- ret = -1;
- goto end;
- }
-
- component_class->methods.query = query_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_set_accept_port_connection_method(
- struct bt_component_class *component_class,
- bt_component_class_accept_port_connection_method method)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !method) {
- ret = -1;
- goto end;
- }
-
- component_class->methods.accept_port_connection = 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)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !method) {
- ret = -1;
- goto end;
- }
-
- component_class->methods.port_disconnected = method;
-
-end:
- return ret;
-}
-
-int bt_component_class_set_finalize_method(
- struct bt_component_class *component_class,
- bt_component_class_finalize_method finalize_method)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !finalize_method) {
- ret = -1;
- goto end;
- }
-
- component_class->methods.finalize = finalize_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_source_set_notification_iterator_init_method(
- struct bt_component_class *component_class,
- bt_component_class_notification_iterator_init_method notification_iterator_init_method)
-{
- struct bt_component_class_source *source_class;
- int ret = 0;
-
- if (!component_class || component_class->frozen ||
- !notification_iterator_init_method ||
- component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- ret = -1;
- goto end;
- }
-
- source_class = container_of(component_class,
- struct bt_component_class_source, parent);
- source_class->methods.iterator.init = notification_iterator_init_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_source_set_notification_iterator_finalize_method(
- struct bt_component_class *component_class,
- bt_component_class_notification_iterator_finalize_method notification_iterator_finalize_method)
-{
- struct bt_component_class_source *source_class;
- int ret = 0;
-
- if (!component_class || component_class->frozen ||
- !notification_iterator_finalize_method ||
- component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- ret = -1;
- goto end;
- }
-
- source_class = container_of(component_class,
- struct bt_component_class_source, parent);
- source_class->methods.iterator.finalize =
- notification_iterator_finalize_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_source_set_notification_iterator_seek_time_method(
- struct bt_component_class *component_class,
- bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
-{
- struct bt_component_class_source *source_class;
- int ret = 0;
-
- if (!component_class || component_class->frozen ||
- !notification_iterator_seek_time_method ||
- component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- ret = -1;
- goto end;
- }
-
- source_class = container_of(component_class,
- struct bt_component_class_source, parent);
- source_class->methods.iterator.seek_time =
- notification_iterator_seek_time_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_filter_set_notification_iterator_init_method(
- struct bt_component_class *component_class,
- bt_component_class_notification_iterator_init_method notification_iterator_init_method)
-{
- struct bt_component_class_filter *filter_class;
- int ret = 0;
-
- if (!component_class || component_class->frozen ||
- !notification_iterator_init_method ||
- component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- ret = -1;
- goto end;
- }
-
- filter_class = container_of(component_class,
- struct bt_component_class_filter, parent);
- filter_class->methods.iterator.init = notification_iterator_init_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_filter_set_notification_iterator_finalize_method(
- struct bt_component_class *component_class,
- bt_component_class_notification_iterator_finalize_method notification_iterator_finalize_method)
-{
- struct bt_component_class_filter *filter_class;
- int ret = 0;
-
- if (!component_class || component_class->frozen ||
- !notification_iterator_finalize_method ||
- component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- ret = -1;
- goto end;
- }
-
- filter_class = container_of(component_class,
- struct bt_component_class_filter, parent);
- filter_class->methods.iterator.finalize =
- notification_iterator_finalize_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_filter_set_notification_iterator_seek_time_method(
- struct bt_component_class *component_class,
- bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
-{
- struct bt_component_class_filter *filter_class;
- int ret = 0;
-
- if (!component_class || component_class->frozen ||
- !notification_iterator_seek_time_method ||
- component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- ret = -1;
- goto end;
- }
-
- filter_class = container_of(component_class,
- struct bt_component_class_filter, parent);
- filter_class->methods.iterator.seek_time =
- notification_iterator_seek_time_method;
-
-end:
- return ret;
-}
-
-int bt_component_class_set_description(
- struct bt_component_class *component_class,
- const char *description)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !description) {
- ret = -1;
- goto end;
- }
-
- g_string_assign(component_class->description, description);
-
-end:
- return ret;
-}
-
-int bt_component_class_set_help(
- struct bt_component_class *component_class,
- const char *help)
-{
- int ret = 0;
-
- if (!component_class || component_class->frozen || !help) {
- ret = -1;
- goto end;
- }
-
- g_string_assign(component_class->help, help);
-
-end:
- return ret;
-}
-
-const char *bt_component_class_get_name(
- struct bt_component_class *component_class)
-{
- return component_class ? component_class->name->str : NULL;
-}
-
-enum bt_component_class_type bt_component_class_get_type(
- struct bt_component_class *component_class)
-{
- return component_class ? component_class->type :
- BT_COMPONENT_CLASS_TYPE_UNKNOWN;
-}
-
-const char *bt_component_class_get_description(
- struct bt_component_class *component_class)
-{
- return component_class && component_class->description &&
- component_class->description->str[0] != '\0' ?
- component_class->description->str : NULL;
-}
-
-const char *bt_component_class_get_help(
- struct bt_component_class *component_class)
-{
- return component_class && component_class->help &&
- component_class->help->str[0] != '\0' ?
- component_class->help->str : NULL;
-}
-
-BT_HIDDEN
-int bt_component_class_add_destroy_listener(struct bt_component_class *class,
- bt_component_class_destroy_listener_func func, void *data)
-{
- int ret = 0;
- struct bt_component_class_destroy_listener listener;
-
- if (!class || class->frozen || !func) {
- ret = -1;
- goto end;
- }
-
- listener.func = func;
- listener.data = data;
- g_array_append_val(class->destroy_listeners, listener);
-
-end:
- return ret;
-}
-
-int bt_component_class_freeze(
- struct bt_component_class *component_class)
-{
- int ret = 0;
-
- if (!component_class) {
- ret = -1;
- goto end;
- }
-
- component_class->frozen = true;
-
-end:
- return ret;
-}
-
-struct bt_value *bt_component_class_query(
- struct bt_component_class *component_class,
- const char *object, struct bt_value *params)
-{
- struct bt_value *results = NULL;
-
- if (!component_class || !object || !params ||
- !component_class->methods.query) {
- goto end;
- }
-
- results = component_class->methods.query(component_class,
- object, params);
-
-end:
- return results;
-}
+++ /dev/null
-/*
- * component.c
- *
- * Babeltrace Plugin Component
- *
- * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/graph/private-component.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/component-class-internal.h>
-#include <babeltrace/graph/component-source-internal.h>
-#include <babeltrace/graph/component-filter-internal.h>
-#include <babeltrace/graph/component-sink-internal.h>
-#include <babeltrace/graph/private-connection.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/babeltrace-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/ref.h>
-
-static
-struct bt_component * (* const component_create_funcs[])(
- struct bt_component_class *, struct bt_value *) = {
- [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
-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 *) = {
- [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)
-{
- struct bt_component *component = NULL;
- struct bt_component_class *component_class = NULL;
-
- if (!obj) {
- return;
- }
-
- component = container_of(obj, struct bt_component, base);
- component_class = component->class;
-
- /*
- * User data is destroyed first, followed by the concrete component
- * instance.
- */
- if (component->class->methods.finalize) {
- component->class->methods.finalize(
- bt_private_component_from_component(component));
- }
-
- if (component->destroy) {
- component->destroy(component);
- }
-
- if (component->input_ports) {
- g_ptr_array_free(component->input_ports, TRUE);
- }
-
- if (component->output_ports) {
- g_ptr_array_free(component->output_ports, TRUE);
- }
-
- g_string_free(component->name, TRUE);
- bt_put(component_class);
- g_free(component);
-}
-
-struct bt_component *bt_component_from_private_component(
- struct bt_private_component *private_component)
-{
- return bt_get(bt_component_from_private(private_component));
-}
-
-enum bt_component_class_type bt_component_get_class_type(
- struct bt_component *component)
-{
- return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
-}
-
-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;
- struct bt_graph *graph = 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);
-
- /*
- * Notify the graph's creator that a new port was added.
- */
- graph = bt_component_get_graph(component);
- if (graph) {
- bt_graph_notify_port_added(graph, new_port);
- BT_PUT(graph);
- }
-
-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, 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) {
- goto end;
- }
-
- component = component_create_funcs[type](component_class, params);
- if (!component) {
- goto end;
- }
-
- 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(
- 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(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;
-
- if (!component) {
- 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_component_class *bt_component_get_class(
- struct bt_component *component)
-{
- return component ? bt_get(component->class) : NULL;
-}
-
-void *bt_private_component_get_user_data(
- struct bt_private_component *private_component)
-{
- struct bt_component *component =
- bt_component_from_private(private_component);
-
- return component ? component->user_data : NULL;
-}
-
-enum bt_component_status bt_private_component_set_user_data(
- struct bt_private_component *private_component,
- void *data)
-{
- struct bt_component *component =
- bt_component_from_private(private_component);
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
- if (!component || !component->initializing) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- component->user_data = data;
-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;
- struct bt_graph *graph;
-
- 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);
- }
-
- /* 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);
-
- /*
- * Notify the graph's creator that a port is removed.
- */
- graph = bt_component_get_graph(component);
- if (graph) {
- bt_graph_notify_port_removed(graph, component, port);
- BT_PUT(graph);
- }
-}
-
-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 *self_port,
- struct bt_port *other_port)
-{
- enum bt_component_status status = BT_COMPONENT_STATUS_OK;
-
- assert(comp);
- assert(self_port);
- assert(other_port);
-
- if (comp->class->methods.accept_port_connection) {
- status = comp->class->methods.accept_port_connection(
- bt_private_component_from_component(comp),
- bt_private_port_from_port(self_port),
- other_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(
- bt_private_component_from_component(comp),
- bt_private_port_from_port(port));
- }
-}
+++ /dev/null
-/*
- * connection.c
- *
- * Babeltrace Connection
- *
- * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/graph/notification-iterator-internal.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/component-source-internal.h>
-#include <babeltrace/graph/component-filter-internal.h>
-#include <babeltrace/graph/connection-internal.h>
-#include <babeltrace/graph/private-connection.h>
-#include <babeltrace/graph/graph-internal.h>
-#include <babeltrace/graph/port-internal.h>
-#include <babeltrace/object-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <glib.h>
-
-static
-void bt_connection_destroy(struct bt_object *obj)
-{
- struct bt_connection *connection = container_of(obj,
- struct bt_connection, base);
-
- /*
- * No bt_put on ports as a connection only holds _weak_ references
- * to them.
- */
- g_free(connection);
-}
-
-struct bt_connection *bt_connection_from_private_connection(
- struct bt_private_connection *private_connection)
-{
- return bt_get(bt_connection_from_private(private_connection));
-}
-
-BT_HIDDEN
-struct bt_connection *bt_connection_create(
- struct bt_graph *graph,
- struct bt_port *upstream_port,
- struct bt_port *downstream_port)
-{
- struct bt_connection *connection = NULL;
-
- if (bt_port_get_type(upstream_port) != BT_PORT_TYPE_OUTPUT) {
- goto end;
- }
- if (bt_port_get_type(downstream_port) != BT_PORT_TYPE_INPUT) {
- goto end;
- }
-
- connection = g_new0(struct bt_connection, 1);
- if (!connection) {
- goto end;
- }
-
- bt_object_init(connection, bt_connection_destroy);
- /* Weak references are taken, see comment in header. */
- connection->upstream_port = upstream_port;
- connection->downstream_port = downstream_port;
- bt_port_set_connection(upstream_port, connection);
- bt_port_set_connection(downstream_port, connection);
- bt_object_set_parent(connection, &graph->base);
-end:
- return connection;
-}
-
-BT_HIDDEN
-void bt_connection_disconnect_ports(struct bt_connection *conn)
-{
- struct bt_component *downstream_comp = NULL;
- struct bt_component *upstream_comp = NULL;
- struct bt_port *downstream_port = conn->downstream_port;
- struct bt_port *upstream_port = conn->upstream_port;
- struct bt_graph *graph = (void *) bt_object_get_parent(conn);
-
- if (downstream_port) {
- downstream_comp = bt_port_get_component(downstream_port);
- bt_port_set_connection(downstream_port, NULL);
- conn->downstream_port = NULL;
- }
-
- if (upstream_port) {
- upstream_comp = bt_port_get_component(upstream_port);
- bt_port_set_connection(upstream_port, NULL);
- conn->upstream_port = NULL;
- }
-
- if (downstream_comp) {
- bt_component_port_disconnected(downstream_comp,
- downstream_port);
- }
-
- if (upstream_comp) {
- bt_component_port_disconnected(upstream_comp, upstream_port);
- }
-
- assert(graph);
- bt_graph_notify_ports_disconnected(graph, upstream_comp,
- downstream_comp, upstream_port, downstream_port);
- bt_put(downstream_comp);
- bt_put(upstream_comp);
- bt_put(graph);
-}
-
-struct bt_port *bt_connection_get_upstream_port(
- struct bt_connection *connection)
-{
- return connection ? bt_get(connection->upstream_port) : NULL;
-}
-
-struct bt_port *bt_connection_get_downstream_port(
- struct bt_connection *connection)
-{
- return connection ? bt_get(connection->downstream_port) : NULL;
-}
-
-struct bt_notification_iterator *
-bt_private_connection_create_notification_iterator(
- struct bt_private_connection *private_connection)
-{
- enum bt_notification_iterator_status ret_iterator;
- enum bt_component_class_type upstream_comp_class_type;
- struct bt_notification_iterator *iterator = NULL;
- struct bt_port *upstream_port = NULL;
- struct bt_component *upstream_component = NULL;
- struct bt_component_class *upstream_comp_class = NULL;
- struct bt_connection *connection = NULL;
- bt_component_class_notification_iterator_init_method init_method = NULL;
-
- if (!private_connection) {
- goto error;
- }
-
- connection = bt_connection_from_private(private_connection);
-
- if (!connection->upstream_port || !connection->downstream_port) {
- goto error;
- }
-
- upstream_port = connection->upstream_port;
- assert(upstream_port);
- upstream_component = bt_port_get_component(upstream_port);
- assert(upstream_component);
- upstream_comp_class = upstream_component->class;
-
- if (!upstream_component) {
- goto error;
- }
-
- upstream_comp_class_type =
- bt_component_get_class_type(upstream_component);
- if (upstream_comp_class_type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
- upstream_comp_class_type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- /* Unsupported operation. */
- goto error;
- }
-
- iterator = bt_notification_iterator_create(upstream_component);
- if (!iterator) {
- goto error;
- }
-
- switch (upstream_comp_class_type) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- {
- struct bt_component_class_source *source_class =
- container_of(upstream_comp_class,
- struct bt_component_class_source, parent);
- init_method = source_class->methods.iterator.init;
- break;
- }
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- {
- struct bt_component_class_filter *filter_class =
- container_of(upstream_comp_class,
- struct bt_component_class_filter, parent);
- init_method = filter_class->methods.iterator.init;
- break;
- }
- default:
- /* Unreachable. */
- assert(0);
- }
-
- if (init_method) {
- enum bt_notification_iterator_status status = init_method(
- bt_private_notification_iterator_from_notification_iterator(iterator),
- bt_private_port_from_port(upstream_port));
- if (status < 0) {
- goto error;
- }
- }
-
- ret_iterator = bt_notification_iterator_validate(iterator);
- if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(iterator);
-
-end:
- bt_put(upstream_component);
- return iterator;
-}
+++ /dev/null
-/*
- * filter.c
- *
- * Babeltrace Filter Component
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/values.h>
-#include <babeltrace/graph/component-filter-internal.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/component-class-internal.h>
-#include <babeltrace/graph/notification.h>
-#include <babeltrace/graph/notification-iterator-internal.h>
-
-BT_HIDDEN
-void bt_component_filter_destroy(struct bt_component *component)
-{
-}
-
-BT_HIDDEN
-struct bt_component *bt_component_filter_create(
- struct bt_component_class *class, struct bt_value *params)
-{
- struct bt_component_filter *filter = NULL;
-
- filter = g_new0(struct bt_component_filter, 1);
- if (!filter) {
- goto end;
- }
-
-end:
- return filter ? &filter->parent : NULL;
-}
-
-BT_HIDDEN
-enum bt_component_status bt_component_filter_validate(
- struct bt_component *component)
-{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
- if (!component) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (!component->class) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- /* Enforce iterator limits. */
-end:
- return ret;
-}
-
-enum bt_component_status bt_component_filter_get_input_port_count(
- struct bt_component *component, uint64_t *count)
-{
- enum bt_component_status status = BT_COMPONENT_STATUS_OK;
-
- if (!component || !count ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- status = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- *count = bt_component_get_input_port_count(component);
-end:
- return status;
-}
-
-struct bt_port *bt_component_filter_get_input_port(
- struct bt_component *component, const char *name)
-{
- struct bt_port *port = NULL;
-
- if (!component || !name ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- goto end;
- }
-
- port = bt_component_get_input_port(component, name);
-end:
- return port;
-}
-
-struct bt_port *bt_component_filter_get_input_port_at_index(
- struct bt_component *component, int index)
-{
- struct bt_port *port = NULL;
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- goto end;
- }
-
- port = bt_component_get_input_port_at_index(component, index);
-end:
- return port;
-}
-
-struct bt_port *bt_component_filter_get_default_input_port(
- struct bt_component *component)
-{
- return bt_component_filter_get_input_port(component,
- DEFAULT_INPUT_PORT_NAME);
-}
-
-enum bt_component_status bt_component_filter_get_output_port_count(
- struct bt_component *component, uint64_t *count)
-{
- enum bt_component_status status = BT_COMPONENT_STATUS_OK;
-
- if (!component || !count ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- status = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- *count = bt_component_get_output_port_count(component);
-end:
- return status;
-}
-
-struct bt_port *bt_component_filter_get_output_port(
- struct bt_component *component, const char *name)
-{
- struct bt_port *port = NULL;
-
- if (!component || !name ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- goto end;
- }
-
- port = bt_component_get_output_port(component, name);
-end:
- return port;
-}
-
-struct bt_port *bt_component_filter_get_output_port_at_index(
- struct bt_component *component, int index)
-{
- struct bt_port *port = NULL;
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- goto end;
- }
-
- port = bt_component_get_output_port_at_index(component, index);
-end:
- return port;
-}
-
-struct bt_port *bt_component_filter_get_default_output_port(
- struct bt_component *component)
-{
- return bt_component_filter_get_output_port(component,
- DEFAULT_OUTPUT_PORT_NAME);
-}
-
-struct bt_private_port *
-bt_private_component_filter_get_input_private_port_at_index(
- struct bt_private_component *private_component, int index)
-{
- return bt_private_port_from_port(
- bt_component_filter_get_input_port_at_index(
- bt_component_from_private(private_component), index));
-}
-
-struct bt_private_port *
-bt_private_component_filter_get_default_input_private_port(
- struct bt_private_component *private_component)
-{
- return bt_private_port_from_port(
- bt_component_filter_get_default_input_port(
- bt_component_from_private(private_component)));
-}
-
-struct bt_private_port *bt_private_component_filter_add_input_private_port(
- struct bt_private_component *private_component,
- const char *name)
-{
- struct bt_port *port = NULL;
- struct bt_component *component =
- bt_component_from_private(private_component);
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- goto end;
- }
-
- port = bt_component_add_input_port(component, name);
-end:
- return bt_private_port_from_port(port);
-}
-
-struct bt_private_port *
-bt_private_component_filter_get_output_private_port_at_index(
- struct bt_private_component *private_component, int index)
-{
- return bt_private_port_from_port(
- bt_component_filter_get_output_port_at_index(
- bt_component_from_private(private_component), index));
-}
-
-struct bt_private_port *
-bt_private_component_filter_get_default_output_private_port(
- struct bt_private_component *private_component)
-{
- return bt_private_port_from_port(
- bt_component_filter_get_default_output_port(
- bt_component_from_private(private_component)));
-}
-
-struct bt_private_port *bt_private_component_filter_add_output_private_port(
- struct bt_private_component *private_component,
- const char *name)
-{
- struct bt_port *port = NULL;
- struct bt_component *component =
- bt_component_from_private(private_component);
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
- goto end;
- }
-
- port = bt_component_add_output_port(component, name);
-end:
- return bt_private_port_from_port(port);
-}
+++ /dev/null
-/*
- * graph.c
- *
- * Babeltrace Plugin Component Graph
- *
- * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/graph-internal.h>
-#include <babeltrace/graph/connection-internal.h>
-#include <babeltrace/graph/component-sink-internal.h>
-#include <babeltrace/graph/component-source.h>
-#include <babeltrace/graph/component-filter.h>
-#include <babeltrace/graph/port.h>
-#include <babeltrace/compiler-internal.h>
-#include <unistd.h>
-#include <glib.h>
-
-struct bt_graph_listener {
- void *func;
- void *data;
-};
-
-static
-void bt_graph_destroy(struct bt_object *obj)
-{
- struct bt_graph *graph = container_of(obj,
- struct bt_graph, base);
-
- if (graph->components) {
- g_ptr_array_free(graph->components, TRUE);
- }
- if (graph->connections) {
- g_ptr_array_free(graph->connections, TRUE);
- }
- if (graph->sinks_to_consume) {
- g_queue_free(graph->sinks_to_consume);
- }
-
- if (graph->listeners.port_added) {
- g_array_free(graph->listeners.port_added, TRUE);
- }
-
- if (graph->listeners.port_removed) {
- g_array_free(graph->listeners.port_removed, TRUE);
- }
-
- if (graph->listeners.ports_connected) {
- g_array_free(graph->listeners.ports_connected, TRUE);
- }
-
- if (graph->listeners.ports_disconnected) {
- g_array_free(graph->listeners.ports_disconnected, TRUE);
- }
-
- g_free(graph);
-}
-
-static
-int init_listeners_array(GArray **listeners)
-{
- int ret = 0;
-
- assert(listeners);
- *listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_graph_listener));
- if (!*listeners) {
- ret = -1;
- goto end;
- }
-
-end:
- return ret;
-}
-
-struct bt_graph *bt_graph_create(void)
-{
- struct bt_graph *graph;
- int ret;
-
- graph = g_new0(struct bt_graph, 1);
- if (!graph) {
- goto end;
- }
-
- bt_object_init(graph, bt_graph_destroy);
-
- graph->connections = g_ptr_array_new_with_free_func(bt_object_release);
- if (!graph->connections) {
- goto error;
- }
- graph->components = g_ptr_array_new_with_free_func(bt_object_release);
- if (!graph->components) {
- goto error;
- }
- graph->sinks_to_consume = g_queue_new();
- if (!graph->sinks_to_consume) {
- goto error;
- }
-
- ret = init_listeners_array(&graph->listeners.port_added);
- if (ret) {
- goto error;
- }
-
- ret = init_listeners_array(&graph->listeners.port_removed);
- if (ret) {
- goto error;
- }
-
- ret = init_listeners_array(&graph->listeners.ports_connected);
- if (ret) {
- goto error;
- }
-
- ret = init_listeners_array(&graph->listeners.ports_disconnected);
- if (ret) {
- goto error;
- }
-
-end:
- return graph;
-error:
- BT_PUT(graph);
- goto end;
-}
-
-struct bt_connection *bt_graph_connect_ports(struct bt_graph *graph,
- struct bt_port *upstream_port,
- struct bt_port *downstream_port)
-{
- struct bt_connection *connection = NULL;
- struct bt_graph *upstream_graph = NULL;
- 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 appropriate types for upstream and downstream ports. */
- if (bt_port_get_type(upstream_port) != BT_PORT_TYPE_OUTPUT) {
- goto end;
- }
- if (bt_port_get_type(downstream_port) != BT_PORT_TYPE_INPUT) {
- goto end;
- }
-
- /* Ensure that both ports are currently unconnected. */
- existing_conn = bt_port_get_connection(upstream_port);
- bt_put(existing_conn);
- if (existing_conn) {
- 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) {
- fprintf(stderr, "Downstream port is already connected\n");
- goto end;
- }
-
- /*
- * Ensure that both ports are still attached to their creating
- * component.
- */
- upstream_component = bt_port_get_component(upstream_port);
- if (!upstream_component) {
- fprintf(stderr, "Upstream port does not belong to a component\n");
- goto end;
- }
-
- downstream_component = bt_port_get_component(downstream_port);
- if (!downstream_component) {
- fprintf(stderr, "Downstream port does not belong to a component\n");
- goto end;
- }
-
- /* Ensure the components are not already part of another graph. */
- upstream_graph = bt_component_get_graph(upstream_component);
- if (upstream_graph && (graph != upstream_graph)) {
- fprintf(stderr, "Upstream component is already part of another graph\n");
- goto error;
- }
- upstream_was_already_in_graph = (graph == upstream_graph);
- downstream_graph = bt_component_get_graph(downstream_component);
- if (downstream_graph && (graph != downstream_graph)) {
- fprintf(stderr, "Downstream component is already part of another graph\n");
- goto error;
- }
- downstream_was_already_in_graph = (graph == downstream_graph);
-
- connection = bt_connection_create(graph, upstream_port,
- downstream_port);
- if (!connection) {
- goto error;
- }
-
- /*
- * Ownership of upstream_component/downstream_component and of
- * the connection object is transferred to the graph.
- */
- g_ptr_array_add(graph->connections, connection);
-
- if (!upstream_was_already_in_graph) {
- g_ptr_array_add(graph->components, upstream_component);
- bt_component_set_graph(upstream_component, graph);
- }
- if (!downstream_was_already_in_graph) {
- g_ptr_array_add(graph->components, downstream_component);
- bt_component_set_graph(downstream_component, graph);
- if (bt_component_get_class_type(downstream_component) ==
- BT_COMPONENT_CLASS_TYPE_SINK) {
- g_queue_push_tail(graph->sinks_to_consume,
- downstream_component);
- }
- }
-
- /*
- * 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.
- */
- 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;
- }
-
- /*
- * Both components accepted the connection. Notify the graph's
- * creator that both ports are connected.
- */
- bt_graph_notify_ports_connected(graph, upstream_port, downstream_port);
-
-end:
- bt_put(upstream_graph);
- bt_put(downstream_graph);
- 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);
- goto end;
-}
-
-static
-enum bt_component_status get_component_port_counts(
- struct bt_component *component, uint64_t *input_count,
- uint64_t *output_count)
-{
- enum bt_component_status ret;
-
- switch (bt_component_get_class_type(component)) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- ret = bt_component_source_get_output_port_count(component,
- output_count);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
- break;
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- ret = bt_component_filter_get_output_port_count(component,
- output_count);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
- ret = bt_component_filter_get_input_port_count(component,
- input_count);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
- break;
- case BT_COMPONENT_CLASS_TYPE_SINK:
- ret = bt_component_sink_get_input_port_count(component,
- input_count);
- if (ret != BT_COMPONENT_STATUS_OK) {
- goto end;
- }
- break;
- default:
- assert(false);
- break;
- }
- ret = BT_COMPONENT_STATUS_OK;
-end:
- return ret;
-}
-
-enum bt_graph_status bt_graph_add_component_as_sibling(struct bt_graph *graph,
- struct bt_component *origin,
- struct bt_component *new_component)
-{
- uint64_t origin_input_port_count = 0;
- uint64_t origin_output_port_count = 0;
- uint64_t new_input_port_count = 0;
- uint64_t new_output_port_count = 0;
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
- struct bt_graph *origin_graph = NULL;
- struct bt_graph *new_graph = NULL;
- struct bt_port *origin_port = NULL;
- struct bt_port *new_port = NULL;
- struct bt_port *upstream_port = NULL;
- struct bt_port *downstream_port = NULL;
- struct bt_connection *origin_connection = NULL;
- struct bt_connection *new_connection = NULL;
- int port_index;
-
- if (!graph || !origin || !new_component) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- if (bt_component_get_class_type(origin) !=
- bt_component_get_class_type(new_component)) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- origin_graph = bt_component_get_graph(origin);
- if (!origin_graph || (origin_graph != graph)) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- new_graph = bt_component_get_graph(new_component);
- if (new_graph) {
- status = BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH;
- goto end;
- }
-
- if (get_component_port_counts(origin, &origin_input_port_count,
- &origin_output_port_count) != BT_COMPONENT_STATUS_OK) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
- if (get_component_port_counts(new_component, &new_input_port_count,
- &new_output_port_count) != BT_COMPONENT_STATUS_OK) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- if (origin_input_port_count != new_input_port_count ||
- origin_output_port_count != new_output_port_count) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- /* Replicate input connections. */
- for (port_index = 0; port_index< origin_input_port_count; port_index++) {
- origin_port = bt_component_get_input_port_at_index(origin,
- port_index);
- if (!origin_port) {
- status = BT_GRAPH_STATUS_ERROR;
- goto error_disconnect;
- }
-
- new_port = bt_component_get_input_port_at_index(new_component,
- port_index);
- if (!new_port) {
- status = BT_GRAPH_STATUS_ERROR;
- goto error_disconnect;
- }
-
- origin_connection = bt_port_get_connection(origin_port);
- if (origin_connection) {
- upstream_port = bt_connection_get_upstream_port(
- origin_connection);
- if (!upstream_port) {
- goto error_disconnect;
- }
-
- new_connection = bt_graph_connect_ports(graph,
- upstream_port, new_port);
- if (!new_connection) {
- goto error_disconnect;
- }
- }
-
- BT_PUT(upstream_port);
- BT_PUT(origin_connection);
- BT_PUT(new_connection);
- BT_PUT(origin_port);
- BT_PUT(new_port);
- }
-
- /* Replicate output connections. */
- for (port_index = 0; port_index < origin_output_port_count; port_index++) {
- origin_port = bt_component_get_output_port_at_index(origin,
- port_index);
- if (!origin_port) {
- status = BT_GRAPH_STATUS_ERROR;
- goto error_disconnect;
- }
- new_port = bt_component_get_output_port_at_index(new_component,
- port_index);
- if (!new_port) {
- status = BT_GRAPH_STATUS_ERROR;
- goto error_disconnect;
- }
-
- origin_connection = bt_port_get_connection(origin_port);
- if (origin_connection) {
- downstream_port = bt_connection_get_downstream_port(
- origin_connection);
- if (!downstream_port) {
- goto error_disconnect;
- }
-
- new_connection = bt_graph_connect_ports(graph,
- new_port, downstream_port);
- if (!new_connection) {
- goto error_disconnect;
- }
- }
-
- BT_PUT(downstream_port);
- BT_PUT(origin_connection);
- BT_PUT(new_connection);
- BT_PUT(origin_port);
- BT_PUT(new_port);
- }
-end:
- bt_put(origin_graph);
- bt_put(new_graph);
- bt_put(origin_port);
- bt_put(new_port);
- bt_put(upstream_port);
- bt_put(downstream_port);
- bt_put(origin_connection);
- bt_put(new_connection);
- return status;
-error_disconnect:
- /* Destroy all connections of the new component. */
- /* FIXME. */
- goto end;
-}
-
-enum bt_graph_status bt_graph_consume(struct bt_graph *graph)
-{
- struct bt_component *sink;
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
- enum bt_component_status comp_status;
- GList *current_node;
-
- if (!graph) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- if (g_queue_is_empty(graph->sinks_to_consume)) {
- status = BT_GRAPH_STATUS_END;
- goto end;
- }
-
- current_node = g_queue_pop_head_link(graph->sinks_to_consume);
- sink = current_node->data;
- comp_status = bt_component_sink_consume(sink);
- switch (comp_status) {
- case BT_COMPONENT_STATUS_OK:
- break;
- case BT_COMPONENT_STATUS_END:
- status = BT_GRAPH_STATUS_END;
- break;
- case BT_COMPONENT_STATUS_AGAIN:
- status = BT_GRAPH_STATUS_AGAIN;
- break;
- case BT_COMPONENT_STATUS_INVALID:
- status = BT_GRAPH_STATUS_INVALID;
- break;
- default:
- status = BT_GRAPH_STATUS_ERROR;
- break;
- }
-
- if (status != BT_GRAPH_STATUS_END) {
- g_queue_push_tail_link(graph->sinks_to_consume, current_node);
- goto end;
- }
-
- /* End reached, the node is not added back to the queue and free'd. */
- g_queue_delete_link(graph->sinks_to_consume, current_node);
-
- /* Don't forward an END status if there are sinks left to consume. */
- if (!g_queue_is_empty(graph->sinks_to_consume)) {
- status = BT_GRAPH_STATUS_OK;
- goto end;
- }
-end:
- return status;
-}
-
-enum bt_graph_status bt_graph_run(struct bt_graph *graph)
-{
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
-
- if (!graph) {
- status = BT_GRAPH_STATUS_INVALID;
- goto error;
- }
-
- do {
- status = bt_graph_consume(graph);
- if (status == BT_GRAPH_STATUS_AGAIN) {
- /*
- * If AGAIN is received and there are multiple sinks,
- * go ahead and consume from the next sink.
- *
- * However, in the case where a single sink is left,
- * the caller can decide to busy-wait and call
- * bt_graph_run continuously until the source is ready
- * or it can decide to sleep for an arbitrary amount of
- * time.
- */
- if (graph->sinks_to_consume->length > 1) {
- status = BT_GRAPH_STATUS_OK;
- }
- }
- } while (status == BT_GRAPH_STATUS_OK);
-
- if (g_queue_is_empty(graph->sinks_to_consume)) {
- status = BT_GRAPH_STATUS_END;
- }
-error:
- return status;
-}
-
-static
-void add_listener(GArray *listeners, void *func, void *data)
-{
- struct bt_graph_listener listener = {
- .func = func,
- .data = data,
- };
-
- g_array_append_val(listeners, listener);
-}
-
-enum bt_graph_status bt_graph_add_port_added_listener(
- struct bt_graph *graph,
- bt_graph_port_added_listener listener, void *data)
-{
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
-
- if (!graph || !listener) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- add_listener(graph->listeners.port_added, listener, data);
-
-end:
- return status;
-}
-
-enum bt_graph_status bt_graph_add_port_removed_listener(
- struct bt_graph *graph,
- bt_graph_port_removed_listener listener, void *data)
-{
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
-
- if (!graph || !listener) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- add_listener(graph->listeners.port_removed, listener, data);
-
-end:
- return status;
-}
-
-enum bt_graph_status bt_graph_add_ports_connected_listener(
- struct bt_graph *graph,
- bt_graph_ports_connected_listener listener, void *data)
-{
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
-
- if (!graph || !listener) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- add_listener(graph->listeners.ports_connected, listener, data);
-
-end:
- return status;
-}
-
-enum bt_graph_status bt_graph_add_ports_disconnected_listener(
- struct bt_graph *graph,
- bt_graph_ports_disconnected_listener listener, void *data)
-{
- enum bt_graph_status status = BT_GRAPH_STATUS_OK;
-
- if (!graph || !listener) {
- status = BT_GRAPH_STATUS_INVALID;
- goto end;
- }
-
- add_listener(graph->listeners.ports_disconnected, listener, data);
-
-end:
- return status;
-}
-
-BT_HIDDEN
-void bt_graph_notify_port_added(struct bt_graph *graph, struct bt_port *port)
-{
- size_t i;
-
- for (i = 0; i < graph->listeners.port_added->len; i++) {
- struct bt_graph_listener listener =
- g_array_index(graph->listeners.port_added,
- struct bt_graph_listener, i);
- bt_graph_port_added_listener func = listener.func;
-
- assert(func);
- func(port, listener.data);
- }
-}
-
-BT_HIDDEN
-void bt_graph_notify_port_removed(struct bt_graph *graph,
- struct bt_component *comp, struct bt_port *port)
-{
- size_t i;
-
- for (i = 0; i < graph->listeners.port_removed->len; i++) {
- struct bt_graph_listener listener =
- g_array_index(graph->listeners.port_removed,
- struct bt_graph_listener, i);
- bt_graph_port_removed_listener func = listener.func;
-
- assert(func);
- func(comp, port, listener.data);
- }
-}
-
-BT_HIDDEN
-void bt_graph_notify_ports_connected(struct bt_graph *graph,
- struct bt_port *upstream_port, struct bt_port *downstream_port)
-{
- size_t i;
-
- for (i = 0; i < graph->listeners.ports_connected->len; i++) {
- struct bt_graph_listener listener =
- g_array_index(graph->listeners.ports_connected,
- struct bt_graph_listener, i);
- bt_graph_ports_connected_listener func = listener.func;
-
- assert(func);
- func(upstream_port, downstream_port, listener.data);
- }
-}
-
-BT_HIDDEN
-void bt_graph_notify_ports_disconnected(struct bt_graph *graph,
- struct bt_component *upstream_comp,
- struct bt_component *downstream_comp,
- struct bt_port *upstream_port, struct bt_port *downstream_port)
-{
- size_t i;
-
- for (i = 0; i < graph->listeners.ports_disconnected->len; i++) {
- struct bt_graph_listener listener =
- g_array_index(graph->listeners.ports_disconnected,
- struct bt_graph_listener, i);
- bt_graph_ports_disconnected_listener func = listener.func;
-
- assert(func);
- func(upstream_comp, downstream_comp, upstream_port,
- downstream_port, listener.data);
- }
-}
+++ /dev/null
-/*
- * iterator.c
- *
- * Babeltrace Notification Iterator
- *
- * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/ref.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/component-source-internal.h>
-#include <babeltrace/graph/component-class-internal.h>
-#include <babeltrace/graph/notification-iterator.h>
-#include <babeltrace/graph/notification-iterator-internal.h>
-#include <babeltrace/graph/notification-internal.h>
-
-static
-void bt_notification_iterator_destroy(struct bt_object *obj)
-{
- struct bt_notification_iterator *iterator;
- struct bt_component_class *comp_class;
-
- assert(obj);
- iterator = container_of(obj, struct bt_notification_iterator,
- base);
- assert(iterator->component);
- comp_class = iterator->component->class;
-
- /* Call user-defined destroy method */
- switch (comp_class->type) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- {
- struct bt_component_class_source *source_class;
-
- source_class = container_of(comp_class, struct bt_component_class_source, parent);
-
- if (source_class->methods.iterator.finalize) {
- source_class->methods.iterator.finalize(
- bt_private_notification_iterator_from_notification_iterator(iterator));
- }
- break;
- }
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- {
- struct bt_component_class_filter *filter_class;
-
- filter_class = container_of(comp_class, struct bt_component_class_filter, parent);
-
- if (filter_class->methods.iterator.finalize) {
- filter_class->methods.iterator.finalize(
- bt_private_notification_iterator_from_notification_iterator(iterator));
- }
- break;
- }
- default:
- /* Unreachable */
- assert(0);
- }
-
- BT_PUT(iterator->current_notification);
- BT_PUT(iterator->component);
- g_free(iterator);
-}
-
-BT_HIDDEN
-struct bt_notification_iterator *bt_notification_iterator_create(
- struct bt_component *component)
-{
- enum bt_component_class_type type;
- struct bt_notification_iterator *iterator = NULL;
-
- if (!component) {
- goto end;
- }
-
- type = bt_component_get_class_type(component);
- switch (type) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- break;
- default:
- goto end;
- }
-
- iterator = g_new0(struct bt_notification_iterator, 1);
- if (!iterator) {
- goto end;
- }
-
- iterator->component = bt_get(component);
- bt_object_init(iterator, bt_notification_iterator_destroy);
-end:
- return iterator;
-}
-
-BT_HIDDEN
-enum bt_notification_iterator_status bt_notification_iterator_validate(
- struct bt_notification_iterator *iterator)
-{
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
-
- if (!iterator) {
- ret = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
- goto end;
- }
-end:
- return ret;
-}
-
-void *bt_private_notification_iterator_get_user_data(
- struct bt_private_notification_iterator *private_iterator)
-{
- struct bt_notification_iterator *iterator =
- bt_notification_iterator_from_private(private_iterator);
-
- return iterator ? iterator->user_data : NULL;
-}
-
-enum bt_notification_iterator_status
-bt_private_notification_iterator_set_user_data(
- struct bt_private_notification_iterator *private_iterator,
- void *data)
-{
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- struct bt_notification_iterator *iterator =
- bt_notification_iterator_from_private(private_iterator);
-
- if (!iterator) {
- ret = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
- goto end;
- }
-
- iterator->user_data = data;
-end:
- return ret;
-}
-
-struct bt_notification *bt_notification_iterator_get_notification(
- struct bt_notification_iterator *iterator)
-{
- struct bt_notification *notification = NULL;
-
- if (!iterator) {
- goto end;
- }
-
- notification = bt_get(iterator->current_notification);
-
-end:
- return notification;
-}
-
-enum bt_notification_iterator_status
-bt_notification_iterator_next(struct bt_notification_iterator *iterator)
-{
- struct bt_private_notification_iterator *priv_iterator =
- bt_private_notification_iterator_from_notification_iterator(iterator);
- bt_component_class_notification_iterator_next_method next_method = NULL;
- struct bt_notification_iterator_next_return next_return;
- enum bt_notification_iterator_status status =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
-
- if (!iterator) {
- status = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
- goto end;
- }
-
- assert(iterator->component);
- assert(iterator->component->class);
-
- switch (iterator->component->class->type) {
- case BT_COMPONENT_CLASS_TYPE_SOURCE:
- {
- struct bt_component_class_source *source_class =
- container_of(iterator->component->class,
- struct bt_component_class_source, parent);
-
- assert(source_class->methods.iterator.next);
- next_method = source_class->methods.iterator.next;
- break;
- }
- case BT_COMPONENT_CLASS_TYPE_FILTER:
- {
- struct bt_component_class_filter *filter_class =
- container_of(iterator->component->class,
- struct bt_component_class_filter, parent);
-
- assert(filter_class->methods.iterator.next);
- next_method = filter_class->methods.iterator.next;
- break;
- }
- default:
- assert(false);
- break;
- }
-
- assert(next_method);
- next_return = next_method(priv_iterator);
- if (next_return.status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
- if (!next_return.notification) {
- status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
- goto end;
- }
-
- BT_MOVE(iterator->current_notification,
- next_return.notification);
- bt_notification_freeze(iterator->current_notification);
- }
-
-end:
- return next_return.status;
-}
-
-struct bt_component *bt_notification_iterator_get_component(
- struct bt_notification_iterator *iterator)
-{
- return bt_get(iterator->component);
-}
-
-struct bt_private_component *
-bt_private_notification_iterator_get_private_component(
- struct bt_private_notification_iterator *private_iterator)
-{
- return bt_private_component_from_component(
- bt_notification_iterator_get_component(
- bt_notification_iterator_from_private(private_iterator)));
-}
-
-enum bt_notification_iterator_status bt_notification_iterator_seek_time(
- struct bt_notification_iterator *iterator,
- enum bt_notification_iterator_seek_origin seek_origin,
- int64_t time)
-{
- enum bt_notification_iterator_status ret =
- BT_NOTIFICATION_ITERATOR_STATUS_UNSUPPORTED;
- return ret;
-}
+++ /dev/null
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
-
-noinst_LTLIBRARIES = libcomponent-notification.la
-
-# Plug-in system library
-libcomponent_notification_la_SOURCES = \
- notification.c \
- packet.c \
- event.c \
- stream.c \
- heap.c \
- inactivity.c
+++ /dev/null
-/*
- * Babeltrace Plug-in Event Notification
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/event-internal.h>
-#include <babeltrace/ctf-ir/event-class.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/graph/clock-class-priority-map.h>
-#include <babeltrace/graph/notification-event-internal.h>
-
-static
-void bt_notification_event_destroy(struct bt_object *obj)
-{
- struct bt_notification_event *notification =
- (struct bt_notification_event *) obj;
-
- BT_PUT(notification->event);
- BT_PUT(notification->cc_prio_map);
- g_free(notification);
-}
-
-static
-bool validate_clock_classes(struct bt_notification_event *notif)
-{
- /*
- * For each clock class found in the event's trace, get the
- * event's clock value for this clock class, and if it exists,
- * make sure that this clock class has a priority in the
- * notification's clock class priority map.
- */
- bool is_valid = true;
- int ret;
- int count;
- size_t i;
- struct bt_ctf_event_class *event_class = NULL;
- struct bt_ctf_stream_class *stream_class = NULL;
- struct bt_ctf_trace *trace = NULL;
- uint64_t prio;
-
- event_class = bt_ctf_event_get_class(notif->event);
- assert(event_class);
- stream_class = bt_ctf_event_class_get_stream_class(event_class);
- assert(stream_class);
- trace = bt_ctf_stream_class_get_trace(stream_class);
- assert(trace);
- count = bt_ctf_trace_get_clock_class_count(trace);
- assert(count >= 0);
-
- for (i = 0; i < count; i++) {
- struct bt_ctf_clock_class *clock_class =
- bt_ctf_trace_get_clock_class(trace, i);
-
- assert(clock_class);
- ret = bt_clock_class_priority_map_get_clock_class_priority(
- notif->cc_prio_map, clock_class, &prio);
- bt_put(clock_class);
- if (ret) {
- is_valid = false;
- goto end;
- }
- }
-
-end:
- bt_put(trace);
- bt_put(stream_class);
- bt_put(event_class);
- return is_valid;
-}
-
-struct bt_notification *bt_notification_event_create(struct bt_ctf_event *event,
- struct bt_clock_class_priority_map *cc_prio_map)
-{
- struct bt_notification_event *notification = NULL;
-
- if (!event || !cc_prio_map) {
- goto error;
- }
-
- if (!bt_ctf_event_borrow_packet(event)) {
- goto error;
- }
-
- notification = g_new0(struct bt_notification_event, 1);
- if (!notification) {
- goto error;
- }
- bt_notification_init(¬ification->parent,
- BT_NOTIFICATION_TYPE_EVENT,
- bt_notification_event_destroy);
- notification->event = bt_get(event);
- notification->cc_prio_map = bt_get(cc_prio_map);
- if (!validate_clock_classes(notification)) {
- goto error;
- }
-
- bt_ctf_event_freeze(notification->event);
- return ¬ification->parent;
-error:
- bt_put(notification);
- return NULL;
-}
-
-struct bt_ctf_event *bt_notification_event_get_event(
- struct bt_notification *notification)
-{
- struct bt_ctf_event *event = NULL;
- struct bt_notification_event *event_notification;
-
- if (bt_notification_get_type(notification) !=
- BT_NOTIFICATION_TYPE_EVENT) {
- goto end;
- }
- event_notification = container_of(notification,
- struct bt_notification_event, parent);
- event = bt_get(event_notification->event);
-end:
- return event;
-}
-
-extern struct bt_clock_class_priority_map *
-bt_notification_event_get_clock_class_priority_map(
- struct bt_notification *notification)
-{
- struct bt_clock_class_priority_map *cc_prio_map = NULL;
- struct bt_notification_event *event_notification;
-
- if (bt_notification_get_type(notification) !=
- BT_NOTIFICATION_TYPE_EVENT) {
- goto end;
- }
-
- event_notification = container_of(notification,
- struct bt_notification_event, parent);
- cc_prio_map = bt_get(event_notification->cc_prio_map);
-end:
- return cc_prio_map;
-}
+++ /dev/null
-/*
- * Babeltrace - CTF notification priority heap
- *
- * Static-sized priority heap containing pointers. Based on CLRS,
- * chapter 6.
- *
- * Copyright (c) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <assert.h>
-#include <stddef.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/graph/notification-heap-internal.h>
-
-#ifdef DEBUG_HEAP
-static
-void check_heap(struct bt_notification_heap *heap)
-{
- size_t i;
-
- if (!heap->count) {
- return;
- }
-
- for (i = 1; i < heap->count; i++) {
- assert(!heap->compare(g_ptr_array_index(heap->ptrs, i),
- g_ptr_array_index(heap->ptrs, 0),
- heap->compare_data));
- }
-}
-#else
-void check_heap(struct bt_notification_heap *heap)
-{
-}
-#endif
-
-static
-size_t parent(size_t i)
-{
- return (i - 1) >> 1;
-}
-
-static
-size_t left(size_t i)
-{
- return (i << 1) + 1;
-}
-
-static
-size_t right(size_t i)
-{
- return (i << 1) + 2;
-}
-
-/*
- * Copy of heap->ptrs pointer is invalid after heap_grow.
- */
-static
-int heap_grow(struct bt_notification_heap *heap, size_t new_len)
-{
- size_t alloc_len;
-
- if (likely(heap->ptrs->len >= new_len)) {
- goto end;
- }
-
- alloc_len = max_t(size_t, new_len, heap->ptrs->len << 1);
- g_ptr_array_set_size(heap->ptrs, alloc_len);
-end:
- return 0;
-}
-
-static
-int heap_set_count(struct bt_notification_heap *heap, size_t new_count)
-{
- int ret = 0;
-
- ret = heap_grow(heap, new_count);
- if (unlikely(ret)) {
- goto end;
- }
- heap->count = new_count;
-end:
- return ret;
-}
-
-static
-void heapify(struct bt_notification_heap *heap, size_t i)
-{
- struct bt_notification **ptrs =
- (struct bt_notification **) heap->ptrs->pdata;
-
- for (;;) {
- void *tmp;
- size_t l, r, largest;
-
- l = left(i);
- r = right(i);
- if (l < heap->count && heap->compare(ptrs[l], ptrs[i],
- heap->compare_data)) {
- largest = l;
- } else {
- largest = i;
- }
- if (r < heap->count && heap->compare(ptrs[r], ptrs[largest],
- heap->compare_data)) {
- largest = r;
- }
- if (unlikely(largest == i)) {
- break;
- }
- tmp = ptrs[i];
- ptrs[i] = ptrs[largest];
- ptrs[largest] = tmp;
- i = largest;
- }
- check_heap(heap);
-}
-
-static
-struct bt_notification *heap_replace_max(struct bt_notification_heap *heap,
- struct bt_notification *notification)
-{
- struct bt_notification *res = NULL;
-
- if (unlikely(!heap->count)) {
- (void) heap_set_count(heap, 1);
- g_ptr_array_index(heap->ptrs, 0) = notification;
- check_heap(heap);
- goto end;
- }
-
- /* Replace the current max and heapify. */
- res = g_ptr_array_index(heap->ptrs, 0);
- g_ptr_array_index(heap->ptrs, 0) = notification;
- heapify(heap, 0);
-end:
- return res;
-}
-
-static
-void bt_notification_heap_destroy(struct bt_object *obj)
-{
- struct bt_notification_heap *heap = container_of(obj,
- struct bt_notification_heap, base);
-
- if (heap->ptrs) {
- size_t i;
-
- for (i = 0; i < heap->count; i++) {
- bt_put(g_ptr_array_index(heap->ptrs, i));
- }
- g_ptr_array_free(heap->ptrs, TRUE);
- }
- g_free(heap);
-}
-
-struct bt_notification_heap *bt_notification_heap_create(
- bt_notification_time_compare_func comparator, void *user_data)
-{
- struct bt_notification_heap *heap = NULL;
-
- if (!comparator) {
- goto end;
- }
-
- heap = g_new0(struct bt_notification_heap, 1);
- if (!heap) {
- goto end;
- }
-
- bt_object_init(&heap->base, bt_notification_heap_destroy);
- heap->ptrs = g_ptr_array_new();
- if (!heap->ptrs) {
- BT_PUT(heap);
- goto end;
- }
-
- heap->compare = comparator;
- heap->compare_data = user_data;
-end:
- return heap;
-}
-
-struct bt_notification *bt_notification_heap_peek(
- struct bt_notification_heap *heap)
-{
- check_heap(heap);
- return bt_get(likely(heap->count) ?
- g_ptr_array_index(heap->ptrs, 0) : NULL);
-}
-
-int bt_notification_heap_insert(struct bt_notification_heap *heap,
- struct bt_notification *notification)
-{
- int ret;
- size_t pos;
- struct bt_notification **ptrs;
-
- ret = heap_set_count(heap, heap->count + 1);
- if (unlikely(ret)) {
- goto end;
- }
-
- ptrs = (struct bt_notification **) heap->ptrs->pdata;
- pos = heap->count - 1;
- while (pos > 0 && heap->compare(notification, ptrs[parent(pos)],
- heap->compare_data)) {
- /* Move parent down until we find the right spot. */
- ptrs[pos] = ptrs[parent(pos)];
- pos = parent(pos);
- }
- ptrs[pos] = bt_get(notification);
- check_heap(heap);
-end:
- return ret;
-}
-
-struct bt_notification *bt_notification_heap_pop(
- struct bt_notification_heap *heap)
-{
- struct bt_notification *ret = NULL;
-
- switch (heap->count) {
- case 0:
- goto end;
- case 1:
- (void) heap_set_count(heap, 0);
- ret = g_ptr_array_index(heap->ptrs, 0);
- goto end;
- }
- /*
- * Shrink, replace the current max by previous last entry and heapify.
- */
- heap_set_count(heap, heap->count - 1);
- /* count changed. previous last entry is at heap->count. */
- ret = heap_replace_max(heap, g_ptr_array_index(heap->ptrs,
- heap->count));
-end:
- /*
- * Not taking a supplementary reference since we are relinquishing our
- * own to the caller.
- */
- return ret;
-}
+++ /dev/null
-/*
- * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/object-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/graph/clock-class-priority-map.h>
-#include <babeltrace/graph/notification-internal.h>
-#include <babeltrace/graph/notification-inactivity-internal.h>
-
-static
-void bt_notification_inactivity_destroy(struct bt_object *obj)
-{
- struct bt_notification_inactivity *notification =
- (struct bt_notification_inactivity *) obj;
-
- bt_put(notification->cc_prio_map);
-
- if (notification->clock_values) {
- g_hash_table_destroy(notification->clock_values);
- }
-
- g_free(notification);
-}
-
-struct bt_notification *bt_notification_inactivity_create(
- struct bt_clock_class_priority_map *cc_prio_map)
-{
- struct bt_notification_inactivity *notification;
- struct bt_notification *ret_notif = NULL;
-
- if (!cc_prio_map) {
- goto error;
- }
-
- notification = g_new0(struct bt_notification_inactivity, 1);
- if (!notification) {
- goto error;
- }
- bt_notification_init(¬ification->parent,
- BT_NOTIFICATION_TYPE_INACTIVITY,
- bt_notification_inactivity_destroy);
- ret_notif = ¬ification->parent;
- notification->clock_values = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, bt_put, bt_put);
- if (!notification->clock_values) {
- goto error;
- }
-
- notification->cc_prio_map = bt_get(cc_prio_map);
- goto end;
-
-error:
- BT_PUT(ret_notif);
-
-end:
- return ret_notif;
-}
-
-extern struct bt_clock_class_priority_map *
-bt_notification_inactivity_get_clock_class_priority_map(
- struct bt_notification *notification)
-{
- struct bt_clock_class_priority_map *cc_prio_map = NULL;
- struct bt_notification_inactivity *inactivity_notification;
-
- if (bt_notification_get_type(notification) !=
- BT_NOTIFICATION_TYPE_INACTIVITY) {
- goto end;
- }
-
- inactivity_notification = container_of(notification,
- struct bt_notification_inactivity, parent);
- cc_prio_map = bt_get(inactivity_notification->cc_prio_map);
-end:
- return cc_prio_map;
-}
-
-struct bt_ctf_clock_value *bt_notification_inactivity_get_clock_value(
- struct bt_notification *notification,
- struct bt_ctf_clock_class *clock_class)
-{
- struct bt_ctf_clock_value *clock_value = NULL;
- struct bt_notification_inactivity *inactivity_notification;
-
- if (!notification || !clock_class) {
- goto end;
- }
-
- if (bt_notification_get_type(notification) !=
- BT_NOTIFICATION_TYPE_INACTIVITY) {
- goto end;
- }
-
- inactivity_notification = container_of(notification,
- struct bt_notification_inactivity, parent);
- clock_value = g_hash_table_lookup(inactivity_notification->clock_values,
- clock_class);
- bt_get(clock_value);
-
-end:
- return clock_value;
-}
-
-int bt_notification_inactivity_set_clock_value(
- struct bt_notification *notification,
- struct bt_ctf_clock_value *clock_value)
-{
- int ret = 0;
- uint64_t prio;
- struct bt_ctf_clock_class *clock_class = NULL;
- struct bt_notification_inactivity *inactivity_notification;
-
- if (!notification || !clock_value || notification->frozen) {
- ret = -1;
- goto end;
- }
-
- if (bt_notification_get_type(notification) !=
- BT_NOTIFICATION_TYPE_INACTIVITY) {
- goto end;
- }
-
- inactivity_notification = container_of(notification,
- struct bt_notification_inactivity, parent);
- clock_class = bt_ctf_clock_value_get_class(clock_value);
- ret = bt_clock_class_priority_map_get_clock_class_priority(
- inactivity_notification->cc_prio_map, clock_class, &prio);
- if (ret) {
- /*
- * Clock value's class is not mapped to a priority
- * within the scope of this notification.
- */
- goto end;
- }
-
- g_hash_table_insert(inactivity_notification->clock_values,
- clock_class, bt_get(clock_value));
- clock_class = NULL;
-
-end:
- bt_put(clock_class);
- return ret;
-}
+++ /dev/null
-/*
- * Babeltrace Plug-in Notification
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/graph/notification-internal.h>
-
-BT_HIDDEN
-void bt_notification_init(struct bt_notification *notification,
- enum bt_notification_type type,
- bt_object_release_func release)
-{
- assert(type > BT_NOTIFICATION_TYPE_ALL &&
- type < BT_NOTIFICATION_TYPE_NR);
- notification->type = type;
- bt_object_init(¬ification->base, release);
-}
-
-enum bt_notification_type bt_notification_get_type(
- struct bt_notification *notification)
-{
- return notification ? notification->type : BT_NOTIFICATION_TYPE_UNKNOWN;
-}
-
-struct bt_ctf_stream *bt_notification_get_stream(
- struct bt_notification *notification)
-{
- struct bt_ctf_stream *stream = NULL;
-
- if (!notification || !notification->get_stream) {
- goto end;
- }
-
- stream = notification->get_stream(notification);
-end:
- return stream;
-}
+++ /dev/null
-/*
- * Babeltrace Plug-in Packet-related Notifications
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/graph/notification-packet-internal.h>
-
-static
-void bt_notification_packet_begin_destroy(struct bt_object *obj)
-{
- struct bt_notification_packet_begin *notification =
- (struct bt_notification_packet_begin *) obj;
-
- BT_PUT(notification->packet);
- g_free(notification);
-}
-
-static
-void bt_notification_packet_end_destroy(struct bt_object *obj)
-{
- struct bt_notification_packet_end *notification =
- (struct bt_notification_packet_end *) obj;
-
- BT_PUT(notification->packet);
- g_free(notification);
-}
-
-struct bt_notification *bt_notification_packet_begin_create(
- struct bt_ctf_packet *packet)
-{
- struct bt_notification_packet_begin *notification;
-
- if (!packet) {
- goto error;
- }
-
- notification = g_new0(struct bt_notification_packet_begin, 1);
- bt_notification_init(¬ification->parent,
- BT_NOTIFICATION_TYPE_PACKET_BEGIN,
- bt_notification_packet_begin_destroy);
- notification->packet = bt_get(packet);
- return ¬ification->parent;
-error:
- return NULL;
-}
-
-struct bt_ctf_packet *bt_notification_packet_begin_get_packet(
- struct bt_notification *notification)
-{
- struct bt_ctf_packet *ret = NULL;
- struct bt_notification_packet_begin *packet_begin;
-
- if (notification->type != BT_NOTIFICATION_TYPE_PACKET_BEGIN) {
- goto end;
- }
-
- packet_begin = container_of(notification,
- struct bt_notification_packet_begin, parent);
- ret = bt_get(packet_begin->packet);
-end:
- return ret;
-}
-
-struct bt_notification *bt_notification_packet_end_create(
- struct bt_ctf_packet *packet)
-{
- struct bt_notification_packet_end *notification;
-
- if (!packet) {
- goto error;
- }
-
- notification = g_new0(struct bt_notification_packet_end, 1);
- bt_notification_init(¬ification->parent,
- BT_NOTIFICATION_TYPE_PACKET_END,
- bt_notification_packet_end_destroy);
- notification->packet = bt_get(packet);
- return ¬ification->parent;
-error:
- return NULL;
-}
-
-struct bt_ctf_packet *bt_notification_packet_end_get_packet(
- struct bt_notification *notification)
-{
- struct bt_ctf_packet *ret = NULL;
- struct bt_notification_packet_end *packet_end;
-
- if (notification->type != BT_NOTIFICATION_TYPE_PACKET_END) {
- goto end;
- }
-
- packet_end = container_of(notification,
- struct bt_notification_packet_end, parent);
- ret = bt_get(packet_end->packet);
-end:
- return ret;
-}
+++ /dev/null
-/*
- * Babeltrace Plug-in Stream-related Notifications
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/graph/notification-stream-internal.h>
-
-static
-void bt_notification_stream_end_destroy(struct bt_object *obj)
-{
- struct bt_notification_stream_end *notification =
- (struct bt_notification_stream_end *) obj;
-
- BT_PUT(notification->stream);
- g_free(notification);
-}
-
-struct bt_notification *bt_notification_stream_end_create(
- struct bt_ctf_stream *stream)
-{
- struct bt_notification_stream_end *notification;
-
- if (!stream) {
- goto error;
- }
-
- notification = g_new0(struct bt_notification_stream_end, 1);
- bt_notification_init(¬ification->parent,
- BT_NOTIFICATION_TYPE_STREAM_END,
- bt_notification_stream_end_destroy);
- notification->stream = bt_get(stream);
- return ¬ification->parent;
-error:
- return NULL;
-}
-
-struct bt_ctf_packet *bt_notification_stream_end_get_stream(
- struct bt_notification *notification)
-{
- struct bt_notification_stream_end *stream_end;
-
- stream_end = container_of(notification,
- struct bt_notification_stream_end, parent);
- return bt_get(stream_end->stream);
-}
+++ /dev/null
-/*
- * port.c
- *
- * Babeltrace Port
- *
- * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/port-internal.h>
-#include <babeltrace/graph/connection-internal.h>
-#include <babeltrace/object-internal.h>
-#include <babeltrace/compiler-internal.h>
-
-static
-void bt_port_destroy(struct bt_object *obj)
-{
- struct bt_port *port = container_of(obj, struct bt_port, base);
-
- if (port->name) {
- g_string_free(port->name, TRUE);
- }
- g_free(port);
-}
-
-struct bt_port *bt_port_from_private_port(
- struct bt_private_port *private_port)
-{
- return bt_get(bt_port_from_private(private_port));
-}
-
-BT_HIDDEN
-struct bt_port *bt_port_create(struct bt_component *parent_component,
- enum bt_port_type type, const char *name)
-{
- struct bt_port *port = NULL;
-
- assert(name);
- assert(parent_component);
- assert(type == BT_PORT_TYPE_INPUT || type == BT_PORT_TYPE_OUTPUT);
-
- if (strlen(name) == 0) {
- goto end;
- }
-
- port = g_new0(struct bt_port, 1);
- if (!port) {
- goto end;
- }
-
- bt_object_init(port, bt_port_destroy);
- port->name = g_string_new(name);
- if (!port->name) {
- BT_PUT(port);
- goto end;
- }
-
- port->type = type;
-
- bt_object_set_parent(port, &parent_component->base);
-end:
- return port;
-}
-
-const char *bt_port_get_name(struct bt_port *port)
-{
- return port ? port->name->str : NULL;
-}
-
-enum bt_port_type bt_port_get_type(struct bt_port *port)
-{
- return port ? port->type : BT_PORT_TYPE_UNKOWN;
-}
-
-struct bt_connection *bt_port_get_connection(struct bt_port *port)
-{
- struct bt_connection *connection = NULL;
-
- if (!port || !port->connection) {
- goto end;
- }
-
- connection = bt_get(port->connection);
-end:
- return connection;
-}
-
-struct bt_component *bt_port_get_component(struct bt_port *port)
-{
- return (struct bt_component *) bt_object_get_parent(port);
-}
-
-struct bt_private_connection *bt_private_port_get_private_connection(
- struct bt_private_port *private_port)
-{
- return bt_private_connection_from_connection(bt_port_get_connection(
- bt_port_from_private(private_port)));
-}
-
-struct bt_private_component *bt_private_port_get_private_component(
- struct bt_private_port *private_port)
-{
- return bt_private_component_from_component(bt_port_get_component(
- bt_port_from_private(private_port)));
-}
-
-BT_HIDDEN
-void bt_port_set_connection(struct bt_port *port,
- struct bt_connection *connection)
-{
- /*
- * Don't take a reference on connection as its existence is
- * guaranteed by the existence of the graph in which the
- * connection exists.
- */
- port->connection = connection;
-}
-
-int bt_private_port_remove_from_component(
- struct bt_private_port *private_port)
-{
- int ret = 0;
- struct bt_port *port = bt_port_from_private(private_port);
- struct bt_component *comp = NULL;
-
- if (!port) {
- ret = -1;
- goto end;
- }
-
- comp = (void *) bt_object_get_parent(port);
- ret = bt_component_remove_port(comp, port);
-
-end:
- bt_put(comp);
- return ret;
-}
-
-int bt_port_disconnect(struct bt_port *port)
-{
- int ret = 0;
-
- if (!port) {
- ret = -1;
- goto end;
- }
-
- if (port->connection) {
- bt_connection_disconnect_ports(port->connection);
- }
-
-end:
- return ret;
-}
-
-int bt_port_is_connected(struct bt_port *port)
-{
- int ret;
-
- if (!port) {
- ret = -1;
- goto end;
- }
-
- ret = port->connection ? 1 : 0;
-
-end:
- return ret;
-}
-
-int bt_private_port_set_user_data(
- struct bt_private_port *private_port, void *user_data)
-{
- int ret = 0;
-
- if (!private_port) {
- ret = -1;
- goto end;
- }
-
- bt_port_from_private(private_port)->user_data = user_data;
-
-end:
- return ret;
-}
-
-void *bt_private_port_get_user_data(
- struct bt_private_port *private_port)
-{
- return private_port ?
- bt_port_from_private(private_port)->user_data : NULL;
-}
+++ /dev/null
-/*
- * sink.c
- *
- * Babeltrace Sink Component
- *
- * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/values.h>
-#include <babeltrace/graph/component-sink-internal.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/notification.h>
-
-BT_HIDDEN
-enum bt_component_status bt_component_sink_validate(
- struct bt_component *component)
-{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
- if (!component) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (!component->class) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-end:
- return ret;
-}
-
-BT_HIDDEN
-void bt_component_sink_destroy(struct bt_component *component)
-{
-}
-
-BT_HIDDEN
-struct bt_component *bt_component_sink_create(
- struct bt_component_class *class, struct bt_value *params)
-{
- struct bt_component_sink *sink = NULL;
-
- sink = g_new0(struct bt_component_sink, 1);
- if (!sink) {
- goto end;
- }
-
-end:
- return sink ? &sink->parent : NULL;
-}
-
-BT_HIDDEN
-enum bt_component_status bt_component_sink_consume(
- struct bt_component *component)
-{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- struct bt_component_class_sink *sink_class = NULL;
-
- if (!component) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (bt_component_get_class_type(component) != BT_COMPONENT_CLASS_TYPE_SINK) {
- ret = BT_COMPONENT_STATUS_UNSUPPORTED;
- goto end;
- }
-
- sink_class = container_of(component->class, struct bt_component_class_sink, parent);
- assert(sink_class->methods.consume);
- ret = sink_class->methods.consume(bt_private_component_from_component(component));
-end:
- return ret;
-}
-
-enum bt_component_status bt_component_sink_get_input_port_count(
- struct bt_component *component, uint64_t *count)
-{
- enum bt_component_status status = BT_COMPONENT_STATUS_OK;
-
- if (!component || !count ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
- status = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- *count = bt_component_get_input_port_count(component);
-end:
- return status;
-}
-
-struct bt_port *bt_component_sink_get_input_port(
- struct bt_component *component, const char *name)
-{
- struct bt_port *port = NULL;
-
- if (!component || !name ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
- goto end;
- }
-
- port = bt_component_get_input_port(component, name);
-end:
- return port;
-}
-
-struct bt_port *bt_component_sink_get_input_port_at_index(
- struct bt_component *component, int index)
-{
- struct bt_port *port = NULL;
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
- goto end;
- }
-
- port = bt_component_get_input_port_at_index(component, index);
-end:
- return port;
-}
-
-struct bt_port *bt_component_sink_get_default_input_port(
- struct bt_component *component)
-{
- return bt_component_sink_get_input_port(component,
- DEFAULT_INPUT_PORT_NAME);
-}
-
-struct bt_private_port *
-bt_private_component_sink_get_input_private_port_at_index(
- struct bt_private_component *private_component, int index)
-{
- return bt_private_port_from_port(
- bt_component_sink_get_input_port_at_index(
- bt_component_from_private(private_component), index));
-}
-
-struct bt_private_port *bt_private_component_sink_get_default_input_private_port(
- struct bt_private_component *private_component)
-{
- return bt_private_port_from_port(
- bt_component_sink_get_default_input_port(
- bt_component_from_private(private_component)));
-}
-
-struct bt_private_port *bt_private_component_sink_add_input_private_port(
- struct bt_private_component *private_component,
- const char *name)
-{
- struct bt_port *port = NULL;
- struct bt_component *component =
- bt_component_from_private(private_component);
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
- goto end;
- }
-
- port = bt_component_add_input_port(component, name);
-end:
- return bt_private_port_from_port(port);
-}
+++ /dev/null
-/*
- * source.c
- *
- * Babeltrace Source Component
- *
- * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/ref.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/graph/component-source-internal.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/graph/port-internal.h>
-#include <babeltrace/graph/notification-iterator.h>
-#include <babeltrace/graph/notification-iterator-internal.h>
-
-BT_HIDDEN
-enum bt_component_status bt_component_source_validate(
- struct bt_component *component)
-{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
-
- if (!component) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (!component->class) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- if (component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- ret = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-void bt_component_source_destroy(struct bt_component *component)
-{
-}
-
-BT_HIDDEN
-struct bt_component *bt_component_source_create(
- struct bt_component_class *class, struct bt_value *params)
-{
- struct bt_component_source *source = NULL;
-
- source = g_new0(struct bt_component_source, 1);
- if (!source) {
- goto end;
- }
-
-end:
- return source ? &source->parent : NULL;
-}
-
-enum bt_component_status bt_component_source_get_output_port_count(
- struct bt_component *component, uint64_t *count)
-{
- enum bt_component_status status = BT_COMPONENT_STATUS_OK;
-
- if (!component || !count ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- status = BT_COMPONENT_STATUS_INVALID;
- goto end;
- }
-
- *count = bt_component_get_output_port_count(component);
-end:
- return status;
-}
-
-struct bt_port *bt_component_source_get_output_port(
- struct bt_component *component, const char *name)
-{
- struct bt_port *port = NULL;
-
- if (!component || !name ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- goto end;
- }
-
- port = bt_component_get_output_port(component, name);
-end:
- return port;
-}
-
-struct bt_port *bt_component_source_get_output_port_at_index(
- struct bt_component *component, int index)
-{
- struct bt_port *port = NULL;
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- goto end;
- }
-
- port = bt_component_get_output_port_at_index(component, index);
-end:
- return port;
-}
-
-struct bt_port *bt_component_source_get_default_output_port(
- struct bt_component *component)
-{
- return bt_component_source_get_output_port(component,
- DEFAULT_OUTPUT_PORT_NAME);
-}
-
-struct bt_private_port *bt_private_component_source_get_output_private_port(
- struct bt_private_component *private_component,
- const char *name)
-{
- return bt_private_port_from_port(bt_component_source_get_output_port(
- bt_component_from_private(private_component), name));
-}
-
-struct bt_private_port *
-bt_private_component_source_get_output_private_port_at_index(
- struct bt_private_component *private_component, int index)
-{
- return bt_private_port_from_port(
- bt_component_source_get_output_port_at_index(
- bt_component_from_private(private_component), index));
-}
-
-struct bt_private_port *bt_private_component_source_get_default_output_private_port(
- struct bt_private_component *private_component)
-{
- return bt_private_port_from_port(
- bt_component_source_get_default_output_port(
- bt_component_from_private(private_component)));
-}
-
-struct bt_private_port *bt_private_component_source_add_output_private_port(
- struct bt_private_component *private_component,
- const char *name)
-{
- struct bt_port *port = NULL;
- struct bt_component *component =
- bt_component_from_private(private_component);
-
- if (!component ||
- component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
- goto end;
- }
-
- port = bt_component_add_output_port(component, name);
-end:
- return bt_private_port_from_port(port);
-}
--- /dev/null
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
+
+SUBDIRS = notification
+
+noinst_LTLIBRARIES = libgraph.la
+
+# Graph library
+libgraph_la_SOURCES = \
+ clock-class-priority-map.c \
+ component.c \
+ component-class.c \
+ graph.c \
+ connection.c \
+ port.c \
+ source.c \
+ sink.c \
+ filter.c \
+ iterator.c
+
+libgraph_la_LIBADD = \
+ notification/libgraph-notification.la
--- /dev/null
+/*
+ * clock-class-priority-map.c
+ *
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include <babeltrace/graph/clock-class-priority-map-internal.h>
+#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/ctf-ir/clock-class-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ref.h>
+#include <glib.h>
+
+static
+void bt_clock_class_priority_map_destroy(struct bt_object *obj)
+{
+ struct bt_clock_class_priority_map *cc_prio_map = (void *) obj;
+
+ if (!cc_prio_map) {
+ return;
+ }
+
+ if (cc_prio_map->entries) {
+ g_ptr_array_free(cc_prio_map->entries, TRUE);
+ }
+
+ if (cc_prio_map->prios) {
+ g_hash_table_destroy(cc_prio_map->prios);
+ }
+
+ g_free(cc_prio_map);
+}
+
+struct bt_clock_class_priority_map *bt_clock_class_priority_map_create()
+{
+ struct bt_clock_class_priority_map *cc_prio_map = NULL;
+
+ cc_prio_map = g_new0(struct bt_clock_class_priority_map, 1);
+ if (!cc_prio_map) {
+ goto error;
+ }
+
+ bt_object_init(cc_prio_map, bt_clock_class_priority_map_destroy);
+ cc_prio_map->entries = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_put);
+ if (!cc_prio_map->entries) {
+ goto error;
+ }
+
+ cc_prio_map->prios = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) g_free);
+ if (!cc_prio_map->entries) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_PUT(cc_prio_map);
+
+end:
+ return cc_prio_map;
+}
+
+int bt_clock_class_priority_map_get_clock_class_count(
+ struct bt_clock_class_priority_map *cc_prio_map)
+{
+ int ret = -1;
+
+ if (!cc_prio_map) {
+ goto end;
+ }
+
+ ret = (int) cc_prio_map->entries->len;
+
+end:
+ return ret;
+}
+
+struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class(
+ struct bt_clock_class_priority_map *cc_prio_map,
+ unsigned int index)
+{
+ struct bt_ctf_clock_class *clock_class = NULL;
+
+ if (!cc_prio_map || index >= cc_prio_map->entries->len) {
+ goto end;
+ }
+
+ clock_class = g_ptr_array_index(cc_prio_map->entries, index);
+ bt_get(clock_class);
+
+end:
+ return clock_class;
+}
+
+struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class_by_name(
+ struct bt_clock_class_priority_map *cc_prio_map,
+ const char *name)
+{
+ size_t i;
+ struct bt_ctf_clock_class *clock_class = NULL;
+
+ if (!cc_prio_map || !name) {
+ goto end;
+ }
+
+ for (i = 0; i < cc_prio_map->entries->len; i++) {
+ struct bt_ctf_clock_class *cur_cc =
+ g_ptr_array_index(cc_prio_map->entries, i);
+ // FIXME when available: use bt_ctf_clock_class_get_name()
+ const char *cur_cc_name =
+ cur_cc->name ? cur_cc->name->str : NULL;
+
+ if (!cur_cc_name) {
+ goto end;
+ }
+
+ if (strcmp(cur_cc_name, name) == 0) {
+ clock_class = bt_get(cur_cc);
+ goto end;
+ }
+ }
+
+end:
+ return clock_class;
+}
+
+
+struct clock_class_prio {
+ uint64_t prio;
+ struct bt_ctf_clock_class *clock_class;
+};
+
+static
+void current_highest_prio_gh_func(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ struct clock_class_prio *func_data = user_data;
+ uint64_t *prio = value;
+
+ if (*prio <= func_data->prio) {
+ func_data->prio = *prio;
+ func_data->clock_class = key;
+ }
+}
+
+static
+struct clock_class_prio bt_ctf_clock_class_priority_map_current_highest_prio(
+ struct bt_clock_class_priority_map *cc_prio_map)
+{
+ struct clock_class_prio func_data = {
+ .prio = -1ULL,
+ .clock_class = NULL,
+ };
+
+ g_hash_table_foreach(cc_prio_map->prios, current_highest_prio_gh_func,
+ &func_data);
+ return func_data;
+}
+
+struct bt_ctf_clock_class *
+bt_clock_class_priority_map_get_highest_priority_clock_class(
+ struct bt_clock_class_priority_map *cc_prio_map)
+{
+ struct bt_ctf_clock_class *clock_class = NULL;
+
+ if (!cc_prio_map) {
+ goto end;
+ }
+
+ clock_class = bt_get(cc_prio_map->highest_prio_cc);
+
+end:
+ return clock_class;
+}
+
+int bt_clock_class_priority_map_get_clock_class_priority(
+ struct bt_clock_class_priority_map *cc_prio_map,
+ struct bt_ctf_clock_class *clock_class, uint64_t *priority)
+{
+ int ret = 0;
+ uint64_t *prio;
+
+ if (!cc_prio_map || !clock_class || !priority) {
+ ret = -1;
+ goto end;
+ }
+
+ prio = g_hash_table_lookup(cc_prio_map->prios, clock_class);
+ if (!prio) {
+ ret = -1;
+ goto end;
+ }
+
+ *priority = *prio;
+
+end:
+ return ret;
+}
+
+int bt_clock_class_priority_map_add_clock_class(
+ struct bt_clock_class_priority_map *cc_prio_map,
+ struct bt_ctf_clock_class *clock_class, uint64_t priority)
+{
+ int ret = 0;
+ uint64_t *prio_ptr = NULL;
+ struct clock_class_prio cc_prio;
+
+ // FIXME when available: check
+ // bt_ctf_clock_class_is_valid(clock_class)
+ if (!cc_prio_map) {
+ ret = -1;
+ goto end;
+ }
+
+ /* Check for duplicate clock classes */
+ prio_ptr = g_hash_table_lookup(cc_prio_map->prios, clock_class);
+ if (prio_ptr) {
+ prio_ptr = NULL;
+ ret = -1;
+ goto end;
+ }
+
+ prio_ptr = g_new(uint64_t, 1);
+ if (!prio_ptr) {
+ ret = -1;
+ goto end;
+ }
+
+ *prio_ptr = priority;
+ bt_get(clock_class);
+ g_ptr_array_add(cc_prio_map->entries, clock_class);
+ g_hash_table_insert(cc_prio_map->prios, clock_class, prio_ptr);
+ prio_ptr = NULL;
+ cc_prio = bt_ctf_clock_class_priority_map_current_highest_prio(
+ cc_prio_map);
+ assert(cc_prio.clock_class);
+ cc_prio_map->highest_prio_cc = cc_prio.clock_class;
+
+end:
+ if (prio_ptr) {
+ g_free(prio_ptr);
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * component-class.c
+ *
+ * Babeltrace Plugin Component Class
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/graph/component-class-internal.h>
+#include <babeltrace/ref.h>
+#include <stdbool.h>
+#include <glib.h>
+
+static
+void bt_component_class_destroy(struct bt_object *obj)
+{
+ struct bt_component_class *class;
+ int i;
+
+ assert(obj);
+ class = container_of(obj, struct bt_component_class, base);
+
+ /* Call destroy listeners in reverse registration order */
+ for (i = class->destroy_listeners->len - 1; i >= 0; i--) {
+ struct bt_component_class_destroy_listener *listener =
+ &g_array_index(class->destroy_listeners,
+ struct bt_component_class_destroy_listener,
+ i);
+
+ listener->func(class, listener->data);
+ }
+
+ if (class->name) {
+ g_string_free(class->name, TRUE);
+ }
+ if (class->description) {
+ g_string_free(class->description, TRUE);
+ }
+ if (class->help) {
+ g_string_free(class->help, TRUE);
+ }
+ if (class->destroy_listeners) {
+ g_array_free(class->destroy_listeners, TRUE);
+ }
+
+ g_free(class);
+}
+
+static
+int bt_component_class_init(struct bt_component_class *class,
+ enum bt_component_class_type type, const char *name)
+{
+ int ret = 0;
+
+ bt_object_init(class, bt_component_class_destroy);
+ class->type = type;
+ class->name = g_string_new(name);
+ if (!class->name) {
+ goto error;
+ }
+
+ class->description = g_string_new(NULL);
+ if (!class->description) {
+ goto error;
+ }
+
+ class->help = g_string_new(NULL);
+ if (!class->help) {
+ goto error;
+ }
+
+ class->destroy_listeners = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_component_class_destroy_listener));
+ if (!class->destroy_listeners) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_PUT(class);
+ ret = -1;
+
+end:
+ return ret;
+}
+
+struct bt_component_class *bt_component_class_source_create(const char *name,
+ bt_component_class_notification_iterator_next_method notification_iterator_next_method)
+{
+ struct bt_component_class_source *source_class = NULL;
+ int ret;
+
+ if (!name || !notification_iterator_next_method) {
+ goto end;
+ }
+
+ source_class = g_new0(struct bt_component_class_source, 1);
+ if (!source_class) {
+ goto end;
+ }
+
+ ret = bt_component_class_init(&source_class->parent,
+ BT_COMPONENT_CLASS_TYPE_SOURCE, name);
+ if (ret) {
+ /*
+ * If bt_component_class_init() fails, the component
+ * class is put, therefore its memory is already
+ * freed.
+ */
+ source_class = NULL;
+ goto end;
+ }
+
+ source_class->methods.iterator.next = notification_iterator_next_method;
+
+end:
+ return &source_class->parent;
+}
+
+struct bt_component_class *bt_component_class_filter_create(const char *name,
+ bt_component_class_notification_iterator_next_method notification_iterator_next_method)
+{
+ struct bt_component_class_filter *filter_class = NULL;
+ int ret;
+
+ if (!name || !notification_iterator_next_method) {
+ goto end;
+ }
+
+ filter_class = g_new0(struct bt_component_class_filter, 1);
+ if (!filter_class) {
+ goto end;
+ }
+
+ ret = bt_component_class_init(&filter_class->parent,
+ BT_COMPONENT_CLASS_TYPE_FILTER, name);
+ if (ret) {
+ /*
+ * If bt_component_class_init() fails, the component
+ * class is put, therefore its memory is already
+ * freed.
+ */
+ filter_class = NULL;
+ goto end;
+ }
+
+ filter_class->methods.iterator.next = notification_iterator_next_method;
+
+end:
+ return &filter_class->parent;
+}
+
+struct bt_component_class *bt_component_class_sink_create(const char *name,
+ bt_component_class_sink_consume_method consume_method)
+{
+ struct bt_component_class_sink *sink_class = NULL;
+ int ret;
+
+ if (!name || !consume_method) {
+ goto end;
+ }
+
+ sink_class = g_new0(struct bt_component_class_sink, 1);
+ if (!sink_class) {
+ goto end;
+ }
+
+ ret = bt_component_class_init(&sink_class->parent,
+ BT_COMPONENT_CLASS_TYPE_SINK, name);
+ if (ret) {
+ /*
+ * If bt_component_class_init() fails, the component
+ * class is put, therefore its memory is already
+ * freed.
+ */
+ sink_class = NULL;
+ goto end;
+ }
+
+ sink_class->methods.consume = consume_method;
+
+end:
+ return &sink_class->parent;
+}
+
+int bt_component_class_set_init_method(
+ struct bt_component_class *component_class,
+ bt_component_class_init_method init_method)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !init_method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.init = init_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_set_query_method(
+ struct bt_component_class *component_class,
+ bt_component_class_query_method query_method)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !query_method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.query = query_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_set_accept_port_connection_method(
+ struct bt_component_class *component_class,
+ bt_component_class_accept_port_connection_method method)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.accept_port_connection = 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)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.port_disconnected = method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_set_finalize_method(
+ struct bt_component_class *component_class,
+ bt_component_class_finalize_method finalize_method)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !finalize_method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.finalize = finalize_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_source_set_notification_iterator_init_method(
+ struct bt_component_class *component_class,
+ bt_component_class_notification_iterator_init_method notification_iterator_init_method)
+{
+ struct bt_component_class_source *source_class;
+ int ret = 0;
+
+ if (!component_class || component_class->frozen ||
+ !notification_iterator_init_method ||
+ component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ ret = -1;
+ goto end;
+ }
+
+ source_class = container_of(component_class,
+ struct bt_component_class_source, parent);
+ source_class->methods.iterator.init = notification_iterator_init_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_source_set_notification_iterator_finalize_method(
+ struct bt_component_class *component_class,
+ bt_component_class_notification_iterator_finalize_method notification_iterator_finalize_method)
+{
+ struct bt_component_class_source *source_class;
+ int ret = 0;
+
+ if (!component_class || component_class->frozen ||
+ !notification_iterator_finalize_method ||
+ component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ ret = -1;
+ goto end;
+ }
+
+ source_class = container_of(component_class,
+ struct bt_component_class_source, parent);
+ source_class->methods.iterator.finalize =
+ notification_iterator_finalize_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_source_set_notification_iterator_seek_time_method(
+ struct bt_component_class *component_class,
+ bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
+{
+ struct bt_component_class_source *source_class;
+ int ret = 0;
+
+ if (!component_class || component_class->frozen ||
+ !notification_iterator_seek_time_method ||
+ component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ ret = -1;
+ goto end;
+ }
+
+ source_class = container_of(component_class,
+ struct bt_component_class_source, parent);
+ source_class->methods.iterator.seek_time =
+ notification_iterator_seek_time_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_filter_set_notification_iterator_init_method(
+ struct bt_component_class *component_class,
+ bt_component_class_notification_iterator_init_method notification_iterator_init_method)
+{
+ struct bt_component_class_filter *filter_class;
+ int ret = 0;
+
+ if (!component_class || component_class->frozen ||
+ !notification_iterator_init_method ||
+ component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ ret = -1;
+ goto end;
+ }
+
+ filter_class = container_of(component_class,
+ struct bt_component_class_filter, parent);
+ filter_class->methods.iterator.init = notification_iterator_init_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_filter_set_notification_iterator_finalize_method(
+ struct bt_component_class *component_class,
+ bt_component_class_notification_iterator_finalize_method notification_iterator_finalize_method)
+{
+ struct bt_component_class_filter *filter_class;
+ int ret = 0;
+
+ if (!component_class || component_class->frozen ||
+ !notification_iterator_finalize_method ||
+ component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ ret = -1;
+ goto end;
+ }
+
+ filter_class = container_of(component_class,
+ struct bt_component_class_filter, parent);
+ filter_class->methods.iterator.finalize =
+ notification_iterator_finalize_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_filter_set_notification_iterator_seek_time_method(
+ struct bt_component_class *component_class,
+ bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
+{
+ struct bt_component_class_filter *filter_class;
+ int ret = 0;
+
+ if (!component_class || component_class->frozen ||
+ !notification_iterator_seek_time_method ||
+ component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ ret = -1;
+ goto end;
+ }
+
+ filter_class = container_of(component_class,
+ struct bt_component_class_filter, parent);
+ filter_class->methods.iterator.seek_time =
+ notification_iterator_seek_time_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_set_description(
+ struct bt_component_class *component_class,
+ const char *description)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !description) {
+ ret = -1;
+ goto end;
+ }
+
+ g_string_assign(component_class->description, description);
+
+end:
+ return ret;
+}
+
+int bt_component_class_set_help(
+ struct bt_component_class *component_class,
+ const char *help)
+{
+ int ret = 0;
+
+ if (!component_class || component_class->frozen || !help) {
+ ret = -1;
+ goto end;
+ }
+
+ g_string_assign(component_class->help, help);
+
+end:
+ return ret;
+}
+
+const char *bt_component_class_get_name(
+ struct bt_component_class *component_class)
+{
+ return component_class ? component_class->name->str : NULL;
+}
+
+enum bt_component_class_type bt_component_class_get_type(
+ struct bt_component_class *component_class)
+{
+ return component_class ? component_class->type :
+ BT_COMPONENT_CLASS_TYPE_UNKNOWN;
+}
+
+const char *bt_component_class_get_description(
+ struct bt_component_class *component_class)
+{
+ return component_class && component_class->description &&
+ component_class->description->str[0] != '\0' ?
+ component_class->description->str : NULL;
+}
+
+const char *bt_component_class_get_help(
+ struct bt_component_class *component_class)
+{
+ return component_class && component_class->help &&
+ component_class->help->str[0] != '\0' ?
+ component_class->help->str : NULL;
+}
+
+BT_HIDDEN
+int bt_component_class_add_destroy_listener(struct bt_component_class *class,
+ bt_component_class_destroy_listener_func func, void *data)
+{
+ int ret = 0;
+ struct bt_component_class_destroy_listener listener;
+
+ if (!class || class->frozen || !func) {
+ ret = -1;
+ goto end;
+ }
+
+ listener.func = func;
+ listener.data = data;
+ g_array_append_val(class->destroy_listeners, listener);
+
+end:
+ return ret;
+}
+
+int bt_component_class_freeze(
+ struct bt_component_class *component_class)
+{
+ int ret = 0;
+
+ if (!component_class) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->frozen = true;
+
+end:
+ return ret;
+}
+
+struct bt_value *bt_component_class_query(
+ struct bt_component_class *component_class,
+ const char *object, struct bt_value *params)
+{
+ struct bt_value *results = NULL;
+
+ if (!component_class || !object || !params ||
+ !component_class->methods.query) {
+ goto end;
+ }
+
+ results = component_class->methods.query(component_class,
+ object, params);
+
+end:
+ return results;
+}
--- /dev/null
+/*
+ * component.c
+ *
+ * Babeltrace Plugin Component
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/private-component.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/component-class-internal.h>
+#include <babeltrace/graph/component-source-internal.h>
+#include <babeltrace/graph/component-filter-internal.h>
+#include <babeltrace/graph/component-sink-internal.h>
+#include <babeltrace/graph/private-connection.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/babeltrace-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ref.h>
+
+static
+struct bt_component * (* const component_create_funcs[])(
+ struct bt_component_class *, struct bt_value *) = {
+ [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
+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 *) = {
+ [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)
+{
+ struct bt_component *component = NULL;
+ struct bt_component_class *component_class = NULL;
+
+ if (!obj) {
+ return;
+ }
+
+ component = container_of(obj, struct bt_component, base);
+ component_class = component->class;
+
+ /*
+ * User data is destroyed first, followed by the concrete component
+ * instance.
+ */
+ if (component->class->methods.finalize) {
+ component->class->methods.finalize(
+ bt_private_component_from_component(component));
+ }
+
+ if (component->destroy) {
+ component->destroy(component);
+ }
+
+ if (component->input_ports) {
+ g_ptr_array_free(component->input_ports, TRUE);
+ }
+
+ if (component->output_ports) {
+ g_ptr_array_free(component->output_ports, TRUE);
+ }
+
+ g_string_free(component->name, TRUE);
+ bt_put(component_class);
+ g_free(component);
+}
+
+struct bt_component *bt_component_from_private_component(
+ struct bt_private_component *private_component)
+{
+ return bt_get(bt_component_from_private(private_component));
+}
+
+enum bt_component_class_type bt_component_get_class_type(
+ struct bt_component *component)
+{
+ return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
+}
+
+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;
+ struct bt_graph *graph = 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);
+
+ /*
+ * Notify the graph's creator that a new port was added.
+ */
+ graph = bt_component_get_graph(component);
+ if (graph) {
+ bt_graph_notify_port_added(graph, new_port);
+ BT_PUT(graph);
+ }
+
+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, 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) {
+ goto end;
+ }
+
+ component = component_create_funcs[type](component_class, params);
+ if (!component) {
+ goto end;
+ }
+
+ 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(
+ 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(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;
+
+ if (!component) {
+ 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_component_class *bt_component_get_class(
+ struct bt_component *component)
+{
+ return component ? bt_get(component->class) : NULL;
+}
+
+void *bt_private_component_get_user_data(
+ struct bt_private_component *private_component)
+{
+ struct bt_component *component =
+ bt_component_from_private(private_component);
+
+ return component ? component->user_data : NULL;
+}
+
+enum bt_component_status bt_private_component_set_user_data(
+ struct bt_private_component *private_component,
+ void *data)
+{
+ struct bt_component *component =
+ bt_component_from_private(private_component);
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+ if (!component || !component->initializing) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ component->user_data = data;
+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;
+ struct bt_graph *graph;
+
+ 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);
+ }
+
+ /* 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);
+
+ /*
+ * Notify the graph's creator that a port is removed.
+ */
+ graph = bt_component_get_graph(component);
+ if (graph) {
+ bt_graph_notify_port_removed(graph, component, port);
+ BT_PUT(graph);
+ }
+}
+
+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 *self_port,
+ struct bt_port *other_port)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ assert(comp);
+ assert(self_port);
+ assert(other_port);
+
+ if (comp->class->methods.accept_port_connection) {
+ status = comp->class->methods.accept_port_connection(
+ bt_private_component_from_component(comp),
+ bt_private_port_from_port(self_port),
+ other_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(
+ bt_private_component_from_component(comp),
+ bt_private_port_from_port(port));
+ }
+}
--- /dev/null
+/*
+ * connection.c
+ *
+ * Babeltrace Connection
+ *
+ * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/notification-iterator-internal.h>
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/component-source-internal.h>
+#include <babeltrace/graph/component-filter-internal.h>
+#include <babeltrace/graph/connection-internal.h>
+#include <babeltrace/graph/private-connection.h>
+#include <babeltrace/graph/graph-internal.h>
+#include <babeltrace/graph/port-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <glib.h>
+
+static
+void bt_connection_destroy(struct bt_object *obj)
+{
+ struct bt_connection *connection = container_of(obj,
+ struct bt_connection, base);
+
+ /*
+ * No bt_put on ports as a connection only holds _weak_ references
+ * to them.
+ */
+ g_free(connection);
+}
+
+struct bt_connection *bt_connection_from_private_connection(
+ struct bt_private_connection *private_connection)
+{
+ return bt_get(bt_connection_from_private(private_connection));
+}
+
+BT_HIDDEN
+struct bt_connection *bt_connection_create(
+ struct bt_graph *graph,
+ struct bt_port *upstream_port,
+ struct bt_port *downstream_port)
+{
+ struct bt_connection *connection = NULL;
+
+ if (bt_port_get_type(upstream_port) != BT_PORT_TYPE_OUTPUT) {
+ goto end;
+ }
+ if (bt_port_get_type(downstream_port) != BT_PORT_TYPE_INPUT) {
+ goto end;
+ }
+
+ connection = g_new0(struct bt_connection, 1);
+ if (!connection) {
+ goto end;
+ }
+
+ bt_object_init(connection, bt_connection_destroy);
+ /* Weak references are taken, see comment in header. */
+ connection->upstream_port = upstream_port;
+ connection->downstream_port = downstream_port;
+ bt_port_set_connection(upstream_port, connection);
+ bt_port_set_connection(downstream_port, connection);
+ bt_object_set_parent(connection, &graph->base);
+end:
+ return connection;
+}
+
+BT_HIDDEN
+void bt_connection_disconnect_ports(struct bt_connection *conn)
+{
+ struct bt_component *downstream_comp = NULL;
+ struct bt_component *upstream_comp = NULL;
+ struct bt_port *downstream_port = conn->downstream_port;
+ struct bt_port *upstream_port = conn->upstream_port;
+ struct bt_graph *graph = (void *) bt_object_get_parent(conn);
+
+ if (downstream_port) {
+ downstream_comp = bt_port_get_component(downstream_port);
+ bt_port_set_connection(downstream_port, NULL);
+ conn->downstream_port = NULL;
+ }
+
+ if (upstream_port) {
+ upstream_comp = bt_port_get_component(upstream_port);
+ bt_port_set_connection(upstream_port, NULL);
+ conn->upstream_port = NULL;
+ }
+
+ if (downstream_comp) {
+ bt_component_port_disconnected(downstream_comp,
+ downstream_port);
+ }
+
+ if (upstream_comp) {
+ bt_component_port_disconnected(upstream_comp, upstream_port);
+ }
+
+ assert(graph);
+ bt_graph_notify_ports_disconnected(graph, upstream_comp,
+ downstream_comp, upstream_port, downstream_port);
+ bt_put(downstream_comp);
+ bt_put(upstream_comp);
+ bt_put(graph);
+}
+
+struct bt_port *bt_connection_get_upstream_port(
+ struct bt_connection *connection)
+{
+ return connection ? bt_get(connection->upstream_port) : NULL;
+}
+
+struct bt_port *bt_connection_get_downstream_port(
+ struct bt_connection *connection)
+{
+ return connection ? bt_get(connection->downstream_port) : NULL;
+}
+
+struct bt_notification_iterator *
+bt_private_connection_create_notification_iterator(
+ struct bt_private_connection *private_connection)
+{
+ enum bt_notification_iterator_status ret_iterator;
+ enum bt_component_class_type upstream_comp_class_type;
+ struct bt_notification_iterator *iterator = NULL;
+ struct bt_port *upstream_port = NULL;
+ struct bt_component *upstream_component = NULL;
+ struct bt_component_class *upstream_comp_class = NULL;
+ struct bt_connection *connection = NULL;
+ bt_component_class_notification_iterator_init_method init_method = NULL;
+
+ if (!private_connection) {
+ goto error;
+ }
+
+ connection = bt_connection_from_private(private_connection);
+
+ if (!connection->upstream_port || !connection->downstream_port) {
+ goto error;
+ }
+
+ upstream_port = connection->upstream_port;
+ assert(upstream_port);
+ upstream_component = bt_port_get_component(upstream_port);
+ assert(upstream_component);
+ upstream_comp_class = upstream_component->class;
+
+ if (!upstream_component) {
+ goto error;
+ }
+
+ upstream_comp_class_type =
+ bt_component_get_class_type(upstream_component);
+ if (upstream_comp_class_type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
+ upstream_comp_class_type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ /* Unsupported operation. */
+ goto error;
+ }
+
+ iterator = bt_notification_iterator_create(upstream_component);
+ if (!iterator) {
+ goto error;
+ }
+
+ switch (upstream_comp_class_type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ {
+ struct bt_component_class_source *source_class =
+ container_of(upstream_comp_class,
+ struct bt_component_class_source, parent);
+ init_method = source_class->methods.iterator.init;
+ break;
+ }
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ {
+ struct bt_component_class_filter *filter_class =
+ container_of(upstream_comp_class,
+ struct bt_component_class_filter, parent);
+ init_method = filter_class->methods.iterator.init;
+ break;
+ }
+ default:
+ /* Unreachable. */
+ assert(0);
+ }
+
+ if (init_method) {
+ enum bt_notification_iterator_status status = init_method(
+ bt_private_notification_iterator_from_notification_iterator(iterator),
+ bt_private_port_from_port(upstream_port));
+ if (status < 0) {
+ goto error;
+ }
+ }
+
+ ret_iterator = bt_notification_iterator_validate(iterator);
+ if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_PUT(iterator);
+
+end:
+ bt_put(upstream_component);
+ return iterator;
+}
--- /dev/null
+/*
+ * filter.c
+ *
+ * Babeltrace Filter Component
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/values.h>
+#include <babeltrace/graph/component-filter-internal.h>
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/component-class-internal.h>
+#include <babeltrace/graph/notification.h>
+#include <babeltrace/graph/notification-iterator-internal.h>
+
+BT_HIDDEN
+void bt_component_filter_destroy(struct bt_component *component)
+{
+}
+
+BT_HIDDEN
+struct bt_component *bt_component_filter_create(
+ struct bt_component_class *class, struct bt_value *params)
+{
+ struct bt_component_filter *filter = NULL;
+
+ filter = g_new0(struct bt_component_filter, 1);
+ if (!filter) {
+ goto end;
+ }
+
+end:
+ return filter ? &filter->parent : NULL;
+}
+
+BT_HIDDEN
+enum bt_component_status bt_component_filter_validate(
+ struct bt_component *component)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+ if (!component) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!component->class) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ /* Enforce iterator limits. */
+end:
+ return ret;
+}
+
+enum bt_component_status bt_component_filter_get_input_port_count(
+ struct bt_component *component, uint64_t *count)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ if (!component || !count ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ status = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = bt_component_get_input_port_count(component);
+end:
+ return status;
+}
+
+struct bt_port *bt_component_filter_get_input_port(
+ struct bt_component *component, const char *name)
+{
+ struct bt_port *port = NULL;
+
+ if (!component || !name ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ goto end;
+ }
+
+ port = bt_component_get_input_port(component, name);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_filter_get_input_port_at_index(
+ struct bt_component *component, int index)
+{
+ struct bt_port *port = NULL;
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ goto end;
+ }
+
+ port = bt_component_get_input_port_at_index(component, index);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_filter_get_default_input_port(
+ struct bt_component *component)
+{
+ return bt_component_filter_get_input_port(component,
+ DEFAULT_INPUT_PORT_NAME);
+}
+
+enum bt_component_status bt_component_filter_get_output_port_count(
+ struct bt_component *component, uint64_t *count)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ if (!component || !count ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ status = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = bt_component_get_output_port_count(component);
+end:
+ return status;
+}
+
+struct bt_port *bt_component_filter_get_output_port(
+ struct bt_component *component, const char *name)
+{
+ struct bt_port *port = NULL;
+
+ if (!component || !name ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ goto end;
+ }
+
+ port = bt_component_get_output_port(component, name);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_filter_get_output_port_at_index(
+ struct bt_component *component, int index)
+{
+ struct bt_port *port = NULL;
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ goto end;
+ }
+
+ port = bt_component_get_output_port_at_index(component, index);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_filter_get_default_output_port(
+ struct bt_component *component)
+{
+ return bt_component_filter_get_output_port(component,
+ DEFAULT_OUTPUT_PORT_NAME);
+}
+
+struct bt_private_port *
+bt_private_component_filter_get_input_private_port_at_index(
+ struct bt_private_component *private_component, int index)
+{
+ return bt_private_port_from_port(
+ bt_component_filter_get_input_port_at_index(
+ bt_component_from_private(private_component), index));
+}
+
+struct bt_private_port *
+bt_private_component_filter_get_default_input_private_port(
+ struct bt_private_component *private_component)
+{
+ return bt_private_port_from_port(
+ bt_component_filter_get_default_input_port(
+ bt_component_from_private(private_component)));
+}
+
+struct bt_private_port *bt_private_component_filter_add_input_private_port(
+ struct bt_private_component *private_component,
+ const char *name)
+{
+ struct bt_port *port = NULL;
+ struct bt_component *component =
+ bt_component_from_private(private_component);
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ goto end;
+ }
+
+ port = bt_component_add_input_port(component, name);
+end:
+ return bt_private_port_from_port(port);
+}
+
+struct bt_private_port *
+bt_private_component_filter_get_output_private_port_at_index(
+ struct bt_private_component *private_component, int index)
+{
+ return bt_private_port_from_port(
+ bt_component_filter_get_output_port_at_index(
+ bt_component_from_private(private_component), index));
+}
+
+struct bt_private_port *
+bt_private_component_filter_get_default_output_private_port(
+ struct bt_private_component *private_component)
+{
+ return bt_private_port_from_port(
+ bt_component_filter_get_default_output_port(
+ bt_component_from_private(private_component)));
+}
+
+struct bt_private_port *bt_private_component_filter_add_output_private_port(
+ struct bt_private_component *private_component,
+ const char *name)
+{
+ struct bt_port *port = NULL;
+ struct bt_component *component =
+ bt_component_from_private(private_component);
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
+ goto end;
+ }
+
+ port = bt_component_add_output_port(component, name);
+end:
+ return bt_private_port_from_port(port);
+}
--- /dev/null
+/*
+ * graph.c
+ *
+ * Babeltrace Plugin Component Graph
+ *
+ * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/graph-internal.h>
+#include <babeltrace/graph/connection-internal.h>
+#include <babeltrace/graph/component-sink-internal.h>
+#include <babeltrace/graph/component-source.h>
+#include <babeltrace/graph/component-filter.h>
+#include <babeltrace/graph/port.h>
+#include <babeltrace/compiler-internal.h>
+#include <unistd.h>
+#include <glib.h>
+
+struct bt_graph_listener {
+ void *func;
+ void *data;
+};
+
+static
+void bt_graph_destroy(struct bt_object *obj)
+{
+ struct bt_graph *graph = container_of(obj,
+ struct bt_graph, base);
+
+ if (graph->components) {
+ g_ptr_array_free(graph->components, TRUE);
+ }
+ if (graph->connections) {
+ g_ptr_array_free(graph->connections, TRUE);
+ }
+ if (graph->sinks_to_consume) {
+ g_queue_free(graph->sinks_to_consume);
+ }
+
+ if (graph->listeners.port_added) {
+ g_array_free(graph->listeners.port_added, TRUE);
+ }
+
+ if (graph->listeners.port_removed) {
+ g_array_free(graph->listeners.port_removed, TRUE);
+ }
+
+ if (graph->listeners.ports_connected) {
+ g_array_free(graph->listeners.ports_connected, TRUE);
+ }
+
+ if (graph->listeners.ports_disconnected) {
+ g_array_free(graph->listeners.ports_disconnected, TRUE);
+ }
+
+ g_free(graph);
+}
+
+static
+int init_listeners_array(GArray **listeners)
+{
+ int ret = 0;
+
+ assert(listeners);
+ *listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_graph_listener));
+ if (!*listeners) {
+ ret = -1;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+struct bt_graph *bt_graph_create(void)
+{
+ struct bt_graph *graph;
+ int ret;
+
+ graph = g_new0(struct bt_graph, 1);
+ if (!graph) {
+ goto end;
+ }
+
+ bt_object_init(graph, bt_graph_destroy);
+
+ graph->connections = g_ptr_array_new_with_free_func(bt_object_release);
+ if (!graph->connections) {
+ goto error;
+ }
+ graph->components = g_ptr_array_new_with_free_func(bt_object_release);
+ if (!graph->components) {
+ goto error;
+ }
+ graph->sinks_to_consume = g_queue_new();
+ if (!graph->sinks_to_consume) {
+ goto error;
+ }
+
+ ret = init_listeners_array(&graph->listeners.port_added);
+ if (ret) {
+ goto error;
+ }
+
+ ret = init_listeners_array(&graph->listeners.port_removed);
+ if (ret) {
+ goto error;
+ }
+
+ ret = init_listeners_array(&graph->listeners.ports_connected);
+ if (ret) {
+ goto error;
+ }
+
+ ret = init_listeners_array(&graph->listeners.ports_disconnected);
+ if (ret) {
+ goto error;
+ }
+
+end:
+ return graph;
+error:
+ BT_PUT(graph);
+ goto end;
+}
+
+struct bt_connection *bt_graph_connect_ports(struct bt_graph *graph,
+ struct bt_port *upstream_port,
+ struct bt_port *downstream_port)
+{
+ struct bt_connection *connection = NULL;
+ struct bt_graph *upstream_graph = NULL;
+ 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 appropriate types for upstream and downstream ports. */
+ if (bt_port_get_type(upstream_port) != BT_PORT_TYPE_OUTPUT) {
+ goto end;
+ }
+ if (bt_port_get_type(downstream_port) != BT_PORT_TYPE_INPUT) {
+ goto end;
+ }
+
+ /* Ensure that both ports are currently unconnected. */
+ existing_conn = bt_port_get_connection(upstream_port);
+ bt_put(existing_conn);
+ if (existing_conn) {
+ 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) {
+ fprintf(stderr, "Downstream port is already connected\n");
+ goto end;
+ }
+
+ /*
+ * Ensure that both ports are still attached to their creating
+ * component.
+ */
+ upstream_component = bt_port_get_component(upstream_port);
+ if (!upstream_component) {
+ fprintf(stderr, "Upstream port does not belong to a component\n");
+ goto end;
+ }
+
+ downstream_component = bt_port_get_component(downstream_port);
+ if (!downstream_component) {
+ fprintf(stderr, "Downstream port does not belong to a component\n");
+ goto end;
+ }
+
+ /* Ensure the components are not already part of another graph. */
+ upstream_graph = bt_component_get_graph(upstream_component);
+ if (upstream_graph && (graph != upstream_graph)) {
+ fprintf(stderr, "Upstream component is already part of another graph\n");
+ goto error;
+ }
+ upstream_was_already_in_graph = (graph == upstream_graph);
+ downstream_graph = bt_component_get_graph(downstream_component);
+ if (downstream_graph && (graph != downstream_graph)) {
+ fprintf(stderr, "Downstream component is already part of another graph\n");
+ goto error;
+ }
+ downstream_was_already_in_graph = (graph == downstream_graph);
+
+ connection = bt_connection_create(graph, upstream_port,
+ downstream_port);
+ if (!connection) {
+ goto error;
+ }
+
+ /*
+ * Ownership of upstream_component/downstream_component and of
+ * the connection object is transferred to the graph.
+ */
+ g_ptr_array_add(graph->connections, connection);
+
+ if (!upstream_was_already_in_graph) {
+ g_ptr_array_add(graph->components, upstream_component);
+ bt_component_set_graph(upstream_component, graph);
+ }
+ if (!downstream_was_already_in_graph) {
+ g_ptr_array_add(graph->components, downstream_component);
+ bt_component_set_graph(downstream_component, graph);
+ if (bt_component_get_class_type(downstream_component) ==
+ BT_COMPONENT_CLASS_TYPE_SINK) {
+ g_queue_push_tail(graph->sinks_to_consume,
+ downstream_component);
+ }
+ }
+
+ /*
+ * 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.
+ */
+ 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;
+ }
+
+ /*
+ * Both components accepted the connection. Notify the graph's
+ * creator that both ports are connected.
+ */
+ bt_graph_notify_ports_connected(graph, upstream_port, downstream_port);
+
+end:
+ bt_put(upstream_graph);
+ bt_put(downstream_graph);
+ 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);
+ goto end;
+}
+
+static
+enum bt_component_status get_component_port_counts(
+ struct bt_component *component, uint64_t *input_count,
+ uint64_t *output_count)
+{
+ enum bt_component_status ret;
+
+ switch (bt_component_get_class_type(component)) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ ret = bt_component_source_get_output_port_count(component,
+ output_count);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ break;
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ ret = bt_component_filter_get_output_port_count(component,
+ output_count);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ ret = bt_component_filter_get_input_port_count(component,
+ input_count);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ break;
+ case BT_COMPONENT_CLASS_TYPE_SINK:
+ ret = bt_component_sink_get_input_port_count(component,
+ input_count);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ ret = BT_COMPONENT_STATUS_OK;
+end:
+ return ret;
+}
+
+enum bt_graph_status bt_graph_add_component_as_sibling(struct bt_graph *graph,
+ struct bt_component *origin,
+ struct bt_component *new_component)
+{
+ uint64_t origin_input_port_count = 0;
+ uint64_t origin_output_port_count = 0;
+ uint64_t new_input_port_count = 0;
+ uint64_t new_output_port_count = 0;
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+ struct bt_graph *origin_graph = NULL;
+ struct bt_graph *new_graph = NULL;
+ struct bt_port *origin_port = NULL;
+ struct bt_port *new_port = NULL;
+ struct bt_port *upstream_port = NULL;
+ struct bt_port *downstream_port = NULL;
+ struct bt_connection *origin_connection = NULL;
+ struct bt_connection *new_connection = NULL;
+ int port_index;
+
+ if (!graph || !origin || !new_component) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ if (bt_component_get_class_type(origin) !=
+ bt_component_get_class_type(new_component)) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ origin_graph = bt_component_get_graph(origin);
+ if (!origin_graph || (origin_graph != graph)) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ new_graph = bt_component_get_graph(new_component);
+ if (new_graph) {
+ status = BT_GRAPH_STATUS_ALREADY_IN_A_GRAPH;
+ goto end;
+ }
+
+ if (get_component_port_counts(origin, &origin_input_port_count,
+ &origin_output_port_count) != BT_COMPONENT_STATUS_OK) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+ if (get_component_port_counts(new_component, &new_input_port_count,
+ &new_output_port_count) != BT_COMPONENT_STATUS_OK) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ if (origin_input_port_count != new_input_port_count ||
+ origin_output_port_count != new_output_port_count) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ /* Replicate input connections. */
+ for (port_index = 0; port_index< origin_input_port_count; port_index++) {
+ origin_port = bt_component_get_input_port_at_index(origin,
+ port_index);
+ if (!origin_port) {
+ status = BT_GRAPH_STATUS_ERROR;
+ goto error_disconnect;
+ }
+
+ new_port = bt_component_get_input_port_at_index(new_component,
+ port_index);
+ if (!new_port) {
+ status = BT_GRAPH_STATUS_ERROR;
+ goto error_disconnect;
+ }
+
+ origin_connection = bt_port_get_connection(origin_port);
+ if (origin_connection) {
+ upstream_port = bt_connection_get_upstream_port(
+ origin_connection);
+ if (!upstream_port) {
+ goto error_disconnect;
+ }
+
+ new_connection = bt_graph_connect_ports(graph,
+ upstream_port, new_port);
+ if (!new_connection) {
+ goto error_disconnect;
+ }
+ }
+
+ BT_PUT(upstream_port);
+ BT_PUT(origin_connection);
+ BT_PUT(new_connection);
+ BT_PUT(origin_port);
+ BT_PUT(new_port);
+ }
+
+ /* Replicate output connections. */
+ for (port_index = 0; port_index < origin_output_port_count; port_index++) {
+ origin_port = bt_component_get_output_port_at_index(origin,
+ port_index);
+ if (!origin_port) {
+ status = BT_GRAPH_STATUS_ERROR;
+ goto error_disconnect;
+ }
+ new_port = bt_component_get_output_port_at_index(new_component,
+ port_index);
+ if (!new_port) {
+ status = BT_GRAPH_STATUS_ERROR;
+ goto error_disconnect;
+ }
+
+ origin_connection = bt_port_get_connection(origin_port);
+ if (origin_connection) {
+ downstream_port = bt_connection_get_downstream_port(
+ origin_connection);
+ if (!downstream_port) {
+ goto error_disconnect;
+ }
+
+ new_connection = bt_graph_connect_ports(graph,
+ new_port, downstream_port);
+ if (!new_connection) {
+ goto error_disconnect;
+ }
+ }
+
+ BT_PUT(downstream_port);
+ BT_PUT(origin_connection);
+ BT_PUT(new_connection);
+ BT_PUT(origin_port);
+ BT_PUT(new_port);
+ }
+end:
+ bt_put(origin_graph);
+ bt_put(new_graph);
+ bt_put(origin_port);
+ bt_put(new_port);
+ bt_put(upstream_port);
+ bt_put(downstream_port);
+ bt_put(origin_connection);
+ bt_put(new_connection);
+ return status;
+error_disconnect:
+ /* Destroy all connections of the new component. */
+ /* FIXME. */
+ goto end;
+}
+
+enum bt_graph_status bt_graph_consume(struct bt_graph *graph)
+{
+ struct bt_component *sink;
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+ enum bt_component_status comp_status;
+ GList *current_node;
+
+ if (!graph) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ if (g_queue_is_empty(graph->sinks_to_consume)) {
+ status = BT_GRAPH_STATUS_END;
+ goto end;
+ }
+
+ current_node = g_queue_pop_head_link(graph->sinks_to_consume);
+ sink = current_node->data;
+ comp_status = bt_component_sink_consume(sink);
+ switch (comp_status) {
+ case BT_COMPONENT_STATUS_OK:
+ break;
+ case BT_COMPONENT_STATUS_END:
+ status = BT_GRAPH_STATUS_END;
+ break;
+ case BT_COMPONENT_STATUS_AGAIN:
+ status = BT_GRAPH_STATUS_AGAIN;
+ break;
+ case BT_COMPONENT_STATUS_INVALID:
+ status = BT_GRAPH_STATUS_INVALID;
+ break;
+ default:
+ status = BT_GRAPH_STATUS_ERROR;
+ break;
+ }
+
+ if (status != BT_GRAPH_STATUS_END) {
+ g_queue_push_tail_link(graph->sinks_to_consume, current_node);
+ goto end;
+ }
+
+ /* End reached, the node is not added back to the queue and free'd. */
+ g_queue_delete_link(graph->sinks_to_consume, current_node);
+
+ /* Don't forward an END status if there are sinks left to consume. */
+ if (!g_queue_is_empty(graph->sinks_to_consume)) {
+ status = BT_GRAPH_STATUS_OK;
+ goto end;
+ }
+end:
+ return status;
+}
+
+enum bt_graph_status bt_graph_run(struct bt_graph *graph)
+{
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+
+ if (!graph) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto error;
+ }
+
+ do {
+ status = bt_graph_consume(graph);
+ if (status == BT_GRAPH_STATUS_AGAIN) {
+ /*
+ * If AGAIN is received and there are multiple sinks,
+ * go ahead and consume from the next sink.
+ *
+ * However, in the case where a single sink is left,
+ * the caller can decide to busy-wait and call
+ * bt_graph_run continuously until the source is ready
+ * or it can decide to sleep for an arbitrary amount of
+ * time.
+ */
+ if (graph->sinks_to_consume->length > 1) {
+ status = BT_GRAPH_STATUS_OK;
+ }
+ }
+ } while (status == BT_GRAPH_STATUS_OK);
+
+ if (g_queue_is_empty(graph->sinks_to_consume)) {
+ status = BT_GRAPH_STATUS_END;
+ }
+error:
+ return status;
+}
+
+static
+void add_listener(GArray *listeners, void *func, void *data)
+{
+ struct bt_graph_listener listener = {
+ .func = func,
+ .data = data,
+ };
+
+ g_array_append_val(listeners, listener);
+}
+
+enum bt_graph_status bt_graph_add_port_added_listener(
+ struct bt_graph *graph,
+ bt_graph_port_added_listener listener, void *data)
+{
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+
+ if (!graph || !listener) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ add_listener(graph->listeners.port_added, listener, data);
+
+end:
+ return status;
+}
+
+enum bt_graph_status bt_graph_add_port_removed_listener(
+ struct bt_graph *graph,
+ bt_graph_port_removed_listener listener, void *data)
+{
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+
+ if (!graph || !listener) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ add_listener(graph->listeners.port_removed, listener, data);
+
+end:
+ return status;
+}
+
+enum bt_graph_status bt_graph_add_ports_connected_listener(
+ struct bt_graph *graph,
+ bt_graph_ports_connected_listener listener, void *data)
+{
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+
+ if (!graph || !listener) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ add_listener(graph->listeners.ports_connected, listener, data);
+
+end:
+ return status;
+}
+
+enum bt_graph_status bt_graph_add_ports_disconnected_listener(
+ struct bt_graph *graph,
+ bt_graph_ports_disconnected_listener listener, void *data)
+{
+ enum bt_graph_status status = BT_GRAPH_STATUS_OK;
+
+ if (!graph || !listener) {
+ status = BT_GRAPH_STATUS_INVALID;
+ goto end;
+ }
+
+ add_listener(graph->listeners.ports_disconnected, listener, data);
+
+end:
+ return status;
+}
+
+BT_HIDDEN
+void bt_graph_notify_port_added(struct bt_graph *graph, struct bt_port *port)
+{
+ size_t i;
+
+ for (i = 0; i < graph->listeners.port_added->len; i++) {
+ struct bt_graph_listener listener =
+ g_array_index(graph->listeners.port_added,
+ struct bt_graph_listener, i);
+ bt_graph_port_added_listener func = listener.func;
+
+ assert(func);
+ func(port, listener.data);
+ }
+}
+
+BT_HIDDEN
+void bt_graph_notify_port_removed(struct bt_graph *graph,
+ struct bt_component *comp, struct bt_port *port)
+{
+ size_t i;
+
+ for (i = 0; i < graph->listeners.port_removed->len; i++) {
+ struct bt_graph_listener listener =
+ g_array_index(graph->listeners.port_removed,
+ struct bt_graph_listener, i);
+ bt_graph_port_removed_listener func = listener.func;
+
+ assert(func);
+ func(comp, port, listener.data);
+ }
+}
+
+BT_HIDDEN
+void bt_graph_notify_ports_connected(struct bt_graph *graph,
+ struct bt_port *upstream_port, struct bt_port *downstream_port)
+{
+ size_t i;
+
+ for (i = 0; i < graph->listeners.ports_connected->len; i++) {
+ struct bt_graph_listener listener =
+ g_array_index(graph->listeners.ports_connected,
+ struct bt_graph_listener, i);
+ bt_graph_ports_connected_listener func = listener.func;
+
+ assert(func);
+ func(upstream_port, downstream_port, listener.data);
+ }
+}
+
+BT_HIDDEN
+void bt_graph_notify_ports_disconnected(struct bt_graph *graph,
+ struct bt_component *upstream_comp,
+ struct bt_component *downstream_comp,
+ struct bt_port *upstream_port, struct bt_port *downstream_port)
+{
+ size_t i;
+
+ for (i = 0; i < graph->listeners.ports_disconnected->len; i++) {
+ struct bt_graph_listener listener =
+ g_array_index(graph->listeners.ports_disconnected,
+ struct bt_graph_listener, i);
+ bt_graph_ports_disconnected_listener func = listener.func;
+
+ assert(func);
+ func(upstream_comp, downstream_comp, upstream_port,
+ downstream_port, listener.data);
+ }
+}
--- /dev/null
+/*
+ * iterator.c
+ *
+ * Babeltrace Notification Iterator
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/component-source-internal.h>
+#include <babeltrace/graph/component-class-internal.h>
+#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/notification-iterator-internal.h>
+#include <babeltrace/graph/notification-internal.h>
+
+static
+void bt_notification_iterator_destroy(struct bt_object *obj)
+{
+ struct bt_notification_iterator *iterator;
+ struct bt_component_class *comp_class;
+
+ assert(obj);
+ iterator = container_of(obj, struct bt_notification_iterator,
+ base);
+ assert(iterator->component);
+ comp_class = iterator->component->class;
+
+ /* Call user-defined destroy method */
+ switch (comp_class->type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ {
+ struct bt_component_class_source *source_class;
+
+ source_class = container_of(comp_class, struct bt_component_class_source, parent);
+
+ if (source_class->methods.iterator.finalize) {
+ source_class->methods.iterator.finalize(
+ bt_private_notification_iterator_from_notification_iterator(iterator));
+ }
+ break;
+ }
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ {
+ struct bt_component_class_filter *filter_class;
+
+ filter_class = container_of(comp_class, struct bt_component_class_filter, parent);
+
+ if (filter_class->methods.iterator.finalize) {
+ filter_class->methods.iterator.finalize(
+ bt_private_notification_iterator_from_notification_iterator(iterator));
+ }
+ break;
+ }
+ default:
+ /* Unreachable */
+ assert(0);
+ }
+
+ BT_PUT(iterator->current_notification);
+ BT_PUT(iterator->component);
+ g_free(iterator);
+}
+
+BT_HIDDEN
+struct bt_notification_iterator *bt_notification_iterator_create(
+ struct bt_component *component)
+{
+ enum bt_component_class_type type;
+ struct bt_notification_iterator *iterator = NULL;
+
+ if (!component) {
+ goto end;
+ }
+
+ type = bt_component_get_class_type(component);
+ switch (type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ break;
+ default:
+ goto end;
+ }
+
+ iterator = g_new0(struct bt_notification_iterator, 1);
+ if (!iterator) {
+ goto end;
+ }
+
+ iterator->component = bt_get(component);
+ bt_object_init(iterator, bt_notification_iterator_destroy);
+end:
+ return iterator;
+}
+
+BT_HIDDEN
+enum bt_notification_iterator_status bt_notification_iterator_validate(
+ struct bt_notification_iterator *iterator)
+{
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+
+ if (!iterator) {
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+void *bt_private_notification_iterator_get_user_data(
+ struct bt_private_notification_iterator *private_iterator)
+{
+ struct bt_notification_iterator *iterator =
+ bt_notification_iterator_from_private(private_iterator);
+
+ return iterator ? iterator->user_data : NULL;
+}
+
+enum bt_notification_iterator_status
+bt_private_notification_iterator_set_user_data(
+ struct bt_private_notification_iterator *private_iterator,
+ void *data)
+{
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+ struct bt_notification_iterator *iterator =
+ bt_notification_iterator_from_private(private_iterator);
+
+ if (!iterator) {
+ ret = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
+ goto end;
+ }
+
+ iterator->user_data = data;
+end:
+ return ret;
+}
+
+struct bt_notification *bt_notification_iterator_get_notification(
+ struct bt_notification_iterator *iterator)
+{
+ struct bt_notification *notification = NULL;
+
+ if (!iterator) {
+ goto end;
+ }
+
+ notification = bt_get(iterator->current_notification);
+
+end:
+ return notification;
+}
+
+enum bt_notification_iterator_status
+bt_notification_iterator_next(struct bt_notification_iterator *iterator)
+{
+ struct bt_private_notification_iterator *priv_iterator =
+ bt_private_notification_iterator_from_notification_iterator(iterator);
+ bt_component_class_notification_iterator_next_method next_method = NULL;
+ struct bt_notification_iterator_next_return next_return;
+ enum bt_notification_iterator_status status =
+ BT_NOTIFICATION_ITERATOR_STATUS_OK;
+
+ if (!iterator) {
+ status = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
+ goto end;
+ }
+
+ assert(iterator->component);
+ assert(iterator->component->class);
+
+ switch (iterator->component->class->type) {
+ case BT_COMPONENT_CLASS_TYPE_SOURCE:
+ {
+ struct bt_component_class_source *source_class =
+ container_of(iterator->component->class,
+ struct bt_component_class_source, parent);
+
+ assert(source_class->methods.iterator.next);
+ next_method = source_class->methods.iterator.next;
+ break;
+ }
+ case BT_COMPONENT_CLASS_TYPE_FILTER:
+ {
+ struct bt_component_class_filter *filter_class =
+ container_of(iterator->component->class,
+ struct bt_component_class_filter, parent);
+
+ assert(filter_class->methods.iterator.next);
+ next_method = filter_class->methods.iterator.next;
+ break;
+ }
+ default:
+ assert(false);
+ break;
+ }
+
+ assert(next_method);
+ next_return = next_method(priv_iterator);
+ if (next_return.status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
+ if (!next_return.notification) {
+ status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
+ goto end;
+ }
+
+ BT_MOVE(iterator->current_notification,
+ next_return.notification);
+ bt_notification_freeze(iterator->current_notification);
+ }
+
+end:
+ return next_return.status;
+}
+
+struct bt_component *bt_notification_iterator_get_component(
+ struct bt_notification_iterator *iterator)
+{
+ return bt_get(iterator->component);
+}
+
+struct bt_private_component *
+bt_private_notification_iterator_get_private_component(
+ struct bt_private_notification_iterator *private_iterator)
+{
+ return bt_private_component_from_component(
+ bt_notification_iterator_get_component(
+ bt_notification_iterator_from_private(private_iterator)));
+}
+
+enum bt_notification_iterator_status bt_notification_iterator_seek_time(
+ struct bt_notification_iterator *iterator,
+ enum bt_notification_iterator_seek_origin seek_origin,
+ int64_t time)
+{
+ enum bt_notification_iterator_status ret =
+ BT_NOTIFICATION_ITERATOR_STATUS_UNSUPPORTED;
+ return ret;
+}
--- /dev/null
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
+
+noinst_LTLIBRARIES = libgraph-notification.la
+
+libgraph_notification_la_SOURCES = \
+ notification.c \
+ packet.c \
+ event.c \
+ stream.c \
+ heap.c \
+ inactivity.c
--- /dev/null
+/*
+ * Babeltrace Plug-in Event Notification
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-ir/event.h>
+#include <babeltrace/ctf-ir/event-internal.h>
+#include <babeltrace/ctf-ir/event-class.h>
+#include <babeltrace/ctf-ir/stream-class.h>
+#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include <babeltrace/graph/notification-event-internal.h>
+
+static
+void bt_notification_event_destroy(struct bt_object *obj)
+{
+ struct bt_notification_event *notification =
+ (struct bt_notification_event *) obj;
+
+ BT_PUT(notification->event);
+ BT_PUT(notification->cc_prio_map);
+ g_free(notification);
+}
+
+static
+bool validate_clock_classes(struct bt_notification_event *notif)
+{
+ /*
+ * For each clock class found in the event's trace, get the
+ * event's clock value for this clock class, and if it exists,
+ * make sure that this clock class has a priority in the
+ * notification's clock class priority map.
+ */
+ bool is_valid = true;
+ int ret;
+ int count;
+ size_t i;
+ struct bt_ctf_event_class *event_class = NULL;
+ struct bt_ctf_stream_class *stream_class = NULL;
+ struct bt_ctf_trace *trace = NULL;
+ uint64_t prio;
+
+ event_class = bt_ctf_event_get_class(notif->event);
+ assert(event_class);
+ stream_class = bt_ctf_event_class_get_stream_class(event_class);
+ assert(stream_class);
+ trace = bt_ctf_stream_class_get_trace(stream_class);
+ assert(trace);
+ count = bt_ctf_trace_get_clock_class_count(trace);
+ assert(count >= 0);
+
+ for (i = 0; i < count; i++) {
+ struct bt_ctf_clock_class *clock_class =
+ bt_ctf_trace_get_clock_class(trace, i);
+
+ assert(clock_class);
+ ret = bt_clock_class_priority_map_get_clock_class_priority(
+ notif->cc_prio_map, clock_class, &prio);
+ bt_put(clock_class);
+ if (ret) {
+ is_valid = false;
+ goto end;
+ }
+ }
+
+end:
+ bt_put(trace);
+ bt_put(stream_class);
+ bt_put(event_class);
+ return is_valid;
+}
+
+struct bt_notification *bt_notification_event_create(struct bt_ctf_event *event,
+ struct bt_clock_class_priority_map *cc_prio_map)
+{
+ struct bt_notification_event *notification = NULL;
+
+ if (!event || !cc_prio_map) {
+ goto error;
+ }
+
+ if (!bt_ctf_event_borrow_packet(event)) {
+ goto error;
+ }
+
+ notification = g_new0(struct bt_notification_event, 1);
+ if (!notification) {
+ goto error;
+ }
+ bt_notification_init(¬ification->parent,
+ BT_NOTIFICATION_TYPE_EVENT,
+ bt_notification_event_destroy);
+ notification->event = bt_get(event);
+ notification->cc_prio_map = bt_get(cc_prio_map);
+ if (!validate_clock_classes(notification)) {
+ goto error;
+ }
+
+ bt_ctf_event_freeze(notification->event);
+ return ¬ification->parent;
+error:
+ bt_put(notification);
+ return NULL;
+}
+
+struct bt_ctf_event *bt_notification_event_get_event(
+ struct bt_notification *notification)
+{
+ struct bt_ctf_event *event = NULL;
+ struct bt_notification_event *event_notification;
+
+ if (bt_notification_get_type(notification) !=
+ BT_NOTIFICATION_TYPE_EVENT) {
+ goto end;
+ }
+ event_notification = container_of(notification,
+ struct bt_notification_event, parent);
+ event = bt_get(event_notification->event);
+end:
+ return event;
+}
+
+extern struct bt_clock_class_priority_map *
+bt_notification_event_get_clock_class_priority_map(
+ struct bt_notification *notification)
+{
+ struct bt_clock_class_priority_map *cc_prio_map = NULL;
+ struct bt_notification_event *event_notification;
+
+ if (bt_notification_get_type(notification) !=
+ BT_NOTIFICATION_TYPE_EVENT) {
+ goto end;
+ }
+
+ event_notification = container_of(notification,
+ struct bt_notification_event, parent);
+ cc_prio_map = bt_get(event_notification->cc_prio_map);
+end:
+ return cc_prio_map;
+}
--- /dev/null
+/*
+ * Babeltrace - CTF notification priority heap
+ *
+ * Static-sized priority heap containing pointers. Based on CLRS,
+ * chapter 6.
+ *
+ * Copyright (c) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/graph/notification-heap-internal.h>
+
+#ifdef DEBUG_HEAP
+static
+void check_heap(struct bt_notification_heap *heap)
+{
+ size_t i;
+
+ if (!heap->count) {
+ return;
+ }
+
+ for (i = 1; i < heap->count; i++) {
+ assert(!heap->compare(g_ptr_array_index(heap->ptrs, i),
+ g_ptr_array_index(heap->ptrs, 0),
+ heap->compare_data));
+ }
+}
+#else
+void check_heap(struct bt_notification_heap *heap)
+{
+}
+#endif
+
+static
+size_t parent(size_t i)
+{
+ return (i - 1) >> 1;
+}
+
+static
+size_t left(size_t i)
+{
+ return (i << 1) + 1;
+}
+
+static
+size_t right(size_t i)
+{
+ return (i << 1) + 2;
+}
+
+/*
+ * Copy of heap->ptrs pointer is invalid after heap_grow.
+ */
+static
+int heap_grow(struct bt_notification_heap *heap, size_t new_len)
+{
+ size_t alloc_len;
+
+ if (likely(heap->ptrs->len >= new_len)) {
+ goto end;
+ }
+
+ alloc_len = max_t(size_t, new_len, heap->ptrs->len << 1);
+ g_ptr_array_set_size(heap->ptrs, alloc_len);
+end:
+ return 0;
+}
+
+static
+int heap_set_count(struct bt_notification_heap *heap, size_t new_count)
+{
+ int ret = 0;
+
+ ret = heap_grow(heap, new_count);
+ if (unlikely(ret)) {
+ goto end;
+ }
+ heap->count = new_count;
+end:
+ return ret;
+}
+
+static
+void heapify(struct bt_notification_heap *heap, size_t i)
+{
+ struct bt_notification **ptrs =
+ (struct bt_notification **) heap->ptrs->pdata;
+
+ for (;;) {
+ void *tmp;
+ size_t l, r, largest;
+
+ l = left(i);
+ r = right(i);
+ if (l < heap->count && heap->compare(ptrs[l], ptrs[i],
+ heap->compare_data)) {
+ largest = l;
+ } else {
+ largest = i;
+ }
+ if (r < heap->count && heap->compare(ptrs[r], ptrs[largest],
+ heap->compare_data)) {
+ largest = r;
+ }
+ if (unlikely(largest == i)) {
+ break;
+ }
+ tmp = ptrs[i];
+ ptrs[i] = ptrs[largest];
+ ptrs[largest] = tmp;
+ i = largest;
+ }
+ check_heap(heap);
+}
+
+static
+struct bt_notification *heap_replace_max(struct bt_notification_heap *heap,
+ struct bt_notification *notification)
+{
+ struct bt_notification *res = NULL;
+
+ if (unlikely(!heap->count)) {
+ (void) heap_set_count(heap, 1);
+ g_ptr_array_index(heap->ptrs, 0) = notification;
+ check_heap(heap);
+ goto end;
+ }
+
+ /* Replace the current max and heapify. */
+ res = g_ptr_array_index(heap->ptrs, 0);
+ g_ptr_array_index(heap->ptrs, 0) = notification;
+ heapify(heap, 0);
+end:
+ return res;
+}
+
+static
+void bt_notification_heap_destroy(struct bt_object *obj)
+{
+ struct bt_notification_heap *heap = container_of(obj,
+ struct bt_notification_heap, base);
+
+ if (heap->ptrs) {
+ size_t i;
+
+ for (i = 0; i < heap->count; i++) {
+ bt_put(g_ptr_array_index(heap->ptrs, i));
+ }
+ g_ptr_array_free(heap->ptrs, TRUE);
+ }
+ g_free(heap);
+}
+
+struct bt_notification_heap *bt_notification_heap_create(
+ bt_notification_time_compare_func comparator, void *user_data)
+{
+ struct bt_notification_heap *heap = NULL;
+
+ if (!comparator) {
+ goto end;
+ }
+
+ heap = g_new0(struct bt_notification_heap, 1);
+ if (!heap) {
+ goto end;
+ }
+
+ bt_object_init(&heap->base, bt_notification_heap_destroy);
+ heap->ptrs = g_ptr_array_new();
+ if (!heap->ptrs) {
+ BT_PUT(heap);
+ goto end;
+ }
+
+ heap->compare = comparator;
+ heap->compare_data = user_data;
+end:
+ return heap;
+}
+
+struct bt_notification *bt_notification_heap_peek(
+ struct bt_notification_heap *heap)
+{
+ check_heap(heap);
+ return bt_get(likely(heap->count) ?
+ g_ptr_array_index(heap->ptrs, 0) : NULL);
+}
+
+int bt_notification_heap_insert(struct bt_notification_heap *heap,
+ struct bt_notification *notification)
+{
+ int ret;
+ size_t pos;
+ struct bt_notification **ptrs;
+
+ ret = heap_set_count(heap, heap->count + 1);
+ if (unlikely(ret)) {
+ goto end;
+ }
+
+ ptrs = (struct bt_notification **) heap->ptrs->pdata;
+ pos = heap->count - 1;
+ while (pos > 0 && heap->compare(notification, ptrs[parent(pos)],
+ heap->compare_data)) {
+ /* Move parent down until we find the right spot. */
+ ptrs[pos] = ptrs[parent(pos)];
+ pos = parent(pos);
+ }
+ ptrs[pos] = bt_get(notification);
+ check_heap(heap);
+end:
+ return ret;
+}
+
+struct bt_notification *bt_notification_heap_pop(
+ struct bt_notification_heap *heap)
+{
+ struct bt_notification *ret = NULL;
+
+ switch (heap->count) {
+ case 0:
+ goto end;
+ case 1:
+ (void) heap_set_count(heap, 0);
+ ret = g_ptr_array_index(heap->ptrs, 0);
+ goto end;
+ }
+ /*
+ * Shrink, replace the current max by previous last entry and heapify.
+ */
+ heap_set_count(heap, heap->count - 1);
+ /* count changed. previous last entry is at heap->count. */
+ ret = heap_replace_max(heap, g_ptr_array_index(heap->ptrs,
+ heap->count));
+end:
+ /*
+ * Not taking a supplementary reference since we are relinquishing our
+ * own to the caller.
+ */
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/object-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include <babeltrace/graph/notification-internal.h>
+#include <babeltrace/graph/notification-inactivity-internal.h>
+
+static
+void bt_notification_inactivity_destroy(struct bt_object *obj)
+{
+ struct bt_notification_inactivity *notification =
+ (struct bt_notification_inactivity *) obj;
+
+ bt_put(notification->cc_prio_map);
+
+ if (notification->clock_values) {
+ g_hash_table_destroy(notification->clock_values);
+ }
+
+ g_free(notification);
+}
+
+struct bt_notification *bt_notification_inactivity_create(
+ struct bt_clock_class_priority_map *cc_prio_map)
+{
+ struct bt_notification_inactivity *notification;
+ struct bt_notification *ret_notif = NULL;
+
+ if (!cc_prio_map) {
+ goto error;
+ }
+
+ notification = g_new0(struct bt_notification_inactivity, 1);
+ if (!notification) {
+ goto error;
+ }
+ bt_notification_init(¬ification->parent,
+ BT_NOTIFICATION_TYPE_INACTIVITY,
+ bt_notification_inactivity_destroy);
+ ret_notif = ¬ification->parent;
+ notification->clock_values = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, bt_put, bt_put);
+ if (!notification->clock_values) {
+ goto error;
+ }
+
+ notification->cc_prio_map = bt_get(cc_prio_map);
+ goto end;
+
+error:
+ BT_PUT(ret_notif);
+
+end:
+ return ret_notif;
+}
+
+extern struct bt_clock_class_priority_map *
+bt_notification_inactivity_get_clock_class_priority_map(
+ struct bt_notification *notification)
+{
+ struct bt_clock_class_priority_map *cc_prio_map = NULL;
+ struct bt_notification_inactivity *inactivity_notification;
+
+ if (bt_notification_get_type(notification) !=
+ BT_NOTIFICATION_TYPE_INACTIVITY) {
+ goto end;
+ }
+
+ inactivity_notification = container_of(notification,
+ struct bt_notification_inactivity, parent);
+ cc_prio_map = bt_get(inactivity_notification->cc_prio_map);
+end:
+ return cc_prio_map;
+}
+
+struct bt_ctf_clock_value *bt_notification_inactivity_get_clock_value(
+ struct bt_notification *notification,
+ struct bt_ctf_clock_class *clock_class)
+{
+ struct bt_ctf_clock_value *clock_value = NULL;
+ struct bt_notification_inactivity *inactivity_notification;
+
+ if (!notification || !clock_class) {
+ goto end;
+ }
+
+ if (bt_notification_get_type(notification) !=
+ BT_NOTIFICATION_TYPE_INACTIVITY) {
+ goto end;
+ }
+
+ inactivity_notification = container_of(notification,
+ struct bt_notification_inactivity, parent);
+ clock_value = g_hash_table_lookup(inactivity_notification->clock_values,
+ clock_class);
+ bt_get(clock_value);
+
+end:
+ return clock_value;
+}
+
+int bt_notification_inactivity_set_clock_value(
+ struct bt_notification *notification,
+ struct bt_ctf_clock_value *clock_value)
+{
+ int ret = 0;
+ uint64_t prio;
+ struct bt_ctf_clock_class *clock_class = NULL;
+ struct bt_notification_inactivity *inactivity_notification;
+
+ if (!notification || !clock_value || notification->frozen) {
+ ret = -1;
+ goto end;
+ }
+
+ if (bt_notification_get_type(notification) !=
+ BT_NOTIFICATION_TYPE_INACTIVITY) {
+ goto end;
+ }
+
+ inactivity_notification = container_of(notification,
+ struct bt_notification_inactivity, parent);
+ clock_class = bt_ctf_clock_value_get_class(clock_value);
+ ret = bt_clock_class_priority_map_get_clock_class_priority(
+ inactivity_notification->cc_prio_map, clock_class, &prio);
+ if (ret) {
+ /*
+ * Clock value's class is not mapped to a priority
+ * within the scope of this notification.
+ */
+ goto end;
+ }
+
+ g_hash_table_insert(inactivity_notification->clock_values,
+ clock_class, bt_get(clock_value));
+ clock_class = NULL;
+
+end:
+ bt_put(clock_class);
+ return ret;
+}
--- /dev/null
+/*
+ * Babeltrace Plug-in Notification
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/notification-internal.h>
+
+BT_HIDDEN
+void bt_notification_init(struct bt_notification *notification,
+ enum bt_notification_type type,
+ bt_object_release_func release)
+{
+ assert(type > BT_NOTIFICATION_TYPE_ALL &&
+ type < BT_NOTIFICATION_TYPE_NR);
+ notification->type = type;
+ bt_object_init(¬ification->base, release);
+}
+
+enum bt_notification_type bt_notification_get_type(
+ struct bt_notification *notification)
+{
+ return notification ? notification->type : BT_NOTIFICATION_TYPE_UNKNOWN;
+}
+
+struct bt_ctf_stream *bt_notification_get_stream(
+ struct bt_notification *notification)
+{
+ struct bt_ctf_stream *stream = NULL;
+
+ if (!notification || !notification->get_stream) {
+ goto end;
+ }
+
+ stream = notification->get_stream(notification);
+end:
+ return stream;
+}
--- /dev/null
+/*
+ * Babeltrace Plug-in Packet-related Notifications
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/graph/notification-packet-internal.h>
+
+static
+void bt_notification_packet_begin_destroy(struct bt_object *obj)
+{
+ struct bt_notification_packet_begin *notification =
+ (struct bt_notification_packet_begin *) obj;
+
+ BT_PUT(notification->packet);
+ g_free(notification);
+}
+
+static
+void bt_notification_packet_end_destroy(struct bt_object *obj)
+{
+ struct bt_notification_packet_end *notification =
+ (struct bt_notification_packet_end *) obj;
+
+ BT_PUT(notification->packet);
+ g_free(notification);
+}
+
+struct bt_notification *bt_notification_packet_begin_create(
+ struct bt_ctf_packet *packet)
+{
+ struct bt_notification_packet_begin *notification;
+
+ if (!packet) {
+ goto error;
+ }
+
+ notification = g_new0(struct bt_notification_packet_begin, 1);
+ bt_notification_init(¬ification->parent,
+ BT_NOTIFICATION_TYPE_PACKET_BEGIN,
+ bt_notification_packet_begin_destroy);
+ notification->packet = bt_get(packet);
+ return ¬ification->parent;
+error:
+ return NULL;
+}
+
+struct bt_ctf_packet *bt_notification_packet_begin_get_packet(
+ struct bt_notification *notification)
+{
+ struct bt_ctf_packet *ret = NULL;
+ struct bt_notification_packet_begin *packet_begin;
+
+ if (notification->type != BT_NOTIFICATION_TYPE_PACKET_BEGIN) {
+ goto end;
+ }
+
+ packet_begin = container_of(notification,
+ struct bt_notification_packet_begin, parent);
+ ret = bt_get(packet_begin->packet);
+end:
+ return ret;
+}
+
+struct bt_notification *bt_notification_packet_end_create(
+ struct bt_ctf_packet *packet)
+{
+ struct bt_notification_packet_end *notification;
+
+ if (!packet) {
+ goto error;
+ }
+
+ notification = g_new0(struct bt_notification_packet_end, 1);
+ bt_notification_init(¬ification->parent,
+ BT_NOTIFICATION_TYPE_PACKET_END,
+ bt_notification_packet_end_destroy);
+ notification->packet = bt_get(packet);
+ return ¬ification->parent;
+error:
+ return NULL;
+}
+
+struct bt_ctf_packet *bt_notification_packet_end_get_packet(
+ struct bt_notification *notification)
+{
+ struct bt_ctf_packet *ret = NULL;
+ struct bt_notification_packet_end *packet_end;
+
+ if (notification->type != BT_NOTIFICATION_TYPE_PACKET_END) {
+ goto end;
+ }
+
+ packet_end = container_of(notification,
+ struct bt_notification_packet_end, parent);
+ ret = bt_get(packet_end->packet);
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Babeltrace Plug-in Stream-related Notifications
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/graph/notification-stream-internal.h>
+
+static
+void bt_notification_stream_end_destroy(struct bt_object *obj)
+{
+ struct bt_notification_stream_end *notification =
+ (struct bt_notification_stream_end *) obj;
+
+ BT_PUT(notification->stream);
+ g_free(notification);
+}
+
+struct bt_notification *bt_notification_stream_end_create(
+ struct bt_ctf_stream *stream)
+{
+ struct bt_notification_stream_end *notification;
+
+ if (!stream) {
+ goto error;
+ }
+
+ notification = g_new0(struct bt_notification_stream_end, 1);
+ bt_notification_init(¬ification->parent,
+ BT_NOTIFICATION_TYPE_STREAM_END,
+ bt_notification_stream_end_destroy);
+ notification->stream = bt_get(stream);
+ return ¬ification->parent;
+error:
+ return NULL;
+}
+
+struct bt_ctf_packet *bt_notification_stream_end_get_stream(
+ struct bt_notification *notification)
+{
+ struct bt_notification_stream_end *stream_end;
+
+ stream_end = container_of(notification,
+ struct bt_notification_stream_end, parent);
+ return bt_get(stream_end->stream);
+}
--- /dev/null
+/*
+ * port.c
+ *
+ * Babeltrace Port
+ *
+ * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/port-internal.h>
+#include <babeltrace/graph/connection-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/compiler-internal.h>
+
+static
+void bt_port_destroy(struct bt_object *obj)
+{
+ struct bt_port *port = container_of(obj, struct bt_port, base);
+
+ if (port->name) {
+ g_string_free(port->name, TRUE);
+ }
+ g_free(port);
+}
+
+struct bt_port *bt_port_from_private_port(
+ struct bt_private_port *private_port)
+{
+ return bt_get(bt_port_from_private(private_port));
+}
+
+BT_HIDDEN
+struct bt_port *bt_port_create(struct bt_component *parent_component,
+ enum bt_port_type type, const char *name)
+{
+ struct bt_port *port = NULL;
+
+ assert(name);
+ assert(parent_component);
+ assert(type == BT_PORT_TYPE_INPUT || type == BT_PORT_TYPE_OUTPUT);
+
+ if (strlen(name) == 0) {
+ goto end;
+ }
+
+ port = g_new0(struct bt_port, 1);
+ if (!port) {
+ goto end;
+ }
+
+ bt_object_init(port, bt_port_destroy);
+ port->name = g_string_new(name);
+ if (!port->name) {
+ BT_PUT(port);
+ goto end;
+ }
+
+ port->type = type;
+
+ bt_object_set_parent(port, &parent_component->base);
+end:
+ return port;
+}
+
+const char *bt_port_get_name(struct bt_port *port)
+{
+ return port ? port->name->str : NULL;
+}
+
+enum bt_port_type bt_port_get_type(struct bt_port *port)
+{
+ return port ? port->type : BT_PORT_TYPE_UNKOWN;
+}
+
+struct bt_connection *bt_port_get_connection(struct bt_port *port)
+{
+ struct bt_connection *connection = NULL;
+
+ if (!port || !port->connection) {
+ goto end;
+ }
+
+ connection = bt_get(port->connection);
+end:
+ return connection;
+}
+
+struct bt_component *bt_port_get_component(struct bt_port *port)
+{
+ return (struct bt_component *) bt_object_get_parent(port);
+}
+
+struct bt_private_connection *bt_private_port_get_private_connection(
+ struct bt_private_port *private_port)
+{
+ return bt_private_connection_from_connection(bt_port_get_connection(
+ bt_port_from_private(private_port)));
+}
+
+struct bt_private_component *bt_private_port_get_private_component(
+ struct bt_private_port *private_port)
+{
+ return bt_private_component_from_component(bt_port_get_component(
+ bt_port_from_private(private_port)));
+}
+
+BT_HIDDEN
+void bt_port_set_connection(struct bt_port *port,
+ struct bt_connection *connection)
+{
+ /*
+ * Don't take a reference on connection as its existence is
+ * guaranteed by the existence of the graph in which the
+ * connection exists.
+ */
+ port->connection = connection;
+}
+
+int bt_private_port_remove_from_component(
+ struct bt_private_port *private_port)
+{
+ int ret = 0;
+ struct bt_port *port = bt_port_from_private(private_port);
+ struct bt_component *comp = NULL;
+
+ if (!port) {
+ ret = -1;
+ goto end;
+ }
+
+ comp = (void *) bt_object_get_parent(port);
+ ret = bt_component_remove_port(comp, port);
+
+end:
+ bt_put(comp);
+ return ret;
+}
+
+int bt_port_disconnect(struct bt_port *port)
+{
+ int ret = 0;
+
+ if (!port) {
+ ret = -1;
+ goto end;
+ }
+
+ if (port->connection) {
+ bt_connection_disconnect_ports(port->connection);
+ }
+
+end:
+ return ret;
+}
+
+int bt_port_is_connected(struct bt_port *port)
+{
+ int ret;
+
+ if (!port) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = port->connection ? 1 : 0;
+
+end:
+ return ret;
+}
+
+int bt_private_port_set_user_data(
+ struct bt_private_port *private_port, void *user_data)
+{
+ int ret = 0;
+
+ if (!private_port) {
+ ret = -1;
+ goto end;
+ }
+
+ bt_port_from_private(private_port)->user_data = user_data;
+
+end:
+ return ret;
+}
+
+void *bt_private_port_get_user_data(
+ struct bt_private_port *private_port)
+{
+ return private_port ?
+ bt_port_from_private(private_port)->user_data : NULL;
+}
--- /dev/null
+/*
+ * sink.c
+ *
+ * Babeltrace Sink Component
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/values.h>
+#include <babeltrace/graph/component-sink-internal.h>
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/notification.h>
+
+BT_HIDDEN
+enum bt_component_status bt_component_sink_validate(
+ struct bt_component *component)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+ if (!component) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!component->class) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+BT_HIDDEN
+void bt_component_sink_destroy(struct bt_component *component)
+{
+}
+
+BT_HIDDEN
+struct bt_component *bt_component_sink_create(
+ struct bt_component_class *class, struct bt_value *params)
+{
+ struct bt_component_sink *sink = NULL;
+
+ sink = g_new0(struct bt_component_sink, 1);
+ if (!sink) {
+ goto end;
+ }
+
+end:
+ return sink ? &sink->parent : NULL;
+}
+
+BT_HIDDEN
+enum bt_component_status bt_component_sink_consume(
+ struct bt_component *component)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_component_class_sink *sink_class = NULL;
+
+ if (!component) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (bt_component_get_class_type(component) != BT_COMPONENT_CLASS_TYPE_SINK) {
+ ret = BT_COMPONENT_STATUS_UNSUPPORTED;
+ goto end;
+ }
+
+ sink_class = container_of(component->class, struct bt_component_class_sink, parent);
+ assert(sink_class->methods.consume);
+ ret = sink_class->methods.consume(bt_private_component_from_component(component));
+end:
+ return ret;
+}
+
+enum bt_component_status bt_component_sink_get_input_port_count(
+ struct bt_component *component, uint64_t *count)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ if (!component || !count ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
+ status = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = bt_component_get_input_port_count(component);
+end:
+ return status;
+}
+
+struct bt_port *bt_component_sink_get_input_port(
+ struct bt_component *component, const char *name)
+{
+ struct bt_port *port = NULL;
+
+ if (!component || !name ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
+ goto end;
+ }
+
+ port = bt_component_get_input_port(component, name);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_sink_get_input_port_at_index(
+ struct bt_component *component, int index)
+{
+ struct bt_port *port = NULL;
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
+ goto end;
+ }
+
+ port = bt_component_get_input_port_at_index(component, index);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_sink_get_default_input_port(
+ struct bt_component *component)
+{
+ return bt_component_sink_get_input_port(component,
+ DEFAULT_INPUT_PORT_NAME);
+}
+
+struct bt_private_port *
+bt_private_component_sink_get_input_private_port_at_index(
+ struct bt_private_component *private_component, int index)
+{
+ return bt_private_port_from_port(
+ bt_component_sink_get_input_port_at_index(
+ bt_component_from_private(private_component), index));
+}
+
+struct bt_private_port *bt_private_component_sink_get_default_input_private_port(
+ struct bt_private_component *private_component)
+{
+ return bt_private_port_from_port(
+ bt_component_sink_get_default_input_port(
+ bt_component_from_private(private_component)));
+}
+
+struct bt_private_port *bt_private_component_sink_add_input_private_port(
+ struct bt_private_component *private_component,
+ const char *name)
+{
+ struct bt_port *port = NULL;
+ struct bt_component *component =
+ bt_component_from_private(private_component);
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
+ goto end;
+ }
+
+ port = bt_component_add_input_port(component, name);
+end:
+ return bt_private_port_from_port(port);
+}
--- /dev/null
+/*
+ * source.c
+ *
+ * Babeltrace Source Component
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/graph/component-source-internal.h>
+#include <babeltrace/graph/component-internal.h>
+#include <babeltrace/graph/port-internal.h>
+#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/notification-iterator-internal.h>
+
+BT_HIDDEN
+enum bt_component_status bt_component_source_validate(
+ struct bt_component *component)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+
+ if (!component) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!component->class) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ if (component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+void bt_component_source_destroy(struct bt_component *component)
+{
+}
+
+BT_HIDDEN
+struct bt_component *bt_component_source_create(
+ struct bt_component_class *class, struct bt_value *params)
+{
+ struct bt_component_source *source = NULL;
+
+ source = g_new0(struct bt_component_source, 1);
+ if (!source) {
+ goto end;
+ }
+
+end:
+ return source ? &source->parent : NULL;
+}
+
+enum bt_component_status bt_component_source_get_output_port_count(
+ struct bt_component *component, uint64_t *count)
+{
+ enum bt_component_status status = BT_COMPONENT_STATUS_OK;
+
+ if (!component || !count ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ status = BT_COMPONENT_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = bt_component_get_output_port_count(component);
+end:
+ return status;
+}
+
+struct bt_port *bt_component_source_get_output_port(
+ struct bt_component *component, const char *name)
+{
+ struct bt_port *port = NULL;
+
+ if (!component || !name ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ goto end;
+ }
+
+ port = bt_component_get_output_port(component, name);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_source_get_output_port_at_index(
+ struct bt_component *component, int index)
+{
+ struct bt_port *port = NULL;
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ goto end;
+ }
+
+ port = bt_component_get_output_port_at_index(component, index);
+end:
+ return port;
+}
+
+struct bt_port *bt_component_source_get_default_output_port(
+ struct bt_component *component)
+{
+ return bt_component_source_get_output_port(component,
+ DEFAULT_OUTPUT_PORT_NAME);
+}
+
+struct bt_private_port *bt_private_component_source_get_output_private_port(
+ struct bt_private_component *private_component,
+ const char *name)
+{
+ return bt_private_port_from_port(bt_component_source_get_output_port(
+ bt_component_from_private(private_component), name));
+}
+
+struct bt_private_port *
+bt_private_component_source_get_output_private_port_at_index(
+ struct bt_private_component *private_component, int index)
+{
+ return bt_private_port_from_port(
+ bt_component_source_get_output_port_at_index(
+ bt_component_from_private(private_component), index));
+}
+
+struct bt_private_port *bt_private_component_source_get_default_output_private_port(
+ struct bt_private_component *private_component)
+{
+ return bt_private_port_from_port(
+ bt_component_source_get_default_output_port(
+ bt_component_from_private(private_component)));
+}
+
+struct bt_private_port *bt_private_component_source_add_output_private_port(
+ struct bt_private_component *private_component,
+ const char *name)
+{
+ struct bt_port *port = NULL;
+ struct bt_component *component =
+ bt_component_from_private(private_component);
+
+ if (!component ||
+ component->class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
+ goto end;
+ }
+
+ port = bt_component_add_output_port(component, name);
+end:
+ return bt_private_port_from_port(port);
+}