diff options
Diffstat (limited to 'src/analysis/db/collection.c')
-rw-r--r-- | src/analysis/db/collection.c | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 9ddba48..20b1ff3 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -24,3 +24,494 @@ #include "collection.h" +#include "../../common/io.h" +#include "../../glibext/chrysamarshal.h" + + + +/* Collection générique d'éléments (instance) */ +struct _GDbCollection +{ + GObject parent; /* A laisser en premier */ + + uint32_t featuring; /* Fonctionnalité représentée */ + GType type; /* Identifiant GLib équivalent */ + + GList *items; /* Eléments rassemblés */ + GList *sorted; /* Eléments triés */ + GRWLock params_access; /* Verrou de protection */ + +}; + +/* Collection générique d'éléments (classe) */ +struct _GDbCollectionClass +{ + GObjectClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (* content_changed) (GDbCollection *, DBAction, GDbItem *); + +}; + + + + +/* Initialise la classe des collections génériques d'éléments. */ +static void g_db_collection_class_init(GDbCollectionClass *); + +/* Initialise une collection générique d'éléments. */ +static void g_db_collection_init(GDbCollection *); + +/* Supprime toutes les références externes. */ +static void g_db_collection_dispose(GDbCollection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_collection_finalize(GDbCollection *); + + + + +/* Indique le type défini pour une collection générique d'éléments. */ +G_DEFINE_TYPE(GDbCollection, g_db_collection, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des collections génériques d'éléments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_class_init(GDbCollectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_collection_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_collection_finalize; + + g_signal_new("content-changed", + G_TYPE_DB_COLLECTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GDbCollectionClass, content_changed), + NULL, NULL, + g_cclosure_user_marshal_VOID__ENUM_OBJECT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_OBJECT); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance à initialiser. * +* * +* Description : Initialise une collection générique d'éléments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_init(GDbCollection *collec) +{ + g_rw_lock_init(&collec->params_access); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_dispose(GDbCollection *collec) +{ + G_OBJECT_CLASS(g_db_collection_parent_class)->dispose(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_finalize(GDbCollection *collec) +{ + g_rw_lock_clear(&collec->params_access); + + G_OBJECT_CLASS(g_db_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : id = identifiant réseau des éléments à traiter. * +* type = type GLib des éléments à intégrer dans la collection. * +* * +* Description : Prépare la mise en place d'une nouvelle collection. * +* * +* Retour : Adresse de l'instance ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbCollection *g_db_collection_new(uint32_t id, GType type) +{ + GDbCollection *result; /* Adresse à retourner */ + + result = g_object_new(G_TYPE_DB_COLLECTION, NULL); + + result->featuring = id; + result->type = type; + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = collection générique d'éléments à consulter. * +* * +* Description : Décrit le type des éléments rassemblées dans une collection. * +* * +* Retour : Identifiant interne des éléments collectionés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t g_db_collection_get_feature(const GDbCollection *collec) +{ + return collec->featuring; + +} + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* fd = flux ouvert en lecture pour la réception de données.* +* * +* Description : Réceptionne et traite une requête réseau pour collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : Cette fonction est uniquement destinée aux appels depuis * +* la fonction g_cdb_archive_process() ; une partie des * +* informations ont déjà été tirées des échanges protocolaires. * +* * +******************************************************************************/ + +bool g_db_collection_recv(GDbCollection *collec, int fd) +{ + bool result; /* Bilan à faire remonter */ + uint32_t val32; /* Valeur sur 32 bits */ + bool status; /* Bilan de lecture initiale */ + DBAction action; /* Commande de la requête */ + GDbItem *item; /* Définition d'élément visé */ + + status = safe_recv(fd, &val32, sizeof(uint32_t), 0); + if (!status) return false; + + action = be32toh(val32); + if (action < 0 || action >= DBA_COUNT) return false; + + item = g_object_new(collec->type, NULL); + + status = g_db_item_recv(item, fd, 0); + if (!status) return false; + + result = false; + + switch (action) + { + case DBA_ADD_ITEM: + result = g_db_collection_add_item(collec, item); + break; + + case DBA_REM_ITEM: + break; + + case DBA_MOD_ITEM: + result = g_db_collection_modify_item(collec, item); + break; + + default: + /* Pour GCC : DBA_COUNT */ + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* fd = flux ouvert en écriture pour l'émission de données. * +* action = avenir de l'élément fourni. * +* item = élément de collection à sérialiser. * +* * +* Description : Envoie pour traitement une requête réseau pour collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_collection_send(GDbCollection *collec, int fd, DBAction action, GDbItem *item) +{ + bool status; /* Bilan de lecture initiale */ + + status = safe_send(fd, (uint32_t []) { htobe32(DBC_COLLECTION) }, sizeof(uint32_t), MSG_MORE); + if (!status) return false; + + status = safe_send(fd, (uint32_t []) { htobe32(collec->featuring) }, sizeof(uint32_t), MSG_MORE); + if (!status) return false; + + status = safe_send(fd, (uint32_t []) { htobe32(action) }, sizeof(uint32_t), MSG_MORE); + if (!status) return false; + + status = g_db_item_send(item, fd, 0); + if (!status) return false; + + return true; + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = collection à mettre à jour. * +* write = précise le type d'accès prévu (lecture/écriture). * +* lock = indique le sens du verrouillage à mener. * +* * +* Description : Met à disposition un encadrement des accès aux éléments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock) +{ + if (write) + { + if (lock) g_rw_lock_writer_lock(&collec->params_access); + else g_rw_lock_writer_unlock(&collec->params_access); + } + else + { + if (lock) g_rw_lock_reader_lock(&collec->params_access); + else g_rw_lock_reader_unlock(&collec->params_access); + } + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* * +* Description : Renvoie la liste des éléments rassemblés. * +* * +* Retour : Liste d'éléments à parcourir. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GList *g_db_collection_list_items(const GDbCollection *collec) +{ + /** + * Un verrou doit être posé ! + * Il n'y a pas d'assert() possible pour le vérifier... + */ + + return collec->items; + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* item = élément de collection à manipuler. * +* * +* Description : Procède à l'ajout d'un nouvel élément dans la collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : L'appelant reste le propriétaire de l'object transféré. * +* * +******************************************************************************/ + +bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item) +{ + bool result; /* Bilan à faire remonter */ + GList *found; /* Test de présence existante */ + + g_db_collection_wlock(collec); + + found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare); + + if (found != NULL) + result = g_db_collection_modify_item(collec, item); + + else + { + g_object_ref(G_OBJECT(item)); + collec->items = g_list_append(collec->items, item); + + g_object_ref(G_OBJECT(item)); + collec->sorted = g_list_insert_sorted(collec->sorted, item, (GCompareFunc)g_db_item_compare); + + g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item); + + result = true; + + } + + g_db_collection_wunlock(collec); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* item = élément de collection à copier. * +* * +* Description : Procède à la modification d'un élément dans la collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : L'appelant reste le propriétaire de l'object transféré. * +* * +******************************************************************************/ + +bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item) +{ + bool result; /* Bilan à faire remonter */ + GList *found; /* Test de présence existante */ + + found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare); + + + + result = true; + + + + + + return result; + +} + + + + +/* ---------------------------------------------------------------------------------- */ +/* CREATION DE L'ABSTRACTION POUR COLLECTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de collectons à parcourir. * +* id = identifiant interne du type d'éléments groupés. * +* * +* Description : Recherche une collection correspondant à un type donné. * +* * +* Retour : Collection trouvée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbCollection *find_collection_in_list(GList *list, uint32_t id) +{ + GDbCollection *result; /* Collection trouvée renvoyée */ + GList *iter; /* Boucle de parcours */ + + result = NULL; + + for (iter = g_list_first(list); + iter != NULL; + iter = g_list_next(iter)) + { + result = G_DB_COLLECTION(iter->data); + + if (g_db_collection_get_feature(result) == id) + break; + + } + + return (iter != NULL ? result : NULL); + +} |