gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (b6b80e61 -> 4cf0d858)


From: gnunet
Subject: [taler-exchange] branch master updated (b6b80e61 -> 4cf0d858)
Date: Tue, 20 Dec 2022 11:39:16 +0100

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

joseph-xu pushed a change to branch master
in repository exchange.

    from b6b80e61 refactor wirewatch to enable use of batch API
     new 48b7d459 some modifications in sql code
     new b0c10612 new batch test and standard deviation
     new 4cf0d858 update of batch 1-2-4 test

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 contrib/gana                                       |   2 +-
 src/exchangedb/Makefile.am                         |  28 +-
 .../exchange_do_batch2_reserves_in_insert.sql      | 194 ++++++++
 .../exchange_do_batch4_reserves_in_insert.sql      | 333 +++++++++++++
 ...ql => exchange_do_batch_reserves_in_insert.sql} |  75 +--
 ...n.sql => exchange_do_batch_reserves_update.sql} |  75 +--
 src/exchangedb/pg_batch2_reserves_in_insert.c      | 549 ++++++++++++++++-----
 src/exchangedb/pg_batch2_reserves_in_insert.h      |   1 +
 src/exchangedb/pg_batch4_reserves_in_insert.c      | 505 +++++++++++++++----
 src/exchangedb/pg_batch4_reserves_in_insert.h      |  34 --
 src/exchangedb/pg_batch_reserves_in_insert.c       |  22 +-
 src/exchangedb/procedures.sql.in                   |   7 +-
 .../test_exchangedb_batch_reserves_in_insert.c     |  19 +-
 src/exchangedb/test_exchangedb_by_j.c              | 126 +++--
 src/include/taler_exchangedb_plugin.h              |   1 +
 15 files changed, 1530 insertions(+), 441 deletions(-)
 create mode 100644 src/exchangedb/exchange_do_batch2_reserves_in_insert.sql
 create mode 100644 src/exchangedb/exchange_do_batch4_reserves_in_insert.sql
 copy src/exchangedb/{exchange_do_batch_reserves_in.sql => 
exchange_do_batch_reserves_in_insert.sql} (62%)
 rename src/exchangedb/{exchange_do_batch_reserves_in.sql => 
exchange_do_batch_reserves_update.sql} (56%)
 delete mode 100644 src/exchangedb/pg_batch4_reserves_in_insert.h

diff --git a/contrib/gana b/contrib/gana
index 149aa0a0..3e659ed5 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 149aa0a08d787419e02277ef231d93c6a0154a47
+Subproject commit 3e659ed54023230dd45dbec5664f176e1763d260
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index a6eb6747..755de66a 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -282,13 +282,15 @@ check_PROGRAMS = \
   bench-db-postgres\
   perf-exchangedb-reserves-in-insert-postgres\
   test-exchangedb-by-j-postgres\
-  test-exchangedb-batch-reserves-in-insert-postgres
+  test-exchangedb-batch-reserves-in-insert-postgres\
+  test-exchangedb-populate-table-postgres
 AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export 
PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
 TESTS = \
   test-exchangedb-postgres\
   test-exchangedb-by-j-postgres\
   perf-exchangedb-reserves-in-insert-postgres\
-  test-exchangedb-batch-reserves-in-insert-postgres
+  test-exchangedb-batch-reserves-in-insert-postgres\
+  test-exchangedb-populate-table-postgres
 
 
 test_exchangedb_postgres_SOURCES = \
@@ -313,6 +315,7 @@ test_exchangedb_by_j_postgres_LDADD = \
   -ljansson \
   -lgnunetjson \
   -lgnunetutil \
+  -lm \
   $(XLIB)
 
 
@@ -361,6 +364,27 @@ bench_db_postgres_LDADD = \
   -lgnunetutil \
   $(XLIB)
 
+test_exchangedb_populate_table_postgres_SOURCES = \
+  test_exchangedb_populate_table.c
+test_exchangedb_populate_table_postgres_LDADD = \
+  libtalerexchangedb.la \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/pq/libtalerpq.la \
+  -ljansson \
+  -lgnunetjson \
+  -lgnunetutil \
+  $(XLIB)
+
+bench_db_postgres_SOURCES = \
+  bench_db.c
+bench_db_postgres_LDADD = \
+  libtalerexchangedb.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/pq/libtalerpq.la \
+  -lgnunetpq \
+  -lgnunetutil \
+  $(XLIB)
 
 EXTRA_test_exchangedb_postgres_DEPENDENCIES = \
   libtaler_plugin_exchangedb_postgres.la
