gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: -implement reserve closure in te


From: gnunet
Subject: [taler-exchange] branch master updated: -implement reserve closure in test
Date: Thu, 13 Oct 2022 19:07:32 +0200

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 09310cc6 -implement reserve closure in test
09310cc6 is described below

commit 09310cc66ebbdf083c4b4fa86a368b3ea52c0c16
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Thu Oct 13 19:07:25 2022 +0200

    -implement reserve closure in test
---
 src/exchange/taler-exchange-closer.c              |  19 ++-
 src/exchangedb/Makefile.am                        |   2 +
 src/exchangedb/bench_db.c                         |  18 +--
 src/exchangedb/common-0001.sql                    |  92 +++++-------
 src/exchangedb/exchange-0001-part.sql             |  19 +--
 src/exchangedb/pg_get_expired_reserves.c          | 173 ++++++++++++++++++++++
 src/exchangedb/pg_get_expired_reserves.h          |  45 ++++++
 src/exchangedb/pg_get_unfinished_close_requests.c | 162 ++++++++++++++++++++
 src/exchangedb/pg_get_unfinished_close_requests.h |  46 ++++++
 src/exchangedb/pg_insert_records_by_table.c       |  52 +------
 src/exchangedb/pg_lookup_records_by_table.c       |   9 ++
 src/exchangedb/pg_lookup_serial_by_table.c        |   8 -
 src/exchangedb/plugin_exchangedb_postgres.c       | 165 +--------------------
 src/exchangedb/shard-0001-part.sql                |   5 +-
 src/include/taler_exchangedb_plugin.h             |  29 ++--
 src/testing/test_exchange_p2p.c                   |   3 -
 16 files changed, 536 insertions(+), 311 deletions(-)

diff --git a/src/exchange/taler-exchange-closer.c 
b/src/exchange/taler-exchange-closer.c
index 0e203f0f..eacfa5d5 100644
--- a/src/exchange/taler-exchange-closer.c
+++ b/src/exchange/taler-exchange-closer.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016-2021 Taler Systems SA
+  Copyright (C) 2016-2022 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -431,11 +431,18 @@ run_reserve_closures (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Checking for reserves to close by date %s\n",
               GNUNET_TIME_timestamp2s (now));
-  qs = db_plugin->get_expired_reserves (db_plugin->cls,
-                                        now,
-                                        &expired_reserve_cb,
-                                        NULL);
-  GNUNET_assert (1 >= qs);
+  qs = db_plugin->get_unfinished_close_requests (db_plugin->cls,
+                                                 &expired_reserve_cb,
+                                                 NULL);
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+  {
+    /* Try expired reserves as well */
+    qs = db_plugin->get_expired_reserves (
+      db_plugin->cls,
+      now,
+      &expired_reserve_cb,
+      NULL);
+  }
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index 74edfc4c..e4094cd7 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -70,6 +70,8 @@ endif
 libtaler_plugin_exchangedb_postgres_la_SOURCES = \
   plugin_exchangedb_postgres.c pg_helper.h \
   pg_do_reserve_open.c pg_do_reserve_open.h \
+  pg_get_expired_reserves.c pg_get_expired_reserves.h \
+  pg_get_unfinished_close_requests.c pg_get_unfinished_close_requests.h \
   pg_insert_close_request.c pg_insert_close_request.h \
   pg_insert_records_by_table.c pg_insert_records_by_table.h \
   pg_insert_reserve_open_deposit.c pg_insert_reserve_open_deposit.h \
diff --git a/src/exchangedb/bench_db.c b/src/exchangedb/bench_db.c
index a8dbfbfa..a85834d1 100644
--- a/src/exchangedb/bench_db.c
+++ b/src/exchangedb/bench_db.c
@@ -51,32 +51,28 @@ prepare (struct GNUNET_PQ_Context *conn)
       "(hc"
       ",expiration_date"
       ") VALUES "
