diff options
Diffstat (limited to 'src/analysis/db/cdb.c')
-rw-r--r-- | src/analysis/db/cdb.c | 287 |
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. * |