From 6ba0b073d3cc5040234aad3ab820b7ca4022e3e9 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Sat, 21 Jan 2017 01:16:20 -0500 Subject: [PATCH] Refactor the plugin registration and loading machinery MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch refactors the plugin registration and loading machinery: the different, specific symbol names found in the shared object are dropped in favor of two sections. The goals of this refactoring are: 1. To allow optional plugin attributes now and in the future. 2. To allow optional component class attributes now and in the future. 3. To make backward and forward compatibility easier. 4. To simplify the plugin development API from a user's perspective. 5. To use the same mechanism to load plugins from a shared object and statically from the `babeltrace` binary. You can still find the macros used to define plugins, plugin attributes, and component classes in `babeltrace/plugin/plugin-dev`. We introduce four (IV) new structures to the plugin subsystem: * A *plugin descriptor* describes a single plugin. Note that one shared object can contain one or more plugin descriptors, thus it can contain one or more plugins. A plugin descriptor contains the interface version of the plugin it describes as well as its name (a C string). The BT_PLUGIN_WITH_ID() macro creates a plugin descriptor structure with a specific identifier in its variable name. It also creates a pointer to this structure which is added to the plugin descriptor section (`__bt_plugin_descriptors`). The BT_PLUGIN() macro is an easy-to-use version of BT_PLUGIN_WITH_ID(): it accepts a C identifier which is the name of the plugin. Its plugin descriptor ID is `auto`. * A *plugin descriptor attribute* is an optional attribute attached to a specific plugin descriptor. A plugin descriptor attribute structure has a type (its key) as well as a value (the value's type depends on the attribute type). For debug purposes, we also put a string in this structure which is the name of the attribute type. This can be used by the plugin subsystem to give more information when it warns that an attribute with an unknown type was found (use case: current Babeltrace loading a future plugin). A plugin descriptor attribute also has a member pointing to its "parent" plugin descriptor. The following macros each create a plugin descriptor attribute structure and a pointer to this structure which is added to the plugin attribute section. Each macro accepts a plugin descriptor ID (to attach the attribute to the appropriate descriptor) and a value: * BT_PLUGIN_INIT_WITH_ID(): Initialization function. * BT_PLUGIN_EXIT_WITH_ID(): Exit function. * BT_PLUGIN_AUTHOR_WITH_ID(): Author. * BT_PLUGIN_LICENSE_WITH_ID(): License. * BT_PLUGIN_DESCRIPTION_WITH_ID(): Description. You can use the macros above in any order, but you need to use them after BT_PLUGIN_INIT*(). There's an equivalent, easy-to-use macro for each of the macros above without the `_WITH_ID` suffix which uses the `auto` plugin descriptor. * A *component class descriptor* describes a single component class attached to a specific plugin descriptor. The structure contains the mandatory attributes needed to build a component class (name, component type, component initialization function). The BT_PLUGIN_COMPONENT_CLASS_WITH_ID() macro creates a component class descriptor structure with a specific component class descriptor identifier in its variable name. The component source type is also part of the variable name, as well as the specified plugin descriptor ID. The macro also creates a pointer to this structure which is added to the component class descriptor section (`__bt_plugin_component_descriptors`). The easy-to-use BT_PLUGIN_COMPONENT_CLASS() macro uses the `auto` plugin descriptor and the name of the component class as the component class descriptor ID (a C identifier in this version, to allow this). With this new mechanism, the BT_PLUGIN_COMPONENT_CLASSES_BEGIN and BT_PLUGIN_COMPONENT_CLASSES_END macros do not exist anymore: you can use BT_PLUGIN_COMPONENT_CLASS*() macros anywhere, in any order, as long as they appear after BT_PLUGIN_INIT*(). * A *component class descriptor attribute* is an optional attribute attached to a specific component class descriptor. A component class descriptor attribute structure has a type (its key) as well as a value (the value's type depends on the attribute type). For debug purposes, we also put a string in this structure which is the name of the attribute type. A component class descriptor attribute also has a member pointing to its "parent" component class descriptor (which itself, as stated above, as a member pointing to its "parent" plugin descriptor). As of this patch, the only available component class descriptor attribute is its optional description. The BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION_WITH_ID() macro creates such an attribute. BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION() is the easy-to-use version which uses the `auto` plugin descriptor. You need to place BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION*() after the associated BT_PLUGIN_COMPONENT_CLASS*(). We also add the macro BT_PLUGIN_DECLARE() to declare an `extern` plugin descriptor structure to add plugin attributes to the same plugin descriptor from different compilation units. Thanks to this, the simple fact of linking a given object file or not to a shared object is enough to conditionally add or not one or more component classes. This approach also has the somewhat interesting side effect of refusing to build if you define a plugin descriptor attribute without using BT_PLUGIN_INIT*() (missing name) or if you define the same attribute twice, since the macros create actual variables which must have unique names. When the plugin subsystem loads a shared object, it looks for the beginning and end symbols for the four sections: * Plugin descriptors. * Plugin descriptor attributes. * Component class descriptors. * Component class descriptor attributes. Those are enough to provide everything that is needed to create a plugin object. A plugin's initialization function is called first, and then its component classes are created and added sequentially according to the discovered component class descriptors. Since a single shared object file can now contain more than one plugin (descriptor), the following function: struct bt_plugin *bt_plugin_create_from_file(const char *path); is changed to this: struct bt_plugin **bt_plugin_create_all_from_file(const char *path); In other words, the function returns a NULL-terminated array of plugin objects, just like bt_plugin_create_append_all_from_dir() does. All the existing plugins and tests are updated to follow the changes. Signed-off-by: Philippe Proulx Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- include/babeltrace/plugin/plugin-dev.h | 424 +++++++++-- include/babeltrace/plugin/plugin-internal.h | 17 +- include/babeltrace/plugin/plugin.h | 2 +- lib/component/component-class.c | 23 +- lib/plugin/plugin.c | 700 ++++++++++++------- plugins/ctf/fs/fs.h | 1 - plugins/ctf/lttng-live/lttng-live-internal.h | 1 - plugins/ctf/plugin.c | 15 +- plugins/muxer/muxer.c | 12 +- plugins/text/text.c | 17 +- plugins/trimmer/trimmer.c | 12 +- plugins/writer/writer.c | 11 +- tests/lib/test-plugin-plugins/Makefile.am | 35 +- tests/lib/test-plugin-plugins/invalid.c | 34 - tests/lib/test-plugin-plugins/minimal.c | 2 +- tests/lib/test-plugin-plugins/sfs.c | 15 +- tests/lib/test_plugin.c | 43 +- 17 files changed, 891 insertions(+), 473 deletions(-) delete mode 100644 tests/lib/test-plugin-plugins/invalid.c diff --git a/include/babeltrace/plugin/plugin-dev.h b/include/babeltrace/plugin/plugin-dev.h index ffa39bb5..387cf89e 100644 --- a/include/babeltrace/plugin/plugin-dev.h +++ b/include/babeltrace/plugin/plugin-dev.h @@ -2,7 +2,7 @@ #define BABELTRACE_PLUGIN_PLUGIN_DEV_H /* - * BabelTrace - Babeltrace Plug-in System Interface + * BabelTrace - Babeltrace Plug-in Development API * * This is the header that you need to include for the development of * a Babeltrace plug-in. @@ -31,6 +31,7 @@ * SOFTWARE. */ +#include #include #include @@ -38,83 +39,368 @@ extern "C" { #endif +/* + * Plugin interface's version, not synced with Babeltrace's version + * (internal use). + */ +#define __BT_PLUGIN_VERSION_MAJOR 1 +#define __BT_PLUGIN_VERSION_MINOR 0 + +/* Plugin initialization function type */ typedef enum bt_plugin_status (*bt_plugin_init_func)( struct bt_plugin *plugin); +/* Plugin exit function type */ typedef enum bt_plugin_status (*bt_plugin_exit_func)(void); +/* + * Function to call from a plugin's initialization function to add a + * component class to a plugin object. + */ 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); +/* Plugin descriptor: describes a single plugin (internal use) */ +struct __bt_plugin_descriptor { + /* Plugin's interface major version number */ + uint32_t major; + + /* Plugin's interface minor version number */ + uint32_t minor; + + /* Plugin's name */ + const char *name; +} __attribute__((packed)); + +/* Type of a plugin attribute (internal use) */ +enum __bt_plugin_descriptor_attribute_type { + BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT = 0, + BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT = 1, + BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR = 2, + BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE = 3, + BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION = 4, +}; + +/* Plugin attribute (internal use) */ +struct __bt_plugin_descriptor_attribute { + /* Plugin descriptor to which to associate this attribute */ + const struct __bt_plugin_descriptor *plugin_descriptor; + + /* Attribute's type */ + enum __bt_plugin_descriptor_attribute_type type; + + /* Name of the attribute's type for debug purposes */ + const char *type_name; + + /* Attribute's value */ + union { + /* BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT */ + bt_plugin_init_func init; + + /* BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT */ + bt_plugin_exit_func exit; + + /* BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR */ + const char *author; + + /* BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE */ + const char *license; + + /* BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION */ + const char *description; + } value; +} __attribute__((packed)); + +/* Component class descriptor (internal use) */ +struct __bt_plugin_component_class_descriptor { + /* + * Plugin descriptor to which to associate this component + * class descriptor. + */ + const struct __bt_plugin_descriptor *plugin_descriptor; + + /* Component type */ + enum bt_component_type type; + + /* Component class name */ + const char *name; + + /* Component initialization function */ + bt_component_init_cb init_cb; +} __attribute__((packed)); + +/* Type of a component class attribute (internal use) */ +enum __bt_plugin_component_class_descriptor_attribute_type { + BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION = 0, +}; + +/* Component class attribute (internal use) */ +struct __bt_plugin_component_class_descriptor_attribute { + /* + * Component class plugin attribute to which to associate this + * component class attribute. + */ + const struct __bt_plugin_component_class_descriptor *comp_class_descriptor; + + /* Attribute's type */ + enum __bt_plugin_component_class_descriptor_attribute_type type; + + /* Name of the attribute's type for debug purposes */ + const char *type_name; + + /* Attribute's value */ + union { + /* BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION */ + const char *description; + } value; +} __attribute__((packed)); + +/* + * Variable attributes for a plugin descriptor pointer to be added to + * the plugin descriptor section (internal use). + */ +#define __BT_PLUGIN_DESCRIPTOR_ATTRS \ + __attribute__((section("__bt_plugin_descriptors"), used)) + +/* + * Variable attributes for a plugin attribute pointer to be added to + * the plugin attribute section (internal use). + */ +#define __BT_PLUGIN_DESCRIPTOR_ATTRIBUTES_ATTRS \ + __attribute__((section("__bt_plugin_descriptor_attributes"), used)) + +/* + * Variable attributes for a component class descriptor pointer to be + * added to the component class descriptor section (internal use). + */ +#define __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRS \ + __attribute__((section("__bt_plugin_component_class_descriptors"), used)) + +/* + * Variable attributes for a component class descriptor attribute + * pointer to be added to the component class descriptor attribute + * section (internal use). + */ +#define __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTES_ATTRS \ + __attribute__((section("__bt_plugin_component_class_descriptor_attributes"), used)) + +/* + * Declares a plugin descriptor pointer variable with a custom ID. + * + * _id: ID (any valid C identifier except `auto`). + */ +#define BT_PLUGIN_DECLARE(_id) extern struct __bt_plugin_descriptor __bt_plugin_descriptor_##_id + +/* + * Defines a plugin descriptor with a custom ID. + * + * _id: ID (any valid C identifier except `auto`). + * _name: Plugin's name (C string). + */ +#define BT_PLUGIN_WITH_ID(_id, _name) \ + struct __bt_plugin_descriptor __bt_plugin_descriptor_##_id = { \ + .major = __BT_PLUGIN_VERSION_MAJOR, \ + .minor = __BT_PLUGIN_VERSION_MINOR, \ + .name = _name, \ + }; \ + static struct __bt_plugin_descriptor const * const __bt_plugin_descriptor_##_id##_ptr __BT_PLUGIN_DESCRIPTOR_ATTRS = &__bt_plugin_descriptor_##_id; \ + extern struct __bt_plugin_descriptor const *__start___bt_plugin_descriptors; \ + extern struct __bt_plugin_descriptor const *__stop___bt_plugin_descriptors + +/* + * Defines a plugin attribute (generic, internal use). + * + * _attr_name: Name of the attribute (C identifier). + * _attr_type: Type of the attribute (enum __bt_plugin_descriptor_attribute_type). + * _id: Plugin descriptor ID (C identifier). + * _x: Value. + */ +#define __BT_PLUGIN_DESCRIPTOR_ATTRIBUTE(_attr_name, _attr_type, _id, _x) \ + static struct __bt_plugin_descriptor_attribute __bt_plugin_descriptor_attribute_##_id##_##_attr_name = { \ + .plugin_descriptor = &__bt_plugin_descriptor_##_id, \ + .type = _attr_type, \ + .type_name = #_attr_name, \ + .value._attr_name = _x, \ + }; \ + static struct __bt_plugin_descriptor_attribute const * const __bt_plugin_descriptor_attribute_##_id##_##_attr_name##_ptr __BT_PLUGIN_DESCRIPTOR_ATTRIBUTES_ATTRS = &__bt_plugin_descriptor_attribute_##_id##_##_attr_name; \ + extern struct __bt_plugin_descriptor_attribute const *__start___bt_plugin_descriptor_attributes; \ + extern struct __bt_plugin_descriptor_attribute const *__stop___bt_plugin_descriptor_attributes + +/* + * Defines a plugin initialization function attribute attached to a + * specific plugin descriptor. + * + * _id: Plugin descriptor ID (C identifier). + * _x: Initialization function (bt_plugin_init_func). + */ +#define BT_PLUGIN_INIT_WITH_ID(_id, _x) \ + __BT_PLUGIN_DESCRIPTOR_ATTRIBUTE(init, BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT, _id, _x) + +/* + * Defines a plugin exit function attribute attached to a specific + * plugin descriptor. + * + * _id: Plugin descriptor ID (C identifier). + * _x: Exit function (bt_plugin_exit_func). + */ +#define BT_PLUGIN_EXIT_WITH_ID(_id, _x) \ + __BT_PLUGIN_DESCRIPTOR_ATTRIBUTE(exit, BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT, _id, _x) + +/* + * Defines an author attribute attached to a specific plugin descriptor. + * + * _id: Plugin descriptor ID (C identifier). + * _x: Author (C string). + */ +#define BT_PLUGIN_AUTHOR_WITH_ID(_id, _x) \ + __BT_PLUGIN_DESCRIPTOR_ATTRIBUTE(author, BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR, _id, _x) + +/* + * Defines a license attribute attached to a specific plugin descriptor. + * + * _id: Plugin descriptor ID (C identifier). + * _x: License (C string). + */ +#define BT_PLUGIN_LICENSE_WITH_ID(_id, _x) \ + __BT_PLUGIN_DESCRIPTOR_ATTRIBUTE(license, BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE, _id, _x) + +/* + * Defines a description attribute attached to a specific plugin + * descriptor. + * + * _id: Plugin descriptor ID (C identifier). + * _x: Description (C string). + */ +#define BT_PLUGIN_DESCRIPTION_WITH_ID(_id, _x) \ + __BT_PLUGIN_DESCRIPTOR_ATTRIBUTE(description, BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION, _id, _x) + +/* + * Defines a component class descriptor with a custom ID. + * + * _id: ID (any valid C identifier except `auto`). + * _comp_class_id: Component class ID (C identifier). + * _type: Component class type (enum bt_component_type). + * _name: Component class name (C string). + * _init_func: Component class's initialization function + * (bt_component_init_cb). + */ +#define BT_PLUGIN_COMPONENT_CLASS_WITH_ID(_id, _comp_class_id, _type, _name, _init_cb) \ + static struct __bt_plugin_component_class_descriptor __bt_plugin_component_class_descriptor_##_id##_##_comp_class_id##_##_type = { \ + .plugin_descriptor = &__bt_plugin_descriptor_##_id, \ + .type = _type, \ + .name = _name, \ + .init_cb = _init_cb, \ + }; \ + static struct __bt_plugin_component_class_descriptor const * const __bt_plugin_component_class_descriptor_##_id##_##_comp_class_id##_##_type##_ptr __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRS = &__bt_plugin_component_class_descriptor_##_id##_##_comp_class_id##_##_type; \ + extern struct __bt_plugin_component_class_descriptor const *__start___bt_plugin_component_class_descriptors; \ + extern struct __bt_plugin_component_class_descriptor const *__stop___bt_plugin_component_class_descriptors + +/* + * Defines a component class descriptor attribute (generic, internal + * use). + * + * _id: Plugin descriptor ID (C identifier). + * _comp_class_id: Component class ID (C identifier). + * _type: Component class type (enum bt_component_type). + * _attr_name: Name of the attribute (C identifier). + * _attr_type: Type of the attribute + * (enum __bt_plugin_descriptor_attribute_type). + * _x: Value. + */ +#define __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE(_attr_name, _attr_type, _id, _comp_class_id, _type, _x) \ + static struct __bt_plugin_component_class_descriptor_attribute __bt_plugin_component_class_descriptor_attribute_##_id##_##_comp_class_id##_##_type##_##_attr_name = { \ + .comp_class_descriptor = &__bt_plugin_component_class_descriptor_##_id##_##_comp_class_id##_##_type, \ + .type = _attr_type, \ + .type_name = #_attr_name, \ + .value.description = _x, \ + }; \ + static struct __bt_plugin_component_class_descriptor_attribute const * const __bt_plugin_component_class_descriptor_attribute_##_id##_##_comp_class_id##_##_type##_##_attr_name##_ptr __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTES_ATTRS = &__bt_plugin_component_class_descriptor_attribute_##_id##_##_comp_class_id##_##_type##_##_attr_name; \ + extern struct __bt_plugin_component_class_descriptor_attribute const *__start___bt_plugin_component_class_descriptor_attributes; \ + extern struct __bt_plugin_component_class_descriptor_attribute const *__stop___bt_plugin_component_class_descriptor_attributes + +/* + * Defines a description attribute attached to a specific component + * class descriptor. + * + * _id: Plugin descriptor ID (C identifier). + * _comp_class_id: Component class descriptor ID (C identifier). + * _type: Component class type (enum bt_component_type). + * _x: Description (C string). + */ +#define BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION_WITH_ID(_id, _comp_class_id, _type, _x) \ + __BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE(description, BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION, _id, _comp_class_id, _type, _x) + +/* + * Defines a plugin descriptor with an automatic ID. + * + * _name: Plugin's name (C string). + */ +#define BT_PLUGIN(_name) static BT_PLUGIN_WITH_ID(auto, #_name) + +/* + * Defines a plugin initialization function attribute attached to the + * automatic plugin descriptor. + * + * _x: Initialization function (bt_plugin_init_func). + */ +#define BT_PLUGIN_INIT(_x) BT_PLUGIN_INIT_WITH_ID(auto, _x) + + /* + * Defines a plugin exit function attribute attached to the automatic + * plugin descriptor. + * + * _x: Exit function (bt_plugin_exit_func). + */ +#define BT_PLUGIN_EXIT(_x) BT_PLUGIN_EXIT_WITH_ID(auto, _x) + +/* + * Defines an author attribute attached to the automatic plugin + * descriptor. + * + * _x: Author (C string). + */ +#define BT_PLUGIN_AUTHOR(_x) BT_PLUGIN_AUTHOR_WITH_ID(auto, _x) + +/* + * Defines a license attribute attached to the automatic plugin + * descriptor. + * + * _x: License (C string). + */ +#define BT_PLUGIN_LICENSE(_x) BT_PLUGIN_LICENSE_WITH_ID(auto, _x) + +/* + * Defines a description attribute attached to the automatic plugin + * descriptor. + * + * _x: Description (C string). + */ +#define BT_PLUGIN_DESCRIPTION(_x) BT_PLUGIN_DESCRIPTION_WITH_ID(auto, _x) + +/* + * Defines a component class attached to the automatic plugin + * descriptor. Its ID is the same as its name, hence its name must be a + * C identifier in this version. + * + * _type: Component class type (enum bt_component_type). + * _name: Component class name (C identifier). + * _init_cb: Component class's initialization function + * (bt_component_init_cb). + */ +#define BT_PLUGIN_COMPONENT_CLASS(_type, _name, _init_cb) \ + BT_PLUGIN_COMPONENT_CLASS_WITH_ID(auto, _name, _type, #_name, _init_cb) + +/* + * Defines a description attribute attached to a component class + * descriptor which is attached to the automatic plugin descriptor. + * + * _type: Component class type (enum bt_component_type). + * _name: Component class name (C identifier). + * _x: Description (C string). + */ +#define BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(_type, _name, _x) \ + BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION_WITH_ID(auto, _name, _type, _x) #ifdef __cplusplus } diff --git a/include/babeltrace/plugin/plugin-internal.h b/include/babeltrace/plugin/plugin-internal.h index 0509be44..ac021720 100644 --- a/include/babeltrace/plugin/plugin-internal.h +++ b/include/babeltrace/plugin/plugin-internal.h @@ -37,14 +37,9 @@ 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; - bt_plugin_init_func init; + /* True if initialization function was called */ + bool init_called; bt_plugin_exit_func exit; }; @@ -57,6 +52,14 @@ struct bt_plugin { /* Array of pointers to bt_component_class (owned by this) */ GPtrArray *comp_classes; + + /* Pointers to plugin's memory: do NOT free */ + const struct __bt_plugin_descriptor *descriptor; + const char *name; + const char *author; + const char *license; + const char *description; + bt_plugin_init_func init; }; #endif /* BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H */ diff --git a/include/babeltrace/plugin/plugin.h b/include/babeltrace/plugin/plugin.h index 10581984..66436dfb 100644 --- a/include/babeltrace/plugin/plugin.h +++ b/include/babeltrace/plugin/plugin.h @@ -51,7 +51,7 @@ enum bt_plugin_status { 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_file(const char *path); extern struct bt_plugin **bt_plugin_create_all_from_dir(const char *path, bool recurse); diff --git a/lib/component/component-class.c b/lib/component/component-class.c index 1e1e8388..660964c2 100644 --- a/lib/component/component-class.c +++ b/lib/component/component-class.c @@ -67,7 +67,11 @@ 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_component_class *class; + struct bt_component_class *class = NULL; + + if (!name) { + goto end; + } class = g_new0(struct bt_component_class, 1); if (!class) { @@ -78,11 +82,19 @@ struct bt_component_class *bt_component_class_create( class->type = type; class->init = init; class->name = g_string_new(name); - class->description = g_string_new(description); - if (!class->name || !class->description) { - BT_PUT(class); + if (!class->name) { + BT_PUT(class); goto end; } + + if (description) { + class->description = g_string_new(description); + if (!class->description) { + BT_PUT(class); + goto end; + } + } + class->destroy_listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_component_class_destroyer_listener)); if (!class->destroy_listeners) { @@ -109,7 +121,8 @@ enum bt_component_type bt_component_class_get_type( const char *bt_component_class_get_description( struct bt_component_class *component_class) { - return component_class ? component_class->description->str : NULL; + return component_class && component_class->description ? + component_class->description->str : NULL; } BT_HIDDEN diff --git a/lib/plugin/plugin.c b/lib/plugin/plugin.c index e1e0387b..5a72b42e 100644 --- a/lib/plugin/plugin.c +++ b/lib/plugin/plugin.c @@ -41,12 +41,6 @@ #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" @@ -55,37 +49,18 @@ #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_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) + extern _type __start_##_name __attribute((weak)); \ + extern _type __stop_##_name __attribute((weak)) + +DECLARE_SECTION(struct __bt_plugin_descriptor const *, __bt_plugin_descriptors); +DECLARE_SECTION(struct __bt_plugin_descriptor_attribute const *, __bt_plugin_descriptor_attributes); +DECLARE_SECTION(struct __bt_plugin_component_class_descriptor const *, __bt_plugin_component_class_descriptors); +DECLARE_SECTION(struct __bt_plugin_component_class_descriptor_attribute const *, __bt_plugin_component_class_descriptor_attributes); /* * This hash table, global to the library, maps component class pointers @@ -106,9 +81,9 @@ DECLARE_SECTION(const char *, __bt_plugin_descriptions); * * 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); + * my_plugins = bt_plugin_create_all_from_file("/path/to/my-plugin.so"); + * // instantiate components from a plugin's component classes + * // put plugins and free my_plugins here * // user code of instantiated components still exists * * 2. To decouple the plugin subsystem from the component subsystem: @@ -156,8 +131,11 @@ void bt_plugin_shared_lib_handle_destroy(struct bt_object *obj) 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); + const char *path = shared_lib_handle->path ? + shared_lib_handle->path->str : "[built-in]"; + + printf_verbose("Plugin in module `%s` exited with error %d\n", + path, status); } } @@ -180,7 +158,6 @@ 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) { @@ -204,68 +181,6 @@ struct bt_plugin_shared_lib_handle *bt_plugin_shared_lib_handle_create( 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: @@ -293,47 +208,352 @@ void bt_plugin_destroy(struct bt_object *obj) } static -enum bt_plugin_status init_plugin(struct bt_plugin *plugin) +struct bt_plugin *bt_plugin_create_empty( + struct bt_plugin_shared_lib_handle *shared_lib_handle) +{ + struct bt_plugin *plugin = NULL; + + plugin = g_new0(struct bt_plugin, 1); + if (!plugin) { + goto error; + } + + bt_object_init(plugin, bt_plugin_destroy); + plugin->shared_lib_handle = bt_get(shared_lib_handle); + + /* 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; + } + + goto end; + +error: + BT_PUT(plugin); + +end: + return plugin; +} + +static +enum bt_plugin_status bt_plugin_init( + struct bt_plugin *plugin, + const struct __bt_plugin_descriptor *descriptor, + struct __bt_plugin_descriptor_attribute const * const *attrs_begin, + struct __bt_plugin_descriptor_attribute const * const *attrs_end, + struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin, + struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end, + struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin, + struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end) { + /* + * This structure's members point to the plugin's memory + * (do NOT free). + */ + struct comp_class_full_descriptor { + const struct __bt_plugin_component_class_descriptor *descriptor; + const char *description; + }; + enum bt_plugin_status status = BT_PLUGIN_STATUS_OK; + struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr; + struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr; + struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr; + GArray *comp_class_full_descriptors; + size_t i; + + comp_class_full_descriptors = g_array_new(FALSE, TRUE, + sizeof(struct comp_class_full_descriptor)); + if (!comp_class_full_descriptors) { + status = BT_PLUGIN_STATUS_ERROR; + goto end; + } - if (plugin->shared_lib_handle->init) { - status = plugin->shared_lib_handle->init(plugin); + /* Set mandatory attributes */ + plugin->descriptor = descriptor; + plugin->name = descriptor->name; + /* + * Find and set optional attributes attached to this plugin + * descriptor. + */ + for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) { + const struct __bt_plugin_descriptor_attribute *cur_attr = + *cur_attr_ptr; + + if (cur_attr->plugin_descriptor != descriptor) { + continue; + } + + switch (cur_attr->type) { + case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT: + plugin->init = cur_attr->value.init; + break; + case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT: + plugin->shared_lib_handle->exit = cur_attr->value.exit; + break; + case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR: + plugin->author = cur_attr->value.author; + break; + case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE: + plugin->license = cur_attr->value.license; + break; + case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION: + plugin->description = cur_attr->value.description; + break; + default: + printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n", + cur_attr->type_name, cur_attr->type, + descriptor->name); + break; + } + } + + /* + * Find component class descriptors attached to this plugin + * descriptor and initialize corresponding full component class + * descriptors in the array. + */ + for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) { + const struct __bt_plugin_component_class_descriptor *cur_cc_descr = + *cur_cc_descr_ptr; + struct comp_class_full_descriptor full_descriptor; + + if (cur_cc_descr->plugin_descriptor != descriptor) { + continue; + } + + full_descriptor.descriptor = cur_cc_descr; + full_descriptor.description = NULL; + g_array_append_val(comp_class_full_descriptors, + full_descriptor); + } + + /* + * Find component class descriptor attributes attached to this + * plugin descriptor and update corresponding full component + * class descriptors in the array. + */ + for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) { + const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr = + *cur_cc_descr_attr_ptr; + + if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor != + descriptor) { + continue; + } + + /* Find the corresponding component class descriptor entry */ + for (i = 0; i < comp_class_full_descriptors->len; i++) { + struct comp_class_full_descriptor *cc_full_descr = + &g_array_index(comp_class_full_descriptors, + struct comp_class_full_descriptor, i); + + if (cur_cc_descr_attr->comp_class_descriptor == + cc_full_descr->descriptor) { + switch (cur_cc_descr_attr->type) { + case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION: + cc_full_descr->description = + cur_cc_descr_attr->value.description; + break; + default: + printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n", + cur_cc_descr_attr->type_name, + cur_cc_descr_attr->type, + cur_cc_descr_attr->comp_class_descriptor->name, + cur_cc_descr_attr->comp_class_descriptor->type, + descriptor->name); + break; + } + } + } + } + + /* Initialize plugin */ + if (plugin->init) { + status = plugin->init(plugin); if (status < 0) { printf_verbose("Plugin `%s` initialization error: %d\n", - plugin->shared_lib_handle->name, status); + plugin->name, status); goto end; } } plugin->shared_lib_handle->init_called = true; + for (i = 0; i < comp_class_full_descriptors->len; i++) { + struct comp_class_full_descriptor *cc_full_descr = + &g_array_index(comp_class_full_descriptors, + struct comp_class_full_descriptor, i); + struct bt_component_class *comp_class; + + comp_class = bt_component_class_create( + cc_full_descr->descriptor->type, + cc_full_descr->descriptor->name, + cc_full_descr->description, + cc_full_descr->descriptor->init_cb); + if (!comp_class) { + status = BT_PLUGIN_STATUS_ERROR; + goto end; + } + + status = bt_plugin_add_component_class(plugin, + comp_class); + BT_PUT(comp_class); + if (status < 0) { + printf_verbose("Cannot add component class %s (type %d) to plugin `%s`: status = %d\n", + cc_full_descr->descriptor->name, + cc_full_descr->descriptor->type, + plugin->name, status); + goto end; + } + } + /* - * 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). + * All the plugin's component classes should be added 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: + g_array_free(comp_class_full_descriptors, TRUE); return status; } -struct bt_plugin *bt_plugin_create_from_file(const char *path) +static +struct bt_plugin **bt_plugin_create_all_from_sections( + struct bt_plugin_shared_lib_handle *shared_lib_handle, + struct __bt_plugin_descriptor const * const *descriptors_begin, + struct __bt_plugin_descriptor const * const *descriptors_end, + struct __bt_plugin_descriptor_attribute const * const *attrs_begin, + struct __bt_plugin_descriptor_attribute const * const *attrs_end, + struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin, + struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end, + struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin, + struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end) +{ + size_t descriptor_count; + size_t attrs_count; + size_t cc_descriptors_count; + size_t cc_descr_attrs_count; + size_t i; + struct bt_plugin **plugins = NULL; + + descriptor_count = descriptors_end - descriptors_begin; + attrs_count = attrs_end - attrs_begin; + cc_descriptors_count = cc_descriptors_end - cc_descriptors_begin; + cc_descr_attrs_count = cc_descr_attrs_end - cc_descr_attrs_begin; + printf_verbose("Section: Plugin descriptors: [%p - %p], (%zu elements)\n", + descriptors_begin, descriptors_end, descriptor_count); + printf_verbose("Section: Plugin descriptor attributes: [%p - %p], (%zu elements)\n", + attrs_begin, attrs_end, attrs_count); + printf_verbose("Section: Plugin component class descriptors: [%p - %p], (%zu elements)\n", + cc_descriptors_begin, cc_descriptors_end, cc_descriptors_count); + printf_verbose("Section: Plugin component class descriptor attributes: [%p - %p], (%zu elements)\n", + cc_descr_attrs_begin, cc_descr_attrs_end, attrs_count); + plugins = calloc(descriptor_count + 1, sizeof(*plugins)); + if (!plugins) { + goto error; + } + + for (i = 0; i < descriptor_count; i++) { + enum bt_plugin_status status; + const struct __bt_plugin_descriptor *descriptor = + descriptors_begin[i]; + struct bt_plugin *plugin; + + printf_verbose("Loading plugin %s (%d.%d)\n", descriptor->name, + descriptor->major, descriptor->minor); + + if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) { + printf_error("Unknown plugin's major version: %d\n", + descriptor->major); + goto error; + } + + plugin = bt_plugin_create_empty(shared_lib_handle); + if (!plugin) { + printf_error("Cannot allocate plugin object for plugin %s\n", + descriptor->name); + goto error; + } + + status = bt_plugin_init(plugin, descriptor, attrs_begin, + attrs_end, cc_descriptors_begin, cc_descriptors_end, + cc_descr_attrs_begin, cc_descr_attrs_end); + if (status < 0) { + printf_error("Cannot initialize plugin object %s\n", + descriptor->name); + BT_PUT(plugin); + goto error; + } + + /* Transfer ownership to the array */ + plugins[i] = plugin; + } + + goto end; + +error: + g_free(plugins); + plugins = NULL; + +end: + return plugins; +} + +struct bt_plugin **bt_plugin_create_all_from_static(void) +{ + struct bt_plugin **plugins = NULL; + struct bt_plugin_shared_lib_handle *shared_lib_handle = + bt_plugin_shared_lib_handle_create(NULL); + + if (!shared_lib_handle) { + goto end; + } + + plugins = bt_plugin_create_all_from_sections(shared_lib_handle, + SECTION_BEGIN(__bt_plugin_descriptors), + SECTION_END(__bt_plugin_descriptors), + SECTION_BEGIN(__bt_plugin_descriptor_attributes), + SECTION_END(__bt_plugin_descriptor_attributes), + SECTION_BEGIN(__bt_plugin_component_class_descriptors), + SECTION_END(__bt_plugin_component_class_descriptors), + SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes), + SECTION_END(__bt_plugin_component_class_descriptor_attributes)); + +end: + BT_PUT(shared_lib_handle); + + return plugins; +} + +struct bt_plugin **bt_plugin_create_all_from_file(const char *path) { size_t path_len; - struct bt_plugin *plugin = NULL; + struct bt_plugin **plugins = NULL; + struct __bt_plugin_descriptor const * const *descriptors_begin = NULL; + struct __bt_plugin_descriptor const * const *descriptors_end = NULL; + struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL; + struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL; + struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL; + struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL; + struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL; + struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL; bool is_libtool_wrapper = false, is_shared_object = false; + struct bt_plugin_shared_lib_handle *shared_lib_handle = NULL; if (!path) { - goto error; + goto end; } path_len = strlen(path); if (path_len <= PLUGIN_SUFFIX_LEN) { - goto error; + goto end; } path_len++; @@ -349,43 +569,99 @@ struct bt_plugin *bt_plugin_create_from_file(const char *path) NATIVE_PLUGIN_SUFFIX_LEN); if (!is_shared_object && !is_libtool_wrapper) { /* Name indicates that this is not a plugin file. */ - goto error; + goto end; } - plugin = g_new0(struct bt_plugin, 1); - if (!plugin) { - goto error; + shared_lib_handle = bt_plugin_shared_lib_handle_create(path); + if (!shared_lib_handle) { + goto end; } - bt_object_init(plugin, bt_plugin_destroy); + if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptors", + (gpointer *) &descriptors_begin)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__start___bt_plugin_descriptors", + g_module_name(shared_lib_handle->module)); + goto end; + } - /* 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; + if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptors", + (gpointer *) &descriptors_end)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__stop___bt_plugin_descriptors", + g_module_name(shared_lib_handle->module)); + goto end; } - /* 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; + if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptor_attributes", + (gpointer *) &attrs_begin)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__start___bt_plugin_descriptor_attributes", + g_module_name(shared_lib_handle->module)); } - /* Initialize plugin */ - if (init_plugin(plugin) < 0) { - goto error; + if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptor_attributes", + (gpointer *) &attrs_end)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__stop___bt_plugin_descriptor_attributes", + g_module_name(shared_lib_handle->module)); } - goto end; + if ((!!attrs_begin - !!attrs_end) != 0) { + printf_verbose("Found __start___bt_plugin_descriptor_attributes or __stop___bt_plugin_descriptor_attributes symbol, but not both in %s\n", + g_module_name(shared_lib_handle->module)); + goto end; + } -error: - BT_PUT(plugin); + if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptors", + (gpointer *) &cc_descriptors_begin)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__start___bt_plugin_component_class_descriptors", + g_module_name(shared_lib_handle->module)); + } + + if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptors", + (gpointer *) &cc_descriptors_end)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__stop___bt_plugin_component_class_descriptors", + g_module_name(shared_lib_handle->module)); + } + + if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) { + printf_verbose("Found __start___bt_plugin_component_class_descriptors or __stop___bt_plugin_component_class_descriptors symbol, but not both in %s\n", + g_module_name(shared_lib_handle->module)); + goto end; + } + + if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptor_attributes", + (gpointer *) &cc_descr_attrs_begin)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__start___bt_plugin_component_class_descriptor_attributes", + g_module_name(shared_lib_handle->module)); + } + + if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptor_attributes", + (gpointer *) &cc_descr_attrs_end)) { + printf_verbose("Unable to resolve plugin symbol %s from %s\n", + "__stop___bt_plugin_component_class_descriptor_attributes", + g_module_name(shared_lib_handle->module)); + } + + if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) { + printf_verbose("Found __start___bt_plugin_component_class_descriptor_attributes or __stop___bt_plugin_component_class_descriptor_attributes symbol, but not both in %s\n", + g_module_name(shared_lib_handle->module)); + goto end; + } + + /* Initialize plugin */ + plugins = bt_plugin_create_all_from_sections(shared_lib_handle, + descriptors_begin, descriptors_end, attrs_begin, attrs_end, + cc_descriptors_begin, cc_descriptors_end, + cc_descr_attrs_begin, cc_descr_attrs_end); end: - return plugin; + BT_PUT(shared_lib_handle); + return plugins; } /* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */ @@ -412,9 +688,16 @@ enum bt_plugin_status bt_plugin_create_append_all_from_dir( DIR *directory = NULL; struct dirent *entry = NULL, *result = NULL; char *file_path = NULL; - size_t path_len = strlen(path); + size_t path_len; enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK; + if (!path) { + ret = BT_PLUGIN_STATUS_ERROR; + goto end; + } + + path_len = strlen(path); + if (path_len >= PATH_MAX) { ret = BT_PLUGIN_STATUS_ERROR; goto end; @@ -479,11 +762,18 @@ enum bt_plugin_status bt_plugin_create_append_all_from_dir( goto end; } } else if (S_ISREG(st.st_mode)) { - struct bt_plugin *plugin = bt_plugin_create_from_file(file_path); + struct bt_plugin **plugins_from_file = + bt_plugin_create_all_from_file(file_path); - if (plugin) { - /* Transfer ownership to array */ - g_ptr_array_add(plugins, plugin); + if (plugins_from_file) { + struct bt_plugin **plugin; + + for (plugin = plugins_from_file; *plugin; plugin++) { + /* Transfer ownership to array */ + g_ptr_array_add(plugins, *plugin); + } + + free(plugins_from_file); } } } @@ -505,19 +795,10 @@ end: struct bt_plugin **bt_plugin_create_all_from_dir(const char *path, bool recurse) { - GPtrArray *plugins_array = NULL; + GPtrArray *plugins_array = g_ptr_array_new(); 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); @@ -544,124 +825,19 @@ end: 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; + return plugin ? plugin->name : NULL; } const char *bt_plugin_get_author(struct bt_plugin *plugin) { - return plugin ? plugin->shared_lib_handle->author : NULL; + return plugin ? plugin->author : NULL; } const char *bt_plugin_get_license(struct bt_plugin *plugin) { - return plugin ? plugin->shared_lib_handle->license : NULL; + return plugin ? plugin->license : NULL; } const char *bt_plugin_get_path(struct bt_plugin *plugin) @@ -672,7 +848,7 @@ const char *bt_plugin_get_path(struct bt_plugin *plugin) const char *bt_plugin_get_description(struct bt_plugin *plugin) { - return plugin ? plugin->shared_lib_handle->description : NULL; + return plugin ? plugin->description : NULL; } int bt_plugin_get_component_class_count(struct bt_plugin *plugin) @@ -765,7 +941,7 @@ enum bt_plugin_status bt_plugin_add_component_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, + plugin->name, bt_component_class_get_name(comp_class), bt_component_class_get_type(comp_class)); goto error; diff --git a/plugins/ctf/fs/fs.h b/plugins/ctf/fs/fs.h index 35fbee90..2c0972e6 100644 --- a/plugins/ctf/fs/fs.h +++ b/plugins/ctf/fs/fs.h @@ -32,7 +32,6 @@ #include #include "data-stream.h" -#define CTF_FS_COMPONENT_NAME "fs" #define CTF_FS_COMPONENT_DESCRIPTION \ "Component used to read a CTF trace located on a file system." diff --git a/plugins/ctf/lttng-live/lttng-live-internal.h b/plugins/ctf/lttng-live/lttng-live-internal.h index 3f5b9172..4891b0d2 100644 --- a/plugins/ctf/lttng-live/lttng-live-internal.h +++ b/plugins/ctf/lttng-live/lttng-live-internal.h @@ -30,7 +30,6 @@ #include #include -#define LTTNG_LIVE_COMPONENT_NAME "lttng-live" #define LTTNG_LIVE_COMPONENT_DESCRIPTION "Component implementing an LTTng-live client." BT_HIDDEN diff --git a/plugins/ctf/plugin.c b/plugins/ctf/plugin.c index 36730869..ff168d69 100644 --- a/plugins/ctf/plugin.c +++ b/plugins/ctf/plugin.c @@ -31,15 +31,16 @@ #include "lttng-live/lttng-live-internal.h" /* Initialize plug-in description. */ -BT_PLUGIN_NAME("ctf"); +BT_PLUGIN(ctf); BT_PLUGIN_DESCRIPTION("Built-in Babeltrace plug-in providing CTF read support."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); /* Declare component classes implemented by this plug-in. */ -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_COMPONENT_CLASS_SOURCE_ENTRY(CTF_FS_COMPONENT_NAME, - CTF_FS_COMPONENT_DESCRIPTION, ctf_fs_init) -BT_PLUGIN_COMPONENT_CLASS_SOURCE_ENTRY(LTTNG_LIVE_COMPONENT_NAME, - LTTNG_LIVE_COMPONENT_DESCRIPTION, lttng_live_init) -BT_PLUGIN_COMPONENT_CLASSES_END +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_SOURCE, fs, ctf_fs_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_SOURCE, fs, + CTF_FS_COMPONENT_DESCRIPTION); +BT_PLUGIN_COMPONENT_CLASS_WITH_ID(auto, lttng_live, + BT_COMPONENT_TYPE_SOURCE, "lttng-live", lttng_live_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION_WITH_ID(auto, lttng_live, + BT_COMPONENT_TYPE_SOURCE, LTTNG_LIVE_COMPONENT_DESCRIPTION); diff --git a/plugins/muxer/muxer.c b/plugins/muxer/muxer.c index 6cd355e5..2700be6e 100644 --- a/plugins/muxer/muxer.c +++ b/plugins/muxer/muxer.c @@ -90,13 +90,11 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("muxer"); +BT_PLUGIN(muxer); BT_PLUGIN_DESCRIPTION("Babeltrace Trace Muxer Plug-In."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); - -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_COMPONENT_CLASS_FILTER_ENTRY("muxer", - "Time-correlate multiple traces.", - muxer_component_init) -BT_PLUGIN_COMPONENT_CLASSES_END +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_FILTER, muxer, + muxer_component_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_FILTER, muxer, + "Time-correlate multiple traces."); diff --git a/plugins/text/text.c b/plugins/text/text.c index 2a8e7717..370fb2d3 100644 --- a/plugins/text/text.c +++ b/plugins/text/text.c @@ -40,8 +40,6 @@ #include #include "text.h" -#define PLUGIN_NAME "text" - static const char *plugin_options[] = { "output-path", @@ -224,8 +222,7 @@ bool check_param_exists(const char *key, struct bt_value *object, void *data) if (!bt_value_map_get(plugin_opt_map, key)) { fprintf(text->err, - "[warning] Parameter \"%s\" unknown to \"%s\" plugin\n", - key, PLUGIN_NAME); + "[warning] Parameter \"%s\" unknown to \"text\" plugin\n", key); } return true; } @@ -655,13 +652,11 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("text"); +BT_PLUGIN(text); BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); - -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -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 +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_SINK, text, + text_component_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_SINK, text, + "Formats CTF-IR to text. Formerly known as ctf-text."); diff --git a/plugins/trimmer/trimmer.c b/plugins/trimmer/trimmer.c index a29505d3..49be358b 100644 --- a/plugins/trimmer/trimmer.c +++ b/plugins/trimmer/trimmer.c @@ -385,13 +385,11 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("utils"); +BT_PLUGIN(utils); BT_PLUGIN_DESCRIPTION("Babeltrace Trace Trimmer Plug-In."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); - -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -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 +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_FILTER, trimmer, + trimmer_component_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_FILTER, trimmer, + "Ensure that trace notifications outside of a given range are filtered-out."); diff --git a/plugins/writer/writer.c b/plugins/writer/writer.c index e8b1fefd..971e6bf8 100644 --- a/plugins/writer/writer.c +++ b/plugins/writer/writer.c @@ -272,12 +272,11 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("writer"); +BT_PLUGIN(writer); BT_PLUGIN_DESCRIPTION("Babeltrace CTF-Writer output plug-in."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); - -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_COMPONENT_CLASS_SINK_ENTRY("writer", "Formats CTF-IR to CTF.", - writer_component_init) -BT_PLUGIN_COMPONENT_CLASSES_END +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_SINK, writer, + writer_component_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_SINK, writer, + "Formats CTF-IR to CTF."); diff --git a/tests/lib/test-plugin-plugins/Makefile.am b/tests/lib/test-plugin-plugins/Makefile.am index dc4b5a24..19098656 100644 --- a/tests/lib/test-plugin-plugins/Makefile.am +++ b/tests/lib/test-plugin-plugins/Makefile.am @@ -1,34 +1,17 @@ AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -COMMONLIBADD = \ - $(top_builddir)/lib/libbabeltrace.la \ - $(top_builddir)/formats/ctf/libbabeltrace-ctf.la -# It seems like Automake won't make Libtool create a shared object -# (which we need here since we're building plugins) with a noinst_ -# destination (no install). Indeed we don't want to install those test -# plugins. Libtool creates a shared object when it gets an -rpath -# argument. In this case, Libtool does not seem to care much about -# the actual argument, so we use / (because Libtool needs an absolute -# path), which in the end is not even part of the linked object's -# rpath. -# -# -module makes it possible to not use the `lib` prefix and it makes -# sure that all symbols are dynamically exported. -COMMONLDFLAGS = -rpath / -avoid-version -module - -noinst_LTLIBRARIES = plugin-minimal.la plugin-sfs.la plugin-invalid.la +noinst_LTLIBRARIES = plugin-minimal.la plugin-sfs.la # the minimal plugin plugin_minimal_la_SOURCES = minimal.c -plugin_minimal_la_LDFLAGS = $(COMMONLDFLAGS) -plugin_minimal_la_LIBADD = $(COMMONLIBADD) +plugin_minimal_la_LDFLAGS = -rpath / -avoid-version -module +plugin_minimal_la_LIBADD = \ + $(top_builddir)/lib/libbabeltrace.la \ + $(top_builddir)/formats/ctf/libbabeltrace-ctf.la # source/filter/sink plugin plugin_sfs_la_SOURCES = sfs.c -plugin_sfs_la_LDFLAGS = $(COMMONLDFLAGS) -plugin_sfs_la_LIBADD = $(COMMONLIBADD) - -# invalid plugin -plugin_invalid_la_SOURCES = invalid.c -plugin_invalid_la_LDFLAGS = $(COMMONLDFLAGS) -plugin_invalid_la_LIBADD = $(COMMONLIBADD) +plugin_sfs_la_LDFLAGS = -rpath / -avoid-version -module +plugin_sfs_la_LIBADD = \ + $(top_builddir)/lib/libbabeltrace.la \ + $(top_builddir)/formats/ctf/libbabeltrace-ctf.la diff --git a/tests/lib/test-plugin-plugins/invalid.c b/tests/lib/test-plugin-plugins/invalid.c deleted file mode 100644 index e57eb686..00000000 --- a/tests/lib/test-plugin-plugins/invalid.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017 Philippe Proulx - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -static enum bt_plugin_status plugin_init(struct bt_plugin *plugin) -{ - return BT_PLUGIN_STATUS_OK; -} - -static enum bt_plugin_status plugin_exit(void) -{ - return BT_PLUGIN_STATUS_OK; -} - -BT_PLUGIN_DESCRIPTION("Invalid plugin because the name is missing"); -BT_PLUGIN_AUTHOR("Janine Sutto"); -BT_PLUGIN_LICENSE("Beerware"); -BT_PLUGIN_INIT(plugin_init); -BT_PLUGIN_EXIT(plugin_exit); diff --git a/tests/lib/test-plugin-plugins/minimal.c b/tests/lib/test-plugin-plugins/minimal.c index b99c1fff..ddde63b0 100644 --- a/tests/lib/test-plugin-plugins/minimal.c +++ b/tests/lib/test-plugin-plugins/minimal.c @@ -34,7 +34,7 @@ static enum bt_plugin_status plugin_exit(void) return BT_PLUGIN_STATUS_OK; } -BT_PLUGIN_NAME("test-minimal"); +BT_PLUGIN(test_minimal); BT_PLUGIN_DESCRIPTION("Minimal Babeltrace plugin with no component classes"); BT_PLUGIN_AUTHOR("Janine Sutto"); BT_PLUGIN_LICENSE("Beerware"); diff --git a/tests/lib/test-plugin-plugins/sfs.c b/tests/lib/test-plugin-plugins/sfs.c index 3928be23..943efbeb 100644 --- a/tests/lib/test-plugin-plugins/sfs.c +++ b/tests/lib/test-plugin-plugins/sfs.c @@ -49,13 +49,16 @@ static enum bt_component_status comp_class_dummy_init( return BT_COMPONENT_STATUS_OK; } -BT_PLUGIN_NAME("test-sfs"); +BT_PLUGIN(test_sfs); BT_PLUGIN_DESCRIPTION("Babeltrace plugin with source, sink, and filter component classes"); BT_PLUGIN_AUTHOR("Janine Sutto"); BT_PLUGIN_LICENSE("Beerware"); -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_COMPONENT_CLASS_SOURCE_ENTRY("source", "A source", comp_class_dummy_init) -BT_PLUGIN_COMPONENT_CLASS_SINK_ENTRY("sink", "A sink", comp_class_sink_init) -BT_PLUGIN_COMPONENT_CLASS_FILTER_ENTRY("filter", "A filter", comp_class_dummy_init) -BT_PLUGIN_COMPONENT_CLASSES_END +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_SOURCE, source, comp_class_dummy_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_SOURCE, source, "A source."); + +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_SINK, sink, comp_class_sink_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_SINK, sink, "A sink."); + +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_FILTER, filter, comp_class_dummy_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_FILTER, filter, "A filter."); diff --git a/tests/lib/test_plugin.c b/tests/lib/test_plugin.c index e5261729..9b4ea84f 100644 --- a/tests/lib/test_plugin.c +++ b/tests/lib/test_plugin.c @@ -58,22 +58,16 @@ static char *get_test_plugin_path(const char *plugin_dir, static void test_invalid(const char *plugin_dir) { - struct bt_plugin *plugin; - char *invalid_path = get_test_plugin_path(plugin_dir, "invalid");; - - assert(invalid_path); - - plugin = bt_plugin_create_from_file(NON_EXISTING_PATH); - ok(!plugin, "bt_plugin_create_from_file() fails with a non-existing file"); + struct bt_plugin **plugins; - plugin = bt_plugin_create_from_file(plugin_dir); - ok(!plugin, "bt_plugin_create_from_file() fails with a directory"); + plugins = bt_plugin_create_all_from_file(NON_EXISTING_PATH); + ok(!plugins, "bt_plugin_create_all_from_file() fails with a non-existing file"); - plugin = bt_plugin_create_from_file(invalid_path); - ok(!plugin, "bt_plugin_create_from_file() fails with an invalid plugin file"); + plugins = bt_plugin_create_all_from_file(plugin_dir); + ok(!plugins, "bt_plugin_create_all_from_file() fails with a directory"); - ok(!bt_plugin_create_from_file(NULL), - "bt_plugin_create_from_file() handles NULL correctly"); + ok(!bt_plugin_create_all_from_file(NULL), + "bt_plugin_create_all_from_file() handles NULL correctly"); ok(!bt_plugin_create_all_from_dir(NULL, false), "bt_plugin_create_all_from_dir() handles NULL correctly"); ok(!bt_plugin_get_name(NULL), @@ -92,12 +86,11 @@ static void test_invalid(const char *plugin_dir) "bt_plugin_get_component_class() handles NULL correctly"); ok(!bt_plugin_get_component_class_by_name_and_type(NULL, NULL, 0), "bt_plugin_get_component_class_by_name_and_type() handles NULL correctly"); - - free(invalid_path); } static void test_minimal(const char *plugin_dir) { + struct bt_plugin **plugins; struct bt_plugin *plugin; char *minimal_path = get_test_plugin_path(plugin_dir, "minimal"); @@ -105,11 +98,13 @@ static void test_minimal(const char *plugin_dir) diag("minimal plugin test below"); reset_test_plugin_symbols(); - plugin = bt_plugin_create_from_file(minimal_path); - ok(plugin, "bt_plugin_create_from_file() succeeds with a valid file"); - ok(test_plugin_init_called && !test_plugin_exit_called, - "plugin's initialization function is called during bt_plugin_create_from_file()"); - ok(strcmp(bt_plugin_get_name(plugin), "test-minimal") == 0, + plugins = bt_plugin_create_all_from_file(minimal_path); + ok(plugins && plugins[0], "bt_plugin_create_all_from_file() succeeds with a valid file"); + ok(test_plugin_init_called, "plugin's initialization function is called during bt_plugin_create_all_from_file()"); + ok(plugins && plugins[0] && !plugins[1], + "bt_plugin_create_all_from_file() returns the expected number of plugins"); + plugin = plugins[0]; + ok(strcmp(bt_plugin_get_name(plugin), "test_minimal") == 0, "bt_plugin_get_name() returns the expected name"); ok(strcmp(bt_plugin_get_description(plugin), "Minimal Babeltrace plugin with no component classes") == 0, @@ -126,10 +121,12 @@ static void test_minimal(const char *plugin_dir) ok(test_plugin_exit_called, "plugin's exit function is called when the plugin is destroyed"); free(minimal_path); + free(plugins); } static void test_sfs(const char *plugin_dir) { + struct bt_plugin **plugins; struct bt_plugin *plugin; struct bt_component_class *sink_comp_class; struct bt_component_class *source_comp_class; @@ -140,8 +137,9 @@ static void test_sfs(const char *plugin_dir) assert(sfs_path); diag("sfs plugin test below"); - plugin = bt_plugin_create_from_file(sfs_path); - assert(plugin); + plugins = bt_plugin_create_all_from_file(sfs_path); + assert(plugins && plugins[0]); + plugin = plugins[0]; ok(bt_plugin_get_component_class_count(plugin) == 3, "bt_plugin_get_component_class_count() returns the expected value"); @@ -180,6 +178,7 @@ static void test_sfs(const char *plugin_dir) BT_PUT(sink_component); free(sfs_path); + free(plugins); } static void test_create_all_from_dir(const char *plugin_dir) -- 2.34.1