-      "($1, $2);",
-      2),
+      "($1, $2);"),
     /* Used in #postgres_iterate_denomination_info() */
     GNUNET_PQ_make_prepare (
       "bm_select",
       "SELECT"
       " expiration_date"
       " FROM benchmap"
-      " WHERE hc=$1;",
-      1),
+      " WHERE hc=$1;"),
     GNUNET_PQ_make_prepare (
       "bhm_insert",
       "INSERT INTO benchhmap "
       "(hc"
       ",expiration_date"
       ") VALUES "
-      "($1, $2);",
-      2),
+      "($1, $2);"),
     /* Used in #postgres_iterate_denomination_info() */
     GNUNET_PQ_make_prepare (
       "bhm_select",
       "SELECT"
       " expiration_date"
       " FROM benchhmap"
-      " WHERE hc=$1;",
-      1),
+      " WHERE hc=$1;"),
     GNUNET_PQ_make_prepare (
       "bem_insert",
       "INSERT INTO benchemap "
@@ -84,16 +80,14 @@ prepare (struct GNUNET_PQ_Context *conn)
       ",ihc"
       ",expiration_date"
       ") VALUES "
-      "($1, $2, $3);",
-      3),
+      "($1, $2, $3);"),
     /* Used in #postgres_iterate_denomination_info() */
     GNUNET_PQ_make_prepare (
       "bem_select",
       "SELECT"
       " expiration_date"
       " FROM benchemap"
-      " WHERE ihc=$1 AND hc=$2;",
-      2),
+      " WHERE ihc=$1 AND hc=$2;"),
     GNUNET_PQ_PREPARED_STATEMENT_END
   };
   enum GNUNET_GenericReturnValue ret;
diff --git a/src/exchangedb/common-0001.sql b/src/exchangedb/common-0001.sql
index 68d8643e..9f32ede7 100644
--- a/src/exchangedb/common-0001.sql
+++ b/src/exchangedb/common-0001.sql
@@ -502,57 +502,6 @@ END
 $$;
 
 
---------------------------- reserves_close_requests 
-------------------------------
-
-CREATE OR REPLACE FUNCTION create_table_reserves_close_requests(
-  IN shard_suffix VARCHAR DEFAULT NULL
-)
-RETURNS VOID
-LANGUAGE plpgsql
-AS $$
-DECLARE
-  table_name VARCHAR default 'reserves_close_requests';
-BEGIN
-
-  PERFORM create_partitioned_table(
-    'CREATE TABLE IF NOT EXISTS %I'
-      '(close_request_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE 
/ PRIMARY KEY'
-      ',reserve_pub BYTEA NOT NULL' -- REFERENCES reserves (reserve_pub) ON 
DELETE CASCADE'
-      ',execution_date INT8 NOT NULL'
-      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
-      ',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
-    ') %s ;'
-    ,table_name
-    ,'PARTITION BY HASH (reserve_pub)'
-    ,shard_suffix
-  );
-
-  table_name = concat_ws('_', table_name, shard_suffix);
-
-  EXECUTE FORMAT (
-    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_close_request_uuid_index '
-    'ON ' || table_name || ' '
-    '(close_request_uuid);'
-  );
-END
-$$;
-
-CREATE OR REPLACE FUNCTION 
add_constraints_to_reserves_close_requests_partition(
-  IN partition_suffix VARCHAR
-)
-RETURNS void
-LANGUAGE plpgsql
-AS $$
-BEGIN
-  EXECUTE FORMAT (
-    'ALTER TABLE reserves_close_requests_' || partition_suffix || ' '
-      'ADD CONSTRAINT reserves_close_' || partition_suffix || 
'_close_request_uuid_pkey '
-        'PRIMARY KEY (close_request_uuid)'
-  );
-END
-$$;
-
-
 ---------------------------- reserves_out -------------------------------
 
 CREATE OR REPLACE FUNCTION create_table_reserves_out(
@@ -1752,16 +1701,57 @@ BEGIN
       ',close_fee_val INT8 NOT NULL'
       ',close_fee_frac INT4 NOT NULL'
       ',payto_uri VARCHAR NOT NULL'
+      ',done BOOL NOT NULL DEFAULT(FALSE)'
       ',PRIMARY KEY (reserve_pub,close_timestamp)'
     ') %s ;'
     ,table_name
     ,'PARTITION BY HASH (reserve_pub)'
     ,shard_suffix
   );
+END
+$$;
+
 
