summaryrefslogtreecommitdiff
path: root/src/analysis/db
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-09-25 22:20:25 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-09-25 22:20:25 (GMT)
commit6ed1e4110eb19b78f76154aa095a74414531f04c (patch)
treed1c3562cb6e180baff3c388a3bb3574b0a02213b /src/analysis/db
parent3dc843b3f7991dcd738a30821ff56c7fe13f1094 (diff)
Prepared history for database items.
Diffstat (limited to 'src/analysis/db')
-rw-r--r--src/analysis/db/cdb.c12
-rw-r--r--src/analysis/db/client.c3
-rw-r--r--src/analysis/db/collection-int.h10
-rw-r--r--src/analysis/db/collection.c625
-rw-r--r--src/analysis/db/collection.h31
-rw-r--r--src/analysis/db/item-int.h4
-rw-r--r--src/analysis/db/item.c171
-rw-r--r--src/analysis/db/item.h22
-rw-r--r--src/analysis/db/items/bookmark.c39
-rw-r--r--src/analysis/db/items/comment.c78
-rw-r--r--src/analysis/db/items/move.c40
-rw-r--r--src/analysis/db/items/switcher.c53
-rw-r--r--src/analysis/db/misc/timestamp.h4
-rw-r--r--src/analysis/db/protocol.h9
14 files changed, 504 insertions, 597 deletions
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(&timestamp, pbuf);
+ status = unpack_timestamp(&timestamp, 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