summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-02-05 19:11:47 +0100
committerChristian Grothoff <christian@grothoff.org>2023-02-05 19:11:47 +0100
commitab03ba16e9bc63eb5384e7b6b590fc029bf61152 (patch)
tree7a77a729c132f2fdb9fce0142b0bf3796e568ea1 /src
parente66087987f6c3565594dee3420f53165b85ba4fe (diff)
downloadexchange-ab03ba16e9bc63eb5384e7b6b590fc029bf61152.tar.gz
exchange-ab03ba16e9bc63eb5384e7b6b590fc029bf61152.tar.bz2
exchange-ab03ba16e9bc63eb5384e7b6b590fc029bf61152.zip
exchangedb: use partial index instead of materialized tables deposits_by_ready and deposits_by_matching; remove now broken code; rename benchmarks to use perf_-prefix and correspond to function they benchmark
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-wirewatch.c422
-rw-r--r--src/exchangedb/.gitignore16
-rw-r--r--src/exchangedb/0002-deposits.sql46
-rw-r--r--src/exchangedb/Makefile.am71
-rw-r--r--src/exchangedb/perf_deposits_get_ready.c (renamed from src/exchangedb/test_exchangedb_populate_ready_deposit.c)382
-rw-r--r--src/exchangedb/perf_get_link_data.c (renamed from src/exchangedb/test_exchangedb_populate_link_data.c)234
-rw-r--r--src/exchangedb/perf_reserves_in_insert.c (renamed from src/exchangedb/perf_exchangedb_reserves_in_insert.c)124
-rw-r--r--src/exchangedb/perf_select_refunds_by_coin.c (renamed from src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c)302
-rw-r--r--src/exchangedb/pg_aggregate.c22
-rw-r--r--src/exchangedb/pg_batch2_reserves_in_insert.c914
-rw-r--r--src/exchangedb/pg_batch2_reserves_in_insert.h34
-rw-r--r--src/exchangedb/pg_batch4_reserves_in_insert.c595
-rw-r--r--src/exchangedb/pg_batch_reserves_in_insert.c252
-rw-r--r--src/exchangedb/pg_batch_reserves_in_insert.h35
-rw-r--r--src/exchangedb/pg_get_link_data.c26
-rw-r--r--src/exchangedb/pg_get_ready_deposit.c180
-rw-r--r--src/exchangedb/pg_reserves_in_insert.c1000
-rw-r--r--src/exchangedb/pg_reserves_in_insert.h30
-rw-r--r--src/exchangedb/pg_select_refunds_by_coin.c17
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c6
-rw-r--r--src/exchangedb/test_exchangedb_batch_reserves_in_insert.c196
-rw-r--r--src/include/taler_exchangedb_plugin.h49
22 files changed, 1480 insertions, 3473 deletions
diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c
index a1a3a4ff2..a7a6b004f 100644
--- a/src/exchange/taler-exchange-wirewatch.c
+++ b/src/exchange/taler-exchange-wirewatch.c
@@ -495,397 +495,14 @@ transaction_completed (void)
* We got incoming transaction details from the bank. Add them
* to the database.
*
- * @param details array of transaction details
- * @param details_length length of the @a details array
- */
-static void
-process_reply (const struct TALER_BANK_CreditDetails *details,
- unsigned int details_length)
-{
- enum GNUNET_DB_QueryStatus qs;
- bool shard_done;
- uint64_t lroff = latest_row_off;
-
- if (0 == details_length)
- {
- /* Server should have used 204, not 200! */
- GNUNET_break_op (0);
- transaction_completed ();
- return;
- }
- hh_returned_data = true;
- /* check serial IDs for range constraints */
- for (unsigned int i = 0; i<details_length; i++)
- {
- const struct TALER_BANK_CreditDetails *cd = &details[i];
-
- if (cd->serial_id < lroff)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Serial ID %llu not monotonic (got %llu before). Failing!\n",
- (unsigned long long) cd->serial_id,
- (unsigned long long) lroff);
- db_plugin->rollback (db_plugin->cls);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- if (cd->serial_id > shard_end)
- {
- /* we are *past* the current shard (likely because the serial_id of the
- shard_end happens to not exist in the DB). So commit and stop this
- iteration! */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serial ID %llu past shard end at %llu, ending iteration early!\n",
- (unsigned long long) cd->serial_id,
- (unsigned long long) shard_end);
- details_length = i;
- progress = true;
- lroff = cd->serial_id - 1;
- break;
- }
- lroff = cd->serial_id;
- }
- if (GNUNET_OK !=
- db_plugin->start_read_committed (db_plugin->cls,
- "wirewatch check for incoming wire transfers"))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to start database transaction!\n");
- global_ret = EXIT_FAILURE;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- started_transaction = true;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Importing %u transactions\n",
- details_length);
- for (unsigned int i = 0; i<details_length; i++)
- {
- const struct TALER_BANK_CreditDetails *cd = &details[i];
-
- /* FIXME #7276: Consider using Postgres multi-valued insert here,
- for up to 15x speed-up according to
- https://dba.stackexchange.com/questions/224989/multi-row-insert-vs-transactional-single-row-inserts#225006
- (Note: this may require changing both the
- plugin API as well as modifying how this function is called.) */
- qs = db_plugin->reserves_in_insert (db_plugin->cls,
- &cd->reserve_pub,
- &cd->amount,
- cd->execution_date,
- cd->debit_account_uri,
- ai->section_name,
- cd->serial_id);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got DB soft error for reserves_in_insert. Rolling back.\n");
- handle_soft_error ();
- return;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* Either wirewatch was freshly started after the system was
- shutdown and we're going over an incomplete shard again
- after being restarted, or the shard lock period was too
- short (number of workers set incorrectly?) and a 2nd
- wirewatcher has been stealing our work while we are still
- at it. */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Attempted to import transaction %llu (%s) twice. "
- "This should happen rarely (if not, ask for support).\n",
- (unsigned long long) cd->serial_id,
- job_name);
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Imported transaction %llu.",
- (unsigned long long) cd->serial_id);
- /* normal case */
- progress = true;
- break;
- }
- }
- latest_row_off = lroff;
- shard_done = (shard_end <= latest_row_off);
- if (shard_done)
- {
- /* shard is complete, mark this as well */
- qs = db_plugin->complete_shard (db_plugin->cls,
- job_name,
- shard_start,
- shard_end);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got DB soft error for complete_shard. Rolling back.\n");
- handle_soft_error ();
- return;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0);
- /* Not expected, but let's just continue */
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* normal case */
- progress = true;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Completed shard %s (%llu,%llu] after %s\n",
- job_name,
- (unsigned long long) shard_start,
- (unsigned long long) shard_end,
- GNUNET_STRINGS_relative_time_to_string (
- GNUNET_TIME_absolute_get_duration (shard_start_time),
- true));
- break;
- }
- }
- if (! progress)
- {
- db_plugin->rollback (db_plugin->cls);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Committing %s progress (%llu,%llu] at %llu\n (%s)",
- job_name,
- (unsigned long long) shard_start,
- (unsigned long long) shard_end,
- (unsigned long long) latest_row_off,
- shard_done
- ? "shard done"
- : "shard incomplete");
- qs = db_plugin->commit (db_plugin->cls);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- /* reduce transaction size to reduce rollback probability */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got DB soft error on commit. Reducing transaction size.\n");
- handle_soft_error ();
- return;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- started_transaction = false;
- /* normal case */
- break;
- }
- }
- if (shard_done)
- {
- shard_delay = GNUNET_TIME_absolute_get_duration (shard_start_time);
- shard_open = false;
- transaction_completed ();
- return;
- }
- GNUNET_assert (NULL == task);
- task = GNUNET_SCHEDULER_add_now (&continue_with_shard,
- NULL);
-}
-
-
-/**
- * We got incoming transaction details from the bank. Add them
- * to the database.
- *
- * @param details array of transaction details
- * @param details_length length of the @a details array
- */
-static void
-process_reply_batched (const struct TALER_BANK_CreditDetails *details,
- unsigned int details_length)
-{
- enum GNUNET_DB_QueryStatus qs;
- bool shard_done;
- uint64_t lroff = latest_row_off;
-
- if (0 == details_length)
- {
- /* Server should have used 204, not 200! */
- GNUNET_break_op (0);
- transaction_completed ();
- return;
- }
- /* check serial IDs for range constraints */
- for (unsigned int i = 0; i<details_length; i++)
- {
- const struct TALER_BANK_CreditDetails *cd = &details[i];
-
- if (cd->serial_id < lroff)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Serial ID %llu not monotonic (got %llu before). Failing!\n",
- (unsigned long long) cd->serial_id,
- (unsigned long long) lroff);
- db_plugin->rollback (db_plugin->cls);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- if (cd->serial_id > shard_end)
- {
- /* we are *past* the current shard (likely because the serial_id of the
- shard_end happens to not exist in the DB). So commit and stop this
- iteration! */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serial ID %llu past shard end at %llu, ending iteration early!\n",
- (unsigned long long) cd->serial_id,
- (unsigned long long) shard_end);
- details_length = i;
- progress = true;
- lroff = cd->serial_id - 1;
- break;
- }
- lroff = cd->serial_id;
- }
- if (0 != details_length)
- {
- enum GNUNET_DB_QueryStatus qss[details_length];
- struct TALER_EXCHANGEDB_ReserveInInfo reserves[details_length];
-
- hh_returned_data = true;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Importing %u transactions\n",
- details_length);
- for (unsigned int i = 0; i<details_length; i++)
- {
- const struct TALER_BANK_CreditDetails *cd = &details[i];
- struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[i];
-
- res->reserve_pub = &cd->reserve_pub;
- res->balance = &cd->amount;
- res->execution_time = cd->execution_date;
- res->sender_account_details = cd->debit_account_uri;
- res->exchange_account_name = ai->section_name;
- res->wire_reference = cd->serial_id;
- }
- qs = db_plugin->batch_reserves_in_insert (db_plugin->cls,
- reserves,
- details_length,
- qss);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got DB soft error for batch_reserves_in_insert. Rolling back.\n");
- handle_soft_error ();
- return;
- default:
- break;
- }
- for (unsigned int i = 0; i<details_length; i++)
- {
- const struct TALER_BANK_CreditDetails *cd = &details[i];
-
- switch (qss[i])
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got DB soft error for batch_reserves_in_insert(%u). Rolling back.\n",
- i);
- handle_soft_error ();
- return;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* Either wirewatch was freshly started after the system was
- shutdown and we're going over an incomplete shard again
- after being restarted, or the shard lock period was too
- short (number of workers set incorrectly?) and a 2nd
- wirewatcher has been stealing our work while we are still
- at it. */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Attempted to import transaction %llu (%s) twice. "
- "This should happen rarely (if not, ask for support).\n",
- (unsigned long long) cd->serial_id,
- job_name);
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Imported transaction %llu.",
- (unsigned long long) cd->serial_id);
- /* normal case */
- progress = true;
- break;
- }
- }
- }
-
- latest_row_off = lroff;
- shard_done = (shard_end <= latest_row_off);
- if (shard_done)
- {
- /* shard is complete, mark this as well */
- qs = db_plugin->complete_shard (db_plugin->cls,
- job_name,
- shard_start,
- shard_end);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got DB soft error for complete_shard. Rolling back.\n");
- handle_soft_error ();
- return;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0);
- /* Not expected, but let's just continue */
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* normal case */
- progress = true;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Completed shard %s (%llu,%llu] after %s\n",
- job_name,
- (unsigned long long) shard_start,
- (unsigned long long) shard_end,
- GNUNET_STRINGS_relative_time_to_string (
- GNUNET_TIME_absolute_get_duration (shard_start_time),
- true));
- break;
- }
- shard_delay = GNUNET_TIME_absolute_get_duration (shard_start_time);
- shard_open = false;
- transaction_completed ();
- return;
- }
- GNUNET_assert (NULL == task);
- task = GNUNET_SCHEDULER_add_now (&continue_with_shard,
- NULL);
-}
-
-
-/**
- * We got incoming transaction details from the bank. Add them
- * to the database.
- *
* @param batch_size desired batch size
* @param details array of transaction details
* @param details_length length of the @a details array
*/
static void
-process_reply_batched2 (unsigned int batch_size,
- const struct TALER_BANK_CreditDetails *details,
- unsigned int details_length)
+process_reply (unsigned int batch_size,
+ const struct TALER_BANK_CreditDetails *details,
+ unsigned int details_length)
{
enum GNUNET_DB_QueryStatus qs;
bool shard_done;
@@ -950,11 +567,11 @@ process_reply_batched2 (unsigned int batch_size,
res->exchange_account_name = ai->section_name;
res->wire_reference = cd->serial_id;
}
- qs = db_plugin->batch2_reserves_in_insert (db_plugin->cls,
- reserves,
- details_length,
- batch_size,
- qss);
+ qs = db_plugin->reserves_in_insert (db_plugin->cls,
+ reserves,
+ details_length,
+ batch_size,
+ qss);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
@@ -1074,7 +691,7 @@ history_cb (void *cls,
(void) cls;
if (-2 == batch_mode)
{
- const char *mode = getenv ("TALER_USE_BATCH");
+ const char *mode = getenv ("TALER_WIREWATCH_BATCH_SIZE");
char dummy;
if ( (NULL == mode) ||
@@ -1087,7 +704,7 @@ history_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Bad batch mode `%s' specified\n",
mode);
- batch_mode = -1;
+ batch_mode = 8; /* maximum supported is currently 8 */
}
}
GNUNET_assert (NULL == task);
@@ -1098,22 +715,9 @@ history_cb (void *cls,
switch (reply->http_status)
{
case MHD_HTTP_OK:
- switch (batch_mode)
- {
- case -1:
- process_reply (reply->details.success.details,
- reply->details.success.details_length);
- break;
- case 0:
- process_reply_batched (reply->details.success.details,
- reply->details.success.details_length);
- break;
- default:
- process_reply_batched2 ((unsigned int) batch_mode,
- reply->details.success.details,
- reply->details.success.details_length);
- break;
- }
+ process_reply (batch_mode,
+ reply->details.success.details,
+ reply->details.success.details_length);
return;
case MHD_HTTP_NO_CONTENT:
transaction_completed ();
diff --git a/src/exchangedb/.gitignore b/src/exchangedb/.gitignore
index dd3c5ed1b..264217a3d 100644
--- a/src/exchangedb/.gitignore
+++ b/src/exchangedb/.gitignore
@@ -1,17 +1,9 @@
-test-exchangedb-auditors
-test-exchangedb-denomkeys
-test-exchangedb-fees
test-exchangedb-postgres
-test-exchangedb-signkeys
-test-perf-taler-exchangedb
bench-db-postgres
-shard-drop0001.sqltest-exchangedb-by-j-postgres
-test-exchangedb-by-j-postgres
-perf-exchangedb-reserves-in-insert-postgres
+perf_deposits_get_ready-postgres
+perf_get_link_data-postgres
+perf_reserves_in_insert-postgres
+perf_select_refunds_by_coin-postgres
exchange-0002.sql
procedures.sql
exchange-0003.sql
-test-exchangedb-batch-reserves-in-insert-postgres
-test-exchangedb-populate-table-postgres
-test-exchangedb-populate-link-data-postgres
-test-exchangedb-populate-ready-deposit-postgres
diff --git a/src/exchangedb/0002-deposits.sql b/src/exchangedb/0002-deposits.sql
index 92210afa3..d8afdac84 100644
--- a/src/exchangedb/0002-deposits.sql
+++ b/src/exchangedb/0002-deposits.sql
@@ -1,6 +1,6 @@
--
-- This file is part of TALER
--- Copyright (C) 2014--2022 Taler Systems SA
+-- Copyright (C) 2014--2023 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
@@ -116,6 +116,22 @@ BEGIN
',ADD CONSTRAINT ' || table_name || '_coin_pub_merchant_pub_h_contract_terms_key'
' UNIQUE (coin_pub, merchant_pub, h_contract_terms)'
);
+ EXECUTE FORMAT (
+ 'CREATE INDEX ' || table_name || '_by_ready '
+ 'ON ' || table_name || ' '
+ '(wire_deadline ASC'
+ ',shard ASC'
+ ',coin_pub'
+ ') WHERE NOT (done OR policy_blocked);'
+ );
+ EXECUTE FORMAT (
+ 'CREATE INDEX ' || table_name || '_for_matching '
+ 'ON ' || table_name || ' '
+ '(refund_deadline ASC'
+ ',merchant_pub'
+ ',coin_pub'
+ ') WHERE NOT (done OR policy_blocked);'
+ );
END
$$;
@@ -399,29 +415,5 @@ INSERT INTO exchange_tables
,'exchange-0002'
,'foreign'
,TRUE
- ,FALSE),
- ('deposits_by_ready'
- ,'exchange-0002'
- ,'create'
- ,TRUE
- ,TRUE),
- ('deposits_by_ready'
- ,'exchange-0002'
- ,'constrain'
- ,TRUE
- ,TRUE),
- ('deposits_for_matching'
- ,'exchange-0002'
- ,'create'
- ,TRUE
- ,TRUE),
- ('deposits_for_matching'
- ,'exchange-0002'
- ,'constrain'
- ,TRUE
- ,TRUE),
- ('deposits'
- ,'exchange-0002'
- ,'master'
- ,TRUE
- ,FALSE);
+ ,FALSE)
+ ;
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index e8ef104e1..49bc649b5 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -255,8 +255,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_select_purse_deposits_above_serial_id.h pg_select_purse_deposits_above_serial_id.c \
pg_select_account_merges_above_serial_id.h pg_select_account_merges_above_serial_id.c \
pg_select_all_purse_decisions_above_serial_id.h pg_select_all_purse_decisions_above_serial_id.c \
- pg_batch_reserves_in_insert.h pg_batch_reserves_in_insert.c \
- pg_batch2_reserves_in_insert.h pg_batch2_reserves_in_insert.c \
pg_select_reserve_open_above_serial_id.c pg_select_reserve_open_above_serial_id.h
libtaler_plugin_exchangedb_postgres_la_LIBADD = \
$(LTLIBINTL)
@@ -295,22 +293,14 @@ check_PROGRAMS = \
noinst_PROGRAMS = \
bench-db-postgres\
- perf-exchangedb-reserves-in-insert-postgres\
- test-exchangedb-by-j-postgres\
- test-exchangedb-batch-reserves-in-insert-postgres\
- test-exchangedb-populate-select-refunds-by-coin-postgres\
- test-exchangedb-populate-link-data-postgres\
- test-exchangedb-populate-ready-deposit-postgres
+ perf_get_link_data-postgres\
+ perf_select_refunds_by_coin-postgres\
+ perf_reserves_in_insert-postgres \
+ perf_deposits_get_ready-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-populate-select-refunds-by-coin-postgres\
- test-exchangedb-populate-link-data-postgres\
- test-exchangedb-populate-ready-deposit-postgres
+ (check_PROGRAMS)
test_exchangedb_postgres_SOURCES = \
test_exchangedb.c
test_exchangedb_postgres_LDADD = \
@@ -323,32 +313,6 @@ test_exchangedb_postgres_LDADD = \
-lgnunetutil \
$(XLIB)
-test_exchangedb_by_j_postgres_SOURCES = \
- test_exchangedb_by_j.c
-test_exchangedb_by_j_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 \
- -lm \
- $(XLIB)
-
-
-perf_exchangedb_reserves_in_insert_postgres_SOURCES = \
- perf_exchangedb_reserves_in_insert.c
-perf_exchangedb_reserves_in_insert_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 = \
@@ -359,9 +323,9 @@ bench_db_postgres_LDADD = \
-lgnunetutil \
$(XLIB)
-test_exchangedb_batch_reserves_in_insert_postgres_SOURCES = \
- test_exchangedb_batch_reserves_in_insert.c
-test_exchangedb_batch_reserves_in_insert_postgres_LDADD = \
+perf_reserves_in_insert_postgres_SOURCES = \
+ perf_reserves_in_insert.c
+perf_reserves_in_insert_postgres_LDADD = \
libtalerexchangedb.la \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/util/libtalerutil.la \
@@ -369,11 +333,12 @@ test_exchangedb_batch_reserves_in_insert_postgres_LDADD = \
-ljansson \
-lgnunetjson \
-lgnunetutil \
+ -lm \
$(XLIB)
-test_exchangedb_populate_select_refunds_by_coin_postgres_SOURCES = \
- test_exchangedb_populate_select_refunds_by_coin.c
-test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \
+perf_select_refunds_by_coin_postgres_SOURCES = \
+ perf_select_refunds_by_coin.c
+perf_select_refunds_by_coin_postgres_LDADD = \
libtalerexchangedb.la \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/util/libtalerutil.la \
@@ -384,9 +349,9 @@ test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \
-lm \
$(XLIB)
-test_exchangedb_populate_link_data_postgres_SOURCES = \
- test_exchangedb_populate_link_data.c
-test_exchangedb_populate_link_data_postgres_LDADD = \
+perf_get_link_data_postgres_SOURCES = \
+ perf_get_link_data.c
+perf_get_link_data_postgres_LDADD = \
libtalerexchangedb.la \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/util/libtalerutil.la \
@@ -397,9 +362,9 @@ test_exchangedb_populate_link_data_postgres_LDADD = \
-lm \
$(XLIB)
-test_exchangedb_populate_ready_deposit_postgres_SOURCES = \
- test_exchangedb_populate_ready_deposit.c
-test_exchangedb_populate_ready_deposit_postgres_LDADD = \
+perf_deposits_get_ready_postgres_SOURCES = \
+ perf_deposits_get_ready.c
+perf_deposits_get_ready_postgres_LDADD = \
libtalerexchangedb.la \
$(top_builddir)/src/json/libtalerjson.la \
$(top_builddir)/src/util/libtalerutil.la \
diff --git a/src/exchangedb/test_exchangedb_populate_ready_deposit.c b/src/exchangedb/perf_deposits_get_ready.c
index 97273fc9e..4ad08223c 100644
--- a/src/exchangedb/test_exchangedb_populate_ready_deposit.c
+++ b/src/exchangedb/perf_deposits_get_ready.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2022 Taler Systems SA
+ Copyright (C) 2014-2023 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
@@ -14,8 +14,8 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/test_exchangedb_populate_ready_deposit.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_deposits_get_ready.c
+ * @brief benchmark for deposits_get_ready
* @author Joseph Xu
*/
#include "platform.h"
@@ -34,7 +34,7 @@ static int result;
*/
#define FAILIF(cond) \
do { \
- if (! (cond)) {break;} \
+ if (! (cond)) {break;} \
GNUNET_break (0); \
goto drop; \
} while (0)
@@ -57,21 +57,27 @@ static int result;
*/
#define CURRENCY "EUR"
#define RSA_KEY_SIZE 1024
-#define NUM_ROWS 1000000
-#define ROUNDS 10000
+#define NUM_ROWS 1000
+#define ROUNDS 100
#define MELT_NEW_COINS 5
#define MELT_NOREVEAL_INDEX 1
+
/**
* Database plugin under test.
*/
static struct TALER_EXCHANGEDB_Plugin *plugin;
+
static struct TALER_DenomFeeSet fees;
+
static struct TALER_MerchantWireHashP h_wire_wt;
+
/**
* Denomination keys used for fresh coins in melt test.
*/
static struct DenomKeyPair **new_dkp;
+
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
+
struct DenomKeyPair
{
struct TALER_DenominationPrivateKey priv;
@@ -173,8 +179,6 @@ create_denom_key_pair (unsigned int size,
}
-
-
/**
* Main function that will be run by the scheduler.
*
@@ -191,19 +195,19 @@ run (void *cls)
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
- unsigned long long sqrs=0;
- struct TALER_EXCHANGEDB_Deposit *depos=NULL;
- struct TALER_EXCHANGEDB_Refund *ref=NULL;
+ unsigned long long sqrs = 0;
+ struct TALER_EXCHANGEDB_Deposit *depos = NULL;
+ struct TALER_EXCHANGEDB_Refund *ref = NULL;
unsigned int *perm;
unsigned long long duration_sq;
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
struct TALER_ExchangeWithdrawValues alg_values = {
.cipher = TALER_DENOMINATION_RSA
- };
+ };
- ref = GNUNET_new_array (ROUNDS +1,
+ ref = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Refund);
- depos = GNUNET_new_array (ROUNDS +1,
+ depos = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Deposit);
if (NULL ==
@@ -245,194 +249,190 @@ run (void *cls)
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010",
&fees.refund));
- //DENOMINATION
{
ZR_BLK (&cbc);
- //PAIR KEY LIST
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
- struct DenomKeyPair *);
- //PUBLIC KEY LIST
+ struct DenomKeyPair *);
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
struct TALER_DenominationPublicKey);
- //REFRESH REVEAL COIN LIST
revealed_coins
= GNUNET_new_array (MELT_NEW_COINS,
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
- {
- struct GNUNET_TIME_Timestamp now;
- struct TALER_BlindedRsaPlanchet *rp;
- struct TALER_BlindedPlanchet *bp;
-
- now = GNUNET_TIME_timestamp_get ();
- //5 KEY PAIR
- new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
- now,
- &value,
- &fees);
- GNUNET_assert (NULL != new_dkp[cnt]);
- new_denom_pubs[cnt] = new_dkp[cnt]->pub;
- ccoin = &revealed_coins[cnt];
- bp = &ccoin->blinded_planchet;
- bp->cipher = TALER_DENOMINATION_RSA;
- rp = &bp->details.rsa_blinded_planchet;
- rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
- GNUNET_CRYPTO_QUALITY_WEAK,
- (RSA_KEY_SIZE / 8) - 1);
- rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- rp->blinded_msg,
- rp->blinded_msg_size);
- TALER_denom_pub_hash (&new_dkp[cnt]->pub,
- &ccoin->h_denom_pub);
- ccoin->exchange_vals = alg_values;
- TALER_coin_ev_hash (bp,
- &ccoin->h_denom_pub,
- &ccoin->coin_envelope_hash);
- GNUNET_assert (GNUNET_OK ==
+ {
+ struct GNUNET_TIME_Timestamp now;
+ struct TALER_BlindedRsaPlanchet *rp;
+ struct TALER_BlindedPlanchet *bp;
+
+ now = GNUNET_TIME_timestamp_get ();
+ new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
+ now,
+ &value,
+ &fees);
+ GNUNET_assert (NULL != new_dkp[cnt]);
+ new_denom_pubs[cnt] = new_dkp[cnt]->pub;
+ ccoin = &revealed_coins[cnt];
+ bp = &ccoin->blinded_planchet;
+ bp->cipher = TALER_DENOMINATION_RSA;
+ rp = &bp->details.rsa_blinded_planchet;
+ rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
+ GNUNET_CRYPTO_QUALITY_WEAK,
+ (RSA_KEY_SIZE / 8) - 1);
+ rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ rp->blinded_msg,
+ rp->blinded_msg_size);
+ TALER_denom_pub_hash (&new_dkp[cnt]->pub,
+ &ccoin->h_denom_pub);
+ ccoin->exchange_vals = alg_values;
+ TALER_coin_ev_hash (bp,
+ &ccoin->h_denom_pub,
+ &ccoin->coin_envelope_hash);
+ GNUNET_assert (GNUNET_OK ==
TALER_denom_sign_blinded (&ccoin->coin_sig,
&new_dkp[cnt]->priv,
true,
bp));
- GNUNET_assert (GNUNET_OK ==
- TALER_coin_ev_hash (bp,
- &cbc.denom_pub_hash,
- &cbc.h_coin_envelope));
- GNUNET_assert (
- GNUNET_OK ==
- TALER_denom_sign_blinded (
- &cbc.sig,
- &new_dkp[cnt]->priv,
- false,
- bp));
- }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_coin_ev_hash (bp,
+ &cbc.denom_pub_hash,
+ &cbc.h_coin_envelope));
+ GNUNET_assert (
+ GNUNET_OK ==
+ TALER_denom_sign_blinded (
+ &cbc.sig,
+ &new_dkp[cnt]->priv,
+ false,
+ bp));
+ }
}
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
NUM_ROWS);
- //BEGIN
FAILIF (GNUNET_OK !=
plugin->start (plugin->cls,
"Transaction"));
for (unsigned int j = 0; j < NUM_ROWS; j++)
+ {
+ /*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
+ union TALER_DenominationBlindingKeyP bks;
+ struct GNUNET_TIME_Timestamp deadline;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_CoinPubHashP c_hash;
+ unsigned int k = (unsigned int) rand () % 5;
+ unsigned int i = perm[j];
+ if (i >= ROUNDS)
+ i = ROUNDS; /* throw-away slot, do not keep around */
+ depos[i].deposit_fee = fees.deposit;
+ RND_BLK (&coin_pub);
+ RND_BLK (&c_hash);
+ RND_BLK (&reserve_pub);
+ RND_BLK (&cbc.reserve_sig);
+ TALER_denom_pub_hash (&new_dkp[k]->pub,
+ &cbc.denom_pub_hash);
+ deadline = GNUNET_TIME_timestamp_get ();
+ RND_BLK (&depos[i].coin.coin_pub);
+ TALER_denom_pub_hash (&new_dkp[k]->pub,
+ &depos[i].coin.denom_pub_hash);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
+ &ccoin->coin_sig,
+ &bks,
+ &c_hash,
+ &alg_values,
+ &new_dkp[k]->pub));
+ RND_BLK (&depos[i].merchant_pub);
+ RND_BLK (&depos[i].csig);
+ RND_BLK (&depos[i].h_contract_terms);
+ RND_BLK (&depos[i].wire_salt);
+ depos[i].amount_with_fee = value;
+ depos[i].refund_deadline = deadline;
+ depos[i].wire_deadline = deadline;
+ depos[i].receiver_wire_account =
+ "payto://iban/DE67830654080004822650?receiver-name=Test";
+ TALER_merchant_wire_signature_hash (
+ "payto://iban/DE67830654080004822650?receiver-name=Test",
+ &depos[i].wire_salt,
+ &h_wire_wt);
+ cbc.reserve_pub = reserve_pub;
+ cbc.amount_with_fee = value;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (CURRENCY,
+ &cbc.withdraw_fee));
{
- /*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
- union TALER_DenominationBlindingKeyP bks;
- struct GNUNET_TIME_Timestamp deadline;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_CoinPubHashP c_hash;
- unsigned int k = (unsigned int)rand()%5;
- unsigned int i = perm[j];
- if (i >= ROUNDS)
- i = ROUNDS; /* throw-away slot, do not keep around */
- depos[i].deposit_fee = fees.deposit;
- RND_BLK (&coin_pub);
- RND_BLK (&c_hash);
- RND_BLK (&reserve_pub);
- RND_BLK (&cbc.reserve_sig);
- TALER_denom_pub_hash (&new_dkp[k]->pub,
- &cbc.denom_pub_hash);
- deadline = GNUNET_TIME_timestamp_get ();
- RND_BLK (&depos[i].coin.coin_pub);
- TALER_denom_pub_hash (&new_dkp[k]->pub,
- &depos[i].coin.denom_pub_hash);
- GNUNET_assert (GNUNET_OK ==
- TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
- &ccoin->coin_sig,
- &bks,
- &c_hash,
- &alg_values,
- &new_dkp[k]->pub));
- RND_BLK (&depos[i].merchant_pub);
- RND_BLK (&depos[i].csig);
- RND_BLK (&depos[i].h_contract_terms);
- RND_BLK (&depos[i].wire_salt);
- depos[i].amount_with_fee = value;
- depos[i].refund_deadline = deadline;
- depos[i].wire_deadline = deadline;
- depos[i].receiver_wire_account =
- "payto://iban/DE67830654080004822650?receiver-name=Test";
- TALER_merchant_wire_signature_hash (
- "payto://iban/DE67830654080004822650?receiver-name=Test",
- &depos[i].wire_salt,
- &h_wire_wt);
- cbc.reserve_pub = reserve_pub;
- cbc.amount_with_fee = value;
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (CURRENCY,
- &cbc.withdraw_fee));
- {
- /* INSERT WIRE TARGETS */
- bool found;
- bool nonce_ok;
- bool balance_ok;
- uint64_t ruuid;
- struct GNUNET_TIME_Timestamp now;
- now = GNUNET_TIME_timestamp_get ();
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->do_withdraw (plugin->cls,
- NULL,
- &cbc,
- now,
- &found,
- &balance_ok,
- &nonce_ok,
- &ruuid));
- }
- {
- /* ENSURE_COIN_KNOWN */
- uint64_t known_coin_id;
- struct TALER_DenominationHashP dph;
- struct TALER_AgeCommitmentHash agh;
- FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
- plugin->ensure_coin_known (plugin->cls,
- &depos[i].coin,
- &known_coin_id,
- &dph,
- &agh));
- refresh.coin = depos[i].coin;
- RND_BLK (&refresh.coin_sig);
- RND_BLK (&refresh.rc);
- refresh.amount_with_fee = value;
- refresh.noreveal_index = MELT_NOREVEAL_INDEX;
- }
- /*STORE INTO DEPOSIT*/
- {
- struct GNUNET_TIME_Timestamp now;
- now = GNUNET_TIME_timestamp_get ();
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->insert_deposit (plugin->cls,
- now,
- &depos[i]));
- }
- if (ROUNDS == i)
- TALER_denom_sig_free (&depos[i].coin.denom_sig);
+ bool found;
+ bool nonce_ok;
+ bool balance_ok;
+ uint64_t ruuid;
+ struct GNUNET_TIME_Timestamp now;
+
+ now = GNUNET_TIME_timestamp_get ();
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->do_withdraw (plugin->cls,
+ NULL,
+ &cbc,
+ now,
+ &found,
+ &balance_ok,
+ &nonce_ok,
+ &ruuid));
}
- /* End of benchmark setup */
- GNUNET_free(perm);
- // commit
+ {
+ /* ENSURE_COIN_KNOWN */
+ uint64_t known_coin_id;
+ struct TALER_DenominationHashP dph;
+ struct TALER_AgeCommitmentHash agh;
+ FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
+ plugin->ensure_coin_known (plugin->cls,
+ &depos[i].coin,
+ &known_coin_id,
+ &dph,
+ &agh));
+ refresh.coin = depos[i].coin;
+ RND_BLK (&refresh.coin_sig);
+ RND_BLK (&refresh.rc);
+ refresh.amount_with_fee = value;
+ refresh.noreveal_index = MELT_NOREVEAL_INDEX;
+ }
+ {
+ struct GNUNET_TIME_Timestamp now;
+
+ now = GNUNET_TIME_timestamp_get ();
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->insert_deposit (plugin->cls,
+ now,
+ &depos[i]));
+ }
+ if (ROUNDS == i)
+ TALER_denom_sig_free (&depos[i].coin.denom_sig);
+ }
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->commit (plugin->cls));
+ GNUNET_free (perm);
+ /* End of benchmark setup */
+
/**** CALL GET READY DEPOSIT ****/
- for (unsigned int r=0; r< ROUNDS; r++)
+ for (unsigned int r = 0; r< ROUNDS; r++)
{
struct GNUNET_TIME_Absolute time;
struct GNUNET_TIME_Relative duration;
struct TALER_MerchantPublicKeyP merchant_pub;
char *payto_uri;
- time = GNUNET_TIME_absolute_get();
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->get_ready_deposit (plugin->cls,
- 0,
- INT32_MAX,
- &merchant_pub,
- &payto_uri));
+ enum GNUNET_DB_QueryStatus qs;
+ time = GNUNET_TIME_absolute_get ();
+ qs = plugin->get_ready_deposit (plugin->cls,
+ 0,
+ INT32_MAX,
+ &merchant_pub,
+ &payto_uri);
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
duration = GNUNET_TIME_absolute_get_duration (time);
times = GNUNET_TIME_relative_add (times,
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 (duration_sq / duration.rel_value_us ==
+ duration.rel_value_us);
GNUNET_assert (sqrs + duration_sq >= sqrs);
sqrs += duration_sq;
}
@@ -447,15 +447,14 @@ run (void *cls)
ROUNDS);
avg_dbl = avg.rel_value_us;
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
- fprintf(stdout,
- "%8llu ± %6.0f\n",
- (unsigned long long) avg.rel_value_us,
- sqrt (variance / (ROUNDS-1)));
+ fprintf (stdout,
+ "%8llu ± %6.0f\n",
+ (unsigned long long) avg.rel_value_us,
+ sqrt (variance / (ROUNDS - 1)));
}
result = 0;
drop:
- GNUNET_break (GNUNET_OK ==
- plugin->drop_tables (plugin->cls));
+ // GNUNET_break (GNUNET_OK == plugin->drop_tables (plugin->cls));
cleanup:
if (NULL != revealed_coins)
{
@@ -473,12 +472,12 @@ cleanup:
cnt++)
destroy_denom_key_pair (new_dkp[cnt]);
GNUNET_free (new_dkp);
- for (unsigned int i=0; i< ROUNDS ; i++)
- {
- TALER_denom_sig_free (&depos[i].coin.denom_sig);
- }
- GNUNET_free(depos);
- GNUNET_free(ref);
+ for (unsigned int i = 0; i< ROUNDS; i++)
+ {
+ TALER_denom_sig_free (&depos[i].coin.denom_sig);
+ }
+ GNUNET_free (depos);
+ GNUNET_free (ref);
TALER_EXCHANGEDB_plugin_unload (plugin);
plugin = NULL;
}
@@ -490,7 +489,6 @@ main (int argc,
{
const char *plugin_name;
char *config_filename;
- char *testname;
struct GNUNET_CONFIGURATION_Handle *cfg;
(void) argc;
@@ -504,15 +502,17 @@ main (int argc,
"WARNING",
NULL);
plugin_name++;
- (void) GNUNET_asprintf (&testname,
- "test-exchange-db-%s",
- plugin_name);
- (void) GNUNET_asprintf (&config_filename,
- "%s.conf",
- testname);
- fprintf (stdout,
- "Using config: %s\n",
- config_filename);
+ {
+ char *testname;
+
+ GNUNET_asprintf (&testname,
+ "test-exchange-db-%s",
+ plugin_name);
+ GNUNET_asprintf (&config_filename,
+ "%s.conf",
+ testname);
+ GNUNET_free (testname);
+ }
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse (cfg,
@@ -520,16 +520,14 @@ main (int argc,
{
GNUNET_break (0);
GNUNET_free (config_filename);
- GNUNET_free (testname);
return 2;
}
GNUNET_SCHEDULER_run (&run,
cfg);
GNUNET_CONFIGURATION_destroy (cfg);
GNUNET_free (config_filename);
- GNUNET_free (testname);
return result;
}
-/* end of test_exchangedb_by_j.c */
+/* end of perf_deposits_get_ready.c */
diff --git a/src/exchangedb/test_exchangedb_populate_link_data.c b/src/exchangedb/perf_get_link_data.c
index 84e5ab883..eb1f5f6e2 100644
--- a/src/exchangedb/test_exchangedb_populate_link_data.c
+++ b/src/exchangedb/perf_get_link_data.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2022 Taler Systems SA
+ Copyright (C) 2014-2023 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
@@ -14,8 +14,8 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/test_exchangedb_populate_link_data.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_get_link_data.c
+ * @brief benchmark for get_link_data
* @author Joseph Xu
*/
#include "platform.h"
@@ -29,7 +29,7 @@
*/
#define FAILIF(cond) \
do { \
- if (! (cond)) {break;} \
+ if (! (cond)) {break;} \
GNUNET_break (0); \
goto drop; \
} while (0)
@@ -166,6 +166,8 @@ create_denom_key_pair (unsigned int size,
}
return dkp;
}
+
+
/**
* Function called with the session hashes and transfer secret
* information for a given coin.
@@ -199,22 +201,22 @@ run (void *cls)
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
const uint32_t num_partitions = 10;
struct DenomKeyPair *dkp = NULL;
- struct TALER_EXCHANGEDB_Deposit *depos=NULL;
+ struct TALER_EXCHANGEDB_Deposit *depos = NULL;
struct TALER_Amount value;
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
- unsigned long long sqrs=0;
- struct TALER_EXCHANGEDB_Refund *ref=NULL;
+ unsigned long long sqrs = 0;
+ struct TALER_EXCHANGEDB_Refund *ref = NULL;
unsigned int *perm;
unsigned long long duration_sq;
struct TALER_ExchangeWithdrawValues alg_values = {
.cipher = TALER_DENOMINATION_RSA
- };
+ };
- ref = GNUNET_new_array (ROUNDS +1,
+ ref = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Refund);
- depos = GNUNET_new_array (ROUNDS +1,
+ depos = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Deposit);
- refresh = GNUNET_new_array (ROUNDS +1,
+ refresh = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Refresh);
if (NULL ==
@@ -256,16 +258,14 @@ run (void *cls)
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010",
&fees.refund));
- //DENOMINATION
{
- //PAIR KEY LIST
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
struct DenomKeyPair *);
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
{
struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
-
+
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
now,
&value,
@@ -275,7 +275,6 @@ run (void *cls)
}
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
NUM_ROWS);
- //BEGIN
FAILIF (GNUNET_OK !=
plugin->start (plugin->cls,
"Transaction"));
@@ -290,89 +289,96 @@ run (void *cls)
i = ROUNDS; /* throw-away slot, do not keep around */
RND_BLK (&depos[i].coin.coin_pub);
ZR_BLK (&cbc);
- TALER_denom_pub_hash (&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub,
+ TALER_denom_pub_hash (&new_dkp[(unsigned int) rand ()
+ % MELT_NEW_COINS]->pub,
&depos[i].coin.denom_pub_hash);
-
{
- struct TALER_EXCHANGEDB_RefreshRevealedCoin revealed_coins[MELT_NEW_COINS];
-
- for (unsigned int p=0;p<MELT_NEW_COINS;p++)
- {
- struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin = &revealed_coins[p];
- struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
- struct TALER_BlindedRsaPlanchet *rp = &bp->details.rsa_blinded_planchet;
-
- /* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
- above for NUM_ROWS iterations; instead of making "all new" coins,
- we simply randomize the hash here as nobody is checking for consistency
- anyway ;-) */
- bp->cipher = TALER_DENOMINATION_RSA;
- rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
- GNUNET_CRYPTO_QUALITY_WEAK,
- (RSA_KEY_SIZE / 8) - 1);
- rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- rp->blinded_msg,
- rp->blinded_msg_size);
- TALER_denom_pub_hash (&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub,
- &revealed_coin->h_denom_pub);
- revealed_coin->exchange_vals = alg_values;
- TALER_coin_ev_hash (bp,
- &revealed_coin->h_denom_pub,
- &revealed_coin->coin_envelope_hash);
- GNUNET_assert (GNUNET_OK ==
- TALER_denom_sign_blinded (&revealed_coin->coin_sig,
- &new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->priv,
- true,
- bp));
- GNUNET_assert (
- GNUNET_OK ==
- TALER_denom_sign_blinded (
- &cbc.sig,
- &new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->priv,
- false,
- bp));
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
- &cbc.sig,
- &bks,
- &c_hash,
- &alg_values,
- &new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub));
- {
- /* ENSURE_COIN_KNOWN */
- struct TALER_DenominationHashP dph;
- struct TALER_AgeCommitmentHash agh;
- bool zombie_required = false;
- bool balance_ok;
-
- FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
- plugin->ensure_coin_known (plugin->cls,
- &depos[i].coin,
- &known_coin_id,
- &dph,
- &agh));
- /**** INSERT REFRESH COMMITMENTS ****/
- refresh[i].coin = depos[i].coin;
- RND_BLK (&refresh[i].coin_sig);
- RND_BLK (&refresh[i].rc);
- refresh[i].amount_with_fee = value;
- refresh[i].noreveal_index = MELT_NOREVEAL_INDEX;
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->do_melt (plugin->cls,
- NULL,
- &refresh[i],
- known_coin_id,
- &zombie_required,
- &balance_ok));
- }
+ struct TALER_EXCHANGEDB_RefreshRevealedCoin
+ revealed_coins[MELT_NEW_COINS];
+
+ for (unsigned int p = 0; p<MELT_NEW_COINS; p++)
+ {
+ struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin =
+ &revealed_coins[p];
+ struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
+ struct TALER_BlindedRsaPlanchet *rp = &bp->details.rsa_blinded_planchet;
+
+ /* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
+ above for NUM_ROWS iterations; instead of making "all new" coins,
+ we simply randomize the hash here as nobody is checking for consistency
+ anyway ;-) */
+ bp->cipher = TALER_DENOMINATION_RSA;
+ rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
+ GNUNET_CRYPTO_QUALITY_WEAK,
+ (RSA_KEY_SIZE / 8) - 1);
+ rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ rp->blinded_msg,
+ rp->blinded_msg_size);
+ TALER_denom_pub_hash (&new_dkp[(unsigned int) rand ()
+ % MELT_NEW_COINS]->pub,
+ &revealed_coin->h_denom_pub);
+ revealed_coin->exchange_vals = alg_values;
+ TALER_coin_ev_hash (bp,
+ &revealed_coin->h_denom_pub,
+ &revealed_coin->coin_envelope_hash);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_denom_sign_blinded (&revealed_coin->coin_sig,
+ &new_dkp[(unsigned
+ int) rand ()
+ % MELT_NEW_COINS]->
+ priv,
+ true,
+ bp));
+ GNUNET_assert (
+ GNUNET_OK ==
+ TALER_denom_sign_blinded (
+ &cbc.sig,
+ &new_dkp[(unsigned int) rand () % MELT_NEW_COINS]->priv,
+ false,
+ bp));
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
+ &cbc.sig,
+ &bks,
+ &c_hash,
+ &alg_values,
+ &new_dkp[(unsigned int) rand ()
+ % MELT_NEW_COINS]->pub));
+ {
+ /* ENSURE_COIN_KNOWN */
+ struct TALER_DenominationHashP dph;
+ struct TALER_AgeCommitmentHash agh;
+ bool zombie_required = false;
+ bool balance_ok;
+
+ FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
+ plugin->ensure_coin_known (plugin->cls,
+ &depos[i].coin,
+ &known_coin_id,
+ &dph,
+ &agh));
+ /**** INSERT REFRESH COMMITMENTS ****/
+ refresh[i].coin = depos[i].coin;
+ RND_BLK (&refresh[i].coin_sig);
+ RND_BLK (&refresh[i].rc);
+ refresh[i].amount_with_fee = value;
+ refresh[i].noreveal_index = MELT_NOREVEAL_INDEX;
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->do_melt (plugin->cls,
+ NULL,
+ &refresh[i],
+ known_coin_id,
+ &zombie_required,
+ &balance_ok));
+ }
/****GET melt_serial_id generated by default****/
{
struct TALER_EXCHANGEDB_Melt ret_refresh_session;
-
+
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_melt (plugin->cls,
&refresh[i].rc,
@@ -382,7 +388,7 @@ run (void *cls)
/**** INSERT REFRESH_REVEAL + TRANSFER_KEYS *****/
{
static unsigned int cnt;
-
+
RND_BLK (&tprivs);
RND_BLK (&tpub);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -398,14 +404,14 @@ run (void *cls)
}
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
{
- TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
- TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
+ TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
+ TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
}
-
+
/* {
struct TALER_CoinSpendPublicKeyP ocp;
uint64_t rrc_serial;
-
+
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_old_coin_by_h_blind (plugin->cls,
&revealed_coins->coin_envelope_hash,
@@ -417,17 +423,15 @@ run (void *cls)
TALER_denom_sig_free (&depos[i].coin.denom_sig);
}
/* End of benchmark setup */
- GNUNET_free(perm);
- // commit
+ GNUNET_free (perm);
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->commit (plugin->cls));
- /**** CALL GET LINK DATA ****/
- for (unsigned int r=0; r< ROUNDS; r++)
+ for (unsigned int r = 0; r< ROUNDS; r++)
{
struct GNUNET_TIME_Absolute time;
struct GNUNET_TIME_Relative duration;
enum GNUNET_DB_QueryStatus qs;
- time = GNUNET_TIME_absolute_get();
+ time = GNUNET_TIME_absolute_get ();
qs = plugin->get_link_data (plugin->cls,
&refresh[r].coin.coin_pub,
@@ -439,7 +443,8 @@ run (void *cls)
times = GNUNET_TIME_relative_add (times,
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 (duration_sq / duration.rel_value_us ==
+ duration.rel_value_us);
GNUNET_assert (sqrs + duration_sq >= sqrs);
sqrs += duration_sq;
}
@@ -454,10 +459,10 @@ run (void *cls)
ROUNDS);
avg_dbl = avg.rel_value_us;
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
- fprintf(stdout,
- "%8llu ± %6.0f\n",
- (unsigned long long) avg.rel_value_us,
- sqrt (variance / (ROUNDS-1)));
+ fprintf (stdout,
+ "%8llu ± %6.0f\n",
+ (unsigned long long) avg.rel_value_us,
+ sqrt (variance / (ROUNDS - 1)));
}
result = 0;
drop:
@@ -470,13 +475,13 @@ cleanup:
cnt++)
destroy_denom_key_pair (new_dkp[cnt]);
GNUNET_free (new_dkp);
- for (unsigned int i=0; i< ROUNDS; i++)
- {
- TALER_denom_sig_free (&depos[i].coin.denom_sig);
- }
- GNUNET_free(depos);
- GNUNET_free(ref);
- GNUNET_free(refresh);
+ for (unsigned int i = 0; i< ROUNDS; i++)
+ {
+ TALER_denom_sig_free (&depos[i].coin.denom_sig);
+ }
+ GNUNET_free (depos);
+ GNUNET_free (ref);
+ GNUNET_free (refresh);
dkp = NULL;
TALER_EXCHANGEDB_plugin_unload (plugin);
plugin = NULL;
@@ -509,9 +514,6 @@ main (int argc,
(void) GNUNET_asprintf (&config_filename,
"%s.conf",
testname);
- fprintf (stdout,
- "Using config: %s\n",
- config_filename);
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse (cfg,
diff --git a/src/exchangedb/perf_exchangedb_reserves_in_insert.c b/src/exchangedb/perf_reserves_in_insert.c
index fc2a00089..9f3ed4604 100644
--- a/src/exchangedb/perf_exchangedb_reserves_in_insert.c
+++ b/src/exchangedb/perf_reserves_in_insert.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2022 Taler Systems SA
+ Copyright (C) 2014-2023 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
@@ -14,8 +14,8 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/test_exchangedb_by_j.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_reserves_in_insert.c
+ * @brief benchmark for 'reserves_in_insert'
* @author Joseph Xu
*/
#include "platform.h"
@@ -23,6 +23,7 @@
#include "taler_json_lib.h"
#include "taler_exchangedb_plugin.h"
+
/**
* Global result from the testcase.
*/
@@ -33,7 +34,7 @@ static int result;
*/
#define FAILIF(cond) \
do { \
- if (! (cond)) { break;} \
+ if (! (cond)) {break;} \
GNUNET_break (0); \
goto drop; \
} while (0)
@@ -51,6 +52,10 @@ static int result;
#define ZR_BLK(ptr) \
memset (ptr, 0, sizeof (*ptr))
+/**
+ * How many rounds do we average over?
+ */
+#define ROUNDS 5
/**
* Currency we use. Must match test-exchange-db-*.conf.
@@ -73,6 +78,10 @@ run (void *cls)
{
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
const uint32_t num_partitions = 10;
+ static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 32 };
+ const unsigned int lcm = 3 * 32;
+ struct GNUNET_TIME_Relative times[sizeof (batches) / sizeof(*batches)];
+ unsigned long long sqrs[sizeof (batches) / sizeof(*batches)];
if (NULL ==
(plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
@@ -91,46 +100,78 @@ run (void *cls)
result = 77;
goto cleanup;
}
- for (unsigned int i = 0; i< 8; i++)
+
+ memset (times, 0, sizeof (times));
+ memset (sqrs, 0, sizeof (sqrs));
+ for (unsigned int r = 0; r < ROUNDS; r++)
{
- 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_ReservePublicKeyP reserve_pub;
-
- 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++)
+ for (unsigned int i = 0;
+ i< sizeof(batches) / sizeof(*batches);
+ i++)
{
- plugin->start (plugin->cls,
- "test_by_exchange_j");
- for (unsigned int k = 0; k<batch_size; k++)
+ unsigned int batch_size = batches[i];
+ struct TALER_Amount value;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_TIME_Timestamp ts;
+ unsigned long long duration_sq;
+ struct GNUNET_TIME_Relative duration;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (CURRENCY ":1.000010",
+ &value));
+ now = GNUNET_TIME_absolute_get ();
+ ts = GNUNET_TIME_timestamp_get ();
{
- RND_BLK (&reserve_pub);
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ const char *sndr = "payto://x-taler-bank/localhost:8080/1";
+ struct TALER_ReservePublicKeyP reserve_pubs[lcm];
+ struct TALER_EXCHANGEDB_ReserveInInfo reserves[lcm];
+ enum GNUNET_DB_QueryStatus results[lcm];
+
+ for (unsigned int k = 0; k<lcm; k++)
+ {
+ RND_BLK (&reserve_pubs[k]);
+ reserves[k].reserve_pub = &reserve_pubs[k];
+ 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;
+ }
+ FAILIF (lcm !=
plugin->reserves_in_insert (plugin->cls,
- &reserve_pub,
- &value,
- ts,
- sndr,
- "section",
- 4));
+ reserves,
+ lcm,
+ batch_size,
+ results));
}
- plugin->commit (plugin->cls);
- }
- duration = GNUNET_TIME_absolute_get_duration (now);
+ 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;
+ } /* for 'i' batch size */
+ } /* for 'r' ROUNDS */
+
+ for (unsigned int i = 0;
+ i< sizeof(batches) / sizeof(*batches);
+ 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,
- "for a batchsize equal to %d it took %s\n",
- batch_size,
- GNUNET_STRINGS_relative_time_to_string (duration,
- GNUNET_NO) );
+ "Batch[%2u]: %8llu ± %6.0f\n",
+ batches[i],
+ (unsigned long long) avg.rel_value_us,
+ sqrt (variance / (ROUNDS - 1)));
}
result = 0;
drop:
@@ -150,7 +191,6 @@ main (int argc,
char *config_filename;
char *testname;
struct GNUNET_CONFIGURATION_Handle *cfg;
-
(void) argc;
result = -1;
if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
@@ -158,6 +198,7 @@ main (int argc,
GNUNET_break (0);
return -1;
}
+
GNUNET_log_setup (argv[0],
"WARNING",
NULL);
@@ -168,9 +209,6 @@ main (int argc,
(void) GNUNET_asprintf (&config_filename,
"%s.conf",
testname);
- fprintf (stdout,
- "Using config: %s\n",
- config_filename);
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse (cfg,
@@ -190,4 +228,4 @@ main (int argc,
}
-/* end of test_exchangedb_by_j.c */
+/* end of perf_reserves_in_insert.c */
diff --git a/src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c b/src/exchangedb/perf_select_refunds_by_coin.c
index c094b2048..85c92f4b9 100644
--- a/src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c
+++ b/src/exchangedb/perf_select_refunds_by_coin.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2022 Taler Systems SA
+ Copyright (C) 2014-2023 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
@@ -14,8 +14,8 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/test_exchangedb_populate_table.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_select_refunds_by_coin.c
+ * @brief benchmark for select_refunds_by_coin
* @author Joseph Xu
*/
#include "platform.h"
@@ -34,7 +34,7 @@ static int result;
*/
#define FAILIF(cond) \
do { \
- if (! (cond)) {break;} \
+ if (! (cond)) {break;} \
GNUNET_break (0); \
goto drop; \
} while (0)
@@ -56,24 +56,31 @@ static int result;
*/
#define CURRENCY "EUR"
#define RSA_KEY_SIZE 1024
-#define ROUNDS 10000
-#define NUM_ROWS 1000000
+#define ROUNDS 100
+#define NUM_ROWS 1000
#define MELT_NEW_COINS 5
#define MELT_NOREVEAL_INDEX 1
+
/**
* Database plugin under test.
*/
static struct TALER_EXCHANGEDB_Plugin *plugin;
+
static struct TALER_DenomFeeSet fees;
+
static struct TALER_MerchantWireHashP h_wire_wt;
+
static struct DenomKeyPair **new_dkp;
+
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
+
struct DenomKeyPair
{
struct TALER_DenominationPrivateKey priv;
struct TALER_DenominationPublicKey pub;
};
+
/**
* Destroy a denomination key pair. The key is not necessarily removed from the DB.
*
@@ -166,6 +173,8 @@ create_denom_key_pair (unsigned int size,
}
return dkp;
}
+
+
/**
* Callback invoked with information about refunds applicable
* to a particular coin.
@@ -179,6 +188,7 @@ check_refund_cb (void *cls,
const struct TALER_Amount *amount_with_fee)
{
const struct TALER_EXCHANGEDB_Refund *refund = cls;
+
if (0 != TALER_amount_cmp (amount_with_fee,
&refund->details.refund_amount))
{
@@ -201,7 +211,7 @@ run (void *cls)
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
const uint32_t num_partitions = 10;
struct GNUNET_TIME_Timestamp ts;
- struct TALER_EXCHANGEDB_Deposit *depos=NULL;
+ struct TALER_EXCHANGEDB_Deposit *depos = NULL;
struct GNUNET_TIME_Timestamp deadline;
struct TALER_Amount value;
union TALER_DenominationBlindingKeyP bks;
@@ -209,20 +219,20 @@ run (void *cls)
struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
struct TALER_ExchangeWithdrawValues alg_values = {
.cipher = TALER_DENOMINATION_RSA
- };
+ };
struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
unsigned long long sqrs = 0;
- struct TALER_EXCHANGEDB_Refund *ref=NULL;
+ struct TALER_EXCHANGEDB_Refund *ref = NULL;
unsigned int *perm;
unsigned long long duration_sq;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
- unsigned int count=0;
+ unsigned int count = 0;
- ref = GNUNET_new_array (ROUNDS +1,
+ ref = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Refund);
- depos = GNUNET_new_array (ROUNDS +1,
+ depos = GNUNET_new_array (ROUNDS + 1,
struct TALER_EXCHANGEDB_Deposit);
ZR_BLK (&cbc);
@@ -249,8 +259,6 @@ run (void *cls)
GNUNET_break (0);
goto cleanup;
}
-
-
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.000010",
&value));
@@ -270,78 +278,72 @@ run (void *cls)
ts = GNUNET_TIME_timestamp_get ();
deadline = GNUNET_TIME_timestamp_get ();
- //DENOMINATION
{
- //PAIR KEY LIST
new_dkp = GNUNET_new_array (MELT_NEW_COINS,
- struct DenomKeyPair *);
- //PUBLIC KEY LIST
+ struct DenomKeyPair *);
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
struct TALER_DenominationPublicKey);
- //REFRESH REVEAL COIN LIST
revealed_coins
= GNUNET_new_array (MELT_NEW_COINS,
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
- {
- struct GNUNET_TIME_Timestamp now;
- struct TALER_BlindedRsaPlanchet *rp;
- struct TALER_BlindedPlanchet *bp;
-
- now = GNUNET_TIME_timestamp_get ();
- //5 KEY PAIR
- new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
- now,
- &value,
- &fees);
- GNUNET_assert (NULL != new_dkp[cnt]);
- new_denom_pubs[cnt] = new_dkp[cnt]->pub;
- ccoin = &revealed_coins[cnt];
- bp = &ccoin->blinded_planchet;
- bp->cipher = TALER_DENOMINATION_RSA;
- rp = &bp->details.rsa_blinded_planchet;
- rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
- GNUNET_CRYPTO_QUALITY_WEAK,
- (RSA_KEY_SIZE / 8) - 1);
- rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- rp->blinded_msg,
- rp->blinded_msg_size);
- TALER_denom_pub_hash (&new_dkp[cnt]->pub,
- &ccoin->h_denom_pub);
- ccoin->exchange_vals = alg_values;
- TALER_coin_ev_hash (bp,
- &ccoin->h_denom_pub,
- &ccoin->coin_envelope_hash);
- GNUNET_assert (GNUNET_OK ==
+ {
+ struct GNUNET_TIME_Timestamp now;
+ struct TALER_BlindedRsaPlanchet *rp;
+ struct TALER_BlindedPlanchet *bp;
+
+ now = GNUNET_TIME_timestamp_get ();
+ new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
+ now,
+ &value,
+ &fees);
+ GNUNET_assert (NULL != new_dkp[cnt]);
+ new_denom_pubs[cnt] = new_dkp[cnt]->pub;
+ ccoin = &revealed_coins[cnt];
+ bp = &ccoin->blinded_planchet;
+ bp->cipher = TALER_DENOMINATION_RSA;
+ rp = &bp->details.rsa_blinded_planchet;
+ rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
+ GNUNET_CRYPTO_QUALITY_WEAK,
+ (RSA_KEY_SIZE / 8) - 1);
+ rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ rp->blinded_msg,
+ rp->blinded_msg_size);
+ TALER_denom_pub_hash (&new_dkp[cnt]->pub,
+ &ccoin->h_denom_pub);
+ ccoin->exchange_vals = alg_values;
+ TALER_coin_ev_hash (bp,
+ &ccoin->h_denom_pub,
+ &ccoin->coin_envelope_hash);
+ GNUNET_assert (GNUNET_OK ==
TALER_denom_sign_blinded (&ccoin->coin_sig,
&new_dkp[cnt]->priv,
true,
bp));
- GNUNET_assert (GNUNET_OK ==
- TALER_coin_ev_hash (bp,
- &cbc.denom_pub_hash,
- &cbc.h_coin_envelope));
- GNUNET_assert (
- GNUNET_OK ==
- TALER_denom_sign_blinded (
- &cbc.sig,
- &new_dkp[cnt]->priv,
- false,
- bp));
- }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_coin_ev_hash (bp,
+ &cbc.denom_pub_hash,
+ &cbc.h_coin_envelope));
+ GNUNET_assert (
+ GNUNET_OK ==
+ TALER_denom_sign_blinded (
+ &cbc.sig,
+ &new_dkp[cnt]->priv,
+ false,
+ bp));
+ }
}
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
NUM_ROWS);
- // begin
FAILIF (GNUNET_OK !=
plugin->start (plugin->cls,
"Transaction"));
- for (unsigned int j=0; j< NUM_ROWS; j++)
+ for (unsigned int j = 0; j< NUM_ROWS; j++)
{
unsigned int i = perm[j];
- unsigned int k = (unsigned int)rand()%5;
+ unsigned int k = (unsigned int) rand () % 5;
if (i >= ROUNDS)
i = ROUNDS; /* throw-away slot, do not keep around */
RND_BLK (&coin_pub);
@@ -350,8 +352,6 @@ run (void *cls)
RND_BLK (&depos[i].coin.coin_pub);
TALER_denom_pub_hash (&new_dkp[k]->pub,
&depos[i].coin.denom_pub_hash);
- // TALER_denom_pub_hash (&dkp->pub,
- // &ref.coin.denom_pub_hash);
GNUNET_assert (GNUNET_OK ==
TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
&cbc.sig,
@@ -369,15 +369,15 @@ run (void *cls)
depos[i].receiver_wire_account =
"payto://iban/DE67830654080004822650?receiver-name=Test";
TALER_merchant_wire_signature_hash (
- "payto://iban/DE67830654080004822650?receiver-name=Test",
- &depos[i].wire_salt,
- &h_wire_wt);
+ "payto://iban/DE67830654080004822650?receiver-name=Test",
+ &depos[i].wire_salt,
+ &h_wire_wt);
depos[i].timestamp = ts;
- uint64_t known_coin_id;
- {//ENSURE_COIN_KNOWN
-
+ uint64_t known_coin_id;
+ {
struct TALER_DenominationHashP dph;
struct TALER_AgeCommitmentHash agh;
+
FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
plugin->ensure_coin_known (plugin->cls,
&depos[i].coin,
@@ -385,9 +385,9 @@ run (void *cls)
&dph,
&agh));
}
- /*STORE INTO DEPOSIT*/
{
struct GNUNET_TIME_Timestamp now;
+
now = GNUNET_TIME_timestamp_get ();
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->insert_deposit (plugin->cls,
@@ -399,12 +399,13 @@ run (void *cls)
bool refund_ok;
bool gone;
bool conflict;
- unsigned int refund_percent=0;
- switch (refund_percent){
- case 2 ://100% refund
+ unsigned int refund_percent = 0;
+ switch (refund_percent)
+ {
+ case 2: // 100% refund
ref[i].coin = depos[i].coin;
ref[i].details.merchant_pub = depos[i].merchant_pub;
- RND_BLK(&ref[i].details.merchant_sig);
+ RND_BLK (&ref[i].details.merchant_sig);
ref[i].details.h_contract_terms = depos[i].h_contract_terms;
ref[i].coin.coin_pub = depos[i].coin.coin_pub;
ref[i].details.rtransaction_id = i;
@@ -420,58 +421,58 @@ run (void *cls)
&gone,
&conflict));
break;
- case 1 ://10% refund
- if (count < (NUM_ROWS/10))
- {
- ref[i].coin = depos[i].coin;
- ref[i].details.merchant_pub = depos[i].merchant_pub;
- RND_BLK(&ref[i].details.merchant_sig);
- ref[i].details.h_contract_terms = depos[i].h_contract_terms;
- ref[i].coin.coin_pub = depos[i].coin.coin_pub;
- ref[i].details.rtransaction_id = i;
- ref[i].details.refund_amount = value;
- ref[i].details.refund_fee = fees.refund;
- }
- else
- {
+ case 1:// 10% refund
+ if (count < (NUM_ROWS / 10))
+ {
+ ref[i].coin = depos[i].coin;
+ ref[i].details.merchant_pub = depos[i].merchant_pub;
+ RND_BLK (&ref[i].details.merchant_sig);
+ ref[i].details.h_contract_terms = depos[i].h_contract_terms;
+ ref[i].coin.coin_pub = depos[i].coin.coin_pub;
+ ref[i].details.rtransaction_id = i;
+ ref[i].details.refund_amount = value;
+ ref[i].details.refund_fee = fees.refund;
+ }
+ else
+ {
+ ref[i].coin = depos[i].coin;
+ RND_BLK (&ref[i].details.merchant_pub);
+ RND_BLK (&ref[i].details.merchant_sig);
+ RND_BLK (&ref[i].details.h_contract_terms);
+ RND_BLK (&ref[i].coin.coin_pub);
+ ref[i].details.rtransaction_id = i;
+ ref[i].details.refund_amount = value;
+ ref[i].details.refund_fee = fees.refund;
+ }
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->do_refund (plugin->cls,
+ &ref[i],
+ &fees.deposit,
+ known_coin_id,
+ &not_found,
+ &refund_ok,
+ &gone,
+ &conflict));
+ count++;
+ break;
+ case 0:// no refund
ref[i].coin = depos[i].coin;
- RND_BLK(&ref[i].details.merchant_pub);
- RND_BLK(&ref[i].details.merchant_sig);
- RND_BLK(&ref[i].details.h_contract_terms);
- RND_BLK(&ref[i].coin.coin_pub);
+ RND_BLK (&ref[i].details.merchant_pub);
+ RND_BLK (&ref[i].details.merchant_sig);
+ RND_BLK (&ref[i].details.h_contract_terms);
+ RND_BLK (&ref[i].coin.coin_pub);
ref[i].details.rtransaction_id = i;
ref[i].details.refund_amount = value;
ref[i].details.refund_fee = fees.refund;
- }
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->do_refund (plugin->cls,
- &ref[i],
- &fees.deposit,
- known_coin_id,
- &not_found,
- &refund_ok,
- &gone,
- &conflict));
- count++;
- break;
- case 0://no refund
- ref[i].coin=depos[i].coin;
- RND_BLK(&ref[i].details.merchant_pub);
- RND_BLK(&ref[i].details.merchant_sig);
- RND_BLK(&ref[i].details.h_contract_terms);
- RND_BLK(&ref[i].coin.coin_pub);
- ref[i].details.rtransaction_id = i;
- ref[i].details.refund_amount = value;
- ref[i].details.refund_fee = fees.refund;
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->do_refund (plugin->cls,
- &ref[i],
- &fees.deposit,
- known_coin_id,
- &not_found,
- &refund_ok,
- &gone,
- &conflict));
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->do_refund (plugin->cls,
+ &ref[i],
+ &fees.deposit,
+ known_coin_id,
+ &not_found,
+ &refund_ok,
+ &gone,
+ &conflict));
break;
}/* END OF SWITCH CASE */
}
@@ -480,7 +481,6 @@ run (void *cls)
}
/* End of benchmark setup */
GNUNET_free (perm);
- // commit
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->commit (plugin->cls));
for (unsigned int r = 0; r < ROUNDS; r++)
@@ -500,7 +500,8 @@ run (void *cls)
times = GNUNET_TIME_relative_add (times,
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 (duration_sq / duration.rel_value_us ==
+ duration.rel_value_us);
GNUNET_assert (sqrs + duration_sq >= sqrs);
sqrs += duration_sq;
}
@@ -514,10 +515,10 @@ run (void *cls)
ROUNDS);
avg_dbl = avg.rel_value_us;
variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
- fprintf(stdout,
- "%8llu ± %6.0f\n",
- (unsigned long long) avg.rel_value_us,
- sqrt (variance / (ROUNDS-1)));
+ fprintf (stdout,
+ "%8llu ± %6.0f\n",
+ (unsigned long long) avg.rel_value_us,
+ sqrt (variance / (ROUNDS - 1)));
}
result = 0;
drop:
@@ -540,12 +541,12 @@ cleanup:
cnt++)
destroy_denom_key_pair (new_dkp[cnt]);
GNUNET_free (new_dkp);
- for (unsigned int i=0; i< ROUNDS +1 ; i++)
- {
- TALER_denom_sig_free (&depos[i].coin.denom_sig);
- }
- GNUNET_free(depos);
- GNUNET_free(ref);
+ for (unsigned int i = 0; i< ROUNDS + 1; i++)
+ {
+ TALER_denom_sig_free (&depos[i].coin.denom_sig);
+ }
+ GNUNET_free (depos);
+ GNUNET_free (ref);
TALER_EXCHANGEDB_plugin_unload (plugin);
plugin = NULL;
}
@@ -557,7 +558,6 @@ main (int argc,
{
const char *plugin_name;
char *config_filename;
- char *testname;
struct GNUNET_CONFIGURATION_Handle *cfg;
(void) argc;
@@ -571,15 +571,17 @@ main (int argc,
"WARNING",
NULL);
plugin_name++;
- (void) GNUNET_asprintf (&testname,
- "test-exchange-db-%s",
- plugin_name);
- (void) GNUNET_asprintf (&config_filename,
- "%s.conf",
- testname);
- fprintf (stdout,
- "Using config: %s\n",
- config_filename);
+ {
+ char *testname;
+
+ GNUNET_asprintf (&testname,
+ "test-exchange-db-%s",
+ plugin_name);
+ GNUNET_asprintf (&config_filename,
+ "%s.conf",
+ testname);
+ GNUNET_free (testname);
+ }
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse (cfg,
@@ -587,16 +589,14 @@ main (int argc,
{
GNUNET_break (0);
GNUNET_free (config_filename);
- GNUNET_free (testname);
return 2;
}
GNUNET_SCHEDULER_run (&run,
cfg);
GNUNET_CONFIGURATION_destroy (cfg);
GNUNET_free (config_filename);
- GNUNET_free (testname);
return result;
}
-/* end of test_exchangedb_by_j.c */
+/* end of perf_select_refunds_by_coin.c */
diff --git a/src/exchangedb/pg_aggregate.c b/src/exchangedb/pg_aggregate.c
index f1c4d6776..6e94cbebb 100644
--- a/src/exchangedb/pg_aggregate.c
+++ b/src/exchangedb/pg_aggregate.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
+ Copyright (C) 2022, 2023 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
@@ -72,26 +72,16 @@ TEH_PG_aggregate (
now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
pg->aggregator_shift);
- /* Used in #postgres_aggregate() */
+ /* Used in #postgres_aggregate() */
PREPARE (pg,
"aggregate",
- "WITH rdy AS (" /* find deposits ready by merchant */
- " SELECT"
- " coin_pub"
- " FROM deposits_for_matching"
- " WHERE refund_deadline<$1" /* filter by shard, only actually executable deposits */
- " AND merchant_pub=$2" /* filter by target merchant */
- " ORDER BY refund_deadline ASC" /* ordering is not critical */
- " LIMIT "
- TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits transaction size */
- " )"
- " ,dep AS (" /* restrict to our merchant and account and mark as done */
+ "WITH dep AS (" /* restrict to our merchant and account and mark as done */
" UPDATE deposits"
" SET done=TRUE"
- " WHERE coin_pub IN (SELECT coin_pub FROM rdy)"
- " AND merchant_pub=$2" /* theoretically, same coin could be spent at another merchant */
+ " WHERE NOT (done OR policy_blocked)" /* only actually executable deposits */
+ " AND refund_deadline<$1" /* filter by shard */
+ " AND merchant_pub=$2" /* filter by target merchant */
" AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */
- " AND done=FALSE" /* theoretically, same coin could be spend at the same merchant a 2nd time */
" RETURNING"
" deposit_serial_id"
" ,coin_pub"
diff --git a/src/exchangedb/pg_batch2_reserves_in_insert.c b/src/exchangedb/pg_batch2_reserves_in_insert.c
deleted file mode 100644
index 1ef9045da..000000000
--- a/src/exchangedb/pg_batch2_reserves_in_insert.c
+++ /dev/null
@@ -1,914 +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_batch2_reserves_in_insert.c
- * @brief Implementation of the reserves_in_insert function for Postgres
- * @author Joseph Xu
- */
-#include "platform.h"
-#include "taler_error_codes.h"
-#include "taler_dbevents.h"
-#include "taler_pq_lib.h"
-#include "pg_batch2_reserves_in_insert.h"
-#include "pg_helper.h"
-#include "pg_start.h"
-#include "pg_rollback.h"
-#include "pg_start_read_committed.h"
-#include "pg_commit.h"
-#include "pg_reserves_get.h"
-#include "pg_reserves_update.h"
-#include "pg_setup_wire_target.h"
-#include "pg_event_notify.h"
-#include "pg_preflight.h"
-
-/**
- * Generate event notification for the reserve change.
- *
- * @param reserve_pub reserve to notfiy on
- */
-static char *
-compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
-{
- struct TALER_ReserveEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
- .reserve_pub = *reserve_pub
- };
-
- return GNUNET_PG_get_event_notify_channel (&rep.header);
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert1(struct PostgresClosure *pg,
- const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
- 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 results[1])
-{
- 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);");
-
- 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_end
- };
-
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("conflicted",
- &conflict[0]),
- GNUNET_PQ_result_spec_bool ("transaction_duplicate",
- &transaction_duplicate[0]),
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
- &reserve_uuid[0]),
- GNUNET_PQ_result_spec_end
- };
-
-
- TALER_payto_hash (reserves[0].sender_account_details,
- &h_payto);
-
- 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 1(%d)\n",
- qs2);
- results[0] = qs2;
- return qs2;
- }
- GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
- if ((! conflict[0]) && transaction_duplicate[0])
- {
- GNUNET_break (0);
- TEH_PG_rollback (pg);
- results[0] = GNUNET_DB_STATUS_HARD_ERROR;
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- 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 results[1])
-{
- enum GNUNET_DB_QueryStatus qs1;
- PREPARE (pg,
- "batch2_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,$22);");
-
- 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_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_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 ("transaction_duplicate",
- &transaction_duplicate[0]),
- GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
- &transaction_duplicate[1]),
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
- &reserve_uuid[0]),
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
- &reserve_uuid[1]),
- 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);
-
-
- qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "batch2_reserve_create",
- params,
- rs);
- if (qs1 < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserves 2(%d)\n",
- qs1);
- results[0]=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[0]) && (transaction_duplicate[0]))
- ||((! conflict[1]) && (transaction_duplicate[1]))
- )
- {
- GNUNET_break (0);
- TEH_PG_rollback (pg); //ROLLBACK
- results[0] = GNUNET_DB_STATUS_HARD_ERROR;
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- 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 results[1])
-{
- 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_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserves4 (%d)\n",
- qs3);
- results[0] = qs3;
- return qs3;
- }
-
- GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
-
- 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);
- results[0] = GNUNET_DB_STATUS_HARD_ERROR;
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- return qs3;
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert8 (struct PostgresClosure *pg,
- const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8],
- 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 results[1])
-{
- enum GNUNET_DB_QueryStatus qs3;
- PREPARE (pg,
- "batch8_reserve_create",
- "SELECT "
- "out_reserve_found AS conflicted"
- ",out_reserve_found2 AS conflicted2"
- ",out_reserve_found3 AS conflicted3"
- ",out_reserve_found4 AS conflicted4"
- ",out_reserve_found5 AS conflicted5"
- ",out_reserve_found6 AS conflicted6"
- ",out_reserve_found7 AS conflicted7"
- ",out_reserve_found8 AS conflicted8"
- ",transaction_duplicate"
- ",transaction_duplicate2"
- ",transaction_duplicate3"
- ",transaction_duplicate4"
- ",transaction_duplicate5"
- ",transaction_duplicate6"
- ",transaction_duplicate7"
- ",transaction_duplicate8"
- ",ruuid AS reserve_uuid"
- ",ruuid2 AS reserve_uuid2"
- ",ruuid3 AS reserve_uuid3"
- ",ruuid4 AS reserve_uuid4"
- ",ruuid5 AS reserve_uuid5"
- ",ruuid6 AS reserve_uuid6"
- ",ruuid7 AS reserve_uuid7"
- ",ruuid8 AS reserve_uuid8"
- " FROM exchange_do_batch8_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,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$80,$81,$82);");
-
- 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_string (notify_s[4]),
- GNUNET_PQ_query_param_string (notify_s[5]),
- GNUNET_PQ_query_param_string (notify_s[6]),
- GNUNET_PQ_query_param_string (notify_s[7]),
-
- 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_auto_from_type (reserves[4].reserve_pub),
- GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference),
- TALER_PQ_query_param_amount (reserves[4].balance),
- GNUNET_PQ_query_param_string (reserves[4].exchange_account_name),
- GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (reserves[4].sender_account_details),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
- GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub),
- GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference),
- TALER_PQ_query_param_amount (reserves[5].balance),
- GNUNET_PQ_query_param_string (reserves[5].exchange_account_name),
- GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (reserves[5].sender_account_details),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
- GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub),
- GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference),
- TALER_PQ_query_param_amount (reserves[6].balance),
- GNUNET_PQ_query_param_string (reserves[6].exchange_account_name),
- GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (reserves[6].sender_account_details),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
- GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub),
- GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference),
- TALER_PQ_query_param_amount (reserves[7].balance),
- GNUNET_PQ_query_param_string (reserves[7].exchange_account_name),
- GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (reserves[7].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 ("conflicted5",
- &conflict[4]),
- GNUNET_PQ_result_spec_bool ("conflicted6",
- &conflict[5]),
- GNUNET_PQ_result_spec_bool ("conflicted7",
- &conflict[6]),
- GNUNET_PQ_result_spec_bool ("conflicted8",
- &conflict[7]),
- 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_bool ("transaction_duplicate5",
- &transaction_duplicate[4]),
- GNUNET_PQ_result_spec_bool ("transaction_duplicate6",
- &transaction_duplicate[5]),
- GNUNET_PQ_result_spec_bool ("transaction_duplicate7",
- &transaction_duplicate[6]),
- GNUNET_PQ_result_spec_bool ("transaction_duplicate8",
- &transaction_duplicate[7]),
- 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_uint64 ("reserve_uuid5",
- &reserve_uuid[4]),
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid6",
- &reserve_uuid[5]),
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid7",
- &reserve_uuid[6]),
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid8",
- &reserve_uuid[7]),
- 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);
- TALER_payto_hash (reserves[4].sender_account_details,
- &h_payto);
- TALER_payto_hash (reserves[5].sender_account_details,
- &h_payto);
- TALER_payto_hash (reserves[6].sender_account_details,
- &h_payto);
- TALER_payto_hash (reserves[7].sender_account_details,
- &h_payto);
-
- qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "batch8_reserve_create",
- params,
- rs);
- if (qs3 < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserves8 (%d)\n",
- qs3);
- results[0]=qs3;
- return qs3;
- }
-
- 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]))
- ||((! conflict[4]) && (transaction_duplicate[4]))
- ||((! conflict[5]) && (transaction_duplicate[5]))
- ||((! conflict[6]) && (transaction_duplicate[6]))
- ||((! conflict[7]) && (transaction_duplicate[7]))
- )
- {
- GNUNET_break (0);
- TEH_PG_rollback (pg);
- results[0]=GNUNET_DB_STATUS_HARD_ERROR;
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- 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;
- bool t_duplicate=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 >= 8)
- {
- qs1=insert8(pg,
- &reserves[i],
- expiry,
- gc,
- h_payto,
- &notify_s[i],
- reserve_expiration,
- &transaction_duplicate[i],
- &conflicts[i],
- &reserve_uuid[i],
- &results[i]);
-
- if (qs1<0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserve batch_8 (%d)\n",
- qs1);
- return qs1;
- }
- need_update |= conflicts[i];
- need_update |= conflicts[i+1];
- need_update |= conflicts[i+2];
- need_update |= conflicts[i+3];
- need_update |= conflicts[i+4];
- need_update |= conflicts[i+5];
- need_update |= conflicts[i+6];
- need_update |= conflicts[i+7];
- t_duplicate |= transaction_duplicate[i];
- t_duplicate |= transaction_duplicate[i+1];
- t_duplicate |= transaction_duplicate[i+2];
- t_duplicate |= transaction_duplicate[i+3];
- t_duplicate |= transaction_duplicate[i+4];
- t_duplicate |= transaction_duplicate[i+5];
- t_duplicate |= transaction_duplicate[i+6];
- t_duplicate |= transaction_duplicate[i+7];
- i+=8;
- continue;
- }
- switch (bs)
- {
- case 7:
- case 6 :
- case 5:
- case 4 :
- qs4=insert4(pg,
- &reserves[i],
- expiry,
- gc,
- h_payto,
- &notify_s[i],
- reserve_expiration,
- &transaction_duplicate[i],
- &conflicts[i],
- &reserve_uuid[i],
- &results[i]);
-
- if (qs4<0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserve batch_4 (%d)\n",
- qs4);
- return qs4;
- }
- need_update |= conflicts[i];
- need_update |= conflicts[i+1];
- need_update |= conflicts[i+2];
- need_update |= conflicts[i+3];
- t_duplicate |= transaction_duplicate[i];
- t_duplicate |= transaction_duplicate[i+1];
- t_duplicate |= transaction_duplicate[i+2];
- t_duplicate |= transaction_duplicate[i+3];
- // fprintf(stdout, "reserve_uuid : %ld %ld %ld %ld\n", reserve_uuid[i], reserve_uuid[i+1], reserve_uuid[i+2], reserve_uuid[i+3]);
- i += 4;
- break;
- 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],
- &results[i]);
- if (qs5<0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserve batch_2 (%d)\n",
- qs5);
- return qs5;
- }
- need_update |= conflicts[i];
- need_update |= conflicts[i+1];
- t_duplicate |= transaction_duplicate[i];
- t_duplicate |= transaction_duplicate[i+1];
- results[i] = (t_duplicate)
- ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
- : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- // fprintf(stdout, "reserve_uuid : %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],
- &results[i]);
- if (qs2<0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserve batch_1 (%d)\n)"
- ,qs2);
- return qs2;
- }
- need_update |= conflicts[i];
- t_duplicate |= transaction_duplicate[i];
- // fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[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 !=
- TEH_PG_start (pg,
- "reserve-insert-continued"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
-
- enum GNUNET_DB_QueryStatus qs3;
- PREPARE (pg,
- "reserves_update",
- "SELECT"
- " out_duplicate AS duplicate "
- "FROM exchange_do_batch_reserves_update"
- " ($1,$2,$3,$4,$5,$6,$7,$8);");
- for (unsigned int i = 0; i<reserves_length; i++)
- {
- if (! conflicts[i])
- continue;
- {
- bool duplicate;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
- GNUNET_PQ_query_param_timestamp (&expiry),
- GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
- TALER_PQ_query_param_amount (reserves[i].balance),
- GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (notify_s[i]),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("duplicate",
- &duplicate),
- GNUNET_PQ_result_spec_end
- };
- qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "reserves_update",
- params,
- rs);
- if (qs3<0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to update reserves (%d)\n",
- qs3);
- results[i] = qs3;
- return qs3;
- }
- results[i] = duplicate
- ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
- : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
-
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TEH_PG_commit (pg);
- if (cs < 0)
- return cs;
- }
-
-exit:
- for (unsigned int i = 0; i<reserves_length; i++)
- GNUNET_free (notify_s[i]);
-
- return reserves_length;
-}
diff --git a/src/exchangedb/pg_batch2_reserves_in_insert.h b/src/exchangedb/pg_batch2_reserves_in_insert.h
deleted file mode 100644
index 3191f867e..000000000
--- a/src/exchangedb/pg_batch2_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_batch2_reserves_in_insert.h
- * @brief implementation of the batch2_reserves_in_insert function for Postgres
- * @author Joseph XU
- */
-#ifndef PG_BATCH2_RESERVES_IN_INSERT_H
-#define PG_BATCH2_RESERVES_IN_INSERT_H
-
-#include "taler_util.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-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
deleted file mode 100644
index 6536eb56c..000000000
--- a/src/exchangedb/pg_batch4_reserves_in_insert.c
+++ /dev/null
@@ -1,595 +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_batch_reserves_in_insert.c
- * @brief Implementation of the reserves_in_insert function for Postgres
- * @author Joseph Xu
- */
-#include "platform.h"
-#include "taler_error_codes.h"
-#include "taler_dbevents.h"
-#include "taler_pq_lib.h"
-#include "pg_batch_reserves_in_insert.h"
-#include "pg_helper.h"
-#include "pg_start.h"
-#include "pg_rollback.h"
-#include "pg_start_read_committed.h"
-#include "pg_commit.h"
-#include "pg_reserves_get.h"
-#include "pg_reserves_update.h"
-#include "pg_setup_wire_target.h"
-#include "pg_event_notify.h"
-#include "pg_preflight.h"
-
-/**
- * Generate event notification for the reserve change.
- *
- * @param reserve_pub reserve to notfiy on
- */
-static char *
-compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
-{
- struct TALER_ReserveEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
- .reserve_pub = *reserve_pub
- };
-
- return GNUNET_PG_get_event_notify_channel (&rep.header);
-}
-
-
-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_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[reserves_length];
- bool conflicted;
- bool conflicted2;
- 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];
- 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)
- {
- 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]);
-
- 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)
- {
- 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;
- }
- } /* end while */
- // commit
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TEH_PG_commit (pg);
- if (cs < 0)
- return cs;
- }
-
- if (!need_update )
- goto exit;
- // begin serializable
- {
- if (GNUNET_OK !=
- TEH_PG_start(pg,
- "reserve-insert-continued"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
-
- enum GNUNET_DB_QueryStatus qs3;
- PREPARE (pg,
- "reserves_in_add_transaction",
- "CALL exchange_do_batch_reserves_update"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
- for (unsigned int i=0;i<reserves_length;i++)
- {
- if (! conflicts[i])
- continue;
- {
- 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_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_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (notify_s[i]),
- GNUNET_PQ_query_param_end
- };
-
- qs3 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reserves_in_add_transaction",
- params);
- if (qs3<0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to update reserves (%d)\n",
- qs3);
- return qs3;
- }
- }
- }
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TEH_PG_commit (pg);
- if (cs < 0)
- return cs;
- }
-
- exit:
- for (unsigned int i=0;i<reserves_length;i++)
- GNUNET_free (notify_s[i]);
-
- return reserves_length;
-}
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.c b/src/exchangedb/pg_batch_reserves_in_insert.c
deleted file mode 100644
index f1e4a9362..000000000
--- a/src/exchangedb/pg_batch_reserves_in_insert.c
+++ /dev/null
@@ -1,252 +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_batch_reserves_in_insert.c
- * @brief Implementation of the reserves_in_insert function for Postgres
- * @author Joseph Xu
- */
-#include "platform.h"
-#include "taler_error_codes.h"
-#include "taler_dbevents.h"
-#include "taler_pq_lib.h"
-#include "pg_batch_reserves_in_insert.h"
-#include "pg_helper.h"
-#include "pg_start.h"
-#include "pg_rollback.h"
-#include "pg_start_read_committed.h"
-#include "pg_commit.h"
-#include "pg_reserves_get.h"
-#include "pg_reserves_update.h"
-#include "pg_setup_wire_target.h"
-#include "pg_event_notify.h"
-#include "pg_preflight.h"
-
-
-/**
- * Generate event notification for the reserve change.
- *
- * @param reserve_pub reserve to notfiy on
- */
-static char *
-compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
-{
- struct TALER_ReserveEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
- .reserve_pub = *reserve_pub
- };
-
- return GNUNET_PG_get_event_notify_channel (&rep.header);
-}
-
-
-enum GNUNET_DB_QueryStatus
-TEH_PG_batch_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;
- struct GNUNET_TIME_Timestamp expiry;
- struct GNUNET_TIME_Timestamp gc;
- struct TALER_PaytoHashP h_payto;
- uint64_t reserve_uuid;
- 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;
- }
- PREPARE (pg,
- "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);");
- 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);
- }
- bool need_update = false;
- for (unsigned int i = 0; i<reserves_length; i++)
- {
- bool conflicted;
- bool transaction_duplicate;
-
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
- GNUNET_PQ_query_param_timestamp (&expiry),
- GNUNET_PQ_query_param_timestamp (&gc),
- GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
- TALER_PQ_query_param_amount (reserves[i].balance),
- GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
- GNUNET_PQ_query_param_timestamp (&reserves[i].execution_time),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (reserves[i].sender_account_details),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
- GNUNET_PQ_query_param_string (notify_s[i]),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("conflicted",
- &conflicted),
- 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 (reserves[i].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);
- if (qs1 < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to create reserves (%d)\n",
- qs1);
- results[i] = qs1;
- return qs1;
- }
- GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
- conflicts[i] = conflicted;
- // fprintf(stdout, "%d", conflicts[i]);
- if (conflicts[i] && transaction_duplicate)
- {
- GNUNET_break (0);
- results[i] = GNUNET_DB_STATUS_HARD_ERROR;
- TEH_PG_rollback (pg);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- results[i] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- need_update |= conflicted;
- }
- // commit
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TEH_PG_commit (pg);
- if (cs < 0)
- return cs;
- }
- if (! need_update)
- goto exit;
- // begin serializable
- {
- if (GNUNET_OK !=
- TEH_PG_start (pg,
- "reserve-insert-continued"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
-
- enum GNUNET_DB_QueryStatus qs2;
- PREPARE (pg,
- "reserves_in_add_transaction",
- "SELECT"
- " out_duplicate AS duplicate"
- " FROM exchange_do_batch_reserves_update"
- " ($1,$2,$3,$4,$5,$6,$7,$8);");
- for (unsigned int i = 0; i<reserves_length; i++)
- {
- if (! conflicts[i])
- continue;
- {
- bool duplicate;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
- GNUNET_PQ_query_param_timestamp (&expiry),
- GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
- TALER_PQ_query_param_amount (reserves[i].balance),
- GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_string (notify_s[i]),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("duplicate",
- &duplicate),
- GNUNET_PQ_result_spec_end
- };
- qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "reserves_in_add_transaction",
- params,
- rs);
- if (qs2 < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to update reserves (%d)\n",
- qs2);
- results[i] = qs2;
- return qs2;
- }
- results[i] = duplicate
- ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
- : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TEH_PG_commit (pg);
- if (cs < 0)
- return cs;
- }
-exit:
- for (unsigned int i = 0; i<reserves_length; i++)
- GNUNET_free (notify_s[i]);
-
- return reserves_length;
-}
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.h b/src/exchangedb/pg_batch_reserves_in_insert.h
deleted file mode 100644
index 766795672..000000000
--- a/src/exchangedb/pg_batch_reserves_in_insert.h
+++ /dev/null
@@ -1,35 +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_batch_reserves_in_insert.h
- * @brief implementation of the batch_reserves_in_insert function for Postgres
- * @author Christian Grothoff
- */
-#ifndef PG_BATCH_RESERVES_IN_INSERT_H
-#define PG_BATCH_RESERVES_IN_INSERT_H
-
-#include "taler_util.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-
-
-enum GNUNET_DB_QueryStatus
-TEH_PG_batch_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_get_link_data.c b/src/exchangedb/pg_get_link_data.c
index 26225a13d..a07954335 100644
--- a/src/exchangedb/pg_get_link_data.c
+++ b/src/exchangedb/pg_get_link_data.c
@@ -55,7 +55,7 @@ struct LinkDataContext
/**
* Status, set to #GNUNET_SYSERR on errors,
*/
- int status;
+ enum GNUNET_GenericReturnValue status;
};
@@ -190,20 +190,18 @@ TEH_PG_get_link_data (void *cls,
"%d%c",
&percent_refund,
&dummy)) )
- {
- if (NULL != mode)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bad mode `%s' specified\n",
- mode);
- }
- if (NULL==mode)
- percent_refund=0;
+ {
+ if (NULL != mode)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Bad mode `%s' specified\n",
+ mode);
+ percent_refund = 0;
+ }
}
-
switch (percent_refund)
{
case 0:
- query="get_link";
+ query = "get_link";
PREPARE (pg,
query,
"SELECT "
@@ -225,7 +223,7 @@ TEH_PG_get_link_data (void *cls,
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
break;
case 1:
- query="get_link_v1";
+ query = "get_link_v1";
PREPARE (pg,
query,
"WITH rc AS MATERIALIZED ("
@@ -252,7 +250,7 @@ TEH_PG_get_link_data (void *cls,
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
break;
case 2:
- query="get_link_v2";
+ query = "get_link_v2";
PREPARE (pg,
query,
"SELECT"
@@ -300,5 +298,3 @@ TEH_PG_get_link_data (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
return qs;
}
-
-
diff --git a/src/exchangedb/pg_get_ready_deposit.c b/src/exchangedb/pg_get_ready_deposit.c
index 73ac9e47b..91151c617 100644
--- a/src/exchangedb/pg_get_ready_deposit.c
+++ b/src/exchangedb/pg_get_ready_deposit.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
+ Copyright (C) 2022, 2023 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
@@ -33,15 +33,16 @@ TEH_PG_get_ready_deposit (void *cls,
struct TALER_MerchantPublicKeyP *merchant_pub,
char **payto_uri)
{
+ static int choose_mode = -2;
struct PostgresClosure *pg = cls;
- struct GNUNET_TIME_Absolute now = {0};
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_uint64 (&start_shard_row),
GNUNET_PQ_query_param_uint64 (&end_shard_row),
GNUNET_PQ_query_param_end
};
-
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
merchant_pub),
@@ -49,181 +50,70 @@ TEH_PG_get_ready_deposit (void *cls,
payto_uri),
GNUNET_PQ_result_spec_end
};
-
- now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
- pg->aggregator_shift);
- GNUNET_assert (start_shard_row < end_shard_row);
- GNUNET_assert (end_shard_row <= INT32_MAX);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Finding ready deposits by deadline %s (%llu)\n",
- GNUNET_TIME_absolute2s (now),
- (unsigned long long) now.abs_value_us);
- int choose_mode =-2;
const char *query;
if (-2 == choose_mode)
{
- const char *mode = getenv ("NEW_LOGIC");
+ const char *mode = getenv ("TALER_POSTGRES_GET_READY_LOGIC");
char dummy;
+
if ( (NULL==mode) ||
(1 != sscanf (mode,
"%d%c",
&choose_mode,
&dummy)) )
- {
- if (NULL != mode)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bad mode `%s' specified\n",
- mode);
- }
- if (NULL==mode)
- choose_mode=0;
-
-
+ {
+ if (NULL != mode)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Bad mode `%s' specified\n",
+ mode);
+ choose_mode = 0;
+ }
}
switch (choose_mode)
{
case 0:
- query="deposits_get_ready";
+ query = "deposits_get_ready-v5";
PREPARE (pg,
query,
"SELECT"
" payto_uri"
",merchant_pub"
- " FROM deposits_by_ready dbr"
- " JOIN deposits dep"
- " ON (dbr.coin_pub = dep.coin_pub AND"
- " dbr.deposit_serial_id = dep.deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE dbr.wire_deadline<=$1"
- " AND dbr.shard >= $2"
- " AND dbr.shard <= $3"
+ " FROM deposits dep"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE NOT (done OR policy_blocked)"
+ " AND dep.wire_deadline<=$1"
+ " AND dep.shard >= $2"
+ " AND dep.shard <= $3"
" ORDER BY "
- " dbr.wire_deadline ASC"
- " ,dbr.shard ASC"
+ " dep.wire_deadline ASC"
+ " ,dep.shard ASC"
" LIMIT 1;");
break;
case 1:
- query="deposits_get_ready_v1";
+ query = "deposits_get_ready-v6";
PREPARE (pg,
query,
"WITH rc AS MATERIALIZED ("
" SELECT"
- " coin_pub"
- ",deposit_serial_id"
- " FROM deposits_by_ready"
- " WHERE"
- " wire_deadline<=$1"
- " AND shard >= $2"
- " AND shard <= $3"
- " ORDER BY "
- " wire_deadline ASC"
- " ,shard ASC"
- " LIMIT 1"
- ")"
- "SELECT"
- " wt.payto_uri"
- ",dep.merchant_pub"
- " FROM ("
- " SELECT"
- " wire_target_h_payto"
- ",merchant_pub"
+ " merchant_pub"
+ ",wire_target_h_payto"
" FROM deposits"
- " WHERE coin_pub=(SELECT coin_pub FROM rc)"
- " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
- ") dep"
- " JOIN wire_targets wt"
- " ON (dep.wire_target_h_payto = wt.wire_target_h_payto)"
- );
-
- break;
- case 2:
- query = "stored_procedure_get_ready_deposit";
- PREPARE (pg,
- query,
- "SELECT"
- " out_payto_uri AS payto_uri"
- ",out_merchant_pub AS merchant_pub"
- " FROM"
- " exchange_do_get_ready_deposit"
- " ($1, $2, $3) ");
- break;
- case 3:
- query="deposits_get_ready_v3";
- PREPARE (pg,
- query,
- "WITH rc AS MATERIALIZED ("
- " SELECT"
- " coin_pub"
- ",deposit_serial_id"
- " FROM deposits_by_ready"
- " WHERE"
- " wire_deadline<=$1"
- " AND shard >= $2"
- " AND shard <= $3"
- " ORDER BY "
- " wire_deadline ASC"
+ " WHERE NOT (done OR policy_blocked)"
+ " AND wire_deadline<=$1"
+ " AND shard >= $2"
+ " AND shard <= $3"
+ " ORDER BY wire_deadline ASC"
" ,shard ASC"
" LIMIT 1"
")"
"SELECT"
" wt.payto_uri"
- ",dep.merchant_pub"
- " FROM ("
- " SELECT"
- " wire_target_h_payto"
- ",merchant_pub"
- ",coin_pub"
- " FROM deposits"
- " WHERE coin_pub=(SELECT coin_pub FROM rc)"
- " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
- ") dep"
- " JOIN wire_targets wt"
- " ON (dep.wire_target_h_payto = wt.wire_target_h_payto)"
- " JOIN rc"
- " ON (dep.coin_pub=rc.coin_pub)"
- );
-
- break;
- case 4:
- query="deposits_get_ready_v4";
- PREPARE (pg,
- query,
- "WITH rc AS MATERIALIZED ("
- " SELECT"
- " coin_pub"
- ",deposit_serial_id"
- " FROM deposits_by_ready"
- " WHERE"
- " wire_deadline<=$1"
- " AND shard >= $2"
- " AND shard <= $3"
- " ORDER BY "
- " wire_deadline ASC"
- " ,shard ASC"
- " LIMIT 1"
- "),"
- "WITH rv AS MATERIALIZED ("
- " SELECT"
- " payto_uri"
- ",wire_target_h_payto"
- " FROM wire_targets"
- ")"
- "SELECT"
- " rv.payto_uri"
- ",dep.merchant_pub"
- " FROM ("
- " SELECT"
- " wire_target_h_payto"
- ",merchant_pub"
- " FROM deposits"
- " WHERE coin_pub=(SELECT coin_pub FROM rc)"
- " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
- ") dep"
- " JOIN rv"
- " ON (rv.wire_target_h_payto=dep.wire_target_h_payto)"
- );
+ ",rc.merchant_pub"
+ " FROM wire_targets wt"
+ " JOIN rc"
+ " USING (wire_target_h_payto);");
break;
default:
GNUNET_break (0);
diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c
index 0fdc4a16c..314e89d8b 100644
--- a/src/exchangedb/pg_reserves_in_insert.c
+++ b/src/exchangedb/pg_reserves_in_insert.c
@@ -27,6 +27,8 @@
#include "pg_start.h"
#include "pg_start_read_committed.h"
#include "pg_commit.h"
+#include "pg_preflight.h"
+#include "pg_rollback.h"
#include "pg_reserves_get.h"
#include "pg_reserves_update.h"
#include "pg_setup_wire_target.h"
@@ -34,15 +36,13 @@
/**
- * Generate event notification for the reserve
- * change.
+ * Generate event notification for the reserve change.
*
- * @param pg plugin state
* @param reserve_pub reserve to notfiy on
+ * @return string to pass to postgres for the notification
*/
-static void
-notify_on_reserve (struct PostgresClosure *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub)
+static char *
+compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
{
struct TALER_ReserveEventP rep = {
.header.size = htons (sizeof (rep)),
@@ -50,246 +50,868 @@ notify_on_reserve (struct PostgresClosure *pg,
.reserve_pub = *reserve_pub
};
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Notifying on reserve!\n");
- TEH_PG_event_notify (pg,
- &rep.header,
- NULL,
- 0);
+ return GNUNET_PG_get_event_notify_channel (&rep.header);
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert1 (struct PostgresClosure *pg,
+ const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
+ 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 results[1])
+{
+ 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);");
+
+ 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_end
+ };
+
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("conflicted",
+ &conflict[0]),
+ GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+ &transaction_duplicate[0]),
+ GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+ &reserve_uuid[0]),
+ GNUNET_PQ_result_spec_end
+ };
+
+
+ TALER_payto_hash (reserves[0].sender_account_details,
+ &h_payto);
+
+ 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 1(%d)\n",
+ qs2);
+ results[0] = qs2;
+ return qs2;
+ }
+ GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
+ if ((! conflict[0]) && transaction_duplicate[0])
+ {
+ GNUNET_break (0);
+ TEH_PG_rollback (pg);
+ results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ 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 results[1])
+{
+ enum GNUNET_DB_QueryStatus qs1;
+ PREPARE (pg,
+ "batch2_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,$22);");
+
+ 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_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_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 ("transaction_duplicate",
+ &transaction_duplicate[0]),
+ GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+ &transaction_duplicate[1]),
+ GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+ &reserve_uuid[0]),
+ GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+ &reserve_uuid[1]),
+ 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);
+
+
+ qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "batch2_reserve_create",
+ params,
+ rs);
+ if (qs1 < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserves 2(%d)\n",
+ qs1);
+ results[0] = 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[0]) && (transaction_duplicate[0]))
+ || ((! conflict[1]) && (transaction_duplicate[1]))
+ )
+ {
+ GNUNET_break (0);
+ TEH_PG_rollback (pg); // ROLLBACK
+ results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ 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 results[1])
+{
+ 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_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserves4 (%d)\n",
+ qs3);
+ results[0] = qs3;
+ return qs3;
+ }
+
+ GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
+
+ 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);
+ results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ return qs3;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert8 (struct PostgresClosure *pg,
+ const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8],
+ 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 results[1])
+{
+ enum GNUNET_DB_QueryStatus qs3;
+ PREPARE (pg,
+ "batch8_reserve_create",
+ "SELECT "
+ "out_reserve_found AS conflicted"
+ ",out_reserve_found2 AS conflicted2"
+ ",out_reserve_found3 AS conflicted3"
+ ",out_reserve_found4 AS conflicted4"
+ ",out_reserve_found5 AS conflicted5"
+ ",out_reserve_found6 AS conflicted6"
+ ",out_reserve_found7 AS conflicted7"
+ ",out_reserve_found8 AS conflicted8"
+ ",transaction_duplicate"
+ ",transaction_duplicate2"
+ ",transaction_duplicate3"
+ ",transaction_duplicate4"
+ ",transaction_duplicate5"
+ ",transaction_duplicate6"
+ ",transaction_duplicate7"
+ ",transaction_duplicate8"
+ ",ruuid AS reserve_uuid"
+ ",ruuid2 AS reserve_uuid2"
+ ",ruuid3 AS reserve_uuid3"
+ ",ruuid4 AS reserve_uuid4"
+ ",ruuid5 AS reserve_uuid5"
+ ",ruuid6 AS reserve_uuid6"
+ ",ruuid7 AS reserve_uuid7"
+ ",ruuid8 AS reserve_uuid8"
+ " FROM exchange_do_batch8_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,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$80,$81,$82);");
+
+ 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_string (notify_s[4]),
+ GNUNET_PQ_query_param_string (notify_s[5]),
+ GNUNET_PQ_query_param_string (notify_s[6]),
+ GNUNET_PQ_query_param_string (notify_s[7]),
+
+ 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_auto_from_type (reserves[4].reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference),
+ TALER_PQ_query_param_amount (reserves[4].balance),
+ GNUNET_PQ_query_param_string (reserves[4].exchange_account_name),
+ GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_string (reserves[4].sender_account_details),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+ GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference),
+ TALER_PQ_query_param_amount (reserves[5].balance),
+ GNUNET_PQ_query_param_string (reserves[5].exchange_account_name),
+ GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_string (reserves[5].sender_account_details),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+ GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference),
+ TALER_PQ_query_param_amount (reserves[6].balance),
+ GNUNET_PQ_query_param_string (reserves[6].exchange_account_name),
+ GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_string (reserves[6].sender_account_details),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+ GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference),
+ TALER_PQ_query_param_amount (reserves[7].balance),
+ GNUNET_PQ_query_param_string (reserves[7].exchange_account_name),
+ GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_string (reserves[7].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 ("conflicted5",
+ &conflict[4]),
+ GNUNET_PQ_result_spec_bool ("conflicted6",
+ &conflict[5]),
+ GNUNET_PQ_result_spec_bool ("conflicted7",
+ &conflict[6]),
+ GNUNET_PQ_result_spec_bool ("conflicted8",
+ &conflict[7]),
+ 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_bool ("transaction_duplicate5",
+ &transaction_duplicate[4]),
+ GNUNET_PQ_result_spec_bool ("transaction_duplicate6",
+ &transaction_duplicate[5]),
+ GNUNET_PQ_result_spec_bool ("transaction_duplicate7",
+ &transaction_duplicate[6]),
+ GNUNET_PQ_result_spec_bool ("transaction_duplicate8",
+ &transaction_duplicate[7]),
+ 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_uint64 ("reserve_uuid5",
+ &reserve_uuid[4]),
+ GNUNET_PQ_result_spec_uint64 ("reserve_uuid6",
+ &reserve_uuid[5]),
+ GNUNET_PQ_result_spec_uint64 ("reserve_uuid7",
+ &reserve_uuid[6]),
+ GNUNET_PQ_result_spec_uint64 ("reserve_uuid8",
+ &reserve_uuid[7]),
+ 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);
+ TALER_payto_hash (reserves[4].sender_account_details,
+ &h_payto);
+ TALER_payto_hash (reserves[5].sender_account_details,
+ &h_payto);
+ TALER_payto_hash (reserves[6].sender_account_details,
+ &h_payto);
+ TALER_payto_hash (reserves[7].sender_account_details,
+ &h_payto);
+
+ qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "batch8_reserve_create",
+ params,
+ rs);
+ if (qs3 < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserves8 (%d)\n",
+ qs3);
+ results[0] = qs3;
+ return qs3;
+ }
+
+ 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]))
+ || ((! conflict[4]) && (transaction_duplicate[4]))
+ || ((! conflict[5]) && (transaction_duplicate[5]))
+ || ((! conflict[6]) && (transaction_duplicate[6]))
+ || ((! conflict[7]) && (transaction_duplicate[7]))
+ )
+ {
+ GNUNET_break (0);
+ TEH_PG_rollback (pg);
+ results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ return qs3;
}
enum GNUNET_DB_QueryStatus
TEH_PG_reserves_in_insert (void *cls,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_Amount *balance,
- struct GNUNET_TIME_Timestamp execution_time,
- const char *sender_account_details,
- const char *exchange_account_section,
- uint64_t wire_ref)
+ 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;
- struct TALER_EXCHANGEDB_Reserve reserve;
+ 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;
- uint64_t reserve_uuid;
+ struct TALER_PaytoHashP h_payto;
+ uint64_t reserve_uuid[reserves_length];
+ bool transaction_duplicate[reserves_length];
+ bool need_update = false;
+ bool t_duplicate = 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;
+ }
- reserve.pub = *reserve_pub;
expiry = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (execution_time.abs_time,
+ 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 (reserve_pub),
+ 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++)
{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- TALER_PQ_query_param_amount (balance),
- GNUNET_PQ_query_param_timestamp (&expiry),
- GNUNET_PQ_query_param_timestamp (&gc),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
- &reserve_uuid),
- GNUNET_PQ_result_spec_end
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Reserve does not exist; creating a new one\n");
- /* Note: query uses 'on conflict do nothing' */
- PREPARE (pg,
- "reserve_create",
- "INSERT INTO reserves "
- "(reserve_pub"
- ",current_balance_val"
- ",current_balance_frac"
- ",expiration_date"
- ",gc_date"
- ") VALUES "
- "($1, $2, $3, $4, $5)"
- " ON CONFLICT DO NOTHING"
- " RETURNING reserve_uuid;");
- qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "reserve_create",
- params,
- rs);
- if (qs1 < 0)
- return qs1;
+ const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+
+ notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
}
- /* Create new incoming transaction, "ON CONFLICT DO NOTHING"
- is again used to guard against duplicates. */
+ unsigned int i = 0;
+
+ while (i < reserves_length)
{
- enum GNUNET_DB_QueryStatus qs2;
- enum GNUNET_DB_QueryStatus qs3;
- struct TALER_PaytoHashP h_payto;
-
- qs3 = TEH_PG_setup_wire_target (pg,
- sender_account_details,
- &h_payto);
- if (qs3 < 0)
- return qs3;
- /* We do not have the UUID, so insert by public key */
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
- GNUNET_PQ_query_param_uint64 (&wire_ref),
- TALER_PQ_query_param_amount (balance),
- GNUNET_PQ_query_param_string (exchange_account_section),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_timestamp (&execution_time),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "reserves_in_add_transaction",
- "INSERT INTO reserves_in "
- "(reserve_pub"
- ",wire_reference"
- ",credit_val"
- ",credit_frac"
- ",exchange_account_section"
- ",wire_source_h_payto"
- ",execution_date"
- ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
- " ON CONFLICT DO NOTHING;");
- qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reserves_in_add_transaction",
- params);
- /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */
- if (0 >= qs2)
+ unsigned int bs = GNUNET_MIN (batch_size,
+ reserves_length - i);
+ if (bs >= 8)
{
- if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) &&
- (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) )
+ qs1 = insert8 (pg,
+ &reserves[i],
+ expiry,
+ gc,
+ h_payto,
+ &notify_s[i],
+ reserve_expiration,
+ &transaction_duplicate[i],
+ &conflicts[i],
+ &reserve_uuid[i],
+ &results[i]);
+
+ if (qs1<0)
{
- /* Conflict for the transaction, but the reserve was
- just now created, that should be impossible. */
- GNUNET_break (0); /* should be impossible: reserve was fresh,
- but transaction already known */
- return GNUNET_DB_STATUS_HARD_ERROR;
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserve batch_8 (%d)\n",
+ qs1);
+ return qs1;
}
- /* Transaction was already known or error. We are finished. */
- return qs2;
+ need_update |= conflicts[i];
+ need_update |= conflicts[i + 1];
+ need_update |= conflicts[i + 2];
+ need_update |= conflicts[i + 3];
+ need_update |= conflicts[i + 4];
+ need_update |= conflicts[i + 5];
+ need_update |= conflicts[i + 6];
+ need_update |= conflicts[i + 7];
+ t_duplicate |= transaction_duplicate[i];
+ t_duplicate |= transaction_duplicate[i + 1];
+ t_duplicate |= transaction_duplicate[i + 2];
+ t_duplicate |= transaction_duplicate[i + 3];
+ t_duplicate |= transaction_duplicate[i + 4];
+ t_duplicate |= transaction_duplicate[i + 5];
+ t_duplicate |= transaction_duplicate[i + 6];
+ t_duplicate |= transaction_duplicate[i + 7];
+ i += 8;
+ continue;
}
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1)
- {
- /* New reserve, we are finished */
- notify_on_reserve (pg,
- reserve_pub);
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
+ switch (bs)
+ {
+ case 7:
+ case 6:
+ case 5:
+ case 4:
+ qs4 = insert4 (pg,
+ &reserves[i],
+ expiry,
+ gc,
+ h_payto,
+ &notify_s[i],
+ reserve_expiration,
+ &transaction_duplicate[i],
+ &conflicts[i],
+ &reserve_uuid[i],
+ &results[i]);
- /* we were wrong with our optimistic assumption:
- reserve did already exist, need to do an update instead */
+ if (qs4<0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserve batch_4 (%d)\n",
+ qs4);
+ return qs4;
+ }
+ need_update |= conflicts[i];
+ need_update |= conflicts[i + 1];
+ need_update |= conflicts[i + 2];
+ need_update |= conflicts[i + 3];
+ t_duplicate |= transaction_duplicate[i];
+ t_duplicate |= transaction_duplicate[i + 1];
+ t_duplicate |= transaction_duplicate[i + 2];
+ t_duplicate |= transaction_duplicate[i + 3];
+ // fprintf(stdout, "reserve_uuid : %ld %ld %ld %ld\n", reserve_uuid[i], reserve_uuid[i+1], reserve_uuid[i+2], reserve_uuid[i+3]);
+ i += 4;
+ break;
+ 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],
+ &results[i]);
+ if (qs5<0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserve batch_2 (%d)\n",
+ qs5);
+ return qs5;
+ }
+ need_update |= conflicts[i];
+ need_update |= conflicts[i + 1];
+ t_duplicate |= transaction_duplicate[i];
+ t_duplicate |= transaction_duplicate[i + 1];
+ results[i] = (t_duplicate)
+ ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ // fprintf(stdout, "reserve_uuid : %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],
+ &results[i]);
+ if (qs2<0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to create reserve batch_1 (%d)\n)"
+ ,qs2);
+ return qs2;
+ }
+ need_update |= conflicts[i];
+ t_duplicate |= transaction_duplicate[i];
+ // fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], conflicts[i], transaction_duplicate[i]);
+ i += 1;
+ break;
+ case 0:
+ GNUNET_assert (0);
+ break;
+ }
+ } /* end while */
+ // commit
{
- /* We need to move away from 'read committed' to serializable.
- Also, we know that it should be safe to commit at this point.
- (We are only run in a larger transaction for performance.) */
enum GNUNET_DB_QueryStatus cs;
cs = TEH_PG_commit (pg);
if (cs < 0)
- return cs;
- if (GNUNET_OK !=
- TEH_PG_start (pg,
- "reserve-update-serializable"))
{
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to commit\n");
+ return cs;
}
}
+ if (! need_update)
{
- enum GNUNET_DB_QueryStatus reserve_exists;
-
- reserve_exists = TEH_PG_reserves_get (pg,
- &reserve);
- switch (reserve_exists)
+ goto exit;
+ }
+ // begin serializable
+ {
+ if (GNUNET_OK !=
+ TEH_PG_start (pg,
+ "reserve-insert-continued"))
{
- case GNUNET_DB_STATUS_HARD_ERROR:
GNUNET_break (0);
- return reserve_exists;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return reserve_exists;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* First we got a conflict, but then we cannot select? Very strange. */
- GNUNET_break (0);
- return GNUNET_DB_STATUS_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* continued below */
- break;
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
}
+ enum GNUNET_DB_QueryStatus qs3;
+ PREPARE (pg,
+ "reserves_update",
+ "SELECT"
+ " out_duplicate AS duplicate "
+ "FROM exchange_do_batch_reserves_update"
+ " ($1,$2,$3,$4,$5,$6,$7,$8);");
+ for (unsigned int i = 0; i<reserves_length; i++)
{
- struct TALER_EXCHANGEDB_Reserve updated_reserve;
- enum GNUNET_DB_QueryStatus qs3;
-
- /* If the reserve already existed, we need to still update the
- balance; we do this after checking for duplication, as
- otherwise we might have to actually pay the cost to roll this
- back for duplicate transactions; like this, we should virtually
- never actually have to rollback anything. */
- updated_reserve.pub = reserve.pub;
- if (0 >
- TALER_amount_add (&updated_reserve.balance,
- &reserve.balance,
- balance))
+ if (! conflicts[i])
+ continue;
{
- /* currency overflow or incompatible currency */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Attempt to deposit incompatible amount into reserve\n");
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry,
- reserve.expiry);
- updated_reserve.gc = GNUNET_TIME_timestamp_max (gc,
- reserve.gc);
- qs3 = TEH_PG_reserves_update (pg,
- &updated_reserve);
- switch (qs3)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return qs3;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return qs3;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* How can the UPDATE not work here? Very strange. */
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* continued below */
- break;
+ bool duplicate;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
+ GNUNET_PQ_query_param_timestamp (&expiry),
+ GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
+ TALER_PQ_query_param_amount (reserves[i].balance),
+ GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_string (notify_s[i]),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("duplicate",
+ &duplicate),
+ GNUNET_PQ_result_spec_end
+ };
+ qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "reserves_update",
+ params,
+ rs);
+ if (qs3<0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to update reserves (%d)\n",
+ qs3);
+ results[i] = qs3;
+ return qs3;
+ }
+ results[i] = duplicate
+ ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
}
- notify_on_reserve (pg,
- reserve_pub);
- /* Go back to original transaction mode */
+
{
enum GNUNET_DB_QueryStatus cs;
cs = TEH_PG_commit (pg);
if (cs < 0)
return cs;
- if (GNUNET_OK !=
- TEH_PG_start_read_committed (pg,
- "reserve-insert-continued"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
}
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+
+exit:
+ for (unsigned int i = 0; i<reserves_length; i++)
+ GNUNET_free (notify_s[i]);
+
+ return reserves_length;
}
diff --git a/src/exchangedb/pg_reserves_in_insert.h b/src/exchangedb/pg_reserves_in_insert.h
index 854019386..f92843e79 100644
--- a/src/exchangedb/pg_reserves_in_insert.h
+++ b/src/exchangedb/pg_reserves_in_insert.h
@@ -24,28 +24,26 @@
#include "taler_util.h"
#include "taler_json_lib.h"
#include "taler_exchangedb_plugin.h"
+
+
/**
* Insert an incoming transaction into reserves. New reserves are also
- * created through this function. Started within the scope of an ongoing
- * transaction.
+ * created through this function. Runs its own transaction(s).
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve_pub public key of the reserve
- * @param balance the amount that has to be added to the reserve
- * @param execution_time when was the amount added
- * @param sender_account_details account information for the sender (payto://-URL)
- * @param exchange_account_section name of the section in the configuration for the exchange's
- * account into which the deposit was made
- * @param wire_ref unique reference identifying the wire transfer
+ * @param reserves array of reserves to insert
+ * @param reserves_length length of the @a reserves array
+ * @param batch_size how many inserts to do in one go
+ * @param[out] results set to query status per reserve, must be of length @a reserves_length
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
-TEH_PG_reserves_in_insert (void *cls,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_Amount *balance,
- struct GNUNET_TIME_Timestamp execution_time,
- const char *sender_account_details,
- const char *exchange_account_section,
- uint64_t wire_ref);
+TEH_PG_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_select_refunds_by_coin.c b/src/exchangedb/pg_select_refunds_by_coin.c
index 255cac342..7325b3597 100644
--- a/src/exchangedb/pg_select_refunds_by_coin.c
+++ b/src/exchangedb/pg_select_refunds_by_coin.c
@@ -129,7 +129,7 @@ TEH_PG_select_refunds_by_coin (
if (-2 == percent_refund)
{
- const char *mode = getenv ("NEW_LOGIC");
+ const char *mode = getenv ("TALER_POSTGRES_SELECT_REFUNDS_BY_COIN_LOGIC");
char dummy;
if ( (NULL==mode) ||
@@ -137,14 +137,13 @@ TEH_PG_select_refunds_by_coin (
"%d%c",
&percent_refund,
&dummy)) )
- {
- if (NULL != mode)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Bad mode `%s' specified\n",
- mode);
- }
- if (NULL==mode)
- percent_refund=0;
+ {
+ if (NULL != mode)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Bad mode `%s' specified\n",
+ mode);
+ percent_refund = 0;
+ }
}
switch (percent_refund)
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index a6e932211..b201ef554 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -203,8 +203,6 @@
#include "pg_reserves_update.h"
#include "pg_setup_wire_target.h"
#include "pg_compute_shard.h"
-#include "pg_batch_reserves_in_insert.h"
-#include "pg_batch2_reserves_in_insert.h"
#include "pg_insert_kyc_attributes.h"
#include "pg_update_kyc_attributes.h"
#include "pg_select_similar_kyc_attributes.h"
@@ -747,10 +745,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_select_purse_by_merge_pub;
plugin->set_purse_balance
= &TEH_PG_set_purse_balance;
- plugin->batch_reserves_in_insert
- = &TEH_PG_batch_reserves_in_insert;
- plugin->batch2_reserves_in_insert
- = &TEH_PG_batch2_reserves_in_insert;
plugin->insert_kyc_attributes
= &TEH_PG_insert_kyc_attributes;
plugin->update_kyc_attributes
diff --git a/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c b/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
deleted file mode 100644
index 1a1c60f31..000000000
--- a/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- 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/>
-*/
-/**
- * @file exchangedb/test_exchangedb_by_j.c
- * @brief test cases for DB interaction functions
- * @author Joseph Xu
- */
-#include "platform.h"
-#include "taler_exchangedb_lib.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-
-/**o
- * Global result from the testcase.
- */
-static int result;
-
-/**
- * Report line of error if @a cond is true, and jump to label "drop".
- */
-#define FAILIF(cond) \
- do { \
- if (! (cond)) {break;} \
- GNUNET_break (0); \
- goto drop; \
- } while (0)
-
-
-/**
- * Initializes @a ptr with random data.
- */
-#define RND_BLK(ptr) \
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
-
-/**
- * Initializes @a ptr with zeros.
- */
-#define ZR_BLK(ptr) \
- memset (ptr, 0, sizeof (*ptr))
-
-
-/**
- * Currency we use. Must match test-exchange-db-*.conf.
- */
-#define CURRENCY "EUR"
-
-/**
- * Database plugin under test.
- */
-static struct TALER_EXCHANGEDB_Plugin *plugin;
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure with config
- */
-static void
-run (void *cls)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- const uint32_t num_partitions = 10;
-
- if (NULL ==
- (plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
- {
- GNUNET_break (0);
- result = 77;
- return;
- }
- (void) plugin->drop_tables (plugin->cls);
- if (GNUNET_OK !=
- plugin->create_tables (plugin->cls,
- true,
- num_partitions))
- {
- GNUNET_break (0);
- result = 77;
- goto cleanup;
- }
-
- for (unsigned int i = 0; i< 8; i++)
- {
- 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;
- struct GNUNET_TIME_Relative duration;
- struct TALER_ReservePublicKeyP reserve_pubs[batch_size];
- struct TALER_EXCHANGEDB_ReserveInInfo reserves[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 k = 0; k<batch_size; k++)
- {
- RND_BLK (&reserve_pubs[k]);
- reserves[k].reserve_pub = &reserve_pubs[k];
- 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;
- }
- FAILIF (batch_size !=
- plugin->batch_reserves_in_insert (plugin->cls,
- reserves,
- batch_size,
- results));
-
-
- 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 ==
- plugin->drop_tables (plugin->cls));
-cleanup:
- TALER_EXCHANGEDB_plugin_unload (plugin);
- plugin = NULL;
-}
-
-
-int
-main (int argc,
- char *const argv[])
-{
- const char *plugin_name;
- char *config_filename;
- char *testname;
- struct GNUNET_CONFIGURATION_Handle *cfg;
- (void) argc;
- result = -1;
- if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
- {
- GNUNET_break (0);
- return -1;
- }
-
- GNUNET_log_setup (argv[0],
- "WARNING",
- NULL);
- plugin_name++;
- (void) GNUNET_asprintf (&testname,
- "test-exchange-db-%s",
- plugin_name);
- (void) GNUNET_asprintf (&config_filename,
- "%s.conf",
- testname);
- fprintf (stdout,
- "Using config: %s\n",
- config_filename);
- cfg = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_parse (cfg,
- config_filename))
- {
- GNUNET_break (0);
- GNUNET_free (config_filename);
- GNUNET_free (testname);
- return 2;
- }
- GNUNET_SCHEDULER_run (&run,
- cfg);
- GNUNET_CONFIGURATION_destroy (cfg);
- GNUNET_free (config_filename);
- GNUNET_free (testname);
- return result;
-}
-
-/* end of test_exchangedb_by_j.c */
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 3e40c985e..50a5c0efe 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -3480,46 +3480,6 @@ struct TALER_EXCHANGEDB_Plugin
/**
- * Insert a incoming transaction into reserves. New reserves are
- * also created through this function.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param reserve_pub public key of the reserve
- * @param balance the amount that has to be added to the reserve
- * @param execution_time when was the amount added
- * @param sender_account_details information about the sender's bank account, in payto://-format
- * @param wire_reference unique reference identifying the wire transfer
- * @return transaction status code
- */
- enum GNUNET_DB_QueryStatus
- (*reserves_in_insert)(void *cls,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_Amount *balance,
- struct GNUNET_TIME_Timestamp execution_time,
- const char *sender_account_details,
- const char *exchange_account_name,
- uint64_t wire_reference);
-
-
- /**
- * Insert a batch of incoming transaction into reserves. New reserves are
- * also created through this function.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param reserves
- * @param reserves_length length of the @a reserves array
- * @param[out] results array of transaction status codes of length @a reserves_length,
- * set to the status of the
- */
- enum GNUNET_DB_QueryStatus
- (*batch_reserves_in_insert)(
- void *cls,
- const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
- unsigned int reserves_length,
- enum GNUNET_DB_QueryStatus *results);
-
-
- /**
* Insert a batch of incoming transaction into reserves. New reserves are
* also created through this function.
*
@@ -3530,7 +3490,7 @@ struct TALER_EXCHANGEDB_Plugin
* set to the status of the
*/
enum GNUNET_DB_QueryStatus
- (*batch2_reserves_in_insert)(
+ (*reserves_in_insert)(
void *cls,
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
unsigned int reserves_length,
@@ -4102,13 +4062,6 @@ struct TALER_EXCHANGEDB_Plugin
char **payto_uri);
-/**
- * Maximum number of results we return from iterate_matching_deposits().
- *
- * Limit on the number of transactions we aggregate at once.
- */
-#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000
-
/**
* Aggregate all matching deposits for @a h_payto and
* @a merchant_pub, returning the total amounts.