diff options
Diffstat (limited to 'src/plugins/pglist.c')
-rw-r--r-- | src/plugins/pglist.c | 289 |
1 files changed, 213 insertions, 76 deletions
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index 112a560..54c8784 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -32,40 +32,27 @@ #include <config.h> +#include <i18n.h> #include "plugin-int.h" #include "../common/extstr.h" -/* Représentation dédiée aux listes de greffons */ -typedef struct _pg_array -{ - PluginAction action; /* Action commune ou PGA_ALL */ - - GPluginModule **plugins; /* Liste de greffons */ - size_t plugins_count; /* Taille de cette liste */ - -} pg_array; - -/* Propriétés de l'ensemble des greffons */ -typedef struct _plugins_list -{ - pg_array *all; /* Liste de tous les greffons */ - pg_array sorted[PGA_COUNT]; /* Tri par catégories */ - -} plugins_list; - /* Liste de l'ensemble des greffons */ -static plugins_list _list; +static GPluginModule **_pg_list = NULL; +static size_t _pg_count = 0; + +/* Accès à cette liste */ +static GRWLock _pg_lock; /* Filtre les répertoire et les modules de greffons pootentels. */ -int filter_dirs_or_mods(const struct dirent *); +static int filter_dirs_or_mods(const struct dirent *); /* Part à la recherche de greffons sous forme de modules. */ -void browse_directory_for_plugins(plugins_list *, const char *); +static void browse_directory_for_plugins(const char *); @@ -83,15 +70,11 @@ void browse_directory_for_plugins(plugins_list *, const char *); bool init_all_plugins(void) { - size_t i; /* Boucle de parcours */ + g_rw_lock_init(&_pg_lock); - for (i = 0; i < PGA_COUNT; i++) - _list.sorted[i].action = PGA_EMPTY; + browse_directory_for_plugins(PACKAGE_SOURCE_DIR "/plugins"); - _list.sorted[0].action = PGA_ALL; - _list.all = &_list.sorted[0]; - - browse_directory_for_plugins(&_list, PACKAGE_SOURCE_DIR "/plugins"); + load_remaning_plugins(); return true; @@ -114,11 +97,16 @@ void exit_all_plugins(void) { size_t i; /* Boucle de parcours */ - for (i = 0; i < _list.all->plugins_count; i++) - g_object_unref(_list.all->plugins[i]); + if (_pg_list != NULL) + { + for (i = 0; i < _pg_count; i++) + g_object_unref(_pg_list[i]); + + free(_pg_list); + + } - for (i = 0; i < PGA_COUNT; i++) - free(_list.sorted[i].plugins); + g_rw_lock_clear(&_pg_lock); } @@ -135,7 +123,7 @@ void exit_all_plugins(void) * * ******************************************************************************/ -int filter_dirs_or_mods(const struct dirent *entry) +static int filter_dirs_or_mods(const struct dirent *entry) { int result; /* Conclusion à remonter */ @@ -152,8 +140,7 @@ int filter_dirs_or_mods(const struct dirent *entry) /****************************************************************************** * * -* Paramètres : list = liste de greffons à compléter si possible. * -* dir = répertoire à parcourir en quête de greffons (sans /). * +* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). * * * * Description : Part à la recherche de greffons sous forme de modules. * * * @@ -163,7 +150,7 @@ int filter_dirs_or_mods(const struct dirent *entry) * * ******************************************************************************/ -void browse_directory_for_plugins(plugins_list *list, const char *dir) +static void browse_directory_for_plugins(const char *dir) { struct dirent **namelist; /* Eléments trouvés */ int ret; /* Bilan du parcours */ @@ -186,14 +173,14 @@ void browse_directory_for_plugins(plugins_list *list, const char *dir) strcat(filename, namelist[ret]->d_name); if (namelist[ret]->d_type == DT_DIR) - browse_directory_for_plugins(list, filename); + browse_directory_for_plugins(filename); else { plugin = g_plugin_module_new(filename); if (plugin != NULL) - add_plugin_to_main_list(plugin); + register_plugin(plugin); } @@ -209,34 +196,57 @@ void browse_directory_for_plugins(plugins_list *list, const char *dir) /****************************************************************************** * * -* Paramètres : action = fonctionnalité recherchée. * -* count = nombre de greffons trouvés. [OUT] * +* Paramètres : plugin = greffon à ajouter aux autres disponibles. * * * -* Description : Founit les greffons offrant le service demandé. * +* Description : Ajoute un greffon à la liste principale de greffons. * * * -* Retour : Liste de greffons correspondants issue d'un tri interne. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -const GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count) +void _register_plugin(GPluginModule *plugin) { - const GPluginModule **result; /* Greffon à retourner */ size_t i; /* Boucle de parcours */ + const plugin_interface *pg_iface; /* Informations à consulter */ + const char *name; /* Désignation du greffon */ - result = NULL; - *count = 0; + /** + * L'appel sans verrou n'est fourni que pour les greffons + * mettant en place des greffons en interne ! + */ - for (i = 0; i < PGA_COUNT; i++) - if (_list.sorted[i].action == action) + /* Recherche d'un éventuel doublon */ + + pg_iface = g_plugin_module_get_interface(plugin); + + name = pg_iface->name; + + for (i = 0; i < _pg_count; i++) + { + pg_iface = g_plugin_module_get_interface(_pg_list[i]); + + if (strcmp(name, pg_iface->name) == 0) { - result = (const GPluginModule **)_list.sorted[i].plugins; - *count = _list.sorted[i].plugins_count; + log_variadic_message(LMT_ERROR, + _("Plugin '%s' already registered!"), name); + break; + } - return result; + } + + /* Ajout du greffon à la liste */ + + if (i == _pg_count) + { + _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule)); + + _pg_list[_pg_count - 1] = plugin; + + } } @@ -253,52 +263,179 @@ const GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *co * * ******************************************************************************/ -void add_plugin_to_main_list(GPluginModule *plugin) +void register_plugin(GPluginModule *plugin) { - const plugin_interface *interface; /* Informations à consulter */ - size_t i; /* Boucle de parcours #1 */ - size_t j; /* Boucle de parcours #2 */ + g_rw_lock_writer_lock(&_pg_lock); + + _register_plugin(plugin); + + g_rw_lock_writer_unlock(&_pg_lock); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Charge tous les greffons restant à charger. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - interface = g_plugin_module_get_interface(plugin); +void load_remaning_plugins(void) +{ + bool changed; /* Variation de dépendances */ + size_t i; /* Boucle de parcours */ + PluginStatusFlags flags; /* Fanions de greffon */ + + g_rw_lock_reader_lock(&_pg_lock); - void add_plugin_into_array(pg_array *array, GPluginModule *pg) + /* Etablit la liste de toutes les dépendances */ + + do { - array->plugins = (GPluginModule **)realloc(array->plugins, - ++array->plugins_count * sizeof(GPluginModule)); + changed = false; - array->plugins[array->plugins_count - 1] = pg; + for (i = 0; i < _pg_count; i++) + changed |= g_plugin_module_resolve_dependencies(_pg_list[i], _pg_list, _pg_count); } + while (changed); - /* FIXME : lock */ + /* Effectue les chargements possibles */ - add_plugin_into_array(_list.all, plugin); + for (i = 0; i < _pg_count; i++) + { + flags = g_plugin_module_get_flags(_pg_list[i]); - for (i = 0; i < interface->actions_count; i++) + if ((flags & (BROKEN_PLUGIN_STATUS | PSF_LOADED)) == 0) + g_plugin_module_load(_pg_list[i], _pg_list, _pg_count); + + } + + /* Supprime les greffons non chargés */ + + for (i = 0; i < _pg_count; i++) { - if (interface->actions[i] == PGA_ALL) continue; + flags = g_plugin_module_get_flags(_pg_list[i]); - for (j = 1; j < PGA_COUNT; j++) + if ((flags & PSF_LOADED) == 0) { - if (_list.sorted[j].action == interface->actions[i]) - { - add_plugin_into_array(&_list.sorted[j], plugin); - break; - } + g_object_unref(G_OBJECT(_pg_list[i])); + + memmove(&_pg_list[i], &_pg_list[i + 1], (_pg_count - i - 1) * sizeof(GPluginModule *)); + _pg_count--; - else if (_list.sorted[j].action == PGA_EMPTY) + } + + } + + g_rw_lock_reader_unlock(&_pg_lock); + +} + + +/****************************************************************************** +* * +* Paramètres : name = désignation du greffon recherché. * +* index = indice du greffon trouvé. [OUT] * +* * +* Description : Founit le greffon répondant à un nom donné. * +* * +* Retour : Instance du greffon trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GPluginModule *get_plugin_by_name(const char *name, size_t *index) +{ + GPluginModule *result; /* Greffon trouvé à renvoyer */ + size_t i; /* Boucle de parcours */ + const plugin_interface *pg_iface; /* Vitrine d'un greffon */ + + result = NULL; + + /** + * L'accès à la liste doit être encadré. + */ + assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE); + + for (i = 0; i < _pg_count && result == NULL; i++) + { + pg_iface = g_plugin_module_get_interface(_pg_list[i]); + + if (strcmp(pg_iface->name, name) == 0) + { + result = _pg_list[i]; + + if (index != NULL) + *index = i; + + } + + } + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : action = fonctionnalité recherchée. * +* count = nombre de greffons trouvés. [OUT] * +* * +* Description : Founit les greffons offrant le service demandé. * +* * +* Retour : Liste de greffons correspondants issue d'un tri interne. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count) +{ + GPluginModule **result; /* Liste à retourner */ + const plugin_interface *pg_iface; /* Informations à consulter */ + size_t i; /* Boucle de parcours #1 */ + size_t j; /* Boucle de parcours #2 */ + + result = NULL; + *count = 0; + + g_rw_lock_reader_lock(&_pg_lock); + + for (i = 0; i < _pg_count; i++) + { + pg_iface = g_plugin_module_get_interface(_pg_list[i]); + + for (j = 0; j < pg_iface->actions_count; j++) + { + if (pg_iface->actions[j] == action) { - add_plugin_into_array(&_list.sorted[j], plugin); - _list.sorted[j].action = interface->actions[i]; + result = (GPluginModule **)realloc(result, ++(*count) * sizeof(GPluginModule *)); + + result[*count - 1] = _pg_list[i]; + g_object_ref(G_OBJECT(_pg_list[i])); + break; + } } - assert(j < PGA_COUNT); - } - /* FIXME : lock */ + g_rw_lock_reader_unlock(&_pg_lock); + + return result; } |