X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Fcomponent-factory.c;h=65840d4cac79e883b6a025846d2405b099b3d9a2;hb=7c7c0433f4507935fbe2adab29d942df22ee8168;hp=b4ebe3f2ef9f0ac57abae257bdfac92a9f30c63a;hpb=f3e4505ba1b7bacce5fc1cc942f4cfaa905b4e74;p=babeltrace.git diff --git a/plugins/component-factory.c b/plugins/component-factory.c index b4ebe3f2..65840d4c 100644 --- a/plugins/component-factory.c +++ b/plugins/component-factory.c @@ -28,32 +28,24 @@ #include #include +#include +#include +#include #include #include +#include #include #include #include +#include +#include #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 @@ -78,8 +70,11 @@ 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; + bool is_libtool_wrapper = false, is_shared_object = false; if (!factory || !path) { ret = BT_COMPONENT_FACTORY_STATUS_INVAL; @@ -88,6 +83,7 @@ bt_component_factory_load_file(struct bt_component_factory *factory, path_len = strlen(path); if (path_len <= PLUGIN_SUFFIX_LEN) { + ret = BT_COMPONENT_FACTORY_STATUS_INVAL; goto end; } @@ -96,23 +92,53 @@ bt_component_factory_load_file(struct bt_component_factory *factory, * Check if the file ends with a known plugin file type suffix (i.e. .so * 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. */ + is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX, + path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN, + LIBTOOL_PLUGIN_SUFFIX_LEN); + is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX, + path + path_len - NATIVE_PLUGIN_SUFFIX_LEN, + NATIVE_PLUGIN_SUFFIX_LEN); + if (!is_shared_object && !is_libtool_wrapper) { + /* 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; + } + + /* Load plugin and make sure it defines the required entry points */ + plugin = bt_plugin_create(module, path); + 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; } - /* Check if the module defines the appropriate entry points */ + 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; + } end: return ret; } @@ -151,11 +177,25 @@ bt_component_factory_load_dir_recursive(struct bt_component_factory *factory, file_path[path_len++] = '/'; } + directory = opendir(file_path); + if (!directory) { + perror("Failed to open plug-in directory"); + ret = BT_COMPONENT_FACTORY_STATUS_ERROR; + goto end; + } + /* Recursively walk directory */ while (!readdir_r(directory, entry, &result) && result) { struct stat st; int stat_ret; - size_t file_name_len = strlen(result->d_name); + size_t file_name_len; + + if (result->d_name[0] == '.') { + /* Skip hidden files, . and .. */ + continue; + } + + file_name_len = strlen(result->d_name); if (path_len + file_name_len >= PATH_MAX) { continue; @@ -173,35 +213,44 @@ bt_component_factory_load_dir_recursive(struct bt_component_factory *factory, 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: + if (directory) { + if (closedir(directory)) { + /* + * We don't want to override the error since there is + * nothing could do. + */ + perror("Failed to close plug-in directory"); + } + } free(entry); free(file_path); 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->component_classes) { + g_ptr_array_free(factory->component_classes, 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; @@ -210,56 +259,162 @@ bt_component_factory_create(void) goto end; } - factory->modules = g_ptr_array_new_with_free_func(module_close); - if (!factory->modules) { - goto error; - } - - factory->components = g_ptr_array_new_with_free_func(factory_destroy); - if (factory->components) { + bt_object_init(factory, bt_component_factory_destroy); + factory->component_classes = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_put); + if (!factory->component_classes) { goto error; } end: return factory; error: - bt_component_factory_destroy(factory); + BT_PUT(factory); + return factory; +} + +int bt_component_factory_get_component_class_count( + struct bt_component_factory *factory) +{ + return factory ? factory->component_classes->len : -1; +} + +struct bt_component_class *bt_component_factory_get_component_class_index( + struct bt_component_factory *factory, int index) +{ + struct bt_component_class *component_class = NULL; + + if (!factory || index < 0 || index >= factory->component_classes->len) { + goto end; + } + + component_class = bt_get(g_ptr_array_index( + factory->component_classes, index)); +end: + return component_class; +} + +struct bt_component_class *bt_component_factory_get_component_class( + struct bt_component_factory *factory, + const char *plugin_name, enum bt_component_type type, + const char *component_name) +{ + size_t i; + struct bt_component_class *component_class = NULL; + + if (!factory || (!plugin_name && !component_name && + type == BT_COMPONENT_TYPE_UNKNOWN)) { + /* At least one criterion must be provided. */ + goto no_match; + } + + for (i = 0; i < factory->component_classes->len; i++) { + struct bt_plugin *plugin = NULL; + + component_class = g_ptr_array_index(factory->component_classes, + i); + plugin = bt_component_class_get_plugin(component_class); + assert(plugin); + + if (type != BT_COMPONENT_TYPE_UNKNOWN) { + if (type != bt_component_class_get_type( + component_class)) { + continue; + } + } + + if (plugin_name) { + const char *cur_plugin_name = bt_plugin_get_name( + plugin); + + assert(cur_plugin_name); + if (strcmp(plugin_name, cur_plugin_name)) { + continue; + } + } + + if (component_name) { + const char *cur_cc_name = bt_component_class_get_name( + component_class); + + assert(cur_cc_name); + if (strcmp(component_name, cur_cc_name)) { + continue; + } + } + + /* All criteria met. */ + goto match; + } + +no_match: return NULL; +match: + return bt_get(component_class); } 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; +} + +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; + enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK; + + if (!factory || !name || !init) { + ret = BT_COMPONENT_FACTORY_STATUS_INVAL; + goto end; } + + class = bt_component_class_create(type, name, description, + factory->current_plugin); + g_ptr_array_add(factory->component_classes, class); +end: return ret; } + +enum bt_component_factory_status +bt_component_factory_register_source_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_SOURCE); +} + +enum bt_component_factory_status +bt_component_factory_register_sink_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_SINK); +}