+CREATE OR REPLACE FUNCTION add_constraints_to_close_requests(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'close_requests';
+BEGIN
+
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_close_request_uuid_index '
+    'ON ' || table_name || ' '
+    '(close_request_serial_id);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_close_request_done_index '
+    'ON ' || table_name || ' '
+    '(done);'
+  );
+END
+$$;
+
+CREATE OR REPLACE FUNCTION add_constraints_to_close_requests_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE close_requests_' || partition_suffix || ' '
+      'ADD CONSTRAINT close_requests_' || partition_suffix || 
'_close_request_uuid_pkey '
+        'UNIQUE (close_request_serial_id)'
+  );
 END
 $$;
 
+
+
 ------------------------------- purse_deposits -------------------------------
 
 CREATE OR REPLACE FUNCTION create_table_purse_deposits(
diff --git a/src/exchangedb/exchange-0001-part.sql 
b/src/exchangedb/exchange-0001-part.sql
index 48515a47..760acd98 100644
--- a/src/exchangedb/exchange-0001-part.sql
+++ b/src/exchangedb/exchange-0001-part.sql
@@ -269,22 +269,6 @@ CREATE TABLE IF NOT EXISTS reserves_open_deposits_default
 SELECT add_constraints_to_reserves_open_deposits_partition('default');
 
 
--- ------------------------------ reserves_close_requests 
----------------------------------------
-
-SELECT create_table_reserves_close_requests();
-
-COMMENT ON TABLE reserves_close_requests
-  IS 'explicit requests by clients to affect an immediate closure of a 
reserve';
-COMMENT ON COLUMN reserves_close_requests.wire_target_h_payto
-  IS 'Identifies the credited bank account. Optional.';
-
-CREATE TABLE IF NOT EXISTS reserves_close_requests_default
-  PARTITION OF reserves_close_requests
-  FOR VALUES WITH (MODULUS 1, REMAINDER 0);
-
-SELECT add_constraints_to_reserves_close_requests_partition('default');
-
-
 -- ------------------------------ reserves_out 
----------------------------------------
 
 SELECT create_table_reserves_out();
@@ -1284,11 +1268,14 @@ COMMENT ON COLUMN close_requests.reserve_sig
   IS 'Signature affirming that the reserve is to be closed';
 COMMENT ON COLUMN close_requests.close_val
   IS 'Balance of the reserve at the time of closing, to be wired to the 
associated bank account (minus the closing fee)';
+COMMENT ON COLUMN close_requests.payto_uri
+  IS 'Identifies the credited bank account. Optional.';
 
 CREATE TABLE IF NOT EXISTS close_requests_default
   PARTITION OF close_requests
   FOR VALUES WITH (MODULUS 1, REMAINDER 0);
 
+SELECT add_constraints_to_close_requests_partition('default');
 
 -- ------------------------------ purse_deposits 
----------------------------------------
 
diff --git a/src/exchangedb/pg_get_expired_reserves.c 
b/src/exchangedb/pg_get_expired_reserves.c
new file mode 100644
index 00000000..07a73911
--- /dev/null
+++ b/src/exchangedb/pg_get_expired_reserves.c
@@ -0,0 +1,173 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 pg_get_expired_reserves.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_expired_reserves.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #reserve_expired_cb().
+ */
+struct ExpiredReserveContext
+{
+  /**
+   * Function to call for each expired reserve.
+   */
+  TALER_EXCHANGEDB_ReserveExpiredCallback rec;
+
+  /**
+   * Closure to give to @e rec.
+   */
+  void *rec_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_expired_cb (void *cls,
+                    PGresult *result,
+                    unsigned int num_results)
+{
+  struct ExpiredReserveContext *erc = cls;
+  struct PostgresClosure *pg = erc->pg;
+  enum GNUNET_GenericReturnValue ret;
+
+  ret = GNUNET_OK;
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct GNUNET_TIME_Timestamp exp_date;
+    char *account_details;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_Amount remaining_balance;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_timestamp ("expiration_date",
+                                       &exp_date),
+      GNUNET_PQ_result_spec_string ("account_details",
+                                    &account_details),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
+                                   &remaining_balance),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ret = GNUNET_SYSERR;
+      break;
+    }
+    ret = erc->rec (erc->rec_cls,
+                    &reserve_pub,
+                    &remaining_balance,
+                    account_details,
+                    exp_date);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+  erc->status = ret;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_expired_reserves (void *cls,
+                             struct GNUNET_TIME_Timestamp now,
+                             TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+                             void *rec_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&now),
+    GNUNET_PQ_query_param_end
+  };
+  struct ExpiredReserveContext ectx = {
+    .rec = rec,
+    .rec_cls = rec_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  PREPARE (pg,
+           "get_expired_reserves",
+           "WITH ed AS MATERIALIZED ( "
+           " SELECT * "
+           " FROM reserves "
+           " WHERE expiration_date <= $1 "
+           "   AND (current_balance_val != 0 OR current_balance_frac != 0) "
+           " ORDER BY expiration_date ASC "
+           " LIMIT 1 "
+           ") "
+           "SELECT "
+           " ed.expiration_date "
+           " ,payto_uri AS account_details "
+           " ,ed.reserve_pub "
+           " ,current_balance_val "
+           " ,current_balance_frac "
+           "FROM ( "
+           " SELECT "
+           "  * "
+           " FROM reserves_in "
+           " WHERE reserve_pub = ( "
+           "     SELECT reserve_pub FROM ed) "
+           " ) ri "
+           "JOIN wire_targets wt ON (ri.wire_source_h_payto = 
wt.wire_target_h_payto) "
+           "JOIN ed ON (ri.reserve_pub = ed.reserve_pub);");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "get_expired_reserves",
+                                             params,
+                                             &reserve_expired_cb,
+                                             &ectx);
+  switch (ectx.status)
+  {
+  case GNUNET_SYSERR:
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  case GNUNET_NO:
+    return GNUNET_DB_STATUS_SOFT_ERROR;
+  case GNUNET_OK:
+    break;
+  }
+  return qs;
+}
diff --git a/src/exchangedb/pg_get_expired_reserves.h 
b/src/exchangedb/pg_get_expired_reserves.h
new file mode 100644
index 00000000..0874b531
--- /dev/null
+++ b/src/exchangedb/pg_get_expired_reserves.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 pg_get_expired_reserves.h
+ * @brief implementation of the get_expired_reserves function
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_EXPIRED_RESERVES_H
+#define PG_GET_EXPIRED_RESERVES_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Obtain information about expired reserves and their
+ * remaining balances.
+ *
+ * @param cls closure of the plugin
+ * @param now timestamp based on which we decide expiration
+ * @param rec function to call on expired reserves
+ * @param rec_cls closure for @a rec
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_expired_reserves (void *cls,
+                             struct GNUNET_TIME_Timestamp now,
+                             TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+                             void *rec_cls);
+
+#endif
diff --git a/src/exchangedb/pg_get_unfinished_close_requests.c 
b/src/exchangedb/pg_get_unfinished_close_requests.c
new file mode 100644
index 00000000..d9da6a7c
--- /dev/null
+++ b/src/exchangedb/pg_get_unfinished_close_requests.c
@@ -0,0 +1,162 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 pg_get_unfinished_close_requests.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_unfinished_close_requests.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #reserve_close_cb().
+ */
+struct CloseReserveContext
+{
+  /**
+   * Function to call for each to be closed reserve.
+   */
+  TALER_EXCHANGEDB_ReserveExpiredCallback rec;
+
+  /**
+   * Closure to give to @e rec.
+   */
+  void *rec_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_cb (void *cls,
+            PGresult *result,
+            unsigned int num_results)
+{
+  struct CloseReserveContext *erc = cls;
+  struct PostgresClosure *pg = erc->pg;
+  enum GNUNET_GenericReturnValue ret;
+
+  ret = GNUNET_OK;
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct GNUNET_TIME_Timestamp exp_date;
+    char *account_details;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_Amount remaining_balance;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_timestamp ("expiration_date",
+                                       &exp_date),
+      GNUNET_PQ_result_spec_string ("account_details",
+                                    &account_details),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("close",
+                                   &remaining_balance),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ret = GNUNET_SYSERR;
+      break;
+    }
+    ret = erc->rec (erc->rec_cls,
+                    &reserve_pub,
+                    &remaining_balance,
+                    account_details,
+                    exp_date);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+  erc->status = ret;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_unfinished_close_requests (
+  void *cls,
+  TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+  void *rec_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  struct CloseReserveContext ectx = {
+    .rec = rec,
+    .rec_cls = rec_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  PREPARE (pg,
+           "get_unfinished_close_requests",
+           "UPDATE close_requests AS rc"
+           " SET done=TRUE"
+           " WHERE done=FALSE"
+           " RETURNING"
+           "    reserve_pub"
+           "   ,close_timestamp AS expiration_date"
+           "   ,close_val"
+           "   ,close_frac"
+           "   ,(SELECT payto_uri"
+           "       FROM reserves_in ri"
+           "       JOIN wire_targets wt ON (ri.wire_source_h_payto = 
wt.wire_target_h_payto)"
+           "      WHERE ri.reserve_pub=rc.reserve_pub)"
+           "    AS account_details;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "get_unfinished_close_requests",
+                                             params,
+                                             &reserve_cb,
+                                             &ectx);
+  switch (ectx.status)
+  {
+  case GNUNET_SYSERR:
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  case GNUNET_NO:
+    return GNUNET_DB_STATUS_SOFT_ERROR;
+  case GNUNET_OK:
+    break;
+  }
+  return qs;
+}
diff --git a/src/exchangedb/pg_get_unfinished_close_requests.h 
b/src/exchangedb/pg_get_unfinished_close_requests.h
new file mode 100644
index 00000000..4c5aa0d1
--- /dev/null
+++ b/src/exchangedb/pg_get_unfinished_close_requests.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 pg_get_unfinished_close_requests.h
+ * @brief implementation of the get_unfinished_close_requests function
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_UNFINISHED_CLOSE_REQUESTS_H
+#define PG_GET_UNFINISHED_CLOSE_REQUESTS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Obtain information about force-closed reserves
+ * where the close was not yet done (and their remaining
+ * balances).  Updates the returned reserve's close
+ * status to "done".
+ *
+ * @param cls closure of the plugin
+ * @param rec function to call on expired reserves
+ * @param rec_cls closure for @a rec
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_unfinished_close_requests (
+  void *cls,
+  TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+  void *rec_cls);
+
+#endif
diff --git a/src/exchangedb/pg_insert_records_by_table.c 
b/src/exchangedb/pg_insert_records_by_table.c
index 90d38987..5613166c 100644
--- a/src/exchangedb/pg_insert_records_by_table.c
+++ b/src/exchangedb/pg_insert_records_by_table.c
@@ -429,46 +429,6 @@ irbt_cb_table_reserves_open_deposits (
 }
 
 
-/**
- * Function called with reserves_close records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_reserves_close_requests (
-  struct PostgresClosure *pg,
-  const struct TALER_EXCHANGEDB_TableData *td)
-{
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&td->serial),
-    GNUNET_PQ_query_param_auto_from_type (
-      &td->details.reserves_close_requests.reserve_pub),
-    GNUNET_PQ_query_param_timestamp (
-      &td->details.reserves_close_requests.execution_date),
-    GNUNET_PQ_query_param_auto_from_type (
-      &td->details.reserves_close_requests.reserve_sig),
-    GNUNET_PQ_query_param_auto_from_type (
-      &td->details.reserves_close_requests.wire_target_h_payto),
-    GNUNET_PQ_query_param_end
-  };
-
-  PREPARE (pg,
-           "insert_into_table_reserves_close_requests",
-           "INSERT INTO reserves_close_requests"
-           "(close_request_uuid"
-           ",reserve_pub"
-           ",execution_date"
-           ",reserve_sig"
-           ",wire_target_h_payto"
-           ") VALUES "
-           "($1, $2, $3, $4, $5);");
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             
"insert_into_table_reserves_close_requests",
-                                             params);
-}
-
-
 /**
  * Function called with reserves_close records to insert into table.
  *
@@ -1582,6 +1542,10 @@ irbt_cb_table_close_requests (struct PostgresClosure *pg,
       &td->details.close_requests.reserve_sig),
     TALER_PQ_query_param_amount (
       &td->details.close_requests.close),
+    TALER_PQ_query_param_amount (
+      &td->details.close_requests.close_fee),
+    GNUNET_PQ_query_param_string (
+      td->details.close_requests.payto_uri),
     GNUNET_PQ_query_param_end
   };
 
@@ -1594,8 +1558,11 @@ irbt_cb_table_close_requests (struct PostgresClosure *pg,
            ",reserve_sig"
            ",close_val"
            ",close_frac"
+           ",close_fee_val"
+           ",close_fee_frac"
+           ",payto_uri"
            ") VALUES "
-           "($1, $2, $3, $4, $5, $6);");
+           "($1, $2, $3, $4, $5, $6, $7, $8, $9);");
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              
"insert_into_table_close_requests",
                                              params);
@@ -1883,9 +1850,6 @@ TEH_PG_insert_records_by_table (void *cls,
   case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
     rh = &irbt_cb_table_reserves_open_deposits;
     break;
-  case TALER_EXCHANGEDB_RT_RESERVES_CLOSE_REQUESTS:
-    rh = &irbt_cb_table_reserves_close_requests;
-    break;
   case TALER_EXCHANGEDB_RT_RESERVES_OUT:
     rh = &irbt_cb_table_reserves_out;
     break;
diff --git a/src/exchangedb/pg_lookup_records_by_table.c 
b/src/exchangedb/pg_lookup_records_by_table.c
index 9e47de48..dc1f17ca 100644
--- a/src/exchangedb/pg_lookup_records_by_table.c
+++ b/src/exchangedb/pg_lookup_records_by_table.c
@@ -1867,12 +1867,21 @@ lrbt_cb_table_close_requests (void *cls,
       GNUNET_PQ_result_spec_auto_from_type (
         "reserve_pub",
         &td.details.close_requests.reserve_pub),
+      GNUNET_PQ_result_spec_timestamp (
+        "close_timestamp",
+        &td.details.close_requests.close_timestamp),
       GNUNET_PQ_result_spec_auto_from_type (
         "reserve_sig",
         &td.details.close_requests.reserve_sig),
       TALER_PQ_RESULT_SPEC_AMOUNT (
         "close",
         &td.details.close_requests.close),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "close_fee",
+        &td.details.close_requests.close_fee),
+      GNUNET_PQ_result_spec_string (
+        "payto_uri",
+        &td.details.close_requests.payto_uri),
       GNUNET_PQ_result_spec_end
     };
 
diff --git a/src/exchangedb/pg_lookup_serial_by_table.c 
b/src/exchangedb/pg_lookup_serial_by_table.c
index 500569c1..8dc6e061 100644
--- a/src/exchangedb/pg_lookup_serial_by_table.c
+++ b/src/exchangedb/pg_lookup_serial_by_table.c
@@ -133,14 +133,6 @@ TEH_PG_lookup_serial_by_table (void *cls,
               " ORDER BY open_request_uuid DESC"
               " LIMIT 1;");
     break;
-  case TALER_EXCHANGEDB_RT_RESERVES_CLOSE_REQUESTS:
-    XPREPARE ("select_serial_by_table_reserves_close_requests",
-              "SELECT"
-              " close_request_uuid AS serial"
-              " FROM reserves_close_requests"
-              " ORDER BY close_request_uuid DESC"
-              " LIMIT 1;");
-    break;
   case TALER_EXCHANGEDB_RT_RESERVES_OUT:
     XPREPARE ("select_serial_by_table_reserves_out",
               "SELECT"
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 89998047..9bf42155 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -31,6 +31,8 @@
 #include "taler_exchangedb_plugin.h"
 #include "pg_helper.h"
 #include "pg_do_reserve_open.h"
+#include "pg_get_expired_reserves.h"
+#include "pg_get_unfinished_close_requests.h"
 #include "pg_insert_close_request.h"
 #include "pg_insert_records_by_table.h"
 #include "pg_insert_reserve_open_deposit.h"
@@ -2344,32 +2346,6 @@ prepare_statements (struct PostgresClosure *pg)
       " FROM history_requests"
       " WHERE reserve_pub=$1"
       "  AND request_timestamp>=$2;"),
-    /* Used in #postgres_get_expired_reserves() */
-    GNUNET_PQ_make_prepare (
-      "get_expired_reserves",
-      "WITH ed AS MATERIALIZED ( "
-      " SELECT * "
-      " FROM reserves "
-      " WHERE expiration_date <= $1 "
-      "   AND (current_balance_val != 0 OR current_balance_frac != 0) "
-      " ORDER BY expiration_date ASC "
-      " LIMIT 1 "
-      ") "
-      "SELECT "
-      " ed.expiration_date "
-      " ,payto_uri AS account_details "
-      " ,ed.reserve_pub "
-      " ,current_balance_val "
-      " ,current_balance_frac "
-      "FROM ( "
-      " SELECT "
-      "  * "
-      " FROM reserves_in "
-      " WHERE reserve_pub = ( "
-      "     SELECT reserve_pub FROM ed) "
-      " ) ri "
-      "JOIN wire_targets wt ON (ri.wire_source_h_payto = 
wt.wire_target_h_payto) "
-      "JOIN ed ON (ri.reserve_pub = ed.reserve_pub);"),
     /* Used in #postgres_get_coin_transactions() to obtain recoup transactions
        for a coin */
     GNUNET_PQ_make_prepare (
@@ -8550,138 +8526,6 @@ postgres_insert_global_fee (void *cls,
 }
 
 
-/**
- * Closure for #reserve_expired_cb().
- */
-struct ExpiredReserveContext
-{
-  /**
-   * Function to call for each expired reserve.
-   */
-  TALER_EXCHANGEDB_ReserveExpiredCallback rec;
-
-  /**
-   * Closure to give to @e rec.
-   */
-  void *rec_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on error.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserve_expired_cb (void *cls,
-                    PGresult *result,
-                    unsigned int num_results)
-{
-  struct ExpiredReserveContext *erc = cls;
-  struct PostgresClosure *pg = erc->pg;
-  enum GNUNET_GenericReturnValue ret;
-
-  ret = GNUNET_OK;
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct GNUNET_TIME_Timestamp exp_date;
-    char *account_details;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_Amount remaining_balance;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_timestamp ("expiration_date",
-                                       &exp_date),
-      GNUNET_PQ_result_spec_string ("account_details",
-                                    &account_details),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            &reserve_pub),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
-                                   &remaining_balance),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      ret = GNUNET_SYSERR;
-      break;
-    }
-    ret = erc->rec (erc->rec_cls,
-                    &reserve_pub,
-                    &remaining_balance,
-                    account_details,
-                    exp_date);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-  erc->status = ret;
-}
-
-
-/**
- * Obtain information about expired reserves and their
- * remaining balances.
- *
- * @param cls closure of the plugin
- * @param now timestamp based on which we decide expiration
- * @param rec function to call on expired reserves
- * @param rec_cls closure for @a rec
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_expired_reserves (void *cls,
-                               struct GNUNET_TIME_Timestamp now,
-                               TALER_EXCHANGEDB_ReserveExpiredCallback rec,
-                               void *rec_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&now),
-    GNUNET_PQ_query_param_end
-  };
-  struct ExpiredReserveContext ectx = {
-    .rec = rec,
-    .rec_cls = rec_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "get_expired_reserves",
-                                             params,
-                                             &reserve_expired_cb,
-                                             &ectx);
-  switch (ectx.status)
-  {
-  case GNUNET_SYSERR:
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  case GNUNET_NO:
-    return GNUNET_DB_STATUS_SOFT_ERROR;
-  case GNUNET_OK:
-    break;
-  }
-  return qs;
-}
-
-
 /**
  * Insert reserve close operation into database.
  *
@@ -15118,7 +14962,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->get_wire_fee = &postgres_get_wire_fee;
   plugin->get_global_fee = &postgres_get_global_fee;
   plugin->get_global_fees = &postgres_get_global_fees;
-  plugin->get_expired_reserves = &postgres_get_expired_reserves;
   plugin->insert_reserve_closed = &postgres_insert_reserve_closed;
   plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert;
   plugin->wire_prepare_data_mark_finished =
@@ -15290,6 +15133,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   /* NEW style, sort alphabetically! */
   plugin->do_reserve_open
     = &TEH_PG_do_reserve_open;
