diff options
Diffstat (limited to 'src/analysis/storage')
-rw-r--r-- | src/analysis/storage/serialize.c | 2 | ||||
-rw-r--r-- | src/analysis/storage/storage-int.h | 2 | ||||
-rw-r--r-- | src/analysis/storage/storage.c | 349 | ||||
-rw-r--r-- | src/analysis/storage/storage.h | 10 | ||||
-rw-r--r-- | src/analysis/storage/tpmem.c | 22 |
5 files changed, 345 insertions, 40 deletions
diff --git a/src/analysis/storage/serialize.c b/src/analysis/storage/serialize.c index 312cfce..d1b0502 100644 --- a/src/analysis/storage/serialize.c +++ b/src/analysis/storage/serialize.c @@ -59,7 +59,7 @@ static void g_serializable_object_default_init(GSerializableObjectInterface *ifa * * * Paramètres : object = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* pbuf = zone tampon à lire. * * * * Description : Charge un objet depuis une mémoire tampon. * * * diff --git a/src/analysis/storage/storage-int.h b/src/analysis/storage/storage-int.h index 7e01cbc..4883aa8 100644 --- a/src/analysis/storage/storage-int.h +++ b/src/analysis/storage/storage-int.h @@ -46,7 +46,7 @@ struct _GObjectStorage GTypeMemory *tpmem; /* Mémorisation de types */ - GLoadedContent *loaded; /* Contenu principal */ + char *hash; /* Empreinte du contenu */ storage_backend_t *backends; /* Gestionnaires existants */ size_t count; /* Quantité de gestionnaires */ diff --git a/src/analysis/storage/storage.c b/src/analysis/storage/storage.c index 395d26d..e286641 100644 --- a/src/analysis/storage/storage.c +++ b/src/analysis/storage/storage.c @@ -31,10 +31,17 @@ #include "storage-int.h" +#include "../db/misc/rlestr.h" +#include "../../common/io.h" +#include "../../common/leb128.h" #include "../../core/logs.h" +#define STORAGE_MAGIC "CSTR" +#define STORAGE_NUMBER "\x00\x01" + + /* Initialise la classe des conservations d'objets en place. */ static void g_object_storage_class_init(GObjectStorageClass *); @@ -50,6 +57,15 @@ static void g_object_storage_finalize(GObjectStorage *); /* Retrouve l'encadrement pour un nouveau groupe d'objets. */ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const char *); +/* Ajoute le support d'un nouveau groupe d'objets construits. */ +static bool g_object_storage_add_backend(GObjectStorage *, const char *, storage_backend_t **); + +/* Extrait d'un tampon des enregistrements spécifiques. */ +static bool g_object_storage_load_backend(GObjectStorage *, packed_buffer_t *); + +/* Place dans un tampon les données liées à des enregistrements. */ +static bool pack_storage_backend(const storage_backend_t *, packed_buffer_t *); + /* Indique le type défini pour une conservation d'objets construits. */ @@ -96,7 +112,7 @@ static void g_object_storage_init(GObjectStorage *storage) { storage->tpmem = g_type_memory_new(); - storage->loaded = NULL; + storage->hash = NULL; storage->backends = NULL; storage->count = 0; @@ -121,8 +137,6 @@ static void g_object_storage_dispose(GObjectStorage *storage) { g_clear_object(&storage->tpmem); - g_clear_object(&storage->loaded); - G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(G_OBJECT(storage)); } @@ -177,6 +191,9 @@ static void g_object_storage_finalize(GObjectStorage *storage) g_mutex_clear(&storage->mutex); + if (storage->hash != NULL) + free(storage->hash); + G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(G_OBJECT(storage)); } @@ -194,14 +211,131 @@ static void g_object_storage_finalize(GObjectStorage *storage) * * ******************************************************************************/ -GObjectStorage *g_object_storage_new(GLoadedContent *loaded) +GObjectStorage *g_object_storage_new(const char *hash) { - GObjectStorage *result; /* Structure à retourner */ + GObjectStorage *result; /* Structure à retourner */ result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); - result->loaded = loaded; - g_object_ref(G_OBJECT(loaded)); + result->hash = strdup(hash); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : pbuf = zone tampon à lire. * +* * +* Description : Charge le support d'une conservation d'objets en place. * +* * +* Retour : Gestionnaire de conservations construit ou NULL si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObjectStorage *g_object_storage_load(packed_buffer_t *pbuf) +{ + GObjectStorage *result; /* Structure à retourner */ + char header[6]; /* Entête attendue des données */ + bool status; /* Bilan d'une extraction */ + rle_string str; /* Chaîne à conserver */ + uleb128_t count; /* Nombre de groupes à charger */ + uleb128_t i; /* Boucle de parcours */ + + result = NULL; + + status = extract_packed_buffer(pbuf, header, 6, false); + if (!status) goto quick_exit; + + if (strncmp(header, STORAGE_MAGIC STORAGE_NUMBER, 6) != 0) + goto quick_exit; + + setup_empty_rle_string(&str); + + status = unpack_rle_string(&str, pbuf); + if (!status) goto quick_exit; + + if (get_rle_string(&str) == NULL) + { + exit_rle_string(&str); + goto quick_exit; + } + + result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); + + result->hash = strdup(get_rle_string(&str)); + + exit_rle_string(&str); + + status = g_type_memory_load_types(result->tpmem, pbuf); + if (!status) goto exit_while_loading; + + status = unpack_uleb128(&count, pbuf); + + for (i = 0; i < count && status; i++) + status = g_object_storage_load_backend(result, pbuf); + + exit_while_loading: + + if (!status) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + quick_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à manipuler. * +* pbuf = zone tampon à remplir. [OUT] * +* * +* Description : Sauvegarde le support d'une conservation d'objets en place. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_object_storage_store(GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string str; /* Chaîne à conserver */ + size_t i; /* Boucle de parcours */ + + result = extend_packed_buffer(pbuf, STORAGE_MAGIC STORAGE_NUMBER, 6, false); + + if (result) + { + init_static_rle_string(&str, storage->hash); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + } + + g_mutex_lock(&storage->mutex); + + if (result) + result = g_type_memory_store_types(storage->tpmem, pbuf); + + if (result) + result = pack_uleb128((uleb128_t []){ storage->count }, pbuf); + + for (i = 0; i < storage->count && result; i++) + result = pack_storage_backend(&storage->backends[i], pbuf); + + g_mutex_unlock(&storage->mutex); return result; @@ -244,9 +378,9 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, /****************************************************************************** * * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* name = désignation d'un nouveau groupe d'objets. * -* filename = éventuel nom de fichier à utiliser ou NULL. * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* name = désignation d'un nouveau groupe d'objets. * +* backend = support mis en place pour les enregistrements. * * * * Description : Ajoute le support d'un nouveau groupe d'objets construits. * * * @@ -256,45 +390,116 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, * * ******************************************************************************/ -bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, const char *filename) +static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend) { bool result; /* Bilan à retourner */ - GBinContent *content; /* Contenu binaire traité */ - const gchar *checksum; /* Empreinte de ce contenu */ char *prefix; /* Début de nom de fichier */ - storage_backend_t backend; /* Informations à intégrer */ + char *filename; /* Chemin d'accès aux données */ + int fd; /* Descripteur de flux ouvert */ result = false; - g_mutex_lock(&storage->mutex); + *backend = NULL; + + assert(!g_mutex_trylock(&storage->mutex)); if (g_object_storage_find_backend(storage, name) != NULL) goto exit; /* Préparatifs */ - content = g_loaded_content_get_content(storage->loaded); + asprintf(&prefix, "%s-%s", storage->hash, name); - checksum = g_binary_content_get_checksum(content); + fd = make_tmp_file(prefix, "cache", &filename); - asprintf(&prefix, "%s-%s", checksum, name); + free(prefix); - g_object_unref(G_OBJECT(content)); + if (fd == -1) + goto exit; - backend.fd = make_tmp_file(prefix, "cache", &backend.filename); + /* Inscription en bonne et due forme */ - free(prefix); + storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t)); + + *backend = &storage->backends[storage->count - 1]; + + (*backend)->name = strdup(name); - if (backend.fd == -1) + (*backend)->filename = filename; + (*backend)->fd = fd; + + result = true; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* pbuf = zone tampon à lire. * +* * +* Description : Extrait d'un tampon des enregistrements spécifiques. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string str; /* Chaîne à conserver */ + bool status; /* Bilan de lecture de contenu */ + storage_backend_t *backend; /* Informations à intégrer */ + uleb128_t length; /* Taille des données à charger*/ + off_t moved; /* Nouvelle position établie */ + + result = false; + + g_mutex_lock(&storage->mutex); + + /* Récupération du nom et création du support */ + + setup_empty_rle_string(&str); + + status = unpack_rle_string(&str, pbuf); + if (!status) goto exit; + + if (get_rle_string(&str) == NULL) + { + exit_rle_string(&str); goto exit; + } - /* Inscription en bonne et due forme */ + status = g_object_storage_add_backend(storage, get_rle_string(&str), &backend); - backend.name = strdup(name); + exit_rle_string(&str); - storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t)); + if (!status) goto exit; + + /* Récupération du contenu */ + + status = unpack_uleb128(&length, pbuf); + if (!status) goto exit; - storage->backends[storage->count - 1] = backend; + status = safe_write(backend->fd, pbuf->data + pbuf->pos, length); + if (!status) goto exit; + + advance_packed_buffer(pbuf, length); + + moved = lseek(backend->fd, 0, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + result = true; exit: @@ -307,6 +512,93 @@ bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, con /****************************************************************************** * * +* Paramètres : backend = stockage des enregistrements spécifiques. * +* pbuf = zone tampon à remplir. [OUT] * +* * +* Description : Place dans un tampon les données liées à des enregistrements.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string str; /* Chaîne à conserver */ + bool status; /* Bilan de lecture de contenu */ + off_t current; /* Position courante */ + off_t moved; /* Nouvelle position établie */ + void *data; /* Données à transférer */ + + result = false; + + /* Inscription du nom */ + + init_static_rle_string(&str, backend->name); + + status = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + if (!status) goto exit; + + /* Inscription du contenu */ + + current = lseek(backend->fd, 0, SEEK_CUR); + if (current == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + moved = lseek(backend->fd, 0, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + data = malloc(current); + if (data == NULL) + { + LOG_ERROR_N("malloc"); + goto restore; + } + + status = safe_read(backend->fd, data, current); + if (!status) goto free_mem; + + status = pack_uleb128((uleb128_t []){ current }, pbuf); + if (!status) goto free_mem; + + status = extend_packed_buffer(pbuf, data, current, false); + + free_mem: + + free(data); + + restore: + + moved = lseek(backend->fd, current, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + result = status; + + exit: + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : storage = gestionnaire à manipuler. * * name = désignation d'un nouveau groupe d'objets. * * pos = tête de lecture avant écriture. * @@ -343,7 +635,7 @@ GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const if (new == pos) { - reset_packed_buffer(&pbuf); + init_packed_buffer(&pbuf); status = read_packed_buffer(&pbuf, backend->fd); } @@ -448,6 +740,9 @@ bool g_object_storage_store_object(GObjectStorage *storage, const char *name, co backend = g_object_storage_find_backend(storage, name); + if (backend == NULL) + g_object_storage_add_backend(storage, name, &backend); + if (backend != NULL) { if (pos == NULL) diff --git a/src/analysis/storage/storage.h b/src/analysis/storage/storage.h index fd5d91f..43860af 100644 --- a/src/analysis/storage/storage.h +++ b/src/analysis/storage/storage.h @@ -31,7 +31,6 @@ #include "serialize.h" #include "tpmem.h" -#include "../loaded.h" @@ -54,10 +53,13 @@ typedef struct _GObjectStorageClass GObjectStorageClass; GType g_object_storage_get_type(void); /* Crée le support d'une conservation d'objets en place. */ -GObjectStorage *g_object_storage_new(GLoadedContent *); +GObjectStorage *g_object_storage_new(const char *); -/* Ajoute le support d'un nouveau groupe d'objets construits. */ -bool g_object_storage_add_backend(GObjectStorage *, const char *, const char *); +/* Charge le support d'une conservation d'objets en place. */ +GObjectStorage *g_object_storage_load(packed_buffer_t *); + +/* Sauvegarde le support d'une conservation d'objets en place. */ +bool g_object_storage_store(GObjectStorage *, packed_buffer_t *); /* Charge un objet à partir de données rassemblées. */ GSerializableObject *g_object_storage_load_object(GObjectStorage *, const char *, off64_t); diff --git a/src/analysis/storage/tpmem.c b/src/analysis/storage/tpmem.c index cda8223..0703aeb 100644 --- a/src/analysis/storage/tpmem.c +++ b/src/analysis/storage/tpmem.c @@ -65,7 +65,7 @@ struct _GTypeMemory GObject parent; /* A laisser en premier */ gtype_ref_info_t *gtypes; /* Types des objets reconnus */ - uint64_t count; /* Quantité de ces objets */ + size_t count; /* Quantité de ces objets */ GMutex mutex; /* Contrôle d'accès à la liste */ }; @@ -248,11 +248,19 @@ bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) assert(tpmem->gtypes == NULL); tpmem->gtypes = calloc(count, sizeof(gtype_ref_info_t)); + setup_empty_rle_string(&str); + for (i = 0; i < tpmem->count && result; i++) { result = unpack_rle_string(&str, pbuf); if (!result) break; + if (get_rle_string(&str) == NULL) + { + exit_rle_string(&str); + break; + } + tpmem->gtypes[i].gtype = g_type_from_name(get_rle_string(&str)); result = (tpmem->gtypes[i].gtype != 0); @@ -291,12 +299,12 @@ bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf) { GObject *result; /* Nouvelle instance à renvoyer*/ - uint64_t index; /* Indice du point d'insertion */ + uleb128_t index; /* Indice du point d'insertion */ bool status; /* Bilan d'une récupération */ result = NULL; - status = extract_packed_buffer(pbuf, &index, sizeof(uint64_t), true); + status = unpack_uleb128(&index, pbuf); if (status) { @@ -318,7 +326,7 @@ GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf) * * * Paramètres : tpmem = mémoire à manipuler. * * obj = instance dont le type est à mémoriser. * -* pbuf = zone tampon à remplir. * +* pbuf = zone tampon à remplir. [OUT] * * * * Description : Sauvegarde le type d'un objet instancié. * * * @@ -332,7 +340,7 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b { bool result; /* Bilan à retourner */ GType gtype; /* Type à enregistrer */ - uint64_t index; /* Indice du point d'insertion */ + size_t index; /* Indice du point d'insertion */ gtype = G_TYPE_FROM_INSTANCE(obj); @@ -369,7 +377,7 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b g_mutex_unlock(&tpmem->mutex); - result = extend_packed_buffer(pbuf, &index, sizeof(uint64_t), true); + result = pack_uleb128((uleb128_t []){ index }, pbuf); } @@ -381,7 +389,7 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b /****************************************************************************** * * * Paramètres : tpmem = mémoire à consulter. * -* pbuf = zone tampon à remplir. * +* pbuf = zone tampon à remplir. [OUT] * * * * Description : Enregistre tous les types mémorisés dans un tampon. * * * |