exchange

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

pg.c (6524B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2014--2025 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 /**
     18  * @file pg.c
     19  * @brief Low-level (statement-level) Postgres database access for the exchange
     20  * @author Florian Dold
     21  * @author Christian Grothoff
     22  * @author Sree Harsha Totakura
     23  * @author Marcello Stanisci
     24  * @author Özgür Kesim
     25  */
     26 #include <poll.h>
     27 #include <pthread.h>
     28 #include <libpq-fe.h>
     29 #include "helper.h"
     30 #include "exchangedb_lib.h"
     31 #include "exchange-database/preflight.h"
     32 
     33 /**
     34  * Set to 1 to enable Postgres auto_explain module. This will
     35  * slow down things a _lot_, but also provide extensive logging
     36  * in the Postgres database logger for performance analysis.
     37  */
     38 #define AUTO_EXPLAIN 0
     39 
     40 
     41 /**
     42  * Log a really unexpected PQ error with all the details we can get hold of.
     43  *
     44  * @param result PQ result object of the PQ operation that failed
     45  * @param conn SQL connection that was used
     46  */
     47 #define BREAK_DB_ERR(result,conn) do {                                  \
     48           GNUNET_break (0);                                                   \
     49           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                                \
     50                       "Database failure: %s/%s/%s/%s/%s",                     \
     51                       PQresultErrorField (result, PG_DIAG_MESSAGE_PRIMARY),   \
     52                       PQresultErrorField (result, PG_DIAG_MESSAGE_DETAIL),    \
     53                       PQresultErrorMessage (result),                          \
     54                       PQresStatus (PQresultStatus (result)),                  \
     55                       PQerrorMessage (conn));                                 \
     56 } while (0)
     57 
     58 
     59 struct TALER_EXCHANGEDB_PostgresContext *
     60 TALER_EXCHANGEDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
     61                           bool skip_preflight)
     62 {
     63   struct TALER_EXCHANGEDB_PostgresContext *pg;
     64   unsigned long long dpl;
     65 
     66   pg = GNUNET_new (struct TALER_EXCHANGEDB_PostgresContext);
     67   pg->cfg = cfg;
     68   if (GNUNET_OK !=
     69       GNUNET_CONFIGURATION_get_value_filename (cfg,
     70                                                "exchangedb-postgres",
     71                                                "SQL_DIR",
     72                                                &pg->sql_dir))
     73   {
     74     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     75                                "exchangedb-postgres",
     76                                "SQL_DIR");
     77     goto fail;
     78   }
     79   if (GNUNET_OK !=
     80       GNUNET_CONFIGURATION_get_value_string (cfg,
     81                                              "exchange",
     82                                              "BASE_URL",
     83                                              &pg->exchange_url))
     84   {
     85     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     86                                "exchange",
     87                                "BASE_URL");
     88     goto fail;
     89   }
     90   if (GNUNET_OK !=
     91       GNUNET_CONFIGURATION_get_value_time (cfg,
     92                                            "exchangedb",
     93                                            "IDLE_RESERVE_EXPIRATION_TIME",
     94                                            &pg->idle_reserve_expiration_time))
     95   {
     96     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     97                                "exchangedb",
     98                                "IDLE_RESERVE_EXPIRATION_TIME");
     99     goto fail;
    100   }
    101   if (GNUNET_OK !=
    102       GNUNET_CONFIGURATION_get_value_time (cfg,
    103                                            "exchangedb",
    104                                            "MAX_AML_PROGRAM_RUNTIME",
    105                                            &pg->max_aml_program_runtime))
    106   {
    107     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    108                                "exchangedb",
    109                                "MAX_AML_PROGRAM_RUNTIME");
    110     goto fail;
    111   }
    112   if (GNUNET_OK !=
    113       GNUNET_CONFIGURATION_get_value_time (cfg,
    114                                            "exchangedb",
    115                                            "LEGAL_RESERVE_EXPIRATION_TIME",
    116                                            &pg->legal_reserve_expiration_time))
    117   {
    118     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    119                                "exchangedb",
    120                                "LEGAL_RESERVE_EXPIRATION_TIME");
    121     goto fail;
    122   }
    123   if (GNUNET_OK !=
    124       GNUNET_CONFIGURATION_get_value_time (cfg,
    125                                            "exchangedb",
    126                                            "AGGREGATOR_SHIFT",
    127                                            &pg->aggregator_shift))
    128   {
    129     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
    130                                "exchangedb",
    131                                "AGGREGATOR_SHIFT");
    132   }
    133   if (GNUNET_OK !=
    134       GNUNET_CONFIGURATION_get_value_number (cfg,
    135                                              "exchangedb",
    136                                              "DEFAULT_PURSE_LIMIT",
    137                                              &dpl))
    138   {
    139     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
    140                                "exchangedb",
    141                                "DEFAULT_PURSE_LIMIT");
    142     pg->def_purse_limit = 1;
    143   }
    144   else
    145   {
    146     pg->def_purse_limit = (uint32_t) dpl;
    147   }
    148 
    149   if (GNUNET_OK !=
    150       TALER_config_get_currency (cfg,
    151                                  "exchange",
    152                                  &pg->currency))
    153   {
    154     goto fail;
    155   }
    156   if (! skip_preflight)
    157   {
    158     if (GNUNET_OK !=
    159         TALER_EXCHANGEDB_preflight (pg))
    160     {
    161       goto fail;
    162     }
    163   }
    164   return pg;
    165 
    166 fail:
    167   GNUNET_free (pg->exchange_url);
    168   GNUNET_free (pg->sql_dir);
    169   GNUNET_free (pg->currency);
    170   GNUNET_free (pg);
    171   return NULL;
    172 }
    173 
    174 
    175 void
    176 TALER_EXCHANGEDB_disconnect (struct TALER_EXCHANGEDB_PostgresContext *pg)
    177 {
    178   if (NULL == pg)
    179     return;
    180   if (NULL != pg->conn)
    181   {
    182     GNUNET_PQ_disconnect (pg->conn);
    183     pg->conn = NULL;
    184   }
    185   GNUNET_free (pg->exchange_url);
    186   GNUNET_free (pg->sql_dir);
    187   GNUNET_free (pg->currency);
    188   GNUNET_free (pg);
    189 }
    190 
    191 
    192 /* end of plugin_exchangedb_postgres.c */