Add support for statically-built plug-ins
[babeltrace.git] / lib / plugin-system / component-factory.c
index 6d76029170232457f515cbb730ee6d68ba86b1fc..471b4b877a26b350ce261c83a8a1f345e40019f9 100644 (file)
@@ -39,6 +39,7 @@
 #include <sys/stat.h>
 #include <gmodule.h>
 #include <stdbool.h>
+#include <dirent.h>
 
 #define NATIVE_PLUGIN_SUFFIX ".so"
 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
@@ -47,6 +48,8 @@
 #define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
                sizeof(LIBTOOL_PLUGIN_SUFFIX))
 
+DECLARE_PLUG_IN_SECTIONS;
+
 /* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
 static
 struct dirent *alloc_dirent(const char *path)
@@ -64,13 +67,36 @@ struct dirent *alloc_dirent(const char *path)
        return entry;
 }
 
+static
+enum bt_component_factory_status init_plugin(
+               struct bt_component_factory *factory, struct bt_plugin *plugin)
+{
+       enum bt_component_status component_status;
+       enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+
+       BT_MOVE(factory->current_plugin, plugin);
+       component_status = bt_plugin_register_component_classes(
+                       factory->current_plugin, factory);
+       BT_PUT(factory->current_plugin);
+       if (component_status != BT_COMPONENT_STATUS_OK) {
+               switch (component_status) {
+               case BT_COMPONENT_STATUS_NOMEM:
+                       ret = BT_COMPONENT_FACTORY_STATUS_NOMEM;
+                       break;
+               default:
+                       ret = BT_COMPONENT_FACTORY_STATUS_ERROR;
+                       break;
+               }
+       }
+       return ret;
+}
+
 static
 enum bt_component_factory_status
 bt_component_factory_load_file(struct bt_component_factory *factory,
                const char *path)
 {
        enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
-       enum bt_component_status component_status;
        size_t path_len;
        GModule *module;
        struct bt_plugin *plugin;
@@ -106,39 +132,22 @@ bt_component_factory_load_file(struct bt_component_factory *factory,
 
        module = g_module_open(path, 0);
        if (!module) {
-               printf_error("Module open error: %s", g_module_error());
+               printf_verbose("Module open error: %s\n", g_module_error());
                ret = BT_COMPONENT_FACTORY_STATUS_ERROR;
                goto end;
        }
 
-       /* Load plugin and make sure it defines the required entry points */
-       plugin = bt_plugin_create(module, path);
+       /* Load plugin and make sure it defines the required entry points. */
+       plugin = bt_plugin_create_from_module(module, path);
        if (!plugin) {
                ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN;
                if (!g_module_close(module)) {
-                       printf_error("Module close error: %s",
+                       printf_error("Module close error: %s\n",
                                g_module_error());
                }
                goto end;
        }
-
-       factory->current_plugin = plugin;
-       component_status = bt_plugin_register_component_classes(plugin,
-                       factory);
-       factory->current_plugin = NULL;
-       if (component_status != BT_COMPONENT_STATUS_OK) {
-               switch (component_status) {
-               case BT_COMPONENT_STATUS_NOMEM:
-                       ret = BT_COMPONENT_FACTORY_STATUS_NOMEM;
-                       break;
-               default:
-                       ret = BT_COMPONENT_FACTORY_STATUS_ERROR;
-                       break;
-               }
-
-               BT_PUT(plugin);
-               goto end;
-       }
+       ret = init_plugin(factory, plugin);
 end:
        return ret;
 }
@@ -318,6 +327,7 @@ struct bt_component_class *bt_component_factory_get_component_class(
                if (type != BT_COMPONENT_TYPE_UNKNOWN) {
                        if (type != bt_component_class_get_type(
                                        component_class)) {
+                               bt_put(plugin);
                                continue;
                        }
                }
@@ -328,6 +338,7 @@ struct bt_component_class *bt_component_factory_get_component_class(
 
                        assert(cur_plugin_name);
                        if (strcmp(plugin_name, cur_plugin_name)) {
+                               bt_put(plugin);
                                continue;
                        }
                }
@@ -338,10 +349,12 @@ struct bt_component_class *bt_component_factory_get_component_class(
 
                        assert(cur_cc_name);
                        if (strcmp(component_name, cur_cc_name)) {
+                               bt_put(plugin);
                                continue;
                        }
                }
 
+               bt_put(plugin);
                /* All criteria met. */
                goto match;
        }
