From db702d1243e6fec187137d48cecb89de17fefc3b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 30 Sep 2017 13:22:46 +0200 Subject: Handled dependencies when loading plugins. --- ChangeLog | 18 +++ plugins/pychrysa/plugin.c | 2 + plugins/pychrysa/pychrysa.c | 3 +- src/common/bits.c | 23 ++++ src/common/bits.h | 3 + src/plugins/pglist.c | 289 ++++++++++++++++++++++++++++++++------------ src/plugins/pglist.h | 24 +++- src/plugins/plugin-def.h | 1 - src/plugins/plugin-int.h | 11 +- src/plugins/plugin.c | 206 ++++++++++++++++++++++++++----- src/plugins/plugin.h | 23 ++++ 11 files changed, 488 insertions(+), 115 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1c8b550..201ab6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +17-08-30 Cyrille Bagard + + * plugins/pychrysa/plugin.c: + * plugins/pychrysa/pychrysa.c: + Update code. + + * src/common/bits.c: + * src/common/bits.h: + Extend the bitfields API. + + * src/plugins/pglist.c: + * src/plugins/pglist.h: + * src/plugins/plugin-def.h: + * src/plugins/plugin-int.h: + * src/plugins/plugin.c: + * src/plugins/plugin.h: + Handle dependencies when loading plugins. + 17-08-28 Cyrille Bagard * plugins/mobicore/mobicore.c: diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c index 7d44f10..fad0084 100644 --- a/plugins/pychrysa/plugin.c +++ b/plugins/pychrysa/plugin.c @@ -345,8 +345,10 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) /* Conclusion */ + /* if (!g_plugin_module_load(G_PLUGIN_MODULE(result))) goto gppn_bad_plugin; + */ return G_PLUGIN_MODULE(result); diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c index e9efc54..4d32ee1 100644 --- a/plugins/pychrysa/pychrysa.c +++ b/plugins/pychrysa/pychrysa.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -478,7 +479,7 @@ static bool load_python_plugins(GPluginModule *plugin) g_plugin_module_log_variadic_message(plugin, LMT_PROCESS, _("Loaded the Python plugin found in the '%s' directory"), filename); - add_plugin_to_main_list(pyplugin); + _register_plugin(pyplugin); } free(filename); diff --git a/src/common/bits.c b/src/common/bits.c index 4d4731a..837e31e 100644 --- a/src/common/bits.c +++ b/src/common/bits.c @@ -180,6 +180,29 @@ void copy_bit_field(bitfield_t *dest, const bitfield_t *src) /****************************************************************************** * * +* Paramètres : field = champ de bits à consulter. * +* * +* Description : Indique la taille d'un champ de bits donné. * +* * +* Retour : Taille du champ de bits. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t get_bit_field_size(const bitfield_t *field) +{ + size_t result; /* Dimension à retourner */ + + result = field->length; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : a = premier champ à analyser. * * b = second champ à analyser. * * * diff --git a/src/common/bits.h b/src/common/bits.h index b9fc0e6..72b431e 100644 --- a/src/common/bits.h +++ b/src/common/bits.h @@ -45,6 +45,9 @@ void delete_bit_field(bitfield_t *); /* Copie un champ de bits dans un autre. */ void copy_bit_field(bitfield_t *, const bitfield_t *); +/* Indique la taille d'un champ de bits donné. */ +size_t get_bit_field_size(const bitfield_t *); + /* Compare deux champs de bits entre eux. */ int compare_bit_fields(const bitfield_t *, const bitfield_t *); 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 +#include #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; } diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index 5dfd6c3..d2f2243 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -41,8 +41,21 @@ bool init_all_plugins(void); /* Procède au déchargement des différents greffons présents. */ void exit_all_plugins(void); +/* Ajoute un greffon à la liste principale de greffons. */ +void _register_plugin(GPluginModule *); + +/* Ajoute un greffon à la liste principale de greffons. */ +void register_plugin(GPluginModule *); + +/* Charge tous les greffons restant à charger. */ +void load_remaning_plugins(void); + +/* Founit le greffon répondant à un nom donné. */ +GPluginModule *get_plugin_by_name(const char *, size_t *); + /* Founit less greffons offrant le service demandé. */ -const GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); +GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); + /** @@ -52,18 +65,23 @@ const GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); #define process_all_plugins_for(a, f, ...) \ { \ size_t __count; \ - const GPluginModule **__list; \ + GPluginModule **__list; \ size_t __i; \ __list = get_all_plugins_for_action(a, &__count); \ for (__i = 0; __i < __count; __i++) \ + { \ f(__list[__i], a, __VA_ARGS__); \ + g_object_ref(G_OBJECT(__list[__i])); \ + } \ + if (__list != NULL) \ + free(__list); \ } \ while (0) /* DPS_FORMAT */ -#define find_matching_format() +//#define find_matching_format() #define handle_binary_format(a, f, s) \ process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s) diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 7344a06..83b2c9a 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -285,7 +285,6 @@ typedef struct _plugin_interface const char **required; /* Pré-chargements requis */ size_t required_count; /* Quantité de ces dépendances */ - /* status */ plugin_action_t *actions; /* Liste des actions gérées */ size_t actions_count; /* Quantité de ces actions */ diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index ac6ade6..821653c 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -32,6 +32,7 @@ #include "plugin.h" #include "plugin-def.h" #include "../analysis/content.h" +#include "../common/bits.h" #include "../gui/panels/log.h" @@ -91,6 +92,10 @@ struct _GPluginModule const plugin_interface *interface; /* Déclaration d'interfaçage */ + PluginStatusFlags flags; /* Fanion pour l'état courant */ + + bitfield_t *dependencies; /* Cartographie des dépendances*/ + pg_management_fc init; /* Procédure d'initialisation */ pg_management_fc exit; /* Procédure d'extinction */ @@ -126,9 +131,6 @@ struct _GPluginModuleClass -/* Termine le chargement du greffon préparé. */ -bool g_plugin_module_load(GPluginModule *); - /* Présente dans le journal un message simple. */ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *); @@ -137,8 +139,7 @@ void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType, -/* Ajoute un greffon à la liste principale de greffons. */ -void add_plugin_to_main_list(GPluginModule *); + diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 03c3b21..cd59ee1 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -25,6 +25,7 @@ #include "plugin.h" +#include #include #include #include @@ -34,6 +35,7 @@ #include +#include "pglist.h" #include "plugin-int.h" @@ -142,6 +144,9 @@ static void g_plugin_module_finalize(GPluginModule *plugin) { free(plugin->filename); + if (plugin->dependencies != NULL) + delete_bit_field(plugin->dependencies); + G_OBJECT_CLASS(g_plugin_module_parent_class)->finalize(G_OBJECT(plugin)); } @@ -318,11 +323,6 @@ GPluginModule *g_plugin_module_new(const gchar *filename) } - /* Conclusion */ - - if (!g_plugin_module_load(result)) - goto bad_plugin; - return result; bad_plugin: @@ -336,42 +336,122 @@ GPluginModule *g_plugin_module_new(const gchar *filename) /****************************************************************************** * * -* Paramètres : plugin = greffon à valider. * +* Paramètres : plugin = greffon à consulter. * * * -* Description : Termine le chargement du greffon préparé. * +* Description : Fournit la description du greffon dans son intégralité. * * * -* Retour : Bilan du chargement effectif. * +* Retour : Interfaçage renseigné. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin) +{ + return plugin->interface; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Fournit des indications sur l'état du greffon. * +* * +* Retour : Fanions portant des indications. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *plugin) +{ + return plugin->flags; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à mettre à jour. * +* list = ensemble des greffons disponibles. * +* count = taille de cet ensemble. * +* * +* Description : Met à jour l'ensemble des dépendances du greffon. * +* * +* Retour : true si la liste des dépendances a évolué. * * * * Remarques : - * * * ******************************************************************************/ -bool g_plugin_module_load(GPluginModule *plugin) +bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule **list, size_t count) { bool result; /* Bilan à faire remonter */ - char *dir; /* Répertoire modifiable */ + const plugin_interface *pg_iface; /* Définition du greffon */ + bitfield_t *new; /* Nouvelle définition */ + size_t i; /* Boucle de parcours */ + GPluginModule *dependency; /* Module nécessaire */ + size_t index; /* Indice de greffon visé */ - result = true; + result = false; - dir = strdup(plugin->filename); - dir = dirname(dir); + if (plugin->dependencies == NULL) + plugin->dependencies = create_bit_field(count, false); - if (plugin->init != NULL) +#ifndef NDEBUG + else + assert(count == get_bit_field_size(plugin->dependencies)); +#endif + + if ((plugin->flags & (PSF_UNKNOW_DEP | PSF_DEP_LOOP)) != 0) { - if (!plugin->init(plugin)) + pg_iface = g_plugin_module_get_interface(plugin); + + /* Collecte des dépendances */ + + new = dup_bit_field(plugin->dependencies); + + for (i = 0; i < pg_iface->required_count; i++) { - log_variadic_message(LMT_ERROR, - _("Plugin '%s' failed to load itself..."), plugin->filename); - result = false; + dependency = get_plugin_by_name(pg_iface->required[i], &index); + + if (dependency == NULL) + plugin->flags |= PSF_UNKNOW_DEP; + + else + { + or_bit_field(new, dependency->dependencies); + + g_object_ref(G_OBJECT(dependency)); + + } + } - } - if (result) - log_variadic_message(LMT_PROCESS, - _("Loaded the '%s' file as plugin from the '%s' directory"), - strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir); + /* Mise à jour du suivi */ + + if (compare_bit_fields(plugin->dependencies, new) != 0) + { + copy_bit_field(plugin->dependencies, new); + result = true; + } + + delete_bit_field(new); + + /* Vérification sanitaire */ + + dependency = get_plugin_by_name(pg_iface->name, &index); + assert(dependency != NULL); - free(dir); + if (test_in_bit_field(plugin->dependencies, index)) + plugin->flags |= PSF_DEP_LOOP; + + g_object_ref(G_OBJECT(dependency)); + + + } return result; @@ -380,19 +460,87 @@ bool g_plugin_module_load(GPluginModule *plugin) /****************************************************************************** * * -* Paramètres : plugin = greffon à consulter. * +* Paramètres : plugin = greffon à valider. * +* list = ensemble des greffons disponibles. * +* count = taille de cet ensemble. * * * -* Description : Fournit la description du greffon dans son intégralité. * +* Description : Termine le chargement du greffon préparé. * * * -* Retour : Interfaçage renseigné. * +* Retour : Bilan du chargement effectif. * * * * Remarques : - * * * ******************************************************************************/ -const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin) +bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t count) { - return plugin->interface; + bool result; /* Bilan à retourner */ + PluginStatusFlags flags; /* Fanions de greffon */ + const plugin_interface *pg_iface; /* Définition du greffon */ + size_t i; /* Boucle de parcours */ + GPluginModule *dependency; /* Module nécessaire */ + char *dir; /* Répertoire modifiable */ + + /* Si un essai précédent a déjà échoué ou réussi... */ + + flags = g_plugin_module_get_flags(plugin); + + assert((flags & BROKEN_PLUGIN_STATUS) == 0); + + if (flags & PSF_FAILURE) return false; + + if (flags & PSF_LOADED) return true; + + /* Chargement des dépendances */ + + pg_iface = g_plugin_module_get_interface(plugin); + + result = true; + + for (i = 0; i < pg_iface->required_count && result; i++) + { + dependency = get_plugin_by_name(pg_iface->required[i], NULL); + + result = g_plugin_module_load(dependency, list, count); + + } + + if (!result) + log_variadic_message(LMT_ERROR, + _("Some dependencies failed to load for Plugin '%s'"), plugin->filename); + + /* Chargement du greffon courant */ + + if (result) + { + if (plugin->init != NULL) + { + result = plugin->init(plugin); + + if (!result) + log_variadic_message(LMT_ERROR, + _("Plugin '%s' failed to load itself..."), plugin->filename); + + } + + if (result) + { + dir = strdup(plugin->filename); + dir = dirname(dir); + + log_variadic_message(LMT_PROCESS, + _("Loaded the '%s' file as plugin from the '%s' directory"), + strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir); + + free(dir); + + plugin->flags |= PSF_LOADED; + + } + + } + + return result; } diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index bc6189f..6d783b7 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -44,6 +44,21 @@ typedef struct _GPluginModule GPluginModule; typedef struct _GPluginModuleClass GPluginModuleClass; +/* Fanions indiquant le statut du greffon */ +typedef enum _PluginStatusFlags +{ + PSF_NONE = (0 << 0), /* Aucune indication */ + PSF_UNKNOW_DEP = (1 << 0), /* Dépendance non trouvée */ + PSF_DEP_LOOP = (1 << 1), /* Dépendances circulaires */ + PSF_FAILURE = (1 << 2), /* Erreur au chargement */ + PSF_LOADED = (1 << 2) /* Greffon intégré au système */ + +} PluginStatusFlags; + + +#define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE) + + #define G_TYPE_PLUGIN_MODULE (g_plugin_module_get_type()) #define G_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule)) #define G_IS_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE)) @@ -61,6 +76,14 @@ GPluginModule *g_plugin_module_new(const gchar *); /* Fournit la description du greffon dans son intégralité. */ const plugin_interface *g_plugin_module_get_interface(const GPluginModule *); +/* Fournit des indications sur l'état du greffon. */ +PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *); + +/* Met à jour l'ensemble des dépendances du greffon. */ +bool g_plugin_module_resolve_dependencies(GPluginModule *, GPluginModule **, size_t); + +/* Termine le chargement du greffon préparé. */ +bool g_plugin_module_load(GPluginModule *, GPluginModule **, size_t); -- cgit v0.11.2-87-g4458