gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-sync] 02/02: first cut at syncdb plugin


From: gnunet
Subject: [taler-sync] 02/02: first cut at syncdb plugin
Date: Thu, 14 Nov 2019 19:34:07 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository sync.

commit d9ce406f23331b54170c2897312798a046bc8ac7
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Nov 14 19:30:04 2019 +0100

    first cut at syncdb plugin
---
 src/syncdb/plugin_sync_postgres.c     | 432 ------------------
 src/syncdb/plugin_syncdb_postgres.c   | 817 ++++++++++++++++++++++++++++++++++
 src/syncdb/test_sync_db.c             |  71 +--
 src/syncdb/test_sync_db_postgres.conf |   6 +-
 4 files changed, 824 insertions(+), 502 deletions(-)

diff --git a/src/syncdb/plugin_sync_postgres.c 
b/src/syncdb/plugin_sync_postgres.c
deleted file mode 100644
index 59df4d5..0000000
--- a/src/syncdb/plugin_sync_postgres.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2014--2019 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 sync/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_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;
-
-  /**
-   * Underlying configuration.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Name of the currently active transaction, NULL if none is active.
-   */
-  const char *transaction_name;
-
-};
-
-
-/**
- * Drop sync tables
- *
- * @param cls closure our `struct Plugin`
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-static int
-postgres_drop_tables (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS accounts CASCADE;"),
-    GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS backups;"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-  return GNUNET_PQ_exec_statements (pg->conn,
-                                    es);
-}
-
-
-/**
- * Check that the database connection is still up.
- *
- * @param pg connection to check
- */
-static void
-check_connection (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  GNUNET_PQ_reconnect_if_down (pg->conn);
-}
-
-
-/**
- * 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
- */
-static void
-postgres_preflight (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_execute ("COMMIT"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-
-  if (NULL == pg->transaction_name)
-    return; /* all good */
-  if (GNUNET_OK ==
-      GNUNET_PQ_exec_statements (pg->conn,
-                                 es))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "BUG: Preflight check committed transaction `%s'!\n",
-                pg->transaction_name);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "BUG: Preflight check failed to commit transaction `%s'!\n",
-                pg->transaction_name);
-  }
-  pg->transaction_name = NULL;
-}
-
-
-/**
- * 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 int
-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
- * @return #GNUNET_OK on success
- */
-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 SYNC_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 older than the given time stamp should be garbage 
collected
-   * @return transaction status
-   */
-static enum SYNC_DB_QueryStatus
-postgres_gc (void *cls,
-             struct GNUNET_TIME_Absolute expire)
-{
-}
-
-
-/**
- * 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_AccountPublicKey *account_pub,
-                       const struct SYNC_AccountSignature *account_sig,
-                       const struct GNUNET_HashCode *backup_hash,
-                       size_t backup_size,
-                       const void *backup)
-{
-}
-
-
-/**
- * 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_AccountPublicKey *account_pub,
-                        const struct GNUNET_HashCode *old_backup_hash,
-                        const struct SYNC_AccountSignature *account_sig,
-                        const struct GNUNET_HashCode *backup_hash,
-                        size_t backup_size,
-                        const void *backup)
-{
-}
-
-
-/**
- * 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 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
- */
-static enum SYNC_DB_QueryStatus
-postgres_lookup_backup (void *cls,
-                        const struct SYNC_AccountPublicKey *account_pub,
-                        struct SYNC_AccountSignature *account_sig,
-                        struct GNUNET_HashCode *backup_hash,
-                        size_t *backup_size,
-                        void **backup)
-{
-}
-
-
-/**
- * Increment account lifetime.
- *
- * @param cls closure
- * @param account_pub which account received a 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_AccountPublicKey *account_pub,
-                             struct GNUNET_TIME_Relative lifetime)
-{
-}
-
-
-/**
- * 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)
-{
-  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct PostgresClosure *pg;
-  struct SYNC_DatabasePlugin *plugin;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    /* Orders created by the frontend, not signed or given a nonce yet.
-       The contract terms will change (nonce will be added) when moved to the
-       contract terms table */
-    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS accounts"
-                            "("
-                            "account_pub BYTEA PRIMARY KEY CHECK 
(length(account_pub)=32),"
-                            "expiration_date INT8 NOT NULL"
-                            ");"),
-    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS backups"
-                            "("
-                            "account_pub BYTEA PRIMARY KEY REFERENCES accounts 
(account_pub),"
-                            "account_sig BYTEA NOT NULL CHECK 
(length(account_sig)=64),"
-                            "backup_hash BYTEA NOT NULL CHECK 
(length(backup_hash)=64),"
-                            "data BYTEA NOT NULL"
-                            ");"),
-    /* index for gc */
-    GNUNET_PQ_make_try_execute (
-      "CREATE INDEX accounts_expire ON "
-      "accounts (expiration_date);"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-  struct GNUNET_PQ_PreparedStatement ps[] = {
-    GNUNET_PQ_make_prepare ("account_insert",
-                            "INSERT INTO accounts "
-                            "("
-                            "account_pub,"
-                            "expiration_date"
-                            ") VALUES "
-                            "($1,$2);",
-                            2),
-    GNUNET_PQ_make_prepare ("account_update",
-                            "UPDATE accounts "
-                            "SET"
-                            " expiration_date=expiration_data+$1 "
-                            "WHERE"
-                            " account_pub=$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("gc",
-                            "DELETE FROM accounts "
-                            "WHERE"
-                            " expiration_data<$1;",
-                            1),
-    GNUNET_PQ_make_prepare ("backup_insert",
-                            "INSERT INTO backups "
-                            "("
-                            "account_pub,"
-                            "account_sig,"
-                            "backup_hash,"
-                            "data"
-                            ") VALUES "
-                            "($1,$2,$3,$4);",
-                            4),
-    GNUNET_PQ_make_prepare ("backup_update",
-                            "UPDATE backups "
-                            " SET"
-                            " backup_hash=$1,"
-                            " account_sig=$2,"
-                            " data=$3"
-                            " WHERE"
-                            "   account_pub=$4"
-                            "  AND"
-                            "   backup_hash=$5"
-                            ") VALUES "
-                            "($1,$2,$3,$4,$5);",
-                            5),
-    GNUNET_PQ_make_prepare ("do_commit",
-                            "COMMIT",
-                            0),
-    GNUNET_PQ_PREPARED_STATEMENT_END
-  };
-
-  pg = GNUNET_new (struct PostgresClosure);
-  pg->cfg = cfg;
-  pg->conn = GNUNET_PQ_connect_with_cfg (cfg,
-                                         "syncdb-postgres",
-                                         es,
-                                         ps);
-  if (NULL == pg->conn)
-  {
-    GNUNET_free (pg);
-    return NULL;
-  }
-  plugin = GNUNET_new (struct SYNC_DatabasePlugin);
-  plugin->cls = pg;
-  plugin->drop_tables = &postgres_drop_tables;
-  plugin->gc = &postgres_gc;
-  plugin->store_backup_TR = &postgres_store_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)
-{
-  struct SYNC_DatabasePlugin *plugin = cls;
-  struct PostgresClosure *pg = plugin->cls;
-
-  GNUNET_PQ_disconnect (pg->conn);
-  GNUNET_free (pg);
-  GNUNET_free (plugin);
-  return NULL;
-}
-
-
-/* end of plugin_syncdb_postgres.c */
diff --git a/src/syncdb/plugin_syncdb_postgres.c 
b/src/syncdb/plugin_syncdb_postgres.c
new file mode 100644
index 0000000..d1c3e3e
--- /dev/null
+++ b/src/syncdb/plugin_syncdb_postgres.c
@@ -0,0 +1,817 @@
+/*
+  This file is part of TALER
+  (C) 2014--2019 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 sync/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_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;
+
+  /**
+   * Underlying configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Name of the currently active transaction, NULL if none is active.
+   */
+  const char *transaction_name;
+
+};
+
+
+/**
+ * Drop sync tables
+ *
+ * @param cls closure our `struct Plugin`
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+static int
+postgres_drop_tables (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS accounts CASCADE;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS backups;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  return GNUNET_PQ_exec_statements (pg->conn,
+                                    es);
+}
+
+
+/**
+ * Check that the database connection is still up.
+ *
+ * @param pg connection to check
+ */
+static void
+check_connection (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+
+  GNUNET_PQ_reconnect_if_down (pg->conn);
+}
+
+
+/**
+ * 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
+ */
+static void
+postgres_preflight (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("COMMIT"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  if (NULL == pg->transaction_name)
+    return; /* all good */
+  if (GNUNET_OK ==
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "BUG: Preflight check committed transaction `%s'!\n",
+                pg->transaction_name);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "BUG: Preflight check failed to commit transaction `%s'!\n",
+                pg->transaction_name);
+  }
+  pg->transaction_name = NULL;
+}
+
+
+/**
+ * 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 int
+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
+ * @return #GNUNET_OK on success
+ */
+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 SYNC_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 older than the given time stamp should be garbage 
collected
+ * @return transaction status
+ */
+static enum SYNC_DB_QueryStatus
+postgres_gc (void *cls,
+             struct GNUNET_TIME_Absolute expire)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_absolute_time (&expire),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  postgres_preflight (pg);
+  return (enum SYNC_DB_QueryStatus)
+         GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "gc",
+                                             params);
+}
+
+
+/**
+ * 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_AccountPublicKey *account_pub,
+                       const struct SYNC_AccountSignature *account_sig,
+                       const struct GNUNET_HashCode *backup_hash,
+                       size_t backup_size,
+                       const void *backup)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryStatus qs;
+  struct GNUNET_HashCode bh;
+
+  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 (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:
+    GNUNET_break (0);
+    return SYNC_DB_NO_RESULTS;
+  case GNUNET_DB_STATUS_SUCCESS_RESULT_ONE:
+    return SYNC_DB_ONE_RESULT;
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    /* handle interesting case below */
+    break;
+  }
+
+  /* First, check if account exists */
+  {
+    struct GNUNET_TIME_Absolute 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_RESULT_ONE:
+    /* handle interesting case below */
+    break;
+  }
+
+  /* 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_RESULT_ONE:
+    /* handle interesting case below */
+    break;
+  }
+
+  /* had an existing backup, is it identical? */
+  if (0 != GNUNET_memcmp (&bh,
+                          backup_hash))
+    /* previous conflicting backup exists */
+    return SYNC_DB_OLD_BACKUP_MISSMATCH;
+  /* backup identical to what was provided, no change */
+  return GNUNET_DB_STATUS_SUCCESS_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_AccountPublicKey *account_pub,
+                        const struct GNUNET_HashCode *old_backup_hash,
+                        const struct SYNC_AccountSignature *account_sig,
+                        const struct GNUNET_HashCode *backup_hash,
+                        size_t backup_size,
+                        const void *backup)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_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_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:
+    GNUNET_break (0);
+    return SYNC_DB_NO_RESULTS;
+  case GNUNET_DB_STATUS_SUCCESS_RESULT_ONE:
+    return SYNC_DB_ONE_RESULT;
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    /* handle interesting case below */
+    break;
+  }
+
+  /* First, check if account exists */
+  {
+    struct GNUNET_TIME_Absolute 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_RESULT_ONE:
+    /* handle interesting case below */
+    break;
+  }
+
+  /* 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:
+    /* Well, trying to update where there is no original
+       is a hard erorr, even though an odd one */
+    return SYNC_DB_HARD_ERROR;
+  case GNUNET_DB_STATUS_SUCCESS_RESULT_ONE:
+    /* handle interesting case below */
+    break;
+  }
+
+  /* had an existing backup, is it identical? */
+  if (0 == GNUNET_memcmp (&bh,
+                          backup_hash))
+    /* backup identical to what was provided, no change */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  if (0 == GNUNET_memcmp (&bh,
+                          old_backup_hash))
+    /* all constraints seem satisified, original error must
+       have been a hard error */
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  /* previous backup does not match old_backup_hash */
+  return SYNC_DB_OLD_BACKUP_MISSMATCH;
+}
+
+
+/**
+ * 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 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
+ */
+static enum SYNC_DB_QueryStatus
+postgres_lookup_backup (void *cls,
+                        const struct SYNC_AccountPublicKey *account_pub,
+                        struct SYNC_AccountSignature *account_sig,
+                        struct GNUNET_HashCode *backup_hash,
+                        size_t *backup_size,
+                        void **backup)
+{
+  struct PostgresClosure *pg = cls;
+  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 ("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_RESULT_ONE:
+    return SYNC_DB_ONE_RESULT;
+  }
+}
+
+
+/**
+ * Increment account lifetime.
+ *
+ * @param cls closure
+ * @param account_pub which account received a 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_AccountPublicKey *account_pub,
+                             struct GNUNET_TIME_Relative lifetime)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute expiration;
+  struct GNUNET_PQ_QueryStatus qs;
+
+  check_connection (pg);
+  if (GNUNET_OK !=
+      begin_transaction (pg,
+                         "increment lifetime"))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (account_pub),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_result_spec_absolute_time ("wire_deadline",
+                                          &wire_deadline),
+      GNUNET_PQ_result_spec_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (session->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_absolute_time (&expiration),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "account_insert",
+                                               params);
+    }
+    break;
+  case GNUNET_DB_STATUS_SUCCESS_RESULT_ONE:
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_absolute_time (&expiration),
+        GNUNET_PQ_query_param_auto_from_type (account_pub),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "account_update",
+                                               params);
+    }
+    break;
+  }
+  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_RESULT_ONE:
+    break;
+  }
+  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_RESULT_ONE:
+    return SYNC_DB_ONE_RESULT;
+  }
+}
+
+
+/**
+ * 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)
+{
+  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct PostgresClosure *pg;
+  struct SYNC_DatabasePlugin *plugin;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    /* Orders created by the frontend, not signed or given a nonce yet.
+       The contract terms will change (nonce will be added) when moved to the
+       contract terms table */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS accounts"
+                            "("
+                            "account_pub BYTEA PRIMARY KEY CHECK 
(length(account_pub)=32),"
+                            "expiration_date INT8 NOT NULL"
+                            ");"),
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS backups"
+                            "("
+                            "account_pub BYTEA PRIMARY KEY REFERENCES accounts 
(account_pub),"
+                            "account_sig BYTEA NOT NULL CHECK 
(length(account_sig)=64),"
+                            "backup_hash BYTEA NOT NULL CHECK 
(length(backup_hash)=64),"
+                            "data BYTEA NOT NULL"
+                            ");"),
+    /* index for gc */
+    GNUNET_PQ_make_try_execute (
+      "CREATE INDEX accounts_expire ON "
+      "accounts (expiration_date);"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+  struct GNUNET_PQ_PreparedStatement ps[] = {
+    GNUNET_PQ_make_prepare ("account_insert",
+                            "INSERT INTO accounts "
+                            "("
+                            "account_pub,"
+                            "expiration_date"
+                            ") VALUES "
+                            "($1,$2);",
+                            2),
+    GNUNET_PQ_make_prepare ("account_update",
+                            "UPDATE accounts "
+                            "SET"
+                            " expiration_date=$1 "
+                            "WHERE"
+                            " account_pub=$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("account_select",
+                            "SELECT"
+                            " expiration_date "
+                            "FROM"
+                            " account"
+                            "WHERE"
+                            " account_pub=$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc",
+                            "DELETE FROM accounts "
+                            "WHERE"
+                            " expiration_data<$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("backup_insert",
+                            "INSERT INTO backups "
+                            "(account_pub"
+                            ",account_sig"
+                            ",backup_hash"
+                            ",data"
+                            ") VALUES "
+                            "($1,$2,$3,$4);",
+                            4),
+    GNUNET_PQ_make_prepare ("backup_update",
+                            "UPDATE backups "
+                            " SET"
+                            " backup_hash=$1"
+                            ",account_sig=$2"
+                            ",data=$3"
+                            " WHERE"
+                            "   account_pub=$4"
+                            "  AND"
+                            "   backup_hash=$5"
+                            ") VALUES "
+                            "($1,$2,$3,$4,$5);",
+                            5),
+    GNUNET_PQ_make_prepare ("backup_select_hash",
+                            "SELECT "
+                            " backup_hash"
+                            "FROM"
+                            " backups"
+                            "WHERE"
+                            " account_pub=$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("backup_select",
+                            "SELECT "
+                            " account_sig"
+                            ",backup_hash"
+                            ",data"
+                            "FROM"
+                            " backups"
+                            "WHERE"
+                            " account_pub=$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("do_commit",
+                            "COMMIT",
+                            0),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
+
+  pg = GNUNET_new (struct PostgresClosure);
+  pg->cfg = cfg;
+  pg->conn = GNUNET_PQ_connect_with_cfg (cfg,
+                                         "syncdb-postgres",
+                                         es,
+                                         ps);
+  if (NULL == pg->conn)
+  {
+    GNUNET_free (pg);
+    return NULL;
+  }
+  plugin = GNUNET_new (struct SYNC_DatabasePlugin);
+  plugin->cls = pg;
+  plugin->drop_tables = &postgres_drop_tables;
+  plugin->gc = &postgres_gc;
+  plugin->store_backup_TR = &postgres_store_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)
+{
+  struct SYNC_DatabasePlugin *plugin = cls;
+  struct PostgresClosure *pg = plugin->cls;
+
+  GNUNET_PQ_disconnect (pg->conn);
+  GNUNET_free (pg);
+  GNUNET_free (plugin);
+  return NULL;
+}
+
+
+/* end of plugin_syncdb_postgres.c */
diff --git a/src/syncdb/test_sync_db.c b/src/syncdb/test_sync_db.c
index e57a548..55e5c98 100644
--- a/src/syncdb/test_sync_db.c
+++ b/src/syncdb/test_sync_db.c
@@ -1,6 +1,6 @@
 /*
   This file is part of
-  (C) 2014-2017 INRIA
+  (C) 2019 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
@@ -16,7 +16,6 @@
 /**
  * @file sync/test_sync_db.c
  * @brief testcase for sync postgres db plugin
- * @author Marcello Stanisci
  * @author Christian Grothoff
  */
 
@@ -50,76 +49,11 @@ static int result;
  */
 static struct SYNC_DatabasePlugin *plugin;
 
-/**
- * Payment Secret for the test, set to a random value
- */
-static struct SYNC_PaymentSecretP paymentSecretP;
-
 /**
  * User public key, set to a random value
  */
 static struct SYNC_AccountPubP accountPubP;
 
-/**
- * Amount which is deposited, set to random value
- */
-static struct TALER_Amount amount;
-
-/**
- * How many posts are paid by the payment
- */
-static unsigned int post_counter;
-
-/**
- * Recoverydata which is stored into the Database, set to a random value
- */
-static void *recovery_data;
-
-/**
- * Recovery_data for the select test
- */
-static void *res_recovery_data;
-
-/**
- * Truthdata which is stored into the Database, set to a random value
- */
-static void *truth_data;
-
-/**
- * Truth for the select test
- */
-static void *truth;
-
-/**
- * Keyshare which is stored into the Database, set to a random value
- */
-static void *key_share;
-
-/**
- * Keyshare for the select test
- */
-static void *res_key_share;
-
-/**
- * Mime-type of truth
- */
-static char *mime_type;
-
-/**
- * Mime-type of truth for the select test
- */
-static char *res_mime_type;
-
-/**
- * Version of a Recoverydocument
- */
-static uint32_t version;
-
-/**
- * Version of the latest Recoverydocument
- */
-static uint32_t res_version;
-
 
 /**
  * Main function that will be run by the scheduler.
@@ -150,6 +84,8 @@ run (void *cls)
     return;
   }
 
+  // FIXME: test logic here!
+
   GNUNET_break (GNUNET_OK ==
                 plugin->drop_tables (plugin->cls));
   SYNC_DB_plugin_unload (plugin);
@@ -197,4 +133,5 @@ main (int argc,
   return result;
 }
 
+
 /* end of test_sync_db.c */
diff --git a/src/syncdb/test_sync_db_postgres.conf 
b/src/syncdb/test_sync_db_postgres.conf
index f91dea1..c020cc7 100644
--- a/src/syncdb/test_sync_db_postgres.conf
+++ b/src/syncdb/test_sync_db_postgres.conf
@@ -1,7 +1,7 @@
-[anastasis]
+[sync]
 #The DB plugin to use
 DB = postgres
 
-[anastasisdb-postgres]
+[syncdb-postgres]
 #The connection string the plugin has to use for connecting to the database
-CONFIG = postgres:///anastasischeck
+CONFIG = postgres:///synccheck

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]