exchange

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

pg_preflight.c (4441B)


      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 exchangedb/pg_preflight.c
     18  * @brief Implementation of the preflight function for Postgres
     19  * @author Christian Grothoff
     20  */
     21 #include "taler/platform.h"
     22 #include "taler/taler_error_codes.h"
     23 #include "taler/taler_dbevents.h"
     24 #include "taler/taler_pq_lib.h"
     25 #include "pg_preflight.h"
     26 #include "pg_helper.h"
     27 #include "plugin_exchangedb_postgres.h"
     28 
     29 
     30 /**
     31  * Connect to the database if the connection does not exist yet
     32  * and check that we are ready to operate.
     33  *
     34  * @param pg the plugin-specific state
     35  * @return #GNUNET_OK on success
     36  */
     37 static enum GNUNET_GenericReturnValue
     38 internal_setup (struct PostgresClosure *pg)
     39 {
     40   if (NULL == pg->conn)
     41   {
     42 #if AUTO_EXPLAIN
     43     /* Enable verbose logging to see where queries do not
     44        properly use indices */
     45     struct GNUNET_PQ_ExecuteStatement es[] = {
     46       GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
     47       GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
     48       GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
     49       GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
     50       /* https://wiki.postgresql.org/wiki/Serializable suggests to really
     51          force the default to 'serializable' if SSI is to be used. */
     52       GNUNET_PQ_make_try_execute (
     53         "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
     54       GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
     55       GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
     56       GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
     57       /* Mergejoin causes issues, see Postgres #18380 */
     58       GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"),
     59       GNUNET_PQ_EXECUTE_STATEMENT_END
     60     };
     61 #else
     62     struct GNUNET_PQ_ExecuteStatement es[] = {
     63       GNUNET_PQ_make_try_execute (
     64         "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
     65       GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
     66       GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
     67       /* Mergejoin causes issues, see Postgres #18380 */
     68       GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"),
     69       GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
     70       GNUNET_PQ_EXECUTE_STATEMENT_END
     71     };
     72 #endif
     73     struct GNUNET_PQ_Context *db_conn;
     74 
     75     db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg,
     76                                            "exchangedb-postgres",
     77                                            "exchange-", /* load_path_suffix */
     78                                            es,
     79                                            NULL /* prepared statements */,
     80                                            GNUNET_PQ_FLAG_CHECK_CURRENT);
     81     if (NULL == db_conn)
     82       return GNUNET_SYSERR;
     83 
     84     pg->prep_gen++;
     85     pg->conn = db_conn;
     86   }
     87   if (NULL == pg->transaction_name)
     88     GNUNET_PQ_reconnect_if_down (pg->conn);
     89   return GNUNET_OK;
     90 }
     91 
     92 
     93 enum GNUNET_GenericReturnValue
     94 TEH_PG_preflight (void *cls)
     95 {
     96   struct PostgresClosure *pg = cls;
     97   struct GNUNET_PQ_ExecuteStatement es[] = {
     98     GNUNET_PQ_make_execute ("ROLLBACK"),
     99     GNUNET_PQ_EXECUTE_STATEMENT_END
    100   };
    101 
    102   if (GNUNET_OK !=
    103       internal_setup (pg))
    104     return GNUNET_SYSERR;
    105   if (NULL == pg->transaction_name)
    106     return GNUNET_OK; /* all good */
    107   if (GNUNET_OK ==
    108       GNUNET_PQ_exec_statements (pg->conn,
    109                                  es))
    110   {
    111     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    112                 "BUG: Preflight check rolled back transaction `%s'!\n",
    113                 pg->transaction_name);
    114   }
    115   else
    116   {
    117     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    118                 "BUG: Preflight check failed to rollback transaction `%s'!\n",
    119                 pg->transaction_name);
    120   }
    121   pg->transaction_name = NULL;
    122   return GNUNET_NO;
    123 }