commit a6fb529dddc757000bdc88084b0d28daa86b18ca
parent d775278abdc10146b7234bcd8388f210bdf7d69e
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 13 Jun 2026 20:58:23 +0200
refactor to use new more robust GNUNET_PQ_init() style to handle database connection drops better
Diffstat:
9 files changed, 108 insertions(+), 126 deletions(-)
diff --git a/src/challenger/challenger-admin.c b/src/challenger/challenger-admin.c
@@ -100,8 +100,7 @@ run (void *cls,
return;
}
if (NULL ==
- (db = CHALLENGERDB_connect (cfg,
- false)))
+ (db = CHALLENGERDB_connect (cfg)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to initialize database connection.\n");
diff --git a/src/challenger/challenger-httpd.c b/src/challenger/challenger-httpd.c
@@ -741,21 +741,12 @@ run (void *cls,
&rc);
rc = GNUNET_CURL_gnunet_rc_create (CH_ctx);
if (NULL ==
- (CH_context = CHALLENGERDB_connect (config,
- false)))
+ (CH_context = CHALLENGERDB_connect (config)))
{
global_ret = EXIT_NOTINSTALLED;
GNUNET_SCHEDULER_shutdown ();
return;
}
- if (GNUNET_OK !=
- CHALLENGERDB_preflight (CH_context))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Database not setup. Did you run challenger-dbinit?\n");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
{
enum GNUNET_GenericReturnValue ret;
diff --git a/src/challengerdb/challenger-dbinit.c b/src/challengerdb/challenger-dbinit.c
@@ -63,8 +63,7 @@ run (void *cls,
(void) args;
(void) cfgfile;
if (NULL ==
- (db = CHALLENGERDB_connect (cfg,
- true)))
+ (db = CHALLENGERDB_connect (cfg)))
{
fprintf (stderr,
"Failed to initialize database connection.\n");
diff --git a/src/challengerdb/create_tables.c b/src/challengerdb/create_tables.c
@@ -29,22 +29,19 @@
enum GNUNET_GenericReturnValue
CHALLENGERDB_create_tables (struct CHALLENGERDB_PostgresContext *pc)
{
- struct GNUNET_PQ_Context *conn;
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
- enum GNUNET_GenericReturnValue ret;
-
- conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
- "challengerdb-postgres",
- "challenger-",
- es,
- NULL);
- if (NULL == conn)
+ if (GNUNET_OK !=
+ GNUNET_PQ_load_versioning (pc->conn))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_PQ_run_sql (pc->conn,
+ "challenger-"))
+ {
+ GNUNET_break (0);
return GNUNET_SYSERR;
- ret = GNUNET_PQ_exec_sql (conn,
- "procedures");
- GNUNET_PQ_disconnect (conn);
- return ret;
+ }
+ return GNUNET_PQ_exec_sql (pc->conn,
+ "procedures");
}
diff --git a/src/challengerdb/drop_tables.c b/src/challengerdb/drop_tables.c
@@ -29,23 +29,6 @@
enum GNUNET_GenericReturnValue
CHALLENGERDB_drop_tables (struct CHALLENGERDB_PostgresContext *pg)
{
- struct GNUNET_PQ_Context *conn;
- enum GNUNET_GenericReturnValue ret;
-
- if (NULL != pg->conn)
- {
- GNUNET_PQ_disconnect (pg->conn);
- pg->conn = NULL;
- }
- conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
- "challengerdb-postgres",
- NULL,
- NULL,
- NULL);
- if (NULL == conn)
- return GNUNET_SYSERR;
- ret = GNUNET_PQ_exec_sql (conn,
- "drop");
- GNUNET_PQ_disconnect (conn);
- return ret;
+ return GNUNET_PQ_exec_sql (pg->conn,
+ "drop");
}
diff --git a/src/challengerdb/pg.c b/src/challengerdb/pg.c
@@ -18,20 +18,93 @@
* @brief database helper functions for postgres used by challenger
* @author Christian Grothoff
*/
-#include "platform.h"
+struct CHALLENGERDB_PostgresContext;
+#define GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE \
+ struct CHALLENGERDB_PostgresContext
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_db_lib.h>
#include <gnunet/gnunet_pq_lib.h>
#include <taler/taler_pq_lib.h>
#include "challenger_database_lib.h"
#include "challenger_util.h"
-#include "challenger-database/preflight.h"
#include "pg_helper.h"
+/**
+ * Function called each time we connect or reconnect to the
+ * database. Gives the application a chance to run some
+ * per-connection initialization logic.
+ *
+ * @param pg database conntext in the auditor
+ * @param pq database connection handle
+ */
+static void
+reconnect_cb (struct CHALLENGERDB_PostgresContext *pg,
+ struct GNUNET_PQ_Context *pq)
+{
+#if AUTO_EXPLAIN
+ /* Enable verbose logging to see where queries do not
+ properly use indices */
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
+ GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
+ GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
+ GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
+ /* https://wiki.postgresql.org/wiki/Serializable suggests to really
+ force the default to 'serializable' if SSI is to be used. */
+ GNUNET_PQ_make_try_execute (
+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
+ GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+#else
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+#endif
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pq,
+ es))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ pg->prep_gen++;
+}
+
+
+/**
+ * Connect to the db if the connection does not exist yet.
+ *
+ * @param[in,out] pg the database state
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+internal_setup (struct CHALLENGERDB_PostgresContext *pg)
+{
+ struct GNUNET_PQ_Context *db_conn;
+
+ if (NULL != pg->conn)
+ return GNUNET_OK;
+ db_conn = GNUNET_PQ_init (pg->cfg,
+ "challengerdb-postgres",
+ &reconnect_cb,
+ pg);
+ if (NULL == db_conn)
+ return GNUNET_SYSERR;
+ if (0 == pg->prep_gen)
+ {
+ GNUNET_PQ_disconnect (db_conn);
+ return GNUNET_SYSERR;
+ }
+ pg->conn = db_conn;
+ return GNUNET_OK;
+}
+
struct CHALLENGERDB_PostgresContext *
-CHALLENGERDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
- bool skip_preflight)
+CHALLENGERDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct CHALLENGERDB_PostgresContext *pg;
@@ -49,15 +122,13 @@ CHALLENGERDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_free (pg);
return NULL;
}
- if (! skip_preflight)
+ if (GNUNET_OK !=
+ internal_setup (pg))
{
- if (GNUNET_OK !=
- CHALLENGERDB_preflight (pg))
- {
- GNUNET_free (pg->sql_dir);
- GNUNET_free (pg);
- return NULL;
- }
+ CHALLENGERDB_disconnect (pg);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to ensure DB is initialized\n");
+ return NULL;
}
return pg;
}
@@ -75,4 +146,4 @@ CHALLENGERDB_disconnect (struct CHALLENGERDB_PostgresContext *pg)
}
-/* end of plugin_challengerdb_postgres.c */
+/* end of pg.c */
diff --git a/src/challengerdb/preflight.c b/src/challengerdb/preflight.c
@@ -24,51 +24,6 @@
#include "pg_helper.h"
-static enum GNUNET_GenericReturnValue
-internal_setup (struct CHALLENGERDB_PostgresContext *pg)
-{
- if (NULL == pg->conn)
- {
-#if AUTO_EXPLAIN
- /* Enable verbose logging to see where queries do not
- properly use indices */
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
- GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
- GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
- GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
- /* https://wiki.postgresql.org/wiki/Serializable suggests to really
- force the default to 'serializable' if SSI is to be used. */
- GNUNET_PQ_make_try_execute (
- "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
- GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-#else
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-#endif
- struct GNUNET_PQ_Context *db_conn;
-
- db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg,
- "challengerdb-postgres",
- "challenger-",
- es,
- NULL,
- GNUNET_PQ_FLAG_CHECK_CURRENT);
- if (NULL == db_conn)
- return GNUNET_SYSERR;
- pg->conn = db_conn;
- pg->prep_gen++;
- }
- if (NULL == pg->transaction_name)
- GNUNET_PQ_reconnect_if_down (pg->conn);
- return GNUNET_OK;
-}
-
-
enum GNUNET_GenericReturnValue
CHALLENGERDB_preflight (struct CHALLENGERDB_PostgresContext *pg)
{
@@ -77,19 +32,11 @@ CHALLENGERDB_preflight (struct CHALLENGERDB_PostgresContext *pg)
GNUNET_PQ_EXECUTE_STATEMENT_END
};
- if (NULL == pg->conn)
- {
- if (GNUNET_OK !=
- internal_setup (pg))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to ensure DB is initialized\n");
- return GNUNET_SYSERR;
- }
- }
- GNUNET_PQ_reconnect_if_down (pg->conn);
if (NULL == pg->transaction_name)
+ {
+ GNUNET_PQ_reconnect_if_down (pg->conn);
return GNUNET_OK; /* all good */
+ }
if (GNUNET_OK ==
GNUNET_PQ_exec_statements (pg->conn,
es))
diff --git a/src/challengerdb/test_challenger_db.c b/src/challengerdb/test_challenger_db.c
@@ -62,8 +62,7 @@ run (void *cls)
{
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- if (NULL == (pg = CHALLENGERDB_connect (cfg,
- true)))
+ if (NULL == (pg = CHALLENGERDB_connect (cfg)))
{
result = 77;
return;
diff --git a/src/include/challenger_database_lib.h b/src/include/challenger_database_lib.h
@@ -29,14 +29,10 @@ struct CHALLENGERDB_PostgresContext;
* Connect to the challenger database.
*
* @param cfg configuration to use
- * @param skip_preflight true if we should skip the usual
- * preflight check which assures us that the DB is actually
- * operational; only challenger-dbinit should use true here.
* @return NULL on failure
*/
struct CHALLENGERDB_PostgresContext *
-CHALLENGERDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
- bool skip_preflight);
+CHALLENGERDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
/**