Refactor the plugin registration and loading machinery
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 21 Jan 2017 06:16:20 +0000 (01:16 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 28 May 2017 16:57:37 +0000 (12:57 -0400)
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 <eeppeliteloop@gmail.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
17 files changed:
include/babeltrace/plugin/plugin-dev.h
include/babeltrace/plugin/plugin-internal.h
include/babeltrace/plugin/plugin.h
lib/component/component-class.c
lib/plugin/plugin.c
plugins/ctf/fs/fs.h
plugins/ctf/lttng-live/lttng-live-internal.h
plugins/ctf/plugin.c
plugins/muxer/muxer.c
plugins/text/text.c
plugins/trimmer/trimmer.c
plugins/writer/writer.c
tests/lib/test-plugin-plugins/Makefile.am
tests/lib/test-plugin-plugins/invalid.c [deleted file]
tests/lib/test-plugin-plugins/minimal.c
tests/lib/test-plugin-plugins/sfs.c
tests/lib/test_plugin.c

index ffa39bb5e2a19fca65f241c19c2ee003013d5639..387cf89eca26e441a7c5769283491fab8ff4b42e 100644 (file)
@@ -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 <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
 }
index 0509be4485dd32d844459c4f3e861a3cff9f3666..ac0217207bcfca61f068df44cc083d43f151afbc 100644 (file)
@@ -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 */
index 10581984f9519cc69ad08a054a0840a67d492396..66436dfb47dbd44eab11d92ad5f1bbab6cc0bfda 100644 (file)
@@ -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);
index 1e1e8388c8ca7e8f5a5313ac20911ab949f89992..660964c2de3b4d5f5f86dcd0f68a139ba40694fa 100644 (file)
@@ -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
index e1e0387b373451a6fc1beb417b4a6e0044fa9e30..5a72b42e49283f944299f3ad624bb4fe9fc068fb 100644 (file)
 #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
@@ -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;
index 35fbee90f839cb3278610eb0380483e9977fd361..2c0972e6da91fd5c8b2efc3c4411ba1b0c066f12 100644 (file)
@@ -32,7 +32,6 @@
 #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."
 
index 3f5b9172a288d6c8c73ff235060d26e60d49894b..4891b0d256bd7aae9509337a2e5f53f61f1c7ccd 100644 (file)
@@ -30,7 +30,6 @@
 #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
index 36730869392ec50990938e228d20ac178c73ec95..ff168d691c901fbfff377dcde2e870d70f18a3bf 100644 (file)
 #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);
index 6cd355e5c94a85939ff6fa59d5182428e717bcb2..2700be6ed5671e5613842712a1d28e48d6f1012b 100644 (file)
@@ -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.");
index 2a8e771773fe067f8d9dc83145e06fd5fddb1b47..370fb2d3478fdb9892e57d916314893a6a714be4 100644 (file)
@@ -40,8 +40,6 @@
 #include <glib.h>
 #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.");
index a29505d32806e00079cc8288e5fce51dc522a42d..49be358b621d58831e242a25b37411d87bf79255 100644 (file)
@@ -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.");
index e8b1fefdba118920d20f08a93834fb236da60823..971e6bf8a61b26facedce6ac3b1daddd16c107c8 100644 (file)
@@ -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.");
index dc4b5a2486fef3b80cfa632ca3f4f1bc9e86b686..1909865637c5a8eda993d1f0fd1d5481bf0609c0 100644 (file)
@@ -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 (file)
index e57eb68..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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);
index b99c1fffbecb87dbc6c378074642fd25d3b416a0..ddde63b010320a74565adeed467b7cd973af35b5 100644 (file)
@@ -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");
index 3928be23179ac8baaaf0cf3a050fd095c7ebe4aa..943efbebf25b8f9f2ab47cf602bc521f7656b90e 100644 (file)
@@ -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.");
index e52617290793897c631bb13f3e864a8a6d8af1c0..9b4ea84f706ccb4beda87832b6ed6734a85e5453 100644 (file)
@@ -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)
This page took 0.049142 seconds and 4 git commands to generate.