sync

Backup service to store encrypted wallet databases (experimental)
Log | Files | Refs | Submodules | README | LICENSE

syncdb_lookup_block_range_TR.c (6911B)


      1 /*
      2   This file is part of TALER
      3   (C) 2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Lesser General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file syncdb/syncdb_lookup_block_range_TR.c
     18  * @brief lookup a (limited) range of blocks starting at a nonce
     19  * @author Iván Ávalos
     20  */
     21 #include "syncdb_pg.h"
     22 
     23 
     24 /**
     25  * Closure for the block iterator callback.
     26  */
     27 struct BlockIteratorContext
     28 {
     29   /**
     30    * Iterator function to call for each block result.
     31    */
     32   SYNC_DB_BlockIterator it;
     33 
     34   /**
     35    * Closure for @e it.
     36    */
     37   void *it_cls;
     38 
     39   /**
     40    * Query status to return.
     41    */
     42   enum SYNC_DB_QueryStatus qs;
     43 
     44   /**
     45    * True if the account does not exist or is unpaid.
     46    */
     47   bool out_account_missing;
     48 
     49   /**
     50    * True if the requested start block does not exist.
     51    */
     52   bool out_block_missing;
     53 
     54   /**
     55    * True if the account has no blocks at all.
     56    */
     57   bool out_backup_empty;
     58 };
     59 
     60 
     61 /**
     62  * Helper function for #SYNCDB_lookup_block_range_TR().
     63  * To be called with the results of a SELECT statement
     64  * that has returned @a num_results results.
     65  *
     66  * @param cls closure of type `struct BlockIteratorContext *`
     67  * @param result the postgres result
     68  * @param num_results the number of results in @a result
     69  */
     70 static void
     71 block_range_cb (void *cls,
     72                 PGresult *result,
     73                 unsigned int num_results)
     74 {
     75   struct BlockIteratorContext *bic = cls;
     76 
     77   for (unsigned int i = 0; i < num_results; i++)
     78   {
     79     bool out_account_missing;
     80     bool out_block_missing;
     81     bool out_backup_empty;
     82     bool null_prev_nonce = false;
     83     bool null_next_nonce = false;
     84     struct SYNC_BlockNonce nonce;
     85     struct GNUNET_HashCode block_hash;
     86     struct SYNC_BlockNonce prev_nonce;
     87     struct SYNC_BlockNonce next_nonce;
     88     size_t data_size = 0;
     89     void *data = NULL;
     90     struct SYNC_AccountSignatureP upload_sig;
     91     struct GNUNET_HashCode old_hash;
     92     struct GNUNET_HashCode refs_hash;
     93     struct GNUNET_PQ_ResultSpec rs[] = {
     94       GNUNET_PQ_result_spec_bool ("out_account_missing",
     95                                   &out_account_missing),
     96       GNUNET_PQ_result_spec_bool ("out_block_missing",
     97                                   &out_block_missing),
     98       GNUNET_PQ_result_spec_bool ("out_backup_empty",
     99                                   &out_backup_empty),
    100       GNUNET_PQ_result_spec_auto_from_type ("nonce",
    101                                             &nonce),
    102       GNUNET_PQ_result_spec_auto_from_type ("block_hash",
    103                                             &block_hash),
    104       GNUNET_PQ_result_spec_allow_null (
    105         GNUNET_PQ_result_spec_auto_from_type ("prev_nonce",
    106                                               &prev_nonce),
    107         &null_prev_nonce),
    108       GNUNET_PQ_result_spec_allow_null (
    109         GNUNET_PQ_result_spec_auto_from_type ("next_nonce",
    110                                               &next_nonce),
    111         &null_next_nonce),
    112       GNUNET_PQ_result_spec_variable_size ("data_blob",
    113                                            &data,
    114                                            &data_size),
    115       GNUNET_PQ_result_spec_auto_from_type ("upload_sig",
    116                                             &upload_sig),
    117       GNUNET_PQ_result_spec_auto_from_type ("old_hash",
    118                                             &old_hash),
    119       GNUNET_PQ_result_spec_auto_from_type ("refs_hash",
    120                                             &refs_hash),
    121       GNUNET_PQ_result_spec_end,
    122     };
    123 
    124     if (GNUNET_OK !=
    125         GNUNET_PQ_extract_result (result,
    126                                   rs,
    127                                   i))
    128     {
    129       GNUNET_break (0);
    130       bic->qs = SYNC_DB_SOFT_ERROR;
    131       return;
    132     }
    133 
    134     bic->qs = i + 1;
    135     bic->out_account_missing = out_account_missing;
    136     bic->out_block_missing = out_block_missing;
    137     bic->out_backup_empty = out_backup_empty;
    138     if ( (! out_account_missing) &&
    139          (! out_block_missing) &&
    140          (! out_backup_empty) )
    141       bic->it (bic->it_cls,
    142                &nonce,
    143                &block_hash,
    144                null_prev_nonce
    145                ? NULL
    146                : &prev_nonce,
    147                null_next_nonce
    148                ? NULL
    149                : &next_nonce,
    150                data_size,
    151                data,
    152                &upload_sig,
    153                &old_hash,
    154                &refs_hash);
    155     GNUNET_PQ_cleanup_result (rs);
    156   }
    157 }
    158 
    159 
    160 enum SYNC_DB_QueryStatus
    161 SYNCDB_lookup_block_range_TR (
    162   const struct SYNC_AccountPublicKeyP *account_pub,
    163   const struct SYNC_BlockNonce *start_nonce,
    164   const int16_t limit,
    165   SYNC_DB_BlockIterator it,
    166   void *it_cls)
    167 {
    168   struct GNUNET_PQ_QueryParam params[] = {
    169     GNUNET_PQ_query_param_auto_from_type (account_pub),
    170     (NULL != start_nonce)
    171     ? GNUNET_PQ_query_param_auto_from_type (start_nonce)
    172     : GNUNET_PQ_query_param_null (),
    173     GNUNET_PQ_query_param_int16 (&limit),
    174     GNUNET_PQ_query_param_end,
    175   };
    176   struct BlockIteratorContext bic = {
    177     .it = it,
    178     .it_cls = it_cls,
    179   };
    180   enum GNUNET_DB_QueryStatus qs;
    181 
    182   SYNCDB_preflight ();
    183   PREPARE ("blocks_select_range",
    184            "SELECT"
    185            " out_account_missing"
    186            ",out_block_missing"
    187            ",out_backup_empty"
    188            ",nonce"
    189            ",block_hash"
    190            ",prev_nonce"
    191            ",next_nonce"
    192            ",data_blob"
    193            ",upload_sig"
    194            ",old_hash"
    195            ",refs_hash"
    196            " FROM sync_do_lookup_block_range"
    197            " ($1,$2,$3)");
    198   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    199                                              "blocks_select_range",
    200                                              params,
    201                                              &block_range_cb,
    202                                              &bic);
    203   switch (qs)
    204   {
    205   case GNUNET_DB_STATUS_HARD_ERROR:
    206     GNUNET_break (0);
    207     return SYNC_DB_HARD_ERROR;
    208   case GNUNET_DB_STATUS_SOFT_ERROR:
    209     return SYNC_DB_SOFT_ERROR;
    210   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    211     /* the stored procedure always returns a status row */
    212     GNUNET_break (0);
    213     return SYNC_DB_NO_RESULTS;
    214   default:
    215     break;
    216   }
    217   /* map the flags of the (single) status row to SYNC_DB codes */
    218   if (bic.out_account_missing)
    219     return SYNC_DB_PAYMENT_REQUIRED;
    220   if (bic.out_block_missing)
    221     return SYNC_DB_TARGET_MISSING;
    222   if (bic.out_backup_empty)
    223     return SYNC_DB_NO_RESULTS;
    224   return bic.qs;
    225 }
    226 
    227 
    228 /* end of syncdb_lookup_block_range_TR.c */