diff options
Diffstat (limited to 'src/analysis/loading.c')
-rw-r--r-- | src/analysis/loading.c | 1337 |
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; |