Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023 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 src/auditordb/iterate_pending_deposits.c
18 : * @brief Implementation of the iterate_pending_deposits function for Postgres
19 : * @author Christian Grothoff
20 : */
21 : #include "taler/taler_pq_lib.h"
22 : #include "auditor-database/iterate_pending_deposits.h"
23 : #include "pg_helper.h"
24 :
25 :
26 : /**
27 : * Hard upper bound on the number of records returned by a single
28 : * call, regardless of the limit requested by the client.
29 : */
30 : #define MAX_RECORDS 50000
31 :
32 :
33 : /**
34 : * Closure for #wire_missing_cb().
35 : */
36 : struct WireMissingContext
37 : {
38 :
39 : /**
40 : * Function to call for each pending deposit.
41 : */
42 : TALER_AUDITORDB_WireMissingCallback cb;
43 :
44 : /**
45 : * Closure for @e cb
46 : */
47 : void *cb_cls;
48 :
49 : /**
50 : * Plugin context.
51 : */
52 : struct TALER_AUDITORDB_PostgresContext *pg;
53 :
54 : /**
55 : * Query status to return.
56 : */
57 : enum GNUNET_DB_QueryStatus qs;
58 : };
59 :
60 :
61 : /**
62 : * Helper function for #TALER_AUDITORDB_iterate_pending_deposits().
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 WireMissingContext *`
67 : * @param result the postgres result
68 : * @param num_results the number of results in @a result
69 : */
70 : static void
71 0 : wire_missing_cb (void *cls,
72 : PGresult *result,
73 : unsigned int num_results)
74 : {
75 0 : struct WireMissingContext *eic = cls;
76 0 : struct TALER_AUDITORDB_PostgresContext *pg = eic->pg;
77 :
78 0 : for (unsigned int i = 0; i < num_results; i++)
79 : {
80 : uint64_t row_id;
81 : uint64_t batch_deposit_serial_id;
82 : struct TALER_Amount total_amount;
83 : struct TALER_FullPaytoHashP wire_target_h_payto;
84 : struct GNUNET_TIME_Timestamp deadline;
85 : bool suppressed;
86 0 : struct GNUNET_PQ_ResultSpec rs[] = {
87 0 : GNUNET_PQ_result_spec_uint64 ("row_id",
88 : &row_id),
89 0 : GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
90 : &batch_deposit_serial_id),
91 0 : TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
92 : &total_amount),
93 0 : GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
94 : &wire_target_h_payto),
95 0 : GNUNET_PQ_result_spec_timestamp ("deadline",
96 : &deadline),
97 0 : GNUNET_PQ_result_spec_bool ("suppressed",
98 : &suppressed),
99 : GNUNET_PQ_result_spec_end
100 : };
101 :
102 0 : if (GNUNET_OK !=
103 0 : GNUNET_PQ_extract_result (result,
104 : rs,
105 : i))
106 : {
107 0 : GNUNET_break (0);
108 0 : eic->qs = GNUNET_DB_STATUS_HARD_ERROR;
109 0 : return;
110 : }
111 0 : eic->cb (eic->cb_cls,
112 : row_id,
113 : batch_deposit_serial_id,
114 : &total_amount,
115 : &wire_target_h_payto,
116 : deadline,
117 : suppressed);
118 : }
119 0 : eic->qs = num_results;
120 : }
121 :
122 :
123 : enum GNUNET_DB_QueryStatus
124 0 : TALER_AUDITORDB_iterate_pending_deposits (struct
125 : TALER_AUDITORDB_PostgresContext *pg,
126 : struct GNUNET_TIME_Absolute deadline,
127 : int64_t limit,
128 : uint64_t offset,
129 : bool return_suppressed,
130 : TALER_AUDITORDB_WireMissingCallback cb
131 : ,
132 : void *cb_cls)
133 : {
134 0 : uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS,
135 : TALER_AUDITORDB_abs_limit (limit));
136 0 : struct GNUNET_PQ_QueryParam params[] = {
137 0 : GNUNET_PQ_query_param_absolute_time (&deadline),
138 0 : GNUNET_PQ_query_param_uint64 (&offset),
139 0 : GNUNET_PQ_query_param_uint64 (&ulimit),
140 0 : GNUNET_PQ_query_param_bool (return_suppressed),
141 : GNUNET_PQ_query_param_end
142 : };
143 0 : struct WireMissingContext eic = {
144 : .cb = cb,
145 : .cb_cls = cb_cls,
146 : .pg = pg
147 : };
148 : enum GNUNET_DB_QueryStatus qs;
149 :
150 0 : PREPARE (pg,
151 : "iterate_pending_deposits_asc",
152 : "SELECT"
153 : " row_id"
154 : ",total_amount"
155 : ",wire_target_h_payto"
156 : ",batch_deposit_serial_id"
157 : ",deadline"
158 : ",suppressed"
159 : " FROM auditor_pending_deposits"
160 : " WHERE deadline<$1"
161 : " AND (row_id > $2)"
162 : " AND ($4 OR NOT suppressed)"
163 : " ORDER BY row_id ASC"
164 : " LIMIT $3;");
165 0 : PREPARE (pg,
166 : "iterate_pending_deposits_desc",
167 : "SELECT"
168 : " row_id"
169 : ",total_amount"
170 : ",wire_target_h_payto"
171 : ",batch_deposit_serial_id"
172 : ",deadline"
173 : ",suppressed"
174 : " FROM auditor_pending_deposits"
175 : " WHERE deadline<$1"
176 : " AND (row_id < $2)"
177 : " AND ($4 OR NOT suppressed)"
178 : " ORDER BY row_id DESC"
179 : " LIMIT $3;");
180 0 : qs = GNUNET_PQ_eval_prepared_multi_select (
181 : pg->conn,
182 : (limit > 0)
183 : ? "iterate_pending_deposits_asc"
184 : : "iterate_pending_deposits_desc",
185 : params,
186 : &wire_missing_cb,
187 : &eic);
188 0 : if (0 > qs)
189 0 : return qs;
190 0 : GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != eic.qs);
191 0 : return eic.qs;
192 : }
|