diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2019-10-27 22:33:11 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2019-10-27 23:10:41 (GMT) | 
| commit | 609c184c3edb350a0da7fe29bf449a7189080c92 (patch) | |
| tree | 4ddd6320ee58a6169cad377f9889a08298fbec47 /src/analysis/db/cdb.c | |
| parent | d0547bc36bd6ccb84eff128fc6e4f2df034a705a (diff) | |
Implemented snapshot related management features.
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.                   *  | 
