X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fplugin%2Fplugin.c;h=59b8727381c2c59efa39d183bb1e91544c5c68f7;hb=f6ccaed94e575af57fe6bf38154771bee4871a2a;hp=4a36fd697c1ef30bf2d8d866cfa4e3bcc9972793;hpb=1aec753b3c82eebcb343a19f056db2a780524186;p=babeltrace.git diff --git a/lib/plugin/plugin.c b/lib/plugin/plugin.c index 4a36fd69..59b87273 100644 --- a/lib/plugin/plugin.c +++ b/lib/plugin/plugin.c @@ -27,55 +27,87 @@ * SOFTWARE. */ +#define BT_LOG_TAG "PLUGIN" +#include + #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include #include +#include #include -#include +#include +#include #define PYTHON_PLUGIN_PROVIDER_FILENAME "libbabeltrace-python-plugin-provider." G_MODULE_SUFFIX #define PYTHON_PLUGIN_PROVIDER_SYM_NAME bt_plugin_python_create_all_from_file #define PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR TOSTRING(PYTHON_PLUGIN_PROVIDER_SYM_NAME) +#define APPEND_ALL_FROM_DIR_NFDOPEN_MAX 8 + #ifdef BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT #include + static struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path) = bt_plugin_python_create_all_from_file; + +static +void init_python_plugin_provider(void) {} #else /* BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT */ static GModule *python_plugin_provider_module; static struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path); -__attribute__((constructor)) static +static void init_python_plugin_provider(void) { + if (bt_plugin_python_create_all_from_file_sym != NULL) { + return; + } + + BT_LOGD_STR("Loading Python plugin provider module."); python_plugin_provider_module = - g_module_open(PYTHON_PLUGIN_PROVIDER_FILENAME, - G_MODULE_BIND_LOCAL); + g_module_open(PYTHON_PLUGIN_PROVIDER_FILENAME, 0); if (!python_plugin_provider_module) { - printf_verbose("Cannot find `%s`: Python plugin support is disabled\n", - PYTHON_PLUGIN_PROVIDER_FILENAME); + BT_LOGI("Cannot open `%s`: %s: continuing without Python plugin support.", + PYTHON_PLUGIN_PROVIDER_FILENAME, g_module_error()); return; } if (!g_module_symbol(python_plugin_provider_module, PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR, (gpointer) &bt_plugin_python_create_all_from_file_sym)) { - printf_verbose("Cannot find the Python plugin provider loading symbole: Python plugin support is disabled\n"); + BT_LOGI("Cannot find the Python plugin provider loading symbol: continuing without Python plugin support: " + "file=\"%s\", symbol=\"%s\"", + PYTHON_PLUGIN_PROVIDER_FILENAME, + PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR); + return; } + + BT_LOGI("Loaded Python plugin provider module: addr=%p", + python_plugin_provider_module); } __attribute__((destructor)) static void fini_python_plugin_provider(void) { if (python_plugin_provider_module) { - (void) g_module_close(python_plugin_provider_module); + BT_LOGD("Unloading Python plugin provider module."); + + if (!g_module_close(python_plugin_provider_module)) { + BT_LOGE("Failed to close the Python plugin provider module: %s.", + g_module_error()); + } + python_plugin_provider_module = NULL; } } @@ -87,6 +119,7 @@ int64_t bt_plugin_set_get_plugin_count(struct bt_plugin_set *plugin_set) int64_t count = -1; if (!plugin_set) { + BT_LOGW_STR("Invalid parameter: plugin set is NULL."); goto end; } @@ -102,7 +135,15 @@ struct bt_plugin *bt_plugin_set_get_plugin(struct bt_plugin_set *plugin_set, { struct bt_plugin *plugin = NULL; - if (!plugin_set || index >= plugin_set->plugins->len) { + if (!plugin_set) { + BT_LOGW_STR("Invalid parameter: plugin set is NULL."); + goto end; + } + + if (index >= plugin_set->plugins->len) { + BT_LOGW("Invalid parameter: index is out of bounds: " + "addr=%p, index=%" PRIu64 ", count=%u", + plugin_set, index, plugin_set->plugins->len); goto end; } @@ -114,6 +155,7 @@ end: struct bt_plugin_set *bt_plugin_create_all_from_static(void) { + /* bt_plugin_so_create_all_from_static() logs errors */ return bt_plugin_so_create_all_from_static(); } @@ -122,10 +164,11 @@ struct bt_plugin_set *bt_plugin_create_all_from_file(const char *path) struct bt_plugin_set *plugin_set = NULL; if (!path) { + BT_LOGW_STR("Invalid parameter: path is NULL."); goto end; } - printf_verbose("Trying to load plugins from `%s`\n", path); + BT_LOGD("Creating plugins from file: path=\"%s\"", path); /* Try shared object plugins */ plugin_set = bt_plugin_so_create_all_from_file(path); @@ -134,6 +177,7 @@ struct bt_plugin_set *bt_plugin_create_all_from_file(const char *path) } /* Try Python plugins if support is available */ + init_python_plugin_provider(); if (bt_plugin_python_create_all_from_file_sym) { plugin_set = bt_plugin_python_create_all_from_file_sym(path); if (plugin_set) { @@ -142,6 +186,15 @@ struct bt_plugin_set *bt_plugin_create_all_from_file(const char *path) } end: + if (plugin_set) { + BT_LOGD("Created %u plugins from file: " + "path=\"%s\", count=%u, plugin-set-addr=%p", + plugin_set->plugins->len, path, + plugin_set->plugins->len, plugin_set); + } else { + BT_LOGD("Found no plugins in file: path=\"%s\"", path); + } + return plugin_set; } @@ -162,11 +215,15 @@ struct bt_plugin *bt_plugin_find(const char *plugin_name) size_t i, j; if (!plugin_name) { + BT_LOGW_STR("Invalid parameter: plugin name is NULL."); goto end; } + BT_LOGD("Finding named plugin in standard directories and built-in plugins: " + "name=\"%s\"", plugin_name); dirs = g_ptr_array_new_with_free_func((GDestroyNotify) destroy_gstring); if (!dirs) { + BT_LOGE_STR("Failed to allocate a GPtrArray."); goto end; } @@ -188,6 +245,7 @@ struct bt_plugin *bt_plugin_find(const char *plugin_name) if (envvar) { ret = bt_common_append_plugin_path_dirs(envvar, dirs); if (ret) { + BT_LOGE_STR("Failed to append plugin path to array of directories."); goto end; } } @@ -198,6 +256,7 @@ struct bt_plugin *bt_plugin_find(const char *plugin_name) g_string_new(home_plugin_dir); if (!home_plugin_dir_str) { + BT_LOGE_STR("Failed to allocate a GString."); goto end; } @@ -210,6 +269,7 @@ struct bt_plugin *bt_plugin_find(const char *plugin_name) g_string_new(system_plugin_dir); if (!system_plugin_dir_str) { + BT_LOGE_STR("Failed to allocate a GString."); goto end; } @@ -219,11 +279,23 @@ struct bt_plugin *bt_plugin_find(const char *plugin_name) for (i = 0; i < dirs->len; i++) { GString *dir = g_ptr_array_index(dirs, i); - printf_verbose("Trying to load plugins from directory `%s`\n", - dir->str); BT_PUT(plugin_set); - plugin_set = bt_plugin_create_all_from_dir(dir->str, false); + + /* + * Skip this if the directory does not exist because + * bt_plugin_create_all_from_dir() would log a warning. + */ + if (!g_file_test(dir->str, G_FILE_TEST_IS_DIR)) { + BT_LOGV("Skipping nonexistent directory path: " + "path=\"%s\"", dir->str); + continue; + } + + /* bt_plugin_create_all_from_dir() logs details/errors */ + plugin_set = bt_plugin_create_all_from_dir(dir->str, BT_FALSE); if (!plugin_set) { + BT_LOGD("No plugins found in directory: path=\"%s\"", + dir->str); continue; } @@ -233,23 +305,31 @@ struct bt_plugin *bt_plugin_find(const char *plugin_name) if (strcmp(bt_plugin_get_name(candidate_plugin), plugin_name) == 0) { + BT_LOGD("Plugin found in directory: name=\"%s\", path=\"%s\"", + plugin_name, dir->str); plugin = bt_get(candidate_plugin); goto end; } } + + BT_LOGD("Plugin not found in directory: name=\"%s\", path=\"%s\"", + plugin_name, dir->str); } bt_put(plugin_set); plugin_set = bt_plugin_create_all_from_static(); + if (plugin_set) { + for (j = 0; j < plugin_set->plugins->len; j++) { + struct bt_plugin *candidate_plugin = + g_ptr_array_index(plugin_set->plugins, j); - for (j = 0; j < plugin_set->plugins->len; j++) { - struct bt_plugin *candidate_plugin = - g_ptr_array_index(plugin_set->plugins, j); - - if (strcmp(bt_plugin_get_name(candidate_plugin), - plugin_name) == 0) { - plugin = bt_get(candidate_plugin); - goto end; + if (strcmp(bt_plugin_get_name(candidate_plugin), + plugin_name) == 0) { + BT_LOGD("Plugin found in built-in plugins: " + "name=\"%s\"", plugin_name); + plugin = bt_get(candidate_plugin); + goto end; + } } } @@ -261,6 +341,15 @@ end: g_ptr_array_free(dirs, TRUE); } + if (plugin) { + BT_LOGD("Found plugin in standard directories and built-in plugins: " + "addr=%p, name=\"%s\", path=\"%s\"", + plugin, plugin_name, bt_plugin_get_path(plugin)); + } else { + BT_LOGD("No plugin found in standard directories and built-in plugins: " + "name=\"%s\"", plugin_name); + } + return plugin; } @@ -271,163 +360,155 @@ struct bt_component_class *bt_plugin_find_component_class( struct bt_plugin *plugin = NULL; struct bt_component_class *comp_cls = NULL; - if (!plugin_name || !comp_cls_name) { + if (!plugin_name) { + BT_LOGW_STR("Invalid parameter: plugin name is NULL."); goto end; } + if (!comp_cls_name) { + BT_LOGW_STR("Invalid parameter: component class name is NULL."); + goto end; + } + + BT_LOGD("Finding named plugin and component class in standard directories and built-in plugins: " + "plugin-name=\"%s\", comp-class-name=\"%s\"", + plugin_name, comp_cls_name); plugin = bt_plugin_find(plugin_name); if (!plugin) { + BT_LOGD_STR("Plugin not found."); goto end; } comp_cls = bt_plugin_get_component_class_by_name_and_type( plugin, comp_cls_name, comp_cls_type); + if (!comp_cls) { + BT_LOGD("Component class not found in plugin: " + "plugin-addr=%p, plugin-path=\"%s\"", + plugin, bt_plugin_get_path(plugin)); + } end: bt_put(plugin); return comp_cls; } -/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */ +static struct { + pthread_mutex_t lock; + struct bt_plugin_set *plugin_set; + bt_bool recurse; +} append_all_from_dir_info = { + .lock = PTHREAD_MUTEX_INITIALIZER +}; + static -struct dirent *alloc_dirent(const char *path) +int nftw_append_all_from_dir(const char *file, const struct stat *sb, int flag, + struct FTW *s) { - size_t len; - long name_max; - struct dirent *entry; + int ret = 0; + const char *name = file + s->base; + + /* Check for recursion */ + if (!append_all_from_dir_info.recurse && s->level > 1) { + goto end; + } + + switch (flag) { + case FTW_F: + { + struct bt_plugin_set *plugins_from_file; + + if (name[0] == '.') { + /* Skip hidden files */ + BT_LOGV("Skipping hidden file: path=\"%s\"", file); + goto end; + } + + plugins_from_file = bt_plugin_create_all_from_file(file); + + if (plugins_from_file) { + size_t j; + + for (j = 0; j < plugins_from_file->plugins->len; j++) { + struct bt_plugin *plugin = + g_ptr_array_index(plugins_from_file->plugins, j); + + BT_LOGD("Adding plugin to plugin set: " + "plugin-path=\"%s\", plugin-addr=%p, plugin-name=\"%s\"", + file, plugin, bt_plugin_get_name(plugin)); + bt_plugin_set_add_plugin(append_all_from_dir_info.plugin_set, plugin); + } - name_max = pathconf(path, _PC_NAME_MAX); - if (name_max == -1) { - name_max = PATH_MAX; + bt_put(plugins_from_file); + } + break; + } + case FTW_DNR: + /* Continue to next file / directory. */ + BT_LOGW("Cannot enter directory: continuing: path=\"%s\"", file); + break; + case FTW_NS: + /* Continue to next file / directory. */ + BT_LOGD("Cannot get file information: continuing: path=\"%s\"", file); + break; } - len = offsetof(struct dirent, d_name) + name_max + 1; - entry = zmalloc(len); - return entry; + +end: + return ret; } static enum bt_plugin_status bt_plugin_create_append_all_from_dir( struct bt_plugin_set *plugin_set, const char *path, - bool recurse) + bt_bool recurse) { - DIR *directory = NULL; - struct dirent *entry = NULL, *result = NULL; - char *file_path = NULL; + int nftw_flags = FTW_PHYS; size_t path_len; enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK; if (!path) { + BT_LOGW_STR("Invalid parameter: path is NULL."); ret = BT_PLUGIN_STATUS_ERROR; goto end; } path_len = strlen(path); - if (path_len >= PATH_MAX) { + BT_LOGW("Invalid parameter: path length is too large: " + "path-length=%zu", path_len); ret = BT_PLUGIN_STATUS_ERROR; goto end; } - entry = alloc_dirent(path); - if (!entry) { - ret = BT_PLUGIN_STATUS_ERROR; - goto end; - } + pthread_mutex_lock(&append_all_from_dir_info.lock); - file_path = zmalloc(PATH_MAX); - if (!file_path) { - ret = BT_PLUGIN_STATUS_NOMEM; - goto end; - } + append_all_from_dir_info.plugin_set = plugin_set; + append_all_from_dir_info.recurse = recurse; + ret = nftw(path, nftw_append_all_from_dir, + APPEND_ALL_FROM_DIR_NFDOPEN_MAX, nftw_flags); - strncpy(file_path, path, path_len); - /* Append a trailing '/' to the path */ - if (file_path[path_len - 1] != '/') { - file_path[path_len++] = '/'; - } + pthread_mutex_unlock(&append_all_from_dir_info.lock); - directory = opendir(file_path); - if (!directory) { - printf_verbose("Failed to open plugin directory \"%s\"\n", - file_path); + if (ret != 0) { + BT_LOGW("Cannot open directory: %s: path=\"%s\", errno=%d", + strerror(errno), path, errno); ret = BT_PLUGIN_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; - - 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; - } - - strncpy(file_path + path_len, result->d_name, file_name_len); - file_path[path_len + file_name_len] = '\0'; - stat_ret = stat(file_path, &st); - if (stat_ret < 0) { - /* Continue to next file / directory. */ - printf_perror("Failed to stat() plugin file\n"); - continue; - } - - if (S_ISDIR(st.st_mode) && recurse) { - ret = bt_plugin_create_append_all_from_dir(plugin_set, - file_path, true); - if (ret < 0) { - goto end; - } - } else if (S_ISREG(st.st_mode)) { - struct bt_plugin_set *plugins_from_file = - bt_plugin_create_all_from_file(file_path); - - if (plugins_from_file) { - size_t j; - - for (j = 0; j < plugins_from_file->plugins->len; j++) { - struct bt_plugin *plugin = - g_ptr_array_index(plugins_from_file->plugins, j); - - bt_plugin_set_add_plugin(plugin_set, - plugin); - } - - bt_put(plugins_from_file); - } - } - } 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; } struct bt_plugin_set *bt_plugin_create_all_from_dir(const char *path, - bool recurse) + bt_bool recurse) { struct bt_plugin_set *plugin_set; enum bt_plugin_status status; + BT_LOGD("Creating all plugins in directory: path=\"%s\", recurse=%d", + path, recurse); plugin_set = bt_plugin_set_create(); if (!plugin_set) { + BT_LOGE_STR("Cannot create empty plugin set."); goto error; } @@ -435,9 +516,14 @@ struct bt_plugin_set *bt_plugin_create_all_from_dir(const char *path, status = bt_plugin_create_append_all_from_dir(plugin_set, path, recurse); if (status < 0) { + BT_LOGW("Cannot append plugins found in directory: " + "path=\"%s\", status=%s", + path, bt_plugin_status_string(status)); goto error; } + BT_LOGD("Created %u plugins from directory: count=%u, path=\"%s\"", + plugin_set->plugins->len, plugin_set->plugins->len, path); goto end; error: @@ -449,27 +535,87 @@ end: const char *bt_plugin_get_name(struct bt_plugin *plugin) { - return plugin && plugin->info.name_set ? plugin->info.name->str : NULL; + const char *val = NULL; + + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto end; + } + + if (plugin->info.name_set) { + val = plugin->info.name->str; + } + +end: + return val; } const char *bt_plugin_get_author(struct bt_plugin *plugin) { - return plugin && plugin->info.author_set ? plugin->info.author->str : NULL; + const char *val = NULL; + + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto end; + } + + if (plugin->info.author_set) { + val = plugin->info.author->str; + } + +end: + return val; } const char *bt_plugin_get_license(struct bt_plugin *plugin) { - return plugin && plugin->info.license_set ? plugin->info.license->str : NULL; + const char *val = NULL; + + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto end; + } + + if (plugin->info.license_set) { + val = plugin->info.license->str; + } + +end: + return val; } const char *bt_plugin_get_path(struct bt_plugin *plugin) { - return plugin && plugin->info.path_set ? plugin->info.path->str : NULL; + const char *val = NULL; + + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto end; + } + + if (plugin->info.path_set) { + val = plugin->info.path->str; + } + +end: + return val; } const char *bt_plugin_get_description(struct bt_plugin *plugin) { - return plugin && plugin->info.description_set ? plugin->info.description->str : NULL; + const char *val = NULL; + + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto end; + } + + if (plugin->info.description_set) { + val = plugin->info.description->str; + } + +end: + return val; } enum bt_plugin_status bt_plugin_get_version(struct bt_plugin *plugin, @@ -478,7 +624,14 @@ enum bt_plugin_status bt_plugin_get_version(struct bt_plugin *plugin, { enum bt_plugin_status status = BT_PLUGIN_STATUS_OK; - if (!plugin || !plugin->info.version_set) { + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + status = BT_PLUGIN_STATUS_ERROR; + goto end; + } + + if (!plugin->info.version_set) { + BT_LOGV("Plugin's version is not set: addr=%p", plugin); status = BT_PLUGIN_STATUS_ERROR; goto end; } @@ -513,7 +666,15 @@ struct bt_component_class *bt_plugin_get_component_class_by_index( { struct bt_component_class *comp_class = NULL; - if (!plugin || index >= plugin->comp_classes->len) { + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto error; + } + + if (index >= plugin->comp_classes->len) { + BT_LOGW("Invalid parameter: index is out of bounds: " + "addr=%p, index=%" PRIu64 ", count=%u", + plugin, index, plugin->comp_classes->len); goto error; } @@ -535,7 +696,13 @@ struct bt_component_class *bt_plugin_get_component_class_by_name_and_type( struct bt_component_class *comp_class = NULL; size_t i; - if (!plugin || !name) { + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto error; + } + + if (!name) { + BT_LOGW_STR("Invalid parameter: name is NULL."); goto error; } @@ -547,8 +714,8 @@ struct bt_component_class *bt_plugin_get_component_class_by_name_and_type( enum bt_component_class_type comp_class_cand_type = bt_component_class_get_type(comp_class_candidate); - assert(comp_class_cand_name); - assert(comp_class_cand_type >= 0); + BT_ASSERT(comp_class_cand_name); + BT_ASSERT(comp_class_cand_type >= 0); if (strcmp(name, comp_class_cand_name) == 0 && comp_class_cand_type == type) { @@ -573,7 +740,20 @@ enum bt_plugin_status bt_plugin_add_component_class( struct bt_component_class *comp_class_dup = NULL; int comp_class_index = -1; - if (!plugin || !comp_class || plugin->frozen) { + if (!plugin) { + BT_LOGW_STR("Invalid parameter: plugin is NULL."); + goto error; + } + + if (!comp_class) { + BT_LOGW_STR("Invalid parameter: component class is NULL."); + goto error; + } + + if (plugin->frozen) { + BT_LOGW("Invalid parameter: plugin is frozen: " + "addr=%p, name=\"%s\"", plugin, + bt_plugin_get_name(plugin)); goto error; } @@ -582,10 +762,14 @@ enum bt_plugin_status bt_plugin_add_component_class( bt_component_class_get_name(comp_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", - bt_plugin_get_name(plugin), + BT_LOGW("Invalid parameter: a component class with this name and type already exists in the plugin: " + "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", " + "comp-class-name=\"%s\", comp-class-type=%s", + plugin, bt_plugin_get_name(plugin), + bt_plugin_get_path(plugin), bt_component_class_get_name(comp_class), - bt_component_class_get_type(comp_class)); + bt_component_class_type_string( + bt_component_class_get_type(comp_class))); goto error; } @@ -598,6 +782,15 @@ enum bt_plugin_status bt_plugin_add_component_class( bt_plugin_so_on_add_component_class(plugin, comp_class); } + BT_LOGD("Added component class to plugin: " + "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", " + "comp-class-addr=%p, comp-class-name=\"%s\", comp-class-type=%s", + plugin, bt_plugin_get_name(plugin), + bt_plugin_get_path(plugin), + comp_class, + bt_component_class_get_name(comp_class), + bt_component_class_type_string( + bt_component_class_get_type(comp_class))); goto end; error: