diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2019-09-25 22:20:25 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2019-09-25 22:20:25 (GMT) | 
| commit | 6ed1e4110eb19b78f76154aa095a74414531f04c (patch) | |
| tree | d1c3562cb6e180baff3c388a3bb3574b0a02213b | |
| parent | 3dc843b3f7991dcd738a30821ff56c7fe13f1094 (diff) | |
Prepared history for database items.
25 files changed, 701 insertions, 677 deletions
| diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c index 01160a5..e97bea6 100644 --- a/plugins/pychrysalide/analysis/binary.c +++ b/plugins/pychrysalide/analysis/binary.c @@ -55,6 +55,9 @@ static PyObject *py_loaded_binary_find_collection(PyObject *, PyObject *);  /* Demande l'intégration d'une modification dans une collection. */  static PyObject *py_loaded_binary_add_to_collection(PyObject *, PyObject *); +/* Active les éléments en amont d'un horodatage donné. */ +static PyObject *py_loaded_binary_set_last_active(PyObject *, PyObject *); +  /* Fournit le nom associé à l'élément binaire. */  static PyObject *py_loaded_binary_get_name(PyObject *, void *); @@ -268,6 +271,52 @@ static PyObject *py_loaded_binary_add_to_collection(PyObject *self, PyObject *ar  /******************************************************************************  *                                                                             * +*  Paramètres  : self = binaire chargé à manipuler.                           * +*                args = arguments d'appel à consulter.                        * +*                                                                             * +*  Description : Active les éléments en amont d'un horodatage donné.          * +*                                                                             * +*  Retour      : True si la commande a bien été envoyée, False sinon.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_loaded_binary_set_last_active(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    unsigned long long timestamp;           /* Horodatage de limite        */ +    int ret;                                /* Bilan de lecture des args.  */ +    GLoadedBinary *binary;                  /* Binaire en cours d'analyse  */ +    bool status;                            /* Bilan de l'opération        */ + +#define LOADED_BINARY_SET_LAST_ACTIVE_METHOD PYTHON_METHOD_DEF          \ +(                                                                       \ +    set_last_active, "$self, timestamp, /",                             \ +    METH_VARARGS, py_loaded_binary,                                     \ +    "Define the timestamp of the last active item in the collection"    \ +    " and returns the status of the request transmission."              \ +) + +    ret = PyArg_ParseTuple(args, "K", ×tamp); +    if (!ret) return NULL; + +    binary = G_LOADED_BINARY(pygobject_get(self)); + +    status = g_loaded_binary_set_last_active(binary, timestamp); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : self    = objet Python concerné par l'appel.                 *  *                closure = non utilisé ici.                                   *  *                                                                             * @@ -468,6 +517,7 @@ PyTypeObject *get_python_loaded_binary_type(void)          LOADED_BINARY_GET_CLIENT_METHOD,          LOADED_BINARY_FIND_COLLECTION_METHOD,          LOADED_BINARY_ADD_TO_COLLECTION_METHOD, +        LOADED_BINARY_SET_LAST_ACTIVE_METHOD,          { NULL }      }; diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c index 13966f5..e5b67da 100644 --- a/plugins/pychrysalide/analysis/db/client.c +++ b/plugins/pychrysalide/analysis/db/client.c @@ -51,6 +51,9 @@ static PyObject *py_hub_client_stop(PyObject *, PyObject *);  /* Effectue une demande de sauvegarde de l'état courant. */  static PyObject *py_hub_client_save(PyObject *, PyObject *); +/* Active les éléments en amont d'un horodatage donné. */ +static PyObject *py_hub_client_set_last_active(PyObject *, PyObject *); +  /****************************************************************************** @@ -146,7 +149,7 @@ static PyObject *py_hub_client_new(PyTypeObject *type, PyObject *args, PyObject  /******************************************************************************  *                                                                             * -*  Paramètres  : self = serveur à manipuler.                                  * +*  Paramètres  : self = client à manipuler.                                   *  *                args = paramètres à transmettre à l'appel natif.             *  *                                                                             *  *  Description : Démarre la connexion à la base de données.                   * @@ -201,7 +204,7 @@ static PyObject *py_hub_client_start(PyObject *self, PyObject *args)  /******************************************************************************  *                                                                             * -*  Paramètres  : self = serveur à manipuler.                                  * +*  Paramètres  : self = client à manipuler.                                   *  *                args = arguments d'appel non utilisés ici.                   *  *                                                                             *  *  Description : Arrête la connexion à la base de données.                    * @@ -238,7 +241,7 @@ static PyObject *py_hub_client_stop(PyObject *self, PyObject *args)  /******************************************************************************  *                                                                             * -*  Paramètres  : self = serveur à manipuler.                                  * +*  Paramètres  : self = client à manipuler.                                   *  *                args = arguments d'appel non utilisés ici.                   *  *                                                                             *  *  Description : Effectue une demande de sauvegarde de l'état courant.        * @@ -279,6 +282,56 @@ static PyObject *py_hub_client_save(PyObject *self, PyObject *args)  /******************************************************************************  *                                                                             * +*  Paramètres  : self = client à manipuler.                                   * +*                args = arguments d'appel à consulter.                        * +*                                                                             * +*  Description : Active les éléments en amont d'un horodatage donné.          * +*                                                                             * +*  Retour      : True si la commande a bien été envoyée, False sinon.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_hub_client_set_last_active(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    unsigned long long timestamp;           /* Horodatage de limite        */ +    int ret;                                /* Bilan de lecture des args.  */ +    GHubClient *client;                     /* Version native du serveur   */ +    bool status;                            /* Bilan de l'opération        */ + +#define HUB_CLIENT_SET_LAST_ACTIVE_METHOD PYTHON_METHOD_DEF             \ +(                                                                       \ +    set_last_active, "$self, timestamp, /",                             \ +    METH_VARARGS, py_hub_client,                                        \ +    "Define the timestamp of the last active item in the collection"    \ +    " and returns the status of the request transmission."              \ +    "\n"                                                                \ +    "This method should not be used directly. Prefer calling"           \ +    " pychrysalide.analysis.LoadedBinary.set_last_active() instead,"    \ +    " as some items may be volatile and thus not handled by clients."   \ +) + +    ret = PyArg_ParseTuple(args, "K", ×tamp); +    if (!ret) return NULL; + +    client = G_HUB_CLIENT(pygobject_get(self)); + +    status = g_hub_client_set_last_active(client, timestamp); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : -                                                            *  *                                                                             *  *  Description : Fournit un accès à une définition de type à diffuser.        * @@ -295,6 +348,7 @@ PyTypeObject *get_python_hub_client_type(void)          HUB_CLIENT_START_METHOD,          HUB_CLIENT_STOP_METHOD,          HUB_CLIENT_SAVE_METHOD, +        HUB_CLIENT_SET_LAST_ACTIVE_METHOD,          { NULL }      }; diff --git a/plugins/pychrysalide/analysis/db/collection.c b/plugins/pychrysalide/analysis/db/collection.c index e62c17e..53cdccc 100644 --- a/plugins/pychrysalide/analysis/db/collection.c +++ b/plugins/pychrysalide/analysis/db/collection.c @@ -59,10 +59,9 @@ static PyObject *py_db_collection_get_items(PyObject *self, void *closure)  {      PyObject *result;                       /* Trouvailles à retourner     */      GDbCollection *collec;                  /* Version native              */ -    size_t counter;                         /* Décompte des éléments       */ -    GList *items;                           /* Eléments déjà en place      */ -    GList *iter;                            /* Boucle de parcours          */ -    int ret;                                /* Bilan d'une extension       */ +    size_t count;                           /* Décompte des éléments       */ +    GDbItem **items;                        /* Eléments déjà en place      */ +    size_t i;                               /* Boucle de parcours          */  #define DB_COLLECTION_ITEMS_ATTRIB PYTHON_GET_DEF_FULL      \  (                                                           \ @@ -74,22 +73,21 @@ static PyObject *py_db_collection_get_items(PyObject *self, void *closure)      collec = G_DB_COLLECTION(pygobject_get(self)); -    counter = 0; -    result = PyTuple_New(counter); -      g_db_collection_rlock(collec); -    items = g_db_collection_get_items(G_DB_COLLECTION(collec)); - -    for (iter = g_list_first(items); iter != NULL; iter = g_list_next(iter)) -    { -        ret = _PyTuple_Resize(&result, ++counter); -        if (ret == -1) break; +    items = g_db_collection_get_items(G_DB_COLLECTION(collec), &count); -        PyTuple_SetItem(result, counter - 1, pygobject_new(G_OBJECT(iter->data))); +    result = PyTuple_New(count); +    for (i = 0; i < count; i++) +    { +        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(items[i]))); +        g_object_unref(G_OBJECT(items[i]));      } +    if (items != NULL) +        free(items); +      g_db_collection_runlock(collec);      return result; diff --git a/plugins/pychrysalide/analysis/db/constants.c b/plugins/pychrysalide/analysis/db/constants.c index 46d0876..07c7a06 100644 --- a/plugins/pychrysalide/analysis/db/constants.c +++ b/plugins/pychrysalide/analysis/db/constants.c @@ -96,6 +96,7 @@ bool define_db_item_constants(PyTypeObject *type)      if (result) result = add_const_to_group(values, "UPDATED", DIF_UPDATED);      if (result) result = add_const_to_group(values, "VOLATILE", DIF_VOLATILE);      if (result) result = add_const_to_group(values, "BROKEN", DIF_BROKEN); +    if (result) result = add_const_to_group(values, "DISABLED", DIF_DISABLED);      if (!result)      { diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c index 0923268..7ef30af 100644 --- a/plugins/pychrysalide/analysis/db/item.c +++ b/plugins/pychrysalide/analysis/db/item.c @@ -48,6 +48,9 @@ static PyObject *py_db_item_remove_flag(PyObject *, PyObject *);  /* Décrit l'élément de collection en place. */  static PyObject *py_db_item_get_label(PyObject *, void *); +/* Fournit l'horodatage associé à l'élément de collection. */ +static PyObject *py_db_item_get_timestamp(PyObject *, void *); +  /* Indique les propriétés particulières appliquées à l'élément. */  static PyObject *py_db_item_get_flags(PyObject *, void *); @@ -178,6 +181,42 @@ static PyObject *py_db_item_get_label(PyObject *self, void *closure)  *  Paramètres  : self    = objet Python concerné par l'appel.                 *  *                closure = non utilisé ici.                                   *  *                                                                             * +*  Description : Fournit l'horodatage associé à l'élément de collection.      * +*                                                                             * +*  Retour      : Date de création de l'élément.                               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_db_item_get_timestamp(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Valeur à retourner          */ +    GDbItem *item;                          /* Elément à consulter         */ +    timestamp_t timestamp;                  /* Horodatage de l'élément     */ + +#define DB_ITEM_TIMESTAMP_ATTRIB PYTHON_GET_DEF_FULL    \ +(                                                       \ +    timestamp, py_db_item,                              \ +    "Timestamp of the item creation."                   \ +) + +    item = G_DB_ITEM(pygobject_get(self)); + +    timestamp = g_db_item_get_timestamp(item); + +    result = PyLong_FromUnsignedLongLong(timestamp); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             *  *  Description : Indique les propriétés particulières appliquées à l'élément. *  *                                                                             *  *  Retour      : Propriétés actives de l'élément.                             * @@ -232,6 +271,7 @@ PyTypeObject *get_python_db_item_type(void)      static PyGetSetDef py_db_item_getseters[] = {          DB_ITEM_LABEL_ATTRIB, +        DB_ITEM_TIMESTAMP_ATTRIB,          DB_ITEM_FLAGS_ATTRIB,          { NULL }      }; diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 822510c..05e42c7 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1127,87 +1127,56 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bo          } +        g_object_unref(G_OBJECT(item)); +      }      g_object_unref(G_OBJECT(collec)); -    g_object_unref(G_OBJECT(item));      return result;  } + +  /******************************************************************************  *                                                                             * -*  Paramètres  : binary  = élément binaire à consulter.                       * -*                feature = fonctionnalité visée par la requête.               * -*                item    = élémnent à retirer d'un serveur de collection.     * -*                lock    = indique si le verrou d'écriture doit être posé.    * +*  Paramètres  : binary    = élément binaire à consulter.                     * +*                timestamp = date du dernier élément à garder comme actif.    *  *                                                                             * -*  Description : Demande la suppression de modification dans une collection.  * +*  Description : Active les éléments en amont d'un horodatage donné.      XXXXXXXXXXXXXXXXX    *  *                                                                             * -*  Retour      : Bilan partiel de l'opération demandée.                       * +*  Retour      : true si la commande a bien été envoyée, false sinon.         *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item, bool lock) +bool g_loaded_binary_set_last_active(GLoadedBinary *binary, timestamp_t timestamp)  { -    bool result;                            /* Bilan à faire remonter      */ -    GDbCollection *collec;                  /* Collection visée au final   */ -    DBStorage storage;                      /* Forme d'enregistrement      */ -    GHubClient *client;                     /* Liaison à utiliser          */ -    packed_buffer out_pbuf;                 /* Tampon d'émission           */ -    SSL *tls_fd;                            /* Canal de communication SSL  */ +    bool result;                            /* Bilan à retourner           */ -    collec = g_loaded_binary_find_collection(binary, feature); -    if (collec == NULL) return false; -    /* S'il n'y a pas besoin de sauvegarde... */ -    if (g_db_item_get_flags(item) & DIF_VOLATILE) -        result = _g_db_collection_remove_item(collec, item, lock, true); +    result = false; -    /* Sinon on envoie par le réseau ! */ -    else -    { -        storage = g_loaded_binary_get_storage(binary, feature); -        if (storage == DBS_ALL_REMOTE) -            client = binary->remote; -        else -            client = NULL; -        if (client == NULL) -            client = binary->local; -        init_packed_buffer(&out_pbuf); +    return result; + +} -        tls_fd = g_hub_client_get_ssl_fd(client); -        if (tls_fd == NULL) -            result = false; -        else -        { -            result = g_db_collection_pack(collec, &out_pbuf, DBA_REM_ITEM, item); -            if (result) -                result = ssl_send_packed_buffer(&out_pbuf, tls_fd); -            g_hub_client_put_ssl_fd(client, tls_fd); -        } -        exit_packed_buffer(&out_pbuf); -    } -    g_object_unref(G_OBJECT(collec)); -    return result; -} diff --git a/src/analysis/binary.h b/src/analysis/binary.h index dd3dfc6..b4c8652 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -131,12 +131,10 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *, GDbItem *, bool);  #define g_loaded_binary_add_to_collection(b, i) \      _g_loaded_binary_add_to_collection(b, i, true) -/* Demande la suppression de modification dans une collection. */ -bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbItem *, bool); -#define g_loaded_binary_remove_from_collection(b, f, i) \ -    _g_loaded_binary_remove_from_collection(b, f, i, true) +/* Active les éléments en amont d'un horodatage donné. */ +bool g_loaded_binary_set_last_active(GLoadedBinary *, timestamp_t); diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index a787a19..ca39a58 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -967,8 +967,16 @@ static void *g_cdb_archive_process(GCdbArchive *archive)                      case DBC_SET_LAST_ACTIVE: -                        status = update_activity_in_collections(archive->collections, &in_pbuf, archive->db); -                        if (!status) goto gcap_bad_exchange; +                        init_packed_buffer(&out_pbuf); + +                        status = update_activity_in_collections(archive->collections, \ +                                                                &in_pbuf, &out_pbuf, archive->db); +                        if (!status) goto gcap_bad_reply; + +                        status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd); +                        if (!status) goto gcap_bad_reply; + +                        exit_packed_buffer(&out_pbuf);                          break; diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 744fa57..beb30c1 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -789,7 +789,7 @@ static void *g_hub_client_update(GHubClient *client)                      status = extract_packed_buffer(&in_pbuf, &tmp8, sizeof(uint8_t), true);                      if (!status) goto gdcu_bad_exchange; -                    client->can_get_updates = (tmp8 == 0x0); +                    client->can_get_updates = (tmp8 == 0x1);                      break;              } @@ -797,6 +797,7 @@ static void *g_hub_client_update(GHubClient *client)              if (has_more_data_in_packed_buffer(&in_pbuf))                  goto next_command; +            client->can_get_updates = true;              continue;   gdcu_bad_exchange: diff --git a/src/analysis/db/collection-int.h b/src/analysis/db/collection-int.h index b3b83bb..c9d37bf 100644 --- a/src/analysis/db/collection-int.h +++ b/src/analysis/db/collection-int.h @@ -35,9 +35,6 @@  /* Crée la table associée à une collection d'éléments. */  typedef bool (* collec_create_db_table_fc) (const GDbCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -typedef bool (* collec_setup_load_fc) (GDbCollection *, bound_value **, size_t *); -  /* Charge les valeurs utiles pour une localisation. */  typedef bool (* collec_load_item) (GDbCollection *, const bound_value *, size_t); @@ -58,8 +55,8 @@ struct _GDbCollection      /* Référence circulaire */      GLoadedBinary *binary;                  /* Binaire rattaché éventuel   */ -    GList *items;                           /* Eléments rassemblés         */ -    GList *sorted;                          /* Eléments triés              */ +    GDbItem **items;                        /* Eléments rassemblés         */ +    size_t count;                           /* Quantité de ces éléments    */      GHashTable *last_items;                 /* Statuts courants d'éléments */      GRWLock params_access;                  /* Verrou de protection        */ @@ -71,7 +68,6 @@ struct _GDbCollectionClass      GObjectClass parent;                    /* A laisser en premier        */      collec_create_db_table_fc create_table; /* Création de la table en SQL */ -    collec_setup_load_fc setup_load;        /* Prépare le chargement       */      collec_load_item load_item;             /* Charge un élément           */      collec_has_key_fc has_key;              /* Recherche de présence       */ @@ -79,6 +75,8 @@ struct _GDbCollectionClass      void (* content_extended) (GDbCollection *, GDbItem *); +    void (* state_changed) (GDbCollection *, GDbItem *); +  }; diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index f728718..edb55d8 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -58,14 +58,23 @@ static void g_db_collection_finalize(GDbCollection *); -/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +#define g_db_collection_find_by_timestamped(c, i) c->count + +#define g_db_collection_find_by_timestamp(c, i) c->count + + + +/* Ajoute un élément dans la liste des éléments actifs. */ +static void g_db_collection_set_last_item(GDbCollection *, GDbItem *, bool); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool _g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *); +/* Retire un élément de la liste des éléments courants. */ +static void g_db_collection_unset_last_item(GDbCollection *, GDbItem *, size_t); + + + +/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *);  /* Charge et intère un élément dans une collection. */  static bool g_db_collection_load_new_item(const bound_value *, size_t, GDbCollection *); @@ -104,8 +113,6 @@ static void g_db_collection_class_init(GDbCollectionClass *klass)      object->dispose = (GObjectFinalizeFunc/* ! */)g_db_collection_dispose;      object->finalize = (GObjectFinalizeFunc)g_db_collection_finalize; -    klass->setup_load = (collec_setup_load_fc)_g_db_collection_setup_load; -      g_signal_new("content-extended",                   G_TYPE_DB_COLLECTION,                   G_SIGNAL_RUN_LAST, @@ -114,6 +121,14 @@ static void g_db_collection_class_init(GDbCollectionClass *klass)                   g_cclosure_marshal_VOID__OBJECT,                   G_TYPE_NONE, 1, G_TYPE_OBJECT); +    g_signal_new("state-changed", +                 G_TYPE_DB_COLLECTION, +                 G_SIGNAL_RUN_LAST, +                 G_STRUCT_OFFSET(GDbCollectionClass, state_changed), +                 NULL, NULL, +                 g_cclosure_marshal_VOID__OBJECT, +                 G_TYPE_NONE, 1, G_TYPE_OBJECT); +  } @@ -133,6 +148,9 @@ static void g_db_collection_init(GDbCollection *collec)  {      collec->binary = NULL; +    collec->items = NULL; +    collec->count = 0; +      collec->last_items = g_hash_table_new_full((GHashFunc)g_db_item_hash_key,                                                 (GEqualFunc)g_db_item_cmp_key,                                                 (GDestroyNotify)g_object_unref, @@ -157,17 +175,10 @@ static void g_db_collection_init(GDbCollection *collec)  static void g_db_collection_dispose(GDbCollection *collec)  { -    if (collec->items != NULL) -    { -        g_list_free_full(collec->items, g_object_unref); -        collec->items = NULL; -    } +    size_t i;                               /* Boucle de parcours          */ -    if (collec->sorted != NULL) -    { -        g_list_free_full(collec->sorted, g_object_unref); -        collec->sorted = NULL; -    } +    for (i = 0; i < collec->count; i++) +        g_clear_object(&collec->items[i]);      G_OBJECT_CLASS(g_db_collection_parent_class)->dispose(G_OBJECT(collec)); @@ -188,6 +199,9 @@ static void g_db_collection_dispose(GDbCollection *collec)  static void g_db_collection_finalize(GDbCollection *collec)  { +    if (collec->items != NULL) +        free(collec->items); +      g_rw_lock_clear(&collec->params_access);      G_OBJECT_CLASS(g_db_collection_parent_class)->finalize(G_OBJECT(collec)); @@ -361,8 +375,6 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3      bool result;                            /* Bilan à faire remonter      */      DBAction action;                        /* Commande de la requête      */      GDbItem *item;                          /* Définition d'élément visé   */ -    GList *found;                           /* Test de présence existante  */ -    timestamp_t inactive;                   /* Horodatage de désactivation */      result = _g_db_collection_unpack(collec, pbuf, &action, &item);      if (!result) return false; @@ -379,7 +391,7 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3              if (result)              { -                if (collec->binary != NULL && g_db_item_is_active(item)) +                if (collec->binary != NULL && !g_db_item_has_flag(item, DIF_DISABLED))                      g_db_item_apply(item, collec->binary);                  if (db != NULL) @@ -389,50 +401,29 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3              break; -        case DBA_REM_ITEM: - -            g_db_collection_wlock(collec); - -            found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_with_timestamp); - -            result = (found != NULL); +        case DBA_CHANGE_STATE: -            if (result) +            if (collec->binary != NULL)              { -                /* Côté client */ -                if (db == NULL) -                    result = _g_db_collection_remove_item(collec, item, false, true); +                result = g_db_collection_update_item_state(collec, item); -                /* Côté serveur */ -                else +                if (result)                  { -                    if (g_db_item_is_active(G_DB_ITEM(found->data))) -                    { -                        inactive = _g_db_collection_compute_inactivity_timestamp(collec, false); -                        result = _g_db_collection_update_item_activity(collec, item, &inactive, false); -                    } +                    if (g_db_item_has_flag(item, DIF_DISABLED)) +                        g_db_item_cancel(item, collec->binary); +                    else +                        g_db_item_apply(item, collec->binary);                  }              } -            g_db_collection_wunlock(collec); - -            break; - -        case DBA_CHANGE_STATE: - -            if (db == NULL) -            { -                if (g_db_item_is_active(item)) -                    result = g_db_collection_update_item_activity(collec, item, NULL); -                else -                { -                    inactive = g_db_item_get_timestamp(item) + 1; -                    result = g_db_collection_update_item_activity(collec, item, &inactive); -                } -            }              else +            { +                assert(db != NULL);                  result = false; +            } + +            g_object_unref(G_OBJECT(item));              break; @@ -442,8 +433,6 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3      } -    g_object_unref(G_OBJECT(item)); -      return result;  } @@ -500,7 +489,7 @@ bool g_db_collection_pack(GDbCollection *collec, packed_buffer *pbuf, DBAction a  bool g_db_collection_pack_all_updates(GDbCollection *collec, packed_buffer *pbuf)  {      bool result;                            /* Bilan à renvoyer            */ -    GList *iter;                            /* Boucle de parcours          */ +    size_t i;                               /* Boucle de parcours          */      result = true; @@ -509,13 +498,8 @@ bool g_db_collection_pack_all_updates(GDbCollection *collec, packed_buffer *pbuf       * g_cdb_archive_add_client().      */ -    for (iter = g_list_first(collec->items); -         iter != NULL && result; -         iter = g_list_next(iter)) -    { -        result = g_db_collection_pack(collec, pbuf, DBA_ADD_ITEM, G_DB_ITEM(iter->data)); - -    } +    for (i = 0; i < collec->count && result; i++) +        result = g_db_collection_pack(collec, pbuf, DBA_ADD_ITEM, G_DB_ITEM(collec->items[i]));      return result; @@ -560,6 +544,7 @@ void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock)  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    * +*                count  = taille de la liste constituée. [OUT]                *  *                                                                             *  *  Description : Renvoie la liste des éléments rassemblés.                    *  *                                                                             * @@ -569,14 +554,34 @@ void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock)  *                                                                             *  ******************************************************************************/ -GList *g_db_collection_get_items(const GDbCollection *collec) +GDbItem **g_db_collection_get_items(const GDbCollection *collec, size_t *count)  { +    GDbItem **result;                       /* Liste à retourner           */ +    size_t i;                               /* Boucle de parcours          */ +      /**       * Un verrou doit être posé !       * Il n'y a pas d'assert() possible pour le vérifier...       */ -    return collec->items; +    *count = collec->count; + +    if (*count == 0) +        result = NULL; + +    else +    { +        result = malloc(*count * sizeof(GDbItem *)); + +        for (i = 0; i < *count; i++) +        { +            result[i] = collec->items[i]; +            g_object_ref(G_OBJECT(result[i])); +        } + +    } + +    return result;  } @@ -626,16 +631,16 @@ GDbItem *g_db_collection_has_key(GDbCollection *collec, ...)  bool g_db_collection_has_item(GDbCollection *collec, GDbItem *item)  {      bool result;                            /* Bilan à retourner           */ -    GList *found;                           /* Test de présence existante  */ +    size_t index;                           /* Indice de l'élément trouvé  */       /**       * Un verrou doit être posé !       * Il n'y a pas d'assert() possible pour le vérifier...       */ -    found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_with_timestamp); +    index = g_db_collection_find_by_timestamped(collec, item); -    result = (found != NULL); +    result = (index < collec->count);      return result; @@ -646,36 +651,46 @@ bool g_db_collection_has_item(GDbCollection *collec, GDbItem *item)  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à considérer.                   *  *                item   = élément de collection à manipuler.                  * -*                lock   = indique si le verrou d'écriture doit être posé.     * +*                new    = précise la nature de l'élément à insérer.           *  *                                                                             * -*  Description : Procède à l'ajout d'un nouvel élément dans la collection.    * +*  Description : Ajoute un élément dans la liste des éléments actifs.         *  *                                                                             * -*  Retour      : Bilan de l'exécution de l'opération.                         * +*  Retour      : -                                                            *  *                                                                             * -*  Remarques   : L'appelant reste le propriétaire de l'object transféré.      * +*  Remarques   :                                                              *  *                                                                             *  ******************************************************************************/ -bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) +static void g_db_collection_set_last_item(GDbCollection *collec, GDbItem *item, bool new)  { -    bool result;                            /* Bilan à faire remonter      */      GDbItem *prev;                          /* Elément similaire précédent */ +    timestamp_t its;                        /* Horodatage #0               */ +    timestamp_t pts;                        /* Horodatage #1               */ -    result = true; - -    if (lock) -        g_db_collection_wlock(collec); - -    g_object_ref(G_OBJECT(item)); -    collec->items = g_list_append(collec->items, item); - -    g_object_ref(G_OBJECT(item)); -    collec->sorted = g_list_insert_sorted(collec->sorted, item, (GCompareFunc)g_db_item_compare_with_timestamp); +    assert(!g_db_item_has_flag(item, DIF_DISABLED));      prev = g_hash_table_lookup(collec->last_items, item);      if (prev != NULL)      { +        /** +         * Dans le cas où le changement intervient sans contexte particulier, +         * on s'assure de le pas remplacer un élément plus récent déjà en place +         * par un élément nouvellement actif mais dépassé. +         * +         * Le code de g_db_collection_disable_at(), aux conséquences portant +         * dans le serveur et le client, procède de manière à éviter cette +         * situation par un ordre de parcours choisi. +         * +         * On insère néanmoins une petite sécurité. +         */ + +        its = g_db_item_get_timestamp(item); +        pts = g_db_item_get_timestamp(prev); + +        if (timestamp_is_younger(its, pts)) +            goto already_up_to_date; +          g_object_ref(G_OBJECT(prev));          if (g_db_item_get_flags(item) & DIF_ERASER) @@ -683,7 +698,8 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock)          else          { -            g_db_item_add_flag(item, DIF_UPDATED); +            if (new) +                g_db_item_add_flag(item, DIF_UPDATED);              g_object_ref(G_OBJECT(item));              g_object_ref(G_OBJECT(item)); @@ -698,19 +714,20 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock)      else      { -        g_object_ref(G_OBJECT(item)); -        g_object_ref(G_OBJECT(item)); +        if (g_db_item_get_flags(item) & DIF_ERASER) +        { +            g_object_ref(G_OBJECT(item)); +            g_object_ref(G_OBJECT(item)); -        g_hash_table_add(collec->last_items, item); +            g_hash_table_add(collec->last_items, item); + +        }      } -    g_signal_emit_by_name(collec, "content-extended", item); + already_up_to_date: -    if (lock) -        g_db_collection_wunlock(collec); - -    return result; +    ;  } @@ -720,49 +737,30 @@ bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock)  *  Paramètres  : collec = ensemble d'éléments à considérer.                   *  *                item   = élément de collection à manipuler.                  *  *                lock   = indique si le verrou d'écriture doit être posé.     * -*                signal = émet un événement pour signaler le retrait.         *  *                                                                             * -*  Description : Procède au retrait d'un nouvel élément dans la collection.   * +*  Description : Procède à l'ajout d'un nouvel élément dans la collection.    *  *                                                                             *  *  Retour      : Bilan de l'exécution de l'opération.                         *  *                                                                             * -*  Remarques   : L'appelant reste le propriétaire de l'object transféré.      * +*  Remarques   : L'appelant perd la propriété de l'object transféré.          *  *                                                                             *  ******************************************************************************/ -bool _g_db_collection_remove_item(GDbCollection *collec, GDbItem *item, bool lock, bool signal) +bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock)  {      bool result;                            /* Bilan à faire remonter      */ -    GList *found;                           /* Test de présence existante  */ -    GDbItem *internal;                      /* Elément interne à modifier  */      result = true;      if (lock)          g_db_collection_wlock(collec); -    found = g_list_find_custom(collec->sorted, item, (GCompareFunc)g_db_item_compare_with_timestamp); - -    result = (found != NULL); +    collec->items = realloc(collec->items, ++collec->count * sizeof(GDbItem *)); +    collec->items[collec->count - 1] = item; -    if (result) -    { -        internal = G_DB_ITEM(found->data); +    g_db_collection_set_last_item(collec, item, true); -        collec->sorted = g_list_delete_link(collec->sorted, found); - -        found = g_list_find(collec->items, item); -        assert(found != NULL); - -        collec->items = g_list_delete_link(collec->items, found); - -        if (signal) -            ;//g_signal_emit_by_name(collec, "content-changed", DBA_REM_ITEM, internal); - -        g_object_unref(G_OBJECT(internal)); -        g_object_unref(G_OBJECT(internal)); - -    } +    g_signal_emit_by_name(collec, "content-extended", item);      if (lock)          g_db_collection_wunlock(collec); @@ -775,47 +773,54 @@ bool _g_db_collection_remove_item(GDbCollection *collec, GDbItem *item, bool loc  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à considérer.                   * -*                lock   = indique si le verrou d'écriture doit être posé.     * +*                pbuf   = paquet de données où venir inscrire les infos.      *  *                                                                             * -*  Description : Détermine l'horodatage le plus jeune pour une désactivation. * +*  Description : Procède au retrait des éléments désactivés de la collection. *  *                                                                             * -*  Retour      : Horodatage à utiliser pour une phase de désactivation.       * +*  Retour      : Bilan de l'exécution de l'opération.                         *  *                                                                             * -*  Remarques   : -                                                            * +*  Remarques   :                                                              *  *                                                                             *  ******************************************************************************/ -timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec, bool lock) +bool g_db_collection_drop_disabled_items(GDbCollection *collec, packed_buffer *pbuf)  { -    timestamp_t result;                     /* Horodatage à retourner      */ -    GList *iter;                            /* Boucle de parcours          */ -    GDbItem *item;                          /* Elément interne à consulter */ -    timestamp_t stamp;                      /* Horodatage de l'élément     */ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */ +    GDbItem *item;                          /* Elément désactivé           */ +#ifndef NDEBUG +    GDbItem *enabled;                       /* Eventuel similarité active  */ +#endif -    result = TIMESTAMP_ALL_ACTIVE; +    /** +     * Voie de suppression d'un élément côté serveur. +     */ -    if (lock) -        g_db_collection_wlock(collec); +    result = true; -    for (iter = g_list_first(collec->items); -         iter != NULL; -         iter = g_list_next(iter)) +    g_db_collection_wlock(collec); + +    for (i = collec->count; i > 0 && result; i--)      { -        item = G_DB_ITEM(iter->data); +        item = collec->items[i - 1]; -        if (!g_db_item_is_active(item)) -        { -            stamp = g_db_item_get_timestamp(item); +        if (!g_db_item_has_flag(item, DIF_DISABLED)) +            break; -            if (timestamp_is_younger(stamp, result)) -                result = stamp; +#ifndef NDEBUG +        enabled = g_hash_table_lookup(collec->last_items, item); +        assert(enabled != item); +#endif -        } +        collec->items = realloc(collec->items, --collec->count * sizeof(GDbItem *)); + +        result = g_db_collection_pack(collec, pbuf, DBA_REM_ITEM, item); + +        g_object_unref(G_OBJECT(item));      } -    if (lock) -        g_db_collection_wunlock(collec); +    g_db_collection_wunlock(collec);      return result; @@ -826,9 +831,8 @@ timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec,  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à considérer.                   *  *                item   = élément de collection à manipuler.                  * -*                lock   = indique si le verrou d'écriture doit être posé.     *  *                                                                             * -*  Description : Met à jour le statut d'activité d'un élément de collection.  * +*  Description : Procède au retrait d'un élément dans la collection.          *  *                                                                             *  *  Retour      : Bilan de l'exécution de l'opération.                         *  *                                                                             * @@ -836,31 +840,47 @@ timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *collec,  *                                                                             *  ******************************************************************************/ -bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item, timestamp_t *timestamp, bool lock) +bool g_db_collection_remove_item(GDbCollection *collec, const GDbItem *item)  {      bool result;                            /* Bilan à faire remonter      */ -    GList *found;                           /* Test de présence existante  */ -    GDbItem *internal;                      /* Elément interne à modifier  */ +    size_t found;                           /* Indice de l'élément concerné*/ +    GDbItem *disabled;                      /* Elément désactivé           */ +#ifndef NDEBUG +    GDbItem *enabled;                       /* Eventuel similarité active  */ +#endif -    if (lock) -        g_db_collection_wlock(collec); +    /** +     * Voie de suppression d'un élément côté serveur. +     */ -    found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare_without_timestamp); +    g_db_collection_wlock(collec); -    result = (found != NULL); +    found = g_db_collection_find_by_timestamped(collec, item); + +    result = (found < collec->count); +    assert(result);      if (result)      { -        internal = G_DB_ITEM(found->data); +        disabled = collec->items[found]; + +        assert(g_db_item_has_flag(disabled, DIF_DISABLED)); + +#ifndef NDEBUG +        enabled = g_hash_table_lookup(collec->last_items, disabled); +        assert(enabled != disabled); +#endif + +        memmove(collec->items + found, collec->items + found + 1, +                (collec->count - found - 1) * sizeof(GDbItem *)); -        result = g_db_item_set_activity(internal, collec->binary, timestamp); +        collec->items = realloc(collec->items, --collec->count * sizeof(GDbItem *)); -        //g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, internal); +        g_object_unref(G_OBJECT(disabled));      } -    if (lock) -        g_db_collection_wunlock(collec); +    g_db_collection_wunlock(collec);      return result; @@ -869,157 +889,202 @@ bool _g_db_collection_update_item_activity(GDbCollection *collec, GDbItem *item,  /******************************************************************************  *                                                                             * -*  Paramètres  : collec    = ensemble d'éléments à considérer.                * -*                timestamp = date du dernier élément à garder comme actif.    * -*                inactive  = date du premier élément inactif rencontré. [OUT] * -*                db        = base de données à mettre à jour.                 * +*  Paramètres  : collec = ensemble d'éléments à considérer.                   * +*                item   = élément de collection à manipuler.                  * +*                count  = décompte des éléments actifs.                       *  *                                                                             * -*  Description : Active les éléments en amont d'un horodatage donné.          * +*  Description : Retire un élément de la liste des éléments courants.         *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * -*  Remarques   : -                                                            * +*  Remarques   :                                                              *  *                                                                             *  ******************************************************************************/ -GList *g_db_collection_set_last_active(GDbCollection *collec, timestamp_t timestamp, timestamp_t *inactive, sqlite3 *db) +static void g_db_collection_unset_last_item(GDbCollection *collec, GDbItem *item, size_t count)  { -    GList *result;                          /* Liste d'inactifs à renvoyer */ -    GList *i;                               /* Parcours des éléments       */ -    GDbItem *item;                          /* Elément à traiter           */ -    timestamp_t stamp;                      /* Horodatage de l'élément     */ +    GDbItem *prev;                          /* Elément similaire précédent */ +    GDbItem *old;                           /* Ancien élément similaire    */ +    size_t i;                               /* Boucle de parcours          */ -    result = NULL; +    assert(g_db_item_has_flag(item, DIF_DISABLED)); + +    prev = g_hash_table_lookup(collec->last_items, item); -    for (i = g_list_first(collec->items); i != NULL; i = g_list_next(i)) +    if (prev == item)      { -        item = G_DB_ITEM(i->data); -        stamp = g_db_item_get_timestamp(item); +        old = NULL; -        if (timestamp_is_younger(stamp, timestamp)) -        { -            if (!g_db_item_is_active(item)) -            { -                /* ... */g_db_item_set_activity(item, collec->binary, NULL); -                /* ... */g_db_collection_store_updated_item(collec, item, db); -                //g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, item); -            } +        for (i = count; i > 0; i++) +            if (g_db_item_cmp_key(collec->items[i - 1], item)) +                break; +            else +                old = collec->items[i - 1]; -        } +        if (old == NULL || g_db_item_get_flags(old) & DIF_ERASER) +            g_hash_table_remove(collec->last_items, item);          else          { -            if (!g_db_item_is_active(item)) -            { -                if (timestamp_is_younger(stamp, *inactive)) -                    *inactive = stamp; -            } +            g_object_ref(G_OBJECT(old)); +            g_object_ref(G_OBJECT(old)); -            else -                result = g_list_append(result, item); +            g_hash_table_replace(collec->last_items, old, old);          }      } -    return result; -  }  /******************************************************************************  *                                                                             * -*  Paramètres  : collec    = ensemble d'éléments à considérer.                * -*                item      = élément à désactiver.                            * -*                timestamp = date du premier élément inactif rencontré. [OUT] * +*  Paramètres  : binary    = élément binaire à consulter.                     * +*                timestamp = date du dernier élément à garder comme actif.    * +*                db        = base de données à mettre à jour.                 * +*                pbuf      = paquet de données où venir inscrire les infos.   *  *                                                                             *  *  Description : Désactive les éléments en aval d'un horodatage donné.        *  *                                                                             * -*  Retour      : true si l'élément a été traité, false sinon.                 * +*  Retour      : true si la commande a bien été envoyée, false sinon.         *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -bool g_db_collection_set_inactive(GDbCollection *collec, GDbItem *item, timestamp_t *timestamp) +bool g_db_collection_disable_at(GDbCollection *collec, timestamp_t timestamp, sqlite3 *db, packed_buffer *pbuf)  {      bool result;                            /* Bilan à retourner           */ +    size_t start;                           /* Début de la zone à changer  */ +    size_t back;                            /* Début de restauration       */ +    size_t i;                               /* Boucle de parcours          */ +    GDbItem *item;                          /* Elément à traiter           */ -    /* Si cette collection n'est pas concernée, on ne bouge pas ! */ -    if (G_OBJECT_TYPE(G_OBJECT(item)) != collec->type) return false; +    result = true; -    result = g_db_item_set_activity(item, collec->binary, timestamp); +    g_db_collection_wlock(collec); -    //g_signal_emit_by_name(collec, "content-changed", DBA_CHANGE_STATE, item); +    start = g_db_collection_find_by_timestamp(collec, timestamp); -    return result; +    /* Réactivation d'éléments ? */ -} +    if (start > 0) +    { +        back = start; +        for (i = start; i > 0; i--) +            if (!g_db_item_has_flag(collec->items[i - 1], DIF_DISABLED)) +                break; +            else +                back--; +        for (i = back; i < start && result; i++) +        { +            item = collec->items[i]; -/* ---------------------------------------------------------------------------------- */ -/*                       MANIPULATIONS AVEC UNE BASE DE DONNEES                       */ -/* ---------------------------------------------------------------------------------- */ +            g_db_item_remove_flag(item, DIF_DISABLED); +            g_db_collection_store_updated_item(collec, item, db); -/****************************************************************************** -*                                                                             * -*  Paramètres  : collec = ensemble d'éléments spectateur des opérations.      * -*                db     = accès à la base de données.                         * -*                                                                             * -*  Description : Crée la table d'élément dans une base de données.            * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +            g_db_collection_set_last_item(collec, item, false); -bool g_db_collection_create_db_table(const GDbCollection *collec, sqlite3 *db) -{ -    return G_DB_COLLECTION_GET_CLASS(collec)->create_table(collec, db); +            result = g_db_collection_pack(collec, pbuf, DBA_CHANGE_STATE, item); + +        } + +    } + +    /* Désactivation des éléments en queue */ + +    for (i = start; i < collec->count && result; i++) +    { +        item = collec->items[i]; + +        if (g_db_item_has_flag(item, DIF_DISABLED)) +            break; + +        g_db_item_add_flag(item, DIF_DISABLED); + +        g_db_collection_store_updated_item(collec, item, db); + +        g_db_collection_unset_last_item(collec, item, start); + +        result = g_db_collection_pack(collec, pbuf, DBA_CHANGE_STATE, item); + +    } + +    g_db_collection_wunlock(collec); + +    return result;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : collec = ensemble d'éléments à consulter.                    * -*                values = tableau d'éléments à compléter. [OUT]               * -*                count  = nombre de descriptions renseignées. [OUT]           * +*  Paramètres  : collec = ensemble d'éléments à considérer.                   * +*                item   = élément de collection à manipuler.                  *  *                                                                             * -*  Description : Décrit les colonnes utiles à un chargement de données.       * +*  Description : Prend acte d'un changement d'état d'un élément de collection.*  *                                                                             * -*  Retour      : Bilan de l'opération.                                        * +*  Retour      : Bilan de l'exécution de l'opération.                         *  *                                                                             * -*  Remarques   : -                                                            * +*  Remarques   : L'appelant reste le propriétaire de l'object transféré.      *  *                                                                             *  ******************************************************************************/ -static bool _g_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count) +bool g_db_collection_update_item_state(GDbCollection *collec, const GDbItem *item)  { -    if (!store_timestamp(NULL, "created", values, count)) -        return false; +    bool result;                            /* Bilan à faire remonter      */ +    size_t index;                           /* Indice de l'élément visé    */ +    GDbItem *changed;                       /* Elément à basculer          */ +    DbItemFlags new;                        /* Nouvelles propriétés        */ + +    result = false; + +    g_db_collection_wlock(collec); + +    index = g_db_collection_find_by_timestamped(collec, item); -    if (!store_timestamp(NULL, "timestamp", values, count)) -        return false; +    result = (index < collec->count); -    if (!store_rle_string(NULL, "author", values, count)) -        return false; +    if (result) +    { +        changed = collec->items[index]; + +        new = g_db_item_get_flags(item); + +        g_db_item_set_flags(changed, new); + +        if (new & DIF_DISABLED) +            g_db_collection_unset_last_item(collec, changed, index); +        else +            g_db_collection_set_last_item(collec, changed, false); + +        g_signal_emit_by_name(collec, "state-changed", changed); + +    } -    return true; +    g_db_collection_wunlock(collec); + +    return result;  } + +/* ---------------------------------------------------------------------------------- */ +/*                       MANIPULATIONS AVEC UNE BASE DE DONNEES                       */ +/* ---------------------------------------------------------------------------------- */ + +  /******************************************************************************  *                                                                             * -*  Paramètres  : collec = ensemble d'éléments à consulter.                    * -*                values = tableau d'éléments à compléter. [OUT]               * -*                count  = nombre de descriptions renseignées. [OUT]           * +*  Paramètres  : collec = ensemble d'éléments spectateur des opérations.      * +*                db     = accès à la base de données.                         *  *                                                                             * -*  Description : Décrit les colonnes utiles à un chargement de données.       * +*  Description : Crée la table d'élément dans une base de données.            *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -1027,12 +1092,9 @@ static bool _g_db_collection_setup_load(GDbCollection *collec, bound_value **val  *                                                                             *  ******************************************************************************/ -static bool g_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count) +bool g_db_collection_create_db_table(const GDbCollection *collec, sqlite3 *db)  { -    *values = NULL; -    *count = 0; -     -    return G_DB_COLLECTION_GET_CLASS(collec)->setup_load(collec, values, count); +    return G_DB_COLLECTION_GET_CLASS(collec)->create_table(collec, db);  } @@ -1061,13 +1123,10 @@ static bool g_db_collection_load_new_item(const bound_value *values, size_t coun      result = g_db_item_load(new, values, count);      if (result) -    {          result = g_db_collection_add_item(G_DB_COLLECTION(collec), new); - +    else          g_object_unref(G_OBJECT(new)); -    } -      return result;  } @@ -1089,10 +1148,15 @@ static bool g_db_collection_load_new_item(const bound_value *values, size_t coun  bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)  {      bool result;                            /* Conclusion à faire remonter */ +    GDbItem *dummy;                         /* Interface vide              */      bound_value *values;                    /* Champs de table à inclure   */      size_t count;                           /* Nombre de ces champs        */ -    result = g_db_collection_setup_load(collec, &values, &count); +    dummy = g_object_new(collec->type, NULL); + +    result = g_db_item_setup_load(dummy, &values, &count); + +    g_object_unref(G_OBJECT(dummy));      if (result)          result = load_db_values(db, collec->name, values, count, (db_load_cb)g_db_collection_load_new_item, collec); @@ -1447,9 +1511,10 @@ bool pack_all_collection_updates(GList *list, packed_buffer *pbuf)  /******************************************************************************  *                                                                             * -*  Paramètres  : list = ensemble de collectons à traiter.                     * -*                pbuf = paquet de données où venir puiser les infos.          * -*                db   = base de données à mettre à jour.                      * +*  Paramètres  : list   = ensemble de collectons à traiter.                   * +*                inbuf  = paquet de données où venir puiser les infos.        * +*                outbuf = paquet de données où inscrire les mises à jour.     * +*                db     = base de données à mettre à jour.                    *  *                                                                             *  *  Description : Met à jour les statuts d'activité des éléments.              *  *                                                                             * @@ -1459,18 +1524,14 @@ bool pack_all_collection_updates(GList *list, packed_buffer *pbuf)  *                                                                             *  ******************************************************************************/ -bool update_activity_in_collections(GList *list, packed_buffer *pbuf, sqlite3 *db) +bool update_activity_in_collections(GList *list, packed_buffer *inbuf, packed_buffer *outbuf, sqlite3 *db)  {      bool result;                            /* Résultat global à renvoyer  */      bool status;                            /* Bilan de lecture initiale   */      timestamp_t timestamp;                  /* Horodatage de limite        */ -    timestamp_t inactive;                   /* Date du premier inactif     */ -    GList *remaining;                       /* Eléments restants à traiter */ -    GList *c;                               /* Boucle de parcours #1       */ -    GDbCollection *collec;                  /* Collection à manipuler      */ -    GList *got;                             /* Eléments restants à traiter */ -    GList *i;                               /* Boucle de parcours #2       */ -    GDbItem *item;                          /* Elément collecté à manipuler*/ +    GList *iter;                            /* Boucle de parcours          */ + +    result = true;      /**       * Cette procédure n'est appelée que depuis g_cdb_archive_process(), @@ -1479,55 +1540,19 @@ bool update_activity_in_collections(GList *list, packed_buffer *pbuf, sqlite3 *d       * On a donc l'assurance d'un traitement global homgène des horodatages.       */ -    status = unpack_timestamp(×tamp, pbuf); +    status = unpack_timestamp(×tamp, inbuf);      if (!status) return false; -    inactive = TIMESTAMP_ALL_ACTIVE; - -    remaining = NULL; - -    wlock_collections(list); - -    for (c = g_list_first(list); c != NULL; c = g_list_next(c)) -    { -        collec = G_DB_COLLECTION(c->data); - -        got = g_db_collection_set_last_active(collec, timestamp, &inactive, db); -        remaining = g_list_concat(remaining, got); - -    } - -    gint sort_with_timestamp(GDbItem *a, GDbItem *b) -    { -        return g_db_item_cmp(a, b, false); -    } -    remaining = g_list_sort(remaining, (GCompareFunc)sort_with_timestamp); -    result = true; - -    for (i = g_list_last(remaining); i != NULL && result; i = g_list_previous(i)) +    for (iter = g_list_first(list); +         iter != NULL && result; +         iter = g_list_next(iter))      { -        item = G_DB_ITEM(i->data); - -        for (c = g_list_first(list); c != NULL && result; c = g_list_next(c)) -        { -            collec = G_DB_COLLECTION(c->data); - -            if (g_db_collection_set_inactive(collec, item, &inactive)) -            { -                result = g_db_collection_store_updated_item(collec, item, db); -                break; -            } - -        } +        result = g_db_collection_disable_at(G_DB_COLLECTION(iter->data), timestamp, db, outbuf);      } -    wunlock_collections(list); - -    g_list_free(remaining); -      return result;  } diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index 60e5c26..9539229 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -93,7 +93,7 @@ void g_db_collection_lock_unlock(GDbCollection *, bool, bool);  #define g_db_collection_runlock(col) g_db_collection_lock_unlock(col, false, false);  /* Renvoie la liste des éléments rassemblés. */ -GList *g_db_collection_get_items(const GDbCollection *); +GDbItem **g_db_collection_get_items(const GDbCollection *, size_t *);  /* Détermine si un élément est déjà présent ou non. */  GDbItem *g_db_collection_has_key(GDbCollection *, ...); @@ -104,25 +104,24 @@ bool g_db_collection_has_item(GDbCollection *, GDbItem *);  /* Procède à l'ajout d'un nouvel élément dans la collection. */  bool _g_db_collection_add_item(GDbCollection *, GDbItem *, bool); -/* Procède au retrait d'un nouvel élément dans la collection. */ -bool _g_db_collection_remove_item(GDbCollection *, GDbItem *, bool, bool); +/* Procède au retrait des éléments désactivés de la collection. */ +bool g_db_collection_drop_disabled_items(GDbCollection *, packed_buffer *); -/* Détermine l'horodatage le plus jeune pour une désactivation. */ -timestamp_t _g_db_collection_compute_inactivity_timestamp(GDbCollection *, bool); +/* Procède au retrait d'un élément dans la collection. */ +bool g_db_collection_remove_item(GDbCollection *, const GDbItem *); -/* Met à jour le statut d'activité d'un élément de collection. */ -bool _g_db_collection_update_item_activity(GDbCollection *, GDbItem *, timestamp_t *, bool); +/* Désactive les éléments en aval d'un horodatage donné. */ +bool g_db_collection_disable_at(GDbCollection *, timestamp_t, sqlite3 *, packed_buffer *); -#define g_db_collection_add_item(c, i) _g_db_collection_add_item(c, i, true) -#define g_db_collection_remove_item(c, i) _g_db_collection_remove_item(c, i, true, true) -#define g_db_collection_compute_inactivity_timestamp(c) _g_db_collection_compute_inactivity_timestamp(c, true) -#define g_db_collection_update_item_activity(c, i, t) _g_db_collection_update_item_activity(c, i, t, true) +/* Prend acte d'un changement d'état d'un élément de collection. */ +bool g_db_collection_update_item_state(GDbCollection *, const GDbItem *); -/* Active les éléments en amont d'un horodatage donné. */ -GList *g_db_collection_set_last_active(GDbCollection *, timestamp_t, timestamp_t *, sqlite3 *); -/* Désactive les éléments en aval d'un horodatage donné. */ -bool g_db_collection_set_inactive(GDbCollection *, GDbItem *, timestamp_t *); + + + +#define g_db_collection_add_item(c, i) _g_db_collection_add_item(c, i, true) +//#define g_db_collection_remove_item(c, i) _g_db_collection_remove_item(c, i, true, true) @@ -159,7 +158,7 @@ void lock_unlock_collections(GList *, bool, bool);  bool pack_all_collection_updates(GList *, packed_buffer *);  /* Met à jour les statuts d'activité des éléments. */ -bool update_activity_in_collections(GList *, packed_buffer *, sqlite3 *); +bool update_activity_in_collections(GList *, packed_buffer *, packed_buffer *, sqlite3 *); diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h index 8bba8a3..8c13cd9 100644 --- a/src/analysis/db/item-int.h +++ b/src/analysis/db/item-int.h @@ -111,8 +111,8 @@ struct _GDbItemClass  /* Définition du tronc commun pour les créations SQLite */  #define SQLITE_DB_ITEM_CREATE                   \      SQLITE_TIMESTAMP_CREATE("created") ", "     \ -    SQLITE_TIMESTAMP_CREATE("timestamp") ", "   \ -    SQLITE_RLESTR_CREATE("author") +    SQLITE_RLESTR_CREATE("author") ", "         \ +    "flags INTEGER" diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index efa2cdf..f9c4201 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -462,7 +462,7 @@ bool g_db_item_apply(GDbItem *item, GLoadedBinary *binary)  {      bool result;                            /* Bilan à faire remonter      */ -    assert(g_db_item_is_active(item)); +    assert(!g_db_item_has_flag(item, DIF_DISABLED));      result = G_DB_ITEM_GET_CLASS(item)->apply(item, binary); @@ -491,7 +491,7 @@ bool g_db_item_cancel(GDbItem *item, GLoadedBinary *binary)  {      bool result;                            /* Bilan à faire remonter      */ -    assert(!g_db_item_is_active(item)); +    assert(g_db_item_has_flag(item, DIF_DISABLED));      result = G_DB_ITEM_GET_CLASS(item)->cancel(item, binary); @@ -533,7 +533,7 @@ char *g_db_item_get_label(GDbItem *item)  *                                                                             *  *  Description : Fournit l'horodatage associé à l'élément de collection.      *  *                                                                             * -*  Retour      : Date d'activité de l'élément.                                * +*  Retour      : Date de création de l'élément.                               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             * @@ -541,56 +541,9 @@ char *g_db_item_get_label(GDbItem *item)  timestamp_t g_db_item_get_timestamp(const GDbItem *item)  { -    return item->timestamp; +    timestamp_t result;                     /* Horodatage à retourner      */ -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : item   = élément de collection à mettre à jour.              * -*                binary = binaire chargé en mémoire à modifier.               * -*                first  = horodatage du premier élément désactivé ou NULL.    * -*                                                                             * -*  Description : Active ou désactive un élément de collection en place.       * -*                                                                             * -*  Retour      : Bilan de la mise à jour de l'élément.                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -bool g_db_item_set_activity(GDbItem *item, GLoadedBinary *binary, timestamp_t *first) -{ -    bool result;                            /* Bilan à faire remonter      */ -    bool active;                            /* Etat avant changement       */ - -    active = g_db_item_is_active(item); - -    /* Archivage de l'état */ - -    if (first == NULL) -    { -        assert(!active); -        item->timestamp = item->created; -    } -    else -    { -        assert(active); -        item->timestamp = --(*first); -    } - -    /* Application de l'état */ - -    if (binary != NULL) -    { -        if (active) -            result = g_db_item_cancel(item, binary); -        else -            result = g_db_item_apply(item, binary); -    } -    else -        result = true; +    result = item->created;      return result; @@ -599,19 +552,20 @@ bool g_db_item_set_activity(GDbItem *item, GLoadedBinary *binary, timestamp_t *f  /******************************************************************************  *                                                                             * -*  Paramètres  : item = élément de collection à consulter.                    * +*  Paramètres  : item = base d'éléments à mettre à jour.                      * +*                flag = type de propriété à traiter.                          *  *                                                                             * -*  Description : Indique si l'élément est activé ou désactivé.                * +*  Description : Applique un ensemble de propriétés à un élément.             *  *                                                                             * -*  Retour      : Etat de l'activité de l'élément.                             * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -bool g_db_item_is_active(const GDbItem *item) +void g_db_item_set_flags(GDbItem *item, DbItemFlags flag)  { -    return (cmp_timestamp(&item->created, &item->timestamp) == 0); +    g_atomic_int_set(&item->atomic_flags, flag);  } @@ -684,6 +638,50 @@ DbItemFlags g_db_item_get_flags(const GDbItem *item)  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : item   = élément de collection à mettre à jour.              * +*                binary = binaire chargé en mémoire à modifier.               * +*                                                                             * +*  Description : Active ou désactive un élément de collection en place.       * +*                                                                             * +*  Retour      : Bilan de la mise à jour de l'élément.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_db_item_switch_state(GDbItem *item, GLoadedBinary *binary) +{ +    bool result;                            /* Bilan à faire remonter      */ +    bool enabled;                           /* Etat avant changement       */ + +    enabled = !g_db_item_has_flag(item, DIF_DISABLED); + +    /* Archivage de l'état */ + +    if (enabled) +        g_db_item_add_flag(item, DIF_DISABLED); +    else +        g_db_item_remove_flag(item, DIF_DISABLED); + +    /* Application de l'état */ + +    if (binary != NULL) +    { +        if (enabled) +            result = g_db_item_cancel(item, binary); +        else +            result = g_db_item_apply(item, binary); +    } +    else +        result = true; + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                       MANIPULATIONS AVEC UNE BASE DE DONNEES                       */ @@ -692,6 +690,30 @@ DbItemFlags g_db_item_get_flags(const GDbItem *item)  /******************************************************************************  *                                                                             * +*  Paramètres  : item   = base d'éléments à consulter.                        * +*                values = tableau d'éléments à compléter. [OUT]               * +*                count  = nombre de descriptions renseignées. [OUT]           * +*                                                                             * +*  Description : Décrit les colonnes utiles à un chargement de données.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_db_item_setup_load(const GDbItem *item, bound_value **values, size_t *count) +{ +    *values = NULL; +    *count = 0; + +    return G_DB_ITEM_GET_CLASS(item)->store(NULL, values, count); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : item   = base d'éléments à charger depuis les réponses.      *  *                values = tableau d'éléments à consulter.                     *  *                count  = nombre de descriptions renseignées.                 * @@ -707,14 +729,23 @@ DbItemFlags g_db_item_get_flags(const GDbItem *item)  static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t count)  {      bool result;                            /* Bilan global à retourner    */ +    const bound_value *value;               /* Valeur à intégrer           */      result = load_timestamp(&item->created, "created", values, count);      if (result) -        result = load_timestamp(&item->timestamp, "timestamp", values, count); +        result = load_rle_string(&item->author, "author", values, count);      if (result) -        result = load_rle_string(&item->author, "author", values, count); +    { +        value = find_bound_value(values, count, "flags"); + +        result = (value != NULL && value->type == SQLITE_INTEGER); + +        if (result) +            item->flags = value->integer; + +    }      return result; @@ -763,6 +794,7 @@ bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count)  static bool _g_db_item_store(const GDbItem *item, bound_value **values, size_t *count)  {      bool result;                            /* Bilan à retourner           */ +    bound_value *value;                     /* Valeur à éditer / définir   */      if (item == NULL)          result = store_timestamp(NULL, "created", values, count); @@ -772,17 +804,26 @@ static bool _g_db_item_store(const GDbItem *item, bound_value **values, size_t *      if (result)      {          if (item == NULL) -            result = store_timestamp(NULL, "timestamp", values, count); +            result = store_rle_string(NULL, "author", values, count);          else -            result = store_timestamp(&item->timestamp, "timestamp", values, count); +            result = store_rle_string(&item->author, "author", values, count);      }      if (result)      { -        if (item == NULL) -            result = store_rle_string(NULL, "author", values, count); -        else -            result = store_rle_string(&item->author, "author", values, count); +        *values = realloc(*values, ++(*count) * sizeof(bound_value)); + +        value = &(*values)[*count - 1]; + +        value->cname = "flags"; +        value->built_name = false; +        value->type = SQLITE_INTEGER; + +        value->has_value = (item != NULL); + +        if (value->has_value) +            value->integer = g_db_item_get_flags(item); +      }      return result; diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h index 395a56f..b735fb8 100644 --- a/src/analysis/db/item.h +++ b/src/analysis/db/item.h @@ -48,6 +48,7 @@ typedef enum _DbItemFlags      DIF_UPDATED  = (1 << 1),                /* Mise à jour de l'élément    */      DIF_VOLATILE = (1 << 2),                /* Abscence de sauvegarde      */      DIF_BROKEN   = (1 << 3),                /* Application impossible      */ +    DIF_DISABLED = (1 << 4),                /* Désactivation forcée        */  } DbItemFlags; @@ -109,11 +110,8 @@ char *g_db_item_get_label(GDbItem *);  /* Fournit l'horodatage associé à l'élément de collection. */  timestamp_t g_db_item_get_timestamp(const GDbItem *); -/*  Active ou désactive un élément de collection en place. */ -bool g_db_item_set_activity(GDbItem *, GLoadedBinary *, timestamp_t *); - -/* Indique si l'élément est activé ou désactivé. */ -bool g_db_item_is_active(const GDbItem *); +/* Applique un ensemble de propriétés à un élément. */ +void g_db_item_set_flags(GDbItem *, DbItemFlags);  /* Ajoute une propriété à un élément de base de données. */  void g_db_item_add_flag(GDbItem *, DbItemFlags); @@ -124,11 +122,25 @@ void g_db_item_remove_flag(GDbItem *, DbItemFlags);  /* Indique les propriétés particulières appliquées à l'élément. */  DbItemFlags g_db_item_get_flags(const GDbItem *); +#define g_db_item_has_flag(i, f) \ +    (g_db_item_get_flags(i) & f) + + +////////// +#define g_db_item_is_enabled(i) ((g_db_item_get_flags(i) & DIF_DISABLED) == 0) + + +/* Active ou désactive un élément de collection en place. */ +bool g_db_item_switch_state(GDbItem *, GLoadedBinary *); +  /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +/* Décrit les colonnes utiles à un chargement de données. */ +bool g_db_item_setup_load(const GDbItem *, bound_value **, size_t *); +  /* Charge les valeurs utiles pour un élément de collection. */  bool g_db_item_load(GDbItem *, const bound_value *, size_t); diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 3d66f6b..c1b0fec 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -141,9 +141,6 @@ static void g_bookmark_collection_finalize(GBookmarkCollection *);  /* Crée la table des signets dans une base de données. */  static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_bookmark_collection_setup_load(GBookmarkCollection *, bound_value **, size_t *); -  /* Détermine si un élément est déjà présent ou non. */  static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *, va_list); @@ -796,7 +793,6 @@ static void g_bookmark_collection_class_init(GBookmarkCollectionClass *klass)      collec = G_DB_COLLECTION_CLASS(klass);      collec->create_table = (collec_create_db_table_fc)g_bookmark_collection_create_db_table; -    collec->setup_load = (collec_setup_load_fc)g_bookmark_collection_setup_load;      collec->has_key = (collec_has_key_fc)g_bookmark_collection_has_key;  } @@ -934,39 +930,6 @@ static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *col  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    * -*                values = tableau d'éléments à compléter. [OUT]               * -*                count  = nombre de descriptions renseignées. [OUT]           * -*                                                                             * -*  Description : Décrit les colonnes utiles à un chargement de données.       * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_bookmark_collection_setup_load(GBookmarkCollection *collec, bound_value **values, size_t *count) -{ -    bool status;                            /* Bilan d'une préparation     */ - -    status = G_DB_COLLECTION_CLASS(g_bookmark_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ -                                                                                   values, count); -    if (!status) return false; - -    if (!store_vmpa(NULL, NULL, values, count)) -        return false; - -    if (!store_rle_string(NULL, "comment", values, count)) -        return false; - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : collec = ensemble d'éléments à consulter.                    *  *                ap     = clef identifiant de manière unique un élément.      *  *                                                                             *  *  Description : Détermine si un élément est déjà présent ou non.             * @@ -989,6 +952,7 @@ static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *collec, va_li      ref = va_arg(ap, vmpa2t *); +#if 0      items = g_db_collection_get_items(G_DB_COLLECTION(collec));      for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -1005,6 +969,7 @@ static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *collec, va_li              result = G_DB_ITEM(bm);      } +#endif      return result; diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index a987464..a231749 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -183,9 +183,6 @@ static void g_comment_collection_finalize(GCommentCollection *);  /* Crée la table des commentaires dans une base de données. */  static bool g_comment_collection_create_db_table(const GCommentCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_comment_collection_setup_load(GCommentCollection *, bound_value **, size_t *); -  /* Détermine si un élément est déjà présent ou non. */  static GDbItem *g_comment_collection_has_key(GCommentCollection *, va_list); @@ -995,7 +992,7 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si      if (result)      { -        value = find_bound_value(values, count, "flags"); +        value = find_bound_value(values, count, "lflags");          result = (value != NULL && value->type == SQLITE_INTEGER);          if (result) @@ -1072,16 +1069,20 @@ static bool g_db_comment_store(GDbComment *comment, bound_value **values, size_t      value = &(*values)[*count - 1]; -    value->cname = "flags"; +    value->cname = "lflags";      value->built_name = false;      value->type = SQLITE_INTEGER; -    value->integer = comment->flags; -    value->delete = NULL;      value->has_value = (comment != NULL);      if (value->has_value)      { +        value->integer = comment->flags; +        value->delete = NULL; +    } + +    if (value->has_value) +    {          init_dynamic_rle_string(&text, g_db_comment_get_text(comment));          status = store_rle_string(&text, "text", values, count);          exit_rle_string(&text); @@ -1514,7 +1515,6 @@ static void g_comment_collection_class_init(GCommentCollectionClass *klass)      collec = G_DB_COLLECTION_CLASS(klass);      collec->create_table = (collec_create_db_table_fc)g_comment_collection_create_db_table; -    collec->setup_load = (collec_setup_load_fc)g_comment_collection_setup_load;      collec->has_key = (collec_has_key_fc)g_comment_collection_has_key;  } @@ -1626,7 +1626,7 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle      sql = "CREATE TABLE Comments ("             \               SQLITE_DB_ITEM_CREATE ", "         \               "%s, "                             \ -             "flags INTEGER, "                  \ +             "lflags INTEGER, "                 \               SQLITE_RLESTR_CREATE("text") ", "  \               "inlined INTEGER, "                \               "repeatable INTEGER"               \ @@ -1655,64 +1655,6 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    * -*                values = tableau d'éléments à compléter. [OUT]               * -*                count  = nombre de descriptions renseignées. [OUT]           * -*                                                                             * -*  Description : Décrit les colonnes utiles à un chargement de données.       * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_value **values, size_t *count) -{ -    bool status;                            /* Bilan d'une préparation     */ -    bound_value *value;                     /* Valeur à éditer / définir   */ - -    status = G_DB_COLLECTION_CLASS(g_comment_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ -                                                                                  values, count); -    if (!status) return false; - -    if (!store_vmpa(NULL, NULL, values, count)) -        return false; - -    *count += 1; -    *values = realloc(*values, *count * sizeof(bound_value)); - -    value = &(*values)[*count - 1]; - -    value->cname = "flags"; -    value->built_name = false; -    value->type = SQLITE_INTEGER; - -    if (!store_rle_string(NULL, "text", values, count)) -        return false; - -    *count += 2; -    *values = realloc(*values, *count * sizeof(bound_value)); - -    value = &(*values)[*count - 2]; - -    value->cname = "inlined"; -    value->built_name = false; -    value->type = SQLITE_BOOLEAN; - -    value = &(*values)[*count - 1]; - -    value->cname = "repeatable"; -    value->built_name = false; -    value->type = SQLITE_BOOLEAN; - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : collec = ensemble d'éléments à consulter.                    *  *                ap     = clef identifiant de manière unique un élément.      *  *                                                                             *  *  Description : Détermine si un élément est déjà présent ou non.             * @@ -1735,6 +1677,7 @@ static GDbItem *g_comment_collection_has_key(GCommentCollection *collec, va_list      ref = va_arg(ap, vmpa2t *); +#if 0      items = g_db_collection_get_items(G_DB_COLLECTION(collec));      for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -1751,6 +1694,7 @@ static GDbItem *g_comment_collection_has_key(GCommentCollection *collec, va_list              result = G_DB_ITEM(bm);      } +#endif      return result; diff --git a/src/analysis/db/items/move.c b/src/analysis/db/items/move.c index a5d2773..afc3331 100644 --- a/src/analysis/db/items/move.c +++ b/src/analysis/db/items/move.c @@ -136,9 +136,6 @@ static void g_move_collection_finalize(GMoveCollection *);  /* Crée la table des basculements dans une base de données. */  static bool g_move_collection_create_db_table(const GMoveCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_move_collection_setup_load(GMoveCollection *, bound_value **, size_t *); -  /* Détermine si un élément est déjà présent ou non. */  static GDbItem *g_move_collection_has_key(GMoveCollection *, va_list); @@ -638,7 +635,6 @@ static void g_move_collection_class_init(GMoveCollectionClass *klass)      collec = G_DB_COLLECTION_CLASS(klass);      collec->create_table = (collec_create_db_table_fc)g_move_collection_create_db_table; -    collec->setup_load = (collec_setup_load_fc)g_move_collection_setup_load;      collec->has_key = (collec_has_key_fc)g_move_collection_has_key;  } @@ -779,40 +775,6 @@ static bool g_move_collection_create_db_table(const GMoveCollection *collec, sql  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    * -*                values = tableau d'éléments à compléter. [OUT]               * -*                count  = nombre de descriptions renseignées. [OUT]           * -*                                                                             * -*  Description : Décrit les colonnes utiles à un chargement de données.       * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_move_collection_setup_load(GMoveCollection *collec, bound_value **values, size_t *count) -{ -    bool status;                            /* Bilan d'une préparation     */ - -    status = G_DB_COLLECTION_CLASS(g_move_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ -                                                                                   values, count); -    if (!status) return false; - -    if (!g_binary_cursor_store(NULL, "src", values, count)) -        return false; - -    if (!g_binary_cursor_store(NULL, "dest", values, count)) -        return false; - -    return true; - - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : collec = ensemble d'éléments à consulter.                    *  *                ap     = clef identifiant de manière unique un élément.      *  *                                                                             *  *  Description : Détermine si un élément est déjà présent ou non.             * @@ -835,6 +797,7 @@ static GDbItem *g_move_collection_has_key(GMoveCollection *collec, va_list ap)      ref = va_arg(ap, const GLineCursor *); +#if 0      items = g_db_collection_get_items(G_DB_COLLECTION(collec));      for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -851,6 +814,7 @@ static GDbItem *g_move_collection_has_key(GMoveCollection *collec, va_list ap)              result = G_DB_ITEM(bm);      } +#endif      return result; diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c index 043effd..94d4940 100644 --- a/src/analysis/db/items/switcher.c +++ b/src/analysis/db/items/switcher.c @@ -136,9 +136,6 @@ static void g_switcher_collection_finalize(GSwitcherCollection *);  /* Crée la table des basculements dans une base de données. */  static bool g_switcher_collection_create_db_table(const GSwitcherCollection *, sqlite3 *); -/* Décrit les colonnes utiles à un chargement de données. */ -static bool g_switcher_collection_setup_load(GSwitcherCollection *, bound_value **, size_t *); -  /* Détermine si un élément est déjà présent ou non. */  static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *, va_list); @@ -790,7 +787,6 @@ static void g_switcher_collection_class_init(GSwitcherCollectionClass *klass)      collec = G_DB_COLLECTION_CLASS(klass);      collec->create_table = (collec_create_db_table_fc)g_switcher_collection_create_db_table; -    collec->setup_load = (collec_setup_load_fc)g_switcher_collection_setup_load;      collec->has_key = (collec_has_key_fc)g_switcher_collection_has_key;  } @@ -929,53 +925,6 @@ static bool g_switcher_collection_create_db_table(const GSwitcherCollection *col  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    * -*                values = tableau d'éléments à compléter. [OUT]               * -*                count  = nombre de descriptions renseignées. [OUT]           * -*                                                                             * -*  Description : Décrit les colonnes utiles à un chargement de données.       * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_value **values, size_t *count) -{ -    bool status;                            /* Bilan d'une préparation     */ -    bound_value *value;                     /* Valeur à éditer / définir   */ - -    status = G_DB_COLLECTION_CLASS(g_switcher_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ -                                                                                   values, count); -    if (!status) return false; - -    if (!store_vmpa(NULL, NULL, values, count)) -        return false; - -    *count += 2; -    *values = realloc(*values, *count * sizeof(bound_value)); - -    value = &(*values)[*count - 2]; - -    value->cname = "op_index"; -    value->built_name = false; -    value->type = SQLITE_INTEGER; - -    value = &(*values)[*count - 1]; - -    value->cname = "type"; -    value->built_name = false; -    value->type = SQLITE_INTEGER; - -    return true; - - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : collec = ensemble d'éléments à consulter.                    *  *                ap     = clef identifiant de manière unique un élément.      *  *                                                                             *  *  Description : Détermine si un élément est déjà présent ou non.             * @@ -998,6 +947,7 @@ static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_li      ref = va_arg(ap, vmpa2t *); +#if 0      items = g_db_collection_get_items(G_DB_COLLECTION(collec));      for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) @@ -1014,6 +964,7 @@ static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_li              result = G_DB_ITEM(bm);      } +#endif      return result; diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h index eba0fa7..4ff714e 100644 --- a/src/analysis/db/misc/timestamp.h +++ b/src/analysis/db/misc/timestamp.h @@ -39,8 +39,8 @@ typedef uint64_t timestamp_t;  /* Valeurs particulières */ -#define TIMESTAMP_ALL_ACTIVE 0 -#define TIMESTAMP_ALL_INACTIVE 1 +#define TIMESTAMP_ALL_ACTIVE 0      // REMME +#define TIMESTAMP_ALL_INACTIVE 1    // REMME  /* Obtient un horodatage initialisé au moment même. */ diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 5c3eed6..d429530 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -95,7 +95,6 @@ typedef enum _DBAction  {      DBA_ADD_ITEM,                           /* Ajout d'un élément          */      DBA_REM_ITEM,                           /* Suppression d'un élément    */ -      DBA_CHANGE_STATE,                       /* Changement d'activité       */      DBA_COUNT @@ -186,16 +185,16 @@ typedef enum _DBCommand       * avec une série de paquets de la forme :       *       *    [ Traitement de collection : DBC_COLLECTION   ] -     *    [ Action : DBC_SET_LAST_ACTIVE                ] +     *    [ Action : DBA_CHANGE_STATE                   ]       *    [ <élément dont le statut a évolué>           ]       *       * Les traitements se réalisent dans : -     *  - g_db_collection_set_last_active() pour la partie serveur. -     *  - g_db_client_set_last_active() pour la partie client. +     *  - g_db_collection_disable_at() pour la partie serveur. +     *  - g_db_collection_update_item_state() pour la partie client.       *       */ -    DBC_SET_LAST_ACTIVE,                    /* Définition du dernier actif */ +    DBC_SET_LAST_ACTIVE,                    /* Définition du dernier actif */   // REMME      DBC_COUNT diff --git a/src/core/collections.c b/src/core/collections.c index a047a15..34b7bc1 100644 --- a/src/core/collections.c +++ b/src/core/collections.c @@ -114,11 +114,11 @@ bool load_hard_coded_collection_definitions(void)      REGISTER_COLLECTION(G_TYPE_BM_COLLECTION, DBF_BOOKMARKS); -    REGISTER_COLLECTION(G_TYPE_COMMENT_COLLECTION, DBF_COMMENTS); +    //REGISTER_COLLECTION(G_TYPE_COMMENT_COLLECTION, DBF_COMMENTS); -    REGISTER_COLLECTION(G_TYPE_MOVE_COLLECTION, DBF_MOVES); +    //REGISTER_COLLECTION(G_TYPE_MOVE_COLLECTION, DBF_MOVES); -    REGISTER_COLLECTION(G_TYPE_SWITCHER_COLLECTION, DBF_DISPLAY_SWITCHERS); +    //REGISTER_COLLECTION(G_TYPE_SWITCHER_COLLECTION, DBF_DISPLAY_SWITCHERS);      return true; diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c index f4b0712..01f24e8 100644 --- a/src/gui/menus/edition.c +++ b/src/gui/menus/edition.c @@ -722,7 +722,7 @@ static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar)      exist = NULL;//g_db_collection_has_key(collec, &addr);      if (exist != NULL) -        g_loaded_binary_remove_from_collection(binary, DBF_BOOKMARKS, exist); +        ;//g_loaded_binary_remove_from_collection(binary, DBF_BOOKMARKS, exist);      else      { @@ -746,7 +746,10 @@ static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar)                                            "Do you want to replace it ?"));                  if (ret != GTK_RESPONSE_YES) +                { +                    g_object_unref(G_OBJECT(bookmark));                      goto mcb_ebt_add_finish; +                }              } diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c index f32f9f5..ebe1f62 100644 --- a/src/gui/panels/bookmarks.c +++ b/src/gui/panels/bookmarks.c @@ -473,12 +473,13 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary      g_db_collection_rlock(collec); +    /*      items = g_db_collection_get_items(collec);      for (b = g_list_first(items); b != NULL; b = g_list_next(b))      {          bookmark = G_DB_BOOKMARK(b->data); -        if (!g_db_item_is_active(G_DB_ITEM(bookmark))) continue; +        if (!g_db_item_is_enabled(G_DB_ITEM(bookmark))) continue;          addr = g_db_bookmark_get_address(bookmark); @@ -500,6 +501,7 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary                             -1);      } +    */      g_db_collection_runlock(collec); @@ -543,7 +545,7 @@ static void on_collection_content_changed(GDbCollection *collec, DBAction action      store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store")); -    if (action == DBA_ADD_ITEM || (action == DBA_CHANGE_STATE && g_db_item_is_active(G_DB_ITEM(bookmark)))) +    if (action == DBA_ADD_ITEM || (action == DBA_CHANGE_STATE && g_db_item_is_enabled(G_DB_ITEM(bookmark))))      {          proc = g_loaded_binary_get_processor(panel->binary);          msize = g_arch_processor_get_memory_size(proc); @@ -568,7 +570,7 @@ static void on_collection_content_changed(GDbCollection *collec, DBAction action      } -    else /*if (action == DBA_CHANGE_STATE && g_db_item_is_active(G_DB_ITEM(bookmark)))*/ +    else /*if (action == DBA_CHANGE_STATE && g_db_item_is_enabled(G_DB_ITEM(bookmark)))*/      {          model = GTK_TREE_MODEL(store); @@ -1183,7 +1185,7 @@ static void mcb_bookmarks_panel_delete(GtkMenuItem *menuitem, GBookmarksPanel *p      mark = get_selected_panel_bookmark(treeview, NULL);      if (mark == NULL) return; -    g_loaded_binary_remove_from_collection(panel->binary, DBF_BOOKMARKS, G_DB_ITEM(mark)); +    //g_loaded_binary_remove_from_collection(panel->binary, DBF_BOOKMARKS, G_DB_ITEM(mark));      g_object_unref(G_OBJECT(mark)); diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c index 57e6a14..df3fde1 100644 --- a/src/gui/panels/history.c +++ b/src/gui/panels/history.c @@ -330,6 +330,7 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo      {          g_db_collection_rlock(collections[k]); +        /*          items = g_db_collection_get_items(collections[k]);          for (i = g_list_first(items); i != NULL; i = g_list_next(i)) @@ -342,13 +343,14 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo              gtk_list_store_set(store, &iter,                                 HTC_ITEM, item,                                 //HTC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, -                               HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", +                               HTC_FOREGROUND, g_db_item_is_enabled(item) ? NULL : "grey",                                 HTC_LABEL, label,                                 -1);              free(label);          } +        */          //g_signal_connect_to_main(collections[k], "content-changed", G_CALLBACK(on_history_changed), panel,          //                         g_cclosure_user_marshal_VOID__ENUM_OBJECT); @@ -440,7 +442,7 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem *              gtk_list_store_set(store, &iter,                                 HTC_ITEM, item,                                 //HTC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, -                               HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", +                               HTC_FOREGROUND, g_db_item_is_enabled(item) ? NULL : "grey",                                 HTC_LABEL, label,                                 -1); @@ -459,7 +461,7 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem *              if (find_changed_item(model, item, &iter))                  gtk_list_store_set(store, &iter, -                                   HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", +                                   HTC_FOREGROUND, g_db_item_is_enabled(item) ? NULL : "grey",                                     -1);              break; @@ -480,7 +482,7 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem *              gtk_tree_model_get(_model, _iter, HTC_ITEM, &item, -1); -            active = g_db_item_is_active(item); +            active = g_db_item_is_enabled(item);              g_object_unref(G_OBJECT(item)); @@ -566,10 +568,10 @@ static void on_history_selection_change(GtkTreeSelection *selection, GHistoryPan          gtk_tree_model_get(model, &iter, HTC_ITEM, &item, -1);          button = GTK_WIDGET(gtk_builder_get_object(builder, "undo")); -        gtk_widget_set_sensitive(button, g_db_item_is_active(item)); +        gtk_widget_set_sensitive(button, g_db_item_is_enabled(item));          button = GTK_WIDGET(gtk_builder_get_object(builder, "redo")); -        gtk_widget_set_sensitive(button, !g_db_item_is_active(item)); +        gtk_widget_set_sensitive(button, !g_db_item_is_enabled(item));          g_object_unref(G_OBJECT(item)); | 