diff --git a/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql
new file mode 100644
index 00000000..6a0cc6d7
--- /dev/null
+++ b/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql
@@ -0,0 +1,194 @@
+--
+-- This file is part of TALER
+-- Copyright (C) 2014--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/>
+--
+CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert(
+  IN in_reserve_pub BYTEA,
+  IN in_expiration_date INT8,
+  IN in_gc_date INT8,
+  IN in_wire_ref INT8,
+  IN in_credit_val INT8,
+  IN in_credit_frac INT4,
+  IN in_exchange_account_name VARCHAR,
+  IN in_exectution_date INT8,
+  IN in_wire_source_h_payto BYTEA,    ---h_payto
+  IN in_payto_uri VARCHAR,
+  IN in_reserve_expiration INT8,
+  IN in_notify text,
+  IN in2_notify text,
+  IN in2_reserve_pub BYTEA,
+  IN in2_wire_ref INT8,
+  IN in2_credit_val INT8,
+  IN in2_credit_frac INT4,
+  IN in2_exchange_account_name VARCHAR,
+  IN in2_exectution_date INT8,
+  IN in2_wire_source_h_payto BYTEA,    ---h_payto
+  IN in2_payto_uri VARCHAR,
+  IN in2_reserve_expiration INT8,
+  OUT out_reserve_found BOOLEAN,
+  OUT out_reserve_found2 BOOLEAN,
+  OUT transaction_duplicate BOOLEAN,
+  OUT transaction_duplicate2 BOOLEAN,
+  OUT ruuid INT8,
+  OUT ruuid2 INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  curs_reserve_exist REFCURSOR;
+
+--  FOR SELECT reserve_pub
+--  FROM reserves
+--  WHERE in_reserve_pub = reserves.reserve_pub
+--  OR in2_reserve_pub = reserves.reserve_pub;
+DECLARE
+  curs_transaction_exist CURSOR
+  FOR SELECT reserve_pub
+  FROM reserves_in
+  WHERE in_reserve_pub = reserves_in.reserve_pub
+  OR in2_reserve_pub = reserves_in.reserve_pub;
+DECLARE
+  i RECORD;
+
+BEGIN
+  --SIMPLE INSERT ON CONFLICT DO NOTHING
+  transaction_duplicate=FALSE;
+  transaction_duplicate2=FALSE;
+  out_reserve_found = TRUE;
+  out_reserve_found2 = TRUE;
+  ruuid=0;
+  ruuid2=0;
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri),
+    (in2_wire_source_h_payto
+    ,in2_payto_uri)
+  ON CONFLICT DO NOTHING;
+
+  OPEN curs_reserve_exist FOR
+  WITH reserve_changes AS (
+    INSERT INTO reserves
+      (reserve_pub
+      ,current_balance_val
+      ,current_balance_frac
+      ,expiration_date
+      ,gc_date)
+      VALUES
+      (in_reserve_pub
+      ,in_credit_val
+      ,in_credit_frac
+      ,in_expiration_date
+      ,in_gc_date),
+      (in2_reserve_pub
+      ,in2_credit_val
+      ,in2_credit_frac
+      ,in_expiration_date
+      ,in_gc_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_uuid,reserve_pub)
+    SELECT * FROM reserve_changes;
+
+  FETCH FROM curs_reserve_exist INTO i;
+  IF FOUND
+  THEN
+    IF in_reserve_pub = i.reserve_pub
+    THEN
+       out_reserve_found = FALSE;
+       ruuid = i.reserve_uuid;
+    END IF;
+    IF in2_reserve_pub = i.reserve_pub
+    THEN
+        out_reserve_found2 = FALSE;
+        ruuid2 = i.reserve_uuid;
+    END IF;
+    FETCH FROM curs_reserve_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+        out_reserve_found = FALSE;
+        ruuid = i.reserve_uuid;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+        out_reserve_found2 = FALSE;
+        ruuid2 = i.reserve_uuid;
+     END IF;
+    END IF;
+  END IF;
+  CLOSE curs_reserve_exist;
+  IF out_reserve_found AND out_reserve_found2
+  THEN
+      RETURN;
+  END IF;
+
+  PERFORM pg_notify(in_notify, NULL);
+  PERFORM pg_notify(in2_notify, NULL);
+
+  INSERT INTO reserves_in
+    (reserve_pub
+    ,wire_reference
+    ,credit_val
+    ,credit_frac
+    ,exchange_account_section
+    ,wire_source_h_payto
+    ,execution_date)
+    VALUES
+    (in_reserve_pub
+    ,in_wire_ref
+    ,in_credit_val
+    ,in_credit_frac
+    ,in_exchange_account_name
+    ,in_wire_source_h_payto
+    ,in_expiration_date),
+    (in2_reserve_pub
+    ,in2_wire_ref
+    ,in2_credit_val
+    ,in2_credit_frac
+    ,in2_exchange_account_name
+    ,in2_wire_source_h_payto
+    ,in_expiration_date)
+    ON CONFLICT DO NOTHING;
+  IF FOUND
+  THEN
+    transaction_duplicate = FALSE;  /*HAPPY PATH THERE IS NO DUPLICATE TRANS 
AND NEW RESERVE*/
+    transaction_duplicate2 = FALSE;
+    RETURN;
+  ELSE
+    FOR l IN curs_transaction_exist
+    LOOP
+      IF in_reserve_pub = l.reserve_pub
+      THEN
+         transaction_duplicate = TRUE;
+      END IF;
+
+      IF in2_reserve_pub = l.reserve_pub
+      THEN
+         transaction_duplicate2 = TRUE;
+      END IF;
+
+      IF transaction_duplicate AND transaction_duplicate2
+      THEN
+        RETURN;
+      END IF;
+    END LOOP;
+  END IF;
+
+  CLOSE curs_reserve_exist;
+  CLOSE curs_transaction_exist;
+  RETURN;
+END $$;
+
diff --git a/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql
new file mode 100644
index 00000000..ece92698
--- /dev/null
+++ b/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql
@@ -0,0 +1,333 @@
+--
+-- This file is part of TALER
+-- Copyright (C) 2014--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/>
+--
+CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert(
+  IN in_reserve_pub BYTEA,
+  IN in_expiration_date INT8,
+  IN in_gc_date INT8,
+  IN in_wire_ref INT8,
+  IN in_credit_val INT8,
+  IN in_credit_frac INT4,
+  IN in_exchange_account_name VARCHAR,
+  IN in_exectution_date INT8,
+  IN in_wire_source_h_payto BYTEA,    ---h_payto
+  IN in_payto_uri VARCHAR,
+  IN in_reserve_expiration INT8,
+  IN in_notify text,
+  IN in2_notify text,
+  IN in3_notify text,
+  IN in4_notify text,
+  IN in2_reserve_pub BYTEA,
+  IN in2_wire_ref INT8,
+  IN in2_credit_val INT8,
+  IN in2_credit_frac INT4,
+  IN in2_exchange_account_name VARCHAR,
+  IN in2_exectution_date INT8,
+  IN in2_wire_source_h_payto BYTEA,    ---h_payto
+  IN in2_payto_uri VARCHAR,
+  IN in2_reserve_expiration INT8,
+  IN in3_reserve_pub BYTEA,
+  IN in3_wire_ref INT8,
+  IN in3_credit_val INT8,
+  IN in3_credit_frac INT4,
+  IN in3_exchange_account_name VARCHAR,
+  IN in3_exectution_date INT8,
+  IN in3_wire_source_h_payto BYTEA,    ---h_payto
+  IN in3_payto_uri VARCHAR,
+  IN in3_reserve_expiration INT8,
+  IN in4_reserve_pub BYTEA,
+  IN in4_wire_ref INT8,
+  IN in4_credit_val INT8,
+  IN in4_credit_frac INT4,
+  IN in4_exchange_account_name VARCHAR,
+  IN in4_exectution_date INT8,
+  IN in4_wire_source_h_payto BYTEA,    ---h_payto
+  IN in4_payto_uri VARCHAR,
+  IN in4_reserve_expiration INT8,
+  OUT out_reserve_found BOOLEAN,
+  OUT out_reserve_found2 BOOLEAN,
+  OUT out_reserve_found3 BOOLEAN,
+  OUT out_reserve_found4 BOOLEAN,
+  OUT transaction_duplicate BOOLEAN,
+  OUT transaction_duplicate2 BOOLEAN,
+  OUT transaction_duplicate3 BOOLEAN,
+  OUT transaction_duplicate4 BOOLEAN,
+  OUT ruuid INT8,
+  OUT ruuid2 INT8,
+  OUT ruuid3 INT8,
+  OUT ruuid4 INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  curs_reserve_exist refcursor;
+
+DECLARE
+  curs_transaction_exist CURSOR
+  FOR SELECT reserve_pub
+  FROM reserves_in
+  WHERE in_reserve_pub = reserves_in.reserve_pub
+  OR in2_reserve_pub = reserves_in.reserve_pub
+  OR in3_reserve_pub = reserves_in.reserve_pub
+  OR in4_reserve_pub = reserves_in.reserve_pub;
+DECLARE
+  i RECORD;
+
+BEGIN
+--INITIALIZATION
+  transaction_duplicate=FALSE;
+  transaction_duplicate2=FALSE;
+  transaction_duplicate3=FALSE;
+  transaction_duplicate4=FALSE;
+  out_reserve_found = TRUE;
+  out_reserve_found2 = TRUE;
+  out_reserve_found3 = TRUE;
+  out_reserve_found4 = TRUE;
+  ruuid=0;
+  ruuid2=0;
+  ruuid3=0;
+  ruuid4=0;
+
+  --SIMPLE INSERT ON CONFLICT DO NOTHING
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri),
+    (in2_wire_source_h_payto
+    ,in2_payto_uri),
+    (in3_wire_source_h_payto
+    ,in3_payto_uri),
+    (in4_wire_source_h_payto
+    ,in4_payto_uri)
+  ON CONFLICT DO NOTHING;
+
+  OPEN curs_reserve_exist FOR
+  WITH reserve_changes AS (
+    INSERT INTO reserves
+      (reserve_pub
+      ,current_balance_val
+      ,current_balance_frac
+      ,expiration_date
+      ,gc_date)
+      VALUES
+      (in_reserve_pub
+      ,in_credit_val
+      ,in_credit_frac
+      ,in_expiration_date
+      ,in_gc_date),
+      (in2_reserve_pub
+      ,in2_credit_val
+      ,in2_credit_frac
+      ,in_expiration_date
+      ,in_gc_date),
+      (in3_reserve_pub
+      ,in3_credit_val
+      ,in3_credit_frac
+      ,in_expiration_date
+      ,in_gc_date),
+      (in4_reserve_pub
+      ,in4_credit_val
+      ,in4_credit_frac
+      ,in_expiration_date
+      ,in_gc_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_uuid,reserve_pub)
+    SELECT * FROM reserve_changes;
+
+  FETCH FROM curs_reserve_exist INTO i;
+  IF FOUND
+  THEN
+    IF in_reserve_pub = i.reserve_pub
+    THEN
+       out_reserve_found = FALSE;
+       ruuid = i.reserve_uuid;
+    END IF;
+    IF in2_reserve_pub = i.reserve_pub
+    THEN
+        out_reserve_found2 = FALSE;
+        ruuid2 = i.reserve_uuid;
+    END IF;
+    IF in3_reserve_pub = i.reserve_pub
+    THEN
+        out_reserve_found3 = FALSE;
+        ruuid3 = i.reserve_uuid;
+    END IF;
+    IF in4_reserve_pub = i.reserve_pub
+    THEN
+        out_reserve_found4 = FALSE;
+        ruuid4 = i.reserve_uuid;
+    END IF;
+    FETCH FROM curs_reserve_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+        out_reserve_found = FALSE;
+        ruuid = i.reserve_uuid;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+        out_reserve_found2 = FALSE;
+        ruuid2 = i.reserve_uuid;
+      END IF;
+      IF in3_reserve_pub = i.reserve_pub
+      THEN
+        out_reserve_found3 = FALSE;
+        ruuid3 = i.reserve_uuid;
+      END IF;
+      IF in4_reserve_pub = i.reserve_pub
+      THEN
+        out_reserve_found4 = FALSE;
+        ruuid4 = i.reserve_uuid;
+      END IF;
+    END IF;
+    FETCH FROM curs_reserve_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found = FALSE;
+          ruuid = i.reserve_uuid;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found2 = FALSE;
+          ruuid2 = i.reserve_uuid;
+      END IF;
+      IF in3_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found3 = FALSE;
+          ruuid3 = i.reserve_uuid;
+      END IF;
+      IF in4_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found4 = FALSE;
+          ruuid4 = i.reserve_uuid;
+      END IF;
+    END IF;
+    FETCH FROM curs_reserve_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found = FALSE;
+          ruuid = i.reserve_uuid;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found2 = FALSE;
+          ruuid2 = i.reserve_uuid;
+      END IF;
+      IF in3_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found3 = FALSE;
+          ruuid3 = i.reserve_uuid;
+      END IF;
+      IF in4_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found4 = FALSE;
+          ruuid4 = i.reserve_uuid;
+      END IF;
+    END IF;
+  END IF;
+  CLOSE curs_reserve_exist;
+  IF out_reserve_found AND out_reserve_found2 AND out_reserve_found3 AND 
out_reserve_found4
+  THEN
+      RETURN;
+  END IF;
+
+  PERFORM pg_notify(in_notify, NULL);
+  PERFORM pg_notify(in2_notify, NULL);
+  PERFORM pg_notify(in3_notify, NULL);
+  PERFORM pg_notify(in4_notify, NULL);
+
+  INSERT INTO reserves_in
+    (reserve_pub
+    ,wire_reference
+    ,credit_val
+    ,credit_frac
+    ,exchange_account_section
+    ,wire_source_h_payto
+    ,execution_date)
+    VALUES
+    (in_reserve_pub
+    ,in_wire_ref
+    ,in_credit_val
+    ,in_credit_frac
+    ,in_exchange_account_name
+    ,in_wire_source_h_payto
+    ,in_expiration_date),
+    (in2_reserve_pub
+    ,in2_wire_ref
+    ,in2_credit_val
+    ,in2_credit_frac
+    ,in2_exchange_account_name
+    ,in2_wire_source_h_payto
+    ,in_expiration_date),
+    (in3_reserve_pub
+    ,in3_wire_ref
+    ,in3_credit_val
+    ,in3_credit_frac
+    ,in3_exchange_account_name
+    ,in3_wire_source_h_payto
+    ,in_expiration_date),
+    (in4_reserve_pub
+    ,in4_wire_ref
+    ,in4_credit_val
+    ,in4_credit_frac
+    ,in4_exchange_account_name
+    ,in4_wire_source_h_payto
+    ,in_expiration_date)
+    ON CONFLICT DO NOTHING;
+  IF FOUND
+  THEN
+    transaction_duplicate = FALSE;  /*HAPPY PATH THERE IS NO DUPLICATE TRANS 
AND NEW RESERVE*/
+    transaction_duplicate2 = FALSE;
+    transaction_duplicate3 = FALSE;
+    transaction_duplicate4 = FALSE;
+    RETURN;
+  ELSE
+    FOR l IN curs_transaction_exist
+    LOOP
+      IF in_reserve_pub = l.reserve_pub
+      THEN
+         transaction_duplicate = TRUE;
+      END IF;
+
+      IF in2_reserve_pub = l.reserve_pub
+      THEN
+         transaction_duplicate2 = TRUE;
+      END IF;
+      IF in3_reserve_pub = l.reserve_pub
+      THEN
+         transaction_duplicate3 = TRUE;
+      END IF;
+      IF in4_reserve_pub = l.reserve_pub
+      THEN
+         transaction_duplicate4 = TRUE;
+      END IF;
+
+      IF transaction_duplicate AND transaction_duplicate2 AND 
transaction_duplicate3 AND transaction_duplicate4
+      THEN
+        RETURN;
+      END IF;
+    END LOOP;
+  END IF;
+
+  CLOSE curs_reserve_exist;
+  CLOSE curs_transaction_exist;
+  RETURN;
+END $$;
diff --git a/src/exchangedb/exchange_do_batch_reserves_in.sql 
b/src/exchangedb/exchange_do_batch_reserves_in_insert.sql
similarity index 62%
copy from src/exchangedb/exchange_do_batch_reserves_in.sql
copy to src/exchangedb/exchange_do_batch_reserves_in_insert.sql
index faad2ca8..ef4c84aa 100644
--- a/src/exchangedb/exchange_do_batch_reserves_in.sql
+++ b/src/exchangedb/exchange_do_batch_reserves_in_insert.sql
@@ -13,7 +13,8 @@
 -- 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/>
 --
-CREATE OR REPLACE FUNCTION batch_reserves_in(
+
+CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert(
   IN in_reserve_pub BYTEA,
   IN in_expiration_date INT8,
   IN in_gc_date INT8,
@@ -25,16 +26,22 @@ CREATE OR REPLACE FUNCTION batch_reserves_in(
   IN in_wire_source_h_payto BYTEA,    ---h_payto
   IN in_payto_uri VARCHAR,
   IN in_reserve_expiration INT8,
+  IN in_notify text,
   OUT out_reserve_found BOOLEAN,
   OUT transaction_duplicate BOOLEAN,
   OUT ruuid INT8)
 LANGUAGE plpgsql
 AS $$
-DECLARE
-  my_amount_val INT8;
-DECLARE
-  my_amount_frac INT4;
+
 BEGIN
+  --SIMPLE INSERT ON CONFLICT DO NOTHING
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri)
+  ON CONFLICT DO NOTHING;
 
   INSERT INTO reserves
     (reserve_pub
@@ -50,6 +57,7 @@ BEGIN
     ,in_gc_date)
    ON CONFLICT DO NOTHING
    RETURNING reserve_uuid INTO ruuid;
+   PERFORM pg_notify(in_notify, NULL);
 
   IF FOUND
   THEN
@@ -57,18 +65,10 @@ BEGIN
     out_reserve_found = FALSE;
   ELSE
     -- We made no change, which means the reserve existed.
-    out_reserve_found = TRUE;
+    out_reserve_found = TRUE; /*RESERVE EXISTED BUT WE DO NOT KNOW ANY 
INFORMATIONS ABOUT TRANSACTION, RETURN*/
+    RETURN;
   END IF;
 
-  --SIMPLE INSERT ON CONFLICT DO NOTHING
-  INSERT INTO wire_targets
-    (wire_target_h_payto
-    ,payto_uri)
-    VALUES
-    (in_wire_source_h_payto
-    ,in_payto_uri)
-  ON CONFLICT DO NOTHING;
-
   INSERT INTO reserves_in
     (reserve_pub
     ,wire_reference
@@ -84,47 +84,14 @@ BEGIN
     ,in_credit_frac
     ,in_exchange_account_name
     ,in_wire_source_h_payto
-    ,in_expiration_date);
-
-  --IF THE INSERTION WAS A SUCCESS IT MEANS NO DUPLICATED TRANSACTION
+    ,in_expiration_date)
+    ON CONFLICT DO NOTHING;
   IF FOUND
   THEN
-    transaction_duplicate = FALSE;
-    IF out_reserve_found
-    THEN
-      UPDATE reserves
-        SET
-           current_balance_frac = current_balance_frac+in_credit_frac
-             - CASE
-               WHEN current_balance_frac + in_credit_frac >= 100000000
-                 THEN 100000000
-               ELSE 1
-               END
-              ,current_balance_val = current_balance_val+in_credit_val
-             + CASE
-               WHEN current_balance_frac + in_credit_frac >= 100000000
-                 THEN 1
-               ELSE 0
-               END
-               ,expiration_date=GREATEST(expiration_date,in_expiration_date)
-               ,gc_date=GREATEST(gc_date,in_expiration_date)
-             WHERE reserves.reserve_pub=in_reserve_pub;
-      out_reserve_found = TRUE;
-      RETURN;
-    ELSE
-      out_reserve_found=FALSE;
-      RETURN;
-    END IF;
-    out_reserve_found = TRUE;
+    transaction_duplicate = FALSE;  /*HAPPY PATH THERE IS NO DUPLICATE TRANS 
AND NEW RESERVE*/
+    RETURN;
   ELSE
-    transaction_duplicate = TRUE;
-    IF out_reserve_found
-    THEN
-      out_reserve_found = TRUE;
-      RETURN;
-    ELSE
-      out_reserve_found = FALSE;
-      RETURN;
-    END IF;
+    transaction_duplicate = TRUE; /*HAPPY PATH IF THERE IS A DUPLICATE TRANS 
WE JUST NEED TO ROLLBACK COMPLAIN*/
+    RETURN;
   END IF;
 END $$;
diff --git a/src/exchangedb/exchange_do_batch_reserves_in.sql 
b/src/exchangedb/exchange_do_batch_reserves_update.sql
similarity index 56%
rename from src/exchangedb/exchange_do_batch_reserves_in.sql
rename to src/exchangedb/exchange_do_batch_reserves_update.sql
index faad2ca8..f6b972c6 100644
--- a/src/exchangedb/exchange_do_batch_reserves_in.sql
+++ b/src/exchangedb/exchange_do_batch_reserves_update.sql
@@ -13,62 +13,21 @@
 -- 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/>
 --
-CREATE OR REPLACE FUNCTION batch_reserves_in(
+
+CREATE OR REPLACE PROCEDURE exchange_do_batch_reserves_update(
   IN in_reserve_pub BYTEA,
   IN in_expiration_date INT8,
-  IN in_gc_date INT8,
   IN in_wire_ref INT8,
   IN in_credit_val INT8,
   IN in_credit_frac INT4,
   IN in_exchange_account_name VARCHAR,
-  IN in_exectution_date INT8,
-  IN in_wire_source_h_payto BYTEA,    ---h_payto
-  IN in_payto_uri VARCHAR,
-  IN in_reserve_expiration INT8,
-  OUT out_reserve_found BOOLEAN,
-  OUT transaction_duplicate BOOLEAN,
-  OUT ruuid INT8)
+  IN in_reserve_found BOOLEAN,
+  IN in_wire_source_h_payto BYTEA,
+  IN in_notify text)    ---h_payto
 LANGUAGE plpgsql
 AS $$
-DECLARE
-  my_amount_val INT8;
-DECLARE
-  my_amount_frac INT4;
 BEGIN
 
-  INSERT INTO reserves
-    (reserve_pub
-    ,current_balance_val
-    ,current_balance_frac
-    ,expiration_date
-    ,gc_date)
-    VALUES
-    (in_reserve_pub
-    ,in_credit_val
-    ,in_credit_frac
-    ,in_expiration_date
-    ,in_gc_date)
-   ON CONFLICT DO NOTHING
-   RETURNING reserve_uuid INTO ruuid;
-
-  IF FOUND
-  THEN
-    -- We made a change, so the reserve did not previously exist.
-    out_reserve_found = FALSE;
-  ELSE
-    -- We made no change, which means the reserve existed.
-    out_reserve_found = TRUE;
-  END IF;
-
-  --SIMPLE INSERT ON CONFLICT DO NOTHING
-  INSERT INTO wire_targets
-    (wire_target_h_payto
-    ,payto_uri)
-    VALUES
-    (in_wire_source_h_payto
-    ,in_payto_uri)
-  ON CONFLICT DO NOTHING;
-
   INSERT INTO reserves_in
     (reserve_pub
     ,wire_reference
@@ -86,11 +45,11 @@ BEGIN
     ,in_wire_source_h_payto
     ,in_expiration_date);
 
-  --IF THE INSERTION WAS A SUCCESS IT MEANS NO DUPLICATED TRANSACTION
+--IF THE INSERTION WAS A SUCCESS IT MEANS NO DUPLICATED TRANSACTION
   IF FOUND
   THEN
-    transaction_duplicate = FALSE;
-    IF out_reserve_found
+--    transaction_duplicate = FALSE;
+    IF in_reserve_found
     THEN
       UPDATE reserves
         SET
@@ -109,22 +68,8 @@ BEGIN
                ,expiration_date=GREATEST(expiration_date,in_expiration_date)
                ,gc_date=GREATEST(gc_date,in_expiration_date)
              WHERE reserves.reserve_pub=in_reserve_pub;
-      out_reserve_found = TRUE;
-      RETURN;
-    ELSE
-      out_reserve_found=FALSE;
-      RETURN;
-    END IF;
-    out_reserve_found = TRUE;
-  ELSE
-    transaction_duplicate = TRUE;
-    IF out_reserve_found
-    THEN
-      out_reserve_found = TRUE;
-      RETURN;
-    ELSE
-      out_reserve_found = FALSE;
-      RETURN;
     END IF;
+    PERFORM pg_notify(in_notify, NULL);
   END IF;
+
 END $$;
diff --git a/src/exchangedb/pg_batch2_reserves_in_insert.c 
b/src/exchangedb/pg_batch2_reserves_in_insert.c
index 77120254..5518b2c6 100644
--- a/src/exchangedb/pg_batch2_reserves_in_insert.c
+++ b/src/exchangedb/pg_batch2_reserves_in_insert.c
@@ -52,40 +52,97 @@ compute_notify_on_reserve (const struct 
TALER_ReservePublicKeyP *reserve_pub)
 }
 
 
-enum GNUNET_DB_QueryStatus
-TEH_PG_batch2_reserves_in_insert (void *cls,
-                                  const struct
-                                  TALER_EXCHANGEDB_ReserveInInfo *reserves,
-                                  unsigned int reserves_length,
-                                  enum GNUNET_DB_QueryStatus *results)
+static enum GNUNET_DB_QueryStatus
+insert1(struct PostgresClosure *pg,
+        const struct TALER_EXCHANGEDB_ReserveInInfo *reserve,
+        struct GNUNET_TIME_Timestamp expiry,
+        struct GNUNET_TIME_Timestamp gc,
+        struct TALER_PaytoHashP h_payto,
+        const char *notify_s,
+        struct GNUNET_TIME_Timestamp reserve_expiration,
+        bool *transaction_duplicate,
+        bool *conflict,
+        uint64_t *reserve_uuid)
 {
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs1;
-  struct GNUNET_TIME_Timestamp expiry;
-  struct GNUNET_TIME_Timestamp gc;
-  struct TALER_PaytoHashP h_payto;
-  uint64_t reserve_uuid;
-  uint64_t reserve_uuid2;
-  bool conflicted;
-  bool conflicted2;
-  bool transaction_duplicate;
-  bool transaction_duplicate2;
-  bool need_update = false;
-  bool need_update2 = false;
-  struct GNUNET_TIME_Timestamp reserve_expiration
-    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
-  bool conflicts[reserves_length];
-  bool conflicts2[reserves_length];
-  char *notify_s[reserves_length];
+  enum GNUNET_DB_QueryStatus qs2;
+  PREPARE (pg,
+           "batch1_reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",transaction_duplicate"
+           ",ruuid AS reserve_uuid"
+           " FROM exchange_do_batch_reserves_in_insert"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
 
-  if (GNUNET_OK !=
-      TEH_PG_preflight (pg))
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (reserve->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+      TALER_PQ_query_param_amount (reserve->balance),
+      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s),
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  conflict),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  transaction_duplicate),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    reserve_uuid),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserve->sender_account_details,
+                      &h_payto);
+
+    /* Note: query uses 'on conflict do nothing' */
+    qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "batch1_reserve_create",
+                                                    params,
+                                                    rs);
+
+    if (qs2 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs2);
+      return qs2;
+    }
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
+
+   if ((*conflict) && (*transaction_duplicate))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+   return qs2;
+}
+
+
+
+static enum GNUNET_DB_QueryStatus
+insert2 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2],
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         char *const*notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *conflict,
+         uint64_t *reserve_uuid)
+{
+  enum GNUNET_DB_QueryStatus qs1;
   PREPARE (pg,
-           "reserve_create",
+           "batch2_reserve_create",
            "SELECT "
            "out_reserve_found AS conflicted"
            ",out_reserve_found2 AS conflicted2"
@@ -93,95 +150,60 @@ TEH_PG_batch2_reserves_in_insert (void *cls,
            ",transaction_duplicate2"
            ",ruuid AS reserve_uuid"
            ",ruuid2 AS reserve_uuid2"
-           " FROM batch2_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
-  expiry = GNUNET_TIME_absolute_to_timestamp (
-    GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
-                              pg->idle_reserve_expiration_time));
-  gc = GNUNET_TIME_absolute_to_timestamp (
-    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
-                              pg->legal_reserve_expiration_time));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Creating reserve %s with expiration in %s\n",
-              TALER_B2S (reserves->reserve_pub),
-              GNUNET_STRINGS_relative_time_to_string (
-                pg->idle_reserve_expiration_time,
-                GNUNET_NO));
-
-  {
-    if (GNUNET_OK !=
-        TEH_PG_start_read_committed (pg,
-                                     "READ_COMMITED"))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-  }
-  /* Optimistically assume this is a new reserve, create balance for the first
-     time; we do this before adding the actual transaction to "reserves_in",
-     as for a new reserve it can't be a duplicate 'add' operation, and as
-     the 'add' operation needs the reserve entry as a foreign key. */
-  for (unsigned int i = 0; i<reserves_length; i++)
-  {
-    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
-    notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
-  }
+           " FROM exchange_do_batch2_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22);");
 
