From: Philippe Proulx Date: Tue, 4 Apr 2017 18:54:09 +0000 (-0400) Subject: Rename lib/component/ -> lib/graph/ to match include/babeltrace/graph/ X-Git-Tag: v2.0.0-pre1~381 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=c5504f7322f93b32b4bcc65a950ed61efadd694a Rename lib/component/ -> lib/graph/ to match include/babeltrace/graph/ Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- diff --git a/configure.ac b/configure.ac index c3714659..18335bd5 100644 --- a/configure.ac +++ b/configure.ac @@ -466,8 +466,8 @@ AC_CONFIG_FILES([ 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 diff --git a/lib/Makefile.am b/lib/Makefile.am index 49fff815..068d858e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -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 @@ -10,7 +10,7 @@ libbabeltrace_la_LDFLAGS = -version-info $(BABELTRACE_LIBRARY_VERSION) 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 \ diff --git a/lib/component/Makefile.am b/lib/component/Makefile.am deleted file mode 100644 index a72766e0..00000000 --- a/lib/component/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -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 diff --git a/lib/component/clock-class-priority-map.c b/lib/component/clock-class-priority-map.c deleted file mode 100644 index f9055198..00000000 --- a/lib/component/clock-class-priority-map.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * clock-class-priority-map.c - * - * Copyright 2017 Philippe Proulx - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/lib/component/component-class.c b/lib/component/component-class.c deleted file mode 100644 index 4585b1f3..00000000 --- a/lib/component/component-class.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * component-class.c - * - * Babeltrace Plugin Component Class - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include - -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; -} diff --git a/lib/component/component.c b/lib/component/component.c deleted file mode 100644 index 9b996f62..00000000 --- a/lib/component/component.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * component.c - * - * Babeltrace Plugin Component - * - * Copyright 2015 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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)); - } -} diff --git a/lib/component/connection.c b/lib/component/connection.c deleted file mode 100644 index 986303ed..00000000 --- a/lib/component/connection.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * connection.c - * - * Babeltrace Connection - * - * Copyright 2017 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/lib/component/filter.c b/lib/component/filter.c deleted file mode 100644 index 5931b3b3..00000000 --- a/lib/component/filter.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * filter.c - * - * Babeltrace Filter Component - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include - -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); -} diff --git a/lib/component/graph.c b/lib/component/graph.c deleted file mode 100644 index c861fa3c..00000000 --- a/lib/component/graph.c +++ /dev/null @@ -1,777 +0,0 @@ -/* - * graph.c - * - * Babeltrace Plugin Component Graph - * - * Copyright 2017 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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); - } -} diff --git a/lib/component/iterator.c b/lib/component/iterator.c deleted file mode 100644 index 29562955..00000000 --- a/lib/component/iterator.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * iterator.c - * - * Babeltrace Notification Iterator - * - * Copyright 2015 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/lib/component/notification/Makefile.am b/lib/component/notification/Makefile.am deleted file mode 100644 index 1b08e684..00000000 --- a/lib/component/notification/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -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 diff --git a/lib/component/notification/event.c b/lib/component/notification/event.c deleted file mode 100644 index a9fbf48b..00000000 --- a/lib/component/notification/event.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Babeltrace Plug-in Event Notification - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/lib/component/notification/heap.c b/lib/component/notification/heap.c deleted file mode 100644 index fc0bce81..00000000 --- a/lib/component/notification/heap.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Babeltrace - CTF notification priority heap - * - * Static-sized priority heap containing pointers. Based on CLRS, - * chapter 6. - * - * Copyright (c) 2011 Mathieu Desnoyers - * Copyright (c) 2016 Jérémie Galarneau - * - * 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 -#include -#include -#include - -#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; -} diff --git a/lib/component/notification/inactivity.c b/lib/component/notification/inactivity.c deleted file mode 100644 index 48073955..00000000 --- a/lib/component/notification/inactivity.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2017 Philippe Proulx - * - * 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 -#include -#include -#include -#include -#include - -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; -} diff --git a/lib/component/notification/notification.c b/lib/component/notification/notification.c deleted file mode 100644 index 9dc64d79..00000000 --- a/lib/component/notification/notification.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Babeltrace Plug-in Notification - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 - -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; -} diff --git a/lib/component/notification/packet.c b/lib/component/notification/packet.c deleted file mode 100644 index fa6a0ee3..00000000 --- a/lib/component/notification/packet.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Babeltrace Plug-in Packet-related Notifications - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include - -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; -} diff --git a/lib/component/notification/stream.c b/lib/component/notification/stream.c deleted file mode 100644 index 68b9bcdb..00000000 --- a/lib/component/notification/stream.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Babeltrace Plug-in Stream-related Notifications - * - * Copyright 2016 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include - -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); -} diff --git a/lib/component/port.c b/lib/component/port.c deleted file mode 100644 index c0d5e061..00000000 --- a/lib/component/port.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * port.c - * - * Babeltrace Port - * - * Copyright 2017 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include - -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; -} diff --git a/lib/component/sink.c b/lib/component/sink.c deleted file mode 100644 index 49bd8402..00000000 --- a/lib/component/sink.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * sink.c - * - * Babeltrace Sink Component - * - * Copyright 2015 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include - -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); -} diff --git a/lib/component/source.c b/lib/component/source.c deleted file mode 100644 index 0c4f1817..00000000 --- a/lib/component/source.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * source.c - * - * Babeltrace Source Component - * - * Copyright 2015 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * 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 -#include -#include -#include -#include -#include -#include - -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); -} diff --git a/lib/graph/Makefile.am b/lib/graph/Makefile.am new file mode 100644 index 00000000..09bb1792 --- /dev/null +++ b/lib/graph/Makefile.am @@ -0,0 +1,21 @@ +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 diff --git a/lib/graph/clock-class-priority-map.c b/lib/graph/clock-class-priority-map.c new file mode 100644 index 00000000..f9055198 --- /dev/null +++ b/lib/graph/clock-class-priority-map.c @@ -0,0 +1,267 @@ +/* + * clock-class-priority-map.c + * + * Copyright 2017 Philippe Proulx + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/component-class.c b/lib/graph/component-class.c new file mode 100644 index 00000000..4585b1f3 --- /dev/null +++ b/lib/graph/component-class.c @@ -0,0 +1,544 @@ +/* + * component-class.c + * + * Babeltrace Plugin Component Class + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/component.c b/lib/graph/component.c new file mode 100644 index 00000000..9b996f62 --- /dev/null +++ b/lib/graph/component.c @@ -0,0 +1,568 @@ +/* + * component.c + * + * Babeltrace Plugin Component + * + * Copyright 2015 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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)); + } +} diff --git a/lib/graph/connection.c b/lib/graph/connection.c new file mode 100644 index 00000000..986303ed --- /dev/null +++ b/lib/graph/connection.c @@ -0,0 +1,231 @@ +/* + * connection.c + * + * Babeltrace Connection + * + * Copyright 2017 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/filter.c b/lib/graph/filter.c new file mode 100644 index 00000000..5931b3b3 --- /dev/null +++ b/lib/graph/filter.c @@ -0,0 +1,259 @@ +/* + * filter.c + * + * Babeltrace Filter Component + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/lib/graph/graph.c b/lib/graph/graph.c new file mode 100644 index 00000000..c861fa3c --- /dev/null +++ b/lib/graph/graph.c @@ -0,0 +1,777 @@ +/* + * graph.c + * + * Babeltrace Plugin Component Graph + * + * Copyright 2017 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); + } +} diff --git a/lib/graph/iterator.c b/lib/graph/iterator.c new file mode 100644 index 00000000..29562955 --- /dev/null +++ b/lib/graph/iterator.c @@ -0,0 +1,260 @@ +/* + * iterator.c + * + * Babeltrace Notification Iterator + * + * Copyright 2015 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/notification/Makefile.am b/lib/graph/notification/Makefile.am new file mode 100644 index 00000000..db32a43c --- /dev/null +++ b/lib/graph/notification/Makefile.am @@ -0,0 +1,11 @@ +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 diff --git a/lib/graph/notification/event.c b/lib/graph/notification/event.c new file mode 100644 index 00000000..a9fbf48b --- /dev/null +++ b/lib/graph/notification/event.c @@ -0,0 +1,162 @@ +/* + * Babeltrace Plug-in Event Notification + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/notification/heap.c b/lib/graph/notification/heap.c new file mode 100644 index 00000000..fc0bce81 --- /dev/null +++ b/lib/graph/notification/heap.c @@ -0,0 +1,264 @@ +/* + * Babeltrace - CTF notification priority heap + * + * Static-sized priority heap containing pointers. Based on CLRS, + * chapter 6. + * + * Copyright (c) 2011 Mathieu Desnoyers + * Copyright (c) 2016 Jérémie Galarneau + * + * 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 +#include +#include +#include + +#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; +} diff --git a/lib/graph/notification/inactivity.c b/lib/graph/notification/inactivity.c new file mode 100644 index 00000000..48073955 --- /dev/null +++ b/lib/graph/notification/inactivity.c @@ -0,0 +1,163 @@ +/* + * Copyright 2017 Philippe Proulx + * + * 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 +#include +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/notification/notification.c b/lib/graph/notification/notification.c new file mode 100644 index 00000000..9dc64d79 --- /dev/null +++ b/lib/graph/notification/notification.c @@ -0,0 +1,58 @@ +/* + * Babeltrace Plug-in Notification + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 + +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; +} diff --git a/lib/graph/notification/packet.c b/lib/graph/notification/packet.c new file mode 100644 index 00000000..fa6a0ee3 --- /dev/null +++ b/lib/graph/notification/packet.c @@ -0,0 +1,120 @@ +/* + * Babeltrace Plug-in Packet-related Notifications + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include + +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; +} diff --git a/lib/graph/notification/stream.c b/lib/graph/notification/stream.c new file mode 100644 index 00000000..68b9bcdb --- /dev/null +++ b/lib/graph/notification/stream.c @@ -0,0 +1,67 @@ +/* + * Babeltrace Plug-in Stream-related Notifications + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include + +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); +} diff --git a/lib/graph/port.c b/lib/graph/port.c new file mode 100644 index 00000000..c0d5e061 --- /dev/null +++ b/lib/graph/port.c @@ -0,0 +1,212 @@ +/* + * port.c + * + * Babeltrace Port + * + * Copyright 2017 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include + +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; +} diff --git a/lib/graph/sink.c b/lib/graph/sink.c new file mode 100644 index 00000000..49bd8402 --- /dev/null +++ b/lib/graph/sink.c @@ -0,0 +1,189 @@ +/* + * sink.c + * + * Babeltrace Sink Component + * + * Copyright 2015 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include + +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); +} diff --git a/lib/graph/source.c b/lib/graph/source.c new file mode 100644 index 00000000..0c4f1817 --- /dev/null +++ b/lib/graph/source.c @@ -0,0 +1,176 @@ +/* + * source.c + * + * Babeltrace Source Component + * + * Copyright 2015 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * 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 +#include +#include +#include +#include +#include +#include + +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); +}