summaryrefslogtreecommitdiff
path: root/src/analysis/loading.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-04-21 22:00:00 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-04-21 22:00:00 (GMT)
commit8eb95d316f7b6fbad0ff798abfe7f70f89e812d2 (patch)
tree4f310c7ffdb94d48fff236e63c7e6f0ed9f1dee1 /src/analysis/loading.c
parent315146a49b5570294ca20beca720c4e3f74a86bd (diff)
Improved the way file formats are detected and loaded.
Diffstat (limited to 'src/analysis/loading.c')
-rw-r--r--src/analysis/loading.c1337
1 files changed, 1095 insertions, 242 deletions
diff --git a/src/analysis/loading.c b/src/analysis/loading.c
index 5aff20f..f2ae882 100644
--- a/src/analysis/loading.c
+++ b/src/analysis/loading.c
@@ -24,134 +24,268 @@
#include "loading.h"
-#include "../core/formats.h"
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
#include "../core/global.h"
-#include "../core/logs.h"
#include "../glibext/delayed-int.h"
-#include "../glibext/signal.h"
+#include "../plugins/pglist.h"
+
+/* ------------------------- TACHE D'EXPLORATION DE CONTENU ------------------------- */
-/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
+#define G_TYPE_EXPLORING_WORK g_exploring_work_get_type()
+#define G_EXPLORING_WORK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_EXPLORING_WORK, GExploringWork))
+#define G_IS_EXPLORING_WORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_EXPLORING_WORK))
+#define G_EXPLORING_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_EXPLORING_WORK, GExploringWorkClass))
+#define G_IS_EXPLORING_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_EXPLORING_WORK))
+#define G_EXPLORING_WORK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_EXPLORING_WORK, GExploringWorkClass))
-/* Ensembles binaires à désassembler (instance) */
-struct _GDelayedStudy
+
+/* Conversion de contenu binaire en contenu chargé (instance) */
+typedef struct _GExploringWork
{
GDelayedWork parent; /* A laisser en premier */
- GStudyProject *project; /* Projet de rattachement */
- GBinContent *content; /* Contenu binaire à traiter */
- ProjectContentState state; /* Renseigne le type de contenu*/
+ const gid_t *gid; /* Groupe d'appartenance */
- bool only_preload; /* Enregistrement seulement ? */
+ GBinContent *content; /* Contenu brut à disposition */
-};
+} GExploringWork;
-/* Ensembles binaires à désassembler (classe) */
-struct _GDelayedStudyClass
+/* Conversion de contenu binaire en contenu chargé (classe) */
+typedef struct _GExploringWorkClass
{
GDelayedWorkClass parent; /* A laisser en premier */
-};
+} GExploringWorkClass;
+
+/* Indique le type défini pour l'exploration de contenu binaire. */
+GType g_exploring_work_get_type(void);
-/* Initialise la classe des intégrations de binaires à étudier. */
-static void g_delayed_study_class_init(GDelayedStudyClass *);
+/* Initialise la classe des tâches d'exploration de contenu. */
+static void g_exploring_work_class_init(GExploringWorkClass *);
-/* Initialise une intégration de binaire à étudier. */
-static void g_delayed_study_init(GDelayedStudy *);
+/* Initialise une tâche d'exploration de contenu. */
+static void g_exploring_work_init(GExploringWork *);
/* Supprime toutes les références externes. */
-static void g_delayed_study_dispose(GDelayedStudy *);
+static void g_exploring_work_dispose(GExploringWork *);
/* Procède à la libération totale de la mémoire. */
-static void g_delayed_study_finalize(GDelayedStudy *);
+static void g_exploring_work_finalize(GExploringWork *);
+
+/* Prépare la conversion non bloquée d'un contenu binaire. */
+static GExploringWork *g_exploring_work_new(GBinContent *);
-/* Prépare une intégration de binaire au projet courant. */
-static void g_delayed_study_process(GDelayedStudy *, GtkStatusStack *);
+/* Fournit l'identifiant du groupe de rattachement de la tâche. */
+static gid_t g_exploring_work_get_group_id(const GExploringWork *);
+/* Définit l'identifiant du groupe de rattachement de la tâche. */
+static void g_exploring_work_set_group_id(GExploringWork *, const gid_t *);
+/* Réalise l'exploration effective de formes de contenus. */
+static void g_exploring_work_process(GExploringWork *, GtkStatusStack *);
-/* ----------------------- CHARGEMENT DE BINAIRE NON BLOQUANT ----------------------- */
-#define G_TYPE_BINARY_LOADER g_binary_loader_get_type()
-#define G_BINARY_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BINARY_LOADER, GBinaryLoader))
-#define G_IS_BINARY_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BINARY_LOADER))
-#define G_BINARY_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_LOADER, GBinaryLoaderClass))
-#define G_IS_BINARY_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_LOADER))
-#define G_BINARY_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_LOADER, GBinaryLoaderClass))
+/* --------------------- EXPLORATION NON BLOQUANTE DES CONTENUS --------------------- */
-/* Chargement non bloquant d'un binaire (instance) */
-struct _GBinaryLoader
+/* Regroupement des chargements */
+typedef struct _exploring_group
{
- GDelayedWork parent; /* A laisser en premier */
+ GBinContent *original; /* Contenu binaire initial */
- bool from_content; /* Sélection de champs */
+ wgroup_id_t wid; /* Groupe de travail */
+ gid_t gid; /* Groupe d'appartenance */
- union
- {
- GBinContent *content; /* Contenu brut à disposition */
+ GBinContent **contents; /* Contenus reconnus dispos. */
+ size_t count; /* Taille de cette liste */
- struct
- {
- char *filename; /* Chemin vers l'ensemble XML */
- char *path; /* Chemin de la définition XML */
+} exploring_group;
- };
+/* Exploration de contenus binaires (instance) */
+struct _GContentExplorer
+{
+ GObject parent; /* A laisser en premier */
+
+ gid_t generator; /* Générateur d'identifiants */
- };
+ exploring_group *groups; /* Rassemblement de chargements*/
+ size_t count; /* Nombre de ces groupes */
+ GMutex mutex; /* Accès protégé à la liste */
- GStudyProject *project; /* Accès aux contenus liés */
+};
+
+/* Exploration de contenus binaires (classe) */
+struct _GContentExplorerClass
+{
+ GObjectClass parent; /* A laisser en premier */
- GLoadedBinary *binary; /* Résultat du chargement */
+ /* Signaux */
+
+ void (* explored) (GContentExplorer *, gid_t);
};
-/* Chargement non bloquant d'un binaire (classe) */
-struct _GBinaryLoaderClass
+
+/* Initialise la classe les explorations de contenus binaires. */
+static void g_content_explorer_class_init(GContentExplorerClass *);
+
+/* Initialise une exploration de contenus binaires. */
+static void g_content_explorer_init(GContentExplorer *);
+
+/* Supprime toutes les références externes. */
+static void g_content_explorer_dispose(GContentExplorer *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_content_explorer_finalize(GContentExplorer *);
+
+/* Retrouve le groupe correspondant à un identifiant donné. */
+static exploring_group *g_content_explorer_find_group(GContentExplorer *, gid_t);
+
+/* Note la fin d'une phase d'exploration de contenu. */
+static void g_content_explorer_ack(GContentExplorer *, GExploringWork *);
+
+
+
+/* ------------------------- TACHE DE RESOLUTION DE CONTENU ------------------------- */
+
+
+#define G_TYPE_RESOLVING_WORK g_resolving_work_get_type()
+#define G_RESOLVING_WORK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RESOLVING_WORK, GResolvingWork))
+#define G_IS_RESOLVING_WORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RESOLVING_WORK))
+#define G_RESOLVING_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RESOLVING_WORK, GResolvingWorkClass))
+#define G_IS_RESOLVING_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RESOLVING_WORK))
+#define G_RESOLVING_WORK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RESOLVING_WORK, GResolvingWorkClass))
+
+
+/* Conversion de contenu binaire en contenu chargé (instance) */
+typedef struct _GResolvingWork
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ const gid_t *gid; /* Groupe d'appartenance */
+
+ GBinContent *content; /* Contenu brut à disposition */
+
+} GResolvingWork;
+
+/* Conversion de contenu binaire en contenu chargé (classe) */
+typedef struct _GResolvingWorkClass
{
GDelayedWorkClass parent; /* A laisser en premier */
+} GResolvingWorkClass;
+
+
+/* Indique le type défini pour la conversion de contenu binaire en contenu chargé. */
+GType g_resolving_work_get_type(void);
+
+/* Initialise la classe des tâches de conversion de contenu. */
+static void g_resolving_work_class_init(GResolvingWorkClass *);
+
+/* Initialise une tâche de conversion de contenu. */
+static void g_resolving_work_init(GResolvingWork *);
+
+/* Supprime toutes les références externes. */
+static void g_resolving_work_dispose(GResolvingWork *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_resolving_work_finalize(GResolvingWork *);
+
+/* Prépare la conversion non bloquée d'un contenu binaire. */
+static GResolvingWork *g_resolving_work_new(GBinContent *);
+
+/* Fournit l'identifiant du groupe de rattachement de la tâche. */
+static gid_t g_resolving_work_get_group_id(const GResolvingWork *);
+
+/* Définit l'identifiant du groupe de rattachement de la tâche. */
+static void g_resolving_work_set_group_id(GResolvingWork *, const gid_t *);
+
+/* Réalise la conversion effective de formes de contenus. */
+static void g_resolving_work_process(GResolvingWork *, GtkStatusStack *);
+
+
+
+/* ------------------- RESOLUTION DE CONTENUS BINAIRES EN CHARGES ------------------- */
+
+
+/* Regroupement des chargements */
+typedef struct _resolving_group
+{
+ size_t remaining; /* Nombre de tâches restantes */
+
+ const gid_t *gid; /* Groupe d'appartenance */
+
+ GLoadedContent **loaded; /* Contenus reconnus à intégrer*/
+ size_t count; /* Taille de cette liste */
+
+} resolving_group;
+
+/* Résolution de contenus binaires en formats chargés (instance) */
+struct _GContentResolver
+{
+ GObject parent; /* A laisser en premier */
+
+ resolving_group *groups; /* Rassemblement de chargements*/
+ size_t count; /* Nombre de ces groupes */
+ GMutex mutex; /* Accès protégé à la liste */
+
};
+/* Résolution de contenus binaires en formats chargés (classe) */
+struct _GContentResolverClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ /* Signaux */
-/* Indique le type défini pour le chargement non bloquant d'un binaire. */
-GType g_binary_loader_get_type(void);
+ void (* resolved) (GContentResolver *, gid_t);
-/* Initialise la classe des tâches de chargement non bloquant. */
-static void g_binary_loader_class_init(GBinaryLoaderClass *);
+};
+
+
+/* Initialise la classe des résolutions de contenus binaires. */
+static void g_content_resolver_class_init(GContentResolverClass *);
-/* Initialise une tâche de chargement non bloquant d'un binaire. */
-static void g_binary_loader_init(GBinaryLoader *);
+/* Initialise une résolution de contenus binaires. */
+static void g_content_resolver_init(GContentResolver *);
/* Supprime toutes les références externes. */
-static void g_binary_loader_dispose(GBinaryLoader *);
+static void g_content_resolver_dispose(GContentResolver *);
/* Procède à la libération totale de la mémoire. */
-static void g_binary_loader_finalize(GBinaryLoader *);
+static void g_content_resolver_finalize(GContentResolver *);
-/* Réalise le chargement effectif d'un binaire. */
-static void g_binary_loader_process(GBinaryLoader *, GtkStatusStack *);
+/* Retrouve le groupe correspondant à un identifiant donné. */
+static resolving_group *g_content_resolver_find_group(GContentResolver *, gid_t);
+
+/* Note la fin d'une phase de resolution de contenu. */
+static void g_content_resolver_ack(GContentResolver *, GResolvingWork *);
/* ---------------------------------------------------------------------------------- */
-/* AMORCE POUR CHARGEMENT DE CONTENUS */
+/* TACHE D'EXPLORATION DE CONTENU */
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour les tâches de préparations d'étude. */
-G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK);
+/* Indique le type défini pour l'exploration de contenu binaire. */
+G_DEFINE_TYPE(GExploringWork, g_exploring_work, G_TYPE_DELAYED_WORK);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des intégrations de binaires à étudier. *
+* Description : Initialise la classe des tâches d'exploration de contenu. *
* *
* Retour : - *
* *
@@ -159,27 +293,28 @@ G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK);
* *
******************************************************************************/
-static void g_delayed_study_class_init(GDelayedStudyClass *klass)
+static void g_exploring_work_class_init(GExploringWorkClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GDelayedWorkClass *work; /* Version en classe parente */
object = G_OBJECT_CLASS(klass);
- work = G_DELAYED_WORK_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_study_dispose;
- object->finalize = (GObjectFinalizeFunc)g_delayed_study_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_exploring_work_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_exploring_work_finalize;
- work->run = (run_task_fc)g_delayed_study_process;
+ work = G_DELAYED_WORK_CLASS(klass);
+
+ work->run = (run_task_fc)g_exploring_work_process;
}
/******************************************************************************
* *
-* Paramètres : dstudy = instance à initialiser. *
+* Paramètres : work = instance à initialiser. *
* *
-* Description : Initialise une intégration de binaire à étudier. *
+* Description : Initialise une tâche d'exploration de contenu. *
* *
* Retour : - *
* *
@@ -187,16 +322,18 @@ static void g_delayed_study_class_init(GDelayedStudyClass *klass)
* *
******************************************************************************/
-static void g_delayed_study_init(GDelayedStudy *dstudy)
+static void g_exploring_work_init(GExploringWork *work)
{
- dstudy->only_preload = false;
+ work->gid = NULL;
+
+ work->content = NULL;
}
/******************************************************************************
* *
-* Paramètres : binary = instance d'objet GLib à traiter. *
+* Paramètres : work = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -206,19 +343,18 @@ static void g_delayed_study_init(GDelayedStudy *dstudy)
* *
******************************************************************************/
-static void g_delayed_study_dispose(GDelayedStudy *dstudy)
+static void g_exploring_work_dispose(GExploringWork *work)
{
- g_object_unref(G_OBJECT(dstudy->project));
- g_object_unref(G_OBJECT(dstudy->content));
+ g_object_unref(G_OBJECT(work->content));
- G_OBJECT_CLASS(g_delayed_study_parent_class)->dispose(G_OBJECT(dstudy));
+ G_OBJECT_CLASS(g_exploring_work_parent_class)->dispose(G_OBJECT(work));
}
/******************************************************************************
* *
-* Paramètres : binary = instance d'objet GLib à traiter. *
+* Paramètres : work = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -228,40 +364,58 @@ static void g_delayed_study_dispose(GDelayedStudy *dstudy)
* *
******************************************************************************/
-static void g_delayed_study_finalize(GDelayedStudy *dstudy)
+static void g_exploring_work_finalize(GExploringWork *work)
{
- G_OBJECT_CLASS(g_delayed_study_parent_class)->finalize(G_OBJECT(dstudy));
+ G_OBJECT_CLASS(g_exploring_work_parent_class)->finalize(G_OBJECT(work));
}
/******************************************************************************
* *
-* Paramètres : project = projet dont le contenu est à compléter. *
-* content = contenu binaire chargé à analyser. *
-* state = état du contenu à conserver. *
+* Paramètres : content = contenu binaire disponible pour traitements. *
* *
-* Description : Crée une tâche d'intégration de contenu binaire. *
+* Description : Prépare l'exploration non bloquée d'un contenu binaire. *
* *
-* Retour : Tâche créée. *
+* Retour : Tâche de travail mise en place. *
* *
-* Remarques : L'appelant perd la propriété du contenu. *
+* Remarques : - *
* *
******************************************************************************/
-GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content, ProjectContentState state)
+static GExploringWork *g_exploring_work_new(GBinContent *content)
{
- GDelayedStudy *result; /* Tâche à retourner */
+ GExploringWork *result; /* Tâche à retourner */
- result = g_object_new(G_TYPE_DELAYED_STUDY, NULL);
+ result = g_object_new(G_TYPE_EXPLORING_WORK, NULL);
- g_object_ref(G_OBJECT(project));
- result->project = project;
-
- g_object_ref(G_OBJECT(content));
result->content = content;
+ g_object_ref(G_OBJECT(content));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : work = instance à consulter. *
+* *
+* Description : Fournit l'identifiant du groupe de rattachement de la tâche. *
+* *
+* Retour : Identifiant d'un même ensemble d'explorations. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gid_t g_exploring_work_get_group_id(const GExploringWork *work)
+{
+ gid_t result; /* Identifiant à retourner */
+
+ assert(work->gid != NULL);
- result->state = state;
+ result = *work->gid;
return result;
@@ -270,10 +424,63 @@ GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content,
/******************************************************************************
* *
-* Paramètres : dstudy = intégration à mener. *
+* Paramètres : work = instance à compléter. *
+* gid = identifiant d'un même ensemble d'explorations. *
+* *
+* Description : Définit l'identifiant du groupe de rattachement de la tâche. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_exploring_work_set_group_id(GExploringWork *work, const gid_t *gid)
+{
+ work->gid = gid;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : work = encadrement de conversion à mener. *
* status = barre de statut à tenir informée. *
* *
-* Description : Prépare une intégration de binaire au projet courant. *
+* Description : Réalise l'exploration effective de formes de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_exploring_work_process(GExploringWork *work, GtkStatusStack *status)
+{
+ gid_t gid; /* Groupe d'appartenance */
+
+ gid = g_exploring_work_get_group_id(work);
+
+ handle_binary_content(PGA_CONTENT_EXPLORER, work->content, gid, status);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* EXPLORATION NON BLOQUANTE DES CONTENUS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour l'exploration de contenus binaires. */
+G_DEFINE_TYPE(GContentExplorer, g_content_explorer, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe les explorations de contenus binaires. *
* *
* Retour : - *
* *
@@ -281,84 +488,317 @@ GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content,
* *
******************************************************************************/
-static void g_delayed_study_process(GDelayedStudy *dstudy, GtkStatusStack *status)
+static void g_content_explorer_class_init(GContentExplorerClass *klass)
{
- FormatMatchStatus mstatus; /* Statut d'une reconnaissance */
- char *target; /* Sous-traitance requise */
- GBinaryLoader *loader; /* Dispositif de chargement */
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_content_explorer_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_content_explorer_finalize;
+
+ g_signal_new("explored",
+ G_TYPE_CONTENT_EXPLORER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GContentExplorerClass, explored),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : explorer = instance à initialiser. *
+* *
+* Description : Initialise une exploration de contenus binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_explorer_init(GContentExplorer *explorer)
+{
+ explorer->generator = 0;
+
+ explorer->groups = NULL;
+ explorer->count = 0;
+
+ g_mutex_init(&explorer->mutex);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : explorer = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_explorer_dispose(GContentExplorer *explorer)
+{
+ while (explorer->count > 0)
+ g_content_explorer_delete_group(explorer, explorer->groups[0].gid);
+
+ if (explorer->groups != NULL)
+ free(explorer->groups);
+
+ g_mutex_clear(&explorer->mutex);
+
+ G_OBJECT_CLASS(g_content_explorer_parent_class)->dispose(G_OBJECT(explorer));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : explorer = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_explorer_finalize(GContentExplorer *explorer)
+{
+ G_OBJECT_CLASS(g_content_explorer_parent_class)->finalize(G_OBJECT(explorer));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un gestionnaire des explorations de contenus binaires. *
+* *
+* Retour : Instance mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GContentExplorer *g_content_explorer_new(void)
+{
+ GContentExplorer *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_CONTENT_EXPLORER, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : explorer = gestionnaire d'explorations à consulter. *
+* gid = identifiant du groupe recherché. *
+* *
+* Description : Retrouve le groupe correspondant à un identifiant donné. *
+* *
+* Retour : Groupe trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static exploring_group *g_content_explorer_find_group(GContentExplorer *explorer, gid_t gid)
+{
+ exploring_group *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+
+ assert(!g_mutex_trylock(&explorer->mutex));
+
+ result = NULL;
+
+ for (i = 0; i < explorer->count && result == NULL; i++)
+ if (explorer->groups[i].gid == gid)
+ result = &explorer->groups[i];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : explorer = gestionnaire d'explorations à consulter. *
+* work = exploration qui vient de se terminer. *
+* *
+* Description : Note la fin d'une phase d'exploration de contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_explorer_ack(GContentExplorer *explorer, GExploringWork *work)
+{
+ gid_t gid; /* Groupe d'appartenance */
+ exploring_group *group; /* Groupe d'opération concerné */
GWorkQueue *queue; /* Gestionnaire de différés */
+ bool empty; /* Fin de l'exploration ? */
- mstatus = find_matching_format(dstudy->content, NULL, &target);
+ gid = g_exploring_work_get_group_id(work);
- switch (mstatus)
- {
- case FMS_MATCHED:
+ g_mutex_lock(&explorer->mutex);
- if (dstudy->only_preload)
- g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state);
+ group = g_content_explorer_find_group(explorer, gid);
+ assert(group != NULL);
- else
- {
- loader = g_binary_loader_new(dstudy->content, dstudy->project);
+ queue = get_work_queue();
- queue = get_work_queue();
- g_work_queue_schedule_work(queue, G_DELAYED_WORK(loader), DEFAULT_WORK_GROUP);
+ empty = g_work_queue_is_empty(queue, group->wid);
- }
+ g_mutex_unlock(&explorer->mutex);
- break;
+ if (empty)
+ g_signal_emit_by_name(explorer, "explored", gid);
- case FMS_FORWARDED:
- /**
- * L'émetteur de ce type de réponse a pour charge de
- * reprogrammer lui même l'analyse de nouveaux contenus.
- */
- log_variadic_message(LMT_PROCESS, _("binary '%s' contains other binaries..."),
- g_binary_content_describe(dstudy->content, true));
+}
- if (dstudy->state == PCS_ROOT)
- g_study_project_add_binary_content(dstudy->project, dstudy->content, PCS_ROOT);
- break;
+/******************************************************************************
+* *
+* Paramètres : explorer = gestionnaire d'explorations à manipuler. *
+* content = contenu initial à découvrir. *
+* *
+* Description : Initie une nouvelle vague d'exploration de contenu. *
+* *
+* Retour : Identifiant du nouveau groupe mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const gid_t *g_content_explorer_create_group(GContentExplorer *explorer, GBinContent *content)
+{
+ const gid_t *result; /* Identifiant à retourner */
+ gid_t loop; /* Détection de boucle */
+ gid_t id; /* Nouvelle identifiant généré */
+ exploring_group *group; /* Groupe ciblé par l'opération*/
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ GExploringWork *work; /* Nouvelle vague d'exploration*/
+
+ g_mutex_lock(&explorer->mutex);
+
+ /* Récupération d'un identifiant libre */
+
+ /**
+ * Note :
+ *
+ * Comme 0 est l'identifiant du groupe de travail par défaut (DEFAULT_WORK_GROUP)
+ * et qu'il n'est pas possible de bloquer ce groupe lors des appels à
+ * g_work_queue_is_empty(), on différencie les identifiants de groupes
+ * de contenus et les identifiants de groupes de travail.
+ */
+
+ loop = explorer->generator;
+
+ do
+ {
+ id = ++explorer->generator;
+
+ /* Verification de la satisfaisabilité de la création */
+
+ assert(id != loop);
+
+ /* Vérification que la place est libre... */
+
+ group = g_content_explorer_find_group(explorer, id);
- default:
- /**
- * Les jeux sont faits pour le contenu binaire courant.
- */
- log_variadic_message(LMT_PROCESS, _("Unknown binary format for '%s'..."),
- g_binary_content_describe(dstudy->content, true));
+ if (group == NULL)
break;
}
+ while (1);
+
+ /* Mise en place du groupe */
+
+ explorer->groups = (exploring_group *)realloc(explorer->groups, ++explorer->count * sizeof(exploring_group));
+
+ group = &explorer->groups[explorer->count - 1];
+
+ group->original = content;
+ g_object_ref(G_OBJECT(content));
+
+ queue = get_work_queue();
+
+ group->wid = g_work_queue_define_work_group(queue);
+ group->gid = id;
+
+ result = &group->gid;
+
+ group->contents = NULL;
+ group->count = 0;
+
+ /* Alimentation du contenu initial */
+
+ work = g_exploring_work_new(content);
+ g_exploring_work_set_group_id(work, &group->gid);
+
+ g_signal_connect_swapped(work, "work-completed", G_CALLBACK(g_content_explorer_ack), explorer);
+
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), group->wid);
+
+ g_mutex_unlock(&explorer->mutex);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : dstudy = tâche d'analyse de contenu pour projet à mener. *
+* Paramètres : explorer = gestionnaire d'explorations à manipuler. *
+* gid = identifiant du groupe à consulter. *
* *
-* Description : Limite l'étude et l'intégration d'un contenu binaire. *
+* Description : Fournit l'identifiant attribué pour les tâches parallèles. *
* *
-* Retour : - *
+* Retour : Identifiant des tâches liées au groupe. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_delayed_study_preload_only(GDelayedStudy *dstudy)
+const wgroup_id_t *g_content_explorer_get_group_work_id(GContentExplorer *explorer, gid_t gid)
{
- dstudy->only_preload = true;
+ const wgroup_id_t *result; /* Identifiant à retourner */
+ exploring_group *group; /* Groupe d'opération concerné */
+
+ g_mutex_lock(&explorer->mutex);
+
+ group = g_content_explorer_find_group(explorer, gid);
+ assert(group != NULL);
+
+ result = &group->wid;
+
+ g_mutex_unlock(&explorer->mutex);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : content = contenu binaire chargé à analyser. *
-* state = état du contenu à conserver. *
+* Paramètres : explorer = gestionnaire d'explorations à manipuler. *
+* gid = identifiant du groupe à supprimer. *
* *
-* Description : Programme l'étude et l'intégration d'un contenu binaire. *
+* Description : Termine une vague d'exploration de contenu. *
* *
* Retour : - *
* *
@@ -366,60 +806,162 @@ void g_delayed_study_preload_only(GDelayedStudy *dstudy)
* *
******************************************************************************/
-void qck_study_new_content(GBinContent *content, ProjectContentState state)
+void g_content_explorer_delete_group(GContentExplorer *explorer, gid_t gid)
{
- GStudyProject *project; /* Projet courant */
- GDelayedStudy *dstudy; /* Etude à conduire */
- project = get_current_project();
- dstudy = g_delayed_study_new(project, content, state);
- g_object_unref(G_OBJECT(project));
+ exploring_group *group; /* Groupe ciblé par l'opération*/
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ size_t i; /* Boucle de parcours */
+ size_t index; /* Indice des paramètres */
+
+ g_mutex_lock(&explorer->mutex);
+
+ group = g_content_explorer_find_group(explorer, gid);
+
+ /* Supression des contenus chargés */
+
+ queue = get_work_queue();
+
+ g_work_queue_delete_work_group(queue, group->wid);
+
+ for (i = 0; i < group->count; i++)
+ g_object_unref(G_OBJECT(group->contents[i]));
+
+ /* Réorganisation de la liste */
+
+ index = group - explorer->groups;
+
+ if ((index + 1) < explorer->count)
+ memmove(&explorer->groups[index], &explorer->groups[index + 1],
+ (explorer->count - index - 1) * sizeof(exploring_group));
+
+ explorer->groups = (exploring_group *)realloc(explorer->groups,
+ --explorer->count * sizeof(exploring_group));
- study_new_content(dstudy);
+ /* Sortie */
+
+ g_mutex_unlock(&explorer->mutex);
}
/******************************************************************************
* *
-* Paramètres : content = contenu binaire chargé à analyser. *
-* state = état du contenu à conserver. *
+* Paramètres : explorer = gestionnaire d'explorations à consulter. *
+* gid = identifiant du groupe à parcourir. *
+* content = nouveau contenu à intégrer. *
* *
-* Description : Programme l'étude et l'intégration d'un contenu binaire. *
+* Description : Ajoute un nouveau contenu découvert au crédit d'un groupe. *
* *
* Retour : - *
* *
-* Remarques : - *
+* Remarques : La propritété du contenu fourni est cédée. *
* *
******************************************************************************/
-void study_new_content(GDelayedStudy *dstudy)
+void g_content_explorer_populate_group(GContentExplorer *explorer, gid_t gid, GBinContent *content)
{
+ exploring_group *group; /* Groupe d'opération concerné */
GWorkQueue *queue; /* Gestionnaire de différés */
+ GExploringWork *work; /* Nouvelle vague d'exploration*/
+
+ g_mutex_lock(&explorer->mutex);
+
+ group = g_content_explorer_find_group(explorer, gid);
+ assert(group != NULL);
+
+ /* Conservation du résultat */
+
+ group->contents = (GBinContent **)realloc(group->contents, ++group->count * sizeof(GBinContent *));
+
+ group->contents[group->count - 1] = content;
+
+ /* Relancement des explorations */
+
+ work = g_exploring_work_new(content);
+ g_exploring_work_set_group_id(work, &group->gid);
+
+ g_signal_connect_swapped(work, "work-completed", G_CALLBACK(g_content_explorer_ack), explorer);
queue = get_work_queue();
- g_work_queue_schedule_work(queue, G_DELAYED_WORK(dstudy), DEFAULT_WORK_GROUP);
+
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), group->wid);
+
+ g_mutex_unlock(&explorer->mutex);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : explorer = gestionnaire d'explorations à consulter. *
+* gid = identifiant du groupe à parcourir. *
+* count = nombre de contenus binaires retournés. [OUT] *
+* *
+* Description : Fournit la liste de tous les contenus disponibles. *
+* *
+* Retour : Liste de contenus binaires enregistrés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent **g_content_explorer_get_all(GContentExplorer *explorer, gid_t gid, size_t *count)
+{
+ GBinContent **result; /* Trouvailles à retourner */
+ exploring_group *group; /* Groupe d'opération concerné */
+ size_t i; /* Boucle de parcours */
+
+ g_mutex_lock(&explorer->mutex);
+
+ group = g_content_explorer_find_group(explorer, gid);
+ assert(group != NULL);
+
+ /* Allocation de la liste finale */
+
+ *count = 1 + group->count;
+ result = (GBinContent **)malloc(*count * sizeof(GBinContent *));
+
+ /* On regarde déjà du côté de la source */
+
+ result[0] = group->original;
+
+ g_object_ref(G_OBJECT(result[0]));
+
+ /* On parcourt les éventuels contenus encapsulés découverts */
+
+ for (i = 0; i < group->count; i++)
+ {
+ result[1 + i] = group->contents[i];
+
+ g_object_ref(G_OBJECT(result[i + 1]));
+
+ }
+
+ g_mutex_unlock(&explorer->mutex);
+
+ return result;
}
/* ---------------------------------------------------------------------------------- */
-/* CHARGEMENT DE BINAIRE NON BLOQUANT */
+/* TACHE DE RESOLUTION DE CONTENU */
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour le chargement non bloquant d'un binaire. */
-G_DEFINE_TYPE(GBinaryLoader, g_binary_loader, G_TYPE_DELAYED_WORK);
+/* Indique le type défini pour la conversion de contenu binaire en contenu chargé. */
+G_DEFINE_TYPE(GResolvingWork, g_resolving_work, G_TYPE_DELAYED_WORK);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des tâches de chargement non bloquant. *
+* Description : Initialise la classe des tâches de conversion de contenu. *
* *
* Retour : - *
* *
@@ -427,28 +969,28 @@ G_DEFINE_TYPE(GBinaryLoader, g_binary_loader, G_TYPE_DELAYED_WORK);
* *
******************************************************************************/
-static void g_binary_loader_class_init(GBinaryLoaderClass *klass)
+static void g_resolving_work_class_init(GResolvingWorkClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GDelayedWorkClass *work; /* Version en classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_loader_dispose;
- object->finalize = (GObjectFinalizeFunc)g_binary_loader_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_resolving_work_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_resolving_work_finalize;
work = G_DELAYED_WORK_CLASS(klass);
- work->run = (run_task_fc)g_binary_loader_process;
+ work->run = (run_task_fc)g_resolving_work_process;
}
/******************************************************************************
* *
-* Paramètres : loader = instance à initialiser. *
+* Paramètres : work = instance à initialiser. *
* *
-* Description : Initialise une tâche de chargement non bloquant d'un binaire.*
+* Description : Initialise une tâche de conversion de contenu. *
* *
* Retour : - *
* *
@@ -456,16 +998,18 @@ static void g_binary_loader_class_init(GBinaryLoaderClass *klass)
* *
******************************************************************************/
-static void g_binary_loader_init(GBinaryLoader *loader)
+static void g_resolving_work_init(GResolvingWork *work)
{
- loader->binary = NULL;
+ work->gid = NULL;
+
+ work->content = NULL;
}
/******************************************************************************
* *
-* Paramètres : loader = instance d'objet GLib à traiter. *
+* Paramètres : work = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -475,24 +1019,18 @@ static void g_binary_loader_init(GBinaryLoader *loader)
* *
******************************************************************************/
-static void g_binary_loader_dispose(GBinaryLoader *loader)
+static void g_resolving_work_dispose(GResolvingWork *work)
{
- if (loader->from_content)
- g_object_unref(G_OBJECT(loader->content));
-
- g_object_unref(G_OBJECT(loader->project));
-
- if (loader->binary != NULL)
- g_object_unref(G_OBJECT(loader->binary));
+ g_object_unref(G_OBJECT(work->content));
- G_OBJECT_CLASS(g_binary_loader_parent_class)->dispose(G_OBJECT(loader));
+ G_OBJECT_CLASS(g_resolving_work_parent_class)->dispose(G_OBJECT(work));
}
/******************************************************************************
* *
-* Paramètres : loader = instance d'objet GLib à traiter. *
+* Paramètres : work = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -502,45 +1040,58 @@ static void g_binary_loader_dispose(GBinaryLoader *loader)
* *
******************************************************************************/
-static void g_binary_loader_finalize(GBinaryLoader *loader)
+static void g_resolving_work_finalize(GResolvingWork *work)
{
- if (!loader->from_content)
- {
- free(loader->filename);
- free(loader->path);
- }
-
- G_OBJECT_CLASS(g_binary_loader_parent_class)->finalize(G_OBJECT(loader));
+ G_OBJECT_CLASS(g_resolving_work_parent_class)->finalize(G_OBJECT(work));
}
/******************************************************************************
* *
-* Paramètres : content = contenu binaire chargé en mémoire. *
-* project = projet dans lequel venir ajouter des contenus. *
+* Paramètres : content = contenu binaire disponible pour traitements. *
* *
-* Description : Prépare le chargement non bloqué d'un contenu binaire. *
+* Description : Prépare la conversion non bloquée d'un contenu binaire. *
* *
-* Retour : Instance de binaire chargé ou NULL en cas d'échec. *
+* Retour : Tâche de travail mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-GBinaryLoader *g_binary_loader_new(GBinContent *content, GStudyProject *project)
+static GResolvingWork *g_resolving_work_new(GBinContent *content)
{
- GBinaryLoader *result; /* Tâche à retourner */
-
- result = g_object_new(G_TYPE_BINARY_LOADER, NULL);
+ GResolvingWork *result; /* Tâche à retourner */
- result->from_content = true;
+ result = g_object_new(G_TYPE_RESOLVING_WORK, NULL);
result->content = content;
g_object_ref(G_OBJECT(content));
- result->project = project;
- g_object_ref(G_OBJECT(project));
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : work = instance à consulter. *
+* *
+* Description : Fournit l'identifiant du groupe de rattachement de la tâche. *
+* *
+* Retour : Identifiant d'un même ensemble de conversions. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gid_t g_resolving_work_get_group_id(const GResolvingWork *work)
+{
+ gid_t result; /* Identifiant à retourner */
+
+ assert(work->gid != NULL);
+
+ result = *work->gid;
return result;
@@ -549,31 +1100,202 @@ GBinaryLoader *g_binary_loader_new(GBinContent *content, GStudyProject *project)
/******************************************************************************
* *
-* Paramètres : filename = chemin d'accès au fichier à charger. *
-* path = chemin d'accès au noeud XML à lire. *
-* project = projet dans lequel venir rechercher les contenus. *
+* Paramètres : work = instance à compléter. *
+* gid = identifiant d'un même ensemble de conversions. *
+* *
+* Description : Définit l'identifiant du groupe de rattachement de la tâche. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_resolving_work_set_group_id(GResolvingWork *work, const gid_t *gid)
+{
+ work->gid = gid;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : work = encadrement de conversion à mener. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Réalise la conversion effective de formes de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_resolving_work_process(GResolvingWork *work, GtkStatusStack *status)
+{
+ gid_t gid; /* Groupe d'appartenance */
+
+ gid = g_resolving_work_get_group_id(work);
+
+ handle_binary_content(PGA_CONTENT_RESOLVER, work->content, gid, status);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RESOLUTION DE CONTENUS BINAIRES EN CHARGES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour la résolution de contenus binaires en formats chargés. */
+G_DEFINE_TYPE(GContentResolver, g_content_resolver, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des résolutions de contenus binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_resolver_class_init(GContentResolverClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_content_resolver_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_content_resolver_finalize;
+
+ g_signal_new("resolved",
+ G_TYPE_CONTENT_RESOLVER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GContentResolverClass, resolved),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = instance à initialiser. *
+* *
+* Description : Initialise une résolution de contenus binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_resolver_init(GContentResolver *resolver)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_resolver_dispose(GContentResolver *resolver)
+{
+ while (resolver->count > 0)
+ g_content_resolver_delete_group(resolver, *resolver->groups[0].gid);
+
+ if (resolver->groups != NULL)
+ free(resolver->groups);
+
+ g_mutex_clear(&resolver->mutex);
+
+ G_OBJECT_CLASS(g_content_resolver_parent_class)->dispose(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_resolver_finalize(GContentResolver *resolver)
+{
+ G_OBJECT_CLASS(g_content_resolver_parent_class)->finalize(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
* *
-* Description : Prépare le chargement non bloqué d'un contenu XML. *
+* Description : Crée un gestionnaire des résolutions de contenus binaires. *
* *
-* Retour : Instance de binaire chargé ou NULL en cas d'échec. *
+* Retour : Instance mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-GBinaryLoader *g_binary_loader_new_from_xml(const char *filename, const char *path, GStudyProject *project)
+GContentResolver *g_content_resolver_new(void)
{
- GBinaryLoader *result; /* Tâche à retourner */
+ GContentResolver *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_CONTENT_RESOLVER, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = gestionnaire de résolutions à consulter. *
+* gid = identifiant du groupe recherché. *
+* *
+* Description : Retrouve le groupe correspondant à un identifiant donné. *
+* *
+* Retour : Groupe trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- result = g_object_new(G_TYPE_BINARY_LOADER, NULL);
+static resolving_group *g_content_resolver_find_group(GContentResolver *resolver, gid_t gid)
+{
+ resolving_group *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
- result->from_content = false;
+ assert(!g_mutex_trylock(&resolver->mutex));
- result->filename = strdup(filename);
- result->path = strdup(path);
+ result = NULL;
- result->project = project;
- g_object_ref(G_OBJECT(project));
+ for (i = 0; i < resolver->count && result == NULL; i++)
+ if (*resolver->groups[i].gid == gid)
+ result = &resolver->groups[i];
return result;
@@ -582,10 +1304,51 @@ GBinaryLoader *g_binary_loader_new_from_xml(const char *filename, const char *pa
/******************************************************************************
* *
-* Paramètres : loader = encadrement du chargement à mener. *
-* status = barre de statut à tenir informée. *
+* Paramètres : resolver = gestionnaire de résolutions à consulter. *
+* work = resolvation qui vient de se terminer. *
+* *
+* Description : Note la fin d'une phase de resolution de contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_resolver_ack(GContentResolver *resolver, GResolvingWork *work)
+{
+ gid_t gid; /* Groupe d'appartenance */
+ resolving_group *group; /* Groupe d'opération concerné */
+ bool empty; /* Fin de l'resolvation ? */
+
+ gid = g_resolving_work_get_group_id(work);
+
+ g_mutex_lock(&resolver->mutex);
+
+ group = g_content_resolver_find_group(resolver, gid);
+ assert(group != NULL);
+
+ assert(group->remaining > 0);
+
+ empty = (--group->remaining == 0);
+
+ g_mutex_unlock(&resolver->mutex);
+
+ if (empty)
+ g_signal_emit_by_name(resolver, "resolved", gid);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = gestionnaire de résolutions à manipuler. *
+* wid = identifiant du groupe de tâches réservé. *
+* gid = identifiant unique généré en amont. *
+* contents = contenus à analyser. *
+* count = nombre de ces contenus. *
* *
-* Description : Réalise le chargement effectif d'un binaire. *
+* Description : Initie une nouvelle vague de résolution de contenus. *
* *
* Retour : - *
* *
@@ -593,76 +1356,166 @@ GBinaryLoader *g_binary_loader_new_from_xml(const char *filename, const char *pa
* *
******************************************************************************/
-static void g_binary_loader_process(GBinaryLoader *loader, GtkStatusStack *status)
+void g_content_resolver_create_group(GContentResolver *resolver, const wgroup_id_t *wid, const gid_t *gid, GBinContent **contents, size_t count)
{
- xmlDocPtr xdoc; /* Structure XML chargée */
- xmlXPathContextPtr context; /* Contexte pour les XPath */
- GLoadedBinary *binary; /* Binaire désormais en place */
+ resolving_group *group; /* Groupe ciblé par l'opération*/
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ size_t i; /* Boucle de parcours */
+ GResolvingWork *work; /* Nouvelle vague de résolution*/
+
+ g_mutex_lock(&resolver->mutex);
+
+ /* Mise en place du groupe */
+
+ resolver->groups = (resolving_group *)realloc(resolver->groups, ++resolver->count * sizeof(resolving_group));
- /* Tentative de chargement de binaire */
+ group = &resolver->groups[resolver->count - 1];
- if (loader->from_content)
- loader->binary = g_loaded_binary_new(loader->content);
+ group->remaining = count;
- else
+ group->gid = gid;
+
+ group->loaded = NULL;
+ group->count = 0;
+
+ /* Alimentation du contenu initial */
+
+ queue = get_work_queue();
+
+ for (i = 0; i < count; i++)
{
- if (open_xml_file(loader->filename, &xdoc, &context))
- {
- loader->binary = g_loaded_binary_new_from_xml(context, loader->path, loader->project);
+ work = g_resolving_work_new(contents[i]);
+ g_resolving_work_set_group_id(work, gid);
- close_xml_file(xdoc, context);
+ g_signal_connect_swapped(work, "work-completed", G_CALLBACK(g_content_resolver_ack), resolver);
- }
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), *wid);
}
- /* Poursuites qui peuvent être traitées dans la foulée */
+ g_mutex_unlock(&resolver->mutex);
- if (loader->binary != NULL)
- {
- /* Si le contenu n'a pas déjà été ajouté au projet au moment du chargement de ce dernier... */
- if (loader->from_content)
- g_study_project_add_binary_content(loader->project, loader->content, PCS_ROOT/* FIXME : dstudy->state*/);
+}
- binary = g_binary_loader_get_result(loader);
- if (binary != NULL)
- {
- g_signal_connect_to_main_swapped(binary, "disassembly-done",
- G_CALLBACK(g_study_project_attach_content), loader->project,
- g_cclosure_marshal_VOID__VOID);
+/******************************************************************************
+* *
+* Paramètres : resolver = gestionnaire d'explorations à manipuler. *
+* gid = identifiant du groupe à supprimer. *
+* *
+* Description : Termine une vague de résolution de contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_loaded_binary_analyse(binary);
+void g_content_resolver_delete_group(GContentResolver *resolver, gid_t gid)
+{
+ resolving_group *group; /* Groupe ciblé par l'opération*/
+ size_t i; /* Boucle de parcours */
+ size_t index; /* Indice des paramètres */
- g_object_unref(G_OBJECT(binary));
+ g_mutex_lock(&resolver->mutex);
- }
+ group = g_content_resolver_find_group(resolver, gid);
- }
+ /* Supression des contenus chargés */
+
+ for (i = 0; i < group->count; i++)
+ g_object_unref(G_OBJECT(group->loaded[i]));
+
+ /* Réorganisation de la liste */
+
+ index = group - resolver->groups;
+
+ if ((index + 1) < resolver->count)
+ memmove(&resolver->groups[index], &resolver->groups[index + 1],
+ (resolver->count - index - 1) * sizeof(resolving_group));
+
+ resolver->groups = (resolving_group *)realloc(resolver->groups,
+ --resolver->count * sizeof(resolving_group));
+
+ /* Sortie */
+
+ g_mutex_unlock(&resolver->mutex);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = gestionnaire de résolutions à consulter. *
+* gid = identifiant du groupe recherché. *
+* loaded = contenu chargé et pouvant être représenté. *
+* *
+* Description : Intègre un contenu chargé dans les résultats. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_content_resolver_add_detected(GContentResolver *resolver, gid_t gid, GLoadedContent *loaded)
+{
+ resolving_group *group; /* Groupe ciblé par l'opération*/
+
+ g_mutex_lock(&resolver->mutex);
+
+ group = g_content_resolver_find_group(resolver, gid);
+
+ group->loaded = (GLoadedContent **)realloc(group->loaded, ++group->count * sizeof(GLoadedContent *));
+
+ group->loaded[group->count - 1] = loaded;
+
+ g_mutex_unlock(&resolver->mutex);
}
/******************************************************************************
* *
-* Paramètres : loader = encadrement du chargement à consulter. *
+* Paramètres : resolver = gestionnaire de resolutions à consulter. *
+* gid = identifiant du groupe à parcourir. *
+* count = nombre de contenus binaires retournés. [OUT] *
* *
-* Description : Retourne l'instance du binaire chargé en cas de succès. *
+* Description : Fournit la liste de tous les contenus chargés valables. *
* *
-* Retour : Instance mise en place ou NULL. *
+* Retour : Liste de contenus chargés enregistrés. *
* *
* Remarques : - *
* *
******************************************************************************/
-GLoadedBinary *g_binary_loader_get_result(const GBinaryLoader *loader)
+GLoadedContent **g_content_resolver_get_all(GContentResolver *resolver, gid_t gid, size_t *count)
{
- GLoadedBinary *result; /* Chargement à faire suivre */
+ GLoadedContent **result; /* Trouvailles à retourner */
+ resolving_group *group; /* Groupe d'opération concerné */
+ size_t i; /* Boucle de parcours */
- result = loader->binary;
+ g_mutex_lock(&resolver->mutex);
+
+ group = g_content_resolver_find_group(resolver, gid);
+ assert(group != NULL);
+
+ /* Allocation de la liste finale */
+
+ *count = group->count;
+ result = (GLoadedContent **)malloc(*count * sizeof(GLoadedContent *));
+
+ /* On parcourt les éventuels contenus encapsulés découverts */
+
+ for (i = 0; i < group->count; i++)
+ {
+ result[i] = group->loaded[i];
+
+ g_object_ref(G_OBJECT(result[i]));
+
+ }
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
+ g_mutex_unlock(&resolver->mutex);
return result;