From 6ed1e4110eb19b78f76154aa095a74414531f04c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 26 Sep 2019 00:20:25 +0200 Subject: Prepared history for database items. --- plugins/pychrysalide/analysis/binary.c | 50 +++ plugins/pychrysalide/analysis/db/client.c | 60 ++- plugins/pychrysalide/analysis/db/collection.c | 26 +- plugins/pychrysalide/analysis/db/constants.c | 1 + plugins/pychrysalide/analysis/db/item.c | 40 ++ src/analysis/binary.c | 59 +-- src/analysis/binary.h | 6 +- src/analysis/db/cdb.c | 12 +- src/analysis/db/client.c | 3 +- src/analysis/db/collection-int.h | 10 +- src/analysis/db/collection.c | 625 +++++++++++++------------- src/analysis/db/collection.h | 31 +- src/analysis/db/item-int.h | 4 +- src/analysis/db/item.c | 171 ++++--- src/analysis/db/item.h | 22 +- src/analysis/db/items/bookmark.c | 39 +- src/analysis/db/items/comment.c | 78 +--- src/analysis/db/items/move.c | 40 +- src/analysis/db/items/switcher.c | 53 +-- src/analysis/db/misc/timestamp.h | 4 +- src/analysis/db/protocol.h | 9 +- src/core/collections.c | 6 +- src/gui/menus/edition.c | 5 +- src/gui/panels/bookmarks.c | 10 +- src/gui/panels/history.c | 14 +- 25 files changed, 701 insertions(+), 677 deletions(-) diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c index 01160a5..e97bea6 100644 --- a/plugins/pychrysalide/analysis/binary.c +++ b/plugins/pychrysalide/analysis/binary.c @@ -55,6 +55,9 @@ static PyObject *py_loaded_binary_find_collection(PyObject *, PyObject *); /* Demande l'intégration d'une modification dans une collection. */ static PyObject *py_loaded_binary_add_to_collection(PyObject *, PyObject *); +/* Active les éléments en amont d'un horodatage donné. */ +static PyObject *py_loaded_binary_set_last_active(PyObject *, PyObject *); + /* Fournit le nom associé à l'élément binaire. */ static PyObject *py_loaded_binary_get_name(PyObject *, void *); @@ -268,6 +271,52 @@ static PyObject *py_loaded_binary_add_to_collection(PyObject *self, PyObject *ar /****************************************************************************** * * +* Paramètres : self = binaire chargé à manipuler. * +* args = arguments d'appel à consulter. * +* * +* Description : Active les éléments en amont d'un horodatage donné. * +* * +* Retour : True si la commande a bien été envoyée, False sinon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_loaded_binary_set_last_active(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned long long timestamp; /* Horodatage de limite */ + int ret; /* Bilan de lecture des args. */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ + bool status; /* Bilan de l'opération */ + +#define LOADED_BINARY_SET_LAST_ACTIVE_METHOD PYTHON_METHOD_DEF \ +( \ + set_last_active, "$self, timestamp, /", \ + METH_VARARGS, py_loaded_binary, \ + "Define the timestamp of the last active item in the collection" \ + " and returns the status of the request transmission." \ +) + + ret = PyArg_ParseTuple(args, "K", ×tamp); + if (!ret) return NULL; + + binary = G_LOADED_BINARY(pygobject_get(self)); + + status = g_loaded_binary_set_last_active(binary, timestamp); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * @@ -468,6 +517,7 @@ PyTypeObject *get_python_loaded_binary_type(void) LOADED_BINARY_GET_CLIENT_METHOD, LOADED_BINARY_FIND_COLLECTION_METHOD, LOADED_BINARY_ADD_TO_COLLECTION_METHOD, + LOADED_BINARY_SET_LAST_ACTIVE_METHOD, { NULL } }; diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c index 13966f5..e5b67da 100644 --- a/plugins/pychrysalide/analysis/db/client.c +++ b/plugins/pychrysalide/analysis/db/client.c @@ -51,6 +51,9 @@ static PyObject *py_hub_client_stop(PyObject *, PyObject *); /* Effectue une demande de sauvegarde de l'état courant. */ static PyObject *py_hub_client_save(PyObject *, PyObject *); +/* Active les éléments en amont d'un horodatage donné. */ +static PyObject *py_hub_client_set_last_active(PyObject *, PyObject *); + /****************************************************************************** @@ -146,7 +149,7 @@ static PyObject *py_hub_client_new(PyTypeObject *type, PyObject *args, PyObject /****************************************************************************** * * -* Paramètres : self = serveur à manipuler. * +* Paramètres : self = client à manipuler. * * args = paramètres à transmettre à l'appel natif. * * * * Description : Démarre la connexion à la base de données. * @@ -201,7 +204,7 @@ static PyObject *py_hub_client_start(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : self = serveur à manipuler. * +* Paramètres : self = client à manipuler. * * args = arguments d'appel non utilisés ici. * * * * Description : Arrête la connexion à la base de données. * @@ -238,7 +241,7 @@ static PyObject *py_hub_client_stop(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : self = serveur à manipuler. * +* Paramètres : self = client à manipuler. * * args = arguments d'appel non utilisés ici. * * * * Description : Effectue une demande de sauvegarde de l'état courant. * @@ -279,6 +282,56 @@ static PyObject *py_hub_client_save(PyObject *self, PyObject *args) /****************************************************************************** * * +* Paramètres : self = client à manipuler. * +* args = arguments d'appel à consulter. * +* * +* Description : Active les éléments en amont d'un horodatage donné. * +* * +* Retour : True si la commande a bien été envoyée, False sinon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_hub_client_set_last_active(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned long long timestamp; /* Horodatage de limite */ + int ret; /* Bilan de lecture des args. */ + GHubClient *client; /* Version native du serveur */ + bool status; /* Bilan de l'opération */ + +#define HUB_CLIENT_SET_LAST_ACTIVE_METHOD PYTHON_METHOD_DEF \ +( \ + set_last_active, "$self, timestamp, /", \ + METH_VARARGS, py_hub_client, \ + "Define the timestamp of the last active item in the collection" \ + " and returns the status of the request transmission." \ + "\n" \ + "This method should not be used directly. Prefer calling" \ + " pychrysalide.analysis.LoadedBinary.set_last_active() instead," \ + " as some items may be volatile and thus not handled by clients." \ +) + + ret = PyArg_ParseTuple(args, "K", ×tamp); + if (!ret) return NULL; + + client = G_HUB_CLIENT(pygobject_get(self)); + + status = g_hub_client_set_last_active(client, timestamp); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -295,6 +348,7 @@ PyTypeObject *get_python_hub_client_type(void) HUB_CLIENT_START_METHOD, HUB_CLIENT_STOP_METHOD, HUB_CLIENT_SAVE_METHOD, + HUB_CLIENT_SET_LAST_ACTIVE_METHOD, { NULL } }; diff --git a/plugins/pychrysalide/analysis/db/collection.c b/plugins/pychrysalide/analysis/db/collection.c index e62c17e..53cdccc 100644 --- a/plugins/pychrysalide/analysis/db/collection.c +++ b/plugins/pychrysalide/analysis/db/collection.c @@ -59,10 +59,9 @@ static PyObject *py_db_collection_get_items(PyObject *self, void *closure) { PyObject *result; /* Trouvailles à retourner */ GDbCollection *collec; /* Version native */ - size_t counter; /* Décompte des éléments */ - GList *items; /* Eléments déjà en place */ - GList *iter; /* Boucle de parcours */ - int ret; /* Bilan d'une extension */ + size_t count; /* Décompte des éléments */ + GDbItem **items; /* Eléments déjà en place */ + size_t i; /* Boucle de parcours */ #define DB_COLLECTION_ITEMS_ATTRIB PYTHON_GET_DEF_FULL \ ( \ @@ -74,22 +73,21 @@ static PyObject *py_db_collection_get_items(PyObject *self, void *closure) collec = G_DB_COLLECTION(pygobject_get(self)); - counter = 0; - result = PyTuple_New(counter); - g_db_collection_rlock(collec); - items = g_db_collection_get_items(G_DB_COLLECTION(collec)); - - for (iter = g_list_first(items); iter != NULL; iter = g_list_next(iter)) - { - ret = _PyTuple_Resize(&result, ++counter); - if (ret == -1) break; + items = g_db_collection_get_items(G_DB_COLLECTION(collec), &count); - PyTuple_SetItem(result, counter - 1, pygobject_new(G_OBJECT(iter->data))); + result = PyTuple_New(count); + for (i = 0; i < count; i++) + { + PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(items[i]))); + g_object_unref(G_OBJECT(items[i])); } + if (items != NULL) + free(items); + g_db_collection_runlock(collec); return result; diff --git a/plugins/pychrysalide/analysis/db/constants.c b/plugins/pychrysalide/analysis/db/constants.c index 46d0876..07c7a06 100644 --- a/plugins/pychrysalide/analysis/db/constants.c +++ b/plugins/pychrysalide/analysis/db/constants.c @@ -96,6 +96,7 @@ bool define_db_item_constants(PyTypeObject *type) if (result) result = add_const_to_group(values, "UPDATED", DIF_UPDATED); if (result) result = add_const_to_group(values, "VOLATILE", DIF_VOLATILE); if (result) result = add_const_to_group(values, "BROKEN", DIF_BROKEN); + if (result) result = add_const_to_group(values, "DISABLED", DIF_DISABLED); if (!result) { diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c index 0923268..7ef30af 100644 --- a/plugins/pychrysalide/analysis/db/item.c +++ b/plugins/pychrysalide/analysis/db/item.c @@ -48,6 +48,9 @@ static PyObject *py_db_item_remove_flag(PyObject *, PyObject *); /* Décrit l'élément de collection en place. */ static PyObject *py_db_item_get_label(PyObject *, void *); +/* Fournit l'horodatage associé à l'élément de collection. */ +static PyObject *py_db_item_get_timestamp(PyObject *, void *); + /* Indique les propriétés particulières appliquées à l'élément. */ static PyObject *py_db_item_get_flags(PyObject *, void *); @@ -178,6 +181,42 @@ static PyObject *py_db_item_get_label(PyObject *self, void *closure) * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * +* Description : Fournit l'horodatage associé à l'élément de collection. * +* * +* Retour : Date de création de l'élément. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_item_get_timestamp(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDbItem *item; /* Elément à consulter */ + timestamp_t timestamp; /* Horodatage de l'élément */ + +#define DB_ITEM_TIMESTAMP_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + timestamp, py_db_item, \ + "Timestamp of the item creation." \ +) + + item = G_DB_ITEM(pygobject_get(self)); + + timestamp = g_db_item_get_timestamp(item); + + result = PyLong_FromUnsignedLongLong(timestamp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * * Description : Indique les propriétés particulières appliquées à l'élément. * * * * Retour : Propriétés actives de l'élément. * @@ -232,6 +271,7 @@ PyTypeObject *get_python_db_item_type(void) static PyGetSetDef py_db_item_getseters[] = { DB_ITEM_LABEL_ATTRIB, + DB_ITEM_TIMESTAMP_ATTRIB, DB_ITEM_FLAGS_ATTRIB, { NULL } }; diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 822510c..05e42c7 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1127,87 +1127,56 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bo } + g_object_unref(G_OBJECT(item)); + } g_object_unref(G_OBJECT(collec)); - g_object_unref(G_OBJECT(item)); return result; } + + /****************************************************************************** * * -* 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é. * +* Paramètres : binary = élément binaire à consulter. * +* timestamp = date du dernier élément à garder comme actif. * * * -* Description : Demande la suppression de modification dans une collection. * +* Description : Active les éléments en amont d'un horodatage donné. XXXXXXXXXXXXXXXXX * * * -* Retour : Bilan partiel de l'opération demandée. * +* Retour : true si la commande a bien été envoyée, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item, bool lock) +bool g_loaded_binary_set_last_active(GLoadedBinary *binary, timestamp_t timestamp) { - bool result; /* Bilan à faire remonter */ - GDbCollection *collec; /* Collection visée au final */ - DBStorage storage; /* Forme d'enregistrement */ - GHubClient *client; /* Liaison à utiliser */ - packed_buffer out_pbuf; /* Tampon d'émission */ - SSL *tls_fd; /* Canal de communication SSL */ + bool result; /* Bilan à retourner */ - 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_get_flags(item) & DIF_VOLATILE) - result = _g_db_collection_remove_item(collec, item, lock, true); + result = false; - /* Sinon on envoie par le réseau ! */ - else - { - storage = g_loaded_binary_get_storage(binary, feature); - if (storage == DBS_ALL_REMOTE) - client = binary->remote; - else - client = NULL; - if (client == NULL) - client = binary->local; - init_packed_buffer(&out_pbuf); + return result; + +} - tls_fd = g_hub_client_get_ssl_fd(client); - if (tls_fd == NULL) - result = false; - else - { - result = g_db_collection_pack(collec, &out_pbuf, DBA_REM_ITEM, item); - if (result) - result = ssl_send_packed_buffer(&out_pbuf, tls_fd); - g_hub_client_put_ssl_fd(client, tls_fd); - } - exit_packed_buffer(&out_pbuf); - } - g_object_unref(G_OBJECT(collec)); - return result; -} diff --git a/src/analysis/binary.h b/src/analysis/binary.h index dd3dfc6..b4c8652 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -131,12 +131,10 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *, GDbItem *, bool); #define g_loaded_binary_add_to_collection(b, i) \ _g_loaded_binary_add_to_collection(b, 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) +/* Active les éléments en amont d'un horodatage donné. */ +bool g_loaded_binary_set_last_active(GLoadedBinary *, timestamp_t); diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index a787a19..ca39a58 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -967,8 +967,16 @@ static void *g_cdb_archive_process(GCdbArchive *archive) case DBC_SET_LAST_ACTIVE: - status = update_activity_in_collections(archive->collections, &in_pbuf, archive->db); - if (!status) goto gcap_bad_exchange; + init_packed_buffer(&out_pbuf); + + status = update_activity_in_collections(archive->collections, \ + &in_pbuf, &out_pbuf, archive->db); + if (!status) goto gcap_bad_reply; + + status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd); + if (!status) goto gcap_bad_reply; + + exit_packed_buffer(&out_pbuf); break; diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 744fa57..beb30c1 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -789,7 +789,7 @@ static void *g_hub_client_update(GHubClient *client) status = extract_packed_buffer(&in_pbuf, &tmp8, sizeof(uint8_t), true); if (!status) goto gdcu_bad_exchange; - client->can_get_updates = (tmp8 == 0x0); + client->can_get_updates = (tmp8 == 0x1); break; } @@ -797,6 +797,7 @@ static void *g_hub_client_update(GHubClient *client) if (has_more_data_in_packed_buffer(&in_pbuf)) goto next_command; + client->can_get_updates = true; continue; gdcu_bad_exchange: diff --git a/src/analysis/db/collection-int.h b/src/analysis/db/collection-int.h index b3b83bb..c9d37bf 100644 --- a/src/analysis/db/collection-int.h +++ b/src/analysis/db/collection-int.h @@ -35,9 +35,6 @@ /* Crée la table associée à une collection d'éléments. */ typedef bool (* collec_create_db_table_fc) (const GDbCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -typedef bool (* collec_setup_load_fc) (GDbCollection *, bound_value **, size_t *); - /* Charge les valeurs utiles pour une localisation. */ typedef bool (* collec_load_item) (GDbCollection *, const bound_value *, size_t); @@ -58,8 +55,8 @@ struct _GDbCollection /* Référence circulaire */ GLoadedBinary *binary; /* Binaire rattaché éventuel */ - GList *items; /* Eléments rassemblés */ - GList *sorted; /* Eléments triés */ + GDbItem **items; /* Eléments rassemblés */ + size_t count; /* Quantité de ces éléments */ GHashTable *last_items; /* Statuts courants d'éléments */ GRWLock params_access; /* Verrou de protection */ @@ -71,7 +68,6 @@ struct _GDbCollectionClass GObjectClass parent; /* A laisser en premier */ collec_create_db_table_fc create_table; /* Création de la table en SQL */ - collec_setup_load_fc setup_load; /* Prépare le chargement */ collec_load_item load_item; /* Charge un élément */ collec_has_key_fc has_key; /* Recherche de présence */ @@ -79,6 +75,8 @@ struct _GDbCollectionClass void (* content_extended) (GDbCollection *, GDbItem *); + void (* state_changed) (GDbCollection *, GDbItem *); + }; 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; } diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index 60e5c26..9539229 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -93,7 +93,7 @@ void g_db_collection_lock_unlock(GDbCollection *, bool, bool); #define g_db_collection_runlock(col) g_db_collection_lock_unlock(col, false, false); /* Renvoie la liste des éléments rassemblés. */ -GList *g_db_collection_get_items(const GDbCollection *); +GDbItem **g_db_collection_get_items(const GDbCollection *, size_t *); /* Détermine si un élément est déjà présent ou non. */ GDbItem *g_db_collection_has_key(GDbCollection *, ...); @@ -104,25 +104,24 @@ 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, bool); +/* Procède au retrait des éléments désactivés de la collection. */ +bool g_db_collection_drop_disabled_items(GDbCollection *, packed_buffer *); -/* Détermine l'horodatage le plus jeune pour une désactivation. */ -timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *, bool); +/* Procède au retrait d'un élément dans la collection. */ +bool g_db_collection_remove_item(GDbCollection *, const GDbItem *); -/* Met à jour le statut d'activité d'un élément de collection. */ -bool _g_db_collection_update_item_activity(GDbCollection *, GDbItem *, timestamp_t *, bool); +/* Désactive les éléments en aval d'un horodatage donné. */ +bool g_db_collection_disable_at(GDbCollection *, timestamp_t, sqlite3 *, packed_buffer *); -#define g_db_collection_add_item(c, i) _g_db_collection_add_item(c, i, true) -#define g_db_collection_remove_item(c, i) _g_db_collection_remove_item(c, i, true, 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) +/* Prend acte d'un changement d'état d'un élément de collection. */ +bool g_db_collection_update_item_state(GDbCollection *, const GDbItem *); -/* Active les éléments en amont d'un horodatage donné. */ -GList *g_db_collection_set_last_active(GDbCollection *, timestamp_t, timestamp_t *, sqlite3 *); -/* Désactive les éléments en aval d'un horodatage donné. */ -bool g_db_collection_set_inactive(GDbCollection *, GDbItem *, timestamp_t *); + + + +#define g_db_collection_add_item(c, i) _g_db_collection_add_item(c, i, true) +//#define g_db_collection_remove_item(c, i) _g_db_collection_remove_item(c, i, true, true) @@ -159,7 +158,7 @@ void lock_unlock_collections(GList *, bool, bool); bool pack_all_collection_updates(GList *, packed_buffer *); /* Met à jour les statuts d'activité des éléments. */ -bool update_activity_in_collections(GList *, packed_buffer *, sqlite3 *); +bool update_activity_in_collections(GList *, packed_buffer *, packed_buffer *, sqlite3 *); diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h index 8bba8a3..8c13cd9 100644 --- a/src/analysis/db/item-int.h +++ b/src/analysis/db/item-int.h @@ -111,8 +111,8 @@ struct _GDbItemClass /* Définition du tronc commun pour les créations SQLite */ #define SQLITE_DB_ITEM_CREATE \ SQLITE_TIMESTAMP_CREATE("created") ", " \ - SQLITE_TIMESTAMP_CREATE("timestamp") ", " \ - SQLITE_RLESTR_CREATE("author") + SQLITE_RLESTR_CREATE("author") ", " \ + "flags INTEGER" diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index efa2cdf..f9c4201 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -462,7 +462,7 @@ bool g_db_item_apply(GDbItem *item, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ - assert(g_db_item_is_active(item)); + assert(!g_db_item_has_flag(item, DIF_DISABLED)); result = G_DB_ITEM_GET_CLASS(item)->apply(item, binary); @@ -491,7 +491,7 @@ bool g_db_item_cancel(GDbItem *item, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ - assert(!g_db_item_is_active(item)); + assert(g_db_item_has_flag(item, DIF_DISABLED)); result = G_DB_ITEM_GET_CLASS(item)->cancel(item, binary); @@ -533,7 +533,7 @@ char *g_db_item_get_label(GDbItem *item) * * * Description : Fournit l'horodatage associé à l'élément de collection. * * * -* Retour : Date d'activité de l'élément. * +* Retour : Date de création de l'élément. * * * * Remarques : - * * * @@ -541,56 +541,9 @@ char *g_db_item_get_label(GDbItem *item) timestamp_t g_db_item_get_timestamp(const GDbItem *item) { - return item->timestamp; + timestamp_t result; /* Horodatage à retourner */ -} - - -/****************************************************************************** -* * -* Paramètres : item = élément de collection à mettre à jour. * -* binary = binaire chargé en mémoire à modifier. * -* first = horodatage du premier élément désactivé ou NULL. * -* * -* Description : Active ou désactive un élément de collection en place. * -* * -* Retour : Bilan de la mise à jour de l'élément. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_db_item_set_activity(GDbItem *item, GLoadedBinary *binary, timestamp_t *first) -{ - bool result; /* Bilan à faire remonter */ - bool active; /* Etat avant changement */ - - active = g_db_item_is_active(item); - - /* Archivage de l'état */ - - if (first == NULL) - { - assert(!active); - item->timestamp = item->created; - } - else - { - assert(active); - item->timestamp = --(*first); - } - - /* Application de l'état */ - - if (binary != NULL) - { - if (active) - result = g_db_item_cancel(item, binary); - else - result = g_db_item_apply(item, binary); - } - else - result = true; + result = item->created; return result; @@ -599,19 +552,20 @@ bool g_db_item_set_activity(GDbItem *item, GLoadedBinary *binary, timestamp_t *f /****************************************************************************** * * -* Paramètres : item = élément de collection à consulter. * +* Paramètres : item = base d'éléments à mettre à jour. * +* flag = type de propriété à traiter. * * * -* Description : Indique si l'élément est activé ou désactivé. * +* Description : Applique un ensemble de propriétés à un élément. * * * -* Retour : Etat de l'activité de l'élément. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_db_item_is_active(const GDbItem *item) +void g_db_item_set_flags(GDbItem *item, DbItemFlags flag) { - return (cmp_timestamp(&item->created, &item->timestamp) == 0); + g_atomic_int_set(&item->atomic_flags, flag); } @@ -684,6 +638,50 @@ DbItemFlags g_db_item_get_flags(const GDbItem *item) } +/****************************************************************************** +* * +* Paramètres : item = élément de collection à mettre à jour. * +* binary = binaire chargé en mémoire à modifier. * +* * +* Description : Active ou désactive un élément de collection en place. * +* * +* Retour : Bilan de la mise à jour de l'élément. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_item_switch_state(GDbItem *item, GLoadedBinary *binary) +{ + bool result; /* Bilan à faire remonter */ + bool enabled; /* Etat avant changement */ + + enabled = !g_db_item_has_flag(item, DIF_DISABLED); + + /* Archivage de l'état */ + + if (enabled) + g_db_item_add_flag(item, DIF_DISABLED); + else + g_db_item_remove_flag(item, DIF_DISABLED); + + /* Application de l'état */ + + if (binary != NULL) + { + if (enabled) + result = g_db_item_cancel(item, binary); + else + result = g_db_item_apply(item, binary); + } + else + result = true; + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* MANIPULATIONS AVEC UNE BASE DE DONNEES */ @@ -692,6 +690,30 @@ DbItemFlags g_db_item_get_flags(const GDbItem *item) /****************************************************************************** * * +* Paramètres : item = base d'éléments à consulter. * +* values = tableau d'éléments à compléter. [OUT] * +* count = nombre de descriptions renseignées. [OUT] * +* * +* Description : Décrit les colonnes utiles à un chargement de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_item_setup_load(const GDbItem *item, bound_value **values, size_t *count) +{ + *values = NULL; + *count = 0; + + return G_DB_ITEM_GET_CLASS(item)->store(NULL, values, count); + +} + + +/****************************************************************************** +* * * Paramètres : item = base d'éléments à charger depuis les réponses. * * values = tableau d'éléments à consulter. * * count = nombre de descriptions renseignées. * @@ -707,14 +729,23 @@ DbItemFlags g_db_item_get_flags(const GDbItem *item) static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t count) { bool result; /* Bilan global à retourner */ + const bound_value *value; /* Valeur à intégrer */ result = load_timestamp(&item->created, "created", values, count); if (result) - result = load_timestamp(&item->timestamp, "timestamp", values, count); + result = load_rle_string(&item->author, "author", values, count); if (result) - result = load_rle_string(&item->author, "author", values, count); + { + value = find_bound_value(values, count, "flags"); + + result = (value != NULL && value->type == SQLITE_INTEGER); + + if (result) + item->flags = value->integer; + + } return result; @@ -763,6 +794,7 @@ bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count) static bool _g_db_item_store(const GDbItem *item, bound_value **values, size_t *count) { bool result; /* Bilan à retourner */ + bound_value *value; /* Valeur à éditer / définir */ if (item == NULL) result = store_timestamp(NULL, "created", values, count); @@ -772,17 +804,26 @@ static bool _g_db_item_store(const GDbItem *item, bound_value **values, size_t * if (result) { if (item == NULL) - result = store_timestamp(NULL, "timestamp", values, count); + result = store_rle_string(NULL, "author", values, count); else - result = store_timestamp(&item->timestamp, "timestamp", values, count); + result = store_rle_string(&item->author, "author", values, count); } if (result) { - if (item == NULL) - result = store_rle_string(NULL, "author", values, count); - else - result = store_rle_string(&item->author, "author", values, count); + *values = realloc(*values, ++(*count) * sizeof(bound_value)); + + value = &(*values)[*count - 1]; + + value->cname = "flags"; + value->built_name = false; + value->type = SQLITE_INTEGER; + + value->has_value = (item != NULL); + + if (value->has_value) + value->integer = g_db_item_get_flags(item); + } return result; diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h index 395a56f..b735fb8 100644 --- a/src/analysis/db/item.h +++ b/src/analysis/db/item.h @@ -48,6 +48,7 @@ typedef enum _DbItemFlags DIF_UPDATED = (1 << 1), /* Mise à jour de l'élément */ DIF_VOLATILE = (1 << 2), /* Abscence de sauvegarde */ DIF_BROKEN = (1 << 3), /* Application impossible */ + DIF_DISABLED = (1 << 4), /* Désactivation forcée */ } DbItemFlags; @@ -109,11 +110,8 @@ char *g_db_item_get_label(GDbItem *); /* Fournit l'horodatage associé à l'élément de collection. */ timestamp_t g_db_item_get_timestamp(const GDbItem *); -/* Active ou désactive un élément de collection en place. */ -bool g_db_item_set_activity(GDbItem *, GLoadedBinary *, timestamp_t *); - -/* Indique si l'élément est activé ou désactivé. */ -bool g_db_item_is_active(const GDbItem *); +/* Applique un ensemble de propriétés à un élément. */ +void g_db_item_set_flags(GDbItem *, DbItemFlags); /* Ajoute une propriété à un élément de base de données. */ void g_db_item_add_flag(GDbItem *, DbItemFlags); @@ -124,11 +122,25 @@ void g_db_item_remove_flag(GDbItem *, DbItemFlags); /* Indique les propriétés particulières appliquées à l'élément. */ DbItemFlags g_db_item_get_flags(const GDbItem *); +#define g_db_item_has_flag(i, f) \ + (g_db_item_get_flags(i) & f) + + +////////// +#define g_db_item_is_enabled(i) ((g_db_item_get_flags(i) & DIF_DISABLED) == 0) + + +/* Active ou désactive un élément de collection en place. */ +bool g_db_item_switch_state(GDbItem *, GLoadedBinary *); + /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +/* Décrit les colonnes utiles à un chargement de données. */ +bool g_db_item_setup_load(const GDbItem *, bound_value **, size_t *); + /* Charge les valeurs utiles pour un élément de collection. */ bool g_db_item_load(GDbItem *, const bound_value *, size_t); diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 3d66f6b..c1b0fec 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -141,9 +141,6 @@ static void g_bookmark_collection_finalize(GBookmarkCollection *); /* Crée la table des signets dans une base de données. */ static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_bookmark_collection_setup_load(GBookmarkCollection *, bound_value **, size_t *); - /* Détermine si un élément est déjà présent ou non. */ static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *, va_list); @@ -796,7 +793,6 @@ static void g_bookmark_collection_class_init(GBookmarkCollectionClass *klass) collec = G_DB_COLLECTION_CLASS(klass); collec->create_table = (collec_create_db_table_fc)g_bookmark_collection_create_db_table; - collec->setup_load = (collec_setup_load_fc)g_bookmark_collection_setup_load; collec->has_key = (collec_has_key_fc)g_bookmark_collection_has_key; } @@ -934,39 +930,6 @@ static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *col /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à consulter. * -* values = tableau d'éléments à compléter. [OUT] * -* count = nombre de descriptions renseignées. [OUT] * -* * -* Description : Décrit les colonnes utiles à un chargement de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_bookmark_collection_setup_load(GBookmarkCollection *collec, bound_value **values, size_t *count) -{ - bool status; /* Bilan d'une préparation */ - - status = G_DB_COLLECTION_CLASS(g_bookmark_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ - values, count); - if (!status) return false; - - if (!store_vmpa(NULL, NULL, values, count)) - return false; - - if (!store_rle_string(NULL, "comment", values, count)) - return false; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : collec = ensemble d'éléments à consulter. * * ap = clef identifiant de manière unique un élément. * * * * Description : Détermine si un élément est déjà présent ou non. * @@ -989,6 +952,7 @@ static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *collec, va_li ref = va_arg(ap, vmpa2t *); +#if 0 items = g_db_collection_get_items(G_DB_COLLECTION(collec)); for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -1005,6 +969,7 @@ static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *collec, va_li result = G_DB_ITEM(bm); } +#endif return result; diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index a987464..a231749 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -183,9 +183,6 @@ static void g_comment_collection_finalize(GCommentCollection *); /* Crée la table des commentaires dans une base de données. */ static bool g_comment_collection_create_db_table(const GCommentCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_comment_collection_setup_load(GCommentCollection *, bound_value **, size_t *); - /* Détermine si un élément est déjà présent ou non. */ static GDbItem *g_comment_collection_has_key(GCommentCollection *, va_list); @@ -995,7 +992,7 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si if (result) { - value = find_bound_value(values, count, "flags"); + value = find_bound_value(values, count, "lflags"); result = (value != NULL && value->type == SQLITE_INTEGER); if (result) @@ -1072,16 +1069,20 @@ static bool g_db_comment_store(GDbComment *comment, bound_value **values, size_t value = &(*values)[*count - 1]; - value->cname = "flags"; + value->cname = "lflags"; value->built_name = false; value->type = SQLITE_INTEGER; - value->integer = comment->flags; - value->delete = NULL; value->has_value = (comment != NULL); if (value->has_value) { + value->integer = comment->flags; + value->delete = NULL; + } + + if (value->has_value) + { init_dynamic_rle_string(&text, g_db_comment_get_text(comment)); status = store_rle_string(&text, "text", values, count); exit_rle_string(&text); @@ -1514,7 +1515,6 @@ static void g_comment_collection_class_init(GCommentCollectionClass *klass) collec = G_DB_COLLECTION_CLASS(klass); collec->create_table = (collec_create_db_table_fc)g_comment_collection_create_db_table; - collec->setup_load = (collec_setup_load_fc)g_comment_collection_setup_load; collec->has_key = (collec_has_key_fc)g_comment_collection_has_key; } @@ -1626,7 +1626,7 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle sql = "CREATE TABLE Comments (" \ SQLITE_DB_ITEM_CREATE ", " \ "%s, " \ - "flags INTEGER, " \ + "lflags INTEGER, " \ SQLITE_RLESTR_CREATE("text") ", " \ "inlined INTEGER, " \ "repeatable INTEGER" \ @@ -1655,64 +1655,6 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à consulter. * -* values = tableau d'éléments à compléter. [OUT] * -* count = nombre de descriptions renseignées. [OUT] * -* * -* Description : Décrit les colonnes utiles à un chargement de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_value **values, size_t *count) -{ - bool status; /* Bilan d'une préparation */ - bound_value *value; /* Valeur à éditer / définir */ - - status = G_DB_COLLECTION_CLASS(g_comment_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ - values, count); - if (!status) return false; - - if (!store_vmpa(NULL, NULL, values, count)) - return false; - - *count += 1; - *values = realloc(*values, *count * sizeof(bound_value)); - - value = &(*values)[*count - 1]; - - value->cname = "flags"; - value->built_name = false; - value->type = SQLITE_INTEGER; - - if (!store_rle_string(NULL, "text", values, count)) - return false; - - *count += 2; - *values = realloc(*values, *count * sizeof(bound_value)); - - value = &(*values)[*count - 2]; - - value->cname = "inlined"; - value->built_name = false; - value->type = SQLITE_BOOLEAN; - - value = &(*values)[*count - 1]; - - value->cname = "repeatable"; - value->built_name = false; - value->type = SQLITE_BOOLEAN; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : collec = ensemble d'éléments à consulter. * * ap = clef identifiant de manière unique un élément. * * * * Description : Détermine si un élément est déjà présent ou non. * @@ -1735,6 +1677,7 @@ static GDbItem *g_comment_collection_has_key(GCommentCollection *collec, va_list ref = va_arg(ap, vmpa2t *); +#if 0 items = g_db_collection_get_items(G_DB_COLLECTION(collec)); for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -1751,6 +1694,7 @@ static GDbItem *g_comment_collection_has_key(GCommentCollection *collec, va_list result = G_DB_ITEM(bm); } +#endif return result; diff --git a/src/analysis/db/items/move.c b/src/analysis/db/items/move.c index a5d2773..afc3331 100644 --- a/src/analysis/db/items/move.c +++ b/src/analysis/db/items/move.c @@ -136,9 +136,6 @@ static void g_move_collection_finalize(GMoveCollection *); /* Crée la table des basculements dans une base de données. */ static bool g_move_collection_create_db_table(const GMoveCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_move_collection_setup_load(GMoveCollection *, bound_value **, size_t *); - /* Détermine si un élément est déjà présent ou non. */ static GDbItem *g_move_collection_has_key(GMoveCollection *, va_list); @@ -638,7 +635,6 @@ static void g_move_collection_class_init(GMoveCollectionClass *klass) collec = G_DB_COLLECTION_CLASS(klass); collec->create_table = (collec_create_db_table_fc)g_move_collection_create_db_table; - collec->setup_load = (collec_setup_load_fc)g_move_collection_setup_load; collec->has_key = (collec_has_key_fc)g_move_collection_has_key; } @@ -779,40 +775,6 @@ static bool g_move_collection_create_db_table(const GMoveCollection *collec, sql /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à consulter. * -* values = tableau d'éléments à compléter. [OUT] * -* count = nombre de descriptions renseignées. [OUT] * -* * -* Description : Décrit les colonnes utiles à un chargement de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_move_collection_setup_load(GMoveCollection *collec, bound_value **values, size_t *count) -{ - bool status; /* Bilan d'une préparation */ - - status = G_DB_COLLECTION_CLASS(g_move_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ - values, count); - if (!status) return false; - - if (!g_binary_cursor_store(NULL, "src", values, count)) - return false; - - if (!g_binary_cursor_store(NULL, "dest", values, count)) - return false; - - return true; - - -} - - -/****************************************************************************** -* * -* Paramètres : collec = ensemble d'éléments à consulter. * * ap = clef identifiant de manière unique un élément. * * * * Description : Détermine si un élément est déjà présent ou non. * @@ -835,6 +797,7 @@ static GDbItem *g_move_collection_has_key(GMoveCollection *collec, va_list ap) ref = va_arg(ap, const GLineCursor *); +#if 0 items = g_db_collection_get_items(G_DB_COLLECTION(collec)); for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -851,6 +814,7 @@ static GDbItem *g_move_collection_has_key(GMoveCollection *collec, va_list ap) result = G_DB_ITEM(bm); } +#endif return result; diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c index 043effd..94d4940 100644 --- a/src/analysis/db/items/switcher.c +++ b/src/analysis/db/items/switcher.c @@ -136,9 +136,6 @@ static void g_switcher_collection_finalize(GSwitcherCollection *); /* Crée la table des basculements dans une base de données. */ static bool g_switcher_collection_create_db_table(const GSwitcherCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_switcher_collection_setup_load(GSwitcherCollection *, bound_value **, size_t *); - /* Détermine si un élément est déjà présent ou non. */ static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *, va_list); @@ -790,7 +787,6 @@ static void g_switcher_collection_class_init(GSwitcherCollectionClass *klass) collec = G_DB_COLLECTION_CLASS(klass); collec->create_table = (collec_create_db_table_fc)g_switcher_collection_create_db_table; - collec->setup_load = (collec_setup_load_fc)g_switcher_collection_setup_load; collec->has_key = (collec_has_key_fc)g_switcher_collection_has_key; } @@ -929,53 +925,6 @@ static bool g_switcher_collection_create_db_table(const GSwitcherCollection *col /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à consulter. * -* values = tableau d'éléments à compléter. [OUT] * -* count = nombre de descriptions renseignées. [OUT] * -* * -* Description : Décrit les colonnes utiles à un chargement de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_value **values, size_t *count) -{ - bool status; /* Bilan d'une préparation */ - bound_value *value; /* Valeur à éditer / définir */ - - status = G_DB_COLLECTION_CLASS(g_switcher_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ - values, count); - if (!status) return false; - - if (!store_vmpa(NULL, NULL, values, count)) - return false; - - *count += 2; - *values = realloc(*values, *count * sizeof(bound_value)); - - value = &(*values)[*count - 2]; - - value->cname = "op_index"; - value->built_name = false; - value->type = SQLITE_INTEGER; - - value = &(*values)[*count - 1]; - - value->cname = "type"; - value->built_name = false; - value->type = SQLITE_INTEGER; - - return true; - - -} - - -/****************************************************************************** -* * -* Paramètres : collec = ensemble d'éléments à consulter. * * ap = clef identifiant de manière unique un élément. * * * * Description : Détermine si un élément est déjà présent ou non. * @@ -998,6 +947,7 @@ static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_li ref = va_arg(ap, vmpa2t *); +#if 0 items = g_db_collection_get_items(G_DB_COLLECTION(collec)); for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -1014,6 +964,7 @@ static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_li result = G_DB_ITEM(bm); } +#endif return result; diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h index eba0fa7..4ff714e 100644 --- a/src/analysis/db/misc/timestamp.h +++ b/src/analysis/db/misc/timestamp.h @@ -39,8 +39,8 @@ typedef uint64_t timestamp_t; /* Valeurs particulières */ -#define TIMESTAMP_ALL_ACTIVE 0 -#define TIMESTAMP_ALL_INACTIVE 1 +#define TIMESTAMP_ALL_ACTIVE 0 // REMME +#define TIMESTAMP_ALL_INACTIVE 1 // REMME /* Obtient un horodatage initialisé au moment même. */ diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 5c3eed6..d429530 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -95,7 +95,6 @@ typedef enum _DBAction { DBA_ADD_ITEM, /* Ajout d'un élément */ DBA_REM_ITEM, /* Suppression d'un élément */ - DBA_CHANGE_STATE, /* Changement d'activité */ DBA_COUNT @@ -186,16 +185,16 @@ typedef enum _DBCommand * avec une série de paquets de la forme : * * [ Traitement de collection : DBC_COLLECTION ] - * [ Action : DBC_SET_LAST_ACTIVE ] + * [ Action : DBA_CHANGE_STATE ] * [ <élément dont le statut a évolué> ] * * Les traitements se réalisent dans : - * - g_db_collection_set_last_active() pour la partie serveur. - * - g_db_client_set_last_active() pour la partie client. + * - g_db_collection_disable_at() pour la partie serveur. + * - g_db_collection_update_item_state() pour la partie client. * */ - DBC_SET_LAST_ACTIVE, /* Définition du dernier actif */ + DBC_SET_LAST_ACTIVE, /* Définition du dernier actif */ // REMME DBC_COUNT diff --git a/src/core/collections.c b/src/core/collections.c index a047a15..34b7bc1 100644 --- a/src/core/collections.c +++ b/src/core/collections.c @@ -114,11 +114,11 @@ bool load_hard_coded_collection_definitions(void) REGISTER_COLLECTION(G_TYPE_BM_COLLECTION, DBF_BOOKMARKS); - REGISTER_COLLECTION(G_TYPE_COMMENT_COLLECTION, DBF_COMMENTS); + //REGISTER_COLLECTION(G_TYPE_COMMENT_COLLECTION, DBF_COMMENTS); - REGISTER_COLLECTION(G_TYPE_MOVE_COLLECTION, DBF_MOVES); + //REGISTER_COLLECTION(G_TYPE_MOVE_COLLECTION, DBF_MOVES); - REGISTER_COLLECTION(G_TYPE_SWITCHER_COLLECTION, DBF_DISPLAY_SWITCHERS); + //REGISTER_COLLECTION(G_TYPE_SWITCHER_COLLECTION, DBF_DISPLAY_SWITCHERS); return true; diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c index f4b0712..01f24e8 100644 --- a/src/gui/menus/edition.c +++ b/src/gui/menus/edition.c @@ -722,7 +722,7 @@ static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar) exist = NULL;//g_db_collection_has_key(collec, &addr); if (exist != NULL) - g_loaded_binary_remove_from_collection(binary, DBF_BOOKMARKS, exist); + ;//g_loaded_binary_remove_from_collection(binary, DBF_BOOKMARKS, exist); else { @@ -746,7 +746,10 @@ static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar) "Do you want to replace it ?")); if (ret != GTK_RESPONSE_YES) + { + g_object_unref(G_OBJECT(bookmark)); goto mcb_ebt_add_finish; + } } diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c index f32f9f5..ebe1f62 100644 --- a/src/gui/panels/bookmarks.c +++ b/src/gui/panels/bookmarks.c @@ -473,12 +473,13 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary g_db_collection_rlock(collec); + /* items = g_db_collection_get_items(collec); for (b = g_list_first(items); b != NULL; b = g_list_next(b)) { bookmark = G_DB_BOOKMARK(b->data); - if (!g_db_item_is_active(G_DB_ITEM(bookmark))) continue; + if (!g_db_item_is_enabled(G_DB_ITEM(bookmark))) continue; addr = g_db_bookmark_get_address(bookmark); @@ -500,6 +501,7 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary -1); } + */ g_db_collection_runlock(collec); @@ -543,7 +545,7 @@ static void on_collection_content_changed(GDbCollection *collec, DBAction action store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store")); - if (action == DBA_ADD_ITEM || (action == DBA_CHANGE_STATE && g_db_item_is_active(G_DB_ITEM(bookmark)))) + if (action == DBA_ADD_ITEM || (action == DBA_CHANGE_STATE && g_db_item_is_enabled(G_DB_ITEM(bookmark)))) { proc = g_loaded_binary_get_processor(panel->binary); msize = g_arch_processor_get_memory_size(proc); @@ -568,7 +570,7 @@ static void on_collection_content_changed(GDbCollection *collec, DBAction action } - else /*if (action == DBA_CHANGE_STATE && g_db_item_is_active(G_DB_ITEM(bookmark)))*/ + else /*if (action == DBA_CHANGE_STATE && g_db_item_is_enabled(G_DB_ITEM(bookmark)))*/ { model = GTK_TREE_MODEL(store); @@ -1183,7 +1185,7 @@ static void mcb_bookmarks_panel_delete(GtkMenuItem *menuitem, GBookmarksPanel *p mark = get_selected_panel_bookmark(treeview, NULL); if (mark == NULL) return; - g_loaded_binary_remove_from_collection(panel->binary, DBF_BOOKMARKS, G_DB_ITEM(mark)); + //g_loaded_binary_remove_from_collection(panel->binary, DBF_BOOKMARKS, G_DB_ITEM(mark)); g_object_unref(G_OBJECT(mark)); diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c index 57e6a14..df3fde1 100644 --- a/src/gui/panels/history.c +++ b/src/gui/panels/history.c @@ -330,6 +330,7 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo { g_db_collection_rlock(collections[k]); + /* items = g_db_collection_get_items(collections[k]); for (i = g_list_first(items); i != NULL; i = g_list_next(i)) @@ -342,13 +343,14 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo gtk_list_store_set(store, &iter, HTC_ITEM, item, //HTC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, - HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", + HTC_FOREGROUND, g_db_item_is_enabled(item) ? NULL : "grey", HTC_LABEL, label, -1); free(label); } + */ //g_signal_connect_to_main(collections[k], "content-changed", G_CALLBACK(on_history_changed), panel, // g_cclosure_user_marshal_VOID__ENUM_OBJECT); @@ -440,7 +442,7 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem * gtk_list_store_set(store, &iter, HTC_ITEM, item, //HTC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, - HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", + HTC_FOREGROUND, g_db_item_is_enabled(item) ? NULL : "grey", HTC_LABEL, label, -1); @@ -459,7 +461,7 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem * if (find_changed_item(model, item, &iter)) gtk_list_store_set(store, &iter, - HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", + HTC_FOREGROUND, g_db_item_is_enabled(item) ? NULL : "grey", -1); break; @@ -480,7 +482,7 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem * gtk_tree_model_get(_model, _iter, HTC_ITEM, &item, -1); - active = g_db_item_is_active(item); + active = g_db_item_is_enabled(item); g_object_unref(G_OBJECT(item)); @@ -566,10 +568,10 @@ static void on_history_selection_change(GtkTreeSelection *selection, GHistoryPan gtk_tree_model_get(model, &iter, HTC_ITEM, &item, -1); button = GTK_WIDGET(gtk_builder_get_object(builder, "undo")); - gtk_widget_set_sensitive(button, g_db_item_is_active(item)); + gtk_widget_set_sensitive(button, g_db_item_is_enabled(item)); button = GTK_WIDGET(gtk_builder_get_object(builder, "redo")); - gtk_widget_set_sensitive(button, !g_db_item_is_active(item)); + gtk_widget_set_sensitive(button, !g_db_item_is_enabled(item)); g_object_unref(G_OBJECT(item)); -- cgit v0.11.2-87-g4458