challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

pg.c (5233B)


      1 /*
      2   This file is part of Challenger
      3   (C) 2023 Taler Systems SA
      4 
      5   Challenger 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   Challenger is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of ANASTASISABILITY 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   Challenger; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file challengerdb/plugin_challengerdb_postgres.c
     18  * @brief database helper functions for postgres used by challenger
     19  * @author Christian Grothoff
     20  */
     21 struct CHALLENGERDB_PostgresContext;
     22 #define GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE \
     23         struct CHALLENGERDB_PostgresContext
     24 #include <gnunet/gnunet_util_lib.h>
     25 #include <gnunet/gnunet_db_lib.h>
     26 #include <gnunet/gnunet_pq_lib.h>
     27 #include <taler/taler_pq_lib.h>
     28 #include "challenger_database_lib.h"
     29 #include "challenger_util.h"
     30 #include "pg_helper.h"
     31 
     32 /**
     33  * Function called each time we connect or reconnect to the
     34  * database. Gives the application a chance to run some
     35  * per-connection initialization logic.
     36  *
     37  * @param pg database conntext in the auditor
     38  * @param pq database connection handle
     39  */
     40 static void
     41 reconnect_cb (struct CHALLENGERDB_PostgresContext *pg,
     42               struct GNUNET_PQ_Context *pq)
     43 {
     44 #if AUTO_EXPLAIN
     45   /* Enable verbose logging to see where queries do not
     46      properly use indices */
     47   struct GNUNET_PQ_ExecuteStatement es[] = {
     48     GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
     49     GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
     50     GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
     51     GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
     52     /* https://wiki.postgresql.org/wiki/Serializable suggests to really
     53        force the default to 'serializable' if SSI is to be used. */
     54     GNUNET_PQ_make_try_execute (
     55       "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
     56     GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
     57     GNUNET_PQ_EXECUTE_STATEMENT_END
     58   };
     59 #else
     60   struct GNUNET_PQ_ExecuteStatement es[] = {
     61     GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
     62     GNUNET_PQ_EXECUTE_STATEMENT_END
     63   };
     64 #endif
     65 
     66   if (GNUNET_OK !=
     67       GNUNET_PQ_exec_statements (pq,
     68                                  es))
     69   {
     70     GNUNET_break (0);
     71     return;
     72   }
     73   pg->prep_gen++;
     74 }
     75 
     76 
     77 /**
     78  * Connect to the db if the connection does not exist yet.
     79  *
     80  * @param[in,out] pg the database state
     81  * @return #GNUNET_OK on success
     82  */
     83 static enum GNUNET_GenericReturnValue
     84 internal_setup (struct CHALLENGERDB_PostgresContext *pg)
     85 {
     86   struct GNUNET_PQ_Context *db_conn;
     87 
     88   if (NULL != pg->conn)
     89     return GNUNET_OK;
     90   db_conn = GNUNET_PQ_init (pg->cfg,
     91                             "challengerdb-postgres",
     92                             &reconnect_cb,
     93                             pg);
     94   if (NULL == db_conn)
     95     return GNUNET_SYSERR;
     96   if (0 == pg->prep_gen)
     97   {
     98     GNUNET_PQ_disconnect (db_conn);
     99     return GNUNET_SYSERR;
    100   }
    101   pg->conn = db_conn;
    102   return GNUNET_OK;
    103 }
    104 
    105 
    106 static struct CHALLENGERDB_PostgresContext *
    107 do_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
    108             bool check_current)
    109 {
    110   struct CHALLENGERDB_PostgresContext *pg;
    111 
    112   pg = GNUNET_new (struct CHALLENGERDB_PostgresContext);
    113   pg->cfg = cfg;
    114   if (GNUNET_OK !=
    115       GNUNET_CONFIGURATION_get_value_filename (cfg,
    116                                                "challengerdb-postgres",
    117                                                "SQL_DIR",
    118                                                &pg->sql_dir))
    119   {
    120     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    121                                "challengerdb-postgres",
    122                                "SQL_DIR");
    123     GNUNET_free (pg);
    124     return NULL;
    125   }
    126   if (GNUNET_OK !=
    127       internal_setup (pg))
    128   {
    129     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    130                 "Failed to ensure DB is initialized\n");
    131     CHALLENGERDB_disconnect (pg);
    132     return NULL;
    133   }
    134   if (check_current &&
    135       (GNUNET_OK !=
    136        GNUNET_PQ_check_current (pg->conn,
    137                                 "challenger-")) )
    138   {
    139     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    140                 "Database schema is not up-to-date. Try running challenger-dbinit or challenger-dbconfig!\n");
    141     CHALLENGERDB_disconnect (pg);
    142     return NULL;
    143   }
    144   return pg;
    145 }
    146 
    147 
    148 struct CHALLENGERDB_PostgresContext *
    149 CHALLENGERDB_connect (
    150   const struct GNUNET_CONFIGURATION_Handle *cfg)
    151 {
    152   return do_connect (cfg,
    153                      true);
    154 }
    155 
    156 
    157 struct CHALLENGERDB_PostgresContext *
    158 CHALLENGERDB_connect_admin (
    159   const struct GNUNET_CONFIGURATION_Handle *cfg)
    160 {
    161   return do_connect (cfg,
    162                      false);
    163 }
    164 
    165 
    166 void
    167 CHALLENGERDB_disconnect (struct CHALLENGERDB_PostgresContext *pg)
    168 {
    169   if (NULL == pg)
    170     return;
    171   if (NULL != pg->conn)
    172     GNUNET_PQ_disconnect (pg->conn);
    173   GNUNET_free (pg->sql_dir);
    174   GNUNET_free (pg);
    175 }
    176 
    177 
    178 /* end of pg.c */