+  plugin->get_expired_reserves
+    = &TEH_PG_get_expired_reserves;
+  plugin->get_unfinished_close_requests
+    = &TEH_PG_get_unfinished_close_requests;
   plugin->insert_records_by_table
     = &TEH_PG_insert_records_by_table;
   plugin->insert_reserve_open_deposit
diff --git a/src/exchangedb/shard-0001-part.sql 
b/src/exchangedb/shard-0001-part.sql
index 0f20be63..a54eb8dc 100644
--- a/src/exchangedb/shard-0001-part.sql
+++ b/src/exchangedb/shard-0001-part.sql
@@ -50,9 +50,6 @@ BEGIN
   PERFORM create_table_reserves_open_deposits(shard_suffix);
   PERFORM add_constraints_to_reserves_open_deposits_partition(shard_suffix);
 
-  PERFORM create_table_reserves_close_requests(shard_suffix);
-  PERFORM add_constraints_to_reserves_close_requests_partition(shard_suffix);
-
   PERFORM create_table_reserves_out(shard_suffix);
   PERFORM add_constraints_to_reserves_out_partition(shard_suffix);
 
@@ -119,6 +116,8 @@ BEGIN
   PERFORM create_table_history_requests(shard_suffix);
 
   PERFORM create_table_close_requests(shard_suffix);
