get_auditor_progress.c (4641B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU 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 get_auditor_progress.c 18 * @brief Implementation of get_auditor_progress function 19 * @author Christian Grothoff 20 */ 21 #include "taler/taler_error_codes.h" 22 #include "taler/taler_pq_lib.h" 23 #include "auditor-database/get_auditor_progress.h" 24 #include "pg_helper.h" 25 26 27 /** 28 * Closure for #auditor_progress_cb(). 29 */ 30 struct AuditorProgressContext 31 { 32 33 /** 34 * Where to store results. 35 */ 36 uint64_t **dst; 37 38 /** 39 * Offset in @e dst. 40 */ 41 unsigned int off; 42 43 /** 44 * Length of array at @e dst. 45 */ 46 unsigned int len; 47 48 /** 49 * Plugin context. 50 */ 51 struct TALER_AUDITORDB_PostgresContext *pg; 52 53 /** 54 * Set to true on failure. 55 */ 56 bool failure; 57 }; 58 59 60 /** 61 * Helper function for #TALER_AUDITORDB_get_auditor_progress(). 62 * To be called with the results of a SELECT statement 63 * that has returned @a num_results results. 64 * 65 * @param cls closure of type `struct AuditorProgressContext *` 66 * @param result the postgres result 67 * @param num_results the number of results in @a result 68 */ 69 static void 70 auditor_progress_cb (void *cls, 71 PGresult *result, 72 unsigned int num_results) 73 { 74 struct AuditorProgressContext *ctx = cls; 75 76 if (num_results > ctx->len) 77 { 78 GNUNET_break (0); 79 ctx->failure = true; 80 return; 81 } 82 for (unsigned int i = 0; i < num_results; i++) 83 { 84 bool is_missing = false; 85 struct GNUNET_PQ_ResultSpec rs[] = { 86 GNUNET_PQ_result_spec_allow_null ( 87 GNUNET_PQ_result_spec_uint64 ("progress_offset", 88 ctx->dst[i]), 89 &is_missing), 90 GNUNET_PQ_result_spec_end 91 }; 92 93 if (GNUNET_OK != 94 GNUNET_PQ_extract_result (result, 95 rs, 96 i)) 97 { 98 GNUNET_break (0); 99 ctx->failure = true; 100 return; 101 } 102 if (is_missing) 103 *ctx->dst[i] = 0; 104 ctx->off++; 105 } 106 } 107 108 109 enum GNUNET_DB_QueryStatus 110 TALER_AUDITORDB_get_auditor_progress ( 111 struct TALER_AUDITORDB_PostgresContext *pg, 112 const char *progress_key, 113 uint64_t *progress_offset, 114 ...) 115 { 116 unsigned int cnt = 1; 117 va_list ap; 118 119 va_start (ap, 120 progress_offset); 121 while (NULL != va_arg (ap, 122 const char *)) 123 { 124 cnt++; 125 (void) va_arg (ap, 126 uint64_t *); 127 } 128 va_end (ap); 129 { 130 const char *keys[cnt]; 131 uint64_t *dsts[cnt]; 132 unsigned int off = 1; 133 struct GNUNET_PQ_QueryParam params[] = { 134 GNUNET_PQ_query_param_array_ptrs_string (cnt, 135 keys, 136 pg->conn), 137 GNUNET_PQ_query_param_end 138 }; 139 struct AuditorProgressContext ctx = { 140 .dst = dsts, 141 .len = cnt, 142 .pg = pg 143 }; 144 enum GNUNET_DB_QueryStatus qs; 145 146 keys[0] = progress_key; 147 dsts[0] = progress_offset; 148 va_start (ap, 149 progress_offset); 150 while (off < cnt) 151 { 152 keys[off] = va_arg (ap, 153 const char *); 154 dsts[off] = va_arg (ap, 155 uint64_t *); 156 off++; 157 } 158 GNUNET_assert (NULL == va_arg (ap, 159 const char *)); 160 va_end (ap); 161 162 PREPARE (pg, 163 "get_auditor_progress", 164 "SELECT" 165 " auditor_do_get_auditor_progress AS progress_offset" 166 " FROM auditor_do_get_auditor_progress " 167 "($1);"); 168 ctx.off = 0; 169 qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, 170 "get_auditor_progress", 171 params, 172 &auditor_progress_cb, 173 &ctx); 174 GNUNET_PQ_cleanup_query_params_closures (params); 175 if (ctx.failure) 176 return GNUNET_DB_STATUS_HARD_ERROR; 177 if (qs < 0) 178 return qs; 179 GNUNET_assert (ctx.off == cnt); 180 return qs; 181 } 182 }