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 */