commit 8b63fe8d76052c9a2c47b154e8bdae45041d6803
parent 0df42cb55f6d2368affbb64b8777bfbd418134e7
Author: Iván Ávalos <avalos@disroot.org>
Date: Wed, 1 Jul 2026 11:58:26 +0200
Revert "refactor to use new more robust GNUNET_PQ_init() style to handle database connection drops better"
This reverts commit ea203ef668ce4be4e92048b4b4ab8c8d2ff721bc.
Diffstat:
13 files changed, 163 insertions(+), 140 deletions(-)
diff --git a/src/include/sync/sync_database_lib.h b/src/include/sync/sync_database_lib.h
@@ -37,10 +37,14 @@
* Initialize the sync database subsystem.
*
* @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 sync-dbinit should use true here.
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
enum GNUNET_GenericReturnValue
-SYNCDB_init (const struct GNUNET_CONFIGURATION_Handle *cfg);
+SYNCDB_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ bool skip_preflight);
/**
diff --git a/src/sync/sync-httpd.c b/src/sync/sync-httpd.c
@@ -555,7 +555,8 @@ run (void *cls,
}
if (GNUNET_OK !=
- SYNCDB_init (config))
+ SYNCDB_init (config,
+ false))
{
global_ret = EXIT_NOTCONFIGURED;
GNUNET_SCHEDULER_shutdown ();
diff --git a/src/sync/sync-httpd2.c b/src/sync/sync-httpd2.c
@@ -503,7 +503,8 @@ run (void *cls,
}
if (GNUNET_OK !=
- SYNCDB_init (config))
+ SYNCDB_init (config,
+ false))
{
global_ret = EXIT_NOTCONFIGURED;
GNUNET_SCHEDULER_shutdown ();
diff --git a/src/syncdb/procedures.sql.in b/src/syncdb/procedures.sql.in
@@ -22,6 +22,5 @@ SET search_path TO sync;
#include "syncdb_lookup_account_TR.sql"
#include "syncdb_store_backup_TR.sql"
#include "syncdb_update_backup_TR.sql"
-#include "syncdb_gc.sql"
COMMIT;
diff --git a/src/syncdb/sync-dbinit.c b/src/syncdb/sync-dbinit.c
@@ -55,7 +55,8 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
if (GNUNET_OK !=
- SYNCDB_init (cfg))
+ SYNCDB_init (cfg,
+ true))
{
fprintf (stderr,
"Failed to initialize database.\n");
diff --git a/src/syncdb/syncdb_create_tables.c b/src/syncdb/syncdb_create_tables.c
@@ -24,27 +24,24 @@
enum GNUNET_GenericReturnValue
SYNCDB_create_tables (void)
{
- if (GNUNET_SYSERR ==
- GNUNET_PQ_load_versioning (pg->conn))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_PQ_run_sql (pg->conn,
- "sync-"))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_PQ_exec_sql (pg->conn,
- "procedures"))
- {
- GNUNET_break (0);
+ struct GNUNET_PQ_Context *conn;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("SET search_path TO sync;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "syncdb-postgres",
+ "sync-",
+ es,
+ NULL);
+ if (NULL == conn)
return GNUNET_SYSERR;
- }
- return GNUNET_OK;
+ ret = GNUNET_PQ_exec_sql (conn,
+ "procedures");
+ GNUNET_PQ_disconnect (conn);
+ return ret;
}
diff --git a/src/syncdb/syncdb_drop_tables.c b/src/syncdb/syncdb_drop_tables.c
@@ -24,8 +24,25 @@
enum GNUNET_GenericReturnValue
SYNCDB_drop_tables (void)
{
- return GNUNET_PQ_exec_sql (pg->conn,
- "drop");
+ 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,
+ "syncdb-postgres",
+ NULL,
+ NULL,
+ NULL);
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ ret = GNUNET_PQ_exec_sql (conn,
+ "drop");
+ GNUNET_PQ_disconnect (conn);
+ return ret;
}
diff --git a/src/syncdb/syncdb_gc.c b/src/syncdb/syncdb_gc.c
@@ -27,26 +27,33 @@ SYNCDB_gc (struct GNUNET_TIME_Absolute expire_backups,
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_absolute_time (&expire_backups),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params2[] = {
GNUNET_PQ_query_param_absolute_time (&expire_pending_payments),
GNUNET_PQ_query_param_end
};
-
- if (GNUNET_OK !=
- GNUNET_PQ_prepare_anon (
- pg->conn,
- "CALL sync.sync_do_gc ($1, $2);"))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (0 > GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "",
- params))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
+ enum GNUNET_DB_QueryStatus qs;
+
+ SYNCDB_preflight ();
+ PREPARE ("gc_accounts",
+ "DELETE FROM accounts "
+ "WHERE"
+ " expiration_date < $1;");
+ PREPARE ("gc_pending_payments",
+ "DELETE FROM payments "
+ "WHERE"
+ " paid=FALSE"
+ " AND"
+ " timestamp < $1;");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "gc_accounts",
+ params);
+ if (qs < 0)
+ return qs;
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "gc_pending_payments",
+ params2);
}
diff --git a/src/syncdb/syncdb_gc.sql b/src/syncdb/syncdb_gc.sql
@@ -1,34 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 Taler Systems SA
---
--- TALER is free software; you can redistribute it and/or modify it under the
--- terms of the GNU General Public License as published by the Free Software
--- Foundation; either version 3, or (at your option) any later version.
---
--- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
--- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License along with
--- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
---
-
-DROP PROCEDURE IF EXISTS sync_do_gc;
-CREATE PROCEDURE sync_do_gc(
- in_expire_backups INT8
- ,in_expire_pending_payments INT8)
-LANGUAGE plpgsql
-AS $$
-BEGIN
- DELETE
- FROM accounts
- WHERE expiration_date < expire_backups;
- DELETE
- FROM payments
- WHERE paid=FALSE
- AND timestamp < in_expire_pending_payments;
-END $$;
-COMMENT ON PROCEDURE sync_do_gc
- IS 'Performs garbage collection on sync data';
-COMMIT;
diff --git a/src/syncdb/syncdb_pg.c b/src/syncdb/syncdb_pg.c
@@ -18,10 +18,6 @@
* @brief shared database state and helpers for sync postgres
* @author Christian Grothoff
*/
-
-struct PostgresClosure;
-#define GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE \
- struct PostgresClosure
#include "syncdb_pg.h"
#include "sync/sync_util.h"
@@ -29,63 +25,29 @@ struct PostgresClosure;
/**
* Global database closure.
*/
-// FIXME: prefix!
struct PostgresClosure *pg;
-/**
- * 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 PostgresClosure *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_try_execute ("SET enable_sort=OFF;"),
- GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
- GNUNET_PQ_make_execute ("SET search_path TO sync;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-#else
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("SET search_path TO sync;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-#endif
-
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pq,
- es))
- {
- GNUNET_break (0);
- return;
- }
- pg_->prep_gen++;
-}
-
-
enum GNUNET_GenericReturnValue
-SYNCDB_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
+SYNCDB_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ bool skip_preflight)
{
pg = GNUNET_new (struct PostgresClosure);
pg->cfg = cfg;
if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "syncdb-postgres",
+ "SQL_DIR",
+ &pg->sql_dir))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "syncdb-postgres",
+ "SQL_DIR");
+ GNUNET_free (pg);
+ pg = NULL;
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"sync",
"CURRENCY",
@@ -94,17 +56,19 @@ SYNCDB_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"sync",
"CURRENCY");
+ GNUNET_free (pg->sql_dir);
GNUNET_free (pg);
+ pg = NULL;
return GNUNET_SYSERR;
}
- pg->conn = GNUNET_PQ_init (pg->cfg,
- "merchantdb-postgres",
- &reconnect_cb,
- pg);
- if (NULL == pg->conn)
+ if ( (! skip_preflight) &&
+ (GNUNET_OK !=
+ SYNCDB_preflight ()) )
{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Database not ready. Try running sync-dbinit!\n");
SYNCDB_fini ();
- return GNUNET_NO;
+ return GNUNET_SYSERR;
}
return GNUNET_OK;
}
@@ -118,7 +82,9 @@ SYNCDB_fini (void)
if (NULL != pg->conn)
GNUNET_PQ_disconnect (pg->conn);
GNUNET_free (pg->currency);
+ GNUNET_free (pg->sql_dir);
GNUNET_free (pg);
+ pg = NULL;
}
diff --git a/src/syncdb/syncdb_pg.h b/src/syncdb/syncdb_pg.h
@@ -40,6 +40,11 @@ struct PostgresClosure
struct GNUNET_PQ_Context *conn;
/**
+ * Directory with SQL statements to run to create tables.
+ */
+ char *sql_dir;
+
+ /**
* Underlying configuration.
*/
const struct GNUNET_CONFIGURATION_Handle *cfg;
diff --git a/src/syncdb/syncdb_preflight.c b/src/syncdb/syncdb_preflight.c
@@ -21,6 +21,53 @@
#include "syncdb_pg.h"
+static enum GNUNET_GenericReturnValue
+internal_setup (void)
+{
+ 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_try_execute ("SET enable_sort=OFF;"),
+ GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
+ GNUNET_PQ_make_execute ("SET search_path TO sync;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+#else
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("SET search_path TO sync;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+#endif
+ struct GNUNET_PQ_Context *db_conn;
+
+ db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg,
+ "syncdb-postgres",
+ "sync-",
+ 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
SYNCDB_preflight (void)
{
@@ -29,11 +76,22 @@ SYNCDB_preflight (void)
GNUNET_PQ_EXECUTE_STATEMENT_END
};
- if (NULL == pg->transaction_name)
+ if (NULL == pg->conn)
+ {
+ if (GNUNET_OK !=
+ internal_setup ())
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to ensure DB is initialized\n");
+ return GNUNET_SYSERR;
+ }
+ }
+ else
{
GNUNET_PQ_reconnect_if_down (pg->conn);
- return GNUNET_OK; /* all good */
}
+ if (NULL == pg->transaction_name)
+ return GNUNET_OK; /* all good */
if (GNUNET_OK ==
GNUNET_PQ_exec_statements (pg->conn,
es))
diff --git a/src/syncdb/test_sync_db.c b/src/syncdb/test_sync_db.c
@@ -90,7 +90,8 @@ run (void *cls)
void *b = NULL;
if (GNUNET_OK !=
- SYNCDB_init (cfg))
+ SYNCDB_init (cfg,
+ true))
{
result = 77;
return;