From 33b34c437c354e1c065e33151135bc2e57e2e29c Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 18 Jan 2017 13:30:07 -0500 Subject: [PATCH] Decouple component class from plugin subsystem, remove component factory MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is a refactoring of the component class and plugin subsystems of Babeltrace 2. There's not much new code, it's mostly moved from one file to another and some functions are renamed. The goal of this patch is to decouple the component class objects from plugin objects, that is, remove the dependency from the component class to the plugin. This reference is not necessary, as component classes can be provided by many sources, a plugin being one of them. A similar plugin subsystem could be implemented outside of the Babeltrace library with plugin-agnostic component class objects. Also the component factory concept is completely removed. At the end of this refactoring, it's nothing more than a hash table, so the name is bad, and the object itself is just a very basic util. Summary of changes: * You can create a bt_component_class object manually with bt_component_class_create(). The function accepts the same parameters as before, except for a plugin reference. * Internal code can use bt_component_class_add_destroy_listener() to add a custom destroy listener to a component class. Destroy listeners are called in reverse order just before the component class is destroyed when its last reference is dropped. This is needed to implement the plugin subsystem. It could be made public eventually to allow a custom component class provider system similar to the Babeltrace plugin subsystem. It could be generalized to bt_object_add_destroy_listener() or bt_add_destroy_listener(). * bt_component_class_get_plugin() is removed. * There are three functions to create a bt_plugin object (in `babeltrace/plugin/plugin.h`): * bt_plugin_create_from_file(): Accepts a path and creates a plugin object from this single file. This must be a `.so` or `.la` file for the moment, but eventually we can support other plugins like Python plugins `.py`, Windows DLLs `.dll`, etc. * bt_plugin_create_all_from_dir(): Traverses a directory, optionally recursively, and creates one plugin object for each shared library found. Errors are ignored in this function because it's possible that a shared library in this directoy is not a Babeltrace plugin and we still want to continue the search. The return value is a NULL-terminated array of bt_plugin objects which the caller must free. Each plugin object in this array has its reference count set to 1. * bt_plugin_create_all_from_static(): Loads all the plugins found in the static sections of the Babeltrace binary. The return value has the same format as with bt_plugin_create_all_from_dir(). There is no way to create an "empty", fresh bt_plugin object. It's always created from an existing file in the end. * A bt_plugin object is a simple provider of component classes. Once it's created with one of the three functions above, you can access its global properties (name, license, description, etc.), as well as its component classes with bt_plugin_get_component_class_count(), bt_plugin_get_component_class(), and bt_plugin_get_component_class_by_name_and_type(). The initialization function of a plugin can add new component classes to a bt_plugin object (passed as a parameter) thanks to the new bt_plugin_add_component_class() function. This function is exclusive to a plugin's initialization stage: once the initialization is done, the plugin is marked as frozen, and you cannot call bt_plugin_add_component_class() again on this plugin. This ensures that all the contained component classes were created by the plugin's code itself. There's a mechanism which involves a global hash table of component class adresses to shared library handles and a custom component class destroy listener to ensure that, even if a bt_plugin object is destroyed (reference count falls to zero), its associated shared library is not closed until all its component classes are also destroyed. See plugin.c:89 for more details. * All the headers related to components, component classes, and notifications are moved to `babeltrace/component`. Plugin-specific headers are in `babeltrace/plugin`. * Plugin development macros are in `babeltrace/plugin/plugin-dev.h` (instead of `plugin-macros.h`). This is the header that any plugin's main source file must include. * Two new function typedefs in `plugin-dev.h`: * bt_plugin_init_func: plugin's initialization function which accepts a plugin object to which to add component classes. You can set such a function with BT_PLUGIN_INIT(). * bt_plugin_exit_func: plugin's exit function, if anything global to the plugin must be freed/released. This is not called when the bt_plugin object is destroyed: because component classes could still be alive when this happens, it's called just before the shared library is closed (when it is guaranteed that no user code found in this plugin will be called in the future of this process). You can set such a function with BT_PLUGIN_EXIT(). * The BT_PLUGIN_COMPONENT_CLASS_*_ENTRY() macros create a component class of the associated type with bt_component_class_create(), and add it to the plugin object with bt_plugin_add_component_class(). You can also do this manually in a custom initialization function. When you use BT_PLUGIN_COMPONENT_CLASSES_BEGIN and BT_PLUGIN_COMPONENT_CLASSES_END, BT_PLUGIN_INIT() and BT_PLUGIN_EXIT() (no-op exit function) are automatically used. * Everything found in `babeltrace/plugin/plugin-system.h` is moved to the appropriate headers, depending on the types of the objects. * Plugins, tests, and internal code are updated to use the new macros and header files. * The converter is updated to use the updated subsystems instead of relying on a component factory. A global GLib pointer array is used to keep the currently loaded plugins. This is used instead of the component factory. When a new plugin is found, we check in this array if it was already added (same name) from another file or statically before adding it. The static find_plugin() and find_component_class() are the equivalent of the component factory interface. print_component_classes_found() also prints the number of loaded plugins. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- configure.ac | 10 +- converter/babeltrace.c | 255 ++++-- formats/ctf/ir/trace.c | 2 +- include/Makefile.am | 66 +- .../component-class-internal.h | 36 +- .../{plugin => component}/component-class.h | 20 +- .../component-connection-internal.h | 0 .../component-connection.h | 0 .../component-graph-internal.h | 8 +- .../{plugin => component}/component-graph.h | 10 +- .../component-internal.h | 11 +- .../plugin-system.h => component/component.h} | 158 ++-- .../{plugin => component}/filter-internal.h | 13 +- .../babeltrace/{plugin => component}/filter.h | 8 +- .../babeltrace/{plugin => component}/input.h | 6 +- .../notification/eot-internal.h | 0 .../{plugin => component}/notification/eot.h | 6 +- .../notification/event-internal.h | 8 +- .../notification/event.h | 6 +- .../notification/heap-internal.h | 10 +- .../{plugin => component}/notification/heap.h | 8 +- .../notification/iterator-internal.h | 9 +- .../notification/iterator.h | 111 ++- .../notification/notification-internal.h | 8 +- .../notification/notification.h | 6 +- .../notification/packet-internal.h | 8 +- .../notification/packet.h | 8 +- .../notification/schema.h | 6 +- .../notification/stream-internal.h | 8 +- .../notification/stream.h | 8 +- .../{plugin => component}/sink-internal.h | 13 +- .../babeltrace/{plugin => component}/sink.h | 8 +- .../{plugin => component}/source-internal.h | 11 +- .../babeltrace/{plugin => component}/source.h | 8 +- include/babeltrace/ctf-ir/trace.h | 2 +- .../plugin/component-factory-internal.h | 74 -- include/babeltrace/plugin/component-factory.h | 169 ---- include/babeltrace/plugin/component.h | 107 --- include/babeltrace/plugin/plugin-dev.h | 123 +++ include/babeltrace/plugin/plugin-internal.h | 48 +- include/babeltrace/plugin/plugin-macros.h | 80 -- include/babeltrace/plugin/plugin.h | 41 +- lib/Makefile.am | 5 +- lib/{plugin-system => component}/Makefile.am | 10 +- .../component-class.c | 57 +- .../component-graph.c | 2 +- lib/{plugin-system => component}/component.c | 12 +- lib/{plugin-system => component}/filter.c | 10 +- lib/{plugin-system => component}/input.c | 2 +- lib/{plugin-system => component}/iterator.c | 8 +- .../notification/Makefile.am | 4 +- .../notification/event.c | 2 +- .../notification/heap.c | 2 +- .../notification/notification.c | 2 +- .../notification/packet.c | 2 +- .../notification/stream.c | 2 +- lib/{plugin-system => component}/sink.c | 6 +- lib/{plugin-system => component}/source.c | 8 +- lib/plugin-system/component-factory.c | 511 ----------- lib/plugin-system/plugin.c | 187 ---- lib/plugin/Makefile.am | 7 + lib/plugin/plugin.c | 807 ++++++++++++++++++ plugins/ctf/common/notif-iter/notif-iter.c | 6 +- plugins/ctf/fs/data-stream.c | 2 +- plugins/ctf/fs/fs.c | 11 +- plugins/ctf/fs/fs.h | 2 +- plugins/ctf/lttng-live/lttng-live-internal.h | 2 +- plugins/ctf/lttng-live/lttng-live.c | 2 +- plugins/ctf/plugin.c | 6 +- plugins/muxer/muxer.c | 14 +- plugins/muxer/muxer.h | 1 - plugins/text/text.c | 14 +- plugins/text/text.h | 2 +- plugins/trimmer/iterator.c | 12 +- plugins/trimmer/iterator.h | 3 +- plugins/trimmer/trimmer.c | 14 +- plugins/trimmer/trimmer.h | 2 - plugins/writer/writer.c | 17 +- plugins/writer/writer.h | 2 +- tests/lib/test_bt_notification_heap.c | 6 +- 80 files changed, 1647 insertions(+), 1614 deletions(-) rename include/babeltrace/{plugin => component}/component-class-internal.h (64%) rename include/babeltrace/{plugin => component}/component-class.h (85%) rename include/babeltrace/{plugin => component}/component-connection-internal.h (100%) rename include/babeltrace/{plugin => component}/component-connection.h (100%) rename include/babeltrace/{plugin => component}/component-graph-internal.h (89%) rename include/babeltrace/{plugin => component}/component-graph.h (92%) rename include/babeltrace/{plugin => component}/component-internal.h (88%) rename include/babeltrace/{plugin/plugin-system.h => component/component.h} (66%) rename include/babeltrace/{plugin => component}/filter-internal.h (86%) rename include/babeltrace/{plugin => component}/filter.h (92%) rename include/babeltrace/{plugin => component}/input.h (92%) rename include/babeltrace/{plugin => component}/notification/eot-internal.h (100%) rename include/babeltrace/{plugin => component}/notification/eot.h (90%) rename include/babeltrace/{plugin => component}/notification/event-internal.h (85%) rename include/babeltrace/{plugin => component}/notification/event.h (92%) rename include/babeltrace/{plugin => component}/notification/heap-internal.h (83%) rename include/babeltrace/{plugin => component}/notification/heap.h (94%) rename include/babeltrace/{plugin => component}/notification/iterator-internal.h (89%) rename include/babeltrace/{plugin => component}/notification/iterator.h (53%) rename include/babeltrace/{plugin => component}/notification/notification-internal.h (87%) rename include/babeltrace/{plugin => component}/notification/notification.h (93%) rename include/babeltrace/{plugin => component}/notification/packet-internal.h (85%) rename include/babeltrace/{plugin => component}/notification/packet.h (89%) rename include/babeltrace/{plugin => component}/notification/schema.h (95%) rename include/babeltrace/{plugin => component}/notification/stream-internal.h (84%) rename include/babeltrace/{plugin => component}/notification/stream.h (88%) rename include/babeltrace/{plugin => component}/sink-internal.h (87%) rename include/babeltrace/{plugin => component}/sink.h (91%) rename include/babeltrace/{plugin => component}/source-internal.h (87%) rename include/babeltrace/{plugin => component}/source.h (91%) delete mode 100644 include/babeltrace/plugin/component-factory-internal.h delete mode 100644 include/babeltrace/plugin/component-factory.h delete mode 100644 include/babeltrace/plugin/component.h create mode 100644 include/babeltrace/plugin/plugin-dev.h delete mode 100644 include/babeltrace/plugin/plugin-macros.h rename lib/{plugin-system => component}/Makefile.am (54%) rename lib/{plugin-system => component}/component-class.c (71%) rename lib/{plugin-system => component}/component-graph.c (97%) rename lib/{plugin-system => component}/component.c (95%) rename lib/{plugin-system => component}/filter.c (96%) rename lib/{plugin-system => component}/input.c (97%) rename lib/{plugin-system => component}/iterator.c (96%) rename lib/{plugin-system => component}/notification/Makefile.am (58%) rename lib/{plugin-system => component}/notification/event.c (97%) rename lib/{plugin-system => component}/notification/heap.c (98%) rename lib/{plugin-system => component}/notification/notification.c (96%) rename lib/{plugin-system => component}/notification/packet.c (98%) rename lib/{plugin-system => component}/notification/stream.c (97%) rename lib/{plugin-system => component}/sink.c (98%) rename lib/{plugin-system => component}/source.c (93%) delete mode 100644 lib/plugin-system/component-factory.c delete mode 100644 lib/plugin-system/plugin.c create mode 100644 lib/plugin/Makefile.am create mode 100644 lib/plugin/plugin.c diff --git a/configure.ac b/configure.ac index bc04b288..25ad0ac5 100644 --- a/configure.ac +++ b/configure.ac @@ -349,8 +349,11 @@ AC_SUBST(babeltracectfirincludedir) babeltracepluginincludedir="${includedir}/babeltrace/plugin" AC_SUBST(babeltracepluginincludedir) -# Add a rule to $program_transform_name to rename babeltrace.bin to babeltrace on installation +babeltracecomponentincludedir="${includedir}/babeltrace/component" +AC_SUBST(babeltracecomponentincludedir) + program_transform_name="s&babeltrace\.bin&babeltrace&;$program_transform_name" +AC_SUBST(program_transform_name) # check for Doxygen AC_ARG_ENABLE( @@ -402,8 +405,9 @@ AC_CONFIG_FILES([ doc/images/Makefile lib/Makefile lib/prio_heap/Makefile - lib/plugin-system/Makefile - lib/plugin-system/notification/Makefile + lib/plugin/Makefile + lib/component/Makefile + lib/component/notification/Makefile include/Makefile bindings/Makefile bindings/python/Makefile diff --git a/converter/babeltrace.c b/converter/babeltrace.c index af789b18..f884467e 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -27,10 +27,13 @@ */ #include -#include #include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -38,10 +41,61 @@ #include #include #include +#include #include "babeltrace-cfg.h" #include "default-cfg.h" -static struct bt_component_factory *component_factory; +GPtrArray *loaded_plugins; + +static +void init_loaded_plugins_array(void) +{ + loaded_plugins = g_ptr_array_new_full(8, bt_put); +} + +static +void fini_loaded_plugins_array(void) +{ + g_ptr_array_free(loaded_plugins, TRUE); +} + +static +struct bt_plugin *find_plugin(const char *name) +{ + int i; + struct bt_plugin *plugin = NULL; + + for (i = 0; i < loaded_plugins->len; i++) { + plugin = g_ptr_array_index(loaded_plugins, i); + + if (strcmp(name, bt_plugin_get_name(plugin)) == 0) { + break; + } + + plugin = NULL; + } + + return bt_get(plugin); +} + +static +struct bt_component_class *find_component_class(const char *plugin_name, + const char *comp_class_name, + enum bt_component_type comp_class_type) +{ + struct bt_component_class *comp_class = NULL; + struct bt_plugin *plugin = find_plugin(plugin_name); + + if (!plugin) { + goto end; + } + + comp_class = bt_plugin_get_component_class_by_name_and_type(plugin, + comp_class_name, comp_class_type); + BT_PUT(plugin); +end: + return comp_class; +} static const char *component_type_str(enum bt_component_type type) @@ -60,53 +114,65 @@ const char *component_type_str(enum bt_component_type type) } static -void print_component_classes_found(struct bt_component_factory *factory) +void print_component_classes_found(void) { - int count, i; + int plugins_count, component_classes_count = 0, i; if (!babeltrace_verbose) { return; } - count = bt_component_factory_get_component_class_count(factory); - if (count <= 0) { - fprintf(stderr, "No component classes found. Please make sure your plug-in search path is set correctly.\n"); + plugins_count = loaded_plugins->len; + if (plugins_count == 0) { + fprintf(stderr, "No plugins found. Please make sure your plug-in search path is set correctly.\n"); return; } - printf_verbose("Found %d component classes.\n", count); - for (i = 0; i < count; i++) { - struct bt_component_class *component_class = - bt_component_factory_get_component_class_index( - factory, i); - struct bt_plugin *plugin = bt_component_class_get_plugin( - component_class); - const char *plugin_name = bt_plugin_get_name(plugin); - const char *component_name = bt_component_class_get_name( - component_class); - const char *path = bt_plugin_get_path(plugin); - const char *author = bt_plugin_get_author(plugin); - const char *license = bt_plugin_get_license(plugin); - const char *plugin_description = bt_plugin_get_description( - plugin); - const char *component_description = - bt_component_class_get_description( - component_class); - enum bt_component_type type = bt_component_class_get_type( - component_class); - - printf_verbose("[%s - %s (%s)]\n", plugin_name, component_name, - component_type_str(type)); - printf_verbose("\tpath: %s\n", path ? path : "None"); - printf_verbose("\tauthor: %s\n", author ? author : "Unknown"); - printf_verbose("\tlicense: %s\n", license ? license : "Unknown"); - printf_verbose("\tplugin description: %s\n", - plugin_description ? plugin_description : "None"); - printf_verbose("\tcomponent description: %s\n", - component_description ? component_description : "None"); + for (i = 0; i < plugins_count; i++) { + struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i); + + component_classes_count += bt_plugin_get_component_class_count(plugin); + } - bt_put(plugin); - bt_put(component_class); + printf_verbose("Found %d component classes in %d plugins.\n", + component_classes_count, plugins_count); + + for (i = 0; i < plugins_count; i++) { + int j; + struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i); + + component_classes_count = + bt_plugin_get_component_class_count(plugin); + + for (j = 0; j < component_classes_count; j++) { + struct bt_component_class *comp_class = + bt_plugin_get_component_class(plugin, j); + const char *plugin_name = bt_plugin_get_name(plugin); + const char *comp_class_name = + bt_component_class_get_name(comp_class); + const char *path = bt_plugin_get_path(plugin); + const char *author = bt_plugin_get_author(plugin); + const char *license = bt_plugin_get_license(plugin); + const char *plugin_description = + bt_plugin_get_description(plugin); + const char *comp_class_description = + bt_component_class_get_description(comp_class); + enum bt_component_type type = + bt_component_class_get_type(comp_class); + + printf_verbose("[%s - %s (%s)]\n", plugin_name, + comp_class_name, component_type_str(type)); + printf_verbose("\tpath: %s\n", path ? path : "None"); + printf_verbose("\tauthor: %s\n", + author ? author : "Unknown"); + printf_verbose("\tlicense: %s\n", + license ? license : "Unknown"); + printf_verbose("\tplugin description: %s\n", + plugin_description ? plugin_description : "None"); + printf_verbose("\tcomponent description: %s\n", + comp_class_description ? comp_class_description : "None"); + bt_put(comp_class); + } } } @@ -250,7 +316,6 @@ struct bt_component *create_trimmer(struct bt_config_component *source_cfg) struct bt_value *trimmer_params = NULL; struct bt_value *value; - assert(component_factory); trimmer_params = bt_value_map_create(); if (!trimmer_params) { goto end; @@ -290,9 +355,8 @@ struct bt_component *create_trimmer(struct bt_config_component *source_cfg) } } - trimmer_class = bt_component_factory_get_component_class( - component_factory, "utils", BT_COMPONENT_TYPE_FILTER, - "trimmer"); + trimmer_class = find_component_class("utils", "trimmer", + BT_COMPONENT_TYPE_FILTER); if (!trimmer_class) { fprintf(stderr, "Could not find trimmer component class. Aborting...\n"); goto end; @@ -370,17 +434,44 @@ end: return ret; } -static int load_plugins(struct bt_config *cfg) +static +void add_to_loaded_plugins(struct bt_plugin **plugins) { - int nr_paths, i; + while (*plugins) { + struct bt_plugin *plugin = *plugins; + /* Check if it's already loaded (from another path). */ + struct bt_plugin *loaded_plugin = + find_plugin(bt_plugin_get_name(plugin)); + + if (loaded_plugin) { + printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n", + bt_plugin_get_path(plugin), + bt_plugin_get_path(loaded_plugin)); + BT_PUT(loaded_plugin); + BT_PUT(plugin); + } else { + /* Transfer ownership to global array. */ + g_ptr_array_add(loaded_plugins, plugin); + } + *(plugins++) = NULL; + } +} + +static +int load_dynamic_plugins(struct bt_config *cfg) +{ + int nr_paths, i, ret = 0; nr_paths = bt_value_array_size(cfg->plugin_paths); if (nr_paths < 0) { - return -1; + ret = -1; + goto end; } + for (i = 0; i < nr_paths; i++) { struct bt_value *plugin_path_value = NULL; const char *plugin_path; + struct bt_plugin **plugins; plugin_path_value = bt_value_array_get(cfg->plugin_paths, i); if (bt_value_string_get(plugin_path_value, @@ -388,14 +479,41 @@ static int load_plugins(struct bt_config *cfg) BT_PUT(plugin_path_value); continue; } - if (bt_component_factory_load_recursive(component_factory, - plugin_path)) { + + plugins = bt_plugin_create_all_from_dir(plugin_path, true); + if (!plugins) { printf_debug("Unable to dynamically load plugins from path %s.\n", plugin_path); + BT_PUT(plugin_path_value); + continue; } + + add_to_loaded_plugins(plugins); + free(plugins); + BT_PUT(plugin_path_value); } - return 0; +end: + return ret; +} + +static +int load_static_plugins(void) +{ + int ret = 0; + struct bt_plugin **plugins; + + plugins = bt_plugin_create_all_from_static(); + if (!plugins) { + printf_debug("Unable to load static plugins.\n"); + ret = -1; + goto end; + } + + add_to_loaded_plugins(plugins); + free(plugins); +end: + return ret; } int main(int argc, const char **argv) @@ -409,6 +527,8 @@ int main(int argc, const char **argv) enum bt_component_status sink_status; struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL; + init_loaded_plugins_array(); + cfg = bt_config_create(); if (!cfg) { fprintf(stderr, "Failed to create Babeltrace configuration\n"); @@ -421,7 +541,7 @@ int main(int argc, const char **argv) goto end; } - ret = bt_config_init_from_args(cfg, argc, argv); + ret = bt_config_init_from_args(cfg, argc, argv); if (ret == 0) { babeltrace_verbose = cfg->verbose; babeltrace_debug = cfg->debug; @@ -438,33 +558,24 @@ int main(int argc, const char **argv) printf_verbose("Verbose mode active.\n"); printf_debug("Debug mode active.\n"); - component_factory = bt_component_factory_create(); - if (!component_factory) { - fprintf(stderr, "Failed to create component factory.\n"); - ret = -1; - goto end; - } - if (load_plugins(cfg)) { - fprintf(stderr, "Failed to load plugins.\n"); + if (load_dynamic_plugins(cfg)) { + fprintf(stderr, "Failed to load dynamic plugins.\n"); ret = -1; goto end; } - ret = bt_component_factory_load_static(component_factory); - if (ret) { + if (load_static_plugins()) { fprintf(stderr, "Failed to load static plugins.\n"); goto end; } - print_component_classes_found(component_factory); - + print_component_classes_found(); source_cfg = bt_config_get_component(cfg->sources, 0); source_params = bt_get(source_cfg->params); - source_class = bt_component_factory_get_component_class( - component_factory, source_cfg->plugin_name->str, - BT_COMPONENT_TYPE_SOURCE, - source_cfg->component_name->str); + source_class = find_component_class(source_cfg->plugin_name->str, + source_cfg->component_name->str, + BT_COMPONENT_TYPE_SOURCE); if (!source_class) { fprintf(stderr, "Could not find %s.%s source component class. Aborting...\n", source_cfg->plugin_name->str, @@ -475,9 +586,9 @@ int main(int argc, const char **argv) sink_cfg = bt_config_get_component(cfg->sinks, 0); sink_params = bt_get(sink_cfg->params); - sink_class = bt_component_factory_get_component_class(component_factory, - sink_cfg->plugin_name->str, BT_COMPONENT_TYPE_SINK, - sink_cfg->component_name->str); + sink_class = find_component_class(sink_cfg->plugin_name->str, + sink_cfg->component_name->str, + BT_COMPONENT_TYPE_SINK); if (!sink_class) { fprintf(stderr, "Could not find %s.%s output component class. Aborting...\n", sink_cfg->plugin_name->str, @@ -523,7 +634,6 @@ int main(int argc, const char **argv) } } end: - BT_PUT(component_factory); BT_PUT(sink_class); BT_PUT(source_class); BT_PUT(source); @@ -533,5 +643,6 @@ end: BT_PUT(cfg); BT_PUT(sink_cfg); BT_PUT(source_cfg); + fini_loaded_plugins_array(); return ret ? 1 : 0; } diff --git a/formats/ctf/ir/trace.c b/formats/ctf/ir/trace.c index 9c314fe1..37884069 100644 --- a/formats/ctf/ir/trace.c +++ b/formats/ctf/ir/trace.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/Makefile.am b/include/Makefile.am index a463dba4..bcd1994a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -39,23 +39,24 @@ babeltracectfirinclude_HEADERS = \ babeltraceplugininclude_HEADERS = \ babeltrace/plugin/plugin.h \ - babeltrace/plugin/component.h \ - babeltrace/plugin/component-class.h \ - babeltrace/plugin/component-connection.h \ - babeltrace/plugin/component-factory.h \ - babeltrace/plugin/component-graph.h \ - babeltrace/plugin/source.h \ - babeltrace/plugin/sink.h \ - babeltrace/plugin/filter.h \ - babeltrace/plugin/plugin-system.h \ - babeltrace/plugin/notification/eot.h \ - babeltrace/plugin/notification/notification.h \ - babeltrace/plugin/notification/event.h \ - babeltrace/plugin/notification/iterator.h \ - babeltrace/plugin/notification/packet.h \ - babeltrace/plugin/notification/schema.h \ - babeltrace/plugin/notification/stream.h \ - babeltrace/plugin/notification/heap.h + babeltrace/plugin/plugin-dev.h + +babeltracecomponentinclude_HEADERS = \ + babeltrace/component/component.h \ + babeltrace/component/component-class.h \ + babeltrace/component/component-connection.h \ + babeltrace/component/component-graph.h \ + babeltrace/component/source.h \ + babeltrace/component/sink.h \ + babeltrace/component/filter.h \ + babeltrace/component/notification/eot.h \ + babeltrace/component/notification/notification.h \ + babeltrace/component/notification/event.h \ + babeltrace/component/notification/iterator.h \ + babeltrace/component/notification/packet.h \ + babeltrace/component/notification/schema.h \ + babeltrace/component/notification/stream.h \ + babeltrace/component/notification/heap.h noinst_HEADERS = \ babeltrace/align.h \ @@ -116,20 +117,19 @@ noinst_HEADERS = \ babeltrace/compat/mman.h \ babeltrace/endian.h \ babeltrace/mmap-align.h \ - babeltrace/plugin/component-class-internal.h \ - babeltrace/plugin/component-connection-internal.h \ - babeltrace/plugin/component-factory-internal.h \ - babeltrace/plugin/component-internal.h \ - babeltrace/plugin/component-graph-internal.h \ babeltrace/plugin/plugin-internal.h \ - babeltrace/plugin/filter-internal.h \ - babeltrace/plugin/sink-internal.h \ - babeltrace/plugin/source-internal.h \ - babeltrace/plugin/input.h \ - babeltrace/plugin/notification/eot-internal.h \ - babeltrace/plugin/notification/event-internal.h \ - babeltrace/plugin/notification/iterator-internal.h \ - babeltrace/plugin/notification/notification-internal.h \ - babeltrace/plugin/notification/packet-internal.h \ - babeltrace/plugin/notification/stream-internal.h \ - babeltrace/plugin/notification/heap-internal.h + babeltrace/component/component-class-internal.h \ + babeltrace/component/component-connection-internal.h \ + babeltrace/component/component-internal.h \ + babeltrace/component/component-graph-internal.h \ + babeltrace/component/filter-internal.h \ + babeltrace/component/sink-internal.h \ + babeltrace/component/source-internal.h \ + babeltrace/component/input.h \ + babeltrace/component/notification/eot-internal.h \ + babeltrace/component/notification/event-internal.h \ + babeltrace/component/notification/iterator-internal.h \ + babeltrace/component/notification/notification-internal.h \ + babeltrace/component/notification/packet-internal.h \ + babeltrace/component/notification/stream-internal.h \ + babeltrace/component/notification/heap-internal.h diff --git a/include/babeltrace/plugin/component-class-internal.h b/include/babeltrace/component/component-class-internal.h similarity index 64% rename from include/babeltrace/plugin/component-class-internal.h rename to include/babeltrace/component/component-class-internal.h index ccedff87..7ed0f163 100644 --- a/include/babeltrace/plugin/component-class-internal.h +++ b/include/babeltrace/component/component-class-internal.h @@ -1,10 +1,11 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_CLASS_INTERNAL_H -#define BABELTRACE_PLUGIN_COMPONENT_CLASS_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_COMPONENT_CLASS_INTERNAL_H +#define BABELTRACE_COMPONENT_COMPONENT_CLASS_INTERNAL_H /* * BabelTrace - Component Class Internal * * Copyright 2015 Jérémie Galarneau + * Copyright 2017 Philippe Proulx * * Author: Jérémie Galarneau * @@ -27,28 +28,35 @@ * SOFTWARE. */ +#include +#include #include -#include -#include #include +#include + +struct bt_component_class; + +typedef void (*bt_component_class_destroy_listener_func)( + struct bt_component_class *class, void *data); + +struct bt_component_class_destroyer_listener { + bt_component_class_destroy_listener_func func; + void *data; +}; struct bt_component_class { struct bt_object base; enum bt_component_type type; GString *name; GString *description; - struct bt_plugin *plugin; bt_component_init_cb init; -}; -BT_HIDDEN -int bt_component_class_init(struct bt_component_class *class, - enum bt_component_type type, const char *name); + /* Array of struct bt_component_class_destroyer_listener */ + GArray *destroy_listeners; +}; BT_HIDDEN -struct bt_component_class *bt_component_class_create( - enum bt_component_type type, const char *name, - const char *description, bt_component_init_cb init, - struct bt_plugin *plugin); +int bt_component_class_add_destroy_listener(struct bt_component_class *class, + bt_component_class_destroy_listener_func func, void *data); -#endif /* BABELTRACE_PLUGIN_COMPONENT_CLASS_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_COMPONENT_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/plugin/component-class.h b/include/babeltrace/component/component-class.h similarity index 85% rename from include/babeltrace/plugin/component-class.h rename to include/babeltrace/component/component-class.h index 1526e4cb..d12a1202 100644 --- a/include/babeltrace/plugin/component-class.h +++ b/include/babeltrace/component/component-class.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_CLASS_H -#define BABELTRACE_PLUGIN_COMPONENT_CLASS_H +#ifndef BABELTRACE_COMPONENT_COMPONENT_CLASS_H +#define BABELTRACE_COMPONENT_COMPONENT_CLASS_H /* * Babeltrace - Component Class Interface. @@ -25,6 +25,8 @@ * SOFTWARE. */ +#include + #ifdef __cplusplus extern "C" { #endif @@ -48,6 +50,9 @@ enum bt_component_type { struct bt_plugin; struct bt_component_class; +extern struct bt_component_class *bt_component_class_create( + enum bt_component_type type, const char *name, + const char *description, bt_component_init_cb init); /** * Get a component class' name. @@ -79,13 +84,4 @@ extern const char *bt_component_class_get_description( extern enum bt_component_type bt_component_class_get_type( struct bt_component_class *component_class); -/** - * Get a component class' plug-in. - * - * @param component_class Component class of which to get the plug-in - * @returns The plug-in which registered the component class - */ -extern struct bt_plugin *bt_component_class_get_plugin( - struct bt_component_class *component_class); - -#endif /* BABELTRACE_PLUGIN_COMPONENT_CLASS_H */ +#endif /* BABELTRACE_COMPONENT_COMPONENT_CLASS_H */ diff --git a/include/babeltrace/plugin/component-connection-internal.h b/include/babeltrace/component/component-connection-internal.h similarity index 100% rename from include/babeltrace/plugin/component-connection-internal.h rename to include/babeltrace/component/component-connection-internal.h diff --git a/include/babeltrace/plugin/component-connection.h b/include/babeltrace/component/component-connection.h similarity index 100% rename from include/babeltrace/plugin/component-connection.h rename to include/babeltrace/component/component-connection.h diff --git a/include/babeltrace/plugin/component-graph-internal.h b/include/babeltrace/component/component-graph-internal.h similarity index 89% rename from include/babeltrace/plugin/component-graph-internal.h rename to include/babeltrace/component/component-graph-internal.h index ba618b73..ab89a036 100644 --- a/include/babeltrace/plugin/component-graph-internal.h +++ b/include/babeltrace/component/component-graph-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_GRAPH_INTERNAL_H -#define BABELTRACE_PLUGIN_COMPONENT_GRAPH_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_COMPONENT_GRAPH_INTERNAL_H +#define BABELTRACE_COMPONENT_COMPONENT_GRAPH_INTERNAL_H /* * BabelTrace - Component Graph Internal @@ -27,7 +27,7 @@ * SOFTWARE. */ -#include +#include #include #include #include @@ -52,4 +52,4 @@ struct bt_component_graph { GPtrArray *sinks; }; -#endif /* BABELTRACE_PLUGIN_COMPONENT_GRAPH_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_COMPONENT_GRAPH_INTERNAL_H */ diff --git a/include/babeltrace/plugin/component-graph.h b/include/babeltrace/component/component-graph.h similarity index 92% rename from include/babeltrace/plugin/component-graph.h rename to include/babeltrace/component/component-graph.h index 60dfe470..d87b43b9 100644 --- a/include/babeltrace/plugin/component-graph.h +++ b/include/babeltrace/component/component-graph.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_GRAPH_H -#define BABELTRACE_PLUGIN_COMPONENT_GRAPH_H +#ifndef BABELTRACE_COMPONENT_COMPONENT_GRAPH_H +#define BABELTRACE_COMPONENT_COMPONENT_GRAPH_H /* * BabelTrace - Babeltrace Component Graph Interface @@ -27,8 +27,8 @@ * SOFTWARE. */ -#include -#include +#include +#include #include #include @@ -96,4 +96,4 @@ extern enum bt_component_graph_status bt_component_graph_run( } #endif -#endif /* BABELTRACE_PLUGIN_COMPONENT_GRAPH_H */ +#endif /* BABELTRACE_COMPONENT_COMPONENT_GRAPH_H */ diff --git a/include/babeltrace/plugin/component-internal.h b/include/babeltrace/component/component-internal.h similarity index 88% rename from include/babeltrace/plugin/component-internal.h rename to include/babeltrace/component/component-internal.h index 9cc39b3b..7c18f494 100644 --- a/include/babeltrace/plugin/component-internal.h +++ b/include/babeltrace/component/component-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_INTERNAL_H -#define BABELTRACE_PLUGIN_COMPONENT_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_COMPONENT_INTERNAL_H +#define BABELTRACE_COMPONENT_COMPONENT_INTERNAL_H /* * BabelTrace - Component internal @@ -28,9 +28,8 @@ */ #include -#include -#include -#include +#include +#include #include #include #include @@ -64,4 +63,4 @@ BT_HIDDEN struct bt_notification_iterator *bt_component_create_iterator( struct bt_component *component); -#endif /* BABELTRACE_PLUGIN_COMPONENT_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_COMPONENT_INTERNAL_H */ diff --git a/include/babeltrace/plugin/plugin-system.h b/include/babeltrace/component/component.h similarity index 66% rename from include/babeltrace/plugin/plugin-system.h rename to include/babeltrace/component/component.h index 1ec7a08c..7a1464fd 100644 --- a/include/babeltrace/plugin/plugin-system.h +++ b/include/babeltrace/component/component.h @@ -1,11 +1,8 @@ -#ifndef BABELTRACE_PLUGIN_SYSTEM_H -#define BABELTRACE_PLUGIN_SYSTEM_H +#ifndef BABELTRACE_COMPONENT_COMPONENT_H +#define BABELTRACE_COMPONENT_COMPONENT_H /* - * BabelTrace - Babeltrace Plug-in System Interface - * - * This interface is provided for plug-ins to use the Babeltrace - * plug-in system facilities. + * BabelTrace - Babeltrace Component Interface * * Copyright 2015 Jérémie Galarneau * @@ -30,22 +27,41 @@ * SOFTWARE. */ -#include -#include +#include +#include +#include #ifdef __cplusplus extern "C" { #endif -struct bt_notification; -struct bt_notification_iterator; +/** + * Status code. Errors are always negative. + */ +enum bt_component_status { + /** No error, okay. */ + BT_COMPONENT_STATUS_OK = 0, + /** No more work to be done by this component. **/ + BT_COMPONENT_STATUS_END = 1, + /** + * Component can't process a notification at this time + * (e.g. would block), try again later. + */ + BT_COMPONENT_STATUS_AGAIN = 2, + /** General error. */ + BT_COMPONENT_STATUS_ERROR = -1, + /** Unsupported component feature. */ + BT_COMPONENT_STATUS_UNSUPPORTED = -2, + /** Invalid arguments. */ + BT_COMPONENT_STATUS_INVALID = -3, + /** Memory allocation failure. */ + BT_COMPONENT_STATUS_NOMEM = -4, +}; + +struct bt_component_class; struct bt_component; -struct bt_component_factory; struct bt_value; -typedef enum bt_component_status (*bt_plugin_register_func)( - struct bt_component_factory *factory); - /** * Component private data deallocation function type. * @@ -66,6 +82,7 @@ typedef void (*bt_component_destroy_cb)(struct bt_component *component); typedef enum bt_component_status (*bt_component_init_cb)( struct bt_component *component, struct bt_value *params); + /** * Get a component's private data. * @@ -247,112 +264,47 @@ extern enum bt_component_status bt_component_filter_get_input_iterator(struct bt_component *filter, unsigned int input, struct bt_notification_iterator **iterator); -/** bt_notification_iterator */ -/** - * Function returning an iterator's current notification. - * - * @param iterator Notification iterator instance - * @returns A notification instance - */ -typedef struct bt_notification *(*bt_notification_iterator_get_cb)( - struct bt_notification_iterator *iterator); - -/** - * Function advancing an iterator's position of one element. - * - * @param iterator Notification iterator instance - * @returns One of #bt_notification_iterator_status values - */ -typedef enum bt_notification_iterator_status (*bt_notification_iterator_next_cb)( - struct bt_notification_iterator *iterator); - -/** - * Function advancing an iterator's position to a given time (relative to Epoch). - * - * @param iterator Notification iterator instance - * @param time Time at which to seek, expressed in ns since Epoch - * @returns One of #bt_notification_iterator_status values - */ -typedef enum bt_notification_iterator_status - (*bt_notification_iterator_seek_time_cb)( - struct bt_notification_iterator *iterator, int64_t time); - /** - * Function cleaning-up an iterator's private data on destruction. + * Create an instance of a component from a component class. * - * @param iterator Notification iterator instance - */ -typedef void (*bt_notification_iterator_destroy_cb)( - struct bt_notification_iterator *iterator); - -/** - * Set an iterator's "get" callback which return the current notification. - * - * @param iterator Notification iterator instance - * @param get Notification return callback - * @returns One of #bt_notification_iterator_status values - */ -extern enum bt_notification_iterator_status -bt_notification_iterator_set_get_cb(struct bt_notification_iterator *iterator, - bt_notification_iterator_get_cb get); - -/** - * Set an iterator's "next" callback which advances the iterator's position. - * - * @param iterator Notification iterator instance - * @param next Iterator "next" callback - * @returns One of #bt_notification_iterator_status values - */ -extern enum bt_notification_iterator_status -bt_notification_iterator_set_next_cb(struct bt_notification_iterator *iterator, - bt_notification_iterator_next_cb next); - -/** - * Set an iterator's "seek_time" callback which sets the iterator's position to - * provided time (in ns since Epoch). - * - * @param iterator Notification iterator instance - * @param seek_timetime Iterator "seek_time" callback - * @returns One of #bt_notification_iterator_status values + * @param component_class Component class of which to create an instance + * @param name Name of the new component instance, optional + * @param params A dictionary of component parameters + * @returns Returns a pointer to a new component instance */ -extern enum bt_notification_iterator_status -bt_notification_iterator_set_seek_time_cb(struct bt_notification_iterator *iterator, - bt_notification_iterator_seek_time_cb seek_time); +extern struct bt_component *bt_component_create( + struct bt_component_class *component_class, const char *name, + struct bt_value *params); /** - * Set an iterator's "destroy" callback. + * Get component's name. * - * @param iterator Notification iterator instance - * @param next Iterator destruction callback - * @returns One of #bt_notification_iterator_status values + * @param component Component instance of which to get the name + * @returns Returns a pointer to the component's name */ -extern enum bt_notification_iterator_status -bt_notification_iterator_set_destroy_cb( - struct bt_notification_iterator *iterator, - bt_notification_iterator_destroy_cb destroy); +extern const char *bt_component_get_name(struct bt_component *component); /** - * Set an iterator's private data. + * Set component's name. * - * @param iterator Notification iterator instance - * @param data Iterator private data - * @returns One of #bt_notification_iterator_status values + * @param component Component instance of which to set the name + * @param name New component name (will be copied) + * @returns One of #bt_component_status values */ -extern enum bt_notification_iterator_status -bt_notification_iterator_set_private_data( - struct bt_notification_iterator *iterator, void *data); +extern enum bt_component_status bt_component_set_name( + struct bt_component *component, const char *name); /** - * Get an iterator's private data. + * Get component's class. * - * @param iterator Notification iterator instance - * @returns Iterator instance private data + * @param component Component instance of which to get the class + * @returns The component's class */ -extern void *bt_notification_iterator_get_private_data( - struct bt_notification_iterator *iterator); +extern struct bt_component_class *bt_component_get_class( + struct bt_component *component); #ifdef __cplusplus } #endif -#endif /* BABELTRACE_PLUGIN_SYSTEM_H */ +#endif /* BABELTRACE_COMPONENT_COMPONENT_H */ diff --git a/include/babeltrace/plugin/filter-internal.h b/include/babeltrace/component/filter-internal.h similarity index 86% rename from include/babeltrace/plugin/filter-internal.h rename to include/babeltrace/component/filter-internal.h index 00498e40..3a17aa00 100644 --- a/include/babeltrace/plugin/filter-internal.h +++ b/include/babeltrace/component/filter-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_FILTER_INTERNAL_H -#define BABELTRACE_PLUGIN_FILTER_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_FILTER_INTERNAL_H +#define BABELTRACE_COMPONENT_FILTER_INTERNAL_H /* * BabelTrace - Filter Component Internal @@ -28,10 +28,9 @@ */ #include -#include -#include -#include -#include +#include +#include +#include struct bt_value; @@ -67,4 +66,4 @@ BT_HIDDEN enum bt_component_status bt_component_filter_validate( struct bt_component *component); -#endif /* BABELTRACE_PLUGIN_FILTER_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_FILTER_INTERNAL_H */ diff --git a/include/babeltrace/plugin/filter.h b/include/babeltrace/component/filter.h similarity index 92% rename from include/babeltrace/plugin/filter.h rename to include/babeltrace/component/filter.h index 14c6129f..f33d49f7 100644 --- a/include/babeltrace/plugin/filter.h +++ b/include/babeltrace/component/filter.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_FILTER_H -#define BABELTRACE_PLUGIN_FILTER_H +#ifndef BABELTRACE_COMPONENT_FILTER_H +#define BABELTRACE_COMPONENT_FILTER_H /* * BabelTrace - Filter Plug-in Interface @@ -28,7 +28,7 @@ */ #include -#include +#include #ifdef __cplusplus extern "C" { @@ -63,4 +63,4 @@ struct bt_notification_iterator *bt_component_filter_create_iterator( } #endif -#endif /* BABELTRACE_PLUGIN_FILTER_H */ +#endif /* BABELTRACE_COMPONENT_FILTER_H */ diff --git a/include/babeltrace/plugin/input.h b/include/babeltrace/component/input.h similarity index 92% rename from include/babeltrace/plugin/input.h rename to include/babeltrace/component/input.h index e4b861b8..7bf55421 100644 --- a/include/babeltrace/plugin/input.h +++ b/include/babeltrace/component/input.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_INPUT_INTERNAL_H -#define BABELTRACE_PLUGIN_INPUT_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_INPUT_INTERNAL_H +#define BABELTRACE_COMPONENT_INPUT_INTERNAL_H /* * BabelTrace - Component Input @@ -48,4 +48,4 @@ int component_input_validate(struct component_input *input); BT_HIDDEN void component_input_fini(struct component_input *input); -#endif /* BABELTRACE_PLUGIN_INPUT_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_INPUT_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/eot-internal.h b/include/babeltrace/component/notification/eot-internal.h similarity index 100% rename from include/babeltrace/plugin/notification/eot-internal.h rename to include/babeltrace/component/notification/eot-internal.h diff --git a/include/babeltrace/plugin/notification/eot.h b/include/babeltrace/component/notification/eot.h similarity index 90% rename from include/babeltrace/plugin/notification/eot.h rename to include/babeltrace/component/notification/eot.h index d33476c8..4c3626c1 100644 --- a/include/babeltrace/plugin/notification/eot.h +++ b/include/babeltrace/component/notification/eot.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_EOT_H -#define BABELTRACE_PLUGIN_NOTIFICATION_EOT_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_EOT_H +#define BABELTRACE_COMPONENT_NOTIFICATION_EOT_H /* * BabelTrace - Plug-in End of Trace Notification @@ -35,4 +35,4 @@ extern "C" { } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_EOT_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_EOT_H */ diff --git a/include/babeltrace/plugin/notification/event-internal.h b/include/babeltrace/component/notification/event-internal.h similarity index 85% rename from include/babeltrace/plugin/notification/event-internal.h rename to include/babeltrace/component/notification/event-internal.h index 1f3143ff..3db8ffd3 100644 --- a/include/babeltrace/plugin/notification/event-internal.h +++ b/include/babeltrace/component/notification/event-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_EVENT_INTERNAL_H -#define BABELTRACE_PLUGIN_NOTIFICATION_EVENT_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_EVENT_INTERNAL_H +#define BABELTRACE_COMPONENT_NOTIFICATION_EVENT_INTERNAL_H /* * BabelTrace - Plug-in Event Notification internal @@ -28,7 +28,7 @@ */ #include -#include +#include #ifdef __cplusplus extern "C" { @@ -43,4 +43,4 @@ struct bt_notification_event { } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_EVENT_INTERNAL_H */ +#endif /* BABELTRACECOMPONENTPLUGIN_NOTIFICATION_EVENT_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/event.h b/include/babeltrace/component/notification/event.h similarity index 92% rename from include/babeltrace/plugin/notification/event.h rename to include/babeltrace/component/notification/event.h index d60cd564..e5947b7e 100644 --- a/include/babeltrace/plugin/notification/event.h +++ b/include/babeltrace/component/notification/event.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_EVENT_H -#define BABELTRACE_PLUGIN_NOTIFICATION_EVENT_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_EVENT_H +#define BABELTRACE_COMPONENT_NOTIFICATION_EVENT_H /* * BabelTrace - Plug-in Event Notification @@ -61,4 +61,4 @@ extern struct bt_ctf_event *bt_notification_event_get_event( } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_EVENT_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_EVENT_H */ diff --git a/include/babeltrace/plugin/notification/heap-internal.h b/include/babeltrace/component/notification/heap-internal.h similarity index 83% rename from include/babeltrace/plugin/notification/heap-internal.h rename to include/babeltrace/component/notification/heap-internal.h index e21accbb..86037801 100644 --- a/include/babeltrace/plugin/notification/heap-internal.h +++ b/include/babeltrace/component/notification/heap-internal.h @@ -1,5 +1,5 @@ -#ifndef CTF_NOTIF_HEAP_INTERNAL_H -#define CTF_NOTIF_HEAP_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_HEAP_INTERNAL_H +#define BABELTRACE_COMPONENT_NOTIFICATION_HEAP_INTERNAL_H /* * Babeltrace - CTF notification heap priority heap @@ -26,8 +26,8 @@ */ #include -#include -#include +#include +#include #include struct bt_notification_heap { @@ -38,4 +38,4 @@ struct bt_notification_heap { void *compare_data; }; -#endif /* CTF_NOTIF_HEAP_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_HEAP_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/heap.h b/include/babeltrace/component/notification/heap.h similarity index 94% rename from include/babeltrace/plugin/notification/heap.h rename to include/babeltrace/component/notification/heap.h index 7fde9edd..3a5ce6d4 100644 --- a/include/babeltrace/plugin/notification/heap.h +++ b/include/babeltrace/component/notification/heap.h @@ -1,5 +1,5 @@ -#ifndef BT_NOTIFICATION_HEAP_H -#define BT_NOTIFICATION_HEAP_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_HEAP_H +#define BABELTRACE_COMPONENT_NOTIFICATION_HEAP_H /* * Babeltrace - Notification Heap @@ -28,7 +28,7 @@ #include #include -#include +#include #include /** @@ -90,4 +90,4 @@ extern struct bt_notification *bt_notification_heap_peek( extern struct bt_notification *bt_notification_heap_pop( struct bt_notification_heap *heap); -#endif /* BT_NOTIFICATION_HEAP_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_HEAP_H */ diff --git a/include/babeltrace/plugin/notification/iterator-internal.h b/include/babeltrace/component/notification/iterator-internal.h similarity index 89% rename from include/babeltrace/plugin/notification/iterator-internal.h rename to include/babeltrace/component/notification/iterator-internal.h index 4718359a..29a5ff0f 100644 --- a/include/babeltrace/plugin/notification/iterator-internal.h +++ b/include/babeltrace/component/notification/iterator-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_ITERATOR_INTERNAL_H -#define BABELTRACE_PLUGIN_ITERATOR_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_ITERATOR_INTERNAL_H +#define BABELTRACE_COMPONENT_NOTIFICATION_ITERATOR_INTERNAL_H /* * BabelTrace - Notification Iterator Internal @@ -28,9 +28,8 @@ */ #include -#include #include -#include +#include struct bt_notification_iterator { struct bt_object base; @@ -62,4 +61,4 @@ BT_HIDDEN enum bt_notification_iterator_status bt_notification_iterator_validate( struct bt_notification_iterator *iterator); -#endif /* BABELTRACE_PLUGIN_ITERATOR_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_ITERATOR_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/iterator.h b/include/babeltrace/component/notification/iterator.h similarity index 53% rename from include/babeltrace/plugin/notification/iterator.h rename to include/babeltrace/component/notification/iterator.h index 20bc1cbc..69c9b39a 100644 --- a/include/babeltrace/plugin/notification/iterator.h +++ b/include/babeltrace/component/notification/iterator.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_ITERATOR_H -#define BABELTRACE_PLUGIN_NOTIFICATION_ITERATOR_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_ITERATOR_H +#define BABELTRACE_COMPONENT_NOTIFICATION_ITERATOR_H /* * BabelTrace - Plug-in Notification Iterator @@ -126,8 +126,113 @@ extern enum bt_notification_iterator_status bt_notification_iterator_seek_time( extern struct bt_component *bt_notification_iterator_get_component( struct bt_notification_iterator *iterator); +/** bt_notification_iterator */ +/** + * Function returning an iterator's current notification. + * + * @param iterator Notification iterator instance + * @returns A notification instance + */ +typedef struct bt_notification *(*bt_notification_iterator_get_cb)( + struct bt_notification_iterator *iterator); + +/** + * Function advancing an iterator's position of one element. + * + * @param iterator Notification iterator instance + * @returns One of #bt_notification_iterator_status values + */ +typedef enum bt_notification_iterator_status (*bt_notification_iterator_next_cb)( + struct bt_notification_iterator *iterator); + +/** + * Function advancing an iterator's position to a given time (relative to Epoch). + * + * @param iterator Notification iterator instance + * @param time Time at which to seek, expressed in ns since Epoch + * @returns One of #bt_notification_iterator_status values + */ +typedef enum bt_notification_iterator_status + (*bt_notification_iterator_seek_time_cb)( + struct bt_notification_iterator *iterator, int64_t time); + +/** + * Function cleaning-up an iterator's private data on destruction. + * + * @param iterator Notification iterator instance + */ +typedef void (*bt_notification_iterator_destroy_cb)( + struct bt_notification_iterator *iterator); + +/** + * Set an iterator's "get" callback which return the current notification. + * + * @param iterator Notification iterator instance + * @param get Notification return callback + * @returns One of #bt_notification_iterator_status values + */ +extern enum bt_notification_iterator_status +bt_notification_iterator_set_get_cb(struct bt_notification_iterator *iterator, + bt_notification_iterator_get_cb get); + +/** + * Set an iterator's "next" callback which advances the iterator's position. + * + * @param iterator Notification iterator instance + * @param next Iterator "next" callback + * @returns One of #bt_notification_iterator_status values + */ +extern enum bt_notification_iterator_status +bt_notification_iterator_set_next_cb(struct bt_notification_iterator *iterator, + bt_notification_iterator_next_cb next); + +/** + * Set an iterator's "seek_time" callback which sets the iterator's position to + * provided time (in ns since Epoch). + * + * @param iterator Notification iterator instance + * @param seek_timetime Iterator "seek_time" callback + * @returns One of #bt_notification_iterator_status values + */ +extern enum bt_notification_iterator_status +bt_notification_iterator_set_seek_time_cb(struct bt_notification_iterator *iterator, + bt_notification_iterator_seek_time_cb seek_time); + +/** + * Set an iterator's "destroy" callback. + * + * @param iterator Notification iterator instance + * @param next Iterator destruction callback + * @returns One of #bt_notification_iterator_status values + */ +extern enum bt_notification_iterator_status +bt_notification_iterator_set_destroy_cb( + struct bt_notification_iterator *iterator, + bt_notification_iterator_destroy_cb destroy); + +/** + * Set an iterator's private data. + * + * @param iterator Notification iterator instance + * @param data Iterator private data + * @returns One of #bt_notification_iterator_status values + */ +extern enum bt_notification_iterator_status +bt_notification_iterator_set_private_data( + struct bt_notification_iterator *iterator, void *data); + +/** + * Get an iterator's private data. + * + * @param iterator Notification iterator instance + * @returns Iterator instance private data + */ +extern void *bt_notification_iterator_get_private_data( + struct bt_notification_iterator *iterator); + + #ifdef __cplusplus } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_ITERATOR_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_ITERATOR_H */ diff --git a/include/babeltrace/plugin/notification/notification-internal.h b/include/babeltrace/component/notification/notification-internal.h similarity index 87% rename from include/babeltrace/plugin/notification/notification-internal.h rename to include/babeltrace/component/notification/notification-internal.h index 2259eac0..8f3d055b 100644 --- a/include/babeltrace/plugin/notification/notification-internal.h +++ b/include/babeltrace/component/notification/notification-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_INTERNAL_H -#define BABELTRACE_PLUGIN_NOTIFICATION_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_NOTIFICATION_INTERNAL_H +#define BABELTRACE_COMPONENT_NOTIFICATION_NOTIFICATION_INTERNAL_H /* * BabelTrace - Plug-in Notification internal @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #ifdef __cplusplus @@ -55,4 +55,4 @@ void bt_notification_init(struct bt_notification *notification, } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_NOTIFICATION_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/notification.h b/include/babeltrace/component/notification/notification.h similarity index 93% rename from include/babeltrace/plugin/notification/notification.h rename to include/babeltrace/component/notification/notification.h index 34a185a0..d1797337 100644 --- a/include/babeltrace/plugin/notification/notification.h +++ b/include/babeltrace/component/notification/notification.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_H -#define BABELTRACE_PLUGIN_NOTIFICATION_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_NOTIFICATION_H +#define BABELTRACE_COMPONENT_NOTIFICATION_NOTIFICATION_H /* * BabelTrace - Plug-in Notification @@ -85,4 +85,4 @@ extern enum bt_notification_type bt_notification_get_type( } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_NOTIFICATION_H */ diff --git a/include/babeltrace/plugin/notification/packet-internal.h b/include/babeltrace/component/notification/packet-internal.h similarity index 85% rename from include/babeltrace/plugin/notification/packet-internal.h rename to include/babeltrace/component/notification/packet-internal.h index e36bb6a1..3b7836d8 100644 --- a/include/babeltrace/plugin/notification/packet-internal.h +++ b/include/babeltrace/component/notification/packet-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_PACKET_INTERNAL_H -#define BABELTRACE_PLUGIN_NOTIFICATION_PACKET_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_PACKET_INTERNAL_H +#define BABELTRACE_COMPONENT_NOTIFICATION_PACKET_INTERNAL_H /* * BabelTrace - Packet-related Notifications @@ -28,7 +28,7 @@ */ #include -#include +#include struct bt_notification_packet_begin { struct bt_notification parent; @@ -40,4 +40,4 @@ struct bt_notification_packet_end { struct bt_ctf_packet *packet; }; -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_PACKET_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_PACKET_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/packet.h b/include/babeltrace/component/notification/packet.h similarity index 89% rename from include/babeltrace/plugin/notification/packet.h rename to include/babeltrace/component/notification/packet.h index c90b4c99..d457aa21 100644 --- a/include/babeltrace/plugin/notification/packet.h +++ b/include/babeltrace/component/notification/packet.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_PACKET_H -#define BABELTRACE_PLUGIN_NOTIFICATION_PACKET_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_PACKET_H +#define BABELTRACE_COMPONENT_NOTIFICATION_PACKET_H /* * BabelTrace - Plug-in Packet-related Notifications @@ -27,7 +27,7 @@ * SOFTWARE. */ -#include +#include #ifdef __cplusplus extern "C" { @@ -51,4 +51,4 @@ struct bt_ctf_packet *bt_notification_packet_end_get_packet( } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_PACKET_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_PACKET_H */ diff --git a/include/babeltrace/plugin/notification/schema.h b/include/babeltrace/component/notification/schema.h similarity index 95% rename from include/babeltrace/plugin/notification/schema.h rename to include/babeltrace/component/notification/schema.h index 5d7b6425..eb6f09e9 100644 --- a/include/babeltrace/plugin/notification/schema.h +++ b/include/babeltrace/component/notification/schema.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_SCHEMA_H -#define BABELTRACE_PLUGIN_NOTIFICATION_SCHEMA_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_SCHEMA_H +#define BABELTRACE_COMPONENT_NOTIFICATION_SCHEMA_H /* * BabelTrace - Plug-in Schema Change Notification @@ -111,4 +111,4 @@ extern struct bt_ctf_trace *bt_notification_new_trace_get_trace( } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_SCHEMA_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_SCHEMA_H */ diff --git a/include/babeltrace/plugin/notification/stream-internal.h b/include/babeltrace/component/notification/stream-internal.h similarity index 84% rename from include/babeltrace/plugin/notification/stream-internal.h rename to include/babeltrace/component/notification/stream-internal.h index 73e2fd63..83c7e24b 100644 --- a/include/babeltrace/plugin/notification/stream-internal.h +++ b/include/babeltrace/component/notification/stream-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_STREAM_INTERNAL_H -#define BABELTRACE_PLUGIN_NOTIFICATION_STREAM_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_STREAM_INTERNAL_H +#define BABELTRACE_COMPONENT_NOTIFICATION_STREAM_INTERNAL_H /* * BabelTrace - Stream-related Notifications @@ -28,11 +28,11 @@ */ #include -#include +#include struct bt_notification_stream_end { struct bt_notification parent; struct bt_ctf_stream *stream; }; -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_STREAM_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_STREAM_INTERNAL_H */ diff --git a/include/babeltrace/plugin/notification/stream.h b/include/babeltrace/component/notification/stream.h similarity index 88% rename from include/babeltrace/plugin/notification/stream.h rename to include/babeltrace/component/notification/stream.h index f717365c..c33b2518 100644 --- a/include/babeltrace/plugin/notification/stream.h +++ b/include/babeltrace/component/notification/stream.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_NOTIFICATION_STREAM_H -#define BABELTRACE_PLUGIN_NOTIFICATION_STREAM_H +#ifndef BABELTRACE_COMPONENT_NOTIFICATION_STREAM_H +#define BABELTRACE_COMPONENT_NOTIFICATION_STREAM_H /* * BabelTrace - Plug-in Stream-related Notifications @@ -27,7 +27,7 @@ * SOFTWARE. */ -#include +#include #include #ifdef __cplusplus @@ -44,4 +44,4 @@ struct bt_ctf_stream *bt_notification_stream_end_get_stream( } #endif -#endif /* BABELTRACE_PLUGIN_NOTIFICATION_STREAM_H */ +#endif /* BABELTRACE_COMPONENT_NOTIFICATION_STREAM_H */ diff --git a/include/babeltrace/plugin/sink-internal.h b/include/babeltrace/component/sink-internal.h similarity index 87% rename from include/babeltrace/plugin/sink-internal.h rename to include/babeltrace/component/sink-internal.h index 5d0588aa..41733c39 100644 --- a/include/babeltrace/plugin/sink-internal.h +++ b/include/babeltrace/component/sink-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_SINK_INTERNAL_H -#define BABELTRACE_PLUGIN_SINK_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_SINK_INTERNAL_H +#define BABELTRACE_COMPONENT_SINK_INTERNAL_H /* * BabelTrace - Sink Component internal @@ -28,10 +28,9 @@ */ #include -#include -#include -#include -#include +#include +#include +#include struct bt_value; @@ -70,4 +69,4 @@ BT_HIDDEN enum bt_component_status bt_component_sink_validate( struct bt_component *component); -#endif /* BABELTRACE_PLUGIN_SINK_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_SINK_INTERNAL_H */ diff --git a/include/babeltrace/plugin/sink.h b/include/babeltrace/component/sink.h similarity index 91% rename from include/babeltrace/plugin/sink.h rename to include/babeltrace/component/sink.h index c61d752d..31b5b67f 100644 --- a/include/babeltrace/plugin/sink.h +++ b/include/babeltrace/component/sink.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_SINK_H -#define BABELTRACE_PLUGIN_COMPONENT_SINK_H +#ifndef BABELTRACE_COMPONENT_SINK_H +#define BABELTRACE_COMPONENT_SINK_H /* * BabelTrace - Sink Component Interface @@ -27,7 +27,7 @@ * SOFTWARE. */ -#include +#include #ifdef __cplusplus extern "C" { @@ -62,4 +62,4 @@ enum bt_component_status bt_component_sink_consume( } #endif -#endif /* BABELTRACE_PLUGIN_COMPONENT_SINK_H */ +#endif /* BABELTRACE_COMPONENT_SINK_H */ diff --git a/include/babeltrace/plugin/source-internal.h b/include/babeltrace/component/source-internal.h similarity index 87% rename from include/babeltrace/plugin/source-internal.h rename to include/babeltrace/component/source-internal.h index 90e57dd9..0a926fc7 100644 --- a/include/babeltrace/plugin/source-internal.h +++ b/include/babeltrace/component/source-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_SOURCE_INTERNAL_H -#define BABELTRACE_PLUGIN_SOURCE_INTERNAL_H +#ifndef BABELTRACE_COMPONENT_SOURCE_INTERNAL_H +#define BABELTRACE_COMPONENT_SOURCE_INTERNAL_H /* * BabelTrace - Source Component internal @@ -28,9 +28,8 @@ */ #include -#include -#include -#include +#include +#include struct bt_value; @@ -64,4 +63,4 @@ BT_HIDDEN enum bt_component_status bt_component_source_validate( struct bt_component *component); -#endif /* BABELTRACE_PLUGIN_SOURCE_INTERNAL_H */ +#endif /* BABELTRACE_COMPONENT_SOURCE_INTERNAL_H */ diff --git a/include/babeltrace/plugin/source.h b/include/babeltrace/component/source.h similarity index 91% rename from include/babeltrace/plugin/source.h rename to include/babeltrace/component/source.h index 8b71ed26..fdb3eb26 100644 --- a/include/babeltrace/plugin/source.h +++ b/include/babeltrace/component/source.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_SOURCE_H -#define BABELTRACE_PLUGIN_SOURCE_H +#ifndef BABELTRACE_COMPONENT_SOURCE_H +#define BABELTRACE_COMPONENT_SOURCE_H /* * BabelTrace - Source Plug-in Interface @@ -28,7 +28,7 @@ */ #include -#include +#include #ifdef __cplusplus extern "C" { @@ -51,4 +51,4 @@ struct bt_notification_iterator *bt_component_source_create_iterator( } #endif -#endif /* BABELTRACE_PLUGIN_SOURCE_H */ +#endif /* BABELTRACE_COMPONENT_SOURCE_H */ diff --git a/include/babeltrace/ctf-ir/trace.h b/include/babeltrace/ctf-ir/trace.h index a95e206e..b722d922 100644 --- a/include/babeltrace/ctf-ir/trace.h +++ b/include/babeltrace/ctf-ir/trace.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #ifdef __cplusplus diff --git a/include/babeltrace/plugin/component-factory-internal.h b/include/babeltrace/plugin/component-factory-internal.h deleted file mode 100644 index 10a2b787..00000000 --- a/include/babeltrace/plugin/component-factory-internal.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_FACTORY_INTERNAL_H -#define BABELTRACE_PLUGIN_COMPONENT_FACTORY_INTERNAL_H - -/* - * BabelTrace - Component Factory Internal - * - * 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 - -#define SECTION_BEGIN(_name) &__start_##_name -#define SECTION_END(_name) &__stop_##_name - -#define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name)) - -#define DECLARE_SECTION(_type, _name) \ - extern _type const __start_##_name __attribute((weak)); \ - extern _type const __stop_##_name __attribute((weak)) - -#define DECLARE_PLUG_IN_SECTIONS \ - DECLARE_SECTION(bt_plugin_register_func, __plugin_register_funcs); \ - DECLARE_SECTION(const char *, __plugin_names); \ - DECLARE_SECTION(const char *, __plugin_authors); \ - DECLARE_SECTION(const char *, __plugin_licenses); \ - DECLARE_SECTION(const char *, __plugin_descriptions) - -#define PRINT_SECTION(_printer, _name) \ - _printer("Section " #_name " [%p - %p], (%zu elements)\n", \ - SECTION_BEGIN(_name), SECTION_END(_name), SECTION_ELEMENT_COUNT(_name)) - -#define PRINT_PLUG_IN_SECTIONS(_printer) \ - PRINT_SECTION(_printer, __plugin_register_funcs); \ - PRINT_SECTION(_printer, __plugin_names); \ - PRINT_SECTION(_printer, __plugin_authors); \ - PRINT_SECTION(_printer, __plugin_licenses); \ - PRINT_SECTION(_printer, __plugin_descriptions) - -struct bt_component_factory { - struct bt_object base; - /** Array of pointers to struct bt_component_class */ - GPtrArray *component_classes; - /* Plug-in currently registering component classes. Weak ref. */ - struct bt_plugin *current_plugin; -}; - -#endif /* BABELTRACE_PLUGIN_COMPONENT_FACTORY_INTERNAL_H */ diff --git a/include/babeltrace/plugin/component-factory.h b/include/babeltrace/plugin/component-factory.h deleted file mode 100644 index 95c5767b..00000000 --- a/include/babeltrace/plugin/component-factory.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_FACTORY_H -#define BABELTRACE_PLUGIN_COMPONENT_FACTORY_H - -/* - * Babeltrace - Component Factory Class Interface. - * - * Copyright 2015 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 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Status code. Errors are always negative. - */ -enum bt_component_factory_status { - /** General error. */ - BT_COMPONENT_FACTORY_STATUS_ERROR = -128, - - /** Duplicate component class being registered. */ - BT_COMPONENT_FACTORY_STATUS_DUPLICATE = -7, - - /** Invalid plugin. */ - BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN = -6, - - /** Invalid arguments. */ - BT_COMPONENT_FACTORY_STATUS_INVAL = -5, - - /** Memory allocation failure. */ - BT_COMPONENT_FACTORY_STATUS_NOMEM = -4, - - /** I/O error. */ - BT_COMPONENT_FACTORY_STATUS_IO = -3, - - /** No such file or directory. */ - BT_COMPONENT_FACTORY_STATUS_NOENT = -2, - - /** Operation not permitted. */ - BT_COMPONENT_FACTORY_STATUS_PERM = -1, - - /** No error, okay. */ - BT_COMPONENT_FACTORY_STATUS_OK = 0, -}; - -struct bt_component_factory; - -/** - * Create a component factory. - * - * @returns An instance of component factory - */ -extern struct bt_component_factory *bt_component_factory_create(void); - -/** - * Get the number of component classes registered to the component factory. - * - * @param factory A component factory instance - * @returns The number of component classes registered to the - * component factory, or a negative value on error. - */ -extern int bt_component_factory_get_component_class_count( - struct bt_component_factory *factory); - -/** - * Get component class at index. - * - * @param factory A component factory instance - * @param index Index of the component class to return - * @returns A component class instance, NULL on error. - */ -extern struct bt_component_class *bt_component_factory_get_component_class_index( - struct bt_component_factory *factory, int index); - -/** - * Look-up component class. - * - * @param factory A component factory instance - * @param plugin_name Name of the plug-in which registered the - * component class - * @param type Component type (@see #bt_component_type) - * @param component_name Component name - * @returns A component class instance, NULL on error. - */ -extern struct bt_component_class *bt_component_factory_get_component_class( - struct bt_component_factory *factory, - const char *plugin_name, enum bt_component_type type, - const char *component_name); - -/** - * Load and register Babeltrace plugins under a given path. - * - * Path will be traversed if it is a directory, otherwise only the provided file - * will be loaded. - * - * @param factory A component factory instance - * @param path A path to a file or directory - * @returns One of #bt_component_factory_status values - */ -extern enum bt_component_factory_status bt_component_factory_load( - struct bt_component_factory *factory, const char *path); - -/** - * Recursively load and register Babeltrace plugins under a given path. - * - * Path will be traversed recursively if it is a directory, otherwise only the - * provided file will be loaded. - * - * @param factory A component factory instance - * @param path A path to a file or directory - * @returns One of #bt_component_factory_status values - */ -extern enum bt_component_factory_status bt_component_factory_load_recursive( - struct bt_component_factory *factory, const char *path); - -/** - * Load and register Babeltrace plugins statically-linked to the executable. - * - * @param factory A component factory instance - * @returns One of #bt_component_factory_status values - */ -extern enum bt_component_factory_status bt_component_factory_load_static( - struct bt_component_factory *factory); - -extern enum bt_component_factory_status -bt_component_factory_register_source_component_class( - struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init); - -extern enum bt_component_factory_status -bt_component_factory_register_sink_component_class( - struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init); - -extern enum bt_component_factory_status -bt_component_factory_register_filter_component_class( - struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_PLUGIN_COMPONENT_FACTORY_H */ diff --git a/include/babeltrace/plugin/component.h b/include/babeltrace/plugin/component.h deleted file mode 100644 index c1ad622e..00000000 --- a/include/babeltrace/plugin/component.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef BABELTRACE_PLUGIN_COMPONENT_H -#define BABELTRACE_PLUGIN_COMPONENT_H - -/* - * BabelTrace - Babeltrace Component Interface - * - * 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 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Status code. Errors are always negative. - */ -enum bt_component_status { - /** No error, okay. */ - BT_COMPONENT_STATUS_OK = 0, - /** No more work to be done by this component. **/ - BT_COMPONENT_STATUS_END = 1, - /** - * Component can't process a notification at this time - * (e.g. would block), try again later. - */ - BT_COMPONENT_STATUS_AGAIN = 2, - /** General error. */ - BT_COMPONENT_STATUS_ERROR = -1, - /** Unsupported component feature. */ - BT_COMPONENT_STATUS_UNSUPPORTED = -2, - /** Invalid arguments. */ - BT_COMPONENT_STATUS_INVALID = -3, - /** Memory allocation failure. */ - BT_COMPONENT_STATUS_NOMEM = -4, -}; - -struct bt_component; -struct bt_value; - -/** - * Create an instance of a component from a component class. - * - * @param component_class Component class of which to create an instance - * @param name Name of the new component instance, optional - * @param params A dictionary of component parameters - * @returns Returns a pointer to a new component instance - */ -extern struct bt_component *bt_component_create( - struct bt_component_class *component_class, const char *name, - struct bt_value *params); - -/** - * Get component's name. - * - * @param component Component instance of which to get the name - * @returns Returns a pointer to the component's name - */ -extern const char *bt_component_get_name(struct bt_component *component); - -/** - * Set component's name. - * - * @param component Component instance of which to set the name - * @param name New component name (will be copied) - * @returns One of #bt_component_status values - */ -extern enum bt_component_status bt_component_set_name( - struct bt_component *component, const char *name); - -/** - * Get component's class. - * - * @param component Component instance of which to get the class - * @returns The component's class - */ -extern struct bt_component_class *bt_component_get_class( - struct bt_component *component); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_PLUGIN_COMPONENT_H */ diff --git a/include/babeltrace/plugin/plugin-dev.h b/include/babeltrace/plugin/plugin-dev.h new file mode 100644 index 00000000..ffa39bb5 --- /dev/null +++ b/include/babeltrace/plugin/plugin-dev.h @@ -0,0 +1,123 @@ +#ifndef BABELTRACE_PLUGIN_PLUGIN_DEV_H +#define BABELTRACE_PLUGIN_PLUGIN_DEV_H + +/* + * BabelTrace - Babeltrace Plug-in System Interface + * + * This is the header that you need to include for the development of + * a Babeltrace plug-in. + * + * Copyright 2015 Jérémie Galarneau + * Copyright 2017 Philippe Proulx + * + * 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 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum bt_plugin_status (*bt_plugin_init_func)( + struct bt_plugin *plugin); + +typedef enum bt_plugin_status (*bt_plugin_exit_func)(void); + +extern enum bt_plugin_status bt_plugin_add_component_class( + struct bt_plugin *plugin, + struct bt_component_class *component_class); + +#ifdef BT_BUILT_IN_PLUGINS +/* + * Statically-linked plug-in symbol types are stored in separate sections and + * which are read using the bt_component_factory interface. + */ +# define BT_PLUGIN_INIT(_x) static bt_plugin_init_func __attribute__((section("__bt_plugin_init_funcs"), used)) __bt_plugin_init = (_x) +# define BT_PLUGIN_EXIT(_x) static bt_plugin_exit_func __attribute__((section("__bt_plugin_exit_funcs"), used)) __bt_plugin_exit = (_x) +# define BT_PLUGIN_NAME(_x) static const char *__bt_plugin_name __attribute__((section("__bt_plugin_names"), used)) = (_x) +# define BT_PLUGIN_AUTHOR(_x) static const char *__bt_plugin_author __attribute__((section("__bt_plugin_authors"), used)) = (_x) +# define BT_PLUGIN_LICENSE(_x) static const char *__bt_plugin_license __attribute__((section("__bt_plugin_licenses"), used)) = (_x) +# define BT_PLUGIN_DESCRIPTION(_x) static const char *__bt_plugin_description __attribute__((section("__bt_plugin_descriptions"), used)) = (_x) +#else /* BT_BUILT_IN_PLUGINS */ +# define BT_PLUGIN_INIT(_x) bt_plugin_init_func __bt_plugin_init = (_x) +# define BT_PLUGIN_EXIT(_x) bt_plugin_exit_func __bt_plugin_exit = (_x) +# define BT_PLUGIN_NAME(_x) const char __bt_plugin_name[] = (_x) +# define BT_PLUGIN_AUTHOR(_x) const char __bt_plugin_author[] = (_x) +# define BT_PLUGIN_LICENSE(_x) const char __bt_plugin_license[] = (_x) +# define BT_PLUGIN_DESCRIPTION(_x) const char __bt_plugin_description[] = (_x) +#endif /* BT_BUILT_IN_PLUGINS */ + +#define BT_PLUGIN_COMPONENT_CLASSES_BEGIN \ + static enum bt_plugin_status __bt_plugin_init_add_component_classes( \ + struct bt_plugin *plugin) \ + { \ + enum bt_plugin_status status = BT_PLUGIN_STATUS_OK; \ + struct bt_component_class *component_class = NULL; + +#define __BT_PLUGIN_COMPONENT_CLASS_ENTRY_EPILOGUE \ + if (!component_class) { \ + status = BT_PLUGIN_STATUS_ERROR; \ + goto end; \ + } \ + status = bt_plugin_add_component_class(plugin, component_class);\ + bt_put(component_class); \ + component_class = NULL; \ + if (status < 0) { \ + goto end; \ + } + +#define BT_PLUGIN_COMPONENT_CLASS_SOURCE_ENTRY(_name, _description, _init_func) \ + component_class = bt_component_class_create( \ + BT_COMPONENT_TYPE_SOURCE, _name, \ + _description, _init_func); \ + __BT_PLUGIN_COMPONENT_CLASS_ENTRY_EPILOGUE + +#define BT_PLUGIN_COMPONENT_CLASS_SINK_ENTRY(_name, _description, _init_func) \ + component_class = bt_component_class_create( \ + BT_COMPONENT_TYPE_SINK, _name, \ + _description, _init_func); \ + __BT_PLUGIN_COMPONENT_CLASS_ENTRY_EPILOGUE + +#define BT_PLUGIN_COMPONENT_CLASS_FILTER_ENTRY(_name, _description, _init_func) \ + component_class = bt_component_class_create( \ + BT_COMPONENT_TYPE_FILTER, _name, \ + _description, _init_func); \ + __BT_PLUGIN_COMPONENT_CLASS_ENTRY_EPILOGUE + +#define BT_PLUGIN_COMPONENT_CLASSES_END \ + end: \ + return status; \ + } \ + \ + static enum bt_plugin_status __bt_plugin_nop_exit(void) { \ + return BT_PLUGIN_STATUS_OK; \ + } \ + \ + BT_PLUGIN_INIT(__bt_plugin_init_add_component_classes); \ + BT_PLUGIN_EXIT(__bt_plugin_nop_exit); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_PLUGIN_PLUGIN_DEV_H */ diff --git a/include/babeltrace/plugin/plugin-internal.h b/include/babeltrace/plugin/plugin-internal.h index b33eb2e3..0509be44 100644 --- a/include/babeltrace/plugin/plugin-internal.h +++ b/include/babeltrace/plugin/plugin-internal.h @@ -1,5 +1,5 @@ -#ifndef BABELTRACE_PLUGIN_INTERNAL_H -#define BABELTRACE_PLUGIN_INTERNAL_H +#ifndef BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H +#define BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H /* * BabelTrace - Plug-in Internal @@ -28,41 +28,35 @@ */ #include -#include -#include -#include +#include #include +#include #include -/** - * Plug-ins are owned by bt_component_factory and the bt_component_class-es - * it provides. This means that its lifetime bound by either the component - * factory's, or the concrete components' lifetime which may be in use and which - * have hold a reference to their bt_component_class which, in turn, have a - * reference to their plugin. - * - * This ensures that a plugin's library is not closed while it is being used - * even if the bt_component_factory, which created its components, is destroyed. - */ -struct bt_plugin { +struct bt_plugin_shared_lib_handle { struct bt_object base; + GString *path; + GModule *module; + bool init_called; + + /* The members below belong to the shared library */ const char *name; const char *author; const char *license; const char *description; - GString *path; - bt_plugin_register_func _register; - GModule *module; + bt_plugin_init_func init; + bt_plugin_exit_func exit; }; -BT_HIDDEN -struct bt_plugin *bt_plugin_create_from_module(GModule *module, const char *path); +struct bt_plugin { + struct bt_object base; + bool frozen; -BT_HIDDEN -struct bt_plugin *bt_plugin_create_from_static(size_t i); + /* Owned by this */ + struct bt_plugin_shared_lib_handle *shared_lib_handle; -BT_HIDDEN -enum bt_component_status bt_plugin_register_component_classes( - struct bt_plugin *plugin, struct bt_component_factory *factory); + /* Array of pointers to bt_component_class (owned by this) */ + GPtrArray *comp_classes; +}; -#endif /* BABELTRACE_PLUGIN_INTERNAL_H */ +#endif /* BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H */ diff --git a/include/babeltrace/plugin/plugin-macros.h b/include/babeltrace/plugin/plugin-macros.h deleted file mode 100644 index f94c3579..00000000 --- a/include/babeltrace/plugin/plugin-macros.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef BABELTRACE_PLUGIN_MACROS_H -#define BABELTRACE_PLUGIN_MACROS_H - -/* - * BabelTrace - Babeltrace Plug-in Helper Macros - * - * Copyright 2015 Jérémie Galarneau - * Copyright 2015 Philippe Proulx - * - * 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 - -#ifndef BT_BUILT_IN_PLUGINS - -#define BT_PLUGIN_REGISTER(_x) bt_plugin_register_func __bt_plugin_register = (_x) -#define BT_PLUGIN_NAME(_x) const char __bt_plugin_name[] = (_x) -#define BT_PLUGIN_AUTHOR(_x) const char __bt_plugin_author[] = (_x) -#define BT_PLUGIN_LICENSE(_x) const char __bt_plugin_license[] = (_x) -#define BT_PLUGIN_DESCRIPTION(_x) const char __bt_plugin_description[] = (_x) - -#else /* BT_BUILT_IN_PLUGINS */ - -/* - * Statically-linked plug-in symbol types are stored in separate sections and - * which are read using the bt_component_factory interface. - */ -#define BT_PLUGIN_REGISTER(_x) static bt_plugin_register_func __attribute__((section("__plugin_register_funcs"), used)) __plugin_register = (_x) -#define BT_PLUGIN_NAME(_x) static const char *__plugin_name __attribute__((section("__plugin_names"), used)) = (_x) -#define BT_PLUGIN_AUTHOR(_x) static const char *__plugin_author __attribute__((section("__plugin_authors"), used)) = (_x) -#define BT_PLUGIN_LICENSE(_x) static const char *__plugin_license __attribute__((section("__plugin_licenses"), used)) = (_x) -#define BT_PLUGIN_DESCRIPTION(_x) static const char *__plugin_description __attribute__((section("__plugin_descriptions"), used)) = (_x) - -#endif /* BT_BUILT_IN_PLUGINS */ - -#define BT_PLUGIN_COMPONENT_CLASSES_BEGIN \ - static enum bt_component_status __bt_plugin_register_component_classes( \ - struct bt_component_factory *factory) \ - { - -#define BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(_name, description, _init) \ - bt_component_factory_register_source_component_class(factory, \ - _name, description, _init); - -#define BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(_name, _description, _init) \ - bt_component_factory_register_sink_component_class(factory, \ - _name, _description, _init); - -#define BT_PLUGIN_FILTER_COMPONENT_CLASS_ENTRY(_name, _description, _init) \ - bt_component_factory_register_filter_component_class(factory, \ - _name, _description, _init); - -#define BT_PLUGIN_COMPONENT_CLASSES_END \ - return BT_COMPONENT_STATUS_OK; \ -} \ - \ - BT_PLUGIN_REGISTER(__bt_plugin_register_component_classes); \ - -#endif /* BABELTRACE_PLUGIN_MACROS_H */ diff --git a/include/babeltrace/plugin/plugin.h b/include/babeltrace/plugin/plugin.h index 8eec84e5..10581984 100644 --- a/include/babeltrace/plugin/plugin.h +++ b/include/babeltrace/plugin/plugin.h @@ -1,10 +1,11 @@ -#ifndef BABELTRACE_PLUGIN_H -#define BABELTRACE_PLUGIN_H +#ifndef BABELTRACE_PLUGIN_PLUGIN_H +#define BABELTRACE_PLUGIN_PLUGIN_H /* * BabelTrace - Babeltrace Plug-in Interface * * Copyright 2016 Jérémie Galarneau + * Copyright 2017 Philippe Proulx * * Author: Jérémie Galarneau * @@ -27,11 +28,35 @@ * SOFTWARE. */ +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif struct bt_plugin; +struct bt_component_class; + +/** + * Status code. Errors are always negative. + */ +enum bt_plugin_status { + /** No error, okay. */ + BT_PLUGIN_STATUS_OK = 0, + /** General error. */ + BT_PLUGIN_STATUS_ERROR = -1, + /** Memory allocation failure. */ + BT_PLUGIN_STATUS_NOMEM = -4, +}; + +extern struct bt_plugin *bt_plugin_create_from_file(const char *path); + +extern struct bt_plugin **bt_plugin_create_all_from_dir(const char *path, + bool recurse); + +extern struct bt_plugin **bt_plugin_create_all_from_static(void); /** * Get the name of a plug-in. @@ -73,8 +98,18 @@ extern const char *bt_plugin_get_description(struct bt_plugin *plugin); */ extern const char *bt_plugin_get_path(struct bt_plugin *plugin); +extern int bt_plugin_get_component_class_count(struct bt_plugin *plugin); + +extern struct bt_component_class *bt_plugin_get_component_class( + struct bt_plugin *plugin, size_t index); + +extern +struct bt_component_class *bt_plugin_get_component_class_by_name_and_type( + struct bt_plugin *plugin, const char *name, + enum bt_component_type type); + #ifdef __cplusplus } #endif -#endif /* BABELTRACE_PLUGIN_H */ +#endif /* BABELTRACE_PLUGIN_PLUGIN_H */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 9e14ea51..71af87a5 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = prio_heap plugin-system . +SUBDIRS = prio_heap plugin component . AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include @@ -31,4 +31,5 @@ libbabeltrace_la_LIBADD = \ prio_heap/libprio_heap.la \ $(top_builddir)/types/libbabeltrace_types.la \ $(top_builddir)/compat/libcompat.la \ - plugin-system/libplugin-system.la + component/libcomponent.la \ + plugin/libplugin.la diff --git a/lib/plugin-system/Makefile.am b/lib/component/Makefile.am similarity index 54% rename from lib/plugin-system/Makefile.am rename to lib/component/Makefile.am index 45f11d88..4af458ca 100644 --- a/lib/plugin-system/Makefile.am +++ b/lib/component/Makefile.am @@ -2,20 +2,18 @@ AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include SUBDIRS = notification -noinst_LTLIBRARIES = libplugin-system.la +noinst_LTLIBRARIES = libcomponent.la # Plug-in system library -libplugin_system_la_SOURCES = \ +libcomponent_la_SOURCES = \ component.c \ component-class.c \ - component-factory.c \ component-graph.c \ - plugin.c \ source.c \ sink.c \ filter.c \ iterator.c \ input.c -libplugin_system_la_LIBADD = \ - notification/libplugin-system-notification.la +libcomponent_la_LIBADD = \ + notification/libcomponent-notification.la diff --git a/lib/plugin-system/component-class.c b/lib/component/component-class.c similarity index 71% rename from lib/plugin-system/component-class.c rename to lib/component/component-class.c index 84e33bde..1e1e8388 100644 --- a/lib/plugin-system/component-class.c +++ b/lib/component/component-class.c @@ -2,7 +2,7 @@ * component-class.c * * Babeltrace Plugin Component Class - * + * * Copyright 2016 Jérémie Galarneau * * Author: Jérémie Galarneau @@ -27,7 +27,7 @@ */ #include -#include +#include #include #include @@ -35,25 +35,37 @@ 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_destroyer_listener *listener = + &g_array_index(class->destroy_listeners, + struct bt_component_class_destroyer_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->destroy_listeners) { + g_array_free(class->destroy_listeners, TRUE); + } - bt_put(class->plugin); g_free(class); } -BT_HIDDEN struct bt_component_class *bt_component_class_create( enum bt_component_type type, const char *name, - const char *description, bt_component_init_cb init, - struct bt_plugin *plugin) + const char *description, bt_component_init_cb init) { struct bt_component_class *class; @@ -71,8 +83,12 @@ struct bt_component_class *bt_component_class_create( BT_PUT(class); goto end; } - - class->plugin = bt_get(plugin); + class->destroy_listeners = g_array_new(FALSE, TRUE, + sizeof(struct bt_component_class_destroyer_listener)); + if (!class->destroy_listeners) { + BT_PUT(class); + goto end; + } end: return class; } @@ -90,15 +106,28 @@ enum bt_component_type bt_component_class_get_type( BT_COMPONENT_TYPE_UNKNOWN; } -struct bt_plugin *bt_component_class_get_plugin( +const char *bt_component_class_get_description( struct bt_component_class *component_class) { - return component_class ? bt_get(component_class->plugin) : - NULL; + return component_class ? component_class->description->str : NULL; } -const char *bt_component_class_get_description( - struct bt_component_class *component_class) +BT_HIDDEN +int bt_component_class_add_destroy_listener(struct bt_component_class *class, + bt_component_class_destroy_listener_func func, void *data) { - return component_class ? component_class->description->str : NULL; + int ret = 0; + struct bt_component_class_destroyer_listener listener; + + if (!class || !func) { + ret = -1; + goto end; + } + + listener.func = func; + listener.data = data; + g_array_append_val(class->destroy_listeners, listener); + +end: + return ret; } diff --git a/lib/plugin-system/component-graph.c b/lib/component/component-graph.c similarity index 97% rename from lib/plugin-system/component-graph.c rename to lib/component/component-graph.c index 551d2d44..c058998d 100644 --- a/lib/plugin-system/component-graph.c +++ b/lib/component/component-graph.c @@ -26,7 +26,7 @@ * SOFTWARE. */ -#include +#include #include static void bt_component_graph_destroy(struct bt_object *obj) diff --git a/lib/plugin-system/component.c b/lib/component/component.c similarity index 95% rename from lib/plugin-system/component.c rename to lib/component/component.c index ec939079..4ad897c7 100644 --- a/lib/plugin-system/component.c +++ b/lib/component/component.c @@ -26,12 +26,12 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/lib/plugin-system/filter.c b/lib/component/filter.c similarity index 96% rename from lib/plugin-system/filter.c rename to lib/component/filter.c index 2ba611d0..2c9fb471 100644 --- a/lib/plugin-system/filter.c +++ b/lib/component/filter.c @@ -28,11 +28,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include enum bt_component_status bt_component_filter_set_iterator_init_cb( struct bt_component *component, diff --git a/lib/plugin-system/input.c b/lib/component/input.c similarity index 97% rename from lib/plugin-system/input.c rename to lib/component/input.c index 26f0d335..663454b4 100644 --- a/lib/plugin-system/input.c +++ b/lib/component/input.c @@ -26,7 +26,7 @@ * SOFTWARE. */ -#include +#include #include BT_HIDDEN diff --git a/lib/plugin-system/iterator.c b/lib/component/iterator.c similarity index 96% rename from lib/plugin-system/iterator.c rename to lib/component/iterator.c index 9976ad5a..188095cf 100644 --- a/lib/plugin-system/iterator.c +++ b/lib/component/iterator.c @@ -28,10 +28,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include static void bt_notification_iterator_destroy(struct bt_object *obj) diff --git a/lib/plugin-system/notification/Makefile.am b/lib/component/notification/Makefile.am similarity index 58% rename from lib/plugin-system/notification/Makefile.am rename to lib/component/notification/Makefile.am index dca588ee..9cf17358 100644 --- a/lib/plugin-system/notification/Makefile.am +++ b/lib/component/notification/Makefile.am @@ -1,9 +1,9 @@ AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -noinst_LTLIBRARIES = libplugin-system-notification.la +noinst_LTLIBRARIES = libcomponent-notification.la # Plug-in system library -libplugin_system_notification_la_SOURCES = \ +libcomponent_notification_la_SOURCES = \ notification.c \ packet.c \ event.c \ diff --git a/lib/plugin-system/notification/event.c b/lib/component/notification/event.c similarity index 97% rename from lib/plugin-system/notification/event.c rename to lib/component/notification/event.c index eb570909..93833a22 100644 --- a/lib/plugin-system/notification/event.c +++ b/lib/component/notification/event.c @@ -25,7 +25,7 @@ */ #include -#include +#include static void bt_notification_event_destroy(struct bt_object *obj) diff --git a/lib/plugin-system/notification/heap.c b/lib/component/notification/heap.c similarity index 98% rename from lib/plugin-system/notification/heap.c rename to lib/component/notification/heap.c index c1226c9d..b58480fc 100644 --- a/lib/plugin-system/notification/heap.c +++ b/lib/component/notification/heap.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #ifdef DEBUG_HEAP static diff --git a/lib/plugin-system/notification/notification.c b/lib/component/notification/notification.c similarity index 96% rename from lib/plugin-system/notification/notification.c rename to lib/component/notification/notification.c index 139caed0..3b2ffb3d 100644 --- a/lib/plugin-system/notification/notification.c +++ b/lib/component/notification/notification.c @@ -24,7 +24,7 @@ * SOFTWARE. */ -#include +#include BT_HIDDEN void bt_notification_init(struct bt_notification *notification, diff --git a/lib/plugin-system/notification/packet.c b/lib/component/notification/packet.c similarity index 98% rename from lib/plugin-system/notification/packet.c rename to lib/component/notification/packet.c index a57310f1..587b8508 100644 --- a/lib/plugin-system/notification/packet.c +++ b/lib/component/notification/packet.c @@ -25,7 +25,7 @@ */ #include -#include +#include static void bt_notification_packet_begin_destroy(struct bt_object *obj) diff --git a/lib/plugin-system/notification/stream.c b/lib/component/notification/stream.c similarity index 97% rename from lib/plugin-system/notification/stream.c rename to lib/component/notification/stream.c index bc0b1b7e..1fd096c6 100644 --- a/lib/plugin-system/notification/stream.c +++ b/lib/component/notification/stream.c @@ -25,7 +25,7 @@ */ #include -#include +#include static void bt_notification_stream_end_destroy(struct bt_object *obj) diff --git a/lib/plugin-system/sink.c b/lib/component/sink.c similarity index 98% rename from lib/plugin-system/sink.c rename to lib/component/sink.c index f49f93cc..509ea89c 100644 --- a/lib/plugin-system/sink.c +++ b/lib/component/sink.c @@ -28,9 +28,9 @@ #include #include -#include -#include -#include +#include +#include +#include BT_HIDDEN enum bt_component_status bt_component_sink_validate( diff --git a/lib/plugin-system/source.c b/lib/component/source.c similarity index 93% rename from lib/plugin-system/source.c rename to lib/component/source.c index 7a19bc55..a0a21d1b 100644 --- a/lib/plugin-system/source.c +++ b/lib/component/source.c @@ -28,10 +28,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include BT_HIDDEN enum bt_component_status bt_component_source_validate( diff --git a/lib/plugin-system/component-factory.c b/lib/plugin-system/component-factory.c deleted file mode 100644 index 14454f50..00000000 --- a/lib/plugin-system/component-factory.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * component-factory.c - * - * Babeltrace Plugin Component Factory - * - * 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 - -#define NATIVE_PLUGIN_SUFFIX ".so" -#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX) -#define LIBTOOL_PLUGIN_SUFFIX ".la" -#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX) -#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \ - sizeof(LIBTOOL_PLUGIN_SUFFIX)) - -DECLARE_PLUG_IN_SECTIONS; - -/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */ -static -struct dirent *alloc_dirent(const char *path) -{ - size_t len; - long name_max; - struct dirent *entry; - - name_max = pathconf(path, _PC_NAME_MAX); - if (name_max == -1) { - name_max = PATH_MAX; - } - len = offsetof(struct dirent, d_name) + name_max + 1; - entry = zmalloc(len); - return entry; -} - -static -enum bt_component_factory_status init_plugin( - struct bt_component_factory *factory, struct bt_plugin *plugin) -{ - enum bt_component_status component_status; - enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; - - BT_MOVE(factory->current_plugin, plugin); - component_status = bt_plugin_register_component_classes( - factory->current_plugin, factory); - BT_PUT(factory->current_plugin); - if (component_status != BT_COMPONENT_STATUS_OK) { - switch (component_status) { - case BT_COMPONENT_STATUS_NOMEM: - ret = BT_COMPONENT_FACTORY_STATUS_NOMEM; - break; - default: - ret = BT_COMPONENT_FACTORY_STATUS_ERROR; - break; - } - } - return ret; -} - -static -enum bt_component_factory_status -bt_component_factory_load_file(struct bt_component_factory *factory, - const char *path) -{ - enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; - size_t path_len; - GModule *module; - struct bt_plugin *plugin; - bool is_libtool_wrapper = false, is_shared_object = false; - - if (!factory || !path) { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } - - path_len = strlen(path); - if (path_len <= PLUGIN_SUFFIX_LEN) { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } - - path_len++; - /* - * Check if the file ends with a known plugin file type suffix (i.e. .so - * or .la on Linux). - */ - is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX, - path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN, - LIBTOOL_PLUGIN_SUFFIX_LEN); - is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX, - path + path_len - NATIVE_PLUGIN_SUFFIX_LEN, - NATIVE_PLUGIN_SUFFIX_LEN); - if (!is_shared_object && !is_libtool_wrapper) { - /* Name indicates that this is not a plugin file. */ - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } - - module = g_module_open(path, 0); - if (!module) { - printf_verbose("Module open error: %s\n", g_module_error()); - ret = BT_COMPONENT_FACTORY_STATUS_ERROR; - goto end; - } - - /* Load plugin and make sure it defines the required entry points. */ - plugin = bt_plugin_create_from_module(module, path); - if (!plugin) { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN; - if (!g_module_close(module)) { - printf_error("Module close error: %s\n", - g_module_error()); - } - goto end; - } - ret = init_plugin(factory, plugin); -end: - return ret; -} - -static -enum bt_component_factory_status -bt_component_factory_load_dir(struct bt_component_factory *factory, - const char *path, bool recurse) -{ - DIR *directory = NULL; - struct dirent *entry = NULL, *result = NULL; - char *file_path = NULL; - size_t path_len = strlen(path); - enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; - - if (path_len >= PATH_MAX) { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } - - entry = alloc_dirent(path); - if (!entry) { - ret = BT_COMPONENT_FACTORY_STATUS_NOMEM; - goto end; - } - - file_path = zmalloc(PATH_MAX); - if (!file_path) { - ret = BT_COMPONENT_FACTORY_STATUS_NOMEM; - goto end; - } - - strncpy(file_path, path, path_len); - /* Append a trailing '/' to the path */ - if (file_path[path_len - 1] != '/') { - file_path[path_len++] = '/'; - } - - directory = opendir(file_path); - if (!directory) { - perror("Failed to open plug-in directory"); - ret = BT_COMPONENT_FACTORY_STATUS_ERROR; - goto end; - } - - /* Recursively walk directory */ - while (!readdir_r(directory, entry, &result) && result) { - struct stat st; - int stat_ret; - size_t file_name_len; - - if (result->d_name[0] == '.') { - /* Skip hidden files, . and .. */ - continue; - } - - file_name_len = strlen(result->d_name); - - if (path_len + file_name_len >= PATH_MAX) { - continue; - } - - strncpy(file_path + path_len, result->d_name, file_name_len); - file_path[path_len + file_name_len] = '\0'; - - stat_ret = stat(file_path, &st); - if (stat_ret < 0) { - /* Continue to next file / directory. */ - printf_perror("Failed to stat() plugin file\n"); - continue; - } - - if (S_ISDIR(st.st_mode) && recurse) { - ret = bt_component_factory_load_dir(factory, - file_path, true); - if (ret != BT_COMPONENT_FACTORY_STATUS_OK) { - goto end; - } - } else if (S_ISREG(st.st_mode)) { - bt_component_factory_load_file(factory, file_path); - } - } -end: - if (directory) { - if (closedir(directory)) { - /* - * We don't want to override the error since there is - * nothing could do. - */ - perror("Failed to close plug-in directory"); - } - } - free(entry); - free(file_path); - return ret; -} - -static -void bt_component_factory_destroy(struct bt_object *obj) -{ - struct bt_component_factory *factory = NULL; - - assert(obj); - factory = container_of(obj, struct bt_component_factory, base); - - if (factory->component_classes) { - g_ptr_array_free(factory->component_classes, TRUE); - } - g_free(factory); -} - -struct bt_component_factory *bt_component_factory_create(void) -{ - struct bt_component_factory *factory; - - factory = g_new0(struct bt_component_factory, 1); - if (!factory) { - goto end; - } - - bt_object_init(factory, bt_component_factory_destroy); - factory->component_classes = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_put); - if (!factory->component_classes) { - goto error; - } -end: - return factory; -error: - BT_PUT(factory); - return factory; -} - -int bt_component_factory_get_component_class_count( - struct bt_component_factory *factory) -{ - return factory ? factory->component_classes->len : -1; -} - -struct bt_component_class *bt_component_factory_get_component_class_index( - struct bt_component_factory *factory, int index) -{ - struct bt_component_class *component_class = NULL; - - if (!factory || index < 0 || index >= factory->component_classes->len) { - goto end; - } - - component_class = bt_get(g_ptr_array_index( - factory->component_classes, index)); -end: - return component_class; -} - -struct bt_component_class *bt_component_factory_get_component_class( - struct bt_component_factory *factory, - const char *plugin_name, enum bt_component_type type, - const char *component_name) -{ - size_t i; - struct bt_component_class *component_class = NULL; - - if (!factory || (!plugin_name && !component_name && - type == BT_COMPONENT_TYPE_UNKNOWN)) { - /* At least one criterion must be provided. */ - goto no_match; - } - - for (i = 0; i < factory->component_classes->len; i++) { - struct bt_plugin *plugin = NULL; - - component_class = g_ptr_array_index(factory->component_classes, - i); - plugin = bt_component_class_get_plugin(component_class); - assert(plugin); - - if (type != BT_COMPONENT_TYPE_UNKNOWN) { - if (type != bt_component_class_get_type( - component_class)) { - bt_put(plugin); - continue; - } - } - - if (plugin_name) { - const char *cur_plugin_name = bt_plugin_get_name( - plugin); - - assert(cur_plugin_name); - if (strcmp(plugin_name, cur_plugin_name)) { - bt_put(plugin); - continue; - } - } - - if (component_name) { - const char *cur_cc_name = bt_component_class_get_name( - component_class); - - assert(cur_cc_name); - if (strcmp(component_name, cur_cc_name)) { - bt_put(plugin); - continue; - } - } - - bt_put(plugin); - /* All criteria met. */ - goto match; - } - -no_match: - return NULL; -match: - return bt_get(component_class); -} - -static -enum bt_component_factory_status _bt_component_factory_load( - struct bt_component_factory *factory, const char *path, - bool recursive) -{ - enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; - - if (!factory || !path) { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } - - if (!g_file_test(path, G_FILE_TEST_EXISTS)) { - ret = BT_COMPONENT_FACTORY_STATUS_NOENT; - goto end; - } - - if (g_file_test(path, G_FILE_TEST_IS_DIR)) { - ret = bt_component_factory_load_dir(factory, path, recursive); - } else if (g_file_test(path, G_FILE_TEST_IS_REGULAR) || - g_file_test(path, G_FILE_TEST_IS_SYMLINK)) { - ret = bt_component_factory_load_file(factory, path); - } else { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } -end: - return ret; -} - -enum bt_component_factory_status bt_component_factory_load_recursive( - struct bt_component_factory *factory, const char *path) -{ - return _bt_component_factory_load(factory, path, true); -} - -enum bt_component_factory_status bt_component_factory_load( - struct bt_component_factory *factory, const char *path) -{ - return _bt_component_factory_load(factory, path, false); -} - -enum bt_component_factory_status bt_component_factory_load_static( - struct bt_component_factory *factory) -{ - size_t count, i; - enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; - - PRINT_PLUG_IN_SECTIONS(printf_verbose); - - count = SECTION_ELEMENT_COUNT(__plugin_register_funcs); - if (SECTION_ELEMENT_COUNT(__plugin_register_funcs) != count || - SECTION_ELEMENT_COUNT(__plugin_names) != count || - SECTION_ELEMENT_COUNT(__plugin_authors) != count || - SECTION_ELEMENT_COUNT(__plugin_licenses) != count || - SECTION_ELEMENT_COUNT(__plugin_descriptions) != count) { - printf_error("Some statically-linked plug-ins do not define all mandatory symbols\n"); - ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN; - goto end; - } - printf_verbose("Detected %zu statically-linked plug-ins\n", count); - - for (i = 0; i < count; i++) { - struct bt_plugin *plugin = bt_plugin_create_from_static(i); - - if (!plugin) { - continue; - } - - (void) init_plugin(factory, plugin); - } -end: - return ret; -} - -static -enum bt_component_factory_status -add_component_class(struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init, - enum bt_component_type type) -{ - struct bt_component_class *component_class; - enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; - - if (!factory || !name || !init) { - ret = BT_COMPONENT_FACTORY_STATUS_INVAL; - goto end; - } - assert(factory->current_plugin); - - /* - * Ensure this component class does not clash with a currently - * registered class. - */ - component_class = bt_component_factory_get_component_class(factory, - bt_plugin_get_name(factory->current_plugin), type, name); - if (component_class) { - struct bt_plugin *plugin = bt_component_class_get_plugin( - component_class); - - printf_verbose("Duplicate component class registration attempted. Component class %s being registered by plugin %s (path: %s) conflicts with one already registered by plugin %s (path: %s)\n", - name, bt_plugin_get_name(factory->current_plugin), - bt_plugin_get_path(factory->current_plugin), - bt_plugin_get_name(plugin), - bt_plugin_get_path(plugin)); - ret = BT_COMPONENT_FACTORY_STATUS_DUPLICATE; - BT_PUT(component_class); - bt_put(plugin); - goto end; - } - - component_class = bt_component_class_create(type, name, description, - init, factory->current_plugin); - g_ptr_array_add(factory->component_classes, component_class); -end: - return ret; -} - -enum bt_component_factory_status -bt_component_factory_register_source_component_class( - struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init) -{ - return add_component_class(factory, name, description, init, - BT_COMPONENT_TYPE_SOURCE); -} - -enum bt_component_factory_status -bt_component_factory_register_sink_component_class( - struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init) -{ - return add_component_class(factory, name, description, init, - BT_COMPONENT_TYPE_SINK); -} - -enum bt_component_factory_status -bt_component_factory_register_filter_component_class( - struct bt_component_factory *factory, const char *name, - const char *description, bt_component_init_cb init) -{ - return add_component_class(factory, name, description, init, - BT_COMPONENT_TYPE_FILTER); -} diff --git a/lib/plugin-system/plugin.c b/lib/plugin-system/plugin.c deleted file mode 100644 index 295140c0..00000000 --- a/lib/plugin-system/plugin.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * plugin.c - * - * Babeltrace Plugin - * - * 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 - -#define PLUGIN_SYMBOL_NAME "__bt_plugin_name" -#define PLUGIN_SYMBOL_AUTHOR "__bt_plugin_author" -#define PLUGIN_SYMBOL_LICENSE "__bt_plugin_license" -#define PLUGIN_SYMBOL_REGISTER "__bt_plugin_register" -#define PLUGIN_SYMBOL_DESCRIPTION "__bt_plugin_description" - -DECLARE_PLUG_IN_SECTIONS; - -static -void bt_plugin_destroy(struct bt_object *obj) -{ - struct bt_plugin *plugin; - - assert(obj); - plugin = container_of(obj, struct bt_plugin, base); - - if (plugin->module) { - if (!g_module_close(plugin->module)) { - printf_error("Module close error: %s\n", - g_module_error()); - } - } - - if (plugin->path) { - g_string_free(plugin->path, TRUE); - } - g_free(plugin); -} - -BT_HIDDEN -struct bt_plugin *bt_plugin_create_from_module(GModule *module, - const char *path) -{ - struct bt_plugin *plugin = NULL; - gpointer symbol = NULL; - - if (!module || !path) { - goto error; - } - - plugin = g_new0(struct bt_plugin, 1); - if (!plugin) { - goto error; - } - - bt_object_init(plugin, bt_plugin_destroy); - plugin->path = g_string_new(path); - if (!plugin->path) { - goto error; - } - - if (!g_module_symbol(module, PLUGIN_SYMBOL_NAME, - (gpointer *) &plugin->name)) { - printf_verbose("Unable to resolve plugin symbol %s from %s\n", - PLUGIN_SYMBOL_NAME, g_module_name(module)); - goto error; - } - - if (!g_module_symbol(module, PLUGIN_SYMBOL_LICENSE, - (gpointer *) &plugin->license)) { - printf_verbose("Unable to resolve plugin symbol %s from %s\n", - PLUGIN_SYMBOL_LICENSE, g_module_name(module)); - goto error; - } - if (!g_module_symbol(module, PLUGIN_SYMBOL_AUTHOR, - (gpointer *) &plugin->author)) { - printf_verbose("Unable to resolve plugin symbol %s from %s\n", - PLUGIN_SYMBOL_AUTHOR, g_module_name(module)); - goto error; - } - if (!g_module_symbol(module, PLUGIN_SYMBOL_DESCRIPTION, - (gpointer *) &plugin->description)) { - printf_verbose("Unable to resolve plugin symbol %s from %s\n", - PLUGIN_SYMBOL_DESCRIPTION, - g_module_name(module)); - goto error; - } - if (!g_module_symbol(module, PLUGIN_SYMBOL_REGISTER, &symbol)) { - printf_verbose("Unable to resolve plugin symbol %s from %s\n", - PLUGIN_SYMBOL_REGISTER, g_module_name(module)); - goto error; - } else { - plugin->_register = *((bt_plugin_register_func *) symbol); - if (!plugin->_register) { - printf_verbose("NULL %s symbol target\n", - PLUGIN_SYMBOL_REGISTER); - goto error; - } - } - - return plugin; -error: - BT_PUT(plugin); - return plugin; -} - -BT_HIDDEN -struct bt_plugin *bt_plugin_create_from_static(size_t i) -{ - struct bt_plugin *plugin = NULL; - - plugin = g_new0(struct bt_plugin, 1); - if (!plugin) { - goto error; - } - - bt_object_init(plugin, bt_plugin_destroy); - plugin->_register = (SECTION_BEGIN(__plugin_register_funcs))[i]; - if (!plugin->_register) { - goto error; - } - plugin->name = (SECTION_BEGIN(__plugin_names))[i]; - plugin->author = (SECTION_BEGIN(__plugin_authors))[i]; - plugin->license = (SECTION_BEGIN(__plugin_licenses))[i]; - plugin->description = (SECTION_BEGIN(__plugin_descriptions))[i]; - return plugin; -error: - BT_PUT(plugin); - return plugin; -} - -BT_HIDDEN -enum bt_component_status bt_plugin_register_component_classes( - struct bt_plugin *plugin, struct bt_component_factory *factory) -{ - assert(plugin && factory); - return plugin->_register(factory); -} - -const char *bt_plugin_get_name(struct bt_plugin *plugin) -{ - return plugin ? plugin->name : NULL; -} - -const char *bt_plugin_get_author(struct bt_plugin *plugin) -{ - return plugin ? plugin->author : NULL; -} - -const char *bt_plugin_get_license(struct bt_plugin *plugin) -{ - return plugin ? plugin->license : NULL; -} - -const char *bt_plugin_get_path(struct bt_plugin *plugin) -{ - return (plugin && plugin->path) ? plugin->path->str : NULL; -} - -const char *bt_plugin_get_description(struct bt_plugin *plugin) -{ - return plugin ? plugin->description : NULL; -} diff --git a/lib/plugin/Makefile.am b/lib/plugin/Makefile.am new file mode 100644 index 00000000..6a5e4a11 --- /dev/null +++ b/lib/plugin/Makefile.am @@ -0,0 +1,7 @@ +AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include + +noinst_LTLIBRARIES = libplugin.la + +# Plug-in system library +libplugin_la_SOURCES = \ + plugin.c diff --git a/lib/plugin/plugin.c b/lib/plugin/plugin.c new file mode 100644 index 00000000..e1e0387b --- /dev/null +++ b/lib/plugin/plugin.c @@ -0,0 +1,807 @@ +/* + * plugin.c + * + * Babeltrace Plugin + * + * Copyright 2016 Jérémie Galarneau + * Copyright 2017 Philippe Proulx + * + * 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 + +#define PLUGIN_SYMBOL_NAME "__bt_plugin_name" +#define PLUGIN_SYMBOL_AUTHOR "__bt_plugin_author" +#define PLUGIN_SYMBOL_LICENSE "__bt_plugin_license" +#define PLUGIN_SYMBOL_INIT "__bt_plugin_init" +#define PLUGIN_SYMBOL_EXIT "__bt_plugin_exit" +#define PLUGIN_SYMBOL_DESCRIPTION "__bt_plugin_description" +#define NATIVE_PLUGIN_SUFFIX ".so" +#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX) +#define LIBTOOL_PLUGIN_SUFFIX ".la" +#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX) + +#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \ + sizeof(LIBTOOL_PLUGIN_SUFFIX)) + +#define SECTION_BEGIN(_name) &__start_##_name +#define SECTION_END(_name) &__stop_##_name +#define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name)) + +#define DECLARE_SECTION(_type, _name) \ + extern _type const __start_##_name __attribute((weak)); \ + extern _type const __stop_##_name __attribute((weak)) + +DECLARE_SECTION(bt_plugin_init_func, __bt_plugin_init_funcs); +DECLARE_SECTION(bt_plugin_exit_func, __bt_plugin_exit_funcs); +DECLARE_SECTION(const char *, __bt_plugin_names); +DECLARE_SECTION(const char *, __bt_plugin_authors); +DECLARE_SECTION(const char *, __bt_plugin_licenses); +DECLARE_SECTION(const char *, __bt_plugin_descriptions); + +#define PRINT_SECTION(_printer, _name) \ + do { \ + _printer("Section " #_name " [%p - %p], (%zu elements)\n", \ + SECTION_BEGIN(_name), SECTION_END(_name), \ + SECTION_ELEMENT_COUNT(_name)); \ + } while (0) + +#define PRINT_PLUG_IN_SECTIONS(_printer) \ + do { \ + PRINT_SECTION(_printer, __bt_plugin_init_funcs); \ + PRINT_SECTION(_printer, __bt_plugin_exit_funcs); \ + PRINT_SECTION(_printer, __bt_plugin_names); \ + PRINT_SECTION(_printer, __bt_plugin_authors); \ + PRINT_SECTION(_printer, __bt_plugin_licenses); \ + PRINT_SECTION(_printer, __bt_plugin_descriptions); \ + } while (0) + +/* + * This hash table, global to the library, maps component class pointers + * to shared library handles. + * + * The keys (component classes) are NOT owned by this hash table, whereas + * the values (shared library handles) are owned by this hash table. + * + * The keys are the component classes created with + * bt_plugin_add_component_class(). They keep the shared library handle + * object created by their plugin alive so that the plugin's code is + * not discarded when it could still be in use by living components + * created from those component classes: + * + * [component] --ref-> [component class] --through this HT-> [shlib handle] + * + * This hash table exists for two reasons: + * + * 1. To allow this application: + * + * my_plugin = bt_plugin_create_from_file("/path/to/my-plugin.so"); + * // instantiate components from the plugin's component classes + * BT_PUT(my_plugin); + * // user code of instantiated components still exists + * + * 2. To decouple the plugin subsystem from the component subsystem: + * while plugins objects need to know component class objects, the + * opposite is not necessary, thus it makes no sense for a component + * class to keep a reference to the plugin object from which it was + * created. + * + * An entry is removed from this HT when a component class is destroyed + * thanks to a custom destroy listener. When the entry is removed, the + * GLib function calls the value destroy notifier of the HT, which is + * bt_put(). This decreases the reference count of the mapped shared + * library handle. Assuming the original plugin object which contained + * some component classes is put first, when the last component class is + * removed from this HT, the shared library handle object's reference + * count falls to zero and the shared library is finally closed. + */ +static +GHashTable *comp_classes_to_shlib_handles; + +__attribute__((constructor)) static +void init_comp_classes_to_shlib_handles(void) { + comp_classes_to_shlib_handles = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, bt_put); + assert(comp_classes_to_shlib_handles); +} + +__attribute__((destructor)) static +void fini_comp_classes_to_shlib_handles(void) { + if (comp_classes_to_shlib_handles) { + g_hash_table_destroy(comp_classes_to_shlib_handles); + } +} + +static +void bt_plugin_shared_lib_handle_destroy(struct bt_object *obj) +{ + struct bt_plugin_shared_lib_handle *shared_lib_handle; + + assert(obj); + shared_lib_handle = container_of(obj, + struct bt_plugin_shared_lib_handle, base); + + if (shared_lib_handle->init_called && shared_lib_handle->exit) { + enum bt_plugin_status status = shared_lib_handle->exit(); + + if (status < 0) { + printf_verbose("Plugin `%s` exited with error %d\n", + shared_lib_handle->name, status); + } + } + + if (shared_lib_handle->module) { + if (!g_module_close(shared_lib_handle->module)) { + printf_error("Module close error: %s\n", + g_module_error()); + } + } + + if (shared_lib_handle->path) { + g_string_free(shared_lib_handle->path, TRUE); + } + + g_free(shared_lib_handle); +} + +static +struct bt_plugin_shared_lib_handle *bt_plugin_shared_lib_handle_create( + const char *path) +{ + struct bt_plugin_shared_lib_handle *shared_lib_handle = NULL; + gpointer symbol = NULL; + + shared_lib_handle = g_new0(struct bt_plugin_shared_lib_handle, 1); + if (!shared_lib_handle) { + goto error; + } + + bt_object_init(shared_lib_handle, bt_plugin_shared_lib_handle_destroy); + + if (!path) { + goto end; + } + + shared_lib_handle->path = g_string_new(path); + if (!shared_lib_handle->path) { + goto error; + } + + shared_lib_handle->module = g_module_open(path, 0); + if (!shared_lib_handle->module) { + printf_verbose("Module open error: %s\n", g_module_error()); + goto error; + } + + if (!g_module_symbol(shared_lib_handle->module, PLUGIN_SYMBOL_NAME, + (gpointer *) &shared_lib_handle->name)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + PLUGIN_SYMBOL_NAME, + g_module_name(shared_lib_handle->module)); + goto error; + } + + if (!g_module_symbol(shared_lib_handle->module, PLUGIN_SYMBOL_LICENSE, + (gpointer *) &shared_lib_handle->license)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + PLUGIN_SYMBOL_LICENSE, + g_module_name(shared_lib_handle->module)); + goto error; + } + + if (!g_module_symbol(shared_lib_handle->module, PLUGIN_SYMBOL_AUTHOR, + (gpointer *) &shared_lib_handle->author)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + PLUGIN_SYMBOL_AUTHOR, + g_module_name(shared_lib_handle->module)); + goto error; + } + + if (!g_module_symbol(shared_lib_handle->module, PLUGIN_SYMBOL_DESCRIPTION, + (gpointer *) &shared_lib_handle->description)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + PLUGIN_SYMBOL_DESCRIPTION, + g_module_name(shared_lib_handle->module)); + goto error; + } + + if (!g_module_symbol(shared_lib_handle->module, PLUGIN_SYMBOL_INIT, + &symbol)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + PLUGIN_SYMBOL_INIT, + g_module_name(shared_lib_handle->module)); + goto error; + } else { + shared_lib_handle->init = *((bt_plugin_init_func *) symbol); + if (!shared_lib_handle->init) { + printf_verbose("NULL %s symbol target\n", + PLUGIN_SYMBOL_INIT); + goto error; + } + } + + if (!g_module_symbol(shared_lib_handle->module, PLUGIN_SYMBOL_EXIT, + &symbol)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + PLUGIN_SYMBOL_EXIT, + g_module_name(shared_lib_handle->module)); + goto error; + } else { + shared_lib_handle->exit = *((bt_plugin_exit_func *) symbol); + if (!shared_lib_handle->exit) { + printf_verbose("NULL %s symbol target\n", + PLUGIN_SYMBOL_EXIT); + goto error; + } + } + + goto end; + +error: + BT_PUT(shared_lib_handle); + +end: + return shared_lib_handle; +} + +static +void bt_plugin_destroy(struct bt_object *obj) +{ + struct bt_plugin *plugin; + + assert(obj); + plugin = container_of(obj, struct bt_plugin, base); + + BT_PUT(plugin->shared_lib_handle); + + if (plugin->comp_classes) { + g_ptr_array_free(plugin->comp_classes, TRUE); + } + + g_free(plugin); +} + +static +enum bt_plugin_status init_plugin(struct bt_plugin *plugin) +{ + enum bt_plugin_status status = BT_PLUGIN_STATUS_OK; + + if (plugin->shared_lib_handle->init) { + status = plugin->shared_lib_handle->init(plugin); + + if (status < 0) { + printf_verbose("Plugin `%s` initialization error: %d\n", + plugin->shared_lib_handle->name, status); + goto end; + } + } + + plugin->shared_lib_handle->init_called = true; + + /* + * The initialization function should have added the component + * classes at this point. We freeze the plugin so that it's not + * possible to add component classes to this plugin object after + * this stage (plugin object becomes immutable). + */ + plugin->frozen = true; + +end: + return status; +} + +struct bt_plugin *bt_plugin_create_from_file(const char *path) +{ + size_t path_len; + struct bt_plugin *plugin = NULL; + bool is_libtool_wrapper = false, is_shared_object = false; + + if (!path) { + goto error; + } + + path_len = strlen(path); + if (path_len <= PLUGIN_SUFFIX_LEN) { + goto error; + } + + path_len++; + /* + * Check if the file ends with a known plugin file type suffix (i.e. .so + * or .la on Linux). + */ + is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX, + path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN, + LIBTOOL_PLUGIN_SUFFIX_LEN); + is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX, + path + path_len - NATIVE_PLUGIN_SUFFIX_LEN, + NATIVE_PLUGIN_SUFFIX_LEN); + if (!is_shared_object && !is_libtool_wrapper) { + /* Name indicates that this is not a plugin file. */ + goto error; + } + + plugin = g_new0(struct bt_plugin, 1); + if (!plugin) { + goto error; + } + + bt_object_init(plugin, bt_plugin_destroy); + + /* Create shared lib handle */ + plugin->shared_lib_handle = bt_plugin_shared_lib_handle_create(path); + if (!plugin->shared_lib_handle) { + printf_verbose("Failed to create a shared library handle (path `%s`)\n", + path); + goto error; + } + + /* Create empty array of component classes */ + plugin->comp_classes = + g_ptr_array_new_with_free_func((GDestroyNotify) bt_put); + if (!plugin->comp_classes) { + goto error; + } + + /* Initialize plugin */ + if (init_plugin(plugin) < 0) { + goto error; + } + + goto end; + +error: + BT_PUT(plugin); + +end: + return plugin; +} + +/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */ +static +struct dirent *alloc_dirent(const char *path) +{ + size_t len; + long name_max; + struct dirent *entry; + + name_max = pathconf(path, _PC_NAME_MAX); + if (name_max == -1) { + name_max = PATH_MAX; + } + len = offsetof(struct dirent, d_name) + name_max + 1; + entry = zmalloc(len); + return entry; +} + +static +enum bt_plugin_status bt_plugin_create_append_all_from_dir( + GPtrArray *plugins, const char *path, bool recurse) +{ + DIR *directory = NULL; + struct dirent *entry = NULL, *result = NULL; + char *file_path = NULL; + size_t path_len = strlen(path); + enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK; + + if (path_len >= PATH_MAX) { + ret = BT_PLUGIN_STATUS_ERROR; + goto end; + } + + entry = alloc_dirent(path); + if (!entry) { + ret = BT_PLUGIN_STATUS_ERROR; + goto end; + } + + file_path = zmalloc(PATH_MAX); + if (!file_path) { + ret = BT_PLUGIN_STATUS_NOMEM; + goto end; + } + + strncpy(file_path, path, path_len); + /* Append a trailing '/' to the path */ + if (file_path[path_len - 1] != '/') { + file_path[path_len++] = '/'; + } + + directory = opendir(file_path); + if (!directory) { + perror("Failed to open plug-in directory"); + ret = BT_PLUGIN_STATUS_ERROR; + goto end; + } + + /* Recursively walk directory */ + while (!readdir_r(directory, entry, &result) && result) { + struct stat st; + int stat_ret; + size_t file_name_len; + + if (result->d_name[0] == '.') { + /* Skip hidden files, . and .. */ + continue; + } + + file_name_len = strlen(result->d_name); + + if (path_len + file_name_len >= PATH_MAX) { + continue; + } + + strncpy(file_path + path_len, result->d_name, file_name_len); + file_path[path_len + file_name_len] = '\0'; + + stat_ret = stat(file_path, &st); + if (stat_ret < 0) { + /* Continue to next file / directory. */ + printf_perror("Failed to stat() plugin file\n"); + continue; + } + + if (S_ISDIR(st.st_mode) && recurse) { + ret = bt_plugin_create_append_all_from_dir(plugins, + file_path, true); + if (ret < 0) { + goto end; + } + } else if (S_ISREG(st.st_mode)) { + struct bt_plugin *plugin = bt_plugin_create_from_file(file_path); + + if (plugin) { + /* Transfer ownership to array */ + g_ptr_array_add(plugins, plugin); + } + } + } +end: + if (directory) { + if (closedir(directory)) { + /* + * We don't want to override the error since there is + * nothing could do. + */ + perror("Failed to close plug-in directory"); + } + } + free(entry); + free(file_path); + return ret; +} + +struct bt_plugin **bt_plugin_create_all_from_dir(const char *path, + bool recurse) +{ + GPtrArray *plugins_array = NULL; + struct bt_plugin **plugins = NULL; + enum bt_plugin_status status; + + if (!path) { + goto error; + } + + plugins_array = g_ptr_array_new(); + if (!plugins_array) { + goto error; + } + + /* Append found plugins to array */ + status = bt_plugin_create_append_all_from_dir(plugins_array, path, + recurse); + if (status < 0) { + goto error; + } + + /* Add sentinel to array */ + g_ptr_array_add(plugins_array, NULL); + plugins = (struct bt_plugin **) plugins_array->pdata; + goto end; + +error: + if (plugins_array) { + g_ptr_array_free(plugins_array, TRUE); + plugins_array = NULL; + } + +end: + if (plugins_array) { + g_ptr_array_free(plugins_array, FALSE); + } + + return plugins; +} + +static +struct bt_plugin *bt_plugin_create_from_static_at_index(size_t i) +{ + struct bt_plugin *plugin = NULL; + + plugin = g_new0(struct bt_plugin, 1); + if (!plugin) { + goto error; + } + + bt_object_init(plugin, bt_plugin_destroy); + + /* Create shared lib handle */ + plugin->shared_lib_handle = bt_plugin_shared_lib_handle_create(NULL); + if (!plugin->shared_lib_handle) { + goto error; + } + + /* Fill shared lib handle */ + plugin->shared_lib_handle->init = + (SECTION_BEGIN(__bt_plugin_init_funcs))[i]; + if (!plugin->shared_lib_handle->init) { + goto error; + } + + plugin->shared_lib_handle->exit = + (SECTION_BEGIN(__bt_plugin_exit_funcs))[i]; + if (!plugin->shared_lib_handle->exit) { + goto error; + } + + plugin->shared_lib_handle->name = (SECTION_BEGIN(__bt_plugin_names))[i]; + plugin->shared_lib_handle->author = + (SECTION_BEGIN(__bt_plugin_authors))[i]; + plugin->shared_lib_handle->license = + (SECTION_BEGIN(__bt_plugin_licenses))[i]; + plugin->shared_lib_handle->description = + (SECTION_BEGIN(__bt_plugin_descriptions))[i]; + + /* Create empty array of component classes */ + plugin->comp_classes = + g_ptr_array_new_with_free_func((GDestroyNotify) bt_put); + if (!plugin->comp_classes) { + goto error; + } + + /* Initialize plugin */ + if (init_plugin(plugin) < 0) { + goto error; + } + + goto end; + +error: + BT_PUT(plugin); + +end: + return plugin; +} + +struct bt_plugin **bt_plugin_create_all_from_static(void) +{ + size_t count, i; + struct bt_plugin **plugins = NULL; + + PRINT_PLUG_IN_SECTIONS(printf_verbose); + count = SECTION_ELEMENT_COUNT(__bt_plugin_init_funcs); + if (SECTION_ELEMENT_COUNT(__bt_plugin_exit_funcs) != count || + SECTION_ELEMENT_COUNT(__bt_plugin_names) != count || + SECTION_ELEMENT_COUNT(__bt_plugin_authors) != count || + SECTION_ELEMENT_COUNT(__bt_plugin_licenses) != count || + SECTION_ELEMENT_COUNT(__bt_plugin_descriptions) != count) { + printf_error("Some statically-linked plug-ins do not define all the mandatory symbols\n"); + goto error; + } + + printf_verbose("Detected %zu statically-linked plug-ins\n", count); + plugins = g_new0(struct bt_plugin *, count + 1); + if (!plugins) { + goto error; + } + + for (i = 0; i < count; i++) { + struct bt_plugin *plugin = + bt_plugin_create_from_static_at_index(i); + + if (!plugin) { + printf_error("Cannot create statically-linked plug-in at index %zu\n", + i); + goto error; + } + + /* Transfer ownership to the array */ + plugins[i] = plugin; + } + + goto end; + +error: + g_free(plugins); + +end: + return plugins; +} + +const char *bt_plugin_get_name(struct bt_plugin *plugin) +{ + return plugin ? plugin->shared_lib_handle->name : NULL; +} + +const char *bt_plugin_get_author(struct bt_plugin *plugin) +{ + return plugin ? plugin->shared_lib_handle->author : NULL; +} + +const char *bt_plugin_get_license(struct bt_plugin *plugin) +{ + return plugin ? plugin->shared_lib_handle->license : NULL; +} + +const char *bt_plugin_get_path(struct bt_plugin *plugin) +{ + return (plugin && plugin->shared_lib_handle->path) ? + plugin->shared_lib_handle->path->str : NULL; +} + +const char *bt_plugin_get_description(struct bt_plugin *plugin) +{ + return plugin ? plugin->shared_lib_handle->description : NULL; +} + +int bt_plugin_get_component_class_count(struct bt_plugin *plugin) +{ + return plugin ? plugin->comp_classes->len : -1; +} + +struct bt_component_class *bt_plugin_get_component_class( + struct bt_plugin *plugin, size_t index) +{ + struct bt_component_class *comp_class = NULL; + + if (!plugin || index >= plugin->comp_classes->len) { + goto error; + } + + comp_class = g_ptr_array_index(plugin->comp_classes, index); + bt_get(comp_class); + goto end; + +error: + BT_PUT(comp_class); + +end: + return comp_class; +} + +struct bt_component_class *bt_plugin_get_component_class_by_name_and_type( + struct bt_plugin *plugin, const char *name, + enum bt_component_type type) +{ + struct bt_component_class *comp_class = NULL; + size_t i; + + if (!plugin || !name) { + goto error; + } + + for (i = 0; i < plugin->comp_classes->len; i++) { + struct bt_component_class *comp_class_candidate = + g_ptr_array_index(plugin->comp_classes, i); + const char *comp_class_cand_name = + bt_component_class_get_name(comp_class_candidate); + enum bt_component_type comp_class_cand_type = + bt_component_class_get_type(comp_class_candidate); + + assert(comp_class_cand_name); + assert(comp_class_cand_type >= 0); + + if (strcmp(name, comp_class_cand_name) == 0 && + comp_class_cand_type == type) { + comp_class = bt_get(comp_class_candidate); + break; + } + } + + goto end; + +error: + BT_PUT(comp_class); + +end: + return comp_class; +} + +static +void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class, + void *data) +{ + gboolean exists = g_hash_table_remove(comp_classes_to_shlib_handles, + comp_class); + assert(exists); +} + +enum bt_plugin_status bt_plugin_add_component_class( + struct bt_plugin *plugin, struct bt_component_class *comp_class) +{ + enum bt_plugin_status status = BT_PLUGIN_STATUS_OK; + struct bt_component_class *comp_class_dup = NULL; + int ret; + int comp_class_index = -1; + + if (!plugin || !comp_class || plugin->frozen) { + goto error; + } + + /* Check for duplicate */ + comp_class_dup = bt_plugin_get_component_class_by_name_and_type(plugin, + bt_component_class_get_name(comp_class), + bt_component_class_get_type(comp_class)); + if (comp_class_dup) { + printf_verbose("Plugin `%s`: adding component class with existing name `%s` and type %d\n", + plugin->shared_lib_handle->name, + bt_component_class_get_name(comp_class), + bt_component_class_get_type(comp_class)); + goto error; + } + + /* Add new component class */ + comp_class_index = plugin->comp_classes->len; + g_ptr_array_add(plugin->comp_classes, bt_get(comp_class)); + + /* Map component class pointer to shared lib handle in global HT */ + g_hash_table_insert(comp_classes_to_shlib_handles, comp_class, + bt_get(plugin->shared_lib_handle)); + + /* Add our custom destroy listener */ + ret = bt_component_class_add_destroy_listener(comp_class, + plugin_comp_class_destroy_listener, NULL); + if (ret) { + goto error; + } + + goto end; + +error: + /* Remove entry from global hash table (if exists) */ + g_hash_table_remove(comp_classes_to_shlib_handles, + comp_class); + + /* Remove entry from plugin's component classes (if added) */ + if (comp_class_index >= 0) { + g_ptr_array_remove_index(plugin->comp_classes, + comp_class_index); + } + + status = BT_PLUGIN_STATUS_ERROR; + +end: + bt_put(comp_class_dup); + return status; +} diff --git a/plugins/ctf/common/notif-iter/notif-iter.c b/plugins/ctf/common/notif-iter/notif-iter.c index 823a753f..44663f7b 100644 --- a/plugins/ctf/common/notif-iter/notif-iter.c +++ b/plugins/ctf/common/notif-iter/notif-iter.c @@ -38,9 +38,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/plugins/ctf/fs/data-stream.c b/plugins/ctf/fs/data-stream.c index a71cc007..905e26a9 100644 --- a/plugins/ctf/fs/data-stream.c +++ b/plugins/ctf/fs/data-stream.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "file.h" #include "metadata.h" #include "../common/notif-iter/notif-iter.h" diff --git a/plugins/ctf/fs/fs.c b/plugins/ctf/fs/fs.c index ea9bf562..f08f06a5 100644 --- a/plugins/ctf/fs/fs.c +++ b/plugins/ctf/fs/fs.c @@ -26,14 +26,13 @@ * SOFTWARE. */ -#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include diff --git a/plugins/ctf/fs/fs.h b/plugins/ctf/fs/fs.h index 80bd6d04..35fbee90 100644 --- a/plugins/ctf/fs/fs.h +++ b/plugins/ctf/fs/fs.h @@ -29,7 +29,7 @@ */ #include -#include +#include #include "data-stream.h" #define CTF_FS_COMPONENT_NAME "fs" diff --git a/plugins/ctf/lttng-live/lttng-live-internal.h b/plugins/ctf/lttng-live/lttng-live-internal.h index 0cc5afb9..3f5b9172 100644 --- a/plugins/ctf/lttng-live/lttng-live-internal.h +++ b/plugins/ctf/lttng-live/lttng-live-internal.h @@ -28,7 +28,7 @@ */ #include -#include +#include #define LTTNG_LIVE_COMPONENT_NAME "lttng-live" #define LTTNG_LIVE_COMPONENT_DESCRIPTION "Component implementing an LTTng-live client." diff --git a/plugins/ctf/lttng-live/lttng-live.c b/plugins/ctf/lttng-live/lttng-live.c index 4f28f484..5cef2aa9 100644 --- a/plugins/ctf/lttng-live/lttng-live.c +++ b/plugins/ctf/lttng-live/lttng-live.c @@ -27,7 +27,7 @@ */ #include "lttng-live-internal.h" -#include +#include BT_HIDDEN enum bt_component_status lttng_live_init(struct bt_component *component, diff --git a/plugins/ctf/plugin.c b/plugins/ctf/plugin.c index 0aac9032..36730869 100644 --- a/plugins/ctf/plugin.c +++ b/plugins/ctf/plugin.c @@ -26,7 +26,7 @@ * SOFTWARE. */ -#include +#include #include "fs/fs.h" #include "lttng-live/lttng-live-internal.h" @@ -38,8 +38,8 @@ BT_PLUGIN_LICENSE("MIT"); /* Declare component classes implemented by this plug-in. */ BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(CTF_FS_COMPONENT_NAME, +BT_PLUGIN_COMPONENT_CLASS_SOURCE_ENTRY(CTF_FS_COMPONENT_NAME, CTF_FS_COMPONENT_DESCRIPTION, ctf_fs_init) -BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(LTTNG_LIVE_COMPONENT_NAME, +BT_PLUGIN_COMPONENT_CLASS_SOURCE_ENTRY(LTTNG_LIVE_COMPONENT_NAME, LTTNG_LIVE_COMPONENT_DESCRIPTION, lttng_live_init) BT_PLUGIN_COMPONENT_CLASSES_END diff --git a/plugins/muxer/muxer.c b/plugins/muxer/muxer.c index ba78cfb0..6cd355e5 100644 --- a/plugins/muxer/muxer.c +++ b/plugins/muxer/muxer.c @@ -26,12 +26,12 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "muxer.h" static @@ -96,7 +96,7 @@ BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_FILTER_COMPONENT_CLASS_ENTRY("muxer", +BT_PLUGIN_COMPONENT_CLASS_FILTER_ENTRY("muxer", "Time-correlate multiple traces.", muxer_component_init) BT_PLUGIN_COMPONENT_CLASSES_END diff --git a/plugins/muxer/muxer.h b/plugins/muxer/muxer.h index 77937523..7bf89109 100644 --- a/plugins/muxer/muxer.h +++ b/plugins/muxer/muxer.h @@ -29,7 +29,6 @@ #include #include -#include struct muxer { GHashTable *trace_clocks; diff --git a/plugins/text/text.c b/plugins/text/text.c index 2712dd68..2a8e7717 100644 --- a/plugins/text/text.c +++ b/plugins/text/text.c @@ -27,12 +27,12 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -661,7 +661,7 @@ BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(PLUGIN_NAME, +BT_PLUGIN_COMPONENT_CLASS_SINK_ENTRY(PLUGIN_NAME, "Formats CTF-IR to text. Formerly known as ctf-text.", text_component_init) BT_PLUGIN_COMPONENT_CLASSES_END diff --git a/plugins/text/text.h b/plugins/text/text.h index ef80ce3e..9f1706e4 100644 --- a/plugins/text/text.h +++ b/plugins/text/text.h @@ -29,7 +29,7 @@ #include #include -#include +#include enum text_default { TEXT_DEFAULT_UNSET, diff --git a/plugins/trimmer/iterator.c b/plugins/trimmer/iterator.c index e4213f47..942b0264 100644 --- a/plugins/trimmer/iterator.c +++ b/plugins/trimmer/iterator.c @@ -28,12 +28,12 @@ #include "trimmer.h" #include "iterator.h" -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/plugins/trimmer/iterator.h b/plugins/trimmer/iterator.h index f40f4b2d..1ab0b6f5 100644 --- a/plugins/trimmer/iterator.h +++ b/plugins/trimmer/iterator.h @@ -28,7 +28,8 @@ */ #include "trimmer.h" -#include +#include +#include struct trimmer_iterator { /* Input iterators associated with this output iterator. */ diff --git a/plugins/trimmer/trimmer.c b/plugins/trimmer/trimmer.c index 333e7d12..a29505d3 100644 --- a/plugins/trimmer/trimmer.c +++ b/plugins/trimmer/trimmer.c @@ -26,12 +26,12 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "trimmer.h" #include "iterator.h" #include @@ -391,7 +391,7 @@ BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_FILTER_COMPONENT_CLASS_ENTRY("trimmer", +BT_PLUGIN_COMPONENT_CLASS_FILTER_ENTRY("trimmer", "Ensure that trace notifications outside of a given range are filtered-out.", trimmer_component_init) BT_PLUGIN_COMPONENT_CLASSES_END diff --git a/plugins/trimmer/trimmer.h b/plugins/trimmer/trimmer.h index b0acf05f..4d82a244 100644 --- a/plugins/trimmer/trimmer.h +++ b/plugins/trimmer/trimmer.h @@ -29,8 +29,6 @@ #include #include -#include -#include #define NSEC_PER_SEC 1000000000LL diff --git a/plugins/writer/writer.c b/plugins/writer/writer.c index ad99ed8a..e8b1fefd 100644 --- a/plugins/writer/writer.c +++ b/plugins/writer/writer.c @@ -27,13 +27,13 @@ */ #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -278,7 +278,6 @@ BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY("writer", - "Formats CTF-IR to CTF.", +BT_PLUGIN_COMPONENT_CLASS_SINK_ENTRY("writer", "Formats CTF-IR to CTF.", writer_component_init) BT_PLUGIN_COMPONENT_CLASSES_END diff --git a/plugins/writer/writer.h b/plugins/writer/writer.h index 939a12c8..21aae601 100644 --- a/plugins/writer/writer.h +++ b/plugins/writer/writer.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include struct writer_component { diff --git a/tests/lib/test_bt_notification_heap.c b/tests/lib/test_bt_notification_heap.c index 7fe538ad..bacce9f6 100644 --- a/tests/lib/test_bt_notification_heap.c +++ b/tests/lib/test_bt_notification_heap.c @@ -24,9 +24,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #define NR_TESTS 7 -- 2.34.1