LCOV - code coverage report
Current view: top level - exchangedb - helper.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.3 % 6 5
Test Date: 2026-09-11 18:55:36 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :    This file is part of TALER
       3              :    Copyright (C) 2022 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 helper.h
      18              :  * @brief shared internal definitions for the Postgres exchange database
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #ifndef PG_HELPER_H
      22              : #define PG_HELPER_H
      23              : 
      24              : #include "taler/taler_dbevents.h"  /* UNNECESSARY? */
      25              : #include "taler/taler_error_codes.h"  /* UNNECESSARY? */
      26              : #include "exchangedb_lib.h"
      27              : #include "taler/taler_json_lib.h"
      28              : #include "taler/taler_pq_lib.h"
      29              : #include "taler/taler_util.h"
      30              : 
      31              : 
      32              : /**
      33              :  * Context for a Postgres database connection for the exchange.
      34              :  */
      35              : struct TALER_EXCHANGEDB_PostgresContext
      36              : {
      37              : 
      38              :   /**
      39              :    * Our configuration.
      40              :    */
      41              :   const struct GNUNET_CONFIGURATION_Handle *cfg;
      42              : 
      43              :   /**
      44              :    * Directory with SQL statements to run to create tables.
      45              :    */
      46              :   char *sql_dir;
      47              : 
      48              :   /**
      49              :    * How long are AML programs allowed to run?
      50              :    */
      51              :   struct GNUNET_TIME_Relative max_aml_program_runtime;
      52              : 
      53              :   /**
      54              :    * After how long should idle reserves be closed?
      55              :    */
      56              :   struct GNUNET_TIME_Relative idle_reserve_expiration_time;
      57              : 
      58              :   /**
      59              :    * After how long should reserves that have seen withdraw operations
      60              :    * be garbage collected?
      61              :    */
      62              :   struct GNUNET_TIME_Relative legal_reserve_expiration_time;
      63              : 
      64              :   /**
      65              :    * What delay should we introduce before ready transactions
      66              :    * are actually aggregated?
      67              :    */
      68              :   struct GNUNET_TIME_Relative aggregator_shift;
      69              : 
      70              :   /**
      71              :    * Which currency should we assume all amounts to be in?
      72              :    */
      73              :   char *currency;
      74              : 
      75              :   /**
      76              :    * Our base URL.
      77              :    */
      78              :   char *exchange_url;
      79              : 
      80              :   /**
      81              :    * Postgres connection handle.
      82              :    */
      83              :   struct GNUNET_PQ_Context *conn;
      84              : 
      85              :   /**
      86              :    * Name of the current transaction, for debugging.
      87              :    */
      88              :   const char *transaction_name;
      89              : 
      90              :   /**
      91              :    * Number of purses we allow to be opened concurrently
      92              :    * for one year per annual fee payment.
      93              :    */
      94              :   uint32_t def_purse_limit;
      95              : 
      96              : };
      97              : 
      98              : 
      99              : /**
     100              :  * Counts how often we have established a fresh @e conn
     101              :  * to the database. Used to re-prepare statements.
     102              :  */
     103              : extern unsigned long long TEH_PG_prep_gen_;
     104              : 
     105              : 
     106              : /**
     107              :  * Convert the signed @a limit of a paginated listing into the row
     108              :  * limit to pass to SQL.  The sign selects the iteration direction and
     109              :  * the magnitude the number of rows, but computing `-limit` directly is
     110              :  * undefined behaviour for `INT64_MIN`, and the resulting value would
     111              :  * reach Postgres as `LIMIT -9223372036854775808`, which errors out.
     112              :  * `INT64_MIN` is therefore saturated to `INT64_MAX`.
     113              :  *
     114              :  * @param limit signed limit as given by the caller
     115              :  * @return absolute value of @a limit, without signed overflow
     116              :  */
     117              : static inline uint64_t
     118          152 : TALER_EXCHANGEDB_abs_limit (int64_t limit)
     119              : {
     120              :   /* Postgres binds INT8 as a *signed* 64-bit integer, so a magnitude
     121              :      above INT64_MAX would reach LIMIT as a negative number. */
     122          152 :   if (INT64_MIN == limit)
     123            0 :     return (uint64_t) INT64_MAX;
     124          152 :   if (limit < 0)
     125           46 :     return (uint64_t) -limit;
     126          106 :   return (uint64_t) limit;
     127              : }
     128              : 
     129              : 
     130              : /**
     131              :  * Prepares SQL statement @a sql under @a name for
     132              :  * connection @a pg once.
     133              :  * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure.
     134              :  *
     135              :  * @param pg a `struct TALER_EXCHANGEDB_PostgresContext`
     136              :  * @param name name to prepare the statement under
     137              :  * @param sql actual SQL text
     138              :  */
     139              : #define PREPARE(pg,name,sql)                            \
     140              :         do {                                            \
     141              :           static struct {                               \
     142              :             unsigned long long cnt;                     \
     143              :             struct TALER_EXCHANGEDB_PostgresContext *pg;                 \
     144              :           } preps_[2]; /* 2 ctrs for taler-auditor-sync*/ \
     145              :           unsigned int off_ = 0;                        \
     146              :                                                         \
     147              :           while ( (off_ < sizeof(preps_) / sizeof(*preps_)) && \
     148              :                   (NULL != preps_[off_].pg) &&          \
     149              :                   (pg != preps_[off_].pg) ) {           \
     150              :             off_++;                                     \
     151              :           }                                             \
     152              :           GNUNET_assert (off_ <                         \
     153              :                          sizeof(preps_) / sizeof(*preps_)); \
     154              :           if (preps_[off_].cnt < TEH_PG_prep_gen_)      \
     155              :           {                                             \
     156              :             struct GNUNET_PQ_PreparedStatement ps[] = { \
     157              :               GNUNET_PQ_make_prepare (name, sql),       \
     158              :               GNUNET_PQ_PREPARED_STATEMENT_END          \
     159              :             };                                          \
     160              :                                                         \
     161              :             if (GNUNET_OK !=                            \
     162              :                 GNUNET_PQ_prepare_statements (pg->conn, \
     163              :                                               ps))      \
     164              :             {                                           \
     165              :               GNUNET_break (0);                         \
     166              :               return GNUNET_DB_STATUS_HARD_ERROR;       \
     167              :             }                                           \
     168              :             preps_[off_].pg = pg;                       \
     169              :             preps_[off_].cnt = TEH_PG_prep_gen_;        \
     170              :           }                                             \
     171              :         } while (0)
     172              : 
     173              : 
     174              : /**
     175              :  * Wrapper macro to add the currency from the database context in
     176              :  * the `pg` variable of the calling scope when fetching amounts from
     177              :  * the database.
     178              :  *
     179              :  * @param field name of the database field to fetch amount from
     180              :  * @param[out] amountp pointer to amount to set
     181              :  */
     182              : #define TALER_PQ_RESULT_SPEC_AMOUNT(field, \
     183              :                                     amountp) TALER_PQ_result_spec_amount ( \
     184              :           field,pg->currency,amountp)
     185              : 
     186              : 
     187              : #endif
        

Generated by: LCOV version 2.0-1