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