-  for (unsigned int i = 0; i<(reserves_length & ~1); i += 2)
-  {
-    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0 = &reserves[i];
-    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1 = &reserves[i + 1];
     struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserve0->reserve_pub),
+      // THIS is wrong, not 22 args!
+      GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
       GNUNET_PQ_query_param_timestamp (&expiry),
       GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserve0->wire_reference),
-      TALER_PQ_query_param_amount (reserve0->balance),
-      GNUNET_PQ_query_param_string (reserve0->exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserve0->execution_time),
+      GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
+      TALER_PQ_query_param_amount (reserves[0].balance),
+      GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
       GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserve0->sender_account_details),
+      GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
       GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[i]),
-      GNUNET_PQ_query_param_auto_from_type (reserve1->reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserve1->wire_reference),
-      TALER_PQ_query_param_amount (reserve1->balance),
-      GNUNET_PQ_query_param_string (reserve1->exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserve1->execution_time),
+      GNUNET_PQ_query_param_string (notify_s[0]), // FIXME: 2 different 
notifies!
+      GNUNET_PQ_query_param_string (notify_s[1]),
+
+      GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
+      TALER_PQ_query_param_amount (reserves[1].balance),
+      GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
       GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserve1->sender_account_details),
+      GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
       GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
       GNUNET_PQ_query_param_end
     };
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_bool ("conflicted",
-                                  &conflicted),
+                                  &conflict[0]),
       GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  &conflicted2),
