From a22b3a083c0b92de6b5d9b154773a26aeb99db0c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 30 Jul 2015 00:56:33 +0000 Subject: Removed collection items by deactivating them using the activity timestamps. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@560 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 13 ++++ src/analysis/binary.c | 56 +++++++++++++++++ src/analysis/binary.h | 8 ++- src/analysis/db/collection.c | 145 ++++++++++++++++++++++++++++++++++++++++--- src/analysis/db/collection.h | 12 +++- src/analysis/db/item-int.h | 2 - src/analysis/db/item.c | 26 +++----- 7 files changed, 227 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index c92a45e..0eda0bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +15-07-30 Cyrille Bagard + + * src/analysis/binary.c: + * src/analysis/binary.h: + * src/analysis/db/collection.c: + * src/analysis/db/collection.h: + Remove collection items by deactivating them using the activity timestamps. + + * src/analysis/db/item.c: + * src/analysis/db/item-int.h: + Always send and receive timestamps on the network, so do not remember + the side of the collected item (server or not) anymore. + 15-07-29 Cyrille Bagard * src/analysis/db/collection.c: diff --git a/src/analysis/binary.c b/src/analysis/binary.c index c6ae4e5..615e72e 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -862,6 +862,62 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures featur +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à consulter. * +* feature = fonctionnalité visée par la requête. * +* item = élémnent à retirer d'un serveur de collection. * +* lock = indique si le verrou d'écriture doit être posé. * +* * +* Description : Demande la suppression de modification dans une collection. * +* * +* Retour : Bilan partiel de l'opération demandée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item, bool lock) +{ + bool result; /* Bilan à faire remonter */ + GDbCollection *collec; /* Collection visée au final */ + DBStorage storage; /* Forme d'enregistrement */ + GDbClient *client; /* Liaison à utiliser */ + int fd; /* Identifiant du canal de com.*/ + + collec = g_loaded_binary_find_collection(binary, feature); + if (collec == NULL) return false; + + /* S'il n'y a pas besoin de sauvegarde... */ + if (g_db_item_is_volatile(item)) + _g_db_collection_remove_item(collec, item, lock); + + /* Sinon on envoie par le réseau ! */ + else + { + storage = g_loaded_binary_get_storage(binary, feature); + + + /* TODO : sélection du bon client... */ + client = binary->local; + + + fd = g_db_client_get_fd(client); + + result = g_db_collection_send(collec, fd, DBA_REM_ITEM, item); + + g_db_client_put_fd(client); + + } + + g_object_unref(G_OBJECT(collec)); + + return result; + +} + + + diff --git a/src/analysis/binary.h b/src/analysis/binary.h index fb37310..768f53a 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -128,13 +128,15 @@ GDbCollection *g_loaded_binary_find_collection(const GLoadedBinary *, DBFeatures bool _g_loaded_binary_add_to_collection(GLoadedBinary *, DBFeatures, GDbItem *, bool); #define g_loaded_binary_add_to_collection(b, f, i) \ - _g_loaded_binary_add_to_collection(b, f, i, true); + _g_loaded_binary_add_to_collection(b, f, i, true) +/* Demande la suppression de modification dans une collection. */ +bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbItem *, bool); +#define g_loaded_binary_remove_from_collection(b, f, i) \ + _g_loaded_binary_remove_from_collection(b, f, i, true) -#define g_loaded_binary_remove_from_collection(b, f, i) - /** * TODO : diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 5e5adb7..0292c5c 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -278,6 +278,8 @@ bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db) bool status; /* Bilan de lecture initiale */ 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 */ status = safe_recv(fd, &val32, sizeof(uint32_t), 0); if (!status) return false; @@ -287,9 +289,6 @@ bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db) item = g_object_new(collec->type, NULL); - if (db != NULL) - g_db_item_set_server_side(item); - status = g_db_item_recv(item, fd, 0); if (!status) return false; @@ -299,6 +298,10 @@ bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db) { case DBA_ADD_ITEM: + /* Ecrasement des horodatages par les valeurs communes du serveur */ + if (db != NULL) + g_db_item_set_server_side(item); + result = g_db_collection_add_item(collec, item); if (result) @@ -310,17 +313,44 @@ bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db) } if (!result) - /* TODO : retirer l'élémnt */; + /* TODO : retirer l'élément */; 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); + + if (result) + { + /* Côté client */ + if (db == NULL) + result = _g_db_collection_remove_item(collec, item, false); + + /* Côté serveur */ + else + { + 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); + } + } + + } + + g_db_collection_wunlock(collec); + break; case DBA_CHANGE_STATE: if (db == NULL) - result = g_db_collection_update_item_activity(collec, item); + result = g_db_collection_update_item_activity(collec, item, g_db_item_get_timestamp(item) + 1); else result = false; @@ -565,9 +595,104 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item); + if (lock) + g_db_collection_wunlock(collec); + + return result; + +} + + +/****************************************************************************** +* * +* 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 : Procède au retrait 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_remove_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->items, item, (GCompareFunc)g_db_item_compare_with_timestamp); + + result = (found != NULL); + + if (result) + { + internal = G_DB_ITEM(found->data); + + collec->items = g_list_delete_link(collec->items, found); + + g_signal_emit_by_name(collec, "content-changed", DBA_REM_ITEM, internal); + + g_object_unref(G_OBJECT(internal)); + + } + + if (lock) + g_db_collection_wunlock(collec); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* lock = indique si le verrou d'écriture doit être posé. * +* * +* Description : Détermine l'horodatage le plus jeune pour une désactivation. * +* * +* Retour : Horodatage à utiliser pour une phase de désactivation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec, bool lock) +{ + timestamp_t result; /* Horodatage à retourner */ + GList *iter; /* Boucle de parcours */ + GDbItem *item; /* Elément interne à consulter */ + timestamp_t stamp; /* Horodatage de l'élément */ + + result = TIMESTAMP_ALL_ACTIVE; + + if (lock) + g_db_collection_wlock(collec); + + for (iter = g_list_first(collec->items); + iter != NULL && result; + iter = g_list_next(iter)) + { + item = G_DB_ITEM(iter->data); + + if (!g_db_item_is_active(item)) + { + stamp = g_db_item_get_timestamp(item); - printf(" ==== CONTENT CHANGED (-> %u) !!!\n", g_list_length(collec->items)); + if (timestamp_is_younger(stamp, result)) + result = stamp; + } + + } if (lock) g_db_collection_wunlock(collec); @@ -591,7 +716,7 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) * * ******************************************************************************/ -bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item, bool lock) +bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item, timestamp_t timestamp, bool lock) { bool result; /* Bilan à faire remonter */ GList *found; /* Test de présence existante */ @@ -608,7 +733,7 @@ bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item, { internal = G_DB_ITEM(found->data); - g_db_item_set_activity(internal, (timestamp_t []) { g_db_item_get_timestamp(item) + 1 }); + g_db_item_set_activity(internal, (timestamp_t []) { timestamp }); g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, internal); @@ -893,8 +1018,6 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db) new = g_object_new(G_DB_COLLECTION(collec)->type, NULL); - g_db_item_set_server_side(new); - result = g_db_item_load(new, values, count); result &= g_db_collection_add_item(G_DB_COLLECTION(collec), new); @@ -1321,6 +1444,8 @@ bool update_activity_in_collections(GList *list, int fd, sqlite3 *db) GList *i; /* Boucle de parcours #2 */ GDbItem *item; /* Elément collecté à manipuler*/ + /* TODO : lock ? */ + status = recv_timestamp(×tamp, fd, 0); if (!status) return false; diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index ac3e60f..e9f93d2 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -102,11 +102,19 @@ bool g_db_collection_has_item(GDbCollection *, GDbItem *); /* Procède à l'ajout d'un nouvel élément dans la collection. */ bool _g_db_collection_add_item(GDbCollection *, GDbItem *, bool); +/* Procède au retrait d'un nouvel élément dans la collection. */ +bool _g_db_collection_remove_item(GDbCollection *, GDbItem *, bool); + +/* Détermine l'horodatage le plus jeune pour une désactivation. */ +timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *, bool); + /* Met à jour le statut d'activité d'un élément de collection. */ -bool _g_db_collection_update_item_activity(GDbCollection *, GDbItem *, bool); +bool _g_db_collection_update_item_activity(GDbCollection *, GDbItem *, timestamp_t, bool); #define g_db_collection_add_item(c, i) _g_db_collection_add_item(c, i, true) -#define g_db_collection_update_item_activity(c, i) _g_db_collection_update_item_activity(c, i, true) +#define g_db_collection_remove_item(c, i) _g_db_collection_remove_item(c, i, true) +#define g_db_collection_compute_inactivity_timestamp(c) _g_db_collection_compute_inactivity_timestamp(c, true) +#define g_db_collection_update_item_activity(c, i, t) _g_db_collection_update_item_activity(c, i, t, true) /* Active les éléments en amont d'un horodatage donné. */ GList *g_db_collection_set_last_active(GDbCollection *, timestamp_t, timestamp_t *, sqlite3 *); diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h index 1af1048..fb33c72 100644 --- a/src/analysis/db/item-int.h +++ b/src/analysis/db/item-int.h @@ -63,8 +63,6 @@ struct _GDbItem { GObject parent; /* A laisser en premier */ - bool server_side; /* Instance côté serveur */ - timestamp_t created; /* Date de création */ timestamp_t timestamp; /* Date dernière activité */ diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index 5463e85..3fc6f6f 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -191,8 +191,6 @@ void g_db_item_set_server_side(GDbItem *item) init_timestamp(&item->created); item->timestamp = item->created; - item->server_side = true; - } @@ -288,15 +286,11 @@ static bool g_db_item_recv_from_fd(GDbItem *item, int fd, int flags) { bool status; /* Bilan d'une réception */ - if (!item->server_side) - { - status = recv_timestamp(&item->created, fd, flags); - if (!status) return false; - - status = recv_timestamp(&item->timestamp, fd, flags); - if (!status) return false; + status = recv_timestamp(&item->created, fd, flags); + if (!status) return false; - } + status = recv_timestamp(&item->timestamp, fd, flags); + if (!status) return false; status = recv_rle_string(&item->author, fd, flags); if (!status) return false; @@ -354,15 +348,11 @@ static bool g_db_item_send_to_fd(const GDbItem *item, int fd, int flags) { bool status; /* Bilan d'une émission */ - if (item->server_side) - { - status = send_timestamp(&item->created, fd, MSG_MORE | flags); - if (!status) return false; - - status = send_timestamp(&item->timestamp, fd, MSG_MORE | flags); - if (!status) return false; + status = send_timestamp(&item->created, fd, MSG_MORE | flags); + if (!status) return false; - } + status = send_timestamp(&item->timestamp, fd, MSG_MORE | flags); + if (!status) return false; status = send_rle_string(&item->author, fd, MSG_MORE | flags); if (!status) return false; -- cgit v0.11.2-87-g4458