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