[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-exchange] 02/04: some modifications, there is one error which dis
From: |
gnunet |
Subject: |
[taler-exchange] 02/04: some modifications, there is one error which display (no function matches the given name and argument types) |
Date: |
Mon, 21 Nov 2022 16:40:15 +0100 |
This is an automated email from the git hooks/post-receive script.
joseph-xu pushed a commit to branch master
in repository exchange.
commit b9ccfbd66b192e11766f4129bae65c16fddffc5a
Author: Joseph <Joseph.xu@efrei.net>
AuthorDate: Fri Nov 18 11:18:45 2022 -0500
some modifications, there is one error which display (no function matches
the given name and argument types)
---
...by_j.c => perf_exchangedb_reserves_in_insert.c} | 25 ++-
src/exchangedb/pg_batch_reserves_in_insert.c | 195 ++++-----------------
src/exchangedb/pg_batch_reserves_in_insert.h | 1 +
src/exchangedb/plugin_exchangedb_postgres.c | 2 +
src/exchangedb/procedures.sql | 150 +++++++++++-----
src/exchangedb/test_exchangedb_by_j.c | 11 +-
6 files changed, 154 insertions(+), 230 deletions(-)
diff --git a/src/exchangedb/test_exchangedb_by_j.c
b/src/exchangedb/perf_exchangedb_reserves_in_insert.c
similarity index 89%
copy from src/exchangedb/test_exchangedb_by_j.c
copy to src/exchangedb/perf_exchangedb_reserves_in_insert.c
index 175691e9..6c91b6bc 100644
--- a/src/exchangedb/test_exchangedb_by_j.c
+++ b/src/exchangedb/perf_exchangedb_reserves_in_insert.c
@@ -107,8 +107,8 @@ run (void *cls)
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Timestamp ts;
struct GNUNET_TIME_Relative duration;
- struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
- enum GNUNET_DB_QueryStatus *results;
+ struct TALER_ReservePublicKeyP reserve_pub;
+
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.000010",
&value));
@@ -118,19 +118,16 @@ run (void *cls)
"test_by_exchange_j");
for (unsigned int k = 0; k<batch_size; k++)
{
- RND_BLK (&reserves[k].reserve_pub);
- reserves[k].balance = value;
- reserves[k].execution_time = ts;
- reserves[k].sender_account_details = sndr;
- reserves[k].exchange_account_name = "name";
+ RND_BLK (&reserve_pub);
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->reserves_in_insert (plugin->cls,
+ &reserve_pub,
+ &value,
+ ts,
+ sndr,
+ "section",
+ 4));
}
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->batch_reserves_in_insert (plugin->cls,
- reserves,
- batch_size,
- &results));
-
-
plugin->commit (plugin->cls);
duration = GNUNET_TIME_absolute_get_duration (now);
fprintf (stdout,
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.c
b/src/exchangedb/pg_batch_reserves_in_insert.c
index d7ce47dc..216de96b 100644
--- a/src/exchangedb/pg_batch_reserves_in_insert.c
+++ b/src/exchangedb/pg_batch_reserves_in_insert.c
@@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file exchangedb/pg_bash_reserves_in_insert.c
+ * @file exchangedb/pg_batch_reserves_in_insert.c
* @brief Implementation of the reserves_in_insert function for Postgres
* @author JOSEPHxu
*/
@@ -70,7 +70,12 @@ TEH_PG_batch_reserves_in_insert (void *cls,
struct TALER_EXCHANGEDB_Reserve reserve;
struct GNUNET_TIME_Timestamp expiry;
struct GNUNET_TIME_Timestamp gc;
+ struct TALER_PaytoHashP h_payto;
uint64_t reserve_uuid;
+ bool conflicted;
+ bool transaction_duplicate;
+ struct GNUNET_TIME_Timestamp reserve_expiration
+ = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
reserve.pub = reserves->reserve_pub;
expiry = GNUNET_TIME_absolute_to_timestamp (
@@ -91,15 +96,28 @@ TEH_PG_batch_reserves_in_insert (void *cls,
the 'add' operation needs the reserve entry as a foreign key. */
{
struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&(reserves->reserve_pub)),
- TALER_PQ_query_param_amount (&(reserves->balance)),
- GNUNET_PQ_query_param_timestamp (&expiry),
- GNUNET_PQ_query_param_timestamp (&gc),
+ GNUNET_PQ_query_param_auto_from_type (&reserves->reserve_pub), /*$1*/
+ TALER_PQ_query_param_amount (&reserves->balance), /*$2+3*/
+ GNUNET_PQ_query_param_timestamp (&expiry), /*$4*/
+ GNUNET_PQ_query_param_timestamp (&gc), /*$5*/
+ GNUNET_PQ_query_param_uint64 (&reserves->wire_reference), /*6*/
+ TALER_PQ_query_param_amount (&reserves->balance), /*7+8*/
+ GNUNET_PQ_query_param_string (reserves->exchange_account_name), /*9*/
+ GNUNET_PQ_query_param_timestamp (&reserves->execution_time), /*10*/
+ GNUNET_PQ_query_param_auto_from_type (&h_payto), /*11*/
+ GNUNET_PQ_query_param_string (reserves->sender_account_details),/*12*/
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),/*13*/
GNUNET_PQ_query_param_end
};
+
+ /* We should get all our results into results[]*/
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
&reserve_uuid),
+ GNUNET_PQ_result_spec_bool ("conflicted",
+ &conflicted),
+ GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+ &transaction_duplicate),
GNUNET_PQ_result_spec_end
};
@@ -108,7 +126,12 @@ TEH_PG_batch_reserves_in_insert (void *cls,
/* Note: query uses 'on conflict do nothing' */
PREPARE (pg,
"reserve_create",
- "SELECT bash_reserves_in('34', '20','//asdddfs3', '60',
'20'),bash_reserves_in('24', '10','//dfs3', '40', '50'),bash_reserves_in('42',
'40','//d43', '40', '50'),bash_reserves_in('44', '10','//ghs3', '40', '50') AS
existed from reserves;");
+ "SELECT "
+ "out_reserve_found AS conflicted"
+ ",transaction_duplicate"
+ ",ruuid"
+ " FROM batch_reserves_in"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"reserve_create",
@@ -118,167 +141,9 @@ TEH_PG_batch_reserves_in_insert (void *cls,
return qs1;
}
- /* Create new incoming transaction, "ON CONFLICT DO NOTHING"
- is again used to guard against duplicates. */
- {
- enum GNUNET_DB_QueryStatus qs2;
- enum GNUNET_DB_QueryStatus qs3;
- struct TALER_PaytoHashP h_payto;
-
- qs3 = TEH_PG_setup_wire_target (pg,
- reserves->sender_account_details,
- &h_payto);
- if (qs3 < 0)
- return qs3;
- /* We do not have the UUID, so insert by public key */
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
- GNUNET_PQ_query_param_uint64 (&(reserves->wire_reference)),
- TALER_PQ_query_param_amount (&(reserves->balance)),
- GNUNET_PQ_query_param_string (reserves->exchange_account_name),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_timestamp (&reserves->execution_time),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "reserves_in_add_transaction",
- "INSERT INTO reserves_in "
- "(reserve_pub"
- ",wire_reference"
- ",credit_val"
- ",credit_frac"
- ",exchange_account_section"
- ",wire_source_h_payto"
- ",execution_date"
- ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
- " ON CONFLICT DO NOTHING;");
- qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reserves_in_add_transaction",
- params);
- /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */
- if (0 >= qs2)
- {
- if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) &&
- (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) )
- {
- /* Conflict for the transaction, but the reserve was
- just now created, that should be impossible. */
- GNUNET_break (0); /* should be impossible: reserve was fresh,
- but transaction already known */
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- /* Transaction was already known or error. We are finished. */
- return qs2;
- }
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1)
- {
- /* New reserve, we are finished */
- notify_on_reserve (pg,
- &(reserves->reserve_pub));
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
-
- /* we were wrong with our optimistic assumption:
- reserve did already exist, need to do an update instead */
- {
- /* We need to move away from 'read committed' to serializable.
- Also, we know that it should be safe to commit at this point.
- (We are only run in a larger transaction for performance.) */
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TEH_PG_commit(pg);
- if (cs < 0)
- return cs;
- if (GNUNET_OK !=
- TEH_PG_start (pg,
- "reserve-update-serializable"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
- {
- enum GNUNET_DB_QueryStatus reserve_exists;
-
- reserve_exists = TEH_PG_reserves_get (pg,
- &reserve);
- switch (reserve_exists)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return reserve_exists;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return reserve_exists;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* First we got a conflict, but then we cannot select? Very strange. */
- GNUNET_break (0);
- return GNUNET_DB_STATUS_SOFT_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* continued below */
- break;
- }
- }
-
- {
- struct TALER_EXCHANGEDB_Reserve updated_reserve;
- enum GNUNET_DB_QueryStatus qs3;
-
- /* If the reserve already existed, we need to still update the
- balance; we do this after checking for duplication, as
- otherwise we might have to actually pay the cost to roll this
- back for duplicate transactions; like this, we should virtually
- never actually have to rollback anything. */
- updated_reserve.pub = reserve.pub;
- if (0 >
- TALER_amount_add (&updated_reserve.balance,
- &reserve.balance,
- &reserves->balance))
- {
- /* currency overflow or incompatible currency */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Attempt to deposit incompatible amount into reserve\n");
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry,
- reserve.expiry);
- updated_reserve.gc = GNUNET_TIME_timestamp_max (gc,
- reserve.gc);
- qs3 = TEH_PG_reserves_update (pg,
- &updated_reserve);
- switch (qs3)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return qs3;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return qs3;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* How can the UPDATE not work here? Very strange. */
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* continued below */
- break;
- }
- }
notify_on_reserve (pg,
&reserves->reserve_pub);
- /* Go back to original transaction mode */
- {
- enum GNUNET_DB_QueryStatus cs;
- cs = TEH_PG_commit (pg);
- if (cs < 0)
- return cs;
- if (GNUNET_OK !=
- TEH_PG_start_read_committed (pg,
- "reserve-insert-continued"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
+
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.h
b/src/exchangedb/pg_batch_reserves_in_insert.h
index 9422096d..76679567 100644
--- a/src/exchangedb/pg_batch_reserves_in_insert.h
+++ b/src/exchangedb/pg_batch_reserves_in_insert.h
@@ -31,4 +31,5 @@ TEH_PG_batch_reserves_in_insert (void *cls,
const struct TALER_EXCHANGEDB_ReserveInInfo
*reserves,
unsigned int reserves_length,
enum GNUNET_DB_QueryStatus *results);
+
#endif
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c
b/src/exchangedb/plugin_exchangedb_postgres.c
index 11421700..5b59d4b0 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -5446,8 +5446,10 @@ 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;
+
return plugin;
}
diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql
index a9d90294..1e96301a 100644
--- a/src/exchangedb/procedures.sql
+++ b/src/exchangedb/procedures.sql
@@ -2520,62 +2520,120 @@ BEGIN
policy_details_serial_id = out_policy_details_serial_id;
END $$;
-COMMIT;
-
-/*************************************************************/
-
-
-CREATE OR REPLACE FUNCTION bash_reserves_in(
- IN amount_val INT8,
- IN amount_frac INT4,
- IN rpub BYTEA,
- IN now INT8,
- IN min_reserve_gc INT8,
- OUT reserve_found BOOLEAN,
+CREATE OR REPLACE FUNCTION batch_reserves_in(
+ IN in_reserve_pub BYTEA,
+ IN in_current_balance_val INT8,
+ IN in_current_balance_frac INT4,
+ IN in_expiration_date INT8,
+ IN in_gc_date INT8,
+ IN in_wire_ref INT8,
+ IN in_credit_val INT8,
+ IN in_credit_frac INT4,
+ IN in_exchange_account_name VARCHAR,
+ IN in_exectution_date INT4,
+ IN in_wire_source_h_payto BYTEA, ---h_payto
+ IN in_payto_uri VARCHAR,
+ IN in_reserve_expiration INT8,
+ OUT out_reserve_found BOOLEAN,
+ OUT transaction_duplicate BOOLEAN,
OUT ruuid INT8)
LANGUAGE plpgsql
AS $$
DECLARE
- existed BOOLEAN;
- not_existed BOOLEAN;
+ my_amount_val INT8;
+DECLARE
+ my_amount_frac INT4;
BEGIN
- SELECT reserves.reserve_uuid into ruuid from reserves
- where reserves.reserve_pub = rpub;
- IF ruuid IS NOT NULL
- THEN
- existed = TRUE;
- UPDATE reserves
- SET (current_balance_val
- ,current_balance_frac
- ,expiration_date
- ,gc_date) =
- (amount_val
- ,amount_frac
- ,now
- ,min_reserve_gc)
- WHERE
- reserve_pub = rpub
- RETURNING existed into reserve_found;
- END IF;
- IF NOT FOUND
- THEN
- SELECT MAX(reserve_uuid)+1 into ruuid from reserves;
- existed = FALSE;
- INSERT INTO reserves
- (reserve_uuid
- ,reserve_pub
+
+ SELECT
+ current_balance_val
+ ,current_balance_frac
+ INTO
+ my_amount_val
+ ,my_amount_frac
+ FROM reserves
+ WHERE reserves.reserve_pub = in_reserve_pub;
+
+ INSERT INTO reserves
+ (reserve_pub
,current_balance_val
,current_balance_frac
,expiration_date
,gc_date)
VALUES
- (ruuid
- ,rpub
- ,amount_val
- ,amount_frac
- ,now
- ,min_reserve_gc) RETURNING existed into reserve_found;
-
+ (in_reserve_pub
+ ,in_current_balance_val
+ ,in_current_balance_frac
+ ,in_expiration_date
+ ,in_gc_date)
+ ON CONFLICT DO NOTHING
+ RETURNING reserves.reserve_uuid INTO ruuid;
+
+ --IF THE INSERT WAS NOT SUCCESSFUL, REMEMBER IT
+ IF NOT FOUND
+ THEN
+ out_reserve_found = FALSE;
+ ELSE
+ out_reserve_found = TRUE;
END IF;
+ --SIMPLE INSERT ON CONFLICT DO NOTHING
+ INSERT INTO wire_targets
+ (wire_target_h_payto
+ ,payto_uri)
+ VALUES
+ (in_wire_source_h_payto
+ ,in_payto_uri)
+ ON CONFLICT DO NOTHING;
+
+ INSERT INTO reserves_in
+ (reserve_pub
+ ,wire_reference
+ ,credit_val
+ ,credit_frac
+ ,exchange_account_section
+ ,wire_source_h_payto
+ ,execution_date)
+ VALUES
+ (in_reserve_pub
+ ,in_wire_ref
+ ,in_current_balance_val
+ ,in_credit_frac
+ ,in_exchange_account_section
+ ,in_wire_source_h_payto
+ ,in_execution_date);
+
+ --IF THE INSERTION WAS A SUCCESS IT MEANS NO DUPLICATED TRANSACTION
+ IF FOUND
+ THEN
+ transaction_duplicate = FALSE;
+ IF out_reserve_found = TRUE
+ THEN
+ UPDATE reserves
+ SET
+ in_current_balance_frac=in_current_balance_frac+my_amount_frac
+ - CASE
+ WHEN in_current_balance_frac + my_amount_frac >= 100000000
+ THEN 100000000
+ ELSE 0
+ END
+ ,in_current_balance_val=in_current_balance_val+my_amount_val
+ + CASE
+ WHEN in_current_balance_frac + my_amount_frac >= 100000000
+ THEN 1
+ ELSE 0
+ END
+
,expiration_date=GREATEST(in_expiration_date,in_reserve_expiration)
+ ,gc_date=GREATEST(in_gc_date,in_reserve_expiration)
+ WHERE reserves.reserve_pub=in_reserve_pub;
+ RETURN;
+ ELSE
+ RETURN;
+ END IF;
+ ELSE
+ transaction_duplicate = TRUE;
+ RETURN;
+ END IF;
END $$;
+
+COMMIT;
diff --git a/src/exchangedb/test_exchangedb_by_j.c
b/src/exchangedb/test_exchangedb_by_j.c
index 175691e9..eb600103 100644
--- a/src/exchangedb/test_exchangedb_by_j.c
+++ b/src/exchangedb/test_exchangedb_by_j.c
@@ -33,7 +33,7 @@ static int result;
*/
#define FAILIF(cond) \
do { \
- if (! (cond)) { break;} \
+ if (! (cond)) {break;} \
GNUNET_break (0); \
goto drop; \
} while (0)
@@ -108,14 +108,15 @@ run (void *cls)
struct GNUNET_TIME_Timestamp ts;
struct GNUNET_TIME_Relative duration;
struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
- enum GNUNET_DB_QueryStatus *results;
+ 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 ();
plugin->start (plugin->cls,
- "test_by_exchange_j");
+ "test_by_j");
+
for (unsigned int k = 0; k<batch_size; k++)
{
RND_BLK (&reserves[k].reserve_pub);
@@ -123,13 +124,13 @@ run (void *cls)
reserves[k].execution_time = ts;
reserves[k].sender_account_details = sndr;
reserves[k].exchange_account_name = "name";
+
}
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->batch_reserves_in_insert (plugin->cls,
reserves,
batch_size,
- &results));
-
+ results));
plugin->commit (plugin->cls);
duration = GNUNET_TIME_absolute_get_duration (now);
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.