diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2017-09-30 11:22:46 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2017-09-30 11:22:46 (GMT) | 
| commit | db702d1243e6fec187137d48cecb89de17fefc3b (patch) | |
| tree | 13776b4b75377951d9ebf9a57078ae1aed659cba /src/plugins/pglist.c | |
| parent | 6ba73df8224dc2a88fe5f37a331960936758036e (diff) | |
Handled dependencies when loading plugins.
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;  }  | 
