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:
parent
10b9472659
commit
15d9ab22c3
@ -45,10 +45,8 @@ typedef struct _plugin {
|
|||||||
#define TYPE_NAME_FILE_TYPE "file type"
|
#define TYPE_NAME_FILE_TYPE "file type"
|
||||||
#define TYPE_NAME_CODEC "codec"
|
#define TYPE_NAME_CODEC "codec"
|
||||||
|
|
||||||
/* array of plugins */
|
|
||||||
static GPtrArray *plugins_array = NULL;
|
static GSList *plugins_module_list = NULL;
|
||||||
/* map of names to plugin */
|
|
||||||
static GHashTable *plugins_table = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static inline const char *
|
static inline const char *
|
||||||
@ -101,7 +99,7 @@ compare_plugins(gconstpointer a, gconstpointer b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
GDir *dir;
|
||||||
const char *name; /* current file name */
|
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.
|
* 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. */
|
/* Yes, it is. */
|
||||||
report_warning("The plugin '%s' was found "
|
report_warning("The plugin '%s' was found "
|
||||||
"in multiple directories", name);
|
"in multiple directories", name);
|
||||||
@ -200,11 +198,7 @@ DIAG_ON(pedantic)
|
|||||||
new_plug->type_name = type_to_name(type);
|
new_plug->type_name = type_to_name(type);
|
||||||
|
|
||||||
/* Add it to the list of plugins. */
|
/* Add it to the list of plugins. */
|
||||||
if (*plugins_ptr == NULL)
|
g_hash_table_insert(plugins_module, new_plug->name, new_plug);
|
||||||
*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);
|
|
||||||
}
|
}
|
||||||
ws_dir_close(dir);
|
ws_dir_close(dir);
|
||||||
g_free(plugin_folder);
|
g_free(plugin_folder);
|
||||||
@ -214,7 +208,7 @@ DIAG_ON(pedantic)
|
|||||||
* Scan the buildir for plugins.
|
* Scan the buildir for plugins.
|
||||||
*/
|
*/
|
||||||
static void
|
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;
|
const char *name;
|
||||||
char *dirpath;
|
char *dirpath;
|
||||||
@ -223,7 +217,7 @@ scan_plugins_build_dir(GPtrArray **plugins_ptr, plugin_type_e type)
|
|||||||
WS_DIRENT *file; /* current file */
|
WS_DIRENT *file; /* current file */
|
||||||
|
|
||||||
/* Cmake */
|
/* 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 */
|
/* Autotools */
|
||||||
dirpath = g_build_filename(get_plugins_dir(), type_to_dir(type), (char *)NULL);
|
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);
|
g_free(plugin_folder);
|
||||||
plugin_folder = g_build_filename(get_plugins_dir(), name, (gchar *)NULL);
|
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);
|
g_free(plugin_folder);
|
||||||
}
|
}
|
||||||
ws_dir_close(dir);
|
ws_dir_close(dir);
|
||||||
@ -271,12 +265,7 @@ plugins_init(plugin_type_e type)
|
|||||||
if (!g_module_supported())
|
if (!g_module_supported())
|
||||||
return NULL; /* nothing to do */
|
return NULL; /* nothing to do */
|
||||||
|
|
||||||
GPtrArray *plugins = NULL;
|
GHashTable *plugins_module = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free_plugin);
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the global plugin directory.
|
* 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
|
* out-of-tree build. If we find subdirectories scan those since
|
||||||
* they will contain plugins in the case of an in-tree build.
|
* they will contain plugins in the case of an in-tree build.
|
||||||
*/
|
*/
|
||||||
if (running_in_build_directory())
|
if (running_in_build_directory()) {
|
||||||
{
|
scan_plugins_build_dir(plugins_module, type);
|
||||||
scan_plugins_build_dir(&plugins, type);
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
plugins_scan_dir(plugins_module, get_plugins_dir_with_version(), type, TRUE);
|
||||||
plugins_scan_dir(&plugins, 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
|
* if we need privileges to start capturing, we'd need to
|
||||||
* reclaim them before each time we start capturing.)
|
* reclaim them before each time we start capturing.)
|
||||||
*/
|
*/
|
||||||
if (!started_with_special_privs())
|
if (!started_with_special_privs()) {
|
||||||
{
|
plugins_scan_dir(plugins_module, get_plugins_pers_dir_with_version(), type, TRUE);
|
||||||
plugins_scan_dir(&plugins, 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
|
WS_DLL_PUBLIC void
|
||||||
plugins_get_descriptions(plugin_description_callback callback, void *callback_data)
|
plugins_get_descriptions(plugin_description_callback callback, void *callback_data)
|
||||||
{
|
{
|
||||||
if (!plugins_array)
|
GPtrArray *plugins_array = g_ptr_array_new();
|
||||||
return;
|
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++) {
|
for (guint i = 0; i < plugins_array->len; i++) {
|
||||||
plugin *plug = (plugin *)plugins_array->pdata[i];
|
plugin *plug = (plugin *)plugins_array->pdata[i];
|
||||||
callback(plug->name, plug->version, plug->type_name, g_module_name(plug->handle), callback_data);
|
callback(plug->name, plug->version, plug->type_name, g_module_name(plug->handle), callback_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_ptr_array_free(plugins_array, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -341,34 +339,22 @@ plugins_dump_all(void)
|
|||||||
int
|
int
|
||||||
plugins_get_count(void)
|
plugins_get_count(void)
|
||||||
{
|
{
|
||||||
if (plugins_table)
|
guint count = 0;
|
||||||
return g_hash_table_size(plugins_table);
|
|
||||||
return 0;
|
for (GSList *l = plugins_module_list; l != NULL; l = l->next) {
|
||||||
|
count += g_hash_table_size((GHashTable *)l->data);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
plugins_cleanup(plugins_t *plugins)
|
plugins_cleanup(plugins_t *plugins)
|
||||||
{
|
{
|
||||||
if (plugins)
|
if (!plugins)
|
||||||
g_ptr_array_free((GPtrArray *)plugins, TRUE);
|
return;
|
||||||
|
|
||||||
/*
|
plugins_module_list = g_slist_remove(plugins_module_list, plugins);
|
||||||
* This module uses global bookkeeping data structures and per-library
|
g_hash_table_destroy((GHashTable *)plugins);
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_PLUGINS */
|
#endif /* HAVE_PLUGINS */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user