add locking to avoid transaction retries

This commit is contained in:
Christian Grothoff 2019-06-05 21:26:27 +02:00
parent 466a7b7018
commit 2f0015b803
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 46 additions and 13 deletions

View File

@ -739,6 +739,12 @@ postgres_prepare (PGconn *db_conn)
" WHERE reserve_pub=$1"
" FOR UPDATE;",
1),
/* Lock withdraw table; NOTE: we may want to eventually shard the
deposit table to avoid this lock being the main point of
contention limiting transaction performance. */
GNUNET_PQ_make_prepare ("lock_withdraw",
"LOCK TABLE reserves_out;",
0),
/* Used in #postgres_insert_withdraw_info() to store
the signature of a blinded coin with the blinded coin's
details before returning it during /reserve/withdraw. We store
@ -1039,7 +1045,12 @@ postgres_prepare (PGconn *db_conn)
" WHERE refund_serial_id>=$1"
" ORDER BY refund_serial_id ASC;",
1),
/* Lock deposit table; NOTE: we may want to eventually shard the
deposit table to avoid this lock being the main point of
contention limiting transaction performance. */
GNUNET_PQ_make_prepare ("lock_deposit",
"LOCK TABLE deposits;",
0),
/* Store information about a /deposit the exchange is to execute.
Used in #postgres_insert_deposit(). */
GNUNET_PQ_make_prepare ("insert_deposit",
@ -2380,6 +2391,9 @@ postgres_get_withdraw_info (void *cls,
const struct GNUNET_HashCode *h_blind,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
{
struct GNUNET_PQ_QueryParam no_params[] = {
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (h_blind),
GNUNET_PQ_query_param_end
@ -2399,7 +2413,12 @@ postgres_get_withdraw_info (void *cls,
&collectable->withdraw_fee),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
if (0 > (qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
"lock_withdraw",
no_params)))
return qs;
collectable->h_coin_envelope = *h_blind;
return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
"get_withdraw_info",
@ -2876,6 +2895,9 @@ postgres_have_deposit (void *cls,
GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam no_params[] = {
GNUNET_PQ_query_param_end
};
struct TALER_EXCHANGEDB_Deposit deposit2;
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_result_spec_amount ("amount_with_fee",
@ -2892,6 +2914,10 @@ postgres_have_deposit (void *cls,
};
enum GNUNET_DB_QueryStatus qs;
if (0 > (qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
"lock_deposit",
no_params)))
return qs;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Getting deposits for coin %s\n",
TALER_B2S (&deposit->coin.coin_pub));

View File

@ -1995,6 +1995,10 @@ run (void *cls)
result = 10;
deposit2 = deposit;
FAILIF (GNUNET_OK !=
plugin->start (plugin->cls,
session,
"test-2"));
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->have_deposit (plugin->cls,
@ -2010,6 +2014,9 @@ run (void *cls)
GNUNET_YES));
FAILIF (GNUNET_OK !=
test_melting (session));
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
plugin->commit (plugin->cls,
session));
/* test insert_refund! */