summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/pychrysalide/analysis/db/client.c137
-rw-r--r--src/analysis/db/cdb.c21
-rw-r--r--src/analysis/db/client.c185
-rw-r--r--src/analysis/db/client.h3
-rw-r--r--src/analysis/db/misc/rlestr.c2
-rw-r--r--src/analysis/db/misc/snapshot.c78
-rw-r--r--src/analysis/db/misc/snapshot.h14
-rw-r--r--src/analysis/db/misc/timestamp.c19
-rw-r--r--src/analysis/db/misc/timestamp.h3
-rw-r--r--src/analysis/db/protocol.h31
-rw-r--r--src/analysis/db/snapshot.c63
-rw-r--r--src/analysis/db/snapshot.h3
-rw-r--r--src/common/packed.c110
-rw-r--r--src/common/packed.h6
14 files changed, 633 insertions, 42 deletions
diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c
index afece26..f9ce001 100644
--- a/plugins/pychrysalide/analysis/db/client.c
+++ b/plugins/pychrysalide/analysis/db/client.c
@@ -25,6 +25,7 @@
#include "client.h"
+#include <assert.h>
#include <pygobject.h>
@@ -36,6 +37,7 @@
#include "collection.h"
#include "../../access.h"
#include "../../helpers.h"
+#include "../../struct.h"
@@ -54,6 +56,9 @@ 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 *);
+/* Fournit la liste des instantanés existants. */
+static PyObject *py_hub_client_get_snapshots(PyObject *, void *);
+
/* Fournit l'identifiant de l'instantané courant. */
static PyObject *py_hub_client_get_current_snapshot(PyObject *, void *);
@@ -338,6 +343,137 @@ static PyObject *py_hub_client_set_last_active(PyObject *self, PyObject *args)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
+* Description : Fournit la liste des instantanés existants. *
+* *
+* Retour : Liste d'instantanés ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_hub_client_get_snapshots(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GHubClient *client; /* Version native du serveur */
+ snapshot_info_t *info; /* Liste d'instantanés présents*/
+ size_t count; /* Taille de cette liste */
+ bool status; /* Validité de cet identifiant */
+ PyTypeObject *base; /* Modèle d'objet à créer */
+ size_t i; /* Boucle de parcours */
+ PyObject *item; /* Nouvelle description */
+ char *text; /* Valeur textuelle à placer */
+ PyObject *attrib; /* Attribut à constituer */
+ int ret; /* Bilan d'une mise en place */
+ bool failed; /* Détection d'une erreur */
+
+#define HUB_CLIENT_SNAPSHOTS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ snapshots, py_hub_client, \
+ "List of all existing snapshots, provided as a tuple of pychrysalide.PyStructObject." \
+ "\n" \
+ "Each snapshot is characterised by the following properties :\n" \
+ "* parent_id : identifier of the parent snapshot;\n" \
+ "* id : identifier of the snapshot;\n" \
+ "* created : timestamp of the creation date;\n" \
+ "* name : name of the snapshot, or None;\n" \
+ "* desc : description of the snapshot, or None." \
+)
+
+ client = G_HUB_CLIENT(pygobject_get(self));
+
+ status = g_hub_client_get_snapshots(client, &info, &count);
+
+ if (status)
+ {
+ result = PyTuple_New(count);
+
+ base = get_python_py_struct_type();
+
+ failed = false;
+
+ for (i = 0; i < count; i++)
+ {
+ item = PyObject_CallFunction((PyObject *)base, NULL);
+ assert(item != NULL);
+
+ text = snapshot_id_as_string(get_snapshot_info_parent_id(&info[i]));
+ attrib = PyUnicode_FromString(text);
+ ret = PyDict_SetItemString(item, "parent_id", attrib);
+ if (ret != 0) break;
+
+ text = snapshot_id_as_string(get_snapshot_info_id(&info[i]));
+ attrib = PyUnicode_FromString(text);
+ ret = PyDict_SetItemString(item, "id", attrib);
+ if (ret != 0) break;
+
+ attrib = PyLong_FromUnsignedLongLong(get_snapshot_info_created(&info[i]));
+ ret = PyDict_SetItemString(item, "created", attrib);
+ if (ret != 0) break;
+
+ text = get_snapshot_info_name(&info[i]);
+
+ if (text != NULL)
+ attrib = PyUnicode_FromString(text);
+ else
+ {
+ attrib = Py_None;
+ Py_INCREF(attrib);
+ }
+
+ ret = PyDict_SetItemString(item, "name", attrib);
+ if (ret != 0) break;
+
+ text = get_snapshot_info_desc(&info[i]);
+
+ if (text != NULL)
+ attrib = PyUnicode_FromString(text);
+ else
+ {
+ attrib = Py_None;
+ Py_INCREF(attrib);
+ }
+
+ ret = PyDict_SetItemString(item, "desc", attrib);
+ if (ret != 0) break;
+
+ PyTuple_SetItem(result, i, item);
+
+ }
+
+ failed = (i < count);
+
+ for (i = 0; i < count; i++)
+ exit_snapshot_info(&info[i]);
+
+ free(info);
+
+ if (failed)
+ goto on_failure;
+
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+ on_failure:
+
+ Py_DECREF(result);
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
* Description : Fournit l'identifiant de l'instantané courant. *
* *
* Retour : Identifiant d'instantané ou None. *
@@ -452,6 +588,7 @@ PyTypeObject *get_python_hub_client_type(void)
};
static PyGetSetDef py_hub_client_getseters[] = {
+ HUB_CLIENT_SNAPSHOTS_ATTRIB,
HUB_CLIENT_CURRENT_SNAPSHOT_ATTRIB,
{ NULL }
};
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 8e8813a..2df556b 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -1003,6 +1003,27 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
break;
+ case DBC_GET_SNAPSHOTS:
+
+ init_packed_buffer(&out_pbuf);
+
+ status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SNAPSHOTS_UPDATED },
+ sizeof(uint32_t), true);
+ if (!status) goto gcap_bad_reply;
+
+ status = g_db_snapshot_pack_all(archive->snapshot, &out_pbuf);
+ if (!status) goto gcap_bad_reply;
+
+ status = extend_packed_buffer(&out_pbuf, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ, false);
+ 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;
+
case DBC_GET_CUR_SNAPSHOT:
init_packed_buffer(&out_pbuf);
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index 3372c74..2cab655 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -25,6 +25,7 @@
#include <assert.h>
+#include <malloc.h>
#include <netdb.h>
#include <poll.h>
#include <stdio.h>
@@ -76,11 +77,13 @@ struct _GHubClient
bool can_get_updates; /* Réception de maj possibles ?*/
GThread *update; /* Procédure de traitement */
-
-
+ snapshot_info_t *snapshots; /* Liste des instantanés */
+ size_t snap_count; /* Taille de cette liste */
+ GMutex snap_lock; /* Concurrence des accès */
snapshot_id_t current; /* Instantané courant */
bool has_current; /* Validité de l'identifiant */
+ GMutex cur_lock; /* Concurrence des accès */
};
@@ -110,6 +113,9 @@ static bool g_hub_client_start_common(GHubClient *, char *);
/* Assure l'accueil des nouvelles mises à jour. */
static void *g_hub_client_update(GHubClient *);
+/* Met à jour la liste des instantanés courants. */
+static bool g_hub_client_update_snapshots(GHubClient *, packed_buffer *);
+
/* Identifie le canal de communication pour envois au serveur. */
static SSL *g_hub_client_get_ssl_fd(GHubClient *);
@@ -160,6 +166,9 @@ static void g_hub_client_class_init(GHubClientClass *klass)
static void g_hub_client_init(GHubClient *client)
{
+ init_static_rle_string(&client->hash, NULL);
+ client->collections = NULL;
+
client->working = NULL;
client->tls_ctx = NULL;
@@ -168,7 +177,16 @@ static void g_hub_client_init(GHubClient *client)
client->tls_fd = NULL;
client->desc = NULL;
+ g_mutex_init(&client->sending_lock);
+ client->can_get_updates = false;
+ client->update = NULL;
+
+ client->snapshots = NULL;
+ client->snap_count = 0;
+ g_mutex_init(&client->snap_lock);
+
client->has_current = false;
+ g_mutex_init(&client->cur_lock);
}
@@ -189,6 +207,12 @@ static void g_hub_client_dispose(GHubClient *client)
{
g_hub_client_stop(client);
+ g_mutex_clear(&client->cur_lock);
+
+ g_mutex_clear(&client->snap_lock);
+
+ g_mutex_clear(&client->sending_lock);
+
G_OBJECT_CLASS(g_hub_client_parent_class)->dispose(G_OBJECT(client));
}
@@ -208,18 +232,28 @@ static void g_hub_client_dispose(GHubClient *client)
static void g_hub_client_finalize(GHubClient *client)
{
+ size_t i; /* Boucle de parcours */
+
unset_rle_string(&client->hash);
if (client->working != NULL)
free(client->working);
assert(client->tls_ctx == NULL);
-
assert(client->tls_fd == NULL);
if (client->desc != NULL)
free(client->desc);
+ if (client->snapshots != NULL)
+ {
+ for (i = 0; i < client->snap_count; i++)
+ exit_snapshot_info(&client->snapshots[i]);
+
+ free(client->snapshots);
+
+ }
+
G_OBJECT_CLASS(g_hub_client_parent_class)->finalize(G_OBJECT(client));
}
@@ -703,6 +737,13 @@ static void *g_hub_client_update(GHubClient *client)
init_packed_buffer(&out_pbuf);
+ status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_SNAPSHOTS }, sizeof(uint32_t), true);
+ if (!status)
+ {
+ exit_packed_buffer(&out_pbuf);
+ goto exit;
+ }
+
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_CUR_SNAPSHOT }, sizeof(uint32_t), true);
if (!status)
{
@@ -814,6 +855,13 @@ static void *g_hub_client_update(GHubClient *client)
client->can_get_updates = (tmp8 == 0x1);
break;
+ case DBC_SNAPSHOTS_UPDATED:
+
+ status = g_hub_client_update_snapshots(client, &in_pbuf);
+ if (!status) goto gdcu_bad_exchange;
+
+ break;
+
case DBC_GET_CUR_SNAPSHOT:
log_variadic_message(LMT_INFO,
_("This command is not available on this side: 0x%08x"), command);
@@ -825,9 +873,13 @@ static void *g_hub_client_update(GHubClient *client)
status = unpack_snapshot_id(&id, &in_pbuf);
if (!status) goto gdcu_bad_exchange;
+ g_mutex_lock(&client->cur_lock);
+
copy_snapshot_id(&client->current, &id);
client->has_current = true;
+ g_mutex_unlock(&client->cur_lock);
+
break;
case DBC_SET_CUR_SNAPSHOT:
@@ -872,6 +924,82 @@ static void *g_hub_client_update(GHubClient *client)
/******************************************************************************
* *
* Paramètres : client = client pour les accès distants à manipuler. *
+* pbuf = données présentes à traiter. *
+* *
+* Description : Met à jour la liste des instantanés courants. *
+* *
+* Retour : true si la liste retournée est valide, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_hub_client_update_snapshots(GHubClient *client, packed_buffer *pbuf)
+{
+ bool result; /* Validité à retourner */
+ size_t i; /* Boucle de parcours */
+ char id[SNAP_ID_HEX_SZ]; /* Caractères hexadécimaux */
+ snapshot_info_t info; /* Description d'instantané */
+ snapshot_info_t *dest; /* Destination de description */
+
+ result = true;
+
+ g_mutex_lock(&client->snap_lock);
+
+ if (client->snapshots != NULL)
+ {
+ for (i = 0; i < client->snap_count; i++)
+ exit_snapshot_info(&client->snapshots[i]);
+
+ free(client->snapshots);
+
+ client->snapshots = NULL;
+ client->snap_count = 0;
+
+ }
+
+ do
+ {
+ result = peek_packed_buffer(pbuf, id, SNAP_ID_HEX_SZ, false);
+ if (!result) break;
+
+ if (strncmp(id, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ) == 0)
+ {
+ advance_packed_buffer(pbuf, SNAP_ID_HEX_SZ);
+ break;
+ }
+
+ else
+ {
+ setup_empty_snapshot_info(&info);
+
+ result = unpack_snapshot_info(&info, pbuf);
+ if (!result) break;
+
+ client->snapshots = realloc(client->snapshots, ++client->snap_count * sizeof(snapshot_info_t));
+
+ dest = &client->snapshots[client->snap_count - 1];
+
+ setup_empty_snapshot_info(dest);
+ copy_snapshot_info(dest, &info);
+
+ exit_snapshot_info(&info);
+
+ }
+
+ }
+ while (true);
+
+ g_mutex_unlock(&client->snap_lock);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = client pour les accès distants à manipuler. *
* *
* Description : Arrête la connexion à la base de données. *
* *
@@ -1135,6 +1263,53 @@ bool g_hub_client_set_last_active(GHubClient *client, timestamp_t timestamp)
/******************************************************************************
* *
* Paramètres : client = client pour les accès distants à manipuler. *
+* info = description des instantanés présents. [OUT] *
+* count = taille de la liste retournée. [OUT] *
+* *
+* Description : Fournit la liste des instantanés existants. *
+* *
+* Retour : true si la liste retournée est valide, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_hub_client_get_snapshots(GHubClient *client, snapshot_info_t **info, size_t *count)
+{
+ bool result; /* Validité à retourner */
+ size_t i; /* Boucle de parcours */
+ snapshot_info_t *dest; /* Destination de description */
+
+ g_mutex_lock(&client->snap_lock);
+
+ result = (client->snap_count > 0);
+
+ if (result)
+ {
+ *info = malloc(client->snap_count * sizeof(snapshot_info_t));
+ *count = client->snap_count;
+
+ for (i = 0; i < client->snap_count; i++)
+ {
+ dest = &(*info)[i];
+
+ setup_empty_snapshot_info(dest);
+ copy_snapshot_info(dest, &client->snapshots[i]);
+
+ }
+
+ }
+
+ g_mutex_unlock(&client->snap_lock);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = client pour les accès distants à manipuler. *
* id = identifiant d'instantané à renseigner. [OUT] *
* *
* Description : Fournit l'identifiant de l'instantané courant. *
@@ -1149,11 +1324,15 @@ bool g_hub_client_get_current_snapshot(GHubClient *client, snapshot_id_t *id)
{
bool result; /* Validité à retourner */
+ g_mutex_lock(&client->cur_lock);
+
result = client->has_current;
if (result)
copy_snapshot_id(id, &client->current);
+ g_mutex_unlock(&client->cur_lock);
+
return result;
}
diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h
index 36d24e6..039631e 100644
--- a/src/analysis/db/client.h
+++ b/src/analysis/db/client.h
@@ -74,6 +74,9 @@ bool g_hub_client_add_item(GHubClient *, const GDbItem *);
/* Active les éléments en amont d'un horodatage donné. */
bool g_hub_client_set_last_active(GHubClient *, timestamp_t);
+/* Fournit la liste des instantanés existants. */
+bool g_hub_client_get_snapshots(GHubClient *, snapshot_info_t **, size_t *);
+
/* Fournit l'identifiant de l'instantané courant. */
bool g_hub_client_get_current_snapshot(GHubClient *, snapshot_id_t *);
diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c
index 0fe182b..c1cc866 100644
--- a/src/analysis/db/misc/rlestr.c
+++ b/src/analysis/db/misc/rlestr.c
@@ -286,7 +286,7 @@ bool unpack_rle_string(rle_string *str, packed_buffer *pbuf)
if (result && str->length > 0)
{
- str->data = (char *)malloc(str->length + 1);
+ str->data = malloc(str->length + 1);
str->dynamic = true;
result = extract_packed_buffer(pbuf, str->data, str->length + 1, false);
diff --git a/src/analysis/db/misc/snapshot.c b/src/analysis/db/misc/snapshot.c
index 546191b..9aa096f 100644
--- a/src/analysis/db/misc/snapshot.c
+++ b/src/analysis/db/misc/snapshot.c
@@ -41,6 +41,25 @@
* *
* Paramètres : id = identifiant d'instantané à initialiser. [OUT] *
* *
+* Description : Prépare un identifiant pour instantané à une définition. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void setup_empty_snapshot_id(snapshot_id_t *id)
+{
+ memset(id, 0, sizeof(snapshot_id_t));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : id = identifiant d'instantané à initialiser. [OUT] *
+* *
* Description : Construit un identifiant pour instantané de base de données. *
* *
* Retour : Bilan de l'opération. *
@@ -214,6 +233,32 @@ bool pack_snapshot_id(const snapshot_id_t *id, packed_buffer *pbuf)
* *
* Paramètres : info = description d'instantané à initialiser. [OUT] *
* *
+* Description : Prépare une description pour instantané à une définition. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void setup_empty_snapshot_info(snapshot_info_t *info)
+{
+ setup_empty_snapshot_id(&info->parent_id);
+
+ setup_empty_snapshot_id(&info->id);
+
+ setup_empty_timestamp(&info->created);
+
+ info->name = NULL;
+ info->desc = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = description d'instantané à initialiser. [OUT] *
+* *
* Description : Construit une description pour instantané de base de données.*
* *
* Retour : Bilan de l'opération. *
@@ -226,7 +271,10 @@ bool init_snapshot_info(snapshot_info_t *info)
{
bool result; /* Bilan à retourner */
- result = init_snapshot_id(&info->id);
+ result = init_snapshot_id_from_text(&info->parent_id, NO_SNAPSHOT_ROOT);
+
+ if (result)
+ result = init_snapshot_id(&info->id);
if (result)
result = init_timestamp(&info->created);
@@ -262,7 +310,10 @@ bool init_snapshot_info_from_text(snapshot_info_t *info, const char *id, uint64_
{
bool result; /* Bilan à retourner */
- result = init_snapshot_id_from_text(&info->id, id);
+ result = init_snapshot_id_from_text(&info->parent_id, NO_SNAPSHOT_ROOT);
+
+ if (result)
+ result = init_snapshot_id_from_text(&info->id, id);
if (result)
result = init_timestamp_from_value(&info->created, created);
@@ -332,6 +383,8 @@ void copy_snapshot_info(snapshot_info_t *dest, const snapshot_info_t *src)
{
exit_snapshot_info(dest);
+ copy_snapshot_id(&dest->parent_id, &src->parent_id);
+
copy_snapshot_id(&dest->id, &src->id);
copy_timestamp(&dest->created, &src->created);
@@ -362,19 +415,26 @@ bool unpack_snapshot_info(snapshot_info_t *info, packed_buffer *pbuf)
{
bool result; /* Bilan à retourner */
rle_string string; /* Chaîne à transmettre */
+ const char *text; /* Valeur textuelle obtenue */
- result = unpack_snapshot_id(&info->id, pbuf);
+ result = unpack_snapshot_id(&info->parent_id, pbuf);
+
+ if (result)
+ result = unpack_snapshot_id(&info->id, pbuf);
if (result)
result = unpack_timestamp(&info->created, pbuf);
if (result)
{
+ init_static_rle_string(&string, NULL);
+
result = unpack_rle_string(&string, pbuf);
if (result)
{
- info->name = strdup(get_rle_string(&string));
+ text = get_rle_string(&string);
+ info->name = (text != NULL ? strdup(text) : NULL);
exit_rle_string(&string);
}
@@ -382,11 +442,14 @@ bool unpack_snapshot_info(snapshot_info_t *info, packed_buffer *pbuf)
if (result)
{
+ init_static_rle_string(&string, NULL);
+
result = unpack_rle_string(&string, pbuf);
if (result)
{
- info->desc = strdup(get_rle_string(&string));
+ text = get_rle_string(&string);
+ info->desc = (text != NULL ? strdup(text) : NULL);
exit_rle_string(&string);
}
@@ -415,7 +478,10 @@ bool pack_snapshot_info(const snapshot_info_t *info, packed_buffer *pbuf)
bool result; /* Bilan à retourner */
rle_string string; /* Chaîne à transmettre */
- result = pack_snapshot_id(&info->id, pbuf);
+ result = pack_snapshot_id(&info->parent_id, pbuf);
+
+ if (result)
+ result = pack_snapshot_id(&info->id, pbuf);
if (result)
result = pack_timestamp(&info->created, pbuf);
diff --git a/src/analysis/db/misc/snapshot.h b/src/analysis/db/misc/snapshot.h
index 37fad7f..8f9a598 100644
--- a/src/analysis/db/misc/snapshot.h
+++ b/src/analysis/db/misc/snapshot.h
@@ -49,6 +49,13 @@ typedef struct _snapshot_id_t
} snapshot_id_t;
+/* Identifiant d'un parent de racine */
+#define NO_SNAPSHOT_ROOT "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+
+
+/* Prépare un identifiant pour instantané à une définition. */
+void setup_empty_snapshot_id(snapshot_id_t *);
+
/* Construit un identifiant pour instantané de base de données. */
bool init_snapshot_id(snapshot_id_t *);
@@ -77,6 +84,7 @@ bool pack_snapshot_id(const snapshot_id_t *, packed_buffer *);
/* Description d'un instantané */
typedef struct _snapshot_info_t
{
+ snapshot_id_t parent_id; /* Identifiant du propriétaire */
snapshot_id_t id; /* Identifiant attribué */
timestamp_t created; /* Date de création */
@@ -87,6 +95,9 @@ typedef struct _snapshot_info_t
} snapshot_info_t;
+/* Prépare une description pour instantané à une définition. */
+void setup_empty_snapshot_info(snapshot_info_t *);
+
/* Construit une description pour instantané de base de données. */
bool init_snapshot_info(snapshot_info_t *);
@@ -96,8 +107,9 @@ bool init_snapshot_info_from_text(snapshot_info_t *, const char *, uint64_t, con
/* Libère la mémoire occupée par une description d'instantané. */
void exit_snapshot_info(snapshot_info_t *);
+#define get_snapshot_info_parent_id(nfo) &(nfo)->parent_id
#define get_snapshot_info_id(nfo) &(nfo)->id
-#define get_snapshot_info_creation(nfo) (nfo)->created
+#define get_snapshot_info_created(nfo) (nfo)->created
#define get_snapshot_info_name(nfo) (nfo)->name
#define get_snapshot_info_desc(nfo) (nfo)->desc
diff --git a/src/analysis/db/misc/timestamp.c b/src/analysis/db/misc/timestamp.c
index dfc6f25..4d457e2 100644
--- a/src/analysis/db/misc/timestamp.c
+++ b/src/analysis/db/misc/timestamp.c
@@ -37,6 +37,25 @@
* *
* Paramètres : timestamp = horodatage à initialiser. [OUT] *
* *
+* Description : Prépare un horodatage à une définition. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void setup_empty_timestamp(timestamp_t *timestamp)
+{
+ *timestamp = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : timestamp = horodatage à initialiser. [OUT] *
+* *
* Description : Obtient un horodatage initialisé au moment même. *
* *
* Retour : Bilan de l'opération. *
diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h
index 7f6290876..52b99f8 100644
--- a/src/analysis/db/misc/timestamp.h
+++ b/src/analysis/db/misc/timestamp.h
@@ -38,6 +38,9 @@
typedef uint64_t timestamp_t;
+/* Prépare un horodatage à une définition. */
+void setup_empty_timestamp(timestamp_t *);
+
/* Obtient un horodatage initialisé au moment même. */
bool init_timestamp(timestamp_t *);
diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h
index 22f564a..273be8e 100644
--- a/src/analysis/db/protocol.h
+++ b/src/analysis/db/protocol.h
@@ -103,6 +103,9 @@ typedef enum _DBAction
+/* Marqueur de fin pour une transmission d'identifiants */
+#define SNAPSHOT_END_MARK "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+
@@ -198,6 +201,34 @@ typedef enum _DBCommand
/* ------- Gestion des instantanés ------- */
+ /**
+ * Gestion de la commande 'DBC_GET_SNAPSHOTS'.
+ *
+ * Le client connecté envoie un paquet de la forme suivante :
+ *
+ * [ Gestion d'instantané : DBC_GET_SNAPSHOTS ]
+ *
+ * La définition d'un nouvel identifiant d'instantané courant se réalise dans :
+ * - g_hub_client_update() pour la partie client ;
+ * - g_cdb_archive_process() pour la partie serveur.
+ */
+
+ DBC_GET_SNAPSHOTS,
+
+ /**
+ * Gestion de la commande 'DBC_SNAPSHOTS_UPDATED'.
+ *
+ * Le serveur envoie au client un paquet de la forme suivante :
+ *
+ * [ Gestion d'instantané : DBC_SNAPSHOTS_UPDATED ]
+ * [ <liste de descriptions d'instantanés> ]
+ * [ Marqueur de fin : SNAPSHOT_END_MARK ]
+ *
+ * La définition d'un nouvel identifiant d'instantané courant se réalise dans :
+ * - g_cdb_archive_process() pour la partie serveur ;
+ * - g_hub_client_update() pour la partie client.
+ */
+
DBC_SNAPSHOTS_UPDATED, /* Identification d'instantanés*/
/**
diff --git a/src/analysis/db/snapshot.c b/src/analysis/db/snapshot.c
index 6b762b7..79128ef 100644
--- a/src/analysis/db/snapshot.c
+++ b/src/analysis/db/snapshot.c
@@ -82,6 +82,9 @@ static snapshot_node_t *find_snapshot_node(snapshot_node_t *, const snapshot_id_
/* Ajoute un instantané comme prolongement d'un instantané. */
static void add_snapshot_node(snapshot_node_t *, snapshot_node_t *);
+/* Collecte les descriptions d'une arborescence d'instantanés. */
+static bool pack_snapshot_node(const snapshot_node_t *, packed_buffer *);
+
/* --------------------- MANIPULATIONS D'ENSEMBLE D'INSTANTANES --------------------- */
@@ -378,7 +381,7 @@ static DBError save_snapshot_node(const snapshot_node_t *node, xmlDocPtr xdoc, x
goto exit;
}
- created = get_snapshot_info_creation(&node->info);
+ created = get_snapshot_info_created(&node->info);
status = _add_uint64_attribute_to_node(xml_node, "created", created);
@@ -497,13 +500,47 @@ static snapshot_node_t *find_snapshot_node(snapshot_node_t *node, const snapshot
static void add_snapshot_node(snapshot_node_t *node, snapshot_node_t *child)
{
+ snapshot_id_t *src; /* Identifiant d'instantané #0 */
+ snapshot_id_t *dest; /* Identifiant d'instantané #1 */
+
node->children = realloc(node->children, ++node->count * sizeof(snapshot_node_t *));
node->children[node->count - 1] = child;
+ src = get_snapshot_info_id(&node->info);
+ dest = get_snapshot_info_parent_id(&child->info);
+
+ copy_snapshot_id(dest, src);
+
}
+/******************************************************************************
+* *
+* Paramètres : node = définition d'instantané à consulter. *
+* pbuf = paquet de données où venir inscrire des infos. *
+* *
+* Description : Collecte les descriptions d'une arborescence d'instantanés. *
+* *
+* Retour : Bilan du déroulement des opérations. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool pack_snapshot_node(const snapshot_node_t *node, packed_buffer *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = pack_snapshot_info(&node->info, pbuf);
+
+ for (i = 0; i < node->count && result; i++)
+ result = pack_snapshot_node(node->children[i], pbuf);
+
+ return result;
+
+}
@@ -1044,3 +1081,27 @@ sqlite3 *g_db_snapshot_get_database(const GDbSnapshot *snap, const snapshot_id_t
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : snap = gestionnaire d'instantanés à consulter. *
+* pbuf = paquet de données où venir inscrire des infos. *
+* *
+* Description : Collecte les descriptions de l'ensemble des instantanés. *
+* *
+* Retour : Bilan du déroulement des opérations. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_snapshot_pack_all(const GDbSnapshot *snap, packed_buffer *pbuf)
+{
+ bool result; /* Bilan à retourner */
+
+ result = pack_snapshot_node(snap->nodes, pbuf);
+
+ return result;
+
+}
diff --git a/src/analysis/db/snapshot.h b/src/analysis/db/snapshot.h
index f568ba3..543d184 100644
--- a/src/analysis/db/snapshot.h
+++ b/src/analysis/db/snapshot.h
@@ -74,6 +74,9 @@ bool g_db_snapshot_get_current_id(const GDbSnapshot *, snapshot_id_t *);
/* Fournit la base de données correspondant à instanné donné. */
sqlite3 *g_db_snapshot_get_database(const GDbSnapshot *, const snapshot_id_t *);
+/* Collecte les descriptions de l'ensemble des instantanés. */
+bool g_db_snapshot_pack_all(const GDbSnapshot *, packed_buffer *);
+
#endif /* _ANALYSIS_DB_SNAPSHOT_H */
diff --git a/src/common/packed.c b/src/common/packed.c
index a8ce3c5..a10155d 100644
--- a/src/common/packed.c
+++ b/src/common/packed.c
@@ -241,7 +241,7 @@ bool extend_packed_buffer(packed_buffer *pbuf, const void *buf, size_t len, bool
* *
******************************************************************************/
-bool extract_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh)
+bool peek_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh)
{
bool result; /* Bilan à retourner */
uint16_t tmp16; /* Valeur intermédiaire 16b */
@@ -250,52 +250,102 @@ bool extract_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh
result = ((pbuf->pos + len - sizeof(uint32_t)) <= pbuf->used);
+ if (!result)
+ goto failed;
+
/* Conversion au formalisme du réseau */
if (!ntoh)
goto skip_conversion;
- if (result)
+ switch (len)
{
- switch (len)
- {
- case 1:
- *((uint8_t *)buf) = *((uint8_t *)(pbuf->data + pbuf->pos));
- break;
+ case 1:
+ *((uint8_t *)buf) = *((uint8_t *)(pbuf->data + pbuf->pos));
+ break;
- case 2:
- tmp16 = be16toh(*(uint16_t *)(pbuf->data + pbuf->pos));
- *((uint16_t *)buf) = tmp16;
- break;
+ case 2:
+ tmp16 = be16toh(*(uint16_t *)(pbuf->data + pbuf->pos));
+ *((uint16_t *)buf) = tmp16;
+ break;
- case 4:
- tmp32 = be32toh(*(uint32_t *)(pbuf->data + pbuf->pos));
- *((uint32_t *)buf) = tmp32;
- break;
+ case 4:
+ tmp32 = be32toh(*(uint32_t *)(pbuf->data + pbuf->pos));
+ *((uint32_t *)buf) = tmp32;
+ break;
- case 8:
- tmp64 = be64toh(*(uint64_t *)(pbuf->data + pbuf->pos));
- *((uint64_t *)buf) = tmp64;
- break;
+ case 8:
+ tmp64 = be64toh(*(uint64_t *)(pbuf->data + pbuf->pos));
+ *((uint64_t *)buf) = tmp64;
+ break;
- default:
+ default:
skip_conversion:
- /**
- * Dans ce cas de figure, c'est à l'appelant de s'assurer que la
- * conversion a bien été réalisée.
- */
- assert(!ntoh);
+ /**
+ * Dans ce cas de figure, c'est à l'appelant de s'assurer que la
+ * conversion a bien été réalisée.
+ */
+ assert(!ntoh);
+
+ memcpy(buf, pbuf->data + pbuf->pos, len);
+ break;
- memcpy(buf, pbuf->data + pbuf->pos, len);
- break;
+ }
- }
+ failed:
- pbuf->pos += len;
+ return result;
- }
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pbuf = paquet de données à consulter. *
+* len = quantité de ces données. *
+* *
+* Description : Avance la tête de lecture dans les données d'un paquet. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void advance_packed_buffer(packed_buffer *pbuf, size_t len)
+{
+ pbuf->pos += len;
+
+ assert((pbuf->pos - sizeof(uint32_t)) <= pbuf->used);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pbuf = paquet de données à consulter. *
+* buf = nouvelles données à définir. *
+* len = quantité de ces données. *
+* ntoh = indique si une conversion est à réaliser. *
+* *
+* Description : Récupère des données depuis un paquet après une réception. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool extract_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh)
+{
+ bool result; /* Bilan à retourner */
+
+ result = peek_packed_buffer(pbuf, buf, len, ntoh);
+
+ if (result)
+ advance_packed_buffer(pbuf, len);
return result;
diff --git a/src/common/packed.h b/src/common/packed.h
index 4403ad0..019d21a 100644
--- a/src/common/packed.h
+++ b/src/common/packed.h
@@ -66,6 +66,12 @@ bool has_more_data_in_packed_buffer(const packed_buffer *);
bool extend_packed_buffer(packed_buffer *, const void *, size_t, bool);
/* Récupère des données depuis un paquet après une réception. */
+bool peek_packed_buffer(packed_buffer *, void *, size_t, bool);
+
+/* Avance la tête de lecture dans les données d'un paquet. */
+void advance_packed_buffer(packed_buffer *, size_t);
+
+/* Récupère des données depuis un paquet après une réception. */
bool extract_packed_buffer(packed_buffer *, void *, size_t, bool);
/* Lit des données depuis un flux local. */