exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

iterate_pending_deposits.c (5873B)


      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 wire_missing_cb (void *cls,
     72                  PGresult *result,
     73                  unsigned int num_results)
     74 {
     75   struct WireMissingContext *eic = cls;
     76   struct TALER_AUDITORDB_PostgresContext *pg = eic->pg;
     77 
     78   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     struct GNUNET_PQ_ResultSpec rs[] = {
     87       GNUNET_PQ_result_spec_uint64 ("row_id",
     88                                     &row_id),
     89       GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
     90                                     &batch_deposit_serial_id),
     91       TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
     92                                    &total_amount),
     93       GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
     94                                             &wire_target_h_payto),
     95       GNUNET_PQ_result_spec_timestamp ("deadline",
     96                                        &deadline),
     97       GNUNET_PQ_result_spec_bool ("suppressed",
     98                                   &suppressed),
     99       GNUNET_PQ_result_spec_end
    100     };
    101 
    102     if (GNUNET_OK !=
    103         GNUNET_PQ_extract_result (result,
    104                                   rs,
    105                                   i))
    106     {
    107       GNUNET_break (0);
    108       eic->qs = GNUNET_DB_STATUS_HARD_ERROR;
    109       return;
    110     }
    111     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   eic->qs = num_results;
    120 }
    121 
    122 
    123 enum GNUNET_DB_QueryStatus
    124 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   uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS,
    135                                 TALER_AUDITORDB_abs_limit (limit));
    136   struct GNUNET_PQ_QueryParam params[] = {
    137     GNUNET_PQ_query_param_absolute_time (&deadline),
    138     GNUNET_PQ_query_param_uint64 (&offset),
    139     GNUNET_PQ_query_param_uint64 (&ulimit),
    140     GNUNET_PQ_query_param_bool (return_suppressed),
    141     GNUNET_PQ_query_param_end
    142   };
    143   struct WireMissingContext eic = {
    144     .cb = cb,
    145     .cb_cls = cb_cls,
    146     .pg = pg
    147   };
    148   enum GNUNET_DB_QueryStatus qs;
    149 
    150   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   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   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   if (0 > qs)
    189     return qs;
    190   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != eic.qs);
    191   return eic.qs;
    192 }