commit a07cc5b2fd16149b1d023ba479fabe39ae60834e
parent 0df026b55107ae94103641ee726ec9629af4ed4b
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 22 Mar 2026 12:02:46 +0100
refactor sync: split up large DB logic into individual files, decentralize PREPARE, remove plugin
Diffstat:
57 files changed, 2403 insertions(+), 2139 deletions(-)
diff --git a/configure.ac b/configure.ac
@@ -317,6 +317,8 @@ doc/Makefile
doc/doxygen/Makefile
src/Makefile
src/include/Makefile
+src/include/sync/Makefile
+src/include/sync/sync-database/Makefile
src/lib/Makefile
src/util/Makefile
src/sync/Makefile
diff --git a/debian/libsync-dev.install b/debian/libsync-dev.install
@@ -1,2 +1,2 @@
-usr/include
+usr/include/sync/*
usr/lib/*/libsync*
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
@@ -1,12 +1,5 @@
# This Makefile.am is in the public domain
+SUBDIRS = . sync
+
EXTRA_DIST = \
platform.h
-
-talerincludedir = $(includedir)/taler
-
-talerinclude_HEADERS = \
- sync_database_lib.h \
- sync_database_plugin.h \
- sync_service.h \
- sync_testing_lib.h \
- sync_util.h
diff --git a/src/include/sync/Makefile.am b/src/include/sync/Makefile.am
@@ -0,0 +1,10 @@
+# This Makefile.am is in the public domain
+SUBDIRS = . sync-database
+
+syncincludedir = $(includedir)/sync
+
+syncinclude_HEADERS = \
+ sync_database_lib.h \
+ sync_service.h \
+ sync_testing_lib.h \
+ sync_util.h
diff --git a/src/include/sync/sync-database/Makefile.am b/src/include/sync/sync-database/Makefile.am
@@ -0,0 +1,18 @@
+# This Makefile.am is in the public domain
+SUBDIRS = .
+
+syncdbincludedir = $(includedir)/sync/sync-database
+
+syncdbinclude_HEADERS = \
+ create_tables.h \
+ common.h \
+ drop_tables.h \
+ gc.h \
+ increment_lifetime_TR.h \
+ lookup_account_TR.h \
+ lookup_backup_TR.h \
+ lookup_pending_payments_by_account_TR.h \
+ preflight.h \
+ store_backup_TR.h \
+ store_payment_TR.h \
+ update_backup_TR.h
diff --git a/src/include/sync/sync-database/common.h b/src/include/sync/sync-database/common.h
@@ -0,0 +1,72 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_common.h
+ * @brief common sync database definitions
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_COMMON_H
+#define SYNC_DATABASE_COMMON_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
+#include "sync/sync_service.h"
+#include <jansson.h>
+#include <taler/taler_util.h>
+
+
+/**
+ * Possible status codes returned from the SYNC database.
+ */
+enum SYNC_DB_QueryStatus
+{
+ /**
+ * Client claimed to be updating an existing backup, but we have none.
+ */
+ SYNC_DB_OLD_BACKUP_MISSING = -5,
+
+ /**
+ * Update failed because the old backup hash does not match what we previously had in the DB.
+ */
+ SYNC_DB_OLD_BACKUP_MISMATCH = -4,
+
+ /**
+ * Account is unpaid / does not exist.
+ */
+ SYNC_DB_PAYMENT_REQUIRED = -3,
+
+ /**
+ * Hard database issue, retries futile.
+ */
+ SYNC_DB_HARD_ERROR = -2,
+
+ /**
+ * Soft database error, retrying may help.
+ */
+ SYNC_DB_SOFT_ERROR = -1,
+
+ /**
+ * Database succeeded, but no results.
+ */
+ SYNC_DB_NO_RESULTS = 0,
+
+ /**
+ * Database succeeded, one change or result.
+ */
+ SYNC_DB_ONE_RESULT = 1
+};
+
+#endif
diff --git a/src/include/sync/sync-database/create_tables.h b/src/include/sync/sync-database/create_tables.h
@@ -0,0 +1,34 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_create_tables.h
+ * @brief create sync database tables
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_CREATE_TABLES_H
+#define SYNC_DATABASE_CREATE_TABLES_H
+
+#include <gnunet/gnunet_util_lib.h>
+
+/**
+ * Create the necessary tables if they are not present.
+ *
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+SYNCDB_create_tables (void);
+
+#endif
diff --git a/src/include/sync/sync-database/drop_tables.h b/src/include/sync/sync-database/drop_tables.h
@@ -0,0 +1,34 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_drop_tables.h
+ * @brief drop sync tables
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_DROP_TABLES_H
+#define SYNC_DATABASE_DROP_TABLES_H
+
+#include <gnunet/gnunet_util_lib.h>
+
+/**
+ * Drop sync tables. Used for testcases.
+ *
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+SYNCDB_drop_tables (void);
+
+#endif
diff --git a/src/include/sync/sync-database/gc.h b/src/include/sync/sync-database/gc.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_gc.h
+ * @brief garbage collection for sync database
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_GC_H
+#define SYNC_DATABASE_GC_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
+
+/**
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require. Deletes
+ * all user records that are not paid up (and by cascade deletes
+ * the associated recovery documents). Also deletes expired
+ * truth and financial records older than @a fin_expire.
+ *
+ * @param expire_backups backups older than the given time stamp should be garbage collected
+ * @param expire_pending_payments payments still pending from since before
+ * this value should be garbage collected
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+SYNCDB_gc (struct GNUNET_TIME_Absolute expire,
+ struct GNUNET_TIME_Absolute expire_pending_payments);
+
+#endif
diff --git a/src/include/sync/sync-database/increment_lifetime_TR.h b/src/include/sync/sync-database/increment_lifetime_TR.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_increment_lifetime_TR.h
+ * @brief increment account lifetime after payment
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_INCREMENT_LIFETIME_TR_H
+#define SYNC_DATABASE_INCREMENT_LIFETIME_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include "sync/sync_service.h"
+#include "sync/sync-database/common.h"
+
+/**
+ * Increment account lifetime and mark the associated payment
+ * as successful.
+ *
+ * @param account_pub which account received a payment
+ * @param order_id order which was paid, must be unique and match pending payment
+ * @param lifetime for how long is the account now paid (increment)
+ * @return transaction status
+ */
+enum SYNC_DB_QueryStatus
+SYNCDB_increment_lifetime_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const char *order_id,
+ struct GNUNET_TIME_Relative lifetime);
+
+#endif
diff --git a/src/include/sync/sync-database/lookup_account_TR.h b/src/include/sync/sync-database/lookup_account_TR.h
@@ -0,0 +1,40 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_lookup_account_TR.h
+ * @brief lookup account and backup metadata
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_LOOKUP_ACCOUNT_TR_H
+#define SYNC_DATABASE_LOOKUP_ACCOUNT_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include "sync/sync_service.h"
+#include "sync/sync-database/common.h"
+
+/**
+ * Lookup an account and associated backup meta data.
+ *
+ * @param account_pub account to look up
+ * @param[out] backup_hash set to hash of backup
+ * @return transaction status
+ */
+enum SYNC_DB_QueryStatus
+SYNCDB_lookup_account_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ struct GNUNET_HashCode *backup_hash);
+
+#endif
diff --git a/src/include/sync/sync-database/lookup_backup_TR.h b/src/include/sync/sync-database/lookup_backup_TR.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_lookup_backup_TR.h
+ * @brief obtain backup data
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_LOOKUP_BACKUP_TR_H
+#define SYNC_DATABASE_LOOKUP_BACKUP_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include "sync/sync_service.h"
+#include "sync/sync-database/common.h"
+
+/**
+ * Obtain backup.
+ *
+ * @param account_pub account to obtain backup for
+ * @param[out] account_sig set to signature affirming storage request
+ * @param[out] prev_hash set to hash of the previous backup (all zeros if none)
+ * @param[out] backup_hash set to hash of backup
+ * @param[out] backup_size set to number of bytes in backup
+ * @param[out] backup set to raw data to backup, caller MUST FREE
+ * @return transaction status
+ */
+enum SYNC_DB_QueryStatus
+SYNCDB_lookup_backup_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ struct SYNC_AccountSignatureP *account_sig,
+ struct GNUNET_HashCode *prev_hash,
+ struct GNUNET_HashCode *backup_hash,
+ size_t *backup_size,
+ void **backup);
+
+#endif
diff --git a/src/include/sync/sync-database/lookup_pending_payments_by_account_TR.h b/src/include/sync/sync-database/lookup_pending_payments_by_account_TR.h
@@ -0,0 +1,60 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_lookup_pending_payments_by_account_TR.h
+ * @brief lookup pending payments by account
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_LOOKUP_PENDING_PAYMENTS_BY_ACCOUNT_TR_H
+#define SYNC_DATABASE_LOOKUP_PENDING_PAYMENTS_BY_ACCOUNT_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
+#include "sync/sync_service.h"
+
+
+/**
+ * Function called on all pending payments for an account.
+ *
+ * @param cls closure
+ * @param timestamp for how long have we been waiting
+ * @param order_id order id in the backend
+ * @param token claim token, or NULL for none
+ * @param amount how much is the order for
+ */
+typedef void
+(*SYNC_DB_PaymentPendingIterator)(void *cls,
+ struct GNUNET_TIME_Timestamp timestamp,
+ const char *order_id,
+ const struct TALER_ClaimTokenP *token,
+ const struct TALER_Amount *amount);
+
+
+/**
+ * Lookup pending payments by account.
+ *
+ * @param account_pub account to look for pending payments under
+ * @param it iterator to call on all pending payments
+ * @param it_cls closure for @a it
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+SYNCDB_lookup_pending_payments_by_account_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ SYNC_DB_PaymentPendingIterator it,
+ void *it_cls);
+
+#endif
diff --git a/src/include/sync/sync-database/preflight.h b/src/include/sync/sync-database/preflight.h
@@ -0,0 +1,38 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_preflight.h
+ * @brief preflight check for sync database
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_PREFLIGHT_H
+#define SYNC_DATABASE_PREFLIGHT_H
+
+#include <gnunet/gnunet_util_lib.h>
+
+/**
+ * Do a pre-flight check that we are not in an uncommitted transaction.
+ * If we are, try to commit the previous transaction and output a warning.
+ * Does not return anything, as we will continue regardless of the outcome.
+ *
+ * @return #GNUNET_OK if everything is fine
+ * #GNUNET_NO if a transaction was rolled back
+ * #GNUNET_SYSERR on hard errors
+ */
+enum GNUNET_GenericReturnValue
+SYNCDB_preflight (void);
+
+#endif
diff --git a/src/include/sync/sync-database/store_backup_TR.h b/src/include/sync/sync-database/store_backup_TR.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_store_backup_TR.h
+ * @brief store first backup
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_STORE_BACKUP_TR_H
+#define SYNC_DATABASE_STORE_BACKUP_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include "sync/sync_service.h"
+#include "sync/sync-database/common.h"
+
+/**
+ * Store backup. Only applicable for the FIRST backup under
+ * an @a account_pub. Use @e SYNCDB_update_backup_TR to update an
+ * existing backup.
+ *
+ * @param account_pub account to store @a backup under
+ * @param account_sig signature affirming storage request
+ * @param backup_hash hash of @a backup
+ * @param backup_size number of bytes in @a backup
+ * @param backup raw data to backup
+ * @return transaction status
+ */
+enum SYNC_DB_QueryStatus
+SYNCDB_store_backup_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const struct SYNC_AccountSignatureP *account_sig,
+ const struct GNUNET_HashCode *backup_hash,
+ size_t backup_size,
+ const void *backup);
+
+#endif
diff --git a/src/include/sync/sync-database/store_payment_TR.h b/src/include/sync/sync-database/store_payment_TR.h
@@ -0,0 +1,47 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_store_payment_TR.h
+ * @brief store payment for sync database
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_STORE_PAYMENT_TR_H
+#define SYNC_DATABASE_STORE_PAYMENT_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include "sync/sync_service.h"
+#include <taler/taler_util.h>
+#include "sync/sync-database/common.h"
+
+/**
+ * Store payment. Used to begin a payment, not indicative
+ * that the payment actually was made. (That is done
+ * when we increment the account's lifetime.)
+ *
+ * @param account_pub account to store @a backup under
+ * @param order_id order we created
+ * @param token claim token, or NULL for none
+ * @param amount how much we asked for
+ * @return transaction status
+ */
+enum SYNC_DB_QueryStatus
+SYNCDB_store_payment_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const char *order_id,
+ const struct TALER_ClaimTokenP *token,
+ const struct TALER_Amount *amount);
+
+#endif
diff --git a/src/include/sync/sync-database/update_backup_TR.h b/src/include/sync/sync-database/update_backup_TR.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2019, 2021 Taler Systems SA
+
+ Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_update_backup_TR.h
+ * @brief update existing backup
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_DATABASE_UPDATE_BACKUP_TR_H
+#define SYNC_DATABASE_UPDATE_BACKUP_TR_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include "sync/sync_service.h"
+#include "sync/sync-database/common.h"
+
+/**
+ * Update backup.
+ *
+ * @param account_pub account to store @a backup under
+ * @param old_backup_hash hash of the previous backup (must match)
+ * @param account_sig signature affirming storage request
+ * @param backup_hash hash of @a backup
+ * @param backup_size number of bytes in @a backup
+ * @param backup raw data to backup
+ * @return transaction status
+ */
+enum SYNC_DB_QueryStatus
+SYNCDB_update_backup_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const struct GNUNET_HashCode *old_backup_hash,
+ const struct SYNC_AccountSignatureP *account_sig,
+ const struct GNUNET_HashCode *backup_hash,
+ size_t backup_size,
+ const void *backup);
+
+#endif
diff --git a/src/include/sync/sync_database_lib.h b/src/include/sync/sync_database_lib.h
@@ -0,0 +1,59 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2017 Inria & GNUnet e.V.
+
+ 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/>
+*/
+/**
+ * @file include/sync_database_lib.h
+ * @brief sync database library interface
+ */
+#ifndef SYNC_DB_LIB_H
+#define SYNC_DB_LIB_H
+
+#include <taler/taler_util.h>
+#include <sync/sync-database/drop_tables.h>
+#include <sync/sync-database/create_tables.h>
+#include <sync/sync-database/preflight.h>
+#include <sync/sync-database/gc.h>
+#include <sync/sync-database/store_payment_TR.h>
+#include <sync/sync-database/lookup_pending_payments_by_account_TR.h>
+#include <sync/sync-database/store_backup_TR.h>
+#include <sync/sync-database/update_backup_TR.h>
+#include <sync/sync-database/lookup_account_TR.h>
+#include <sync/sync-database/lookup_backup_TR.h>
+#include <sync/sync-database/increment_lifetime_TR.h>
+
+/**
+ * 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,
+ bool skip_preflight);
+
+
+/**
+ * Shutdown the sync database subsystem.
+ */
+void
+SYNCDB_fini (void);
+
+
+#endif /* SYNC_DB_LIB_H */
+
+/* end of sync_database_lib.h */
diff --git a/src/include/sync_service.h b/src/include/sync/sync_service.h
diff --git a/src/include/sync/sync_testing_lib.h b/src/include/sync/sync_testing_lib.h
@@ -0,0 +1,135 @@
+/*
+ This file is part of TALER
+ (C) 2018, 2019 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/>
+*/
+/**
+ * @file include/sync_testing_lib.h
+ * @brief API for writing an interpreter to test SYNC components
+ * @author Christian Grothoff <christian@grothoff.org>
+ */
+#ifndef SYNC_TESTING_LIB_H
+#define SYNC_TESTING_LIB_H
+
+#include "sync/sync_service.h"
+#include <gnunet/gnunet_json_lib.h>
+#include <taler/taler_testing_lib.h>
+#include <microhttpd.h>
+
+
+/**
+ * Make the "backup download" command for a non-existent upload.
+ *
+ * @param label command label
+ * @param sync_url base URL of the sync serving
+ * the policy store request.
+ * @return the command
+ */
+struct TALER_TESTING_Command
+SYNC_TESTING_cmd_backup_nx (const char *label,
+ const char *sync_url);
+
+
+/**
+ * Make the "backup download" command.
+ *
+ * @param label command label
+ * @param sync_url base URL of the sync serving
+ * the policy store request.
+ * @param http_status expected HTTP status.
+ * @param upload_ref reference to upload command
+ * @return the command
+ */
+struct TALER_TESTING_Command
+SYNC_TESTING_cmd_backup_download (const char *label,
+ const char *sync_url,
+ unsigned int http_status,
+ const char *upload_ref);
+
+
+/**
+ * Types of options for performing the upload. Used as a bitmask.
+ */
+enum SYNC_TESTING_UploadOption
+{
+ /**
+ * Do everything by the book.
+ */
+ SYNC_TESTING_UO_NONE = 0,
+
+ /**
+ * Use random hash for previous upload instead of correct
+ * previous hash.
+ */
+ SYNC_TESTING_UO_PREV_HASH_WRONG = 1,
+
+ /**
+ * Request payment.
+ */
+ SYNC_TESTING_UO_REQUEST_PAYMENT = 2,
+
+ /**
+ * Reference payment order ID from linked previous upload.
+ */
+ SYNC_TESTING_UO_REFERENCE_ORDER_ID = 4
+
+
+};
+
+
+/**
+ * Make the "backup upload" command.
+ *
+ * @param label command label
+ * @param sync_url base URL of the sync serving
+ * the policy store request.
+ * @param prev_upload reference to a previous upload we are
+ * supposed to update, NULL for none
+ * @param last_upload reference to the last upload for the
+ * same account, used to check result on MHD_HTTP_CONFLICT
+ * @param uo upload options
+ * @param http_status expected HTTP status.
+ * @param backup_data data to upload
+ * @param backup_data_size number of bytes in @a backup_data
+ * @return the command
+ */
+struct TALER_TESTING_Command
+SYNC_TESTING_cmd_backup_upload (const char *label,
+ const char *sync_url,
+ const char *prev_upload,
+ const char *last_upload,
+ enum SYNC_TESTING_UploadOption uo,
+ unsigned int http_status,
+ const void *backup_data,
+ size_t backup_data_size);
+
+/**
+ * Call @a op on all simple traits.
+ *
+ * @param op macro to call
+ */
+#define SYNC_TESTING_SIMPLE_TRAITS(op) \
+ op (sync_account_pub, const struct SYNC_AccountPublicKeyP) \
+ op (sync_account_priv, const struct SYNC_AccountPrivateKeyP) \
+ op (prev_hash, const struct GNUNET_HashCode) \
+ op (curr_hash, const struct GNUNET_HashCode)
+
+
+/* FIXME: eventually switch to libgnunettesting with the SYNC_ prefix for
+ the symbols instead of TALER_TESTING_! */
+SYNC_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT)
+
+#endif
diff --git a/src/include/sync_util.h b/src/include/sync/sync_util.h
diff --git a/src/include/sync_database_lib.h b/src/include/sync_database_lib.h
@@ -1,50 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2017 Inria & GNUnet e.V.
-
- 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/>
-*/
-/**
- *
- */
-#ifndef SYNC_DB_LIB_H
-#define SYNC_DB_LIB_H
-
-#include <taler/taler_util.h>
-#include "sync_database_plugin.h"
-
-/**
- * Initialize the plugin.
- *
- * @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 NULL on failure
- */
-struct SYNC_DatabasePlugin *
-SYNC_DB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg,
- bool skip_preflight);
-
-
-/**
- * Shutdown the plugin.
- *
- * @param[in] plugin plugin to unload
- */
-void
-SYNC_DB_plugin_unload (struct SYNC_DatabasePlugin *plugin);
-
-
-#endif /* SYNC_DB_LIB_H */
-
-/* end of sync_database_lib.h */
diff --git a/src/include/sync_database_plugin.h b/src/include/sync_database_plugin.h
@@ -1,297 +0,0 @@
-/*
- This file is part of GNU Taler
- Copyright (C) 2019, 2021 Taler Systems SA
-
- Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser 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.GPL. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file include/sync_database_plugin.h
- * @brief database access for Sync
- * @author Christian Grothoff
- */
-#ifndef SYNC_DATABASE_PLUGIN_H
-#define SYNC_DATABASE_PLUGIN_H
-
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_db_lib.h>
-#include "sync_service.h"
-#include <jansson.h>
-#include <taler/taler_util.h>
-
-
-/**
- * Possible status codes returned from the SYNC database.
- */
-enum SYNC_DB_QueryStatus
-{
- /**
- * Client claimed to be updating an existing backup, but we have none.
- */
- SYNC_DB_OLD_BACKUP_MISSING = -5,
-
- /**
- * Update failed because the old backup hash does not match what we previously had in the DB.
- */
- SYNC_DB_OLD_BACKUP_MISMATCH = -4,
-
- /**
- * Account is unpaid / does not exist.
- */
- SYNC_DB_PAYMENT_REQUIRED = -3,
-
- /**
- * Hard database issue, retries futile.
- */
- SYNC_DB_HARD_ERROR = -2,
-
- /**
- * Soft database error, retrying may help.
- */
- SYNC_DB_SOFT_ERROR = -1,
-
- /**
- * Database succeeded, but no results.
- */
- SYNC_DB_NO_RESULTS = 0,
-
- /**
- * Database succeeded, one change or result.
- */
- SYNC_DB_ONE_RESULT = 1
-};
-
-
-/**
- * Function called on all pending payments for an account.
- *
- * @param cls closure
- * @param timestamp for how long have we been waiting
- * @param order_id order id in the backend
- * @param token claim token, or NULL for none
- * @param amount how much is the order for
- */
-typedef void
-(*SYNC_DB_PaymentPendingIterator)(void *cls,
- struct GNUNET_TIME_Timestamp timestamp,
- const char *order_id,
- const struct TALER_ClaimTokenP *token,
- const struct TALER_Amount *amount);
-
-
-/**
- * Handle to interact with the database.
- *
- * Functions ending with "_TR" run their OWN transaction scope
- * and MUST NOT be called from within a transaction setup by the
- * caller. Functions ending with "_NT" require the caller to
- * setup a transaction scope. Functions without a suffix are
- * simple, single SQL queries that MAY be used either way.
- */
-struct SYNC_DatabasePlugin
-{
-
- /**
- * Closure for all callbacks.
- */
- void *cls;
-
- /**
- * Name of the library which generated this plugin. Set by the
- * plugin loader.
- */
- char *library_name;
-
- /**
- * Drop sync tables. Used for testcases.
- *
- * @param cls closure
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
- enum GNUNET_GenericReturnValue
- (*drop_tables)(void *cls);
-
-
- /**
- * Create the necessary tables if they are not present
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
- enum GNUNET_GenericReturnValue
- (*create_tables)(void *cls);
-
-
- /**
- * Do a pre-flight check that we are not in an uncommitted transaction.
- * If we are, try to commit the previous transaction and output a warning.
- * Does not return anything, as we will continue regardless of the outcome.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @return #GNUNET_OK if everything is fine
- * #GNUNET_NO if a transaction was rolled back
- * #GNUNET_SYSERR on hard errors
- */
- enum GNUNET_GenericReturnValue
- (*preflight)(void *cls);
-
-
- /**
- * Function called to perform "garbage collection" on the
- * database, expiring records we no longer require. Deletes
- * all user records that are not paid up (and by cascade deletes
- * the associated recovery documents). Also deletes expired
- * truth and financial records older than @a fin_expire.
- *
- * @param cls closure
- * @param expire_backups backups older than the given time stamp should be garbage collected
- * @param expire_pending_payments payments still pending from since before
- * this value should be garbage collected
- * @return transaction status
- */
- enum GNUNET_DB_QueryStatus
- (*gc)(void *cls,
- struct GNUNET_TIME_Absolute expire,
- struct GNUNET_TIME_Absolute expire_pending_payments);
-
-
- /**
- * Store backup. Only applicable for the FIRST backup under
- * an @a account_pub. Use @e update_backup_TR to update an
- * existing backup.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param account_sig signature affirming storage request
- * @param backup_hash hash of @a backup
- * @param backup_size number of bytes in @a backup
- * @param backup raw data to backup
- * @return transaction status
- */
- enum SYNC_DB_QueryStatus
- (*store_backup_TR)(void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const struct SYNC_AccountSignatureP *account_sig,
- const struct GNUNET_HashCode *backup_hash,
- size_t backup_size,
- const void *backup);
-
-
- /**
- * Store payment. Used to begin a payment, not indicative
- * that the payment actually was made. (That is done
- * when we increment the account's lifetime.)
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param order_id order we created
- * @param token claim token, or NULL for none
- * @param amount how much we asked for
- * @return transaction status
- */
- enum SYNC_DB_QueryStatus
- (*store_payment_TR)(void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const char *order_id,
- const struct TALER_ClaimTokenP *token,
- const struct TALER_Amount *amount);
-
-
- /**
- * Lookup pending payments by account.
- *
- * @param cls closure
- * @param account_pub account to look for pending payments under
- * @param it iterator to call on all pending payments
- * @param it_cls closure for @a it
- * @return transaction status
- */
- enum GNUNET_DB_QueryStatus
- (*lookup_pending_payments_by_account_TR)(void *cls,
- const struct
- SYNC_AccountPublicKeyP *account_pub,
- SYNC_DB_PaymentPendingIterator it,
- void *it_cls);
-
- /**
- * Update backup.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param account_sig signature affirming storage request
- * @param old_backup_hash hash of the previous backup (must match)
- * @param backup_hash hash of @a backup
- * @param backup_size number of bytes in @a backup
- * @param backup raw data to backup
- * @return transaction status
- */
- enum SYNC_DB_QueryStatus
- (*update_backup_TR)(void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const struct GNUNET_HashCode *old_backup_hash,
- const struct SYNC_AccountSignatureP *account_sig,
- const struct GNUNET_HashCode *backup_hash,
- size_t backup_size,
- const void *backup);
-
-
- /**
- * Lookup an account and associated backup meta data.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param backup_hash[OUT] set to hash of @a backup
- * @return transaction status
- */
- enum SYNC_DB_QueryStatus
- (*lookup_account_TR)(void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- struct GNUNET_HashCode *backup_hash);
-
-
- /**
- * Obtain backup.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param account_sig[OUT] set to signature affirming storage request
- * @param prev_hash[OUT] set to hash of the previous @a backup (all zeros if none)
- * @param backup_hash[OUT] set to hash of @a backup
- * @param backup_size[OUT] set to number of bytes in @a backup
- * @param backup[OUT] set to raw data to backup, caller MUST FREE
- */
- enum SYNC_DB_QueryStatus
- (*lookup_backup_TR)(void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- struct SYNC_AccountSignatureP *account_sig,
- struct GNUNET_HashCode *prev_hash,
- struct GNUNET_HashCode *backup_hash,
- size_t *backup_size,
- void **backup);
-
- /**
- * Increment account lifetime and mark the associated payment
- * as successful.
- *
- * @param cls closure
- * @param account_pub which account received a payment
- * @param order_id order which was paid, must be unique and match pending payment
- * @param lifetime for how long is the account now paid (increment)
- * @return transaction status
- */
- enum SYNC_DB_QueryStatus
- (*increment_lifetime_TR)(void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const char *order_id,
- struct GNUNET_TIME_Relative lifetime);
-
-};
-#endif
diff --git a/src/include/sync_testing_lib.h b/src/include/sync_testing_lib.h
@@ -1,135 +0,0 @@
-/*
- This file is part of TALER
- (C) 2018, 2019 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/>
-*/
-/**
- * @file include/sync_testing_lib.h
- * @brief API for writing an interpreter to test SYNC components
- * @author Christian Grothoff <christian@grothoff.org>
- */
-#ifndef SYNC_TESTING_LIB_H
-#define SYNC_TESTING_LIB_H
-
-#include "sync_service.h"
-#include <gnunet/gnunet_json_lib.h>
-#include <taler/taler_testing_lib.h>
-#include <microhttpd.h>
-
-
-/**
- * Make the "backup download" command for a non-existent upload.
- *
- * @param label command label
- * @param sync_url base URL of the sync serving
- * the policy store request.
- * @return the command
- */
-struct TALER_TESTING_Command
-SYNC_TESTING_cmd_backup_nx (const char *label,
- const char *sync_url);
-
-
-/**
- * Make the "backup download" command.
- *
- * @param label command label
- * @param sync_url base URL of the sync serving
- * the policy store request.
- * @param http_status expected HTTP status.
- * @param upload_ref reference to upload command
- * @return the command
- */
-struct TALER_TESTING_Command
-SYNC_TESTING_cmd_backup_download (const char *label,
- const char *sync_url,
- unsigned int http_status,
- const char *upload_ref);
-
-
-/**
- * Types of options for performing the upload. Used as a bitmask.
- */
-enum SYNC_TESTING_UploadOption
-{
- /**
- * Do everything by the book.
- */
- SYNC_TESTING_UO_NONE = 0,
-
- /**
- * Use random hash for previous upload instead of correct
- * previous hash.
- */
- SYNC_TESTING_UO_PREV_HASH_WRONG = 1,
-
- /**
- * Request payment.
- */
- SYNC_TESTING_UO_REQUEST_PAYMENT = 2,
-
- /**
- * Reference payment order ID from linked previous upload.
- */
- SYNC_TESTING_UO_REFERENCE_ORDER_ID = 4
-
-
-};
-
-
-/**
- * Make the "backup upload" command.
- *
- * @param label command label
- * @param sync_url base URL of the sync serving
- * the policy store request.
- * @param prev_upload reference to a previous upload we are
- * supposed to update, NULL for none
- * @param last_upload reference to the last upload for the
- * same account, used to check result on MHD_HTTP_CONFLICT
- * @param uo upload options
- * @param http_status expected HTTP status.
- * @param backup_data data to upload
- * @param backup_data_size number of bytes in @a backup_data
- * @return the command
- */
-struct TALER_TESTING_Command
-SYNC_TESTING_cmd_backup_upload (const char *label,
- const char *sync_url,
- const char *prev_upload,
- const char *last_upload,
- enum SYNC_TESTING_UploadOption uo,
- unsigned int http_status,
- const void *backup_data,
- size_t backup_data_size);
-
-/**
- * Call @a op on all simple traits.
- *
- * @param op macro to call
- */
-#define SYNC_TESTING_SIMPLE_TRAITS(op) \
- op (sync_account_pub, const struct SYNC_AccountPublicKeyP) \
- op (sync_account_priv, const struct SYNC_AccountPrivateKeyP) \
- op (prev_hash, const struct GNUNET_HashCode) \
- op (curr_hash, const struct GNUNET_HashCode)
-
-
-/* FIXME: eventually switch to libgnunettesting with the SYNC_ prefix for
- the symbols instead of TALER_TESTING_! */
-SYNC_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT)
-
-#endif
diff --git a/src/lib/sync_api_download.c b/src/lib/sync_api_download.c
@@ -29,7 +29,7 @@
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include <taler/taler_signatures.h>
-#include "sync_service.h"
+#include "sync/sync_service.h"
#include "sync_api_curl_defaults.h"
diff --git a/src/lib/sync_api_upload.c b/src/lib/sync_api_upload.c
@@ -30,7 +30,7 @@
#include <gnunet/gnunet_curl_lib.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
-#include "sync_service.h"
+#include "sync/sync_service.h"
#include "sync_api_curl_defaults.h"
diff --git a/src/sync/sync-httpd.c b/src/sync/sync-httpd.c
@@ -21,10 +21,10 @@
#include "platform.h"
#include <microhttpd.h>
#include <gnunet/gnunet_util_lib.h>
-#include "sync_util.h"
+#include "sync/sync_util.h"
#include "sync-httpd.h"
#include "sync-httpd_mhd.h"
-#include "sync_database_lib.h"
+#include "sync/sync_database_lib.h"
#include "sync-httpd_backup.h"
#include "sync-httpd_config.h"
@@ -75,11 +75,6 @@ static int global_ret;
static bool have_daemons;
/**
- * Connection handle to the our database
- */
-struct SYNC_DatabasePlugin *db;
-
-/**
* Username and password to use for client authentication
* (optional).
*/
@@ -337,11 +332,7 @@ do_shutdown (void *cls)
rc = NULL;
}
TALER_MHD_daemons_destroy ();
- if (NULL != db)
- {
- SYNC_DB_plugin_unload (db);
- db = NULL;
- }
+ SYNCDB_fini ();
}
@@ -563,16 +554,16 @@ run (void *cls,
GNUNET_free (auth_header);
}
- if (NULL ==
- (db = SYNC_DB_plugin_load (config,
- false)))
+ if (GNUNET_OK !=
+ SYNCDB_init (config,
+ false))
{
global_ret = EXIT_NOTCONFIGURED;
GNUNET_SCHEDULER_shutdown ();
return;
}
if (GNUNET_OK !=
- db->preflight (db->cls))
+ SYNCDB_preflight ())
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Database not setup. Did you run sync-dbinit?\n");
diff --git a/src/sync/sync-httpd.h b/src/sync/sync-httpd.h
@@ -24,7 +24,7 @@
#include "platform.h"
#include <microhttpd.h>
#include <taler/taler_mhd_lib.h>
-#include "sync_database_lib.h"
+#include "sync/sync_database_lib.h"
#include <gnunet/gnunet_mhd_compat.h>
/**
@@ -124,11 +124,6 @@ struct TM_HandlerContext
/**
- * Handle to the database backend.
- */
-extern struct SYNC_DatabasePlugin *db;
-
-/**
* Upload limit to the service, in megabytes.
*/
extern unsigned long long SH_upload_limit_mb;
diff --git a/src/sync/sync-httpd2.c b/src/sync/sync-httpd2.c
@@ -20,9 +20,9 @@
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
-#include "sync_util.h"
+#include "sync/sync_util.h"
#include "sync-httpd2.h"
-#include "sync_database_lib.h"
+#include "sync/sync_database_lib.h"
#include "sync-httpd2_backup.h"
#include "sync-httpd2_config.h"
@@ -73,11 +73,6 @@ static int global_ret;
static bool have_daemons;
/**
- * Connection handle to the our database
- */
-struct SYNC_DatabasePlugin *db;
-
-/**
* Username and password to use for client authentication
* (optional).
*/
@@ -321,11 +316,7 @@ do_shutdown (void *cls)
rc = NULL;
}
TALER_MHD2_daemons_destroy ();
- if (NULL != db)
- {
- SYNC_DB_plugin_unload (db);
- db = NULL;
- }
+ SYNCDB_fini ();
}
@@ -511,16 +502,16 @@ run (void *cls,
GNUNET_free (auth_header);
}
- if (NULL ==
- (db = SYNC_DB_plugin_load (config,
- false)))
+ if (GNUNET_OK !=
+ SYNCDB_init (config,
+ false))
{
global_ret = EXIT_NOTCONFIGURED;
GNUNET_SCHEDULER_shutdown ();
return;
}
if (GNUNET_OK !=
- db->preflight (db->cls))
+ SYNCDB_preflight ())
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Database not setup. Did you run sync-dbinit?\n");
diff --git a/src/sync/sync-httpd2.h b/src/sync/sync-httpd2.h
@@ -24,7 +24,7 @@
#include "platform.h"
#include <microhttpd2.h>
#include <taler/taler_mhd2_lib.h>
-#include "sync_database_lib.h"
+#include "sync/sync_database_lib.h"
/**
* @brief Struct describing an URL and the handler for it.
@@ -97,11 +97,6 @@ struct TM_HandlerContext
/**
- * Handle to the database backend.
- */
-extern struct SYNC_DatabasePlugin *db;
-
-/**
* Upload limit to the service, in megabytes.
*/
extern unsigned long long SH_upload_limit_mb;
diff --git a/src/sync/sync-httpd2_backup-post.c b/src/sync/sync-httpd2_backup-post.c
@@ -311,11 +311,11 @@ proposal_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Storing payment request for order `%s'\n",
por->details.ok.order_id);
- qs = db->store_payment_TR (db->cls,
- &bc->account,
- por->details.ok.order_id,
- por->details.ok.token,
- &SH_annual_fee);
+ qs = SYNCDB_store_payment_TR (
+ &bc->account,
+ por->details.ok.order_id,
+ por->details.ok.token,
+ &SH_annual_fee);
if (0 >= qs)
{
GNUNET_break (0);
@@ -429,10 +429,10 @@ check_payment_cb (void *cls,
{
enum SYNC_DB_QueryStatus qs;
- qs = db->increment_lifetime_TR (db->cls,
- &bc->account,
- bc->order_id,
- GNUNET_TIME_UNIT_YEARS); /* always annual */
+ qs = SYNCDB_increment_lifetime_TR (
+ &bc->account,
+ bc->order_id,
+ GNUNET_TIME_UNIT_YEARS); /* always annual */
if (0 <= qs)
return; /* continue as planned */
GNUNET_break (0);
@@ -519,10 +519,10 @@ begin_payment (struct BackupContext *bc,
{
enum GNUNET_DB_QueryStatus qs;
- qs = db->lookup_pending_payments_by_account_TR (db->cls,
- &bc->account,
- &ongoing_payment_cb,
- bc);
+ qs = SYNCDB_lookup_pending_payments_by_account_TR (
+ &bc->account,
+ &ongoing_payment_cb,
+ bc);
if (qs < 0)
{
GNUNET_break (0);
@@ -712,24 +712,24 @@ handle_upload (void *upload_cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Uploading first backup to account\n");
- qs = db->store_backup_TR (db->cls,
- &bc->account,
- &bc->account_sig,
- &bc->new_backup_hash,
- content_data_size,
- content_data);
+ qs = SYNCDB_store_backup_TR (
+ &bc->account,
+ &bc->account_sig,
+ &bc->new_backup_hash,
+ content_data_size,
+ content_data);
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Uploading existing backup of account\n");
- qs = db->update_backup_TR (db->cls,
- &bc->account,
- &bc->old_backup_hash,
- &bc->account_sig,
- &bc->new_backup_hash,
- content_data_size,
- content_data);
+ qs = SYNCDB_update_backup_TR (
+ &bc->account,
+ &bc->old_backup_hash,
+ &bc->account_sig,
+ &bc->new_backup_hash,
+ content_data_size,
+ content_data);
}
if (qs < 0)
{
@@ -924,9 +924,9 @@ SH_backup_post (struct MHD_Request *request,
struct GNUNET_HashCode hc;
enum SYNC_DB_QueryStatus qs;
- qs = db->lookup_account_TR (db->cls,
- account,
- &hc);
+ qs = SYNCDB_lookup_account_TR (
+ account,
+ &hc);
if (qs < 0)
{
bool suspend;
diff --git a/src/sync/sync-httpd2_backup.c b/src/sync/sync-httpd2_backup.c
@@ -39,9 +39,9 @@ SH_backup_get (struct MHD_Request *request,
struct GNUNET_HashCode backup_hash;
enum SYNC_DB_QueryStatus qs;
- qs = db->lookup_account_TR (db->cls,
- account,
- &backup_hash);
+ qs = SYNCDB_lookup_account_TR (
+ account,
+ &backup_hash);
switch (qs)
{
case SYNC_DB_OLD_BACKUP_MISSING:
@@ -152,13 +152,13 @@ SH_make_backup (const struct SYNC_AccountPublicKeyP *account,
size_t backup_size;
void *backup;
- qs = db->lookup_backup_TR (db->cls,
- account,
- &account_sig,
- &prev_hash,
- &backup_hash,
- &backup_size,
- &backup);
+ qs = SYNCDB_lookup_backup_TR (
+ account,
+ &account_sig,
+ &prev_hash,
+ &backup_hash,
+ &backup_size,
+ &backup);
switch (qs)
{
case SYNC_DB_OLD_BACKUP_MISSING:
diff --git a/src/sync/sync-httpd_backup.c b/src/sync/sync-httpd_backup.c
@@ -40,9 +40,9 @@ SH_backup_get (struct MHD_Connection *connection,
enum SYNC_DB_QueryStatus qs;
MHD_RESULT ret;
- qs = db->lookup_account_TR (db->cls,
- account,
- &backup_hash);
+ qs = SYNCDB_lookup_account_TR (
+ account,
+ &backup_hash);
switch (qs)
{
case SYNC_DB_OLD_BACKUP_MISSING:
@@ -165,13 +165,13 @@ SH_return_backup (struct MHD_Connection *connection,
size_t backup_size;
void *backup;
- qs = db->lookup_backup_TR (db->cls,
- account,
- &account_sig,
- &prev_hash,
- &backup_hash,
- &backup_size,
- &backup);
+ qs = SYNCDB_lookup_backup_TR (
+ account,
+ &account_sig,
+ &prev_hash,
+ &backup_hash,
+ &backup_size,
+ &backup);
switch (qs)
{
case SYNC_DB_OLD_BACKUP_MISSING:
diff --git a/src/sync/sync-httpd_backup_post.c b/src/sync/sync-httpd_backup_post.c
@@ -335,11 +335,11 @@ proposal_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Storing payment request for order `%s'\n",
por->details.ok.order_id);
- qs = db->store_payment_TR (db->cls,
- &bc->account,
- por->details.ok.order_id,
- por->details.ok.token,
- &SH_annual_fee);
+ qs = SYNCDB_store_payment_TR (
+ &bc->account,
+ por->details.ok.order_id,
+ por->details.ok.token,
+ &SH_annual_fee);
if (0 >= qs)
{
GNUNET_break (0);
@@ -456,10 +456,10 @@ check_payment_cb (void *cls,
{
enum SYNC_DB_QueryStatus qs;
- qs = db->increment_lifetime_TR (db->cls,
- &bc->account,
- bc->order_id,
- GNUNET_TIME_UNIT_YEARS); /* always annual */
+ qs = SYNCDB_increment_lifetime_TR (
+ &bc->account,
+ bc->order_id,
+ GNUNET_TIME_UNIT_YEARS); /* always annual */
if (0 <= qs)
return; /* continue as planned */
GNUNET_break (0);
@@ -547,10 +547,10 @@ begin_payment (struct BackupContext *bc,
{
enum GNUNET_DB_QueryStatus qs;
- qs = db->lookup_pending_payments_by_account_TR (db->cls,
- &bc->account,
- &ongoing_payment_cb,
- bc);
+ qs = SYNCDB_lookup_pending_payments_by_account_TR (
+ &bc->account,
+ &ongoing_payment_cb,
+ bc);
if (qs < 0)
{
struct MHD_Response *resp;
@@ -852,9 +852,9 @@ SH_backup_post (struct MHD_Connection *connection,
struct GNUNET_HashCode hc;
enum SYNC_DB_QueryStatus qs;
- qs = db->lookup_account_TR (db->cls,
- account,
- &hc);
+ qs = SYNCDB_lookup_account_TR (
+ account,
+ &hc);
if (qs < 0)
return handle_database_error (bc,
qs);
@@ -976,24 +976,24 @@ SH_backup_post (struct MHD_Connection *connection,
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Uploading first backup to account\n");
- qs = db->store_backup_TR (db->cls,
- account,
- &bc->account_sig,
- &bc->new_backup_hash,
- bc->upload_size,
- bc->upload);
+ qs = SYNCDB_store_backup_TR (
+ account,
+ &bc->account_sig,
+ &bc->new_backup_hash,
+ bc->upload_size,
+ bc->upload);
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Uploading existing backup of account\n");
- qs = db->update_backup_TR (db->cls,
- account,
- &bc->old_backup_hash,
- &bc->account_sig,
- &bc->new_backup_hash,
- bc->upload_size,
- bc->upload);
+ qs = SYNCDB_update_backup_TR (
+ account,
+ &bc->old_backup_hash,
+ &bc->account_sig,
+ &bc->new_backup_hash,
+ bc->upload_size,
+ bc->upload);
}
if (qs < 0)
return handle_database_error (bc,
diff --git a/src/syncdb/Makefile.am b/src/syncdb/Makefile.am
@@ -6,15 +6,6 @@ pkgcfgdir = $(prefix)/share/sync/config.d/
pkgcfg_DATA = \
sync_db_postgres.conf
-plugindir = $(libdir)/sync
-
-if HAVE_POSTGRESQL
-if HAVE_GNUNETPQ
-plugin_LTLIBRARIES = \
- libsync_plugin_db_postgres.la
-endif
-endif
-
if USE_COVERAGE
AM_CFLAGS = --coverage -O0
XLIB = -lgcov
@@ -36,38 +27,40 @@ sync_dbinit_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libsyncutil.la \
libsyncdb.la \
+ -ltalerpq \
-ltalerutil \
+ -lgnunetpq \
-lgnunetutil \
+ -lpq \
$(XLIB)
lib_LTLIBRARIES = \
libsyncdb.la
libsyncdb_la_SOURCES = \
- sync_db_plugin.c
+ syncdb_pg.c syncdb_pg.h \
+ syncdb_drop_tables.c \
+ syncdb_create_tables.c \
+ syncdb_preflight.c \
+ syncdb_gc.c \
+ syncdb_store_payment_TR.c \
+ syncdb_lookup_pending_payments_by_account_TR.c \
+ syncdb_store_backup_TR.c \
+ syncdb_update_backup_TR.c \
+ syncdb_lookup_account_TR.c \
+ syncdb_lookup_backup_TR.c \
+ syncdb_increment_lifetime_TR.c
libsyncdb_la_LIBADD = \
$(top_builddir)/src/util/libsyncutil.la \
+ -ltalerpq \
-lgnunetpq \
-lpq \
-lgnunetutil \
- -lltdl \
$(XLIB)
libsyncdb_la_LDFLAGS = \
$(POSTGRESQL_LDFLAGS) \
- -version-info 0:1:0 \
+ -version-info 1:0:0 \
-no-undefined
-libsync_plugin_db_postgres_la_SOURCES = \
- plugin_syncdb_postgres.c
-libsync_plugin_db_postgres_la_LDFLAGS = \
- $(SYNC_PLUGIN_LDFLAGS)
-libsync_plugin_db_postgres_la_LIBADD = \
- $(LTLIBINTL) \
- -ltalerpq \
- -lgnunetpq \
- -lgnunetutil \
- -lpq \
- $(XLIB)
-
check_PROGRAMS = \
$(TESTS)
diff --git a/src/syncdb/plugin_syncdb_postgres.c b/src/syncdb/plugin_syncdb_postgres.c
@@ -1,1364 +0,0 @@
-/*
- This file is part of TALER
- (C) 2014--2022 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser 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 ANASTASISABILITY 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/>
-*/
-/**
- * @file syncdb/plugin_syncdb_postgres.c
- * @brief database helper functions for postgres used by sync
- * @author Christian Grothoff
- */
-#include "platform.h"
-#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 "sync_database_plugin.h"
-#include "sync_database_lib.h"
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct PostgresClosure
-{
-
- /**
- * Postgres connection handle.
- */
- 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;
-
- /**
- * Name of the currently active transaction, NULL if none is active.
- */
- const char *transaction_name;
-
- /**
- * Currency we accept payments in.
- */
- char *currency;
-
- /**
- * Did we initialize the prepared statements
- * for this session?
- */
- bool init;
-
-};
-
-
-/**
- * Drop sync tables
- *
- * @param cls closure our `struct Plugin`
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-static enum GNUNET_GenericReturnValue
-postgres_drop_tables (void *cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_Context *conn;
- enum GNUNET_GenericReturnValue ret;
-
- if (NULL != pg->conn)
- {
- GNUNET_PQ_disconnect (pg->conn);
- pg->conn = NULL;
- pg->init = false;
- }
- 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;
-}
-
-
-/**
- * Establish connection to the database.
- *
- * @param cls plugin context
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-static enum GNUNET_GenericReturnValue
-prepare_statements (void *cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_PreparedStatement ps[] = {
- GNUNET_PQ_make_prepare ("account_insert",
- "INSERT INTO accounts "
- "(account_pub"
- ",expiration_date"
- ") VALUES "
- "($1,$2);"),
- GNUNET_PQ_make_prepare ("payment_insert",
- "INSERT INTO payments "
- "(account_pub"
- ",order_id"
- ",token"
- ",timestamp"
- ",amount"
- ") VALUES "
- "($1,$2,$3,$4,$5);"),
- GNUNET_PQ_make_prepare ("payment_done",
- "UPDATE payments "
- "SET"
- " paid=TRUE "
- "WHERE"
- " order_id=$1"
- " AND"
- " account_pub=$2"
- " AND"
- " paid=FALSE;"),
- GNUNET_PQ_make_prepare ("account_update",
- "UPDATE accounts "
- "SET"
- " expiration_date=$1 "
- "WHERE"
- " account_pub=$2;"),
- GNUNET_PQ_make_prepare ("account_select",
- "SELECT"
- " expiration_date "
- "FROM"
- " accounts "
- "WHERE"
- " account_pub=$1;"),
- GNUNET_PQ_make_prepare ("payments_select",
- "SELECT"
- " account_pub"
- ",order_id"
- ",amount"
- " FROM payments"
- " WHERE paid=FALSE;"),
- GNUNET_PQ_make_prepare ("payments_select_by_account",
- "SELECT"
- " timestamp"
- ",order_id"
- ",token"
- ",amount"
- " FROM payments"
- " WHERE"
- " paid=FALSE"
- " AND"
- " account_pub=$1;"),
- GNUNET_PQ_make_prepare ("gc_accounts",
- "DELETE FROM accounts "
- "WHERE"
- " expiration_date < $1;"),
- GNUNET_PQ_make_prepare ("gc_pending_payments",
- "DELETE FROM payments "
- "WHERE"
- " paid=FALSE"
- " AND"
- " timestamp < $1;"),
- GNUNET_PQ_make_prepare ("backup_insert",
- "INSERT INTO backups "
- "(account_pub"
- ",account_sig"
- ",prev_hash"
- ",backup_hash"
- ",data"
- ") VALUES "
- "($1,$2,$3,$4,$5);"),
- GNUNET_PQ_make_prepare ("backup_update",
- "UPDATE backups "
- " SET"
- " backup_hash=$1"
- ",account_sig=$2"
- ",prev_hash=$3"
- ",data=$4"
- " WHERE"
- " account_pub=$5"
- " AND"
- " backup_hash=$6;"),
- GNUNET_PQ_make_prepare ("backup_select_hash",
- "SELECT "
- " backup_hash "
- "FROM"
- " backups "
- "WHERE"
- " account_pub=$1;"),
- GNUNET_PQ_make_prepare ("backup_select",
- "SELECT "
- " account_sig"
- ",prev_hash"
- ",backup_hash"
- ",data "
- "FROM"
- " backups "
- "WHERE"
- " account_pub=$1;"),
- GNUNET_PQ_make_prepare ("do_commit",
- "COMMIT"),
- GNUNET_PQ_PREPARED_STATEMENT_END
- };
- enum GNUNET_GenericReturnValue ret;
-
- ret = GNUNET_PQ_prepare_statements (pg->conn,
- ps);
- if (GNUNET_OK != ret)
- return ret;
- pg->init = true;
- return GNUNET_OK;
-}
-
-
-/**
- * Connect to the database if the connection does not exist yet.
- *
- * @param pg the plugin-specific state
- * @param skip_prepare true if we should skip prepared statement setup
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-internal_setup (struct PostgresClosure *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_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;
- }
- if (NULL == pg->transaction_name)
- GNUNET_PQ_reconnect_if_down (pg->conn);
- if (pg->init)
- return GNUNET_OK;
- return prepare_statements (pg);
-}
-
-
-/**
- * Do a pre-flight check that we are not in an uncommitted transaction.
- * If we are, try to commit the previous transaction and output a warning.
- * Does not return anything, as we will continue regardless of the outcome.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @return #GNUNET_OK if everything is fine
- * #GNUNET_NO if a transaction was rolled back
- * #GNUNET_SYSERR on hard errors
- */
-static enum GNUNET_GenericReturnValue
-postgres_preflight (void *cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("ROLLBACK"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- if (! pg->init)
- {
- if (GNUNET_OK !=
- internal_setup (pg))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to ensure DB is initialized\n");
- return GNUNET_SYSERR;
- }
- }
- if (NULL == pg->transaction_name)
- return GNUNET_OK; /* all good */
- if (GNUNET_OK ==
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "BUG: Preflight check rolled back transaction `%s'!\n",
- pg->transaction_name);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "BUG: Preflight check failed to rollback transaction `%s'!\n",
- pg->transaction_name);
- }
- pg->transaction_name = NULL;
- return GNUNET_NO;
-}
-
-
-/**
- * Check that the database connection is still up.
- *
- * @param cls a `struct PostgresClosure` with connection to check
- */
-static void
-check_connection (void *cls)
-{
- struct PostgresClosure *pg = cls;
-
- GNUNET_PQ_reconnect_if_down (pg->conn);
-}
-
-
-/**
- * Start a transaction.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param name unique name identifying the transaction (for debugging),
- * must point to a constant
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-begin_transaction (void *cls,
- const char *name)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- check_connection (pg);
- postgres_preflight (pg);
- pg->transaction_name = name;
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- TALER_LOG_ERROR ("Failed to start transaction\n");
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Roll back the current transaction of a database connection.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- */
-static void
-rollback (void *cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("ROLLBACK"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- TALER_LOG_ERROR ("Failed to rollback transaction\n");
- GNUNET_break (0);
- }
- pg->transaction_name = NULL;
-}
-
-
-/**
- * Commit the current transaction of a database connection.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-commit_transaction (void *cls)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam no_params[] = {
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "do_commit",
- no_params);
- pg->transaction_name = NULL;
- return qs;
-}
-
-
-/**
- * Function called to perform "garbage collection" on the
- * database, expiring records we no longer require. Deletes
- * all user records that are not paid up (and by cascade deletes
- * the associated recovery documents). Also deletes expired
- * truth and financial records older than @a fin_expire.
- *
- * @param cls closure
- * @param expire_backups backups older than the given time stamp should be garbage collected
- * @param expire_pending_payments payments still pending from since before
- * this value should be garbage collected
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_gc (void *cls,
- struct GNUNET_TIME_Absolute expire_backups,
- struct GNUNET_TIME_Absolute expire_pending_payments)
-{
- struct PostgresClosure *pg = cls;
- 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
- };
- enum GNUNET_DB_QueryStatus qs;
-
- check_connection (pg);
- postgres_preflight (pg);
- 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);
-}
-
-
-/**
- * Store payment. Used to begin a payment, not indicative
- * that the payment actually was made. (That is done
- * when we increment the account's lifetime.)
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param order_id order we create
- * @param token claim token to use, NULL for none
- * @param amount how much we asked for
- * @return transaction status
- */
-static enum SYNC_DB_QueryStatus
-postgres_store_payment (void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const char *order_id,
- const struct TALER_ClaimTokenP *token,
- const struct TALER_Amount *amount)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_ClaimTokenP tok;
- struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_string (order_id),
- GNUNET_PQ_query_param_auto_from_type (&tok),
- GNUNET_PQ_query_param_timestamp (&now),
- TALER_PQ_query_param_amount (pg->conn,
- amount),
- GNUNET_PQ_query_param_end
- };
-
- if (NULL == token)
- memset (&tok, 0, sizeof (tok));
- else
- tok = *token;
- check_connection (pg);
- postgres_preflight (pg);
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "payment_insert",
- params);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0);
- return SYNC_DB_NO_RESULTS;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return SYNC_DB_ONE_RESULT;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-}
-
-
-/**
- * Closure for #payment_by_account_cb.
- */
-struct PaymentIteratorContext
-{
- /**
- * Function to call on each result
- */
- SYNC_DB_PaymentPendingIterator it;
-
- /**
- * Closure for @e it.
- */
- void *it_cls;
-
- /**
- * Plugin context.
- */
- struct PostgresClosure *pg;
-
- /**
- * Query status to return.
- */
- enum GNUNET_DB_QueryStatus qs;
-
-};
-
-
-/**
- * Helper function for #postgres_lookup_pending_payments_by_account().
- * To be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PaymentIteratorContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-payment_by_account_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PaymentIteratorContext *pic = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct GNUNET_TIME_Timestamp timestamp;
- char *order_id;
- struct TALER_Amount amount;
- struct TALER_ClaimTokenP token;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("timestamp",
- ×tamp),
- GNUNET_PQ_result_spec_string ("order_id",
- &order_id),
- GNUNET_PQ_result_spec_auto_from_type ("token",
- &token),
- TALER_PQ_result_spec_amount ("amount",
- pic->pg->currency,
- &amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- pic->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- pic->qs = i + 1;
- pic->it (pic->it_cls,
- timestamp,
- order_id,
- &token,
- &amount);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Lookup pending payments by account.
- *
- * @param cls closure
- * @param account_pub account to look for pending payments under
- * @param it iterator to call on all pending payments
- * @param it_cls closure for @a it
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_pending_payments_by_account (void *cls,
- const struct
- SYNC_AccountPublicKeyP *account_pub
- ,
- SYNC_DB_PaymentPendingIterator it,
- void *it_cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct PaymentIteratorContext pic = {
- .it = it,
- .it_cls = it_cls,
- .pg = pg
- };
- enum GNUNET_DB_QueryStatus qs;
-
- check_connection (pg);
- postgres_preflight (pg);
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "payments_select_by_account",
- params,
- &payment_by_account_cb,
- &pic);
- if (qs > 0)
- return pic.qs;
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
- return qs;
-}
-
-
-/**
- * Store backup. Only applicable for the FIRST backup under
- * an @a account_pub. Use @e update_backup_TR to update an
- * existing backup.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param account_sig signature affirming storage request
- * @param backup_hash hash of @a backup
- * @param backup_size number of bytes in @a backup
- * @param backup raw data to backup
- * @return transaction status
- */
-static enum SYNC_DB_QueryStatus
-postgres_store_backup (void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const struct SYNC_AccountSignatureP *account_sig,
- const struct GNUNET_HashCode *backup_hash,
- size_t backup_size,
- const void *backup)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_HashCode bh;
- static struct GNUNET_HashCode no_previous_hash;
-
- check_connection (pg);
- postgres_preflight (pg);
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_auto_from_type (account_sig),
- GNUNET_PQ_query_param_auto_from_type (&no_previous_hash),
- GNUNET_PQ_query_param_auto_from_type (backup_hash),
- GNUNET_PQ_query_param_fixed_size (backup,
- backup_size),
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "backup_insert",
- params);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return SYNC_DB_NO_RESULTS;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return SYNC_DB_ONE_RESULT;
- case GNUNET_DB_STATUS_HARD_ERROR:
- /* handle interesting case below */
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* First, check if account exists */
- {
- struct GNUNET_TIME_Timestamp ed;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
- &ed),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "account_select",
- params,
- rs);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return SYNC_DB_PAYMENT_REQUIRED;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* handle interesting case below */
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* account exists, check if existing backup conflicts */
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
- &bh),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "backup_select_hash",
- params,
- rs);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* original error must have been a hard error, oddly enough */
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* handle interesting case below */
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* had an existing backup, is it identical? */
- if (0 != GNUNET_memcmp (&bh,
- backup_hash))
- /* previous conflicting backup exists */
- return SYNC_DB_OLD_BACKUP_MISMATCH;
- /* backup identical to what was provided, no change */
- return SYNC_DB_NO_RESULTS;
-}
-
-
-/**
- * Update backup.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param account_sig signature affirming storage request
- * @param old_backup_hash hash of the previous backup (must match)
- * @param backup_hash hash of @a backup
- * @param backup_size number of bytes in @a backup
- * @param backup raw data to backup
- * @return transaction status
- */
-static enum SYNC_DB_QueryStatus
-postgres_update_backup (void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const struct GNUNET_HashCode *old_backup_hash,
- const struct SYNC_AccountSignatureP *account_sig,
- const struct GNUNET_HashCode *backup_hash,
- size_t backup_size,
- const void *backup)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_HashCode bh;
-
- check_connection (pg);
- postgres_preflight (pg);
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (backup_hash),
- GNUNET_PQ_query_param_auto_from_type (account_sig),
- GNUNET_PQ_query_param_auto_from_type (old_backup_hash),
- GNUNET_PQ_query_param_fixed_size (backup,
- backup_size),
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_auto_from_type (old_backup_hash),
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "backup_update",
- params);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* handle interesting case below */
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return SYNC_DB_ONE_RESULT;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* First, check if account exists */
- {
- struct GNUNET_TIME_Timestamp ed;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
- &ed),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "account_select",
- params,
- rs);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return SYNC_DB_PAYMENT_REQUIRED;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* handle interesting case below */
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* account exists, check if existing backup conflicts */
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
- &bh),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "backup_select_hash",
- params,
- rs);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return SYNC_DB_OLD_BACKUP_MISSING;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* handle interesting case below */
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* had an existing backup, is it identical? */
- if (0 == GNUNET_memcmp (&bh,
- backup_hash))
- {
- /* backup identical to what was provided, no change */
- return SYNC_DB_NO_RESULTS;
- }
- if (0 == GNUNET_memcmp (&bh,
- old_backup_hash))
- /* all constraints seem satisfied, original error must
- have been a hard error */
- return SYNC_DB_HARD_ERROR;
- /* previous backup does not match old_backup_hash */
- return SYNC_DB_OLD_BACKUP_MISMATCH;
-}
-
-
-/**
- * Lookup an account and associated backup meta data.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param[out] backup_hash set to hash of @a backup
- * @return transaction status
- */
-static enum SYNC_DB_QueryStatus
-postgres_lookup_account (void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- struct GNUNET_HashCode *backup_hash)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
-
- check_connection (pg);
- postgres_preflight (pg);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
- backup_hash),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "backup_select_hash",
- params,
- rs);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- break; /* handle interesting case below */
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return SYNC_DB_ONE_RESULT;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- /* check if account exists */
- {
- struct GNUNET_TIME_Timestamp expiration;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
- &expiration),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "account_select",
- params,
- rs);
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* indicates: no account */
- return SYNC_DB_PAYMENT_REQUIRED;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* indicates: no backup */
- return SYNC_DB_NO_RESULTS;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-}
-
-
-/**
- * Obtain backup.
- *
- * @param cls closure
- * @param account_pub account to store @a backup under
- * @param[out] account_sig set to signature affirming storage request
- * @param[out] prev_hash set to hash of previous @a backup, all zeros if none
- * @param[out] backup_hash set to hash of @a backup
- * @param[out] backup_size set to number of bytes in @a backup
- * @param[out] backup set to raw data to backup, caller MUST FREE
- */
-static enum SYNC_DB_QueryStatus
-postgres_lookup_backup (void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- struct SYNC_AccountSignatureP *account_sig,
- struct GNUNET_HashCode *prev_hash,
- struct GNUNET_HashCode *backup_hash,
- size_t *backup_size,
- void **backup)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("account_sig",
- account_sig),
- GNUNET_PQ_result_spec_auto_from_type ("prev_hash",
- prev_hash),
- GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
- backup_hash),
- GNUNET_PQ_result_spec_variable_size ("data",
- backup,
- backup_size),
- GNUNET_PQ_result_spec_end
- };
-
- check_connection (pg);
- postgres_preflight (pg);
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "backup_select",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return SYNC_DB_NO_RESULTS;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return SYNC_DB_ONE_RESULT;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-}
-
-
-/**
- * Increment account lifetime.
- *
- * @param cls closure
- * @param account_pub which account received a payment
- * @param order_id order which was paid, must be unique and match pending payment
- * @param lifetime for how long is the account now paid (increment)
- * @return transaction status
- */
-static enum SYNC_DB_QueryStatus
-postgres_increment_lifetime (void *cls,
- const struct SYNC_AccountPublicKeyP *account_pub,
- const char *order_id,
- struct GNUNET_TIME_Relative lifetime)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_TIME_Timestamp expiration;
- enum GNUNET_DB_QueryStatus qs;
-
- check_connection (pg);
- if (GNUNET_OK !=
- begin_transaction (pg,
- "increment lifetime"))
- {
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (order_id),
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "payment_done",
- params);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- rollback (pg);
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- rollback (pg);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- rollback (pg);
- return SYNC_DB_NO_RESULTS;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- }
-
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &expiration),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "account_select",
- params,
- rs);
- }
-
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- rollback (pg);
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- rollback (pg);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_timestamp (&expiration),
- GNUNET_PQ_query_param_end
- };
-
- expiration = GNUNET_TIME_relative_to_timestamp (lifetime);
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "account_insert",
- params);
- }
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&expiration),
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
-
- expiration = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (expiration.abs_time,
- lifetime));
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "account_update",
- params);
- }
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- rollback (pg);
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- rollback (pg);
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0);
- rollback (pg);
- return SYNC_DB_NO_RESULTS;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
- qs = commit_transaction (pg);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- return SYNC_DB_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return SYNC_DB_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return SYNC_DB_ONE_RESULT;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return SYNC_DB_ONE_RESULT;
- default:
- GNUNET_break (0);
- return SYNC_DB_HARD_ERROR;
- }
-}
-
-
-/**
- * Initialize tables.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-static enum GNUNET_GenericReturnValue
-postgres_create_tables (void *cls)
-{
- struct PostgresClosure *pc = cls;
- struct GNUNET_PQ_Context *conn;
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("SET search_path TO sync;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
- "syncdb-postgres",
- "sync-",
- es,
- NULL);
- if (NULL == conn)
- return GNUNET_SYSERR;
- GNUNET_PQ_disconnect (conn);
- return GNUNET_OK;
-}
-
-
-/**
- * Initialize Postgres database subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_SYNCDB_Plugin`
- */
-void *
-libsync_plugin_db_postgres_init (void *cls);
-
-/* make compiler happy */
-void *
-libsync_plugin_db_postgres_init (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct PostgresClosure *pg;
- struct SYNC_DatabasePlugin *plugin;
-
- 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);
- return NULL;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "sync",
- "CURRENCY",
- &pg->currency))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "sync",
- "CURRENCY");
- GNUNET_free (pg->sql_dir);
- GNUNET_free (pg);
- return NULL;
- }
- plugin = GNUNET_new (struct SYNC_DatabasePlugin);
- plugin->cls = pg;
- plugin->create_tables = &postgres_create_tables;
- plugin->drop_tables = &postgres_drop_tables;
- plugin->preflight = &postgres_preflight;
- plugin->gc = &postgres_gc;
- plugin->store_payment_TR = &postgres_store_payment;
- plugin->lookup_pending_payments_by_account_TR =
- &postgres_lookup_pending_payments_by_account;
- plugin->store_backup_TR = &postgres_store_backup;
- plugin->lookup_account_TR = &postgres_lookup_account;
- plugin->lookup_backup_TR = &postgres_lookup_backup;
- plugin->update_backup_TR = &postgres_update_backup;
- plugin->increment_lifetime_TR = &postgres_increment_lifetime;
- return plugin;
-}
-
-
-/**
- * Shutdown Postgres database subsystem.
- *
- * @param cls a `struct SYNC_DB_Plugin`
- * @return NULL (always)
- */
-void *
-libsync_plugin_db_postgres_done (void *cls);
-
-/* make compiler happy */
-void *
-libsync_plugin_db_postgres_done (void *cls)
-{
- struct SYNC_DatabasePlugin *plugin = cls;
- struct PostgresClosure *pg = plugin->cls;
-
- GNUNET_PQ_disconnect (pg->conn);
- GNUNET_free (pg->currency);
- GNUNET_free (pg->sql_dir);
- GNUNET_free (pg);
- GNUNET_free (plugin);
- return NULL;
-}
-
-
-/* end of plugin_syncdb_postgres.c */
diff --git a/src/syncdb/sync-dbinit.c b/src/syncdb/sync-dbinit.c
@@ -20,8 +20,8 @@
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
-#include "sync_util.h"
-#include "sync_database_lib.h"
+#include "sync/sync_util.h"
+#include "sync/sync_database_lib.h"
/**
@@ -54,30 +54,28 @@ run (void *cls,
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- struct SYNC_DatabasePlugin *plugin;
-
- if (NULL ==
- (plugin = SYNC_DB_plugin_load (cfg,
- true)))
+ if (GNUNET_OK !=
+ SYNCDB_init (cfg,
+ true))
{
fprintf (stderr,
- "Failed to initialize database plugin.\n");
+ "Failed to initialize database.\n");
global_ret = EXIT_NOTINSTALLED;
return;
}
if (reset_db)
{
- if (GNUNET_OK != plugin->drop_tables (plugin->cls))
+ if (GNUNET_OK != SYNCDB_drop_tables ())
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not drop tables as requested. Either database was not yet initialized, or permission denied. Consult the logs. Will still try to create new tables.\n");
}
}
if (GNUNET_OK !=
- plugin->create_tables (plugin->cls))
+ SYNCDB_create_tables ())
{
global_ret = EXIT_FAILURE;
- SYNC_DB_plugin_unload (plugin);
+ SYNCDB_fini ();
return;
}
if (gc_db)
@@ -91,16 +89,15 @@ run (void *cls,
GNUNET_TIME_UNIT_YEARS,
6));
if (0 >
- plugin->gc (plugin->cls,
- now,
- ancient))
+ SYNCDB_gc (now,
+ ancient))
{
fprintf (stderr,
"Garbage collection failed!\n");
global_ret = EXIT_FAILURE;
}
}
- SYNC_DB_plugin_unload (plugin);
+ SYNCDB_fini ();
}
diff --git a/src/syncdb/sync_db_plugin.c b/src/syncdb/sync_db_plugin.c
@@ -20,8 +20,8 @@
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
*/
#include "platform.h"
-#include "sync_util.h"
-#include "sync_database_lib.h"
+#include "sync/sync_util.h"
+#include "sync/sync_database_lib.h"
#include <ltdl.h>
diff --git a/src/syncdb/syncdb_create_tables.c b/src/syncdb/syncdb_create_tables.c
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_create_tables.c
+ * @brief create sync database tables
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum GNUNET_GenericReturnValue
+SYNCDB_create_tables (void)
+{
+ struct GNUNET_PQ_Context *conn;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("SET search_path TO sync;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "syncdb-postgres",
+ "sync-",
+ es,
+ NULL);
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ GNUNET_PQ_disconnect (conn);
+ return GNUNET_OK;
+}
+
+
+/* end of syncdb_create_tables.c */
diff --git a/src/syncdb/syncdb_drop_tables.c b/src/syncdb/syncdb_drop_tables.c
@@ -0,0 +1,49 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_drop_tables.c
+ * @brief drop sync database tables
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum GNUNET_GenericReturnValue
+SYNCDB_drop_tables (void)
+{
+ 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;
+}
+
+
+/* end of syncdb_drop_tables.c */
diff --git a/src/syncdb/syncdb_gc.c b/src/syncdb/syncdb_gc.c
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_gc.c
+ * @brief garbage collection for sync database
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum GNUNET_DB_QueryStatus
+SYNCDB_gc (struct GNUNET_TIME_Absolute expire_backups,
+ struct GNUNET_TIME_Absolute expire_pending_payments)
+{
+ 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
+ };
+ 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);
+}
+
+
+/* end of syncdb_gc.c */
diff --git a/src/syncdb/syncdb_increment_lifetime_TR.c b/src/syncdb/syncdb_increment_lifetime_TR.c
@@ -0,0 +1,198 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_increment_lifetime_TR.c
+ * @brief increment account lifetime after payment
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum SYNC_DB_QueryStatus
+SYNCDB_increment_lifetime_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const char *order_id,
+ struct GNUNET_TIME_Relative lifetime)
+{
+ struct GNUNET_TIME_Timestamp expiration;
+ enum GNUNET_DB_QueryStatus qs;
+
+ if (GNUNET_OK !=
+ begin_transaction ("increment lifetime"))
+ {
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ PREPARE ("increment_lifetime_payment_done",
+ "UPDATE payments "
+ "SET"
+ " paid=TRUE "
+ "WHERE"
+ " order_id=$1"
+ " AND"
+ " account_pub=$2"
+ " AND"
+ " paid=FALSE;");
+
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (order_id),
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "increment_lifetime_payment_done",
+ params);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ rollback ();
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ rollback ();
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ rollback ();
+ return SYNC_DB_NO_RESULTS;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ }
+
+ PREPARE ("increment_lifetime_account_select",
+ "SELECT"
+ " expiration_date "
+ "FROM"
+ " accounts "
+ "WHERE"
+ " account_pub=$1;");
+
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &expiration),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "increment_lifetime_account_select",
+ params,
+ rs);
+ }
+
+ PREPARE ("increment_lifetime_account_insert",
+ "INSERT INTO accounts "
+ "(account_pub"
+ ",expiration_date"
+ ") VALUES "
+ "($1,$2);");
+
+ PREPARE ("increment_lifetime_account_update",
+ "UPDATE accounts "
+ "SET"
+ " expiration_date=$1 "
+ "WHERE"
+ " account_pub=$2;");
+
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ rollback ();
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ rollback ();
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_timestamp (&expiration),
+ GNUNET_PQ_query_param_end
+ };
+
+ expiration = GNUNET_TIME_relative_to_timestamp (lifetime);
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "increment_lifetime_account_insert",
+ params);
+ }
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&expiration),
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ expiration = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (expiration.abs_time,
+ lifetime));
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "increment_lifetime_account_update",
+ params);
+ }
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ rollback ();
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ rollback ();
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0);
+ rollback ();
+ return SYNC_DB_NO_RESULTS;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+ qs = commit_transaction ();
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return SYNC_DB_ONE_RESULT;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return SYNC_DB_ONE_RESULT;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+}
+
+
+/* end of syncdb_increment_lifetime_TR.c */
diff --git a/src/syncdb/syncdb_lookup_account_TR.c b/src/syncdb/syncdb_lookup_account_TR.c
@@ -0,0 +1,115 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_lookup_account_TR.c
+ * @brief lookup account and backup metadata
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum SYNC_DB_QueryStatus
+SYNCDB_lookup_account_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ struct GNUNET_HashCode *backup_hash)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ SYNCDB_preflight ();
+
+ PREPARE ("lookup_account_backup_select_hash",
+ "SELECT "
+ " backup_hash "
+ "FROM"
+ " backups "
+ "WHERE"
+ " account_pub=$1;");
+
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
+ backup_hash),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_account_backup_select_hash",
+ params,
+ rs);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ break; /* handle interesting case below */
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return SYNC_DB_ONE_RESULT;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ PREPARE ("lookup_account_account_select",
+ "SELECT"
+ " expiration_date "
+ "FROM"
+ " accounts "
+ "WHERE"
+ " account_pub=$1;");
+
+ /* check if account exists */
+ {
+ struct GNUNET_TIME_Timestamp expiration;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
+ &expiration),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_account_account_select",
+ params,
+ rs);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* indicates: no account */
+ return SYNC_DB_PAYMENT_REQUIRED;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* indicates: no backup */
+ return SYNC_DB_NO_RESULTS;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+}
+
+
+/* end of syncdb_lookup_account_TR.c */
diff --git a/src/syncdb/syncdb_lookup_backup_TR.c b/src/syncdb/syncdb_lookup_backup_TR.c
@@ -0,0 +1,84 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_lookup_backup_TR.c
+ * @brief obtain backup data
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum SYNC_DB_QueryStatus
+SYNCDB_lookup_backup_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ struct SYNC_AccountSignatureP *account_sig,
+ struct GNUNET_HashCode *prev_hash,
+ struct GNUNET_HashCode *backup_hash,
+ size_t *backup_size,
+ void **backup)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("account_sig",
+ account_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("prev_hash",
+ prev_hash),
+ GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
+ backup_hash),
+ GNUNET_PQ_result_spec_variable_size ("data",
+ backup,
+ backup_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ SYNCDB_preflight ();
+ PREPARE ("backup_select",
+ "SELECT "
+ " account_sig"
+ ",prev_hash"
+ ",backup_hash"
+ ",data "
+ "FROM"
+ " backups "
+ "WHERE"
+ " account_pub=$1;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "backup_select",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return SYNC_DB_NO_RESULTS;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return SYNC_DB_ONE_RESULT;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+}
+
+
+/* end of syncdb_lookup_backup_TR.c */
diff --git a/src/syncdb/syncdb_lookup_pending_payments_by_account_TR.c b/src/syncdb/syncdb_lookup_pending_payments_by_account_TR.c
@@ -0,0 +1,142 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_lookup_pending_payments_by_account_TR.c
+ * @brief lookup pending payments by account
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+/**
+ * Closure for #payment_by_account_cb.
+ */
+struct PaymentIteratorContext
+{
+ /**
+ * Function to call on each result
+ */
+ SYNC_DB_PaymentPendingIterator it;
+
+ /**
+ * Closure for @e it.
+ */
+ void *it_cls;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+
+};
+
+
+/**
+ * Helper function for #SYNCDB_lookup_pending_payments_by_account_TR().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PaymentIteratorContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+payment_by_account_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PaymentIteratorContext *pic = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct GNUNET_TIME_Timestamp timestamp;
+ char *order_id;
+ struct TALER_Amount amount;
+ struct TALER_ClaimTokenP token;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("timestamp",
+ ×tamp),
+ GNUNET_PQ_result_spec_string ("order_id",
+ &order_id),
+ GNUNET_PQ_result_spec_auto_from_type ("token",
+ &token),
+ TALER_PQ_result_spec_amount ("amount",
+ pg->currency,
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ pic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ pic->qs = i + 1;
+ pic->it (pic->it_cls,
+ timestamp,
+ order_id,
+ &token,
+ &amount);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+SYNCDB_lookup_pending_payments_by_account_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ SYNC_DB_PaymentPendingIterator it,
+ void *it_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct PaymentIteratorContext pic = {
+ .it = it,
+ .it_cls = it_cls
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ SYNCDB_preflight ();
+ PREPARE ("payments_select_by_account",
+ "SELECT"
+ " timestamp"
+ ",order_id"
+ ",token"
+ ",amount"
+ " FROM payments"
+ " WHERE"
+ " paid=FALSE"
+ " AND"
+ " account_pub=$1;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "payments_select_by_account",
+ params,
+ &payment_by_account_cb,
+ &pic);
+ if (qs > 0)
+ return pic.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
+
+
+/* end of syncdb_lookup_pending_payments_by_account_TR.c */
diff --git a/src/syncdb/syncdb_pg.c b/src/syncdb/syncdb_pg.c
@@ -0,0 +1,150 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_pg.c
+ * @brief shared database state and helpers for sync postgres
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+#include "sync/sync_util.h"
+
+
+/**
+ * Global database closure.
+ */
+struct PostgresClosure *pg;
+
+
+enum GNUNET_GenericReturnValue
+begin_transaction (const char *name)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ SYNCDB_preflight ();
+ pg->transaction_name = name;
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+void
+rollback (void)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to rollback transaction\n");
+ GNUNET_break (0);
+ }
+ pg->transaction_name = NULL;
+}
+
+
+enum GNUNET_DB_QueryStatus
+commit_transaction (void)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam no_params[] = {
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE ("do_commit",
+ "COMMIT");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "do_commit",
+ no_params);
+ pg->transaction_name = NULL;
+ return qs;
+}
+
+
+enum GNUNET_GenericReturnValue
+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",
+ &pg->currency))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "CURRENCY");
+ GNUNET_free (pg->sql_dir);
+ GNUNET_free (pg);
+ pg = NULL;
+ return GNUNET_SYSERR;
+ }
+ 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_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+void
+SYNCDB_fini (void)
+{
+ if (NULL == pg)
+ return;
+ if (NULL != pg->conn)
+ GNUNET_PQ_disconnect (pg->conn);
+ GNUNET_free (pg->currency);
+ GNUNET_free (pg->sql_dir);
+ GNUNET_free (pg);
+ pg = NULL;
+}
+
+
+/* end of syncdb_pg.c */
diff --git a/src/syncdb/syncdb_preflight.c b/src/syncdb/syncdb_preflight.c
@@ -0,0 +1,114 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_preflight.c
+ * @brief preflight check for sync database
+ * @author Christian Grothoff
+ */
+#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)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ 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);
+ }
+ if (NULL == pg->transaction_name)
+ return GNUNET_OK; /* all good */
+ if (GNUNET_OK ==
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check rolled back transaction `%s'!\n",
+ pg->transaction_name);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check failed to rollback transaction `%s'!\n",
+ pg->transaction_name);
+ }
+ pg->transaction_name = NULL;
+ return GNUNET_NO;
+}
+
+
+/* end of syncdb_preflight.c */
diff --git a/src/syncdb/syncdb_store_backup_TR.c b/src/syncdb/syncdb_store_backup_TR.c
@@ -0,0 +1,177 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_store_backup_TR.c
+ * @brief store first backup
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum SYNC_DB_QueryStatus
+SYNCDB_store_backup_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const struct SYNC_AccountSignatureP *account_sig,
+ const struct GNUNET_HashCode *backup_hash,
+ size_t backup_size,
+ const void *backup)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_HashCode bh;
+ static struct GNUNET_HashCode no_previous_hash;
+
+ SYNCDB_preflight ();
+
+ PREPARE ("store_backup_backup_insert",
+ "INSERT INTO backups "
+ "(account_pub"
+ ",account_sig"
+ ",prev_hash"
+ ",backup_hash"
+ ",data"
+ ") VALUES "
+ "($1,$2,$3,$4,$5);");
+
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_auto_from_type (account_sig),
+ GNUNET_PQ_query_param_auto_from_type (&no_previous_hash),
+ GNUNET_PQ_query_param_auto_from_type (backup_hash),
+ GNUNET_PQ_query_param_fixed_size (backup,
+ backup_size),
+ GNUNET_PQ_query_param_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "store_backup_backup_insert",
+ params);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return SYNC_DB_NO_RESULTS;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return SYNC_DB_ONE_RESULT;
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ /* handle interesting case below */
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ PREPARE ("store_backup_account_select",
+ "SELECT"
+ " expiration_date "
+ "FROM"
+ " accounts "
+ "WHERE"
+ " account_pub=$1;");
+
+ /* First, check if account exists */
+ {
+ struct GNUNET_TIME_Timestamp ed;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
+ &ed),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "store_backup_account_select",
+ params,
+ rs);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return SYNC_DB_PAYMENT_REQUIRED;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* handle interesting case below */
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ PREPARE ("store_backup_backup_select_hash",
+ "SELECT "
+ " backup_hash "
+ "FROM"
+ " backups "
+ "WHERE"
+ " account_pub=$1;");
+
+
+ /* account exists, check if existing backup conflicts */
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
+ &bh),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "store_backup_backup_select_hash",
+ params,
+ rs);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* original error must have been a hard error, oddly enough */
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* handle interesting case below */
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ /* had an existing backup, is it identical? */
+ if (0 != GNUNET_memcmp (&bh,
+ backup_hash))
+ /* previous conflicting backup exists */
+ return SYNC_DB_OLD_BACKUP_MISMATCH;
+ /* backup identical to what was provided, no change */
+ return SYNC_DB_NO_RESULTS;
+}
+
+
+/* end of syncdb_store_backup_TR.c */
diff --git a/src/syncdb/syncdb_store_payment_TR.c b/src/syncdb/syncdb_store_payment_TR.c
@@ -0,0 +1,81 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_store_payment_TR.c
+ * @brief store payment for sync database
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum SYNC_DB_QueryStatus
+SYNCDB_store_payment_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const char *order_id,
+ const struct TALER_ClaimTokenP *token,
+ const struct TALER_Amount *amount)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct TALER_ClaimTokenP tok;
+ struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_string (order_id),
+ GNUNET_PQ_query_param_auto_from_type (&tok),
+ GNUNET_PQ_query_param_timestamp (&now),
+ TALER_PQ_query_param_amount (pg->conn,
+ amount),
+ GNUNET_PQ_query_param_end
+ };
+
+ if (NULL == token)
+ memset (&tok, 0, sizeof (tok));
+ else
+ tok = *token;
+ SYNCDB_preflight ();
+ PREPARE ("payment_insert",
+ "INSERT INTO payments "
+ "(account_pub"
+ ",order_id"
+ ",token"
+ ",timestamp"
+ ",amount"
+ ") VALUES "
+ "($1,$2,$3,$4,$5);");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "payment_insert",
+ params);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0);
+ return SYNC_DB_NO_RESULTS;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return SYNC_DB_ONE_RESULT;
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+}
+
+
+/* end of syncdb_store_payment_TR.c */
diff --git a/src/syncdb/syncdb_update_backup_TR.c b/src/syncdb/syncdb_update_backup_TR.c
@@ -0,0 +1,184 @@
+/*
+ This file is part of TALER
+ (C) 2014--2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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/>
+*/
+/**
+ * @file syncdb/syncdb_update_backup_TR.c
+ * @brief update existing backup
+ * @author Christian Grothoff
+ */
+#include "syncdb_pg.h"
+
+
+enum SYNC_DB_QueryStatus
+SYNCDB_update_backup_TR (
+ const struct SYNC_AccountPublicKeyP *account_pub,
+ const struct GNUNET_HashCode *old_backup_hash,
+ const struct SYNC_AccountSignatureP *account_sig,
+ const struct GNUNET_HashCode *backup_hash,
+ size_t backup_size,
+ const void *backup)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_HashCode bh;
+
+ SYNCDB_preflight ();
+ PREPARE ("backup_update",
+ "UPDATE backups "
+ " SET"
+ " backup_hash=$1"
+ ",account_sig=$2"
+ ",prev_hash=$3"
+ ",data=$4"
+ " WHERE"
+ " account_pub=$5"
+ " AND"
+ " backup_hash=$6;");
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (backup_hash),
+ GNUNET_PQ_query_param_auto_from_type (account_sig),
+ GNUNET_PQ_query_param_auto_from_type (old_backup_hash),
+ GNUNET_PQ_query_param_fixed_size (backup,
+ backup_size),
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_auto_from_type (old_backup_hash),
+ GNUNET_PQ_query_param_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "backup_update",
+ params);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* handle interesting case below */
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return SYNC_DB_ONE_RESULT;
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ PREPARE ("update_backup_account_select",
+ "SELECT"
+ " expiration_date "
+ "FROM"
+ " accounts "
+ "WHERE"
+ " account_pub=$1;");
+
+ /* First, check if account exists */
+ {
+ struct GNUNET_TIME_Timestamp ed;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
+ &ed),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "update_backup_account_select",
+ params,
+ rs);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return SYNC_DB_PAYMENT_REQUIRED;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* handle interesting case below */
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ PREPARE ("update_backup_backup_select_hash",
+ "SELECT "
+ " backup_hash "
+ "FROM"
+ " backups "
+ "WHERE"
+ " account_pub=$1;");
+
+ /* account exists, check if existing backup conflicts */
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("backup_hash",
+ &bh),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "update_backup_backup_select_hash",
+ params,
+ rs);
+ }
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return SYNC_DB_HARD_ERROR;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return SYNC_DB_SOFT_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return SYNC_DB_OLD_BACKUP_MISSING;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* handle interesting case below */
+ break;
+ default:
+ GNUNET_break (0);
+ return SYNC_DB_HARD_ERROR;
+ }
+
+ /* had an existing backup, is it identical? */
+ if (0 == GNUNET_memcmp (&bh,
+ backup_hash))
+ {
+ /* backup identical to what was provided, no change */
+ return SYNC_DB_NO_RESULTS;
+ }
+ if (0 == GNUNET_memcmp (&bh,
+ old_backup_hash))
+ /* all constraints seem satisfied, original error must
+ have been a hard error */
+ return SYNC_DB_HARD_ERROR;
+ /* previous backup does not match old_backup_hash */
+ return SYNC_DB_OLD_BACKUP_MISMATCH;
+}
+
+
+/* end of syncdb_update_backup_TR.c */
diff --git a/src/syncdb/test_sync_db.c b/src/syncdb/test_sync_db.c
@@ -15,16 +15,15 @@
*/
/**
* @file sync/test_sync_db.c
- * @brief testcase for sync postgres db plugin
+ * @brief testcase for sync postgres db
* @author Christian Grothoff
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
#include <taler/taler_util.h>
-#include "sync_service.h"
-#include "sync_database_plugin.h"
-#include "sync_database_lib.h"
-#include "sync_util.h"
+#include "sync/sync_service.h"
+#include "sync/sync_database_lib.h"
+#include "sync/sync_util.h"
#define FAILIF(cond) \
@@ -44,11 +43,6 @@
*/
static int result;
-/**
- * Handle to the plugin we are testing.
- */
-static struct SYNC_DatabasePlugin *plugin;
-
/**
* Function called on all pending payments for an account.
@@ -95,26 +89,27 @@ run (void *cls)
size_t bs;
void *b = NULL;
- if (NULL == (plugin = SYNC_DB_plugin_load (cfg,
- true)))
+ if (GNUNET_OK !=
+ SYNCDB_init (cfg,
+ true))
{
result = 77;
return;
}
if (GNUNET_OK !=
- plugin->drop_tables (plugin->cls))
+ SYNCDB_drop_tables ())
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Dropping tables failed\n");
}
if (GNUNET_OK !=
- plugin->create_tables (plugin->cls))
+ SYNCDB_create_tables ())
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Creating tables failed\n");
}
GNUNET_assert (GNUNET_OK ==
- plugin->preflight (plugin->cls));
+ SYNCDB_preflight ());
memset (&account_pub, 1, sizeof (account_pub));
memset (&account_sig, 2, sizeof (account_sig));
memset (&token, 3, sizeof (token));
@@ -125,68 +120,59 @@ run (void *cls)
TALER_string_to_amount ("EUR:1",
&amount));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->store_payment_TR (plugin->cls,
- &account_pub,
- "fake-order",
- &token,
- &amount));
+ SYNCDB_store_payment_TR (&account_pub,
+ "fake-order",
+ &token,
+ &amount));
+ FAILIF (SYNC_DB_ONE_RESULT !=
+ SYNCDB_increment_lifetime_TR (&account_pub,
+ "fake-order",
+ GNUNET_TIME_UNIT_MINUTES));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->increment_lifetime_TR (plugin->cls,
- &account_pub,
- "fake-order",
- GNUNET_TIME_UNIT_MINUTES));
+ SYNCDB_store_backup_TR (&account_pub,
+ &account_sig,
+ &h,
+ 4,
+ "data"));
+ FAILIF (SYNC_DB_NO_RESULTS !=
+ SYNCDB_store_backup_TR (&account_pub,
+ &account_sig,
+ &h,
+ 4,
+ "data"));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->store_backup_TR (plugin->cls,
- &account_pub,
+ SYNCDB_update_backup_TR (&account_pub,
+ &h,
&account_sig,
+ &h2,
+ 4,
+ "DATA"));
+ FAILIF (SYNC_DB_OLD_BACKUP_MISMATCH !=
+ SYNCDB_update_backup_TR (&account_pub,
&h,
+ &account_sig,
+ &h3,
4,
- "data"));
+ "ATAD"));
FAILIF (SYNC_DB_NO_RESULTS !=
- plugin->store_backup_TR (plugin->cls,
- &account_pub,
- &account_sig,
+ SYNCDB_update_backup_TR (&account_pub,
&h,
+ &account_sig,
+ &h2,
4,
- "data"));
+ "DATA"));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->update_backup_TR (plugin->cls,
- &account_pub,
- &h,
- &account_sig,
- &h2,
- 4,
- "DATA"));
- FAILIF (SYNC_DB_OLD_BACKUP_MISMATCH !=
- plugin->update_backup_TR (plugin->cls,
- &account_pub,
- &h,
- &account_sig,
- &h3,
- 4,
- "ATAD"));
- FAILIF (SYNC_DB_NO_RESULTS !=
- plugin->update_backup_TR (plugin->cls,
- &account_pub,
- &h,
- &account_sig,
- &h2,
- 4,
- "DATA"));
- FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->lookup_account_TR (plugin->cls,
- &account_pub,
- &r));
+ SYNCDB_lookup_account_TR (&account_pub,
+ &r));
FAILIF (0 != GNUNET_memcmp (&r,
&h2));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->lookup_backup_TR (plugin->cls,
- &account_pub,
- &account_sig2,
- &r,
- &r2,
- &bs,
- &b));
+ SYNCDB_lookup_backup_TR (&account_pub,
+ &account_sig2,
+ &r,
+ &r2,
+ &bs,
+ &b));
FAILIF (0 != GNUNET_memcmp (&r,
&h));
FAILIF (0 != GNUNET_memcmp (&r2,
@@ -200,64 +186,55 @@ run (void *cls)
GNUNET_free (b);
b = NULL;
FAILIF (0 !=
- plugin->lookup_pending_payments_by_account_TR (plugin->cls,
- &account_pub,
- &payment_it,
- NULL));
+ SYNCDB_lookup_pending_payments_by_account_TR (&account_pub,
+ &payment_it,
+ NULL));
memset (&account_pub, 2, sizeof (account_pub));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->store_payment_TR (plugin->cls,
- &account_pub,
- "fake-order-2",
- &token,
- &amount));
+ SYNCDB_store_payment_TR (&account_pub,
+ "fake-order-2",
+ &token,
+ &amount));
FAILIF (1 !=
- plugin->lookup_pending_payments_by_account_TR (plugin->cls,
- &account_pub,
- &payment_it,
- NULL));
+ SYNCDB_lookup_pending_payments_by_account_TR (&account_pub,
+ &payment_it,
+ NULL));
FAILIF (SYNC_DB_PAYMENT_REQUIRED !=
- plugin->store_backup_TR (plugin->cls,
- &account_pub,
- &account_sig,
- &h,
- 4,
- "data"));
+ SYNCDB_store_backup_TR (&account_pub,
+ &account_sig,
+ &h,
+ 4,
+ "data"));
FAILIF (SYNC_DB_ONE_RESULT !=
- plugin->increment_lifetime_TR (plugin->cls,
- &account_pub,
- "fake-order-2",
- GNUNET_TIME_UNIT_MINUTES));
+ SYNCDB_increment_lifetime_TR (&account_pub,
+ "fake-order-2",
+ GNUNET_TIME_UNIT_MINUTES));
FAILIF (SYNC_DB_OLD_BACKUP_MISSING !=
- plugin->update_backup_TR (plugin->cls,
- &account_pub,
- &h,
- &account_sig,
- &h2,
- 4,
- "DATA"));
+ SYNCDB_update_backup_TR (&account_pub,
+ &h,
+ &account_sig,
+ &h2,
+ 4,
+ "DATA"));
ts = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS);
FAILIF (0 >
- plugin->gc (plugin->cls,
- ts,
- ts));
+ SYNCDB_gc (ts,
+ ts));
memset (&account_pub, 1, sizeof (account_pub));
FAILIF (SYNC_DB_NO_RESULTS !=
- plugin->lookup_backup_TR (plugin->cls,
- &account_pub,
- &account_sig2,
- &r,
- &r2,
- &bs,
- &b));
+ SYNCDB_lookup_backup_TR (&account_pub,
+ &account_sig2,
+ &r,
+ &r2,
+ &bs,
+ &b));
result = 0;
drop:
GNUNET_free (b);
GNUNET_break (GNUNET_OK ==
- plugin->drop_tables (plugin->cls));
- SYNC_DB_plugin_unload (plugin);
- plugin = NULL;
+ SYNCDB_drop_tables ());
+ SYNCDB_fini ();
}
diff --git a/src/testing/test_sync_api.c b/src/testing/test_sync_api.c
@@ -33,8 +33,8 @@
#include <taler/taler_testing_lib.h>
#include <taler/taler_merchant_testing_lib.h>
#include <taler/taler_error_codes.h>
-#include "sync_service.h"
-#include "sync_testing_lib.h"
+#include "sync/sync_service.h"
+#include "sync/sync_testing_lib.h"
/**
* Configuration file we use. One (big) configuration is used
diff --git a/src/testing/testing_api_cmd_backup_download.c b/src/testing/testing_api_cmd_backup_download.c
@@ -22,8 +22,8 @@
* @author Christian Grothoff
*/
#include "platform.h"
-#include "sync_service.h"
-#include "sync_testing_lib.h"
+#include "sync/sync_service.h"
+#include "sync/sync_testing_lib.h"
#include <taler/taler_util.h>
#include <taler/taler_testing_lib.h>
diff --git a/src/testing/testing_api_cmd_backup_upload.c b/src/testing/testing_api_cmd_backup_upload.c
@@ -22,12 +22,12 @@
* @author Christian Grothoff
*/
#include "platform.h"
-#include "sync_service.h"
-#include "sync_testing_lib.h"
+#include "sync/sync_service.h"
+#include "sync/sync_testing_lib.h"
#include <taler/taler_util.h>
#include <taler/taler_testing_lib.h>
#include <taler/taler_merchant_service.h>
-#include "sync_testing_lib.h"
+#include "sync/sync_testing_lib.h"
/**
* State for a "backup upload" CMD.
diff --git a/src/testing/testing_api_traits.c b/src/testing/testing_api_traits.c
@@ -22,7 +22,7 @@
* @author Christian Grothoff
*/
#include "platform.h"
-#include "sync_testing_lib.h"
+#include "sync/sync_testing_lib.h"
SYNC_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_IMPL_SIMPLE_TRAIT)
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
@@ -25,7 +25,7 @@
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
-#include "sync_util.h"
+#include "sync/sync_util.h"
/**
diff --git a/src/util/sync-config.c b/src/util/sync-config.c
@@ -24,7 +24,7 @@
* @author Christian Grothoff
*/
#include "platform.h"
-#include "sync_util.h"
+#include "sync/sync_util.h"
/**