+                                  &conflict[1]),
       GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  &transaction_duplicate),
+                                  &transaction_duplicate[0]),
       GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
-                                  &transaction_duplicate2),
+                                  &transaction_duplicate[1]),
       GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid),
+                                    &reserve_uuid[0]),
       GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
-                                    &reserve_uuid2),
+                                    &reserve_uuid[1]),
       GNUNET_PQ_result_spec_end
     };
 
-    TALER_payto_hash (reserve0->sender_account_details,
+    TALER_payto_hash (reserves[0].sender_account_details,
                       &h_payto);
-    TALER_payto_hash (reserve1->sender_account_details,
+    TALER_payto_hash (reserves[1].sender_account_details,
                       &h_payto);
 
-    /* Note: query uses 'on conflict do nothing' */
+
     qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "reserve_create",
+                                                    "batch2_reserve_create",
                                                     params,
                                                     rs);
-
     if (qs1 < 0)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -189,40 +211,329 @@ TEH_PG_batch2_reserves_in_insert (void *cls,
                   qs1);
       return qs1;
     }
-    if (reserves_length & 1)
-    {
-      const struct TALER_EXCHANGEDB_ReserveInInfo *reserve =
-        &reserves[reserves_length - 1];
-      // single insert logic here
-    }
+
     GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
