plugins: Use per-library data structures

This is cleaner and allows the "duplicate plugin name check" to be
performed correctly (per module and not globally).

Change-Id: I2b2122495dc047af5b7043dcf020a525766b7c30
Reviewed-on: https://code.wireshark.org/review/25496
Petri-Dish: João Valverde <j@v6e.pt>
Tested-by: Petri Dish Buildbot
Reviewed-by: João Valverde <j@v6e.pt>
This commit is contained in:
João Valverde 2018-01-28 12:00:29 +00:00 committed by João Valverde
parent 10b9472659
commit 15d9ab22c3
1 changed files with 41 additions and 55 deletions

View File

@ -45,10 +45,8 @@ typedef struct _plugin {
#define TYPE_NAME_FILE_TYPE "file type"
#define TYPE_NAME_CODEC "codec"
/* array of plugins */
static GPtrArray *plugins_array = NULL;
/* map of names to plugin */
static GHashTable *plugins_table = NULL;
static GSList *plugins_module_list = NULL;
static inline const char *
@ -101,7 +99,7 @@ compare_plugins(gconstpointer a, gconstpointer b)
}
static void
plugins_scan_dir(GPtrArray **plugins_ptr, const char *dirpath, plugin_type_e type, gboolean append_type)
plugins_scan_dir(GHashTable *plugins_module, const char *dirpath, plugin_type_e type, gboolean append_type)
{
GDir *dir;
const char *name; /* current file name */
@ -143,7 +141,7 @@ plugins_scan_dir(GPtrArray **plugins_ptr, const char *dirpath, plugin_type_e typ
/*
* Check if the same name is already registered.
*/
if (g_hash_table_lookup(plugins_table, name)) {
if (g_hash_table_lookup(plugins_module, name)) {
/* Yes, it is. */
report_warning("The plugin '%s' was found "
"in multiple directories", name);
@ -200,11 +198,7 @@ DIAG_ON(pedantic)
new_plug->type_name = type_to_name(type);
/* Add it to the list of plugins. */
if (*plugins_ptr == NULL)
*plugins_ptr = g_ptr_array_new_with_free_func(free_plugin);
g_ptr_array_add(*plugins_ptr, new_plug);
g_ptr_array_add(plugins_array, new_plug);
g_hash_table_insert(plugins_table, new_plug->name, new_plug);
g_hash_table_insert(plugins_module, new_plug->name, new_plug);
}
ws_dir_close(dir);
g_free(plugin_folder);
@ -214,7 +208,7 @@ DIAG_ON(pedantic)
* Scan the buildir for plugins.
*/
static void
scan_plugins_build_dir(GPtrArray **plugins_ptr, plugin_type_e type)
scan_plugins_build_dir(GHashTable *plugins_module, plugin_type_e type)
{
const char *name;
char *dirpath;
@ -223,7 +217,7 @@ scan_plugins_build_dir(GPtrArray **plugins_ptr, plugin_type_e type)
WS_DIRENT *file; /* current file */
/* Cmake */
plugins_scan_dir(plugins_ptr, get_plugins_dir_with_version(), type, TRUE);
plugins_scan_dir(plugins_module, get_plugins_dir_with_version(), type, TRUE);
/* Autotools */
dirpath = g_build_filename(get_plugins_dir(), type_to_dir(type), (char *)NULL);
@ -255,7 +249,7 @@ scan_plugins_build_dir(GPtrArray **plugins_ptr, plugin_type_e type)
g_free(plugin_folder);
plugin_folder = g_build_filename(get_plugins_dir(), name, (gchar *)NULL);
}
plugins_scan_dir(plugins_ptr, plugin_folder, type, FALSE);
plugins_scan_dir(plugins_module, plugin_folder, type, FALSE);
g_free(plugin_folder);
}
ws_dir_close(dir);
@ -271,12 +265,7 @@ plugins_init(plugin_type_e type)
if (!g_module_supported())
return NULL; /* nothing to do */
GPtrArray *plugins = NULL;
if (plugins_table == NULL)
plugins_table = g_hash_table_new(g_str_hash, g_str_equal);
if (plugins_array == NULL)
plugins_array = g_ptr_array_new();
GHashTable *plugins_module = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free_plugin);
/*
* Scan the global plugin directory.
@ -285,13 +274,11 @@ plugins_init(plugin_type_e type)
* out-of-tree build. If we find subdirectories scan those since
* they will contain plugins in the case of an in-tree build.
*/
if (running_in_build_directory())
{
scan_plugins_build_dir(&plugins, type);
if (running_in_build_directory()) {
scan_plugins_build_dir(plugins_module, type);
}
else
{
plugins_scan_dir(&plugins, get_plugins_dir_with_version(), type, TRUE);
else {
plugins_scan_dir(plugins_module, get_plugins_dir_with_version(), type, TRUE);
}
/*
@ -302,26 +289,37 @@ plugins_init(plugin_type_e type)
* if we need privileges to start capturing, we'd need to
* reclaim them before each time we start capturing.)
*/
if (!started_with_special_privs())
{
plugins_scan_dir(&plugins, get_plugins_pers_dir_with_version(), type, TRUE);
if (!started_with_special_privs()) {
plugins_scan_dir(plugins_module, get_plugins_pers_dir_with_version(), type, TRUE);
}
g_ptr_array_sort(plugins_array, compare_plugins);
plugins_module_list = g_slist_prepend(plugins_module_list, plugins_module);
return plugins;
return plugins_module;
}
WS_DLL_PUBLIC void
plugins_get_descriptions(plugin_description_callback callback, void *callback_data)
{
if (!plugins_array)
return;
GPtrArray *plugins_array = g_ptr_array_new();
GHashTableIter iter;
gpointer value;
for (GSList *l = plugins_module_list; l != NULL; l = l->next) {
g_hash_table_iter_init (&iter, (GHashTable *)l->data);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
g_ptr_array_add(plugins_array, value);
}
}
g_ptr_array_sort(plugins_array, compare_plugins);
for (guint i = 0; i < plugins_array->len; i++) {
plugin *plug = (plugin *)plugins_array->pdata[i];
callback(plug->name, plug->version, plug->type_name, g_module_name(plug->handle), callback_data);
}
g_ptr_array_free(plugins_array, FALSE);
}
static void
@ -341,34 +339,22 @@ plugins_dump_all(void)
int
plugins_get_count(void)
{
if (plugins_table)
return g_hash_table_size(plugins_table);
return 0;
guint count = 0;
for (GSList *l = plugins_module_list; l != NULL; l = l->next) {
count += g_hash_table_size((GHashTable *)l->data);
}
return count;
}
void
plugins_cleanup(plugins_t *plugins)
{
if (plugins)
g_ptr_array_free((GPtrArray *)plugins, TRUE);
if (!plugins)
return;
/*
* This module uses global bookkeeping data structures and per-library
* objects sharing data. To avoid having to walk the plugins GPtrArray
* and delete each plugin from the global data structures we purge them
* once the first plugin cleanup function is called. This means that after
* calling ONE OF POSSIBLY MANY plugin cleanup function NO OTHER plugin
* APIs can be used except plugins_cleanup. If it ever becomes an issue
* it will be easy to change, for a small performance penalty.
*/
if (plugins_table) {
g_hash_table_destroy(plugins_table);
plugins_table = NULL;
}
if (plugins_array) {
g_ptr_array_free(plugins_array, FALSE);
plugins_array = NULL;
}
plugins_module_list = g_slist_remove(plugins_module_list, plugins);
g_hash_table_destroy((GHashTable *)plugins);
}
#endif /* HAVE_PLUGINS */