diff options
Diffstat (limited to 'src/analysis/project.c')
-rw-r--r-- | src/analysis/project.c | 846 |
1 files changed, 680 insertions, 166 deletions
diff --git a/src/analysis/project.c b/src/analysis/project.c index 09b4aad..88b468a 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -25,7 +25,6 @@ #include <assert.h> -#include <inttypes.h> #include <malloc.h> #include <string.h> @@ -33,40 +32,33 @@ #include <i18n.h> -#include "loaded.h" #include "loading.h" #include "../common/xml.h" #include "../core/global.h" #include "../core/logs.h" #include "../core/params.h" -#include "../glibext/delayed-int.h" -#include "../gui/core/panels.h" -#include "../gui/panels/panel.h" -#include "../format/format.h" /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */ -/* Conservation d'un contenu chargé */ -typedef struct _loaded_content +/* Suivi du chargement de contenus binaires */ +typedef struct _loading_params { - GBinContent *content; /* Contenu binaire en place */ - ProjectContentState state; /* Renseigne le type de contenu*/ - -} loaded_content; - -/* Conservation d'un binaire chargé */ -typedef struct _loaded_binary -{ - GLoadedBinary *binary; /* Binaire en question */ + union + { + const gid_t *exp_gid; /* Identifiant d'exploration */ + const gid_t **exp_gids; /* Identifiants d'exploration */ + }; + size_t exp_count; /* Quantitié d'identifiants */ - GPanelItem **items; /* Supports d'affichage final */ - size_t count; /* Nombre de ces supports */ + size_t resolved; /* Compteur de résolutions */ -} loaded_binary; + xmlDoc *xdoc; /* Structure XML chargée ? */ + xmlXPathContext *context; /* Eventuel contexte XML */ +} loading_params; /* Projet d'étude regroupant les binaires analysés (instance) */ struct _GStudyProject @@ -75,6 +67,10 @@ struct _GStudyProject char *filename; /* Lieu d'enregistrement */ + loading_params *ld_params; /* Infos d'accompagnement */ + size_t ld_count; /* Quantité de ces infos */ + GMutex ld_mutex; /* Encadrement des accès */ + GLoadedContent **contents; /* Contenus chargés et intégrés*/ size_t count; /* Quantité de ces contenus */ GMutex mutex; /* Encadrement des accès */ @@ -101,6 +97,38 @@ static void g_study_project_class_init(GStudyProjectClass *); /*Initialise une instance de projet d'étude. */ static void g_study_project_init(GStudyProject *); +/* Supprime toutes les références externes. */ +static void g_study_project_dispose(GStudyProject *); + +/* Procède à la libération totale de la mémoire. */ +static void g_study_project_finalize(GStudyProject *); + + + +/* ------------------------ INTEGRATION DE CONTENUS BINAIRES ------------------------ */ + + +/* Prépare le suivi d'une nouvelle phase d'intégration. */ +static loading_params *g_study_project_prepare_content_loading(GStudyProject *); + +/* Efface le suivi d'une phase d'intégration obsolète. */ +static void g_study_project_destroy_content_loading(GStudyProject *, loading_params *); + +/* Retrouve les infos de chargements liées à une exploration. */ +static loading_params *g_study_project_find_exploration(GStudyProject *, gid_t, const gid_t **); + +/* Assure l'intégration de contenus listés dans du XML. */ +static void g_study_project_recover_binary_contents(GStudyProject *, xmlDoc *, xmlXPathContext *); + +/* Note la fin d'une phase d'exploration de contenu. */ +static void on_new_content_explored(GContentExplorer *, gid_t, GStudyProject *); + +/* Note la fin d'une phase de resolution de contenu. */ +static void on_new_content_resolved(GContentResolver *, gid_t, GStudyProject *); + +/* Réceptionne la recette d'une analyse de contenu. */ +static void on_loaded_content_analyzed(GLoadedContent *, gboolean, GStudyProject *); + /* ---------------------------------------------------------------------------------- */ @@ -126,6 +154,13 @@ G_DEFINE_TYPE(GStudyProject, g_study_project, G_TYPE_OBJECT); static void g_study_project_class_init(GStudyProjectClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_study_project_dispose; + object->finalize = (GObjectFinalizeFunc)g_study_project_finalize; + g_signal_new("content-added", G_TYPE_STUDY_PROJECT, G_SIGNAL_RUN_LAST, @@ -159,8 +194,104 @@ static void g_study_project_class_init(GStudyProjectClass *klass) static void g_study_project_init(GStudyProject *project) { + GContentExplorer *explorer; /* Explorateur de contenus */ + GContentResolver *resolver; /* Resolveur de contenus */ + + project->filename = NULL; + + project->ld_params = NULL; + project->ld_count = 0; + g_mutex_init(&project->ld_mutex); + + project->contents = NULL; + project->count = 0; g_mutex_init(&project->mutex); + explorer = get_current_content_explorer(); + g_signal_connect(explorer, "explored", G_CALLBACK(on_new_content_explored), project); + g_object_unref(G_OBJECT(explorer)); + + resolver = get_current_content_resolver(); + g_signal_connect(resolver, "resolved", G_CALLBACK(on_new_content_resolved), project); + g_object_unref(G_OBJECT(resolver)); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_study_project_dispose(GStudyProject *project) +{ + GContentExplorer *explorer; /* Explorateur de contenus */ + GContentResolver *resolver; /* Resolveur de contenus */ + size_t i; /* Boucle de parcours */ + + explorer = get_current_content_explorer(); + g_signal_handlers_disconnect_by_func(explorer, G_CALLBACK(on_new_content_explored), project); + g_object_unref(G_OBJECT(explorer)); + + resolver = get_current_content_resolver(); + g_signal_handlers_disconnect_by_func(resolver, G_CALLBACK(on_new_content_resolved), project); + g_object_unref(G_OBJECT(resolver)); + + g_mutex_lock(&project->ld_mutex); + + while (project->ld_count > 0) + g_study_project_destroy_content_loading(project, project->ld_params); + + if (project->ld_params != NULL) + free(project->ld_params); + + g_mutex_unlock(&project->ld_mutex); + + g_mutex_clear(&project->ld_mutex); + + g_mutex_lock(&project->mutex); + + for (i = 0; i < project->count; i++) + g_object_unref(G_OBJECT(project->contents[i])); + + if (project->contents != NULL) + free(project->contents); + + g_mutex_unlock(&project->mutex); + + g_mutex_clear(&project->mutex); + + G_OBJECT_CLASS(g_study_project_parent_class)->dispose(G_OBJECT(project)); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_study_project_finalize(GStudyProject *project) +{ + if (project->filename != NULL) + free(project->filename); + + G_OBJECT_CLASS(g_study_project_parent_class)->finalize(G_OBJECT(project)); + } @@ -201,25 +332,9 @@ GStudyProject *g_study_project_new(void) GStudyProject *g_study_project_open(const char *filename) { - return NULL; - -#if 0 - GStudyProject *result; /* Adresse à retourner */ - xmlDocPtr xdoc; /* Structure XML chargée */ - xmlXPathContextPtr context; /* Contexte pour les XPath */ - unsigned int root_contents; /* Quantité de contenus majeurs*/ - GAsyncQueue *sema; /* Sémaphore taisant son nom */ - xmlXPathObjectPtr xobject; /* Cible d'une recherche */ - unsigned int i; /* Boucle de parcours */ - size_t access_len; /* Taille d'un chemin interne */ - char *access; /* Chemin pour une sous-config.*/ - GBinContent *content; /* Contenu binaire retrouvé */ - long state; /* Etat de ce contenu binaire */ - bool status; /* Bilan d'une lecture */ - GDelayedStudy *dstudy; /* Etude complémentaire à mener*/ - GBinaryLoader *loader; /* Dispositif de chargement */ - GWorkQueue *queue; /* Gestionnaire de différés */ + xmlDoc *xdoc; /* Structure XML chargée */ + xmlXPathContext *context; /* Contexte pour les XPath */ if (!open_xml_file(filename, &xdoc, &context)) return NULL; @@ -227,186 +342,416 @@ GStudyProject *g_study_project_open(const char *filename) result->filename = strdup(filename); - /* Préparations aux traitements parallèles */ + g_study_project_recover_binary_contents(result, xdoc, context); - root_contents = 0; + return result; - sema = g_async_queue_new(); +} - void ack_content_processing(GDelayedStudy *dstudy, GAsyncQueue *aqueue) - { - g_async_queue_push(aqueue, GINT_TO_POINTER(1)); - } - /* Chargement des contenus binaires attachés */ +/****************************************************************************** +* * +* Paramètres : project = project à sauvegarder. * +* filename = nom de fichier à utiliser ou NULL pour l'existant.* +* * +* Description : Procède à l'enregistrement d'un projet donné. * +* * +* Retour : true si l'enregistrement s'est déroule sans encombre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_study_project_save(GStudyProject *project, const char *filename) +{ + bool result; /* Bilan à retourner */ + xmlDocPtr xdoc; /* Document XML à créer */ + xmlXPathContextPtr context; /* Contexte pour les recherches*/ + const char *final; /* Lieu d'enregistrement final */ + size_t root_count; /* Quantité d'origines */ + size_t i; /* Boucle de parcours */ + GBinContent *content; /* Contenu brut à manipuler */ + GBinContent *root; /* Contenu d'origine à traiter */ + const gchar *hash; /* Empreinte d'un contenu */ + char *access; /* Chemin pour une sous-config.*/ + xmlXPathObjectPtr xobject; /* Cible d'une recherche */ + const char *format; /* Format associé à un élément */ + + /* Forme générale */ + + result = create_new_xml_file(&xdoc, &context); + + if (result) + result = (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL); + + if (result) + result = add_string_attribute_to_node(xdoc, context, "/ChrysalideProject", "version", PROJECT_XML_VERSION); + + if (result) + result = (ensure_node_exist(xdoc, context, "/ChrysalideProject/RootContents") != NULL); + + if (result) + result = (ensure_node_exist(xdoc, context, "/ChrysalideProject/LoadedContents") != NULL); + + final = filename != NULL ? filename : project->filename; + + /* Inscriptions des contenus */ + + root_count = 0; - xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content"); + g_mutex_lock(&project->mutex); - for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) + for (i = 0; i < project->count && result; i++) { - access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1; + content = g_loaded_content_get_content(project->contents[i]); - access = calloc(access_len, sizeof(char)); - snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%u]", i + 1); + /* Racine */ - content = g_binary_content_new_from_xml(context, access, filename); - status = get_node_prop_long_value(context, access, "state", &state); + root = g_binary_content_get_root(content); - free(access); + hash = g_binary_content_get_checksum(root); - if (content == NULL) - { - log_variadic_message(LMT_ERROR, _("Unable to load the binary content #%u ; skipping..."), i); - continue; - } + asprintf(&access, "/ChrysalideProject/RootContents/Content[@hash='%s']", hash); - if (!status) - { - log_variadic_message(LMT_ERROR, _("Bad state for content '%s' ; skipping..."), - g_binary_content_describe(content, true)); - continue; - } + xobject = get_node_xpath_object(context, access); - /* Le contenu peut être un conteneur ? */ - if (state == PCS_ROOT) + free(access); + + if (XPATH_OBJ_NODES_COUNT(xobject) == 0) { - dstudy = g_delayed_study_new(result, content, state); - g_signal_connect(dstudy, "work-completed", G_CALLBACK(ack_content_processing), sema); + asprintf(&access, "/ChrysalideProject/RootContents/Content[position()=%zu]", ++root_count); + + if (result) + result = (ensure_node_exist(xdoc, context, access) != NULL); - g_delayed_study_preload_only(dstudy); + if (result) + { + hash = g_binary_content_get_checksum(content); + result = add_string_attribute_to_node(xdoc, context, access, "hash", hash); + } - root_contents++; + if (result) + result = g_binary_content_save(root, xdoc, context, access, final); - study_new_content(dstudy); + free(access); } - } + if(xobject != NULL) + xmlXPathFreeObject(xobject); - if(xobject != NULL) - xmlXPathFreeObject(xobject); + /* Charge utile */ - /* Attente pour la réception de contenus supplémentaires éventuels */ + asprintf(&access, "/ChrysalideProject/LoadedContents/Content[position()=%zu]", i + 1); - for (i = 0; i < root_contents; i++) - g_async_queue_pop(sema); + if (result) + result = (ensure_node_exist(xdoc, context, access) != NULL); - g_async_queue_unref(sema); + if (result) + { + hash = g_binary_content_get_checksum(content); + result = add_string_attribute_to_node(xdoc, context, access, "hash", hash); + } - /* Chargement des binaires analysés */ + if (result) + { + format = g_loaded_content_get_format_name(project->contents[i]); + result = add_string_attribute_to_node(xdoc, context, access, "format", format); + } - xobject = get_node_xpath_object(context, "/ChrysalideProject/Binaries/Binary"); + if (result) + result = g_loaded_content_save(project->contents[i], xdoc, context, access); - for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) - { - access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1; + free(access); - access = calloc(access_len, sizeof(char)); - snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%u]", i + 1); + g_object_unref(G_OBJECT(content)); - loader = g_binary_loader_new_from_xml(filename, access, result); + } - free(access); + g_mutex_unlock(&project->mutex); - queue = get_work_queue(); - g_work_queue_schedule_work(queue, G_DELAYED_WORK(loader), DEFAULT_WORK_GROUP); + /* Sauvegarde finale */ - } + if (result) + result = save_xml_file(xdoc, final); - if(xobject != NULL) - xmlXPathFreeObject(xobject); + if (result && filename != NULL) + { + if (project->filename != NULL) free(project->filename); + project->filename = strdup(filename); - /* Fin du chargement */ + } close_xml_file(xdoc, context); return result; -#endif +} + + +/****************************************************************************** +* * +* Paramètres : project = project à consulter. * +* * +* Description : Indique le chemin du fichier destiné à la sauvegarde. * +* * +* Retour : Chemin de fichier pour l'enregistrement ou NULL si indéfini. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_study_project_get_filename(const GStudyProject *project) +{ + return project->filename; } + +/* ---------------------------------------------------------------------------------- */ +/* INTEGRATION DE CONTENUS BINAIRES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : project = project à sauvegarder. * -* filename = nom de fichier à utiliser ou NULL pour l'existant.* +* Paramètres : project = projet dont le contenu est à compléter. * * * -* Description : Procède à l'enregistrement d'un projet donné. * +* Description : Prépare le suivi d'une nouvelle phase d'intégration. * * * -* Retour : true si l'enregistrement s'est déroule sans encombre. * +* Retour : Nouvelle structure de suivi prête à être complétée. * * * * Remarques : - * * * ******************************************************************************/ -bool g_study_project_save(GStudyProject *project, const char *filename) +static loading_params *g_study_project_prepare_content_loading(GStudyProject *project) { - return false; + loading_params *result; /* Trouvaille à retourner */ -#if 0 + assert(!g_mutex_trylock(&project->ld_mutex)); - bool result; /* Bilan à retourner */ - xmlDocPtr xdoc; /* Document XML à créer */ - xmlXPathContextPtr context; /* Contexte pour les recherches*/ - const char *final; /* Lieu d'enregistrement final */ - size_t i; /* Boucle de parcours */ - char *access; /* Chemin pour une sous-config.*/ + project->ld_params = (loading_params *)realloc(project->ld_params, + ++project->ld_count * sizeof(loading_params)); - result = create_new_xml_file(&xdoc, &context); + result = &project->ld_params[project->ld_count - 1]; - if (result) - result = (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL); + return result; - final = filename != NULL ? filename : project->filename; +} + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à compléter. * +* params = paramètres de chargemeent à supprimer. * +* * +* Description : Efface le suivi d'une phase d'intégration obsolète. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_study_project_destroy_content_loading(GStudyProject *project, loading_params *params) +{ + GContentExplorer *explorer; /* Explorateur de contenus */ + GContentResolver *resolver; /* Resolveur de contenus */ + size_t i; /* Boucle de parcours */ + size_t index; /* Indice des paramètres */ + + assert(!g_mutex_trylock(&project->ld_mutex)); - /* Enregistrement des binaires analysés */ + /* Supression des groupes de travail */ - for (i = 0; i < project->binaries_count && result; i++) + explorer = get_current_content_explorer(); + resolver = get_current_content_resolver(); + + if (params->exp_count == 1) { - asprintf(&access, "/ChrysalideProject/Binaries/Binary[position()=%zu]", i + 1); + g_content_resolver_delete_group(resolver, *params->exp_gid); + g_content_explorer_delete_group(explorer, *params->exp_gid); + } - result = g_loaded_binary_save(project->binaries[i]->binary, xdoc, context, access, final); + else + { + for (i = 0; i < params->exp_count; i++) + { + g_content_resolver_delete_group(resolver, *params->exp_gids[i]); + g_content_explorer_delete_group(explorer, *params->exp_gids[i]); + } - free(access); + free(params->exp_gids); } - /* Sauvegarde finale */ + g_object_unref(G_OBJECT(explorer)); + g_object_unref(G_OBJECT(resolver)); - result &= save_xml_file(xdoc, final); + /* Fermture de l'éventuel fichier XML de chargement */ - if (result && filename != NULL) + if (params->xdoc != NULL) + close_xml_file(params->xdoc, params->context); + + /* Réorganisation de la liste */ + + index = params - project->ld_params; + + if ((index + 1) < project->ld_count) + memmove(&project->ld_params[index], &project->ld_params[index + 1], + (project->ld_count - index - 1) * sizeof(loading_params)); + + project->ld_params = (loading_params *)realloc(project->ld_params, + --project->ld_count * sizeof(loading_params)); + +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à consulter. * +* gid = identifiant du groupe d'exploration recherché. * +* ptr = pointeur vers la valeur d'origine externe. * +* * +* Description : Retrouve les infos de chargements liées à une exploration. * +* * +* Retour : Informations trouvées ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static loading_params *g_study_project_find_exploration(GStudyProject *project, gid_t gid, const gid_t **ptr) +{ + loading_params *result; /* Trouvaille à retourner */ + const gid_t *value; /* Raccourci de confort */ + size_t i; /* Boucle de parcours #1 */ + size_t k; /* Boucle de parcours #2 */ + + assert(!g_mutex_trylock(&project->ld_mutex)); + + result = NULL; + + value = NULL; + + for (i = 0; i < project->ld_count && result == NULL; i++) { - if (project->filename != NULL) free(project->filename); - project->filename = strdup(filename); + if (project->ld_params[i].exp_count == 1) + { + value = project->ld_params[i].exp_gid; + + if (*value == gid) + result = &project->ld_params[i]; + + } + + else + for (k = 0; k < project->ld_params[i].exp_count && result == NULL; k++) + { + value = project->ld_params[i].exp_gids[k]; + + if (*value == gid) + result = &project->ld_params[i]; + + } } - close_xml_file(xdoc, context); + if (ptr != NULL) + { + assert(result == NULL || value != NULL); + *ptr = (result == NULL ? NULL : value); + } return result; -#endif - } /****************************************************************************** * * -* Paramètres : project = project à consulter. * +* Paramètres : project = projet dont le contenu est à compléter. * +* xdoc = structure XML en cours d'édition. * +* context = contexte à utiliser pour les recherches. * * * -* Description : Indique le chemin du fichier destiné à la sauvegarde. * +* Description : Assure l'intégration de contenus listés dans du XML. * * * -* Retour : Chemin de fichier pour l'enregistrement ou NULL si indéfini. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -const char *g_study_project_get_filename(const GStudyProject *project) +static void g_study_project_recover_binary_contents(GStudyProject *project, xmlDoc *xdoc, xmlXPathContext *context) { - return project->filename; + loading_params *params; /* Informations de chargement */ + xmlXPathObjectPtr xobject; /* Cible d'une recherche */ + size_t count; /* Nombre de contenus premiers */ + GContentExplorer *explorer; /* Explorateur de contenus */ + size_t explored; /* Qté. d'explorations lancées */ + size_t i; /* Boucle de parcours */ + char *access; /* Chemin pour un contenu */ + GBinContent *content; /* Contenu binaire retrouvé */ + + xobject = get_node_xpath_object(context, "/ChrysalideProject/RootContents/Content"); + + count = XPATH_OBJ_NODES_COUNT(xobject); + + if (count > 0) + { + explorer = get_current_content_explorer(); + + g_mutex_lock(&project->ld_mutex); + + params = g_study_project_prepare_content_loading(project); + + if (count > 1) + params->exp_gids = (const gid_t **)malloc(count * sizeof(gid_t *)); + + params->resolved = 0; + + params->xdoc = xdoc; + params->context = context; + + explored = 0; + + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) + { + asprintf(&access, "/ChrysalideProject/RootContents/Content[position()=%zu]", i + 1); + + content = g_binary_content_new_from_xml(context, access, project->filename); + + free(access); + + if (content == NULL) + { + log_variadic_message(LMT_ERROR, _("Unable to load the root content #%zu ; skipping..."), i); + continue; + } + + if (count == 1) + { + params->exp_gid = g_content_explorer_create_group(explorer, content); + explored++; + } + else + params->exp_gids[explored++] = g_content_explorer_create_group(explorer, content); + + g_object_unref(G_OBJECT(content)); + + } + + params->exp_count = explored; + + g_mutex_unlock(&project->ld_mutex); + + g_object_unref(G_OBJECT(explorer)); + + } + + if(xobject != NULL) + xmlXPathFreeObject(xobject); } @@ -415,9 +760,8 @@ const char *g_study_project_get_filename(const GStudyProject *project) * * * Paramètres : project = projet dont le contenu est à compléter. * * content = contenu binaire à mémoriser pour le projet. * -* state = état du contenu à conserver. * * * -* Description : Assure l'intégration d'un contenu binaire dans un projet. * +* Description : Assure l'intégration de contenus binaires dans un projet. * * * * Retour : - * * * @@ -425,77 +769,246 @@ const char *g_study_project_get_filename(const GStudyProject *project) * * ******************************************************************************/ -void g_study_project_add_binary_content(GStudyProject *project, GBinContent *content, ProjectContentState state) +void g_study_project_discover_binary_content(GStudyProject *project, GBinContent *content) { -#if 0 + loading_params *params; /* Informations de chargement */ + GContentExplorer *explorer; /* Explorateur de contenus */ - loaded_content *new; /* Nouveau contenu à définir */ + explorer = get_current_content_explorer(); - g_mutex_lock(&project->cnt_mutex); + g_mutex_lock(&project->ld_mutex); - project->contents = (loaded_content *)realloc(project->contents, - ++project->contents_count * sizeof(loaded_content)); + params = g_study_project_prepare_content_loading(project); - new = &project->contents[project->contents_count - 1]; + params->exp_gid = g_content_explorer_create_group(explorer, content); + params->exp_count = 1; - g_object_ref(G_OBJECT(content)); + params->resolved = 0; - new->content = content; - new->state = state; + params->xdoc = NULL; + params->context = NULL; - g_mutex_unlock(&project->cnt_mutex); + g_mutex_unlock(&project->ld_mutex); -#endif + g_object_unref(G_OBJECT(explorer)); } /****************************************************************************** * * -* Paramètres : project = projet dont le contenu est à compléter. * -* hash = empreinte du contenu à retrouver. * +* Paramètres : explorer = gestionnaire d'explorations à consulter. * +* gid = groupe d'exploration concerné. * +* project = projet avide des résultats des opérations. * * * -* Description : Recherche un contenu binaire du projet selon son empreinte. * +* Description : Note la fin d'une phase d'exploration de contenu. * * * -* Retour : Contenu avec propriété transférée ou NULL en cas d'échec. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project, const char *hash) +static void on_new_content_explored(GContentExplorer *explorer, gid_t gid, GStudyProject *project) { - return NULL; + const gid_t *gid_ptr; /* Référence vers l'origine */ + loading_params *params; /* Informations de chargement */ + GBinContent **available; /* Contenus binaires présents */ + size_t count; /* Quantité de ces contenus */ + const wgroup_id_t *wid; /* Groupe de tâches */ + GContentResolver *resolver; /* Resolveur de contenus */ + size_t i; /* Boucle de parcours */ -#if 0 + g_mutex_lock(&project->ld_mutex); + + params = g_study_project_find_exploration(project, gid, &gid_ptr); + + /* S'il s'agit bien d'une exploration nouvelle */ + if (params != NULL) + { + wid = g_content_explorer_get_group_work_id(explorer, gid); + + available = g_content_explorer_get_all(explorer, gid, &count); + assert(count > 0); + + resolver = get_current_content_resolver(); + + g_content_resolver_create_group(resolver, wid, gid_ptr, available, count); + + g_object_unref(G_OBJECT(resolver)); + + for (i = 0; i < count; i++) + g_object_unref(G_OBJECT(available[i])); - GBinContent *result; /* Trouvaille à retourner */ + free(available); + + } + + g_mutex_unlock(&project->ld_mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : resolver = gestionnaire de résolutions à consulter. * +* gid = groupe d'exploration concerné. * +* project = projet avide des résultats des opérations. * +* * +* Description : Note la fin d'une phase de resolution de contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_new_content_resolved(GContentResolver *resolver, gid_t gid, GStudyProject *project) +{ + loading_params *params; /* Informations de chargement */ + GLoadedContent **available; /* Contenus chargés valables */ + size_t count; /* Quantité de ces contenus */ size_t i; /* Boucle de parcours */ - GBinContent *iter; /* Contenu binaire analysé */ - const gchar *other; /* Autre empreinte à comparer */ + GBinContent *content; /* Contenu brut à manipuler */ + const gchar *hash; /* Empreinte d'un contenu */ + const char *format; /* Format associé à un élément */ + char *access; /* Chemin pour une sous-config.*/ + xmlXPathObjectPtr xobject; /* Cible d'une recherche */ + bool status; /* Bilan d'une restauration */ - result = NULL; + g_mutex_lock(&project->ld_mutex); - g_mutex_lock(&project->cnt_mutex); + params = g_study_project_find_exploration(project, gid, NULL); - for (i = 0; i < project->contents_count && result == NULL; i++) + /* S'il s'agit bien d'une exploration nouvelle */ + if (params != NULL) { - iter = project->contents[i].content; - other = g_binary_content_get_checksum(iter); + available = g_content_resolver_get_all(resolver, gid, &count); - if (strcmp(hash, other) == 0) + /* Rechargement à partir d'XML ? */ + if (params->xdoc != NULL) { - g_object_ref(G_OBJECT(iter)); - result = iter; + assert(params->context != NULL); + + for (i = 0; i < count; i++) + { + content = g_loaded_content_get_content(available[i]); + hash = g_binary_content_get_checksum(content); + g_object_unref(G_OBJECT(content)); + + format = g_loaded_content_get_format_name(available[i]); + + asprintf(&access, "/ChrysalideProject/LoadedContents/Content[@hash='%s' and @format='%s']", + hash, format); + + xobject = get_node_xpath_object(params->context, access); + + if (XPATH_OBJ_NODES_COUNT(xobject) > 0) + { + + status = g_loaded_content_restore(available[i], params->xdoc, params->context, access); + + if (!status) + log_variadic_message(LMT_ERROR, + _("Unable to reload binary from XML (hash=%s) ; skipping..."), hash); + + else + { + /** + * S'il s'agit des résultats de la dernière exploration, + * alors les groupes contenant les éléments chargés vont + * être libéré, potentiellement pendant l'analyse. + * + * On temporise en incrémentant les références. + */ + g_object_ref(G_OBJECT(available[i])); + + g_signal_connect(available[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project); + + g_loaded_content_analyze(available[i]); + + } + + } + + free(access); + + if(xobject != NULL) + xmlXPathFreeObject(xobject); + + g_object_unref(G_OBJECT(available[i])); + + } + + } + + /* Découverte(s) initiale(s) ? */ + else + { + for (i = 0; i < count; i++) + { + /** + * S'il s'agit des résultats de la dernière exploration, + * alors les groupes contenant les éléments chargés vont + * être libéré, potentiellement pendant l'analyse. + * + * On temporise en incrémentant les références. + */ + g_object_ref(G_OBJECT(available[i])); + + g_signal_connect(available[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project); + + g_loaded_content_analyze(available[i]); + + g_object_unref(G_OBJECT(available[i])); + + } + } + /* Dans tous les cas... */ + if (available != NULL) + free(available); + + /* Si c'était la dernière résolution... */ + if (++params->resolved == params->exp_count) + g_study_project_destroy_content_loading(project, params); + } - g_mutex_unlock(&project->cnt_mutex); + g_mutex_unlock(&project->ld_mutex); - return result; +} -#endif + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé et analysé. * +* success = bilan d'une analyse menée. * +* project = projet avide des résultats des opérations. * +* * +* Description : Réceptionne la recette d'une analyse de contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_loaded_content_analyzed(GLoadedContent *content, gboolean success, GStudyProject *project) +{ + const char *desc; /* Description du contenu */ + + if (success) + g_study_project_attach_content(project, content); + + else + { + desc = g_loaded_content_describe(content, true); + log_variadic_message(LMT_ERROR, _("Failed to load '%s'"), desc); + } + + g_object_ref(G_OBJECT(content)); } @@ -521,6 +1034,7 @@ void g_study_project_attach_content(GStudyProject *project, GLoadedContent *cont ++project->count * sizeof(GLoadedContent *)); project->contents[project->count - 1] = content; + g_object_ref(G_OBJECT(content)); g_mutex_unlock(&project->mutex); @@ -732,7 +1246,7 @@ void push_project_into_recent_list(const GStudyProject *project) recent.mime_type = "application/chrysalide.project"; recent.app_name = "Chrysalide"; - recent.app_exec = "chrysalide %f"; + recent.app_exec = "chrysalide -p %f"; gtk_recent_manager_add_full(manager, qualified, &recent); |