#include <babeltrace/plugin/component-factory-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/compiler.h>
+#include <babeltrace/ref.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
+#include <gmodule.h>
#define NATIVE_PLUGIN_SUFFIX ".so"
#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
#define LIBTOOL_PLUGIN_SUFFIX ".la"
#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
-#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX),\
- sizeof(LIBTOOL_PLUGIN_SUFFIX))
-
-static
-void module_close(gpointer data)
-{
- if (g_module_close((GModule *) data)) {
- printf_error("Failed to close plugin");
- }
-}
-
-static
-void factory_destroy(gpointer data)
-{
- bt_component_factory_destroy((struct bt_component_factory *)data);
-}
+#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
+ sizeof(LIBTOOL_PLUGIN_SUFFIX))
/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
static
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;
if (!factory || !path) {
ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
path_len = strlen(path);
if (path_len <= PLUGIN_SUFFIX_LEN) {
+ ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
goto end;
}
* or .la on Linux).
*/
if (strncmp(NATIVE_PLUGIN_SUFFIX,
- path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
- NATIVE_PLUGIN_SUFFIX_LEN) &&
- strncmp(LIBTOOL_PLUGIN_SUFFIX,
- path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
- LIBTOOL_PLUGIN_SUFFIX_LEN)) {
- /* Not a plugin file. */
+ path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
+ NATIVE_PLUGIN_SUFFIX_LEN) &&
+ strncmp(LIBTOOL_PLUGIN_SUFFIX,
+ path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
+ LIBTOOL_PLUGIN_SUFFIX_LEN)) {
+ /* Name indicates that this is not a plugin file. */
+ ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
goto end;
}
module = g_module_open(path, 0);
if (!module) {
printf_error("Module open error: %s", g_module_error());
+ ret = BT_COMPONENT_FACTORY_STATUS_ERROR;
goto end;
}
- /* Check if the module defines the appropriate entry points */
+ /* Load plugin and make sure it defines the required entry points */
+ plugin = bt_plugin_create(module);
+ if (!plugin) {
+ ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN;
+ if (!g_module_close(module)) {
+ printf_error("Module close error: %s",
+ g_module_error());
+ }
+ goto end;
+ }
+
+ component_status = bt_plugin_register_component_classes(plugin,
+ factory);
+ 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;
+ }
+ g_ptr_array_add(factory->plugins, plugin);
end:
return ret;
}
if (S_ISDIR(st.st_mode)) {
ret = bt_component_factory_load_dir_recursive(factory,
- file_path);
+ file_path);
if (ret != BT_COMPONENT_FACTORY_STATUS_OK) {
goto end;
}
} else if (S_ISREG(st.st_mode)) {
- ret = bt_component_factory_load_file(factory,
- file_path);
- if (ret != BT_COMPONENT_FACTORY_STATUS_OK) {
- goto end;
- }
+ bt_component_factory_load_file(factory, file_path);
}
}
end:
return ret;
}
-void bt_component_factory_destroy(struct bt_component_factory *factory)
+static
+void bt_component_factory_destroy(struct bt_object *obj)
{
- if (!factory) {
- return;
- }
+ struct bt_component_factory *factory = NULL;
+
+ assert(obj);
+ factory = container_of(obj, struct bt_component_factory, base);
+ if (factory->plugins) {
+ g_ptr_array_free(factory->plugins, TRUE);
+ }
+ if (factory->components) {
+ g_ptr_array_free(factory->components, TRUE);
+ }
g_free(factory);
}
-struct bt_component_factory *
-bt_component_factory_create(void)
+struct bt_component_factory *bt_component_factory_create(void)
{
struct bt_component_factory *factory;
goto end;
}
- factory->modules = g_ptr_array_new_with_free_func(module_close);
- if (!factory->modules) {
+ bt_object_init(factory, bt_component_factory_destroy);
+ factory->plugins = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_put);
+ if (!factory->plugins) {
goto error;
}
-
- factory->components = g_ptr_array_new_with_free_func(factory_destroy);
- if (factory->components) {
+ factory->components = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_put);
+ if (!factory->components) {
goto error;
}
end:
return factory;
error:
- bt_component_factory_destroy(factory);
- return NULL;
+ BT_PUT(factory);
+ return factory;
}
enum bt_component_factory_status bt_component_factory_load(
struct bt_component_factory *factory, const char *path)
{
enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
- DIR *directory = NULL;
if (!factory || !path) {
ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
goto end;
}
- directory = opendir(path) ;
- if (!directory) {
- switch (errno) {
- case ENOTDIR:
- /* Try loading as a file. */
- break;
- case ENOENT:
- ret = BT_COMPONENT_FACTORY_STATUS_NOENT;
- goto end;
- default:
- ret = BT_COMPONENT_FACTORY_STATUS_IO;
- goto end;
- }
+ if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
+ ret = BT_COMPONENT_FACTORY_STATUS_NOENT;
+ goto end;
}
- if (directory) {
+ if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
ret = bt_component_factory_load_dir_recursive(factory, path);
- } else {
+ } else if (g_file_test(path, G_FILE_TEST_IS_REGULAR) ||
+ g_file_test(path, G_FILE_TEST_IS_SYMLINK)) {
ret = bt_component_factory_load_file(factory, path);
+ } else {
+ ret = BT_COMPONENT_FACTORY_STATUS_INVAL;
+ goto end;
}
end:
- if (directory) {
- closedir(directory);
- }
return ret;
}