-    results[i] = (transaction_duplicate)
+         /*   results[i] = (transaction_duplicate)
       ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
-      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    conflicts[i] = conflicted;
-    conflicts2[i] = conflicted2;
-    //    fprintf(stdout, "%d", conflicts[i]);
-    // fprintf(stdout, "%d", conflicts2[i]);
-    if ((! conflicts[i] && transaction_duplicate) || (! conflicts2[i] &&
-                                                      transaction_duplicate2))
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
+
+    if (((conflict[0]) && (transaction_duplicate[0])) ||((conflict[1]) && 
(transaction_duplicate[1])))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+    return qs1;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert4 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4],
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         char *const*notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *conflict,
+         uint64_t *reserve_uuid)
+{
+  enum GNUNET_DB_QueryStatus qs3;
+  PREPARE (pg,
+           "batch4_reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",out_reserve_found3 AS conflicted3"
+           ",out_reserve_found4 AS conflicted4"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",transaction_duplicate3"
+           ",transaction_duplicate4"
+           ",ruuid AS reserve_uuid"
+           ",ruuid2 AS reserve_uuid2"
+           ",ruuid3 AS reserve_uuid3"
+           ",ruuid4 AS reserve_uuid4"
+           " FROM exchange_do_batch4_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,
 $40, $41,$42);");
+
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
+      TALER_PQ_query_param_amount (reserves[0].balance),
+      GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s[0]),
+      GNUNET_PQ_query_param_string (notify_s[1]),
+      GNUNET_PQ_query_param_string (notify_s[2]),
+      GNUNET_PQ_query_param_string (notify_s[3]),
+
+      GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
+      TALER_PQ_query_param_amount (reserves[1].balance),
+      GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
+      TALER_PQ_query_param_amount (reserves[2].balance),
+      GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
+      TALER_PQ_query_param_amount (reserves[3].balance),
+      GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserves[3].sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  &conflict[0]),
+      GNUNET_PQ_result_spec_bool ("conflicted2",
+                                  &conflict[1]),
+      GNUNET_PQ_result_spec_bool ("conflicted3",
+                                  &conflict[2]),
+      GNUNET_PQ_result_spec_bool ("conflicted4",
+                                  &conflict[3]),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  &transaction_duplicate[0]),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                  &transaction_duplicate[1]),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
+                                  &transaction_duplicate[2]),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
+                                  &transaction_duplicate[3]),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    &reserve_uuid[0]),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                    &reserve_uuid[1]),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
+                                    &reserve_uuid[2]),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
+                                    &reserve_uuid[3]),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserves[0].sender_account_details,
+                      &h_payto);
+    TALER_payto_hash (reserves[1].sender_account_details,
+                      &h_payto);
+    TALER_payto_hash (reserves[2].sender_account_details,
+                      &h_payto);
+    TALER_payto_hash (reserves[3].sender_account_details,
+                      &h_payto);
+
+    qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "batch4_reserve_create",
+                                                    params,
+                                                    rs);
+    if (qs3 < 0)
     {
-      GNUNET_break (0);
-      TEH_PG_rollback (pg);
-      return GNUNET_DB_STATUS_HARD_ERROR;
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves4 (%d)\n",
+                  qs3);
+      return qs3;
     }
-    need_update |= conflicted |= conflicted2;
+
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
+   /*   results[i] = (transaction_duplicate)
+      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
+
+    if (((conflict[0]) && (transaction_duplicate[0])) ||((conflict[1]) && 
(transaction_duplicate[1])) ||((conflict[2]) && (transaction_duplicate[2])) 
||((conflict[3]) && (transaction_duplicate[3])))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+    return qs3;
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_batch2_reserves_in_insert (void *cls,
+                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
+                                 unsigned int reserves_length,
+                                  unsigned int batch_size,
+                                 enum GNUNET_DB_QueryStatus *results)
+{
+  struct PostgresClosure *pg = cls;
+  //  enum GNUNET_DB_QueryStatus qs1;
+  enum GNUNET_DB_QueryStatus qs2;
+  enum GNUNET_DB_QueryStatus qs4;
+  enum GNUNET_DB_QueryStatus qs5;
+  struct GNUNET_TIME_Timestamp expiry;
+  struct GNUNET_TIME_Timestamp gc;
+  struct TALER_PaytoHashP h_payto;
+  uint64_t reserve_uuid[reserves_length];
+  bool transaction_duplicate[reserves_length];
+  bool need_update = false;
+  struct GNUNET_TIME_Timestamp reserve_expiration
+    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  bool conflicts[reserves_length];
+  char *notify_s[reserves_length];
+
+  if (GNUNET_OK !=
+      TEH_PG_preflight (pg))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+
+  expiry = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
+                              pg->idle_reserve_expiration_time));
+  gc = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                              pg->legal_reserve_expiration_time));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating reserve %s with expiration in %s\n",
+              TALER_B2S (&(reserves->reserve_pub)),
+              GNUNET_STRINGS_relative_time_to_string (
+                pg->idle_reserve_expiration_time,
+                GNUNET_NO));
+
+  if (GNUNET_OK !=
+      TEH_PG_start_read_committed(pg,
+                                  "READ_COMMITED"))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+
+  /* Optimistically assume this is a new reserve, create balance for the first
+     time; we do this before adding the actual transaction to "reserves_in",
+     as for a new reserve it can't be a duplicate 'add' operation, and as
+     the 'add' operation needs the reserve entry as a foreign key. */
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+
+    notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
   }
+
+  unsigned int i=0;
+
+  while (i < reserves_length)
+  {
+    unsigned int bs = GNUNET_MIN (batch_size,
+                                  reserves_length - i);
+    if (bs >= 4)
+    {
+      //   fprintf(stdout, "batch4");
+      qs4=insert4(pg,
+                  &reserves[i],
+                  expiry,
+                  gc,
+                  h_payto,
+                  &notify_s[i],
+                  reserve_expiration,
+                  &transaction_duplicate[i],
+                  &conflicts[i],
+                  &reserve_uuid[i]);
+
+     if (qs4<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to update reserves4 (%d)\n",
+                    qs4);
+        return qs4;
+      }
+      need_update |= conflicts[i];
+      need_update |= conflicts[i+1];
+      need_update |= conflicts[i+2];
+      need_update |= conflicts[i+3];
+      //     fprintf(stdout, "%ld %ld %ld %ld\n", reserve_uuid[i], 
reserve_uuid[i+1], reserve_uuid[i+2], reserve_uuid[i+3]);
+      //fprintf(stdout, "%d %d %d %d\n", transaction_duplicate[i], 
transaction_duplicate[i+1], transaction_duplicate[i+2], 
transaction_duplicate[i+3]);
+      i += 4;
+      continue;
+    }
+    switch (bs)
+    {
+    case 3:
+    case 2:
+      qs5=insert2(pg,
+                  &reserves[i],
+                  expiry,
+                  gc,
+                  h_payto,
+                  &notify_s[i],
+                  reserve_expiration,
+                  &transaction_duplicate[i],
+                  &conflicts[i],
+                  &reserve_uuid[i]);
+      if (qs5<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to update reserves (%d)\n",
+                    qs5);
+        return qs5;
+      }
+      need_update |= conflicts[i];
+      need_update |= conflicts[i+1];
+      //      fprintf(stdout, "%ld %ld\n", reserve_uuid[i], reserve_uuid[i+1]);
+      i += 2;
+      break;
+    case 1:
+      qs2 = insert1(pg,
+                    &reserves[i],
+                    expiry,
+                    gc,
+                    h_payto,
+                    notify_s[i],
+                    reserve_expiration,
+                    &transaction_duplicate[i],
+                    &conflicts[i],
+                    &reserve_uuid[i]);
+      if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2)
+      {
+        GNUNET_break (0);
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      }
+      need_update |= conflicts[i];
+      i += 1;
+      break;
+    case 0:
+      GNUNET_assert (0);
+      break;
+    }
+  } /* end while */
   // commit
   {
     enum GNUNET_DB_QueryStatus cs;
 
     cs = TEH_PG_commit (pg);
     if (cs < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to commit\n");
       return cs;
+    }
   }
 
   if (! need_update)