@@ -394,23 +407,78 @@ enum bt_component_factory_status bt_component_factory_load(
        return _bt_component_factory_load(factory, path, false);
 }
 
+enum bt_component_factory_status bt_component_factory_load_static(
+               struct bt_component_factory *factory)
+{
+       size_t count, i;
+       enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+
+       PRINT_PLUG_IN_SECTIONS(printf_verbose);
+
+       count = SECTION_ELEMENT_COUNT(__plugin_register_funcs);
+       if (SECTION_ELEMENT_COUNT(__plugin_register_funcs) != count ||
+                       SECTION_ELEMENT_COUNT(__plugin_names) != count ||
+                       SECTION_ELEMENT_COUNT(__plugin_authors) != count ||
+                       SECTION_ELEMENT_COUNT(__plugin_licenses) != count ||
+                       SECTION_ELEMENT_COUNT(__plugin_descriptions) != count) {
+               printf_error("Some statically-linked plug-ins do not define all mandatory symbols\n");
+               ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN;
+               goto end;
+       }
+       printf_verbose("Detected %zu statically-linked plug-ins\n", count);
+
+       for (i = 0; i < count; i++) {
+               struct bt_plugin *plugin = bt_plugin_create_from_static(i);
+
+               if (!plugin) {
+                       continue;
+               }
+
+               (void) init_plugin(factory, plugin);
+       }
+end:
+       return ret;
+}
+
 static
 enum bt_component_factory_status
 add_component_class(struct bt_component_factory *factory, const char *name,
                    const char *description, bt_component_init_cb init,
                    enum bt_component_type type)
 {
-       struct bt_component_class *class;
+       struct bt_component_class *component_class;
        enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
 
        if (!factory || !name || !init) {
                ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
                goto end;
        }
+       assert(factory->current_plugin);
+
+       /*
+        * Ensure this component class does not clash with a currently
+        * registered class.
+        */
+       component_class = bt_component_factory_get_component_class(factory,
+               bt_plugin_get_name(factory->current_plugin), type, name);
+       if (component_class) {
+               struct bt_plugin *plugin = bt_component_class_get_plugin(
+                       component_class);
+
+               printf_warning("Duplicate component class registration attempted. Component class %s being registered by plugin %s (path: %s) conflicts with one already registered by plugin %s (path: %s)",
+                       name, bt_plugin_get_name(factory->current_plugin),
+                       bt_plugin_get_path(factory->current_plugin),
+                       bt_plugin_get_name(plugin),
+                       bt_plugin_get_path(plugin));
+               ret = BT_COMPONENT_FACTORY_STATUS_DUPLICATE;
+               BT_PUT(component_class);
+               bt_put(plugin);
+               goto end;
+       }
 
-       class = bt_component_class_create(type, name, description,
-                       factory->current_plugin);
-       g_ptr_array_add(factory->component_classes, class);
+       component_class = bt_component_class_create(type, name, description,
+                       init, factory->current_plugin);
+       g_ptr_array_add(factory->component_classes, component_class);
 end:
        return ret;
 }
@@ -432,3 +500,12 @@ bt_component_factory_register_sink_component_class(
        return add_component_class(factory, name, description, init,
                        BT_COMPONENT_TYPE_SINK);
 }
+
+enum bt_component_factory_status
+bt_component_factory_register_filter_component_class(
+               struct bt_component_factory *factory, const char *name,
+               const char *description, bt_component_init_cb init)
+{
+       return add_component_class(factory, name, description, init,
+                       BT_COMPONENT_TYPE_FILTER);
+}
This page took 0.027366 seconds and 4 git commands to generate.