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