+  {
     goto exit;
+  }
   // begin serializable
   {
     if (GNUNET_OK !=
@@ -234,10 +545,10 @@ TEH_PG_batch2_reserves_in_insert (void *cls,
     }
   }
 
-  enum GNUNET_DB_QueryStatus qs2;
+  enum GNUNET_DB_QueryStatus qs3;
   PREPARE (pg,
            "reserves_in_add_transaction",
-           "SELECT batch_reserves_update"
+           "CALL exchange_do_batch_reserves_update"
            " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
   for (unsigned int i = 0; i<reserves_length; i++)
   {
@@ -251,21 +562,21 @@ TEH_PG_batch2_reserves_in_insert (void *cls,
         GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
         TALER_PQ_query_param_amount (reserve->balance),
         GNUNET_PQ_query_param_string (reserve->exchange_account_name),
-        GNUNET_PQ_query_param_bool (conflicted),
+        GNUNET_PQ_query_param_bool (conflicts[i]),
         GNUNET_PQ_query_param_auto_from_type (&h_payto),
         GNUNET_PQ_query_param_string (notify_s[i]),
         GNUNET_PQ_query_param_end
       };
 
-      qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+      qs3 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                                 "reserves_in_add_transaction",
                                                 params);
-      if (qs2<0)
+      if (qs3<0)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                     "Failed to update reserves (%d)\n",
-                    qs2);
-        return qs2;
+                    qs3);
+        return qs3;
       }
     }
   }
diff --git a/src/exchangedb/pg_batch2_reserves_in_insert.h 
b/src/exchangedb/pg_batch2_reserves_in_insert.h
index bb6be3f6..491e789c 100644
--- a/src/exchangedb/pg_batch2_reserves_in_insert.h
+++ b/src/exchangedb/pg_batch2_reserves_in_insert.h
@@ -28,6 +28,7 @@ enum GNUNET_DB_QueryStatus
 TEH_PG_batch2_reserves_in_insert (void *cls,
                                  const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
                                  unsigned int reserves_length,
+                                  unsigned int batch_size,
                                  enum GNUNET_DB_QueryStatus *results);
 
 #endif
diff --git a/src/exchangedb/pg_batch4_reserves_in_insert.c 
b/src/exchangedb/pg_batch4_reserves_in_insert.c
index 604a31e7..6536eb56 100644
--- a/src/exchangedb/pg_batch4_reserves_in_insert.c
+++ b/src/exchangedb/pg_batch4_reserves_in_insert.c
@@ -1,3 +1,4 @@
+
 /*
    This file is part of TALER
    Copyright (C) 2022 Taler Systems SA
@@ -14,7 +15,7 @@
    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 /**
- * @file exchangedb/pg_batch4_reserves_in_insert.c
+ * @file exchangedb/pg_batch_reserves_in_insert.c
  * @brief Implementation of the reserves_in_insert function for Postgres
  * @author Joseph Xu
  */
@@ -52,28 +53,357 @@ compute_notify_on_reserve (const struct 
TALER_ReservePublicKeyP *reserve_pub)
 }
 
 
+static enum GNUNET_DB_QueryStatus
+insert1(struct PostgresClosure *pg,
+        const struct TALER_EXCHANGEDB_ReserveInInfo *reserve,
+        struct GNUNET_TIME_Timestamp expiry,
+        struct GNUNET_TIME_Timestamp gc,
+        struct TALER_PaytoHashP h_payto,
+        const char *notify_s,
+        struct GNUNET_TIME_Timestamp reserve_expiration,
+        bool *transaction_duplicate,
+        bool *conflict,
+        uint64_t *reserve_uuid)
+{
+  enum GNUNET_DB_QueryStatus qs2;
+  PREPARE (pg,
+           "reserve_creates",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",transaction_duplicate"
+           ",ruuid AS reserve_uuid"
+           " FROM exchange_do_batch_reserves_in_insert"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
+
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+      TALER_PQ_query_param_amount (&reserve->balance),
+      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s),
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  conflict),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  transaction_duplicate),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    reserve_uuid),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserve->sender_account_details,
+                      &h_payto);
+
+    /* Note: query uses 'on conflict do nothing' */
+    qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "reserve_creates",
+                                                    params,
+                                                    rs);
+
+    if (qs2 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs2);
+      return qs2;
+    }
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
+
+   if ((*conflict) && (*transaction_duplicate))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+   return qs2;
+}
+
+
+
+static enum GNUNET_DB_QueryStatus
+insert2 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0,
+         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1,
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         const char *notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *transaction_duplicate2,
+         bool *conflict,
+         bool *conflict2,
+         uint64_t *reserve_uuid,
+         uint64_t *reserve_uuid2)
+{
+  PREPARE (pg,
+           "reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",ruuid AS reserve_uuid"
+           ",ruuid2 AS reserve_uuid2"
+           " FROM exchange_do_batch2_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
+
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&reserve0->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve0->wire_reference),
+      TALER_PQ_query_param_amount (&reserve0->balance),
+      GNUNET_PQ_query_param_string (reserve0->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve0->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve0->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s),
+      GNUNET_PQ_query_param_auto_from_type (&reserve1->reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserve1->wire_reference),
+      TALER_PQ_query_param_amount (&reserve1->balance),
+      GNUNET_PQ_query_param_string (reserve1->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve1->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve1->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  conflict),
+      GNUNET_PQ_result_spec_bool ("conflicted2",
+                                  conflict2),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  transaction_duplicate),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                  transaction_duplicate2),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    reserve_uuid),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                    reserve_uuid2),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserve0->sender_account_details,
+                      &h_payto);
+    TALER_payto_hash (reserve1->sender_account_details,
+                      &h_payto);
+
+
+    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "reserve_create",
+                                                    params,
+                                                    rs);
+    if (qs1 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs1);
+      return qs1;
+    }
+    /*
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
+   results[i] = (transaction_duplicate)
+      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
+
+    if ((*conflict) && (*transaction_duplicate) ||((*conflict2) && 
(*transaction_duplicate2)))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert4 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0,
+         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1,
+         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve2,
+         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve3,
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         const char *notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *transaction_duplicate2,
+         bool *transaction_duplicate3,
+         bool *transaction_duplicate4,
+         bool *conflict,
+         bool *conflict2,
+         bool *conflict3,
+         bool *conflict4,
+         uint64_t *reserve_uuid,
+         uint64_t *reserve_uuid2,
+         uint64_t *reserve_uuid3,
+         uint64_t *reserve_uuid4)
+{
+  PREPARE (pg,
+           "reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",out_reserve_found3 AS conflicted3"
+           ",out_reserve_found4 AS conflicted4"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",transaction_duplicate3"
+           ",transaction_duplicate4"
+           ",ruuid AS reserve_uuid"
+           ",ruuid2 AS reserve_uuid2"
+           ",ruuid3 AS reserve_uuid3"
+           ",ruuid4 AS reserve_uuid4"
+           " FROM exchange_do_batch4_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39);");
+
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&reserve0->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve0->wire_reference),
+      TALER_PQ_query_param_amount (&reserve0->balance),
+      GNUNET_PQ_query_param_string (reserve0->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve0->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve0->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s),
+
+      GNUNET_PQ_query_param_auto_from_type (&reserve1->reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserve1->wire_reference),
+      TALER_PQ_query_param_amount (&reserve1->balance),
+      GNUNET_PQ_query_param_string (reserve1->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve1->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve1->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_auto_from_type (&reserve2->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve2->wire_reference),
+      TALER_PQ_query_param_amount (&reserve2->balance),
+      GNUNET_PQ_query_param_string (reserve2->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve2->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve2->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_auto_from_type (&reserve3->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve3->wire_reference),
+      TALER_PQ_query_param_amount (&reserve3->balance),
+      GNUNET_PQ_query_param_string (reserve3->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve3->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve3->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration)
+
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  conflict),
+      GNUNET_PQ_result_spec_bool ("conflicted2",
+                                  conflict2),
+      GNUNET_PQ_result_spec_bool ("conflicted3",
+                                  conflict3),
+      GNUNET_PQ_result_spec_bool ("conflicted4",
+                                  conflict4),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  transaction_duplicate),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                  transaction_duplicate2),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
+                                  transaction_duplicate3),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
+                                  transaction_duplicate4),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    reserve_uuid),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                    reserve_uuid2),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
+                                    reserve_uuid3),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
+                                    reserve_uuid4),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserve0->sender_account_details,
+                      &h_payto);
+    TALER_payto_hash (reserve1->sender_account_details,
+                      &h_payto);
+
+
+    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "reserve_create",
+                                                    params,
+                                                    rs);
+    if (qs1 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs1);
+      return qs1;
+    }
+    /*
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
+   results[i] = (transaction_duplicate)
+      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
+
+    if ((*conflict) && (*transaction_duplicate) ||((*conflict2) && 
(*transaction_duplicate2)))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+
+}
+
+
+
 enum GNUNET_DB_QueryStatus
-TEH_PG_batch4_reserves_in_insert (void *cls,
+TEH_PG_batch2_reserves_in_insert (void *cls,
                                  const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
                                  unsigned int reserves_length,
                                  enum GNUNET_DB_QueryStatus *results)
 {
   struct PostgresClosure *pg = cls;
   enum GNUNET_DB_QueryStatus qs1;
+  enum GNUNET_DB_QueryStatus qs2;
+  enum GNUNET_DB_QueryStatus qs4;
+  enum GNUNET_DB_QueryStatus qs5;
   struct GNUNET_TIME_Timestamp expiry;
   struct GNUNET_TIME_Timestamp gc;
   struct TALER_PaytoHashP h_payto;
-  uint64_t reserve_uuid;
+  uint64_t reserve_uuid[reserves_length];
   bool conflicted;
   bool conflicted2;
-  bool transaction_duplicate;
-  bool transaction_duplicate2;
+  bool transaction_duplicate[reserves_length];
   bool need_update = false;
   bool need_update2 = false;
   struct GNUNET_TIME_Timestamp reserve_expiration
     = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
   bool conflicts[reserves_length];
-  bool conflicts2[reserves_length];
   char *notify_s[reserves_length];
 
   if (GNUNET_OK !=
@@ -82,16 +412,7 @@ TEH_PG_batch4_reserves_in_insert (void *cls,
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  PREPARE (pg,
-           "reserve_create",
-           "SELECT "
-           "out_reserve_found AS conflicted"
-           ",out_reserve_found2 AS conflicted2"
-           ",transaction_duplicate"
-           ",transaction_duplicate2"
-           ",ruuid AS reserve_uuid"
-           " FROM batch2_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
+
   expiry = GNUNET_TIME_absolute_to_timestamp (
     GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
                               pg->idle_reserve_expiration_time));
@@ -124,75 +445,83 @@ TEH_PG_batch4_reserves_in_insert (void *cls,
     notify_s[i] = compute_notify_on_reserve (&reserve->reserve_pub);
   }
 
-  for (unsigned int i=0;i<reserves_length;i++)
-  {
-    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
-      TALER_PQ_query_param_amount (&reserve->balance),
-      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserve->sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[i]),
-      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
-      TALER_PQ_query_param_amount (&reserve->balance),
-      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserve->sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_end
-    };
+  unsigned int i=0;
 
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_bool ("conflicted",
-                                  &conflicted),
-            GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  &conflicted2),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  &transaction_duplicate),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid),
-      GNUNET_PQ_result_spec_end
-    };
-
-    TALER_payto_hash (reserve->sender_account_details,
-                      &h_payto);
-
-    /* Note: query uses 'on conflict do nothing' */
-    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "reserve_create",
-                                                    params,
-                                                    rs);
+  while (i < reserves_length)
+  {
+    if (reserves_length - i >= 4)
+    {
+      qs4=insert4(pg,
+              &reserves[i],
+              &reserves[i+2],
+              &reserves[i+3],
+              &reserves[i+4],
+              expiry,
+              gc,
+              h_payto,
+              &notify_s[i],
+              reserve_expiration,
+              &transaction_duplicate[i],
+              &transaction_duplicate[i+1],
+              &transaction_duplicate[i+2],
+              &transaction_duplicate[i+3],
+              &conflicts[i],
+              &conflicts[i+1],
+              &conflicts[i+2],
+              &conflicts[i+3],
+              &reserve_uuid[i],
+              &reserve_uuid[i+1],
+              &reserve_uuid[i+2],
+              &reserve_uuid[i+3]);
 
-    if (qs1 < 0)
+      need_update |= conflicts[i];
+      need_update |= conflicts[i+1];
+      need_update |= conflicts[i+2];
+      need_update |= conflicts[i+3];
+      i += 4;
+      continue;
+    }
+    switch (reserves_length - i)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to create reserves (%d)\n",
-                  qs1);
-      return qs1;
+    case 3:
+    case 2:
+      qs5=insert2(pg,
+              &reserves[i],
+              &reserves[i+1],
+              expiry,
+              gc,
+              h_payto,
+              notify_s[i],
+              reserve_expiration,
+              &transaction_duplicate[i],
+              &transaction_duplicate[i+1],
+              &conflicts[i],
+              &conflicts[i+1],
+              &reserve_uuid[i],
+              &reserve_uuid[i+1]);
+      need_update |= conflicts[i];
+      need_update |= conflicts[i+1];
+      i += 2;
+      break;
+    case 1:
+      qs2 = insert1(pg,
+                    &reserves[i],
+                    expiry,
+                    gc,
+                    h_payto,
+                    notify_s[i],
+                    reserve_expiration,
+                    &transaction_duplicate[i],
+                    &conflicts[i],
+                    &reserve_uuid[i]);
+      need_update |= conflicts[i];
+      i += 1;
+      break;
+    case 0:
+      GNUNET_assert (0);
+      break;
     }