+  PERFORM add_constraints_to_close_requests_partition(shard_suffix);
+
 
   PERFORM create_table_purse_deposits(shard_suffix);
   PERFORM add_constraints_to_purse_deposits_partition(shard_suffix);
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 06fa2479..d361d539 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -202,7 +202,6 @@ enum TALER_EXCHANGEDB_ReplicatedTable
   TALER_EXCHANGEDB_RT_RESERVES_CLOSE,
   TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS,
   TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS,
-  TALER_EXCHANGEDB_RT_RESERVES_CLOSE_REQUESTS,
   TALER_EXCHANGEDB_RT_RESERVES_OUT,
   TALER_EXCHANGEDB_RT_AUDITORS,
   TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS,
@@ -337,14 +336,6 @@ struct TALER_EXCHANGEDB_TableData
       struct TALER_Amount contribution;
     } reserves_open_deposits;
 
-    struct
-    {
-      struct TALER_ReservePublicKeyP reserve_pub;
-      struct GNUNET_TIME_Timestamp execution_date;
-      struct TALER_ReserveSignatureP reserve_sig;
-      struct TALER_PaytoHashP wire_target_h_payto;
-    } reserves_close_requests;
-
     struct
     {
       struct TALER_ReservePublicKeyP reserve_pub;
@@ -587,6 +578,8 @@ struct TALER_EXCHANGEDB_TableData
       struct GNUNET_TIME_Timestamp close_timestamp;
       struct TALER_ReserveSignatureP reserve_sig;
       struct TALER_Amount close;
+      struct TALER_Amount close_fee;
+      char *payto_uri;
     } close_requests;
 
     struct
