syncdb_pg.c (4504B)
1 /* 2 This file is part of TALER 3 (C) 2014--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 Lesser 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 syncdb/syncdb_pg.c 18 * @brief shared database state and helpers for sync postgres 19 * @author Christian Grothoff 20 */ 21 22 struct PostgresClosure; 23 #define GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE \ 24 struct PostgresClosure 25 #include "syncdb_pg.h" 26 #include "sync/sync_util.h" 27 28 29 /** 30 * Global database closure. 31 */ 32 // FIXME: prefix! 33 struct PostgresClosure *pg; 34 35 36 /** 37 * Function called each time we connect or reconnect to the 38 * database. Gives the application a chance to run some 39 * per-connection initialization logic. 40 * 41 * @param pg_ database conntext in the auditor 42 * @param pq database connection handle 43 */ 44 static void 45 reconnect_cb (struct PostgresClosure *pg_, 46 struct GNUNET_PQ_Context *pq) 47 { 48 #if AUTO_EXPLAIN 49 /* Enable verbose logging to see where queries do not 50 properly use indices */ 51 struct GNUNET_PQ_ExecuteStatement es[] = { 52 GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"), 53 GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"), 54 GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"), 55 GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"), 56 /* https://wiki.postgresql.org/wiki/Serializable suggests to really 57 force the default to 'serializable' if SSI is to be used. */ 58 GNUNET_PQ_make_try_execute ( 59 "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), 60 GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), 61 GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), 62 GNUNET_PQ_make_execute ("SET search_path TO sync;"), 63 GNUNET_PQ_EXECUTE_STATEMENT_END 64 }; 65 #else 66 struct GNUNET_PQ_ExecuteStatement es[] = { 67 GNUNET_PQ_make_execute ("SET search_path TO sync;"), 68 GNUNET_PQ_EXECUTE_STATEMENT_END 69 }; 70 #endif 71 72 if (GNUNET_OK != 73 GNUNET_PQ_exec_statements (pq, 74 es)) 75 { 76 GNUNET_break (0); 77 return; 78 } 79 pg_->prep_gen++; 80 } 81 82 83 /** 84 * Initialize the database connection. 85 * 86 * @param cfg configuration to use 87 * @param check_current true to check if the database schema is current 88 * @return NULL on failure 89 */ 90 static enum GNUNET_GenericReturnValue 91 do_init (const struct GNUNET_CONFIGURATION_Handle *cfg, 92 bool check_current) 93 { 94 pg = GNUNET_new (struct PostgresClosure); 95 pg->cfg = cfg; 96 if (GNUNET_OK != 97 GNUNET_CONFIGURATION_get_value_string (cfg, 98 "sync", 99 "CURRENCY", 100 &pg->currency)) 101 { 102 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 103 "sync", 104 "CURRENCY"); 105 GNUNET_free (pg); 106 return GNUNET_SYSERR; 107 } 108 pg->conn = GNUNET_PQ_init (pg->cfg, 109 "syncdb-postgres", 110 &reconnect_cb, 111 pg); 112 if (NULL == pg->conn) 113 { 114 SYNCDB_fini (); 115 return GNUNET_NO; 116 } 117 if (check_current && 118 (GNUNET_OK != 119 GNUNET_PQ_check_current (pg->conn, 120 "sync-")) ) 121 { 122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 123 "Database schema is not up-to-date. Try running sync-dbinit or sync-dbconfig!\n"); 124 SYNCDB_fini (); 125 return GNUNET_NO; 126 } 127 return GNUNET_OK; 128 } 129 130 131 enum GNUNET_GenericReturnValue 132 SYNCDB_init ( 133 const struct GNUNET_CONFIGURATION_Handle *cfg) 134 { 135 return do_init (cfg, 136 true); 137 } 138 139 140 enum GNUNET_GenericReturnValue 141 SYNCDB_init_admin ( 142 const struct GNUNET_CONFIGURATION_Handle *cfg) 143 { 144 return do_init (cfg, 145 false); 146 } 147 148 149 void 150 SYNCDB_fini (void) 151 { 152 if (NULL == pg) 153 return; 154 if (NULL != pg->conn) 155 GNUNET_PQ_disconnect (pg->conn); 156 GNUNET_free (pg->currency); 157 GNUNET_free (pg); 158 } 159 160 161 /* end of syncdb_pg.c */