summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analysis/db/cdb.c42
-rw-r--r--src/analysis/db/client.c112
-rw-r--r--src/analysis/db/client.h7
-rw-r--r--src/analysis/db/item.c9
-rw-r--r--src/analysis/db/misc/snapshot.c228
-rw-r--r--src/analysis/db/misc/snapshot.h30
-rw-r--r--src/analysis/db/misc/timestamp.c71
-rw-r--r--src/analysis/db/misc/timestamp.h8
-rw-r--r--src/analysis/db/protocol.h58
-rw-r--r--src/common/packed.c2
-rw-r--r--src/common/xml.c138
-rw-r--r--src/common/xml.h13
12 files changed, 706 insertions, 12 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 2013750..8e8813a 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -841,6 +841,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
DBError error; /* Bilan d'une opération */
packed_buffer out_pbuf; /* Tampon d'émission */
GDbCollection *collec; /* Collection visée au final */
+ snapshot_id_t id; /* Identifiant d'instantané */
char *msg; /* Erreur à faire remonter */
void interrupt_poll_with_sigusr1(int sig) { };
@@ -910,6 +911,8 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].ssl_fd);
if (!status) goto gcap_bad_exchange;
+ next_command:
+
status = extract_packed_buffer(&in_pbuf, &tmp32, sizeof(uint32_t), true);
if (!status) goto gcap_bad_exchange;
@@ -1000,6 +1003,42 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
break;
+ case DBC_GET_CUR_SNAPSHOT:
+
+ init_packed_buffer(&out_pbuf);
+
+ status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_CUR_SNAPSHOT_UPDATED },
+ sizeof(uint32_t), true);
+ if (!status) goto gcap_bad_reply;
+
+#ifndef NDEBUG
+ status = g_db_snapshot_get_current_id(archive->snapshot, &id);
+ assert(status);
+#else
+ g_db_snapshot_get_current_id(archive->snapshot, &id);
+#endif
+
+ status = pack_snapshot_id(&id, &out_pbuf);
+ 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_CUR_SNAPSHOT_UPDATED:
+ log_variadic_message(LMT_INFO,
+ _("This command is not available on this side: 0x%08x"), command);
+ goto gcap_bad_exchange;
+ break;
+
+ case DBC_SET_CUR_SNAPSHOT:
+
+
+ break;
+
default:
asprintf(&msg, _("Bad protocol command: 0x%08x"), command);
LOG_ERROR(LMT_ERROR, msg);
@@ -1009,6 +1048,9 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
}
+ if (has_more_data_in_packed_buffer(&in_pbuf))
+ goto next_command;
+
exit_packed_buffer(&in_pbuf);
continue;
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index 4c525e1..3372c74 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -76,6 +76,12 @@ struct _GHubClient
bool can_get_updates; /* Réception de maj possibles ?*/
GThread *update; /* Procédure de traitement */
+
+
+
+ snapshot_id_t current; /* Instantané courant */
+ bool has_current; /* Validité de l'identifiant */
+
};
/* Description de client à l'écoute (classe) */
@@ -162,6 +168,8 @@ static void g_hub_client_init(GHubClient *client)
client->tls_fd = NULL;
client->desc = NULL;
+ client->has_current = false;
+
}
@@ -686,6 +694,7 @@ static void *g_hub_client_update(GHubClient *client)
DBError error; /* Bilan d'une commande passée */
GDbCollection *collec; /* Collection visée au final */
uint8_t tmp8; /* Valeur sur 8 bits */
+ snapshot_id_t id; /* Identifiant d'instantané */
char *msg; /* Message d'erreur à imprimer */
/**
@@ -694,6 +703,13 @@ static void *g_hub_client_update(GHubClient *client)
init_packed_buffer(&out_pbuf);
+ status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_CUR_SNAPSHOT }, sizeof(uint32_t), true);
+ if (!status)
+ {
+ exit_packed_buffer(&out_pbuf);
+ goto exit;
+ }
+
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_ALL_ITEMS }, sizeof(uint32_t), true);
if (!status)
{
@@ -798,6 +814,28 @@ static void *g_hub_client_update(GHubClient *client)
client->can_get_updates = (tmp8 == 0x1);
break;
+ case DBC_GET_CUR_SNAPSHOT:
+ log_variadic_message(LMT_INFO,
+ _("This command is not available on this side: 0x%08x"), command);
+ goto gdcu_bad_exchange;
+ break;
+
+ case DBC_CUR_SNAPSHOT_UPDATED:
+
+ status = unpack_snapshot_id(&id, &in_pbuf);
+ if (!status) goto gdcu_bad_exchange;
+
+ copy_snapshot_id(&client->current, &id);
+ client->has_current = true;
+
+ break;
+
+ case DBC_SET_CUR_SNAPSHOT:
+ log_variadic_message(LMT_INFO,
+ _("This command is not available on this side: 0x%08x"), command);
+ goto gdcu_bad_exchange;
+ break;
+
}
if (has_more_data_in_packed_buffer(&in_pbuf))
@@ -1092,3 +1130,77 @@ bool g_hub_client_set_last_active(GHubClient *client, timestamp_t timestamp)
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. *
+* *
+* Retour : true si l'identifiant retourné est valide, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_hub_client_get_current_snapshot(GHubClient *client, snapshot_id_t *id)
+{
+ bool result; /* Validité à retourner */
+
+ result = client->has_current;
+
+ if (result)
+ copy_snapshot_id(id, &client->current);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = client pour les accès distants à manipuler. *
+* id = identifiant d'instantané à activer. *
+* *
+* Description : Définit l'identifiant de l'instantané courant. *
+* *
+* Retour : true si la commande a bien été envoyée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_hub_client_set_current_snapshot(GHubClient *client, const snapshot_id_t *id)
+{
+ bool result; /* Bilan partiel à remonter */
+ packed_buffer out_pbuf; /* Tampon d'émission */
+ SSL *tls_fd; /* Canal de communication SSL */
+
+ init_packed_buffer(&out_pbuf);
+
+ tls_fd = g_hub_client_get_ssl_fd(client);
+
+ if (tls_fd == NULL)
+ result = false;
+
+ else
+ {
+ result = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SET_CUR_SNAPSHOT }, sizeof(uint32_t), true);
+
+ if (result)
+ result = pack_snapshot_id(id, &out_pbuf);
+
+ 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);
+
+ return result;
+
+}
diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h
index f7f7bcb..36d24e6 100644
--- a/src/analysis/db/client.h
+++ b/src/analysis/db/client.h
@@ -31,6 +31,7 @@
#include "collection.h"
+#include "misc/snapshot.h"
@@ -73,6 +74,12 @@ 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 l'identifiant de l'instantané courant. */
+bool g_hub_client_get_current_snapshot(GHubClient *, snapshot_id_t *);
+
+/* Définit l'identifiant de l'instantané courant. */
+bool g_hub_client_set_current_snapshot(GHubClient *, const snapshot_id_t *);
+
#endif /* _ANALYSIS_DB_CLIENT_H */
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index 8fc1763..b3b00fe 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -200,7 +200,16 @@ DBFeatures g_db_item_get_feature(const GDbItem *item)
void g_db_item_set_server_side(GDbItem *item)
{
+#ifndef NDEBUG
+ bool status; /* Bilan d'une initialisation */
+#endif
+
+#ifndef NDEBUG
+ status = init_timestamp(&item->created);
+ assert(status);
+#else
init_timestamp(&item->created);
+#endif
}
diff --git a/src/analysis/db/misc/snapshot.c b/src/analysis/db/misc/snapshot.c
index 982553b..546191b 100644
--- a/src/analysis/db/misc/snapshot.c
+++ b/src/analysis/db/misc/snapshot.c
@@ -210,8 +210,236 @@ bool pack_snapshot_id(const snapshot_id_t *id, packed_buffer *pbuf)
/* ---------------------------------------------------------------------------------- */
+/******************************************************************************
+* *
+* 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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_snapshot_info(snapshot_info_t *info)
+{
+ bool result; /* Bilan à retourner */
+
+ result = init_snapshot_id(&info->id);
+
+ if (result)
+ result = init_timestamp(&info->created);
+
+ if (result)
+ {
+ info->name = NULL;
+ info->desc = NULL;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = description d'instantané à initialiser. [OUT] *
+* id = source de données pour l'identifiant. *
+* created = source de données pour la date de création. *
+* name = source de données éventuelle pour le nom. *
+* desc = source de données éventuelle pour la description. *
+* *
+* Description : Construit une description pour instantané de base de données.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_snapshot_info_from_text(snapshot_info_t *info, const char *id, uint64_t created, const char *name, const char *desc)
+{
+ bool result; /* Bilan à retourner */
+
+ result = init_snapshot_id_from_text(&info->id, id);
+
+ if (result)
+ result = init_timestamp_from_value(&info->created, created);
+
+ if (result)
+ {
+ if (name == NULL)
+ info->name = NULL;
+ else
+ info->name = strdup(name);
+
+ if (desc == NULL)
+ info->desc = NULL;
+ else
+ info->desc = strdup(desc);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = description d'instantané à initialiser. [OUT] *
+* *
+* Description : Libère la mémoire occupée par une description d'instantané. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void exit_snapshot_info(snapshot_info_t *info)
+{
+ if (info->name != NULL)
+ {
+ free(info->name);
+ info->name = NULL;
+ }
+
+ if (info->desc != NULL)
+ {
+ free(info->desc);
+ info->desc = NULL;
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = destination de la copie de description. [OUT] *
+* src = source de la description à copier. *
+* *
+* Description : Effectue une copie de description d'instantané. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void copy_snapshot_info(snapshot_info_t *dest, const snapshot_info_t *src)
+{
+ exit_snapshot_info(dest);
+
+ copy_snapshot_id(&dest->id, &src->id);
+
+ copy_timestamp(&dest->created, &src->created);
+
+ if (src->name != NULL)
+ dest->name = strdup(src->name);
+
+ if (src->desc != NULL)
+ dest->desc = strdup(src->desc);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à constituer. [OUT] *
+* pbuf = paquet de données où venir puiser les infos. *
+* *
+* Description : Importe la description d'un identifiant d'instantané. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool unpack_snapshot_info(snapshot_info_t *info, packed_buffer *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ rle_string string; /* Chaîne à transmettre */
+
+ result = unpack_snapshot_id(&info->id, pbuf);
+
+ if (result)
+ result = unpack_timestamp(&info->created, pbuf);
+
+ if (result)
+ {
+ result = unpack_rle_string(&string, pbuf);
+ if (result)
+ {
+ info->name = strdup(get_rle_string(&string));
+ exit_rle_string(&string);
+ }
+
+ }
+ if (result)
+ {
+ result = unpack_rle_string(&string, pbuf);
+ if (result)
+ {
+ info->desc = strdup(get_rle_string(&string));
+ exit_rle_string(&string);
+ }
+ }
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à sauvegarer. *
+* pbuf = paquet de données où venir inscrire les infos. *
+* *
+* Description : Exporte la description d'un identifiant d'instantané. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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);
+
+ if (result)
+ result = pack_timestamp(&info->created, pbuf);
+
+ if (result)
+ {
+ init_static_rle_string(&string, info->name);
+
+ result = pack_rle_string(&string, pbuf);
+
+ exit_rle_string(&string);
+
+ }
+
+ if (result)
+ {
+ init_static_rle_string(&string, info->desc);
+
+ result = pack_rle_string(&string, pbuf);
+
+ exit_rle_string(&string);
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/db/misc/snapshot.h b/src/analysis/db/misc/snapshot.h
index 4aaa6f9..e3a003c 100644
--- a/src/analysis/db/misc/snapshot.h
+++ b/src/analysis/db/misc/snapshot.h
@@ -29,6 +29,8 @@
#include <stdint.h>
+#include "rlestr.h"
+#include "timestamp.h"
#include "../../../common/packed.h"
@@ -42,7 +44,7 @@
/* Représentation d'un instantané */
typedef struct _snapshot_id_t
{
- char name[SNAP_ID_HEX_SZ];
+ char name[SNAP_ID_HEX_SZ]; /* Caractères hexadécimaux */
} snapshot_id_t;
@@ -72,10 +74,36 @@ bool pack_snapshot_id(const snapshot_id_t *, packed_buffer *);
/* --------------------------- PROPRIETES DES INSTANTANES --------------------------- */
+/* Description d'un instantané */
+typedef struct _snapshot_info_t
+{
+ snapshot_id_t id; /* Identifiant attribué */
+
+ timestamp_t created; /* Date de création */
+
+ char *name; /* Nom de l'instantané */
+ char *desc; /* Description associée */
+
+} snapshot_info_t;
+
+
+/* Construit une description pour instantané de base de données. */
+bool init_snapshot_info(snapshot_info_t *);
+
+/* Construit une description pour instantané de base de données. */
+bool init_snapshot_info_from_text(snapshot_info_t *, const char *, uint64_t, const char *, const char *);
+/* Libère la mémoire occupée par une description d'instantané. */
+void exit_snapshot_info(snapshot_info_t *);
+/* Effectue une copie de description d'instantané. */
+void copy_snapshot_info(snapshot_info_t *, const snapshot_info_t *);
+/* Importe la description d'un identifiant d'instantané. */
+bool unpack_snapshot_info(snapshot_info_t *, packed_buffer *);
+/* Exporte la description d'un identifiant d'instantané. */
+bool pack_snapshot_info(const snapshot_info_t *, packed_buffer *);
diff --git a/src/analysis/db/misc/timestamp.c b/src/analysis/db/misc/timestamp.c
index 12299eb..dfc6f25 100644
--- a/src/analysis/db/misc/timestamp.c
+++ b/src/analysis/db/misc/timestamp.c
@@ -29,6 +29,9 @@
#include <time.h>
+#include "../../../core/logs.h"
+
+
/******************************************************************************
* *
@@ -36,19 +39,59 @@
* *
* Description : Obtient un horodatage initialisé au moment même. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void init_timestamp(timestamp_t *timestamp)
+bool init_timestamp(timestamp_t *timestamp)
{
+ bool result; /* Bilan à retourner */
struct timespec info; /* Détails sur l'époque */
+ int ret; /* Bilan de la récupération */
+
+ ret = clock_gettime(CLOCK_REALTIME, &info);
- clock_gettime(CLOCK_REALTIME, &info);
+ if (ret != 0)
+ {
+ LOG_ERROR_N("clock_gettime");
+ result = false;
+ }
- *timestamp = info.tv_sec * 1000000 + info.tv_nsec / 1000;
+ else
+ {
+ *timestamp = info.tv_sec * 1000000 + info.tv_nsec / 1000;
+ result = true;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : timestamp = horodatage à initialiser. [OUT] *
+* value = valeur d'initialisation. *
+* *
+* Description : Obtient un horodatage initialisé avec une valeur donnée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_timestamp_from_value(timestamp_t *timestamp, uint64_t value)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ *timestamp = value;
+
+ return result;
}
@@ -79,6 +122,26 @@ bool timestamp_is_younger(timestamp_t stamp, timestamp_t limit)
/******************************************************************************
* *
+* Paramètres : dest = destination de la copie d'horodatage. [OUT] *
+* src = source de l'horodatage à copier. *
+* *
+* Description : Effectue une copie d'horodatage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void copy_timestamp(timestamp_t *dest, const timestamp_t *src)
+{
+ *dest = *src;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : t1 = premier horodatage à comparer. *
* t2 = second horodatage à comparer. *
* *
diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h
index 002f4d4..7f6290876 100644
--- a/src/analysis/db/misc/timestamp.h
+++ b/src/analysis/db/misc/timestamp.h
@@ -39,11 +39,17 @@ typedef uint64_t timestamp_t;
/* Obtient un horodatage initialisé au moment même. */
-void init_timestamp(timestamp_t *);
+bool init_timestamp(timestamp_t *);
+
+/* Obtient un horodatage initialisé avec une valeur donnée. */
+bool init_timestamp_from_value(timestamp_t *, uint64_t);
/* Définit si un horodatage est plus récent qu'un autre ou non. */
bool timestamp_is_younger(timestamp_t, timestamp_t);
+/* Effectue une copie d'horodatage. */
+void copy_timestamp(timestamp_t *, const timestamp_t *);
+
/* Effectue la comparaison entre deux horodatages. */
int cmp_timestamp(const timestamp_t *, const timestamp_t *);
diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h
index b42ad15..22f564a 100644
--- a/src/analysis/db/protocol.h
+++ b/src/analysis/db/protocol.h
@@ -127,8 +127,8 @@ typedef enum _DBCommand
* [ Statut d'exécution ; cf. DBError ]
*
* Les traitements se réalisent dans :
- * - g_db_client_save() pour la partie client en émission.
- * - g_cdb_archive_process() pour la partie serveur.
+ * - g_db_client_save() pour la partie client en émission ;
+ * - g_cdb_archive_process() pour la partie serveur ;
* - g_db_client_update() pour la partie client en réception.
*
*/
@@ -165,7 +165,7 @@ typedef enum _DBCommand
* [ marqueur de fin : octet 0x0 ]
*
* Les traitements se réalisent dans :
- * - g_db_client_update() pour la partie client.
+ * - g_db_client_update() pour la partie client ;
* - g_cdb_archive_process() pour la partie serveur.
*
*/
@@ -179,7 +179,7 @@ typedef enum _DBCommand
* Le client connecté envoie un paquet de la forme suivante :
*
* [ Statut d'historique : DBC_SET_LAST_ACTIVE ]
- * [ <horodatage du dernier élément actif ]
+ * [ <horodatage du dernier élément actif> ]
*
* Le serveur s'exécute et notifie le client d'éventuels changements,
* avec une série de paquets de la forme :
@@ -189,13 +189,61 @@ typedef enum _DBCommand
* [ <élément dont le statut a évolué> ]
*
* Les traitements se réalisent dans :
- * - g_db_collection_disable_at() pour la partie serveur.
+ * - 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 */ // REMME
+ /* ------- Gestion des instantanés ------- */
+
+ DBC_SNAPSHOTS_UPDATED, /* Identification d'instantanés*/
+
+ /**
+ * Gestion de la commande 'DBC_GET_CUR_SNAPSHOT'.
+ *
+ * Le client connecté envoie un paquet de la forme suivante :
+ *
+ * [ Gestion d'instantané : DBC_GET_CUR_SNAPSHOT ]
+ *
+ * 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_CUR_SNAPSHOT, /* Demande d'identification */
+
+ /**
+ * Gestion de la commande 'DBC_CUR_SNAPSHOT_UPDATED'.
+ *
+ * Le serveur envoie au client un paquet de la forme suivante :
+ *
+ * [ Gestion d'instantané : DBC_CUR_SNAPSHOT_UPDATED ]
+ * [ <identifiant d'instantané> ]
+ *
+ * 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_CUR_SNAPSHOT_UPDATED, /* Mise à jour de l'instantané */
+
+ /**
+ * Gestion de la commande 'DBC_SET_CUR_SNAPSHOT'.
+ *
+ * Le client connecté envoie un paquet de la forme suivante :
+ *
+ * [ Gestion d'instantané : DBC_SET_CUR_SNAPSHOT ]
+ * [ <identifiant d'instantané> ]
+ *
+ * La définition d'un nouvel identifiant d'instantané courant se réalise dans :
+ * - g_hub_client_set_current_snapshot() pour la partie client ;
+ * -
+ */
+
+ DBC_SET_CUR_SNAPSHOT, /* Définition de l'instantané */
+
DBC_COUNT
} DBCommand;
diff --git a/src/common/packed.c b/src/common/packed.c
index 163ed3b..a8ce3c5 100644
--- a/src/common/packed.c
+++ b/src/common/packed.c
@@ -141,7 +141,7 @@ bool has_more_data_in_packed_buffer(const packed_buffer *pbuf)
{
bool result; /* Bilan à retourner */
- result = (pbuf->pos < pbuf->used);
+ result = (pbuf->pos < (pbuf->used + sizeof(uint32_t)));
return result;
diff --git a/src/common/xml.c b/src/common/xml.c
index aaed2ea..3774359 100644
--- a/src/common/xml.c
+++ b/src/common/xml.c
@@ -25,6 +25,8 @@
#include "xml.h"
+#include <inttypes.h>
+#include <malloc.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -453,6 +455,43 @@ bool qck_get_node_prop_long_value(xmlNodePtr node, const char *name, long *out)
/******************************************************************************
* *
+* Paramètres : node = noeud dont une propriété est à lire. *
+* name = nom de la propriété à lire. *
+* out = valeur entière lue depuis le contenu textuel. [OUT] *
+* *
+* Description : Obtient la valeur entière d'une propriété d'un élément. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool qck_get_node_prop_uint64_value(xmlNodePtr node, const char *name, uint64_t *out)
+{
+ bool result; /* Bilan à retourner */
+ char *value; /* Valeur brute lue */
+
+ value = qck_get_node_prop_value(node, name);
+
+ if (value)
+ {
+ result = true;
+
+ *out = strtoull(value, NULL, 10);
+ free(value);
+
+ }
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : xpathCtx = contexte à utiliser pour les recherches. *
* path = chemin d'accès au noeud à traiter. *
* name = nom de la propriété à lire. *
@@ -522,6 +561,41 @@ bool get_node_prop_long_value(xmlXPathContextPtr xpathCtx, const char *path, con
/******************************************************************************
* *
+* Paramètres : xpathCtx = contexte à utiliser pour les recherches. *
+* path = chemin d'accès au noeud à traiter. *
+* name = nom de la propriété à lire. *
+* out = valeur entière obtenue via contenu textuel. [OUT] *
+* *
+* Description : Obtient la valeur entière d'une propriété d'un élément. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_node_prop_uint64_value(xmlXPathContextPtr xpathCtx, const char *path, const char *name, uint64_t *out)
+{
+ bool result; /* Bilan à retourner */
+ xmlXPathObjectPtr xpathObj; /* Point de départ XML */
+
+ result = NULL;
+
+ xpathObj = get_node_xpath_object(xpathCtx, path);
+ if (xpathObj == NULL) return NULL;
+
+ if (xpathObj->nodesetval->nodeNr > 0)
+ result = qck_get_node_prop_uint64_value(xpathObj->nodesetval->nodeTab[0], name, out);
+
+ xmlXPathFreeObject(xpathObj);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : node = noeud de texte avec un lien avec le document XML. *
* *
* Description : Construit un chemin d'accès complet selon le fichier XML. *
@@ -1250,3 +1324,67 @@ bool add_long_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, cons
return _add_long_attribute_to_node(node, name, value);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud dont le contenu est à mettre à jour. *
+* name = nom de la propriété à créer. *
+* value = valeur numérique à placer. *
+* *
+* Description : Ajoute une propriété à un noeud existant donné. *
+* *
+* Retour : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _add_uint64_attribute_to_node(xmlNodePtr node, const char *name, uint64_t value)
+{
+ bool result; /* Bilan à retourner */
+ char *tmp; /* Stockage temporaire */
+ int ret; /* Bilan de l'impression */
+
+ ret = asprintf(&tmp, "%" PRIu64, value);
+
+ if (ret == -1)
+ result = false;
+
+ else
+ {
+ result = _add_string_attribute_to_node(node, name, tmp);
+ free(tmp);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : xdoc = structure XML chargée. *
+* context = contexte à utiliser pour les recherches. *
+* path = chemin d'accès au noeud visé. *
+* name = nom de la propriété à créer. *
+* value = valeur numérique à placer. *
+* *
+* Description : Ajoute une propriété à un noeud existant donné. *
+* *
+* Retour : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_uint64_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *name, uint64_t value)
+{
+ xmlNodePtr node; /* Noeud à modifier */
+
+ node = ensure_node_exist(xdoc, context, path);
+ if (node == NULL) return false;
+
+ return _add_uint64_attribute_to_node(node, name, value);
+
+}
diff --git a/src/common/xml.h b/src/common/xml.h
index ed009c6..5ae7664 100644
--- a/src/common/xml.h
+++ b/src/common/xml.h
@@ -28,6 +28,7 @@
#include <glib.h>
#include <stdbool.h>
+#include <stdint.h>
#include <libxml/tree.h>
#include <libxml/xmlwriter.h>
#include <libxml/xpath.h>
@@ -79,12 +80,18 @@ char *qck_get_node_prop_value(xmlNodePtr, const char *);
/* Obtient la valeur entière d'une propriété d'un élément. */
bool qck_get_node_prop_long_value(xmlNodePtr, const char *, long *);
+/* Obtient la valeur entière d'une propriété d'un élément. */
+bool qck_get_node_prop_uint64_value(xmlNodePtr, const char *, uint64_t *);
+
/* Obtient la valeur d'une propriété d'un élément. */
char *get_node_prop_value(xmlXPathContextPtr, const char *, const char *);
/* Obtient la valeur entière d'une propriété d'un élément. */
bool get_node_prop_long_value(xmlXPathContextPtr, const char *, const char *, long *);
+/* Obtient la valeur entière d'une propriété d'un élément. */
+bool get_node_prop_uint64_value(xmlXPathContextPtr, const char *, const char *, uint64_t *);
+
/* Construit un chemin d'accès complet selon le fichier XML. */
char *qck_build_filename_with_doc_url(xmlNodePtr);
@@ -158,6 +165,12 @@ bool _add_long_attribute_to_node(xmlNodePtr, const char *, long);
/* Ajoute une propriété à un noeud existant donné. */
bool add_long_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, long);
+/* Ajoute une propriété à un noeud existant donné. */
+bool _add_uint64_attribute_to_node(xmlNodePtr, const char *, uint64_t);
+
+/* Ajoute une propriété à un noeud existant donné. */
+bool add_uint64_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, uint64_t);
+
#endif /* _XML_H */