summaryrefslogtreecommitdiff
path: root/src/analysis/db/cdb.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-10-27 22:33:11 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-10-27 23:10:41 (GMT)
commit609c184c3edb350a0da7fe29bf449a7189080c92 (patch)
tree4ddd6320ee58a6169cad377f9889a08298fbec47 /src/analysis/db/cdb.c
parentd0547bc36bd6ccb84eff128fc6e4f2df034a705a (diff)
Implemented snapshot related management features.
Diffstat (limited to 'src/analysis/db/cdb.c')
-rw-r--r--src/analysis/db/cdb.c287
1 files changed, 236 insertions, 51 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 125f69d..92624f6 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -147,6 +147,15 @@ static void on_collection_extended(GDbCollection *, GDbItem *, GCdbArchive *);
/* Assure le traitement des requêtes de clients. */
static void *g_cdb_archive_process(GCdbArchive *);
+/* Envoie un paquet de données constitué à tous les clients. */
+static void g_cdb_archive_send_reply_to_all_clients(GCdbArchive *, packed_buffer *);
+
+/* Envoie à tous les clients la nouvelle liste d'instantanés. */
+static bool g_cdb_archive_send_snapshot_update(GCdbArchive *, packed_buffer *);
+
+/* Envoie à tous les clients le nouvel instantané courant. */
+static bool g_cdb_archive_send_snapshot_change(GCdbArchive *, packed_buffer *);
+
/* Dissocie un utilisateur de l'archive. */
static void g_cdb_archive_remove_client(GCdbArchive *, size_t);
@@ -255,12 +264,18 @@ static void g_cdb_archive_dispose(GCdbArchive *archive)
static void g_cdb_archive_finalize(GCdbArchive *archive)
{
+#ifndef NDEBUG
int ret; /* Bilan d'un appel */
+#endif
if (archive->db != NULL)
{
+#ifndef NDEBUG
ret = sqlite3_close(archive->db);
assert(ret == SQLITE_OK);
+#else
+ sqlite3_close(archive->db);
+#endif
}
if (archive->xml_desc != NULL)
@@ -299,10 +314,6 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl
GCdbArchive *result; /* Adresse à retourner */
int ret; /* Retour d'un appel */
struct stat finfo; /* Information sur l'archive */
- snapshot_id_t id; /* Identifiant d'instantané */
-#ifndef NDEBUG
- bool status; /* Validité de l'identifiant */
-#endif
result = g_object_new(G_TYPE_CDB_ARCHIVE, NULL);
@@ -348,14 +359,7 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl
/* Récupération de la base courante */
-#ifndef NDEBUG
- status = g_db_snapshot_get_current_id(result->snapshot, &id);
- assert(status);
-#else
- g_db_snapshot_get_current_id(result->snapshot, &id);
-#endif
-
- result->db = g_db_snapshot_get_database(result->snapshot, &id);
+ result->db = g_db_snapshot_get_database(result->snapshot);
if (result->db == NULL)
{
@@ -381,14 +385,7 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl
/* Récupération de la base courante */
-#ifndef NDEBUG
- status = g_db_snapshot_get_current_id(result->snapshot, &id);
- assert(status);
-#else
- g_db_snapshot_get_current_id(result->snapshot, &id);
-#endif
-
- result->db = g_db_snapshot_get_database(result->snapshot, &id);
+ result->db = g_db_snapshot_get_database(result->snapshot);
if (result->db == NULL)
{
@@ -843,7 +840,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é */
+ bool reload; /* Besoin de rechargement */
char *msg; /* Erreur à faire remonter */
void interrupt_poll_with_sigusr1(int sig) { };
@@ -1007,19 +1004,8 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
case DBC_GET_SNAPSHOTS:
- force_snapshots_update:
-
- 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;
+ if (!g_cdb_archive_send_snapshot_update(archive, &out_pbuf))
+ goto critical_error;
status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
if (!status) goto gcap_bad_reply;
@@ -1030,21 +1016,8 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
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;
+ if (!g_cdb_archive_send_snapshot_change(archive, &out_pbuf))
+ goto critical_error;
status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
if (!status) goto gcap_bad_reply;
@@ -1061,8 +1034,34 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
case DBC_SET_CUR_SNAPSHOT:
+ error = g_db_snapshot_restore(archive->snapshot, &in_pbuf, &reload);
+ if (error == DBE_NONE)
+ {
+#ifndef NDEBUG
+ ret = sqlite3_close(archive->db);
+ assert(ret == SQLITE_OK);
+#else
+ sqlite3_close(archive->db);
+#endif
+
+ archive->db = g_db_snapshot_get_database(archive->snapshot);
+
+ if (archive->db == NULL)
+ {
+ error = DBE_SNAPSHOT_RESTORE_FAILURE;
+ }
+ else
+ {
+ if (!g_cdb_archive_send_snapshot_change(archive, NULL))
+ goto critical_error;
+ }
+
+ }
+
+ else if (error == DBE_BAD_EXCHANGE)
+ goto gcap_bad_exchange;
break;
@@ -1071,7 +1070,10 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
error = g_db_snapshot_set_name(archive->snapshot, &in_pbuf);
if (error == DBE_NONE)
- goto force_snapshots_update;
+ {
+ if (!g_cdb_archive_send_snapshot_update(archive, NULL))
+ goto critical_error;
+ }
else if (error == DBE_BAD_EXCHANGE)
goto gcap_bad_exchange;
@@ -1083,7 +1085,47 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
error = g_db_snapshot_set_desc(archive->snapshot, &in_pbuf);
if (error == DBE_NONE)
- goto force_snapshots_update;
+ {
+ if (!g_cdb_archive_send_snapshot_update(archive, NULL))
+ goto critical_error;
+ }
+
+ else if (error == DBE_BAD_EXCHANGE)
+ goto gcap_bad_exchange;
+
+ break;
+
+ case DBC_CREATE_SNAPSHOT:
+
+ error = g_db_snapshot_create(archive->snapshot, archive->db);
+
+ if (error == DBE_NONE)
+ {
+ if (!g_cdb_archive_send_snapshot_update(archive, NULL))
+ goto critical_error;
+ }
+
+ else if (error == DBE_BAD_EXCHANGE)
+ goto gcap_bad_exchange;
+
+ break;
+
+ case DBC_REMOVE_SNAPSHOT:
+
+ error = g_db_snapshot_remove(archive->snapshot, &in_pbuf, &reload);
+
+ if (error == DBE_NONE)
+ {
+ if (!g_cdb_archive_send_snapshot_update(archive, NULL))
+ goto critical_error;
+
+ if (reload)
+ {
+ if (!g_cdb_archive_send_snapshot_change(archive, NULL))
+ goto critical_error;
+ }
+
+ }
else if (error == DBE_BAD_EXCHANGE)
goto gcap_bad_exchange;
@@ -1122,6 +1164,14 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
g_cdb_archive_remove_client(archive, i);
+ continue;
+
+ critical_error:
+
+ LOG_ERROR(LMT_ERROR, _("Internal critical error"));
+
+ assert(0);
+
}
}
@@ -1150,6 +1200,141 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
/******************************************************************************
* *
* Paramètres : archive = archive à connecter avec un utilisateur. *
+* pbuf = paquet de données à émettre. *
+* *
+* Description : Envoie un paquet de données constitué à tous les clients. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_cdb_archive_send_reply_to_all_clients(GCdbArchive *archive, packed_buffer *pbuf)
+{
+ size_t i; /* Boucle de parcours */
+ bool status; /* Bilan d'une émission */
+
+ for (i = 0; i < archive->count; i++)
+ {
+ status = ssl_send_packed_buffer(pbuf, archive->clients[i].ssl_fd);
+ if (!status)
+ {
+ log_variadic_message(LMT_ERROR, _("Error while replying to client %zu"), i);
+
+ g_cdb_archive_remove_client(archive, i);
+ i--;
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
+* pbuf = paquet à consituer pour un envoi unique. [OUT] *
+* *
+* Description : Envoie à tous les clients la nouvelle liste d'instantanés. *
+* *
+* Retour : Bilan de constitution de la réponse. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_cdb_archive_send_snapshot_update(GCdbArchive *archive, packed_buffer *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ bool do_send; /* Réalisation de l'émission */
+ packed_buffer out_pbuf; /* Tampon d'émission */
+
+ do_send = (pbuf == NULL);
+
+ if (pbuf == NULL)
+ pbuf = &out_pbuf;
+
+ init_packed_buffer(pbuf);
+
+ result = extend_packed_buffer(pbuf, (uint32_t []) { DBC_SNAPSHOTS_UPDATED },
+ sizeof(uint32_t), true);
+ if (!result) goto bad_reply;
+
+ result = g_db_snapshot_pack_all(archive->snapshot, pbuf);
+ if (!result) goto bad_reply;
+
+ result = extend_packed_buffer(pbuf, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ, false);
+ if (!result) goto bad_reply;
+
+ if (do_send)
+ g_cdb_archive_send_reply_to_all_clients(archive, pbuf);
+
+ bad_reply:
+
+ if (do_send || !result)
+ exit_packed_buffer(pbuf);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
+* pbuf = paquet à consituer pour un envoi unique. [OUT] *
+* *
+* Description : Envoie à tous les clients le nouvel instantané courant. *
+* *
+* Retour : Bilan de constitution de la réponse. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buffer *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ bool do_send; /* Réalisation de l'émission */
+ packed_buffer out_pbuf; /* Tampon d'émission */
+ snapshot_id_t id; /* Identifiant d'instantané */
+
+ do_send = (pbuf == NULL);
+
+ if (pbuf == NULL)
+ pbuf = &out_pbuf;
+
+ init_packed_buffer(pbuf);
+
+ result = extend_packed_buffer(pbuf, (uint32_t []) { DBC_CUR_SNAPSHOT_UPDATED },
+ sizeof(uint32_t), true);
+ if (!result) goto bad_reply;
+
+ result = g_db_snapshot_get_current_id(archive->snapshot, &id);
+ assert(result);
+ if (!result) goto bad_reply;
+
+ result = pack_snapshot_id(&id, pbuf);
+ if (!result) goto bad_reply;
+
+ if (do_send)
+ g_cdb_archive_send_reply_to_all_clients(archive, pbuf);
+
+ bad_reply:
+
+ if (do_send || !result)
+ exit_packed_buffer(pbuf);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
* fd = canal de communication réseau ouvert. *
* *
* Description : Associe un nouvel utilisateur à l'archive. *