diff options
Diffstat (limited to 'src/analysis/db/collection.c')
-rw-r--r-- | src/analysis/db/collection.c | 625 |
1 files changed, 325 insertions, 300 deletions
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index f728718..edb55d8 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -58,14 +58,23 @@ static void g_db_collection_finalize(GDbCollection *); -/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +#define g_db_collection_find_by_timestamped(c, i) c->count + +#define g_db_collection_find_by_timestamp(c, i) c->count + + + +/* Ajoute un élément dans la liste des éléments actifs. */ +static void g_db_collection_set_last_item(GDbCollection *, GDbItem *, bool); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool _g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *); +/* Retire un élément de la liste des éléments courants. */ +static void g_db_collection_unset_last_item(GDbCollection *, GDbItem *, size_t); + + + +/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *); /* Charge et intère un élément dans une collection. */ static bool g_db_collection_load_new_item(const bound_value *, size_t, GDbCollection *); @@ -104,8 +113,6 @@ static void g_db_collection_class_init(GDbCollectionClass *klass) object->dispose = (GObjectFinalizeFunc/* ! */)g_db_collection_dispose; object->finalize = (GObjectFinalizeFunc)g_db_collection_finalize; - klass->setup_load = (collec_setup_load_fc)_g_db_collection_setup_load; - g_signal_new("content-extended", G_TYPE_DB_COLLECTION, G_SIGNAL_RUN_LAST, @@ -114,6 +121,14 @@ static void g_db_collection_class_init(GDbCollectionClass *klass) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); + g_signal_new("state-changed", + G_TYPE_DB_COLLECTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GDbCollectionClass, state_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + } @@ -133,6 +148,9 @@ static void g_db_collection_init(GDbCollection *collec) { collec->binary = NULL; + collec->items = NULL; + collec->count = 0; + collec->last_items = g_hash_table_new_full((GHashFunc)g_db_item_hash_key, (GEqualFunc)g_db_item_cmp_key, (GDestroyNotify)g_object_unref, @@ -157,17 +175,10 @@ static void g_db_collection_init(GDbCollection *collec) static void g_db_collection_dispose(GDbCollection *collec) { - if (collec->items != NULL) - { - g_list_free_full(collec->items, g_object_unref); - collec->items = NULL; - } + size_t i; /* Boucle de parcours */ - if (collec->sorted != NULL) - { - g_list_free_full(collec->sorted, g_object_unref); - collec->sorted = NULL; - } + for (i = 0; i < collec->count; i++) + g_clear_object(&collec->items[i]); G_OBJECT_CLASS(g_db_collection_parent_class)->dispose(G_OBJECT(collec)); @@ -188,6 +199,9 @@ static void g_db_collection_dispose(GDbCollection *collec) static void g_db_collection_finalize(GDbCollection *collec) { + if (collec->items != NULL) + free(collec->items); + g_rw_lock_clear(&collec->params_access); G_OBJECT_CLASS(g_db_collection_parent_class)->finalize(G_OBJECT(collec)); @@ -361,8 +375,6 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3 bool result; /* Bilan à faire remonter */ DBAction action; /* Commande de la requête */ GDbItem *item; /* Définition d'élément visé */ - GList *found; /* Test de présence existante */ - timestamp_t inactive; /* Horodatage de désactivation */ result = _g_db_collection_unpack(collec, pbuf, &action, &item); if (!result) return false; @@ -379,7 +391,7 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3 if (result) { - if (collec->binary != NULL && g_db_item_is_active(item)) + if (collec->binary != NULL && !g_db_item_has_flag(item, DIF_DISABLED)) g_db_item_apply(item, collec->binary); if (db != NULL) @@ -389,50 +401,29 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3 break; - case DBA_REM_ITEM: - - g_db_collection_wlock(collec); - - found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_with_timestamp); - - result = (found != NULL); + case DBA_CHANGE_STATE: - if (result) + if (collec->binary != NULL) { - /* Côté client */ - if (db == NULL) - result = _g_db_collection_remove_item(collec, item, false, true); + result = g_db_collection_update_item_state(collec, item); - /* Côté serveur */ - else + if (result) { - if (g_db_item_is_active(G_DB_ITEM(found->data))) - { - inactive = _g_db_collection_compute_inactivity_timestamp(collec, false); - result = _g_db_collection_update_item_activity(collec, item, &inactive, false); - } + if (g_db_item_has_flag(item, DIF_DISABLED)) + g_db_item_cancel(item, collec->binary); + else + g_db_item_apply(item, collec->binary); } } - g_db_collection_wunlock(collec); - - break; - - case DBA_CHANGE_STATE: - - if (db == NULL) - { - if (g_db_item_is_active(item)) - result = g_db_collection_update_item_activity(collec, item, NULL); - else - { - inactive = g_db_item_get_timestamp(item) + 1; - result = g_db_collection_update_item_activity(collec, item, &inactive); - } - } else + { + assert(db != NULL); result = false; + } + + g_object_unref(G_OBJECT(item)); break; @@ -442,8 +433,6 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3 } - g_object_unref(G_OBJECT(item)); - return result; } @@ -500,7 +489,7 @@ bool g_db_collection_pack(GDbCollection *collec, packed_buffer *pbuf, DBAction a bool g_db_collection_pack_all_updates(GDbCollection *collec, packed_buffer *pbuf) { bool result; /* Bilan à renvoyer */ - GList *iter; /* Boucle de parcours */ + size_t i; /* Boucle de parcours */ result = true; @@ -509,13 +498,8 @@ bool g_db_collection_pack_all_updates(GDbCollection *collec, packed_buffer *pbuf * g_cdb_archive_add_client(). */ - for (iter = g_list_first(collec->items); - iter != NULL && result; - iter = g_list_next(iter)) - { - result = g_db_collection_pack(collec, pbuf, DBA_ADD_ITEM, G_DB_ITEM(iter->data)); - - } + for (i = 0; i < collec->count && result; i++) + result = g_db_collection_pack(collec, pbuf, DBA_ADD_ITEM, G_DB_ITEM(collec->items[i])); return result; @@ -560,6 +544,7 @@ void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock) /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à consulter. * +* count = taille de la liste constituée. [OUT] * * * * Description : Renvoie la liste des éléments rassemblés. * * * @@ -569,14 +554,34 @@ void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock) * * ******************************************************************************/ -GList *g_db_collection_get_items(const GDbCollection *collec) +GDbItem **g_db_collection_get_items(const GDbCollection *collec, size_t *count) { + GDbItem **result; /* Liste à retourner */ + size_t i; /* Boucle de parcours */ + /** * Un verrou doit être posé ! * Il n'y a pas d'assert() possible pour le vérifier... */ - return collec->items; + *count = collec->count; + + if (*count == 0) + result = NULL; + + else + { + result = malloc(*count * sizeof(GDbItem *)); + + for (i = 0; i < *count; i++) + { + result[i] = collec->items[i]; + g_object_ref(G_OBJECT(result[i])); + } + + } + + return result; } @@ -626,16 +631,16 @@ GDbItem *g_db_collection_has_key(GDbCollection *collec, ...) bool g_db_collection_has_item(GDbCollection *collec, GDbItem *item) { bool result; /* Bilan à retourner */ - GList *found; /* Test de présence existante */ + size_t index; /* Indice de l'élément trouvé */ /** * Un verrou doit être posé ! * Il n'y a pas d'assert() possible pour le vérifier... */ - found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_with_timestamp); + index = g_db_collection_find_by_timestamped(collec, item); - result = (found != NULL); + result = (index < collec->count); return result; @@ -646,36 +651,46 @@ bool g_db_collection_has_item(GDbCollection *collec, GDbItem *item) * * * Paramètres : collec = ensemble d'éléments à considérer. * * item = élément de collection à manipuler. * -* lock = indique si le verrou d'écriture doit être posé. * +* new = précise la nature de l'élément à insérer. * * * -* Description : Procède à l'ajout d'un nouvel élément dans la collection. * +* Description : Ajoute un élément dans la liste des éléments actifs. * * * -* Retour : Bilan de l'exécution de l'opération. * +* Retour : - * * * -* Remarques : L'appelant reste le propriétaire de l'object transféré. * +* Remarques : * * * ******************************************************************************/ -bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) +static void g_db_collection_set_last_item(GDbCollection *collec, GDbItem *item, bool new) { - bool result; /* Bilan à faire remonter */ GDbItem *prev; /* Elément similaire précédent */ + timestamp_t its; /* Horodatage #0 */ + timestamp_t pts; /* Horodatage #1 */ - result = true; - - if (lock) - g_db_collection_wlock(collec); - - 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_with_timestamp); + assert(!g_db_item_has_flag(item, DIF_DISABLED)); prev = g_hash_table_lookup(collec->last_items, item); if (prev != NULL) { + /** + * Dans le cas où le changement intervient sans contexte particulier, + * on s'assure de le pas remplacer un élément plus récent déjà en place + * par un élément nouvellement actif mais dépassé. + * + * Le code de g_db_collection_disable_at(), aux conséquences portant + * dans le serveur et le client, procède de manière à éviter cette + * situation par un ordre de parcours choisi. + * + * On insère néanmoins une petite sécurité. + */ + + its = g_db_item_get_timestamp(item); + pts = g_db_item_get_timestamp(prev); + + if (timestamp_is_younger(its, pts)) + goto already_up_to_date; + g_object_ref(G_OBJECT(prev)); if (g_db_item_get_flags(item) & DIF_ERASER) @@ -683,7 +698,8 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) else { - g_db_item_add_flag(item, DIF_UPDATED); + if (new) + g_db_item_add_flag(item, DIF_UPDATED); g_object_ref(G_OBJECT(item)); g_object_ref(G_OBJECT(item)); @@ -698,19 +714,20 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) else { - g_object_ref(G_OBJECT(item)); - g_object_ref(G_OBJECT(item)); + if (g_db_item_get_flags(item) & DIF_ERASER) + { + g_object_ref(G_OBJECT(item)); + g_object_ref(G_OBJECT(item)); - g_hash_table_add(collec->last_items, item); + g_hash_table_add(collec->last_items, item); + + } } - g_signal_emit_by_name(collec, "content-extended", item); + already_up_to_date: - if (lock) - g_db_collection_wunlock(collec); - - return result; + ; } @@ -720,49 +737,30 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) * Paramètres : collec = ensemble d'éléments à considérer. * * item = élément de collection à manipuler. * * lock = indique si le verrou d'écriture doit être posé. * -* signal = émet un événement pour signaler le retrait. * * * -* Description : Procède au retrait d'un nouvel élément dans la collection. * +* 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é. * +* Remarques : L'appelant perd la propriété de l'object transféré. * * * ******************************************************************************/ -bool _g_db_collection_remove_item(GDbCollection *collec, GDbItem *item, bool lock, bool signal) +bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) { bool result; /* Bilan à faire remonter */ - GList *found; /* Test de présence existante */ - GDbItem *internal; /* Elément interne à modifier */ result = true; if (lock) g_db_collection_wlock(collec); - found = g_list_find_custom(collec->sorted, item, (GCompareFunc)g_db_item_compare_with_timestamp); - - result = (found != NULL); + collec->items = realloc(collec->items, ++collec->count * sizeof(GDbItem *)); + collec->items[collec->count - 1] = item; - if (result) - { - internal = G_DB_ITEM(found->data); + g_db_collection_set_last_item(collec, item, true); - collec->sorted = g_list_delete_link(collec->sorted, found); - - found = g_list_find(collec->items, item); - assert(found != NULL); - - collec->items = g_list_delete_link(collec->items, found); - - if (signal) - ;//g_signal_emit_by_name(collec, "content-changed", DBA_REM_ITEM, internal); - - g_object_unref(G_OBJECT(internal)); - g_object_unref(G_OBJECT(internal)); - - } + g_signal_emit_by_name(collec, "content-extended", item); if (lock) g_db_collection_wunlock(collec); @@ -775,47 +773,54 @@ bool _g_db_collection_remove_item(GDbCollection *collec, GDbItem *item, bool loc /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à considérer. * -* lock = indique si le verrou d'écriture doit être posé. * +* pbuf = paquet de données où venir inscrire les infos. * * * -* Description : Détermine l'horodatage le plus jeune pour une désactivation. * +* Description : Procède au retrait des éléments désactivés de la collection. * * * -* Retour : Horodatage à utiliser pour une phase de désactivation. * +* Retour : Bilan de l'exécution de l'opération. * * * -* Remarques : - * +* Remarques : * * * ******************************************************************************/ -timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec, bool lock) +bool g_db_collection_drop_disabled_items(GDbCollection *collec, packed_buffer *pbuf) { - timestamp_t result; /* Horodatage à retourner */ - GList *iter; /* Boucle de parcours */ - GDbItem *item; /* Elément interne à consulter */ - timestamp_t stamp; /* Horodatage de l'élément */ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + GDbItem *item; /* Elément désactivé */ +#ifndef NDEBUG + GDbItem *enabled; /* Eventuel similarité active */ +#endif - result = TIMESTAMP_ALL_ACTIVE; + /** + * Voie de suppression d'un élément côté serveur. + */ - if (lock) - g_db_collection_wlock(collec); + result = true; - for (iter = g_list_first(collec->items); - iter != NULL; - iter = g_list_next(iter)) + g_db_collection_wlock(collec); + + for (i = collec->count; i > 0 && result; i--) { - item = G_DB_ITEM(iter->data); + item = collec->items[i - 1]; - if (!g_db_item_is_active(item)) - { - stamp = g_db_item_get_timestamp(item); + if (!g_db_item_has_flag(item, DIF_DISABLED)) + break; - if (timestamp_is_younger(stamp, result)) - result = stamp; +#ifndef NDEBUG + enabled = g_hash_table_lookup(collec->last_items, item); + assert(enabled != item); +#endif - } + collec->items = realloc(collec->items, --collec->count * sizeof(GDbItem *)); + + result = g_db_collection_pack(collec, pbuf, DBA_REM_ITEM, item); + + g_object_unref(G_OBJECT(item)); } - if (lock) - g_db_collection_wunlock(collec); + g_db_collection_wunlock(collec); return result; @@ -826,9 +831,8 @@ timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec, * * * Paramètres : collec = ensemble d'éléments à considérer. * * item = élément de collection à manipuler. * -* lock = indique si le verrou d'écriture doit être posé. * * * -* Description : Met à jour le statut d'activité d'un élément de collection. * +* Description : Procède au retrait d'un élément dans la collection. * * * * Retour : Bilan de l'exécution de l'opération. * * * @@ -836,31 +840,47 @@ timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec, * * ******************************************************************************/ -bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item, timestamp_t *timestamp, bool lock) +bool g_db_collection_remove_item(GDbCollection *collec, const GDbItem *item) { bool result; /* Bilan à faire remonter */ - GList *found; /* Test de présence existante */ - GDbItem *internal; /* Elément interne à modifier */ + size_t found; /* Indice de l'élément concerné*/ + GDbItem *disabled; /* Elément désactivé */ +#ifndef NDEBUG + GDbItem *enabled; /* Eventuel similarité active */ +#endif - if (lock) - g_db_collection_wlock(collec); + /** + * Voie de suppression d'un élément côté serveur. + */ - found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_without_timestamp); + g_db_collection_wlock(collec); - result = (found != NULL); + found = g_db_collection_find_by_timestamped(collec, item); + + result = (found < collec->count); + assert(result); if (result) { - internal = G_DB_ITEM(found->data); + disabled = collec->items[found]; + + assert(g_db_item_has_flag(disabled, DIF_DISABLED)); + +#ifndef NDEBUG + enabled = g_hash_table_lookup(collec->last_items, disabled); + assert(enabled != disabled); +#endif + + memmove(collec->items + found, collec->items + found + 1, + (collec->count - found - 1) * sizeof(GDbItem *)); - result = g_db_item_set_activity(internal, collec->binary, timestamp); + collec->items = realloc(collec->items, --collec->count * sizeof(GDbItem *)); - //g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, internal); + g_object_unref(G_OBJECT(disabled)); } - if (lock) - g_db_collection_wunlock(collec); + g_db_collection_wunlock(collec); return result; @@ -869,157 +889,202 @@ bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item, /****************************************************************************** * * -* Paramètres : collec = ensemble d'éléments à considérer. * -* timestamp = date du dernier élément à garder comme actif. * -* inactive = date du premier élément inactif rencontré. [OUT] * -* db = base de données à mettre à jour. * +* Paramètres : collec = ensemble d'éléments à considérer. * +* item = élément de collection à manipuler. * +* count = décompte des éléments actifs. * * * -* Description : Active les éléments en amont d'un horodatage donné. * +* Description : Retire un élément de la liste des éléments courants. * * * * Retour : - * * * -* Remarques : - * +* Remarques : * * * ******************************************************************************/ -GList *g_db_collection_set_last_active(GDbCollection *collec, timestamp_t timestamp, timestamp_t *inactive, sqlite3 *db) +static void g_db_collection_unset_last_item(GDbCollection *collec, GDbItem *item, size_t count) { - GList *result; /* Liste d'inactifs à renvoyer */ - GList *i; /* Parcours des éléments */ - GDbItem *item; /* Elément à traiter */ - timestamp_t stamp; /* Horodatage de l'élément */ + GDbItem *prev; /* Elément similaire précédent */ + GDbItem *old; /* Ancien élément similaire */ + size_t i; /* Boucle de parcours */ - result = NULL; + assert(g_db_item_has_flag(item, DIF_DISABLED)); + + prev = g_hash_table_lookup(collec->last_items, item); - for (i = g_list_first(collec->items); i != NULL; i = g_list_next(i)) + if (prev == item) { - item = G_DB_ITEM(i->data); - stamp = g_db_item_get_timestamp(item); + old = NULL; - if (timestamp_is_younger(stamp, timestamp)) - { - if (!g_db_item_is_active(item)) - { - /* ... */g_db_item_set_activity(item, collec->binary, NULL); - /* ... */g_db_collection_store_updated_item(collec, item, db); - //g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, item); - } + for (i = count; i > 0; i++) + if (g_db_item_cmp_key(collec->items[i - 1], item)) + break; + else + old = collec->items[i - 1]; - } + if (old == NULL || g_db_item_get_flags(old) & DIF_ERASER) + g_hash_table_remove(collec->last_items, item); else { - if (!g_db_item_is_active(item)) - { - if (timestamp_is_younger(stamp, *inactive)) - *inactive = stamp; - } + g_object_ref(G_OBJECT(old)); + g_object_ref(G_OBJECT(old)); - else - result = g_list_append(result, item); + g_hash_table_replace(collec->last_items, old, old); } } - return result; - } /****************************************************************************** * * -* Paramètres : collec = ensemble d'éléments à considérer. * -* item = élément à désactiver. * -* timestamp = date du premier élément inactif rencontré. [OUT] * +* Paramètres : binary = élément binaire à consulter. * +* timestamp = date du dernier élément à garder comme actif. * +* db = base de données à mettre à jour. * +* pbuf = paquet de données où venir inscrire les infos. * * * * Description : Désactive les éléments en aval d'un horodatage donné. * * * -* Retour : true si l'élément a été traité, false sinon. * +* Retour : true si la commande a bien été envoyée, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -bool g_db_collection_set_inactive(GDbCollection *collec, GDbItem *item, timestamp_t *timestamp) +bool g_db_collection_disable_at(GDbCollection *collec, timestamp_t timestamp, sqlite3 *db, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ + size_t start; /* Début de la zone à changer */ + size_t back; /* Début de restauration */ + size_t i; /* Boucle de parcours */ + GDbItem *item; /* Elément à traiter */ - /* Si cette collection n'est pas concernée, on ne bouge pas ! */ - if (G_OBJECT_TYPE(G_OBJECT(item)) != collec->type) return false; + result = true; - result = g_db_item_set_activity(item, collec->binary, timestamp); + g_db_collection_wlock(collec); - //g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, item); + start = g_db_collection_find_by_timestamp(collec, timestamp); - return result; + /* Réactivation d'éléments ? */ -} + if (start > 0) + { + back = start; + for (i = start; i > 0; i--) + if (!g_db_item_has_flag(collec->items[i - 1], DIF_DISABLED)) + break; + else + back--; + for (i = back; i < start && result; i++) + { + item = collec->items[i]; -/* ---------------------------------------------------------------------------------- */ -/* MANIPULATIONS AVEC UNE BASE DE DONNEES */ -/* ---------------------------------------------------------------------------------- */ + g_db_item_remove_flag(item, DIF_DISABLED); + g_db_collection_store_updated_item(collec, item, db); -/****************************************************************************** -* * -* Paramètres : collec = ensemble d'éléments spectateur des opérations. * -* db = accès à la base de données. * -* * -* Description : Crée la table d'élément dans une base de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + g_db_collection_set_last_item(collec, item, false); -bool g_db_collection_create_db_table(const GDbCollection *collec, sqlite3 *db) -{ - return G_DB_COLLECTION_GET_CLASS(collec)->create_table(collec, db); + result = g_db_collection_pack(collec, pbuf, DBA_CHANGE_STATE, item); + + } + + } + + /* Désactivation des éléments en queue */ + + for (i = start; i < collec->count && result; i++) + { + item = collec->items[i]; + + if (g_db_item_has_flag(item, DIF_DISABLED)) + break; + + g_db_item_add_flag(item, DIF_DISABLED); + + g_db_collection_store_updated_item(collec, item, db); + + g_db_collection_unset_last_item(collec, item, start); + + result = g_db_collection_pack(collec, pbuf, DBA_CHANGE_STATE, item); + + } + + g_db_collection_wunlock(collec); + + return result; } /****************************************************************************** * * -* Paramètres : collec = ensemble d'éléments à consulter. * -* values = tableau d'éléments à compléter. [OUT] * -* count = nombre de descriptions renseignées. [OUT] * +* Paramètres : collec = ensemble d'éléments à considérer. * +* item = élément de collection à manipuler. * * * -* Description : Décrit les colonnes utiles à un chargement de données. * +* Description : Prend acte d'un changement d'état d'un élément de collection.* * * -* Retour : Bilan de l'opération. * +* Retour : Bilan de l'exécution de l'opération. * * * -* Remarques : - * +* Remarques : L'appelant reste le propriétaire de l'object transféré. * * * ******************************************************************************/ -static bool _g_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count) +bool g_db_collection_update_item_state(GDbCollection *collec, const GDbItem *item) { - if (!store_timestamp(NULL, "created", values, count)) - return false; + bool result; /* Bilan à faire remonter */ + size_t index; /* Indice de l'élément visé */ + GDbItem *changed; /* Elément à basculer */ + DbItemFlags new; /* Nouvelles propriétés */ + + result = false; + + g_db_collection_wlock(collec); + + index = g_db_collection_find_by_timestamped(collec, item); - if (!store_timestamp(NULL, "timestamp", values, count)) - return false; + result = (index < collec->count); - if (!store_rle_string(NULL, "author", values, count)) - return false; + if (result) + { + changed = collec->items[index]; + + new = g_db_item_get_flags(item); + + g_db_item_set_flags(changed, new); + + if (new & DIF_DISABLED) + g_db_collection_unset_last_item(collec, changed, index); + else + g_db_collection_set_last_item(collec, changed, false); + + g_signal_emit_by_name(collec, "state-changed", changed); + + } - return true; + g_db_collection_wunlock(collec); + + return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATIONS AVEC UNE BASE DE DONNEES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : collec = ensemble d'éléments à consulter. * -* values = tableau d'éléments à compléter. [OUT] * -* count = nombre de descriptions renseignées. [OUT] * +* Paramètres : collec = ensemble d'éléments spectateur des opérations. * +* db = accès à la base de données. * * * -* Description : Décrit les colonnes utiles à un chargement de données. * +* Description : Crée la table d'élément dans une base de données. * * * * Retour : Bilan de l'opération. * * * @@ -1027,12 +1092,9 @@ static bool _g_db_collection_setup_load(GDbCollection *collec, bound_value **val * * ******************************************************************************/ -static bool g_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count) +bool g_db_collection_create_db_table(const GDbCollection *collec, sqlite3 *db) { - *values = NULL; - *count = 0; - - return G_DB_COLLECTION_GET_CLASS(collec)->setup_load(collec, values, count); + return G_DB_COLLECTION_GET_CLASS(collec)->create_table(collec, db); } @@ -1061,13 +1123,10 @@ static bool g_db_collection_load_new_item(const bound_value *values, size_t coun result = g_db_item_load(new, values, count); if (result) - { result = g_db_collection_add_item(G_DB_COLLECTION(collec), new); - + else g_object_unref(G_OBJECT(new)); - } - return result; } @@ -1089,10 +1148,15 @@ static bool g_db_collection_load_new_item(const bound_value *values, size_t coun bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db) { bool result; /* Conclusion à faire remonter */ + GDbItem *dummy; /* Interface vide */ bound_value *values; /* Champs de table à inclure */ size_t count; /* Nombre de ces champs */ - result = g_db_collection_setup_load(collec, &values, &count); + dummy = g_object_new(collec->type, NULL); + + result = g_db_item_setup_load(dummy, &values, &count); + + g_object_unref(G_OBJECT(dummy)); if (result) result = load_db_values(db, collec->name, values, count, (db_load_cb)g_db_collection_load_new_item, collec); @@ -1447,9 +1511,10 @@ bool pack_all_collection_updates(GList *list, packed_buffer *pbuf) /****************************************************************************** * * -* Paramètres : list = ensemble de collectons à traiter. * -* pbuf = paquet de données où venir puiser les infos. * -* db = base de données à mettre à jour. * +* Paramètres : list = ensemble de collectons à traiter. * +* inbuf = paquet de données où venir puiser les infos. * +* outbuf = paquet de données où inscrire les mises à jour. * +* db = base de données à mettre à jour. * * * * Description : Met à jour les statuts d'activité des éléments. * * * @@ -1459,18 +1524,14 @@ bool pack_all_collection_updates(GList *list, packed_buffer *pbuf) * * ******************************************************************************/ -bool update_activity_in_collections(GList *list, packed_buffer *pbuf, sqlite3 *db) +bool update_activity_in_collections(GList *list, packed_buffer *inbuf, packed_buffer *outbuf, sqlite3 *db) { bool result; /* Résultat global à renvoyer */ bool status; /* Bilan de lecture initiale */ timestamp_t timestamp; /* Horodatage de limite */ - timestamp_t inactive; /* Date du premier inactif */ - GList *remaining; /* Eléments restants à traiter */ - GList *c; /* Boucle de parcours #1 */ - GDbCollection *collec; /* Collection à manipuler */ - GList *got; /* Eléments restants à traiter */ - GList *i; /* Boucle de parcours #2 */ - GDbItem *item; /* Elément collecté à manipuler*/ + GList *iter; /* Boucle de parcours */ + + result = true; /** * Cette procédure n'est appelée que depuis g_cdb_archive_process(), @@ -1479,55 +1540,19 @@ bool update_activity_in_collections(GList *list, packed_buffer *pbuf, sqlite3 *d * On a donc l'assurance d'un traitement global homgène des horodatages. */ - status = unpack_timestamp(×tamp, pbuf); + status = unpack_timestamp(×tamp, inbuf); if (!status) return false; - inactive = TIMESTAMP_ALL_ACTIVE; - - remaining = NULL; - - wlock_collections(list); - - for (c = g_list_first(list); c != NULL; c = g_list_next(c)) - { - collec = G_DB_COLLECTION(c->data); - - got = g_db_collection_set_last_active(collec, timestamp, &inactive, db); - remaining = g_list_concat(remaining, got); - - } - - gint sort_with_timestamp(GDbItem *a, GDbItem *b) - { - return g_db_item_cmp(a, b, false); - } - remaining = g_list_sort(remaining, (GCompareFunc)sort_with_timestamp); - result = true; - - for (i = g_list_last(remaining); i != NULL && result; i = g_list_previous(i)) + for (iter = g_list_first(list); + iter != NULL && result; + iter = g_list_next(iter)) { - item = G_DB_ITEM(i->data); - - for (c = g_list_first(list); c != NULL && result; c = g_list_next(c)) - { - collec = G_DB_COLLECTION(c->data); - - if (g_db_collection_set_inactive(collec, item, &inactive)) - { - result = g_db_collection_store_updated_item(collec, item, db); - break; - } - - } + result = g_db_collection_disable_at(G_DB_COLLECTION(iter->data), timestamp, db, outbuf); } - wunlock_collections(list); - - g_list_free(remaining); - return result; } |