diff options
Diffstat (limited to 'src/plugins/plugin.c')
-rw-r--r-- | src/plugins/plugin.c | 206 |
1 files changed, 177 insertions, 29 deletions
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 <assert.h> #include <gmodule.h> #include <libgen.h> #include <malloc.h> @@ -34,6 +35,7 @@ #include <string.h> +#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 '<b>%s</b>' file as plugin from the '<b>%s</b>' 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 '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"), + strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir); + + free(dir); + + plugin->flags |= PSF_LOADED; + + } + + } + + return result; } |