summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-09-30 11:22:46 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-09-30 11:22:46 (GMT)
commitdb702d1243e6fec187137d48cecb89de17fefc3b (patch)
tree13776b4b75377951d9ebf9a57078ae1aed659cba
parent6ba73df8224dc2a88fe5f37a331960936758036e (diff)
Handled dependencies when loading plugins.
-rw-r--r--ChangeLog18
-rw-r--r--plugins/pychrysa/plugin.c2
-rw-r--r--plugins/pychrysa/pychrysa.c3
-rw-r--r--src/common/bits.c23
-rw-r--r--src/common/bits.h3
-rw-r--r--src/plugins/pglist.c289
-rw-r--r--src/plugins/pglist.h24
-rw-r--r--src/plugins/plugin-def.h1
-rw-r--r--src/plugins/plugin-int.h11
-rw-r--r--src/plugins/plugin.c206
-rw-r--r--src/plugins/plugin.h23
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 <nocbos@gmail.com>
+
+ * 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 <nocbos@gmail.com>
* 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 <common/environment.h>
#include <common/extstr.h>
#include <core/core.h>
+#include <plugins/pglist.h>
#include <plugins/plugin-def.h>
#include <plugins/plugin-int.h>
@@ -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 '<b>%s</b>' 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 <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;
}
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 <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;
}
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);