summaryrefslogtreecommitdiff
path: root/src/plugins/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/plugin.c')
-rw-r--r--src/plugins/plugin.c206
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;
}