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 */