diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-05-09 13:33:10 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-05-09 13:33:10 (GMT) |
commit | 421c9d8b228f4926fabe06a19fda86d9023f1e96 (patch) | |
tree | f089835b8f03442c5e7067e940d28381255ef216 /src | |
parent | bb242c2cda6a590fef652e62688c10e2d52a7ff0 (diff) |
Loaded binary contents using a dedicated global work group.
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/project.c | 901 | ||||
-rw-r--r-- | src/core/queue.c | 10 | ||||
-rw-r--r-- | src/core/queue.h | 3 |
3 files changed, 536 insertions, 378 deletions
diff --git a/src/analysis/project.c b/src/analysis/project.c index d2228e2..13887ee 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -37,25 +37,14 @@ #include "../core/global.h" #include "../core/logs.h" #include "../core/params.h" +#include "../core/queue.h" +#include "../glibext/delayed-int.h" /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */ -/* Suivi du chargement de contenus binaires */ -typedef struct _loading_params -{ - const wgroup_id_t **exp_wids; /* Identifiants d'exploration */ - size_t exp_count; /* Quantitié d'identifiants */ - - size_t resolved; /* Compteur de résolutions */ - - xmlDoc *xdoc; /* Structure XML chargée ? */ - xmlXPathContext *context; /* Eventuel contexte XML */ - -} loading_params; - /* Projet d'étude regroupant les binaires analysés (instance) */ struct _GStudyProject { @@ -63,10 +52,6 @@ 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 */ @@ -104,26 +89,83 @@ 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 *); +/* Assure l'intégration de contenus listés dans du XML. */ +static void g_study_project_recover_binary_contents(GStudyProject *, xmlDoc *, xmlXPathContext *); + +/* Réceptionne la recette d'une analyse de contenu. */ +static void on_loaded_content_analyzed(GLoadedContent *, gboolean, 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 *, wgroup_id_t, const wgroup_id_t **); +/* ------------------------ CHARGEMENTS DE CONTENUS BINAIRES ------------------------ */ -/* Assure l'intégration de contenus listés dans du XML. */ -static void g_study_project_recover_binary_contents(GStudyProject *, xmlDoc *, xmlXPathContext *); + +#define G_TYPE_LOADING_HANDLER g_loading_handler_get_type() +#define G_LOADING_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LOADING_HANDLER, GLoadingHandler)) +#define G_IS_LOADING_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LOADING_HANDLER)) +#define G_LOADING_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LOADING_HANDLER, GLoadingHandlerClass)) +#define G_IS_LOADING_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LOADING_HANDLER)) +#define G_LOADING_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LOADING_HANDLER, GLoadingHandlerClass)) + + +/* Chargement de contenus binaires (instance) */ +typedef struct _GLoadingHandler +{ + GDelayedWork parent; /* A laisser en premier */ + + GStudyProject *project; /* Projet à compléter */ + + xmlDoc *xdoc; /* Structure XML chargée ? */ + xmlXPathContext *context; /* Eventuel contexte XML */ + + const wgroup_id_t **exp_wids; /* Identifiants d'exploration */ + size_t exp_count; /* Quantitié d'identifiants */ + size_t resolved; /* Compteur de résolutions */ + GCond wait_cond; /* Réveil d'attente de fin */ + GMutex mutex; /* Encadrement des accès */ + +} GLoadingHandler; + +/* Chargement de contenus binaires (classe) */ +typedef struct _GLoadingHandlerClass +{ + GDelayedWorkClass parent; /* A laisser en premier */ + +} GLoadingHandlerClass; + + +/* Indique le type défini pour les tâches de chargement de contenus binaires. */ +GType g_loading_handler_get_type(void); + +/* Initialise la classe des tâches de chargement de contenus. */ +static void g_loading_handler_class_init(GLoadingHandlerClass *); + +/* Initialise une tâche de chargement de contenus binaires. */ +static void g_loading_handler_init(GLoadingHandler *); + +/* Supprime toutes les références externes. */ +static void g_loading_handler_dispose(GLoadingHandler *); + +/* Procède à la libération totale de la mémoire. */ +static void g_loading_handler_finalize(GLoadingHandler *); + +/* Crée une tâche de chargement de contenu bianire. */ +static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *, GBinContent *); + +/* Crée une tâche de chargement de contenu bianire. */ +static GLoadingHandler *g_loading_handler_new_recovering(GStudyProject *, xmlDoc *, xmlXPathContext *); + +/* Assure le chargement de contenus binaires en différé. */ +static void g_loading_handler_process(GLoadingHandler *, GtkStatusStack *); + +/* Détermine si un encadrement est adapté pour un identifiant. */ +static bool g_loading_handler_check(GLoadingHandler *, wgroup_id_t, const wgroup_id_t **); /* Note la fin d'une phase d'exploration de contenu. */ -static void on_new_content_explored(GContentExplorer *, wgroup_id_t, GStudyProject *); +static void on_new_content_explored(GContentExplorer *, wgroup_id_t, GLoadingHandler *); /* Note la fin d'une phase de resolution de contenu. */ -static void on_new_content_resolved(GContentResolver *, wgroup_id_t, GStudyProject *); - -/* Réceptionne la recette d'une analyse de contenu. */ -static void on_loaded_content_analyzed(GLoadedContent *, gboolean, GStudyProject *); +static void on_new_content_resolved(GContentResolver *, wgroup_id_t, GLoadingHandler *); @@ -190,27 +232,12 @@ 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)); - } @@ -228,30 +255,8 @@ static void g_study_project_init(GStudyProject *project) 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++) @@ -513,36 +518,297 @@ const char *g_study_project_get_filename(const GStudyProject *project) /****************************************************************************** * * * Paramètres : project = projet dont le contenu est à compléter. * +* xdoc = structure XML en cours d'édition. * +* context = contexte à utiliser pour les recherches. * * * -* Description : Prépare le suivi d'une nouvelle phase d'intégration. * +* Description : Assure l'intégration de contenus listés dans du XML. * * * -* Retour : Nouvelle structure de suivi prête à être complétée. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static loading_params *g_study_project_prepare_content_loading(GStudyProject *project) +static void g_study_project_recover_binary_contents(GStudyProject *project, xmlDoc *xdoc, xmlXPathContext *context) { - loading_params *result; /* Trouvaille à retourner */ + GLoadingHandler *handler; /* Encadrement du chargement */ - assert(!g_mutex_trylock(&project->ld_mutex)); + handler = g_loading_handler_new_recovering(project, xdoc, context); - project->ld_params = (loading_params *)realloc(project->ld_params, - ++project->ld_count * sizeof(loading_params)); + if (handler != NULL) + g_work_queue_schedule_work(get_work_queue(), G_DELAYED_WORK(handler), LOADING_WORK_GROUP); - result = &project->ld_params[project->ld_count - 1]; +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à compléter. * +* content = contenu binaire à mémoriser pour le projet. * +* * +* Description : Assure l'intégration de contenus binaires dans un projet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_study_project_discover_binary_content(GStudyProject *project, GBinContent *content) +{ + GLoadingHandler *handler; /* Encadrement du chargement */ + + handler = g_loading_handler_new_discovering(project, content); + + g_work_queue_schedule_work(get_work_queue(), G_DELAYED_WORK(handler), LOADING_WORK_GROUP); + +} + + +/****************************************************************************** +* * +* 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 */ + + desc = g_loaded_content_describe(content, true); + + if (success) + { + g_study_project_attach_content(project, content); + log_variadic_message(LMT_INFO, _("Content from '%s' has been analyzed successfully!"), desc); + } + + else + log_variadic_message(LMT_ERROR, _("Failed to load '%s'"), desc); + + g_object_ref(G_OBJECT(content)); + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à manipuler. * +* content = contenu chargé à associer au projet actuel. * +* * +* Description : Attache un contenu donné à un projet donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_study_project_attach_content(GStudyProject *project, GLoadedContent *content) +{ + g_mutex_lock(&project->mutex); + + project->contents = (GLoadedContent **)realloc(project->contents, + ++project->count * sizeof(GLoadedContent *)); + + project->contents[project->count - 1] = content; + g_object_ref(G_OBJECT(content)); + + g_mutex_unlock(&project->mutex); + + g_signal_emit_by_name(project, "content-added", content); + +} + + +/****************************************************************************** +* * +* Paramètres : project = project à manipuler. * +* content = contenu chargé à dissocier du projet actuel. * +* * +* Description : Détache un contenu donné d'un projet donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_study_project_detach_content(GStudyProject *project, GLoadedContent *content) +{ + size_t i; /* Boucle de parcours */ + + g_mutex_lock(&project->mutex); + + for (i = 0; i < project->count; i++) + if (project->contents[i] == content) break; + + if ((i + 1) < project->count) + memmove(&project->contents[i], &project->contents[i + 1], + (project->count - i - 1) * sizeof(GLoadedContent *)); + + project->contents = (GLoadedContent **)realloc(project->contents, + --project->count * sizeof(GLoadedContent *)); + + g_mutex_unlock(&project->mutex); + + g_signal_emit_by_name(project, "content-removed", content); + + g_object_unref(G_OBJECT(content)); + +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à afficher. * +* * +* Description : Met en place un projet à l'écran. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_study_project_display(const GStudyProject *project) +{ +#if 0 + size_t i; /* Boucle de parcours #1 */ + loaded_binary *handled; /* Binaire prise en compte */ + size_t j; /* Boucle de parcours #2 */ + + for (i = 0; i < project->binaries_count; i++) + { + handled = project->binaries[i]; + + for (j = 0; j < handled->count; j++) + g_panel_item_dock(handled->items[j]); + + } +#endif +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à cacher. * +* * +* Description : Supprime de l'écran un projet en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_study_project_hide(const GStudyProject *project) +{ +#if 0 + size_t i; /* Boucle de parcours #1 */ + loaded_binary *handled; /* Binaire prise en compte */ + size_t j; /* Boucle de parcours #2 */ + + for (i = 0; i < project->binaries_count; i++) + { + handled = project->binaries[i]; + + for (j = 0; j < handled->count; j++) + g_panel_item_undock(handled->items[j]); + + } +#endif +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à afficher. * +* count = nombre de contenus pris en compte. [OUT] * +* * +* Description : Fournit l'ensemble des contenus associés à un projet. * +* * +* Retour : Liste à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GLoadedContent **g_study_project_get_contents(GStudyProject *project, size_t *count) +{ + GLoadedContent **result; /* Tableau à retourner */ + size_t i; /* Boucle de parcours */ + + g_mutex_lock(&project->mutex); + + *count = project->count; + result = (GLoadedContent **)calloc(*count, sizeof(GLoadedContent *)); + + for (i = 0; i < *count; i++) + { + result[i] = project->contents[i]; + g_object_ref(G_OBJECT(result[i])); + } + + g_mutex_unlock(&project->mutex); return result; } + + +/* ---------------------------------------------------------------------------------- */ +/* CHARGEMENTS DE CONTENUS BINAIRES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour les tâches de chargement de contenus binaires. */ +G_DEFINE_TYPE(GLoadingHandler, g_loading_handler, G_TYPE_DELAYED_WORK); + + /****************************************************************************** * * -* Paramètres : project = projet dont le contenu est à compléter. * -* params = paramètres de chargemeent à supprimer. * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des tâches de chargement de contenus. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_loading_handler_class_init(GLoadingHandlerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDelayedWorkClass *work; /* Version en classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_loading_handler_dispose; + object->finalize = (GObjectFinalizeFunc)g_loading_handler_finalize; + + work = G_DELAYED_WORK_CLASS(klass); + + work->run = (run_task_fc)g_loading_handler_process; + +} + + +/****************************************************************************** * * -* Description : Efface le suivi d'une phase d'intégration obsolète. * +* Paramètres : handler = instance à initialiser. * +* * +* Description : Initialise une tâche de chargement de contenus binaires. * * * * Retour : - * * * @@ -550,92 +816,142 @@ static loading_params *g_study_project_prepare_content_loading(GStudyProject *pr * * ******************************************************************************/ -static void g_study_project_destroy_content_loading(GStudyProject *project, loading_params *params) +static void g_loading_handler_init(GLoadingHandler *handler) { 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)); + g_cond_init(&handler->wait_cond); + g_mutex_init(&handler->mutex); + + explorer = get_current_content_explorer(); + g_signal_connect(explorer, "explored", G_CALLBACK(on_new_content_explored), handler); + g_object_unref(G_OBJECT(explorer)); + + resolver = get_current_content_resolver(); + g_signal_connect(resolver, "resolved", G_CALLBACK(on_new_content_resolved), handler); + g_object_unref(G_OBJECT(resolver)); + +} + + +/****************************************************************************** +* * +* Paramètres : handler = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_loading_handler_dispose(GLoadingHandler *handler) +{ + GContentExplorer *explorer; /* Explorateur de contenus */ + GContentResolver *resolver; /* Resolveur de contenus */ + size_t i; /* Boucle de parcours */ /* Supression des groupes de travail */ explorer = get_current_content_explorer(); resolver = get_current_content_resolver(); - for (i = 0; i < params->exp_count; i++) + g_signal_handlers_disconnect_by_func(explorer, G_CALLBACK(on_new_content_explored), handler); + g_signal_handlers_disconnect_by_func(resolver, G_CALLBACK(on_new_content_resolved), handler); + + g_mutex_lock(&handler->mutex); + + for (i = 0; i < handler->exp_count; i++) { - g_content_resolver_delete_group(resolver, *params->exp_wids[i]); - g_content_explorer_delete_group(explorer, *params->exp_wids[i]); + g_content_resolver_delete_group(resolver, *handler->exp_wids[i]); + g_content_explorer_delete_group(explorer, *handler->exp_wids[i]); } - free(params->exp_wids); + g_mutex_unlock(&handler->mutex); g_object_unref(G_OBJECT(explorer)); g_object_unref(G_OBJECT(resolver)); - /* Fermture de l'éventuel fichier XML de chargement */ + /* Nettoyage plus général */ - if (params->xdoc != NULL) - close_xml_file(params->xdoc, params->context); + g_mutex_clear(&handler->mutex); + g_cond_clear(&handler->wait_cond); - /* Réorganisation de la liste */ + g_object_unref(G_OBJECT(handler->project)); - index = params - project->ld_params; + G_OBJECT_CLASS(g_loading_handler_parent_class)->dispose(G_OBJECT(handler)); - if ((index + 1) < project->ld_count) - memmove(&project->ld_params[index], &project->ld_params[index + 1], - (project->ld_count - index - 1) * sizeof(loading_params)); +} + + +/****************************************************************************** +* * +* Paramètres : handler = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_loading_handler_finalize(GLoadingHandler *handler) +{ + free(handler->exp_wids); - project->ld_params = (loading_params *)realloc(project->ld_params, - --project->ld_count * sizeof(loading_params)); + /* Fermture de l'éventuel fichier XML de chargement */ + + if (handler->xdoc != NULL) + close_xml_file(handler->xdoc, handler->context); + + G_OBJECT_CLASS(g_loading_handler_parent_class)->finalize(G_OBJECT(handler)); } /****************************************************************************** * * -* Paramètres : project = projet dont le contenu est à consulter. * -* wid = identifiant du groupe d'exploration recherché. * -* ptr = pointeur vers la valeur d'origine externe. * +* Paramètres : project = projet dont le contenu est à compléter. * +* content = contenu binaire à mémoriser pour le projet. * * * -* Description : Retrouve les infos de chargements liées à une exploration. * +* Description : Crée une tâche de chargement de contenu bianire. * * * -* Retour : Informations trouvées ou NULL en cas d'échec. * +* Retour : Tâche créée. * * * * Remarques : - * * * ******************************************************************************/ -static loading_params *g_study_project_find_exploration(GStudyProject *project, wgroup_id_t wid, const wgroup_id_t **ptr) +static GLoadingHandler *g_loading_handler_new_discovering(GStudyProject *project, GBinContent *content) { - loading_params *result; /* Trouvaille à retourner */ - const wgroup_id_t *value; /* Raccourci de confort */ - size_t i; /* Boucle de parcours #1 */ - size_t k; /* Boucle de parcours #2 */ + GLoadingHandler *result; /* Tâche à retourner */ + GContentExplorer *explorer; /* Explorateur de contenus */ - assert(!g_mutex_trylock(&project->ld_mutex)); + result = g_object_new(G_TYPE_LOADING_HANDLER, NULL); - result = NULL; + result->project = project; + g_object_ref(G_OBJECT(result->project)); - value = NULL; + result->xdoc = NULL; + result->context = NULL; - for (i = 0; i < project->ld_count && result == NULL; i++) - for (k = 0; k < project->ld_params[i].exp_count && result == NULL; k++) - { - value = project->ld_params[i].exp_wids[k]; + result->exp_wids = (const wgroup_id_t **)malloc(sizeof(wgroup_id_t *)); + result->exp_count = 1; - if (*value == wid) - result = &project->ld_params[i]; + result->resolved = 0; - } + explorer = get_current_content_explorer(); - if (ptr != NULL) - { - assert(result == NULL || value != NULL); - *ptr = (result == NULL ? NULL : value); - } + g_mutex_lock(&result->mutex); + + result->exp_wids[0] = g_content_explorer_create_group(explorer, content); + + g_mutex_unlock(&result->mutex); + + g_object_unref(G_OBJECT(explorer)); return result; @@ -648,17 +964,17 @@ static loading_params *g_study_project_find_exploration(GStudyProject *project, * xdoc = structure XML en cours d'édition. * * context = contexte à utiliser pour les recherches. * * * -* Description : Assure l'intégration de contenus listés dans du XML. * +* Description : Crée une tâche de chargement de contenu bianire. * * * -* Retour : - * +* Retour : Tâche créée. * * * * Remarques : - * * * ******************************************************************************/ -static void g_study_project_recover_binary_contents(GStudyProject *project, xmlDoc *xdoc, xmlXPathContext *context) +static GLoadingHandler *g_loading_handler_new_recovering(GStudyProject *project, xmlDoc *xdoc, xmlXPathContext *context) { - loading_params *params; /* Informations de chargement */ + GLoadingHandler *result; /* Tâche à retourner */ xmlXPathObjectPtr xobject; /* Cible d'une recherche */ size_t count; /* Nombre de contenus premiers */ GContentExplorer *explorer; /* Explorateur de contenus */ @@ -673,21 +989,24 @@ static void g_study_project_recover_binary_contents(GStudyProject *project, xmlD if (count > 0) { - explorer = get_current_content_explorer(); + result = g_object_new(G_TYPE_LOADING_HANDLER, NULL); - g_mutex_lock(&project->ld_mutex); + result->project = project; + g_object_ref(G_OBJECT(result->project)); - params = g_study_project_prepare_content_loading(project); + result->xdoc = xdoc; + result->context = context; - params->exp_wids = (const wgroup_id_t **)malloc(count * sizeof(wgroup_id_t *)); + result->exp_wids = (const wgroup_id_t **)malloc(count * sizeof(wgroup_id_t *)); - params->resolved = 0; + result->resolved = 0; - params->xdoc = xdoc; - params->context = context; + explorer = get_current_content_explorer(); explored = 0; + g_mutex_lock(&result->mutex); + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) { asprintf(&access, "/ChrysalideProject/RootContents/Content[position()=%zu]", i + 1); @@ -702,32 +1021,37 @@ static void g_study_project_recover_binary_contents(GStudyProject *project, xmlD continue; } - params->exp_wids[explored++] = g_content_explorer_create_group(explorer, content); + result->exp_wids[explored++] = g_content_explorer_create_group(explorer, content); g_object_unref(G_OBJECT(content)); } - params->exp_count = explored; + result->exp_count = explored; - g_mutex_unlock(&project->ld_mutex); + g_mutex_unlock(&result->mutex); g_object_unref(G_OBJECT(explorer)); } + else + result = NULL; + if(xobject != NULL) xmlXPathFreeObject(xobject); + return result; + } /****************************************************************************** * * -* Paramètres : project = projet dont le contenu est à compléter. * -* content = contenu binaire à mémoriser pour le projet. * +* Paramètres : handler = opération de chargement à menuer. * +* status = barre de statut à tenir informée. * * * -* Description : Assure l'intégration de contenus binaires dans un projet. * +* Description : Assure le chargement de contenus binaires en différé. * * * * Retour : - * * * @@ -735,30 +1059,59 @@ static void g_study_project_recover_binary_contents(GStudyProject *project, xmlD * * ******************************************************************************/ -void g_study_project_discover_binary_content(GStudyProject *project, GBinContent *content) +static void g_loading_handler_process(GLoadingHandler *handler, GtkStatusStack *status) { - loading_params *params; /* Informations de chargement */ - GContentExplorer *explorer; /* Explorateur de contenus */ + g_mutex_lock(&handler->mutex); - explorer = get_current_content_explorer(); + while (handler->resolved < handler->exp_count) + g_cond_wait(&handler->wait_cond, &handler->mutex); + + g_mutex_unlock(&handler->mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : handler = gestionnaire dont contenu est à consulter. * +* wid = identifiant du groupe d'exploration recherché. * +* ptr = pointeur vers la valeur d'origine externe. * +* * +* Description : Détermine si un encadrement est adapté pour un identifiant. * +* * +* Retour : Bilan d'adéquation. * +* * +* Remarques : - * +* * +******************************************************************************/ - g_mutex_lock(&project->ld_mutex); +static bool g_loading_handler_check(GLoadingHandler *handler, wgroup_id_t wid, const wgroup_id_t **ptr) +{ + bool result; /* Bilan à retourner */ + const wgroup_id_t *value; /* Raccourci de confort */ + size_t i; /* Boucle de parcours */ - params = g_study_project_prepare_content_loading(project); + assert(!g_mutex_trylock(&handler->mutex)); - params->exp_wids = (const wgroup_id_t **)malloc(sizeof(wgroup_id_t *)); - params->exp_count = 1; + result = false; + + value = NULL; - params->resolved = 0; + for (i = 0; i < handler->exp_count && !result; i++) + { + value = handler->exp_wids[i]; - params->xdoc = NULL; - params->context = NULL; + result = (*value == wid); - params->exp_wids[0] = g_content_explorer_create_group(explorer, content); + } - g_mutex_unlock(&project->ld_mutex); + if (ptr != NULL) + { + assert(!result || value != NULL); + *ptr = (result ? value : NULL); + } - g_object_unref(G_OBJECT(explorer)); + return result; } @@ -767,7 +1120,7 @@ void g_study_project_discover_binary_content(GStudyProject *project, GBinContent * * * Paramètres : explorer = gestionnaire d'explorations à consulter. * * wid = groupe d'exploration concerné. * -* project = projet avide des résultats des opérations. * +* handler = gestionnaire avide des résultats des opérations. * * * * Description : Note la fin d'une phase d'exploration de contenu. * * * @@ -777,21 +1130,17 @@ void g_study_project_discover_binary_content(GStudyProject *project, GBinContent * * ******************************************************************************/ -static void on_new_content_explored(GContentExplorer *explorer, wgroup_id_t wid, GStudyProject *project) +static void on_new_content_explored(GContentExplorer *explorer, wgroup_id_t wid, GLoadingHandler *handler) { const wgroup_id_t *wid_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 */ GContentResolver *resolver; /* Resolveur de contenus */ size_t i; /* Boucle de parcours */ - g_mutex_lock(&project->ld_mutex); - - params = g_study_project_find_exploration(project, wid, &wid_ptr); + g_mutex_lock(&handler->mutex); - /* S'il s'agit bien d'une exploration nouvelle */ - if (params != NULL) + if (g_loading_handler_check(handler, wid, &wid_ptr)) { available = g_content_explorer_get_all(explorer, wid, &count); assert(count > 0); @@ -809,7 +1158,7 @@ static void on_new_content_explored(GContentExplorer *explorer, wgroup_id_t wid, } - g_mutex_unlock(&project->ld_mutex); + g_mutex_unlock(&handler->mutex); } @@ -818,7 +1167,7 @@ static void on_new_content_explored(GContentExplorer *explorer, wgroup_id_t wid, * * * Paramètres : resolver = gestionnaire de résolutions à consulter. * * wid = groupe d'exploration concerné. * -* project = projet avide des résultats des opérations. * +* handler = gestionnaire avide des résultats des opérations. * * * * Description : Note la fin d'une phase de resolution de contenu. * * * @@ -828,9 +1177,8 @@ static void on_new_content_explored(GContentExplorer *explorer, wgroup_id_t wid, * * ******************************************************************************/ -static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, GStudyProject *project) +static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, GLoadingHandler *handler) { - 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 */ @@ -841,19 +1189,16 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, xmlXPathObjectPtr xobject; /* Cible d'une recherche */ bool status; /* Bilan d'une restauration */ - g_mutex_lock(&project->ld_mutex); + g_mutex_lock(&handler->mutex); - params = g_study_project_find_exploration(project, wid, NULL); - - /* S'il s'agit bien d'une exploration nouvelle */ - if (params != NULL) + if (g_loading_handler_check(handler, wid, NULL)) { available = g_content_resolver_get_all(resolver, wid, &count); /* Rechargement à partir d'XML ? */ - if (params->xdoc != NULL) + if (handler->xdoc != NULL) { - assert(params->context != NULL); + assert(handler->context != NULL); for (i = 0; i < count; i++) { @@ -866,12 +1211,12 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, asprintf(&access, "/ChrysalideProject/LoadedContents/Content[@hash='%s' and @format='%s']", hash, format); - xobject = get_node_xpath_object(params->context, access); + xobject = get_node_xpath_object(handler->context, access); if (XPATH_OBJ_NODES_COUNT(xobject) > 0) { - status = g_loaded_content_restore(available[i], params->xdoc, params->context, access); + status = g_loaded_content_restore(available[i], handler->xdoc, handler->context, access); if (!status) log_variadic_message(LMT_ERROR, @@ -888,7 +1233,8 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, */ g_object_ref(G_OBJECT(available[i])); - g_signal_connect(available[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project); + g_signal_connect(available[i], "analyzed", + G_CALLBACK(on_loaded_content_analyzed), handler->project); g_loaded_content_analyze(available[i]); @@ -921,7 +1267,8 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, */ g_object_ref(G_OBJECT(available[i])); - g_signal_connect(available[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project); + g_signal_connect(available[i], "analyzed", + G_CALLBACK(on_loaded_content_analyzed), handler->project); g_loaded_content_analyze(available[i]); @@ -936,212 +1283,14 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, free(available); /* Si c'était la dernière résolution... */ - if (++params->resolved == params->exp_count) - g_study_project_destroy_content_loading(project, params); - } + handler->resolved++; - g_mutex_unlock(&project->ld_mutex); + g_cond_broadcast(&handler->wait_cond); -} - - -/****************************************************************************** -* * -* 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 */ - - desc = g_loaded_content_describe(content, true); - - if (success) - { - g_study_project_attach_content(project, content); - log_variadic_message(LMT_INFO, _("Content from '%s' has been analyzed successfully!"), desc); } - else - log_variadic_message(LMT_ERROR, _("Failed to load '%s'"), desc); - - g_object_ref(G_OBJECT(content)); - -} - - -/****************************************************************************** -* * -* Paramètres : project = project à manipuler. * -* content = contenu chargé à associer au projet actuel. * -* * -* Description : Attache un contenu donné à un projet donné. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_study_project_attach_content(GStudyProject *project, GLoadedContent *content) -{ - g_mutex_lock(&project->mutex); - - project->contents = (GLoadedContent **)realloc(project->contents, - ++project->count * sizeof(GLoadedContent *)); - - project->contents[project->count - 1] = content; - g_object_ref(G_OBJECT(content)); - - g_mutex_unlock(&project->mutex); - - g_signal_emit_by_name(project, "content-added", content); - -} - - -/****************************************************************************** -* * -* Paramètres : project = project à manipuler. * -* content = contenu chargé à dissocier du projet actuel. * -* * -* Description : Détache un contenu donné d'un projet donné. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_study_project_detach_content(GStudyProject *project, GLoadedContent *content) -{ - size_t i; /* Boucle de parcours */ - - g_mutex_lock(&project->mutex); - - for (i = 0; i < project->count; i++) - if (project->contents[i] == content) break; - - if ((i + 1) < project->count) - memmove(&project->contents[i], &project->contents[i + 1], - (project->count - i - 1) * sizeof(GLoadedContent *)); - - project->contents = (GLoadedContent **)realloc(project->contents, - --project->count * sizeof(GLoadedContent *)); - - g_mutex_unlock(&project->mutex); - - g_signal_emit_by_name(project, "content-removed", content); - - g_object_unref(G_OBJECT(content)); - -} - - -/****************************************************************************** -* * -* Paramètres : project = projet dont le contenu est à afficher. * -* * -* Description : Met en place un projet à l'écran. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_study_project_display(const GStudyProject *project) -{ -#if 0 - size_t i; /* Boucle de parcours #1 */ - loaded_binary *handled; /* Binaire prise en compte */ - size_t j; /* Boucle de parcours #2 */ - - for (i = 0; i < project->binaries_count; i++) - { - handled = project->binaries[i]; - - for (j = 0; j < handled->count; j++) - g_panel_item_dock(handled->items[j]); - - } -#endif -} - - -/****************************************************************************** -* * -* Paramètres : project = projet dont le contenu est à cacher. * -* * -* Description : Supprime de l'écran un projet en place. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_study_project_hide(const GStudyProject *project) -{ -#if 0 - size_t i; /* Boucle de parcours #1 */ - loaded_binary *handled; /* Binaire prise en compte */ - size_t j; /* Boucle de parcours #2 */ - - for (i = 0; i < project->binaries_count; i++) - { - handled = project->binaries[i]; - - for (j = 0; j < handled->count; j++) - g_panel_item_undock(handled->items[j]); - - } -#endif -} - - -/****************************************************************************** -* * -* Paramètres : project = projet dont le contenu est à afficher. * -* count = nombre de contenus pris en compte. [OUT] * -* * -* Description : Fournit l'ensemble des contenus associés à un projet. * -* * -* Retour : Liste à libérer de la mémoire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GLoadedContent **g_study_project_get_contents(GStudyProject *project, size_t *count) -{ - GLoadedContent **result; /* Tableau à retourner */ - size_t i; /* Boucle de parcours */ - - g_mutex_lock(&project->mutex); - - *count = project->count; - result = (GLoadedContent **)calloc(*count, sizeof(GLoadedContent *)); - - for (i = 0; i < *count; i++) - { - result[i] = project->contents[i]; - g_object_ref(G_OBJECT(result[i])); - } - - g_mutex_unlock(&project->mutex); - - return result; + g_mutex_unlock(&handler->mutex); } diff --git a/src/core/queue.c b/src/core/queue.c index 615e351..79a87b2 100644 --- a/src/core/queue.c +++ b/src/core/queue.c @@ -60,6 +60,13 @@ bool init_global_works(void) g_work_queue_define_work_group(queue); #endif +#ifndef NDEBUG + expected = g_work_queue_define_work_group(queue); + assert(expected == LOADING_WORK_GROUP); +#else + g_work_queue_define_work_group(queue); +#endif + return true; } @@ -105,7 +112,8 @@ void wait_for_all_global_works(void) GWorkQueue *queue; /* Singleton pour tâches */ static const wgroup_id_t group_ids[] = { - DEFAULT_WORK_GROUP + DEFAULT_WORK_GROUP, + LOADING_WORK_GROUP }; queue = get_work_queue(); diff --git a/src/core/queue.h b/src/core/queue.h index 1984fff..bee16a4 100644 --- a/src/core/queue.h +++ b/src/core/queue.h @@ -34,8 +34,9 @@ */ #define DEFAULT_WORK_GROUP 0 +#define LOADING_WORK_GROUP 1 -#define GLOBAL_WORK_GROUPS_COUNT 1 +#define GLOBAL_WORK_GROUPS_COUNT 2 /* Met en place les mécanismes de traitements parallèles. */ |