#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.
* SOFTWARE.
*/
+#include <stdint.h>
#include <babeltrace/plugin/plugin.h>
#include <babeltrace/component/component-class.h>
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
}
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;
};
/* 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 */
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);
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) {
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) {
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
#include <sys/stat.h>
#include <dirent.h>
-#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 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
*
* 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:
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);
}
}
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;
}
- 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:
}
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++;
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 */
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;
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);
}
}
}
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);
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)
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)
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;
#include <babeltrace/component/component.h>
#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."
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/component/component.h>
-#define LTTNG_LIVE_COMPONENT_NAME "lttng-live"
#define LTTNG_LIVE_COMPONENT_DESCRIPTION "Component implementing an LTTng-live client."
BT_HIDDEN
#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);
}
/* 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.");
#include <glib.h>
#include "text.h"
-#define PLUGIN_NAME "text"
-
static
const char *plugin_options[] = {
"output-path",
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;
}
}
/* 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.");
}
/* 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.");
}
/* 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.");
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
+++ /dev/null
-/*
- * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * 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 <babeltrace/plugin/plugin-dev.h>
-
-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);
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");
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.");
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),
"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");
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,
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;
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");
BT_PUT(sink_component);
free(sfs_path);
+ free(plugins);
}
static void test_create_all_from_dir(const char *plugin_dir)