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
This commit is contained in:
parent
e66087987f
commit
ab03ba16e9
@ -491,389 +491,6 @@ 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.
|
||||
@ -883,7 +500,7 @@ process_reply_batched (const struct TALER_BANK_CreditDetails *details,
|
||||
* @param details_length length of the @a details array
|
||||
*/
|
||||
static void
|
||||
process_reply_batched2 (unsigned int batch_size,
|
||||
process_reply (unsigned int batch_size,
|
||||
const struct TALER_BANK_CreditDetails *details,
|
||||
unsigned int details_length)
|
||||
{
|
||||
@ -950,7 +567,7 @@ 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,
|
||||
qs = db_plugin->reserves_in_insert (db_plugin->cls,
|
||||
reserves,
|
||||
details_length,
|
||||
batch_size,
|
||||
@ -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,
|
||||
process_reply (batch_mode,
|
||||
reply->details.success.details,
|
||||
reply->details.success.details_length);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case MHD_HTTP_NO_CONTENT:
|
||||
transaction_completed ();
|
||||
|
16
src/exchangedb/.gitignore
vendored
16
src/exchangedb/.gitignore
vendored
@ -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
|
||||
|
@ -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)
|
||||
;
|
||||
|
@ -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,21 +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 = \
|
||||
libtalerexchangedb.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/pq/libtalerpq.la \
|
||||
-ljansson \
|
||||
-lgnunetjson \
|
||||
-lgnunetutil \
|
||||
$(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_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 \
|
||||
@ -384,9 +336,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_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 \
|
||||
@ -397,9 +349,22 @@ 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_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 \
|
||||
$(top_builddir)/src/pq/libtalerpq.la \
|
||||
-ljansson \
|
||||
-lgnunetjson \
|
||||
-lgnunetutil \
|
||||
-lm \
|
||||
$(XLIB)
|
||||
|
||||
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 \
|
||||
|
@ -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"
|
||||
@ -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.
|
||||
*
|
||||
@ -245,16 +249,12 @@ 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
|
||||
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);
|
||||
@ -265,7 +265,6 @@ run (void *cls)
|
||||
struct TALER_BlindedPlanchet *bp;
|
||||
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
//5 KEY PAIR
|
||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||
now,
|
||||
&value,
|
||||
@ -309,7 +308,6 @@ run (void *cls)
|
||||
}
|
||||
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
NUM_ROWS);
|
||||
//BEGIN
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
"Transaction"));
|
||||
@ -362,12 +360,12 @@ run (void *cls)
|
||||
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,
|
||||
@ -396,9 +394,9 @@ run (void *cls)
|
||||
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,
|
||||
@ -408,11 +406,11 @@ run (void *cls)
|
||||
if (ROUNDS == i)
|
||||
TALER_denom_sig_free (&depos[i].coin.denom_sig);
|
||||
}
|
||||
/* End of benchmark setup */
|
||||
GNUNET_free(perm);
|
||||
// commit
|
||||
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++)
|
||||
{
|
||||
@ -420,19 +418,21 @@ run (void *cls)
|
||||
struct GNUNET_TIME_Relative duration;
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
char *payto_uri;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
time = GNUNET_TIME_absolute_get ();
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_ready_deposit (plugin->cls,
|
||||
qs = plugin->get_ready_deposit (plugin->cls,
|
||||
0,
|
||||
INT32_MAX,
|
||||
&merchant_pub,
|
||||
&payto_uri));
|
||||
|
||||
&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;
|
||||
}
|
||||
@ -454,8 +454,7 @@ run (void *cls)
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -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,
|
||||
{
|
||||
char *testname;
|
||||
|
||||
GNUNET_asprintf (&testname,
|
||||
"test-exchange-db-%s",
|
||||
plugin_name);
|
||||
(void) GNUNET_asprintf (&config_filename,
|
||||
GNUNET_asprintf (&config_filename,
|
||||
"%s.conf",
|
||||
testname);
|
||||
fprintf (stdout,
|
||||
"Using config: %s\n",
|
||||
config_filename);
|
||||
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 */
|
@ -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"
|
||||
@ -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.
|
||||
@ -256,9 +258,7 @@ 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 *);
|
||||
|
||||
@ -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,17 +289,19 @@ 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];
|
||||
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_EXCHANGEDB_RefreshRevealedCoin *revealed_coin =
|
||||
&revealed_coins[p];
|
||||
struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
|
||||
struct TALER_BlindedRsaPlanchet *rp = &bp->details.rsa_blinded_planchet;
|
||||
|
||||
@ -316,7 +317,8 @@ run (void *cls)
|
||||
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,
|
||||
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,
|
||||
@ -324,7 +326,10 @@ run (void *cls)
|
||||
&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,
|
||||
&new_dkp[(unsigned
|
||||
int) rand ()
|
||||
% MELT_NEW_COINS]->
|
||||
priv,
|
||||
true,
|
||||
bp));
|
||||
GNUNET_assert (
|
||||
@ -341,7 +346,8 @@ run (void *cls)
|
||||
&bks,
|
||||
&c_hash,
|
||||
&alg_values,
|
||||
&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub));
|
||||
&new_dkp[(unsigned int) rand ()
|
||||
% MELT_NEW_COINS]->pub));
|
||||
{
|
||||
/* ENSURE_COIN_KNOWN */
|
||||
struct TALER_DenominationHashP dph;
|
||||
@ -418,10 +424,8 @@ run (void *cls)
|
||||
}
|
||||
/* End of benchmark setup */
|
||||
GNUNET_free (perm);
|
||||
// commit
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->commit (plugin->cls));
|
||||
/**** CALL GET LINK DATA ****/
|
||||
for (unsigned int r = 0; r< ROUNDS; r++)
|
||||
{
|
||||
struct GNUNET_TIME_Absolute time;
|
||||
@ -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;
|
||||
}
|
||||
@ -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,
|
@ -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.
|
||||
*/
|
||||
@ -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++)
|
||||
{
|
||||
for (unsigned int i = 0;
|
||||
i< sizeof(batches) / sizeof(*batches);
|
||||
i++)
|
||||
{
|
||||
static unsigned int batches[] = {1, 1, 0, 2, 4, 16, 64, 256};
|
||||
const char *sndr = "payto://x-taler-bank/localhost:8080/1";
|
||||
struct TALER_Amount value;
|
||||
unsigned int batch_size = batches[i];
|
||||
struct TALER_Amount value;
|
||||
struct GNUNET_TIME_Absolute now;
|
||||
struct GNUNET_TIME_Timestamp ts;
|
||||
unsigned long long duration_sq;
|
||||
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++)
|
||||
{
|
||||
plugin->start (plugin->cls,
|
||||
"test_by_exchange_j");
|
||||
for (unsigned int k = 0; k<batch_size; k++)
|
||||
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_pub);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->reserves_in_insert (plugin->cls,
|
||||
&reserve_pub,
|
||||
&value,
|
||||
ts,
|
||||
sndr,
|
||||
"section",
|
||||
4));
|
||||
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;
|
||||
}
|
||||
plugin->commit (plugin->cls);
|
||||
FAILIF (lcm !=
|
||||
plugin->reserves_in_insert (plugin->cls,
|
||||
reserves,
|
||||
lcm,
|
||||
batch_size,
|
||||
results));
|
||||
}
|
||||
duration = GNUNET_TIME_absolute_get_duration (now);
|
||||
times[i] = GNUNET_TIME_relative_add (times[i],
|
||||
duration);
|
||||
duration_sq = duration.rel_value_us * duration.rel_value_us;
|
||||
GNUNET_assert (duration_sq / duration.rel_value_us ==
|
||||
duration.rel_value_us);
|
||||
GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]);
|
||||
sqrs[i] += duration_sq;
|
||||
} /* 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 */
|
@ -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"
|
||||
@ -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))
|
||||
{
|
||||
@ -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,15 +278,11 @@ 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
|
||||
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);
|
||||
@ -289,7 +293,6 @@ run (void *cls)
|
||||
struct TALER_BlindedPlanchet *bp;
|
||||
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
//5 KEY PAIR
|
||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||
now,
|
||||
&value,
|
||||
@ -334,7 +337,6 @@ run (void *cls)
|
||||
|
||||
perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
NUM_ROWS);
|
||||
// begin
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
"Transaction"));
|
||||
@ -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,
|
||||
@ -374,10 +374,10 @@ run (void *cls)
|
||||
&h_wire_wt);
|
||||
depos[i].timestamp = ts;
|
||||
uint64_t known_coin_id;
|
||||
{//ENSURE_COIN_KNOWN
|
||||
|
||||
{
|
||||
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,
|
||||
@ -400,7 +400,8 @@ run (void *cls)
|
||||
bool gone;
|
||||
bool conflict;
|
||||
unsigned int refund_percent = 0;
|
||||
switch (refund_percent){
|
||||
switch (refund_percent)
|
||||
{
|
||||
case 2: // 100% refund
|
||||
ref[i].coin = depos[i].coin;
|
||||
ref[i].details.merchant_pub = depos[i].merchant_pub;
|
||||
@ -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;
|
||||
}
|
||||
@ -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,
|
||||
{
|
||||
char *testname;
|
||||
|
||||
GNUNET_asprintf (&testname,
|
||||
"test-exchange-db-%s",
|
||||
plugin_name);
|
||||
(void) GNUNET_asprintf (&config_filename,
|
||||
GNUNET_asprintf (&config_filename,
|
||||
"%s.conf",
|
||||
testname);
|
||||
fprintf (stdout,
|
||||
"Using config: %s\n",
|
||||
config_filename);
|
||||
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 */
|
@ -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
|
||||
@ -75,23 +75,13 @@ TEH_PG_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"
|
||||
|
@ -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,
|
||||
¬ify_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,
|
||||
¬ify_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,
|
||||
¬ify_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,
|
||||
¬ify_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;
|
||||
}
|
@ -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
|
@ -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,
|
||||
¬ify_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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -55,7 +55,7 @@ struct LinkDataContext
|
||||
/**
|
||||
* Status, set to #GNUNET_SYSERR on errors,
|
||||
*/
|
||||
int status;
|
||||
enum GNUNET_GenericReturnValue status;
|
||||
};
|
||||
|
||||
|
||||
@ -195,11 +195,9 @@ TEH_PG_get_link_data (void *cls,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Bad mode `%s' specified\n",
|
||||
mode);
|
||||
}
|
||||
if (NULL==mode)
|
||||
percent_refund = 0;
|
||||
}
|
||||
|
||||
}
|
||||
switch (percent_refund)
|
||||
{
|
||||
case 0:
|
||||
@ -300,5 +298,3 @@ TEH_PG_get_link_data (void *cls,
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,22 +50,13 @@ 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",
|
||||
@ -75,155 +67,53 @@ TEH_PG_get_ready_deposit (void *cls,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Bad mode `%s' specified\n",
|
||||
mode);
|
||||
}
|
||||
if (NULL==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)"
|
||||
" FROM deposits dep"
|
||||
" JOIN wire_targets wt"
|
||||
" USING (wire_target_h_payto)"
|
||||
" WHERE dbr.wire_deadline<=$1"
|
||||
" AND dbr.shard >= $2"
|
||||
" AND dbr.shard <= $3"
|
||||
" 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"
|
||||
" 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"
|
||||
" ,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"
|
||||
" merchant_pub"
|
||||
",wire_target_h_payto"
|
||||
" FROM wire_targets"
|
||||
" FROM deposits"
|
||||
" 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"
|
||||
" 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)"
|
||||
);
|
||||
" wt.payto_uri"
|
||||
",rc.merchant_pub"
|
||||
" FROM wire_targets wt"
|
||||
" JOIN rc"
|
||||
" USING (wire_target_h_payto);");
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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) ||
|
||||
@ -142,10 +142,9 @@ TEH_PG_select_refunds_by_coin (
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Bad mode `%s' specified\n",
|
||||
mode);
|
||||
}
|
||||
if (NULL==mode)
|
||||
percent_refund = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (percent_refund)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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 */
|
@ -3479,28 +3479,6 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
struct TALER_PaytoHashP *h_payto);
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -3512,25 +3490,7 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
* 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.
|
||||
*
|
||||
* @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
|
||||
(*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.
|
||||
|
Loading…
Reference in New Issue
Block a user