@@ -4110,6 +4103,24 @@ struct TALER_EXCHANGEDB_Plugin
                           void *rec_cls);
 
 
+  /**
+   * Obtain information about force-closed reserves
+   * where the close was not yet done (and their remaining
+   * balances).  Updates the returned reserve's close
+   * status to "done".
+   *
+   * @param cls closure of the plugin
+   * @param rec function to call on (to be) closed reserves
+   * @param rec_cls closure for @a rec
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_unfinished_close_requests)(
+    void *cls,
+    TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+    void *rec_cls);
+
+
   /**
    * Insert reserve open coin deposit data into database.
    * Subtracts the @a coin_total from the coin's balance.
diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c
index 1a6c5854..222cd3d4 100644
--- a/src/testing/test_exchange_p2p.c
+++ b/src/testing/test_exchange_p2p.c
@@ -446,8 +446,6 @@ run (void *cls,
                                      "create-reserve-101",
                                      NULL, /* to origin */
                                      MHD_HTTP_OK),
-#if FIXME
-    /* reserve close logic is not yet implemented, hence this fails: */
     TALER_TESTING_cmd_exec_closer ("close-reserves-101",
                                    config_file,
                                    "EUR:1.02",
@@ -459,7 +457,6 @@ run (void *cls,
                               "create-reserve-101",
                               "EUR:0",
                               MHD_HTTP_OK),
-#endif
     TALER_TESTING_cmd_end ()
   };
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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