-   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
-   results[i] = (transaction_duplicate)
-      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
-      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-   conflicts[i] = conflicted;
-   conflicts2[i] = conflicted2;
-   //  fprintf(stdout, "%d", conflicts[i]);
-   if (!conflicts[i] && !conflicts2[i]&& transaction_duplicate)
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg);
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-   need_update |= conflicted |= conflicted2;
-  }
+  } /* end while */
   // commit
   {
     enum GNUNET_DB_QueryStatus cs;
@@ -202,7 +531,7 @@ TEH_PG_batch4_reserves_in_insert (void *cls,
       return cs;
   }
 
-  if (!need_update)
+  if (!need_update )
     goto exit;
   // begin serializable
   {
@@ -215,10 +544,10 @@ TEH_PG_batch4_reserves_in_insert (void *cls,
     }
   }
 
-  enum GNUNET_DB_QueryStatus qs2;
+  enum GNUNET_DB_QueryStatus qs3;
   PREPARE (pg,
            "reserves_in_add_transaction",
-           "SELECT batch_reserves_update"
+           "CALL exchange_do_batch_reserves_update"
            " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
   for (unsigned int i=0;i<reserves_length;i++)
   {
@@ -238,15 +567,15 @@ TEH_PG_batch4_reserves_in_insert (void *cls,
         GNUNET_PQ_query_param_end
       };
 
-      qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+      qs3 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                                 "reserves_in_add_transaction",
                                                 params);
-      if (qs2<0)
+      if (qs3<0)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                     "Failed to update reserves (%d)\n",
-                    qs2);
-        return qs2;
+                    qs3);
+        return qs3;
       }
     }
   }
diff --git a/src/exchangedb/pg_batch4_reserves_in_insert.h 
b/src/exchangedb/pg_batch4_reserves_in_insert.h
deleted file mode 100644
index 3b3a629f..00000000
--- a/src/exchangedb/pg_batch4_reserves_in_insert.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-   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 exchangedb/pg_batch4_reserves_in_insert.h
- * @brief implementation of the batch4_reserves_in_insert function for Postgres
- * @author XU Joseph
- */
-#ifndef PG_BATCH4_RESERVES_IN_INSERT_H
-#define PG_BATCH4_RESERVES_IN_INSERT_H
-
-#include "taler_util.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-
-enum GNUNET_DB_QueryStatus
-TEH_PG_batch4_reserves_in_insert (void *cls,
-                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
-                                 unsigned int reserves_length,
-                                  enum GNUNET_DB_QueryStatus *results);
-
-#endif
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.c 
b/src/exchangedb/pg_batch_reserves_in_insert.c
index 9f00fa1d..5b6ab83a 100644
--- a/src/exchangedb/pg_batch_reserves_in_insert.c
+++ b/src/exchangedb/pg_batch_reserves_in_insert.c
@@ -86,7 +86,7 @@ TEH_PG_batch_reserves_in_insert (
            "out_reserve_found AS conflicted"
            ",transaction_duplicate"
            ",ruuid AS reserve_uuid"
-           " FROM batch_reserves_insert"
+           " FROM exchange_do_batch_reserves_in_insert"
            " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
   expiry = GNUNET_TIME_absolute_to_timestamp (
     GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
@@ -168,15 +168,15 @@ TEH_PG_batch_reserves_in_insert (
     results[i] = (transaction_duplicate)
       ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
       : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    conflicts[i] = conflicted;
-    //  fprintf(stdout, "%d", conflicts[i]);
-    if (! conflicts[i] && transaction_duplicate)
-    {
-      GNUNET_break (0);
-      TEH_PG_rollback (pg);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    need_update |= conflicted;
+   conflicts[i] = conflicted;
+   //   fprintf(stdout, "%d", conflicts[i]);
+   if (!conflicts[i] && transaction_duplicate)
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+   need_update |= conflicted;
   }
   // commit
   {
@@ -203,7 +203,7 @@ TEH_PG_batch_reserves_in_insert (
   enum GNUNET_DB_QueryStatus qs2;
   PREPARE (pg,
            "reserves_in_add_transaction",
-           "SELECT batch_reserves_update"
+           "SELECT exchange_do_batch_reserves_update"
            " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
   for (unsigned int i = 0; i<reserves_length; i++)
   {
diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in
index b412b66d..8ddc0ee2 100644
--- a/src/exchangedb/procedures.sql.in
+++ b/src/exchangedb/procedures.sql.in
@@ -35,7 +35,8 @@ SET search_path TO exchange;
 #include "exchange_do_reserve_open_deposit.sql"
 #include "exchange_do_reserve_open.sql"
 #include "exchange_do_insert_or_update_policy_details.sql"
-#include "exchange_do_batch_reserves_in.sql"
-
-
+#include "exchange_do_batch_reserves_in_insert.sql"
+#include "exchange_do_batch_reserves_update.sql"
+#include "exchange_do_batch2_reserves_in_insert.sql"
+#include "exchange_do_batch4_reserves_in_insert.sql"
 COMMIT;
diff --git a/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c 
b/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
index 460778b8..921bffa8 100644
--- a/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
+++ b/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
@@ -83,15 +83,9 @@ run (void *cls)
   }
   (void) plugin->drop_tables (plugin->cls);
   if (GNUNET_OK !=
-      plugin->create_tables (plugin->cls))
-  {
-    GNUNET_break (0);
-    result = 77;
-    goto cleanup;
-  }
-  if (GNUNET_OK !=
-      plugin->setup_partitions (plugin->cls,
-                                num_partitions))
+      plugin->create_tables (plugin->cls,
+                             true,
+                             num_partitions))
   {
     GNUNET_break (0);
     result = 77;
@@ -100,12 +94,13 @@ run (void *cls)
 
   for (unsigned int i = 0; i< 8; i++)
   {
-    static unsigned int batches[] = {1, 1,0, 2, 4, 16, 64, 256};
+    static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 64, 256};
     const char *sndr = "payto://x-taler-bank/localhost:8080/1";
     struct TALER_Amount value;
     unsigned int batch_size = batches[i];
     struct GNUNET_TIME_Absolute now;
     struct GNUNET_TIME_Timestamp ts;
+    unsigned int iterations = 1024 / batch_size;
     struct GNUNET_TIME_Relative duration;
     struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
     enum GNUNET_DB_QueryStatus results[batch_size];
@@ -114,9 +109,9 @@ run (void *cls)
                                            &value));
     now = GNUNET_TIME_absolute_get ();
     ts = GNUNET_TIME_timestamp_get ();
-    for (unsigned int r=0;r<10;r++)
-    {
 
+    for (unsigned int r = 0; r<iterations; r++)
+    {
       for (unsigned int k = 0; k<batch_size; k++)
       {
         RND_BLK (&reserves[k].reserve_pub);
diff --git a/src/exchangedb/test_exchangedb_by_j.c 
b/src/exchangedb/test_exchangedb_by_j.c
index 834373b5..8e0b413b 100644
--- a/src/exchangedb/test_exchangedb_by_j.c
+++ b/src/exchangedb/test_exchangedb_by_j.c
@@ -22,6 +22,8 @@
 #include "taler_exchangedb_lib.h"
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
+#include "math.h"
+#define ROUNDS 100
 
 /**
  * Global result from the testcase.
@@ -71,6 +73,9 @@ static struct TALER_EXCHANGEDB_Plugin *plugin;
 static void
 run (void *cls)
 {
+  static const unsigned int batches[] = {1, 2, 3, 4, 16 };
+  struct GNUNET_TIME_Relative times[sizeof (batches)/sizeof(*batches)];
+  unsigned long long sqrs[sizeof (batches)/sizeof(*batches)];
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   const uint32_t num_partitions = 10;
 
@@ -81,7 +86,8 @@ run (void *cls)
     result = 77;
     return;
   }
-  (void) plugin->drop_tables (plugin->cls);
+
+
   if (GNUNET_OK !=
       plugin->create_tables (plugin->cls,
                              true,
@@ -92,62 +98,78 @@ run (void *cls)
     goto cleanup;
   }
 
-  for (unsigned int i = 0; i< 7; i++)
-
-  if (GNUNET_OK !=
-      plugin->setup_partitions (plugin->cls,
-                                num_partitions))
-  {
-    GNUNET_break (0);
-    result = 77;
-    goto cleanup;
-  }
-
-  for (unsigned int i = 0; i< 8; i++)
-
-  {
-    static unsigned int batches[] = {1, 1,0, 2, 4, 16, 64, 256};
-    const char *sndr = "payto://x-taler-bank/localhost:8080/1";
-    struct TALER_Amount value;
-    unsigned int batch_size = batches[i];
-    struct GNUNET_TIME_Absolute now;
-    struct GNUNET_TIME_Timestamp ts;
-    struct GNUNET_TIME_Relative duration;
-    struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
-    /*   struct TALER_EXCHANGEDB_ReserveInInfo reserves2[batch_size];*/
-    enum GNUNET_DB_QueryStatus results[batch_size];
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_string_to_amount (CURRENCY ":1.000010",
-                                           &value));
-    now = GNUNET_TIME_absolute_get ();
-    ts = GNUNET_TIME_timestamp_get ();
-    for (unsigned int r = 0; r<10; r++)
+  memset (times, 0, sizeof (times));
+  memset (sqrs, 0, sizeof (sqrs));
+  for (unsigned int r = 0; r < ROUNDS; r++)
     {
-
-       for (unsigned int k = 0; k<batch_size; k++)
+    for (unsigned int i = 0; i< 5; i++)
       {
-        RND_BLK (&reserves[k].reserve_pub);
-        reserves[k].balance = value;
-        reserves[k].execution_time = ts;
-        reserves[k].sender_account_details = sndr;
-        reserves[k].exchange_account_name = "name";
-        reserves[k].wire_reference = k;
+        const char *sndr = "payto://x-taler-bank/localhost:8080/1";
+        struct TALER_Amount value;
+        unsigned int batch_size = batches[i];
+        unsigned int iterations = 1024*10;
+        struct TALER_ReservePublicKeyP reserve_pubs[iterations];
+        struct GNUNET_TIME_Absolute now;
+        struct GNUNET_TIME_Timestamp ts;
+        struct GNUNET_TIME_Relative duration;
+        struct TALER_EXCHANGEDB_ReserveInInfo reserves[iterations];
+        enum GNUNET_DB_QueryStatus results[iterations];
+        unsigned long long duration_sq;
+
+        GNUNET_assert (GNUNET_OK ==
+                       TALER_string_to_amount (CURRENCY ":1.000010",
+                                               &value));
+        now = GNUNET_TIME_absolute_get ();
+        ts = GNUNET_TIME_timestamp_get ();
+        for (unsigned int r = 0; r<iterations; r++)
+          {
+            RND_BLK (&reserve_pubs[r]);
+            reserves[r].reserve_pub = &reserve_pubs[r];
+            reserves[r].balance = &value;
+            reserves[r].execution_time = ts;
+            reserves[r].sender_account_details = sndr;
+            reserves[r].exchange_account_name = "name";
+            reserves[r].wire_reference = r;
+          }
+        FAILIF (iterations !=
+                plugin->batch2_reserves_in_insert (plugin->cls,
+                                                   reserves,
+                                                   iterations,
+                                                   batch_size,
+                                                   results));
+        duration = GNUNET_TIME_absolute_get_duration (now);
+        times[i] = GNUNET_TIME_relative_add (times[i],
+                                             duration);
+        duration_sq = duration.rel_value_us * duration.rel_value_us;
+        GNUNET_assert (duration_sq / duration.rel_value_us == 
duration.rel_value_us);
+        GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]);
+        sqrs[i] += duration_sq;
+        fprintf (stdout,
+                 "for a batchsize equal to %d it took %s\n",
+                 batch_size,
+                 GNUNET_STRINGS_relative_time_to_string (duration,
+                                                         GNUNET_NO) );
+
+        system ("./test.sh"); //DELETE AFTER TIMER
       }
-      FAILIF (batch_size !=
-            plugin->batch_reserves_in_insert (plugin->cls,
-                                              reserves,
-                                              batch_size,
-                                              results));
+    }
+    for (unsigned int i = 0; i< 5; i++)
+    {
+      struct GNUNET_TIME_Relative avg;
+      double avg_dbl;
+      double variance;
+
+      avg = GNUNET_TIME_relative_divide (times[i],
+                                         ROUNDS);
+      avg_dbl = avg.rel_value_us;
+      variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS);
+      fprintf(stdout,
+              "Batch[%2u]: %8llu ± %6.0f\n",
+              batches[i],
+              (unsigned long long) avg.rel_value_us,
+              sqrt (variance / (ROUNDS-1)));
     }
 
-    duration = GNUNET_TIME_absolute_get_duration (now);
-    fprintf (stdout,
-             "for a batchsize equal to %d it took %s\n",
-             batch_size,
-             GNUNET_STRINGS_relative_time_to_string (duration,
-                                                     GNUNET_NO) );
-
-  }
   result = 0;
 drop:
   GNUNET_break (GNUNET_OK ==
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 00f21da1..d680cd73 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -3469,6 +3469,7 @@ struct TALER_EXCHANGEDB_Plugin
     void *cls,
     const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
     unsigned int reserves_length,
+    unsigned int batch_size,
     enum GNUNET_DB_QueryStatus *results);
 
 

-- 
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]