add locking to avoid transaction retries
This commit is contained in:
parent
466a7b7018
commit
2f0015b803
@ -215,8 +215,8 @@ deposit_transaction (void *cls,
|
|||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
tl);
|
tl);
|
||||||
qs = TEH_plugin->insert_deposit (TEH_plugin->cls,
|
qs = TEH_plugin->insert_deposit (TEH_plugin->cls,
|
||||||
session,
|
session,
|
||||||
deposit);
|
deposit);
|
||||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Failed to store /deposit information in database\n");
|
TALER_LOG_WARNING ("Failed to store /deposit information in database\n");
|
||||||
|
@ -59,7 +59,7 @@ reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection,
|
|||||||
struct TALER_Amount balance;
|
struct TALER_Amount balance;
|
||||||
|
|
||||||
json_history = TEH_RESPONSE_compile_reserve_history (rh,
|
json_history = TEH_RESPONSE_compile_reserve_history (rh,
|
||||||
&balance);
|
&balance);
|
||||||
if ((NULL == json_history)
|
if ((NULL == json_history)
|
||||||
/* Address the case where the ptr is not null, but
|
/* Address the case where the ptr is not null, but
|
||||||
* it fails "internally" to dump as string (= corrupted). */
|
* it fails "internally" to dump as string (= corrupted). */
|
||||||
@ -180,9 +180,9 @@ struct WithdrawContext
|
|||||||
*/
|
*/
|
||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
withdraw_transaction (void *cls,
|
withdraw_transaction (void *cls,
|
||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
int *mhd_ret)
|
int *mhd_ret)
|
||||||
{
|
{
|
||||||
struct WithdrawContext *wc = cls;
|
struct WithdrawContext *wc = cls;
|
||||||
struct TALER_EXCHANGEDB_Reserve r;
|
struct TALER_EXCHANGEDB_Reserve r;
|
||||||
@ -197,9 +197,9 @@ withdraw_transaction (void *cls,
|
|||||||
wc->collectable.sig.rsa_signature = NULL;
|
wc->collectable.sig.rsa_signature = NULL;
|
||||||
#endif
|
#endif
|
||||||
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
|
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
|
||||||
session,
|
session,
|
||||||
&wc->wsrd.h_coin_envelope,
|
&wc->wsrd.h_coin_envelope,
|
||||||
&wc->collectable);
|
&wc->collectable);
|
||||||
if (0 > qs)
|
if (0 > qs)
|
||||||
{
|
{
|
||||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||||
|
@ -739,6 +739,12 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
" WHERE reserve_pub=$1"
|
" WHERE reserve_pub=$1"
|
||||||
" FOR UPDATE;",
|
" FOR UPDATE;",
|
||||||
1),
|
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
|
/* Used in #postgres_insert_withdraw_info() to store
|
||||||
the signature of a blinded coin with the blinded coin's
|
the signature of a blinded coin with the blinded coin's
|
||||||
details before returning it during /reserve/withdraw. We store
|
details before returning it during /reserve/withdraw. We store
|
||||||
@ -1039,7 +1045,12 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
" WHERE refund_serial_id>=$1"
|
" WHERE refund_serial_id>=$1"
|
||||||
" ORDER BY refund_serial_id ASC;",
|
" ORDER BY refund_serial_id ASC;",
|
||||||
1),
|
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.
|
/* Store information about a /deposit the exchange is to execute.
|
||||||
Used in #postgres_insert_deposit(). */
|
Used in #postgres_insert_deposit(). */
|
||||||
GNUNET_PQ_make_prepare ("insert_deposit",
|
GNUNET_PQ_make_prepare ("insert_deposit",
|
||||||
@ -2380,6 +2391,9 @@ postgres_get_withdraw_info (void *cls,
|
|||||||
const struct GNUNET_HashCode *h_blind,
|
const struct GNUNET_HashCode *h_blind,
|
||||||
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
|
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
|
||||||
{
|
{
|
||||||
|
struct GNUNET_PQ_QueryParam no_params[] = {
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
GNUNET_PQ_query_param_auto_from_type (h_blind),
|
GNUNET_PQ_query_param_auto_from_type (h_blind),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
@ -2399,12 +2413,17 @@ postgres_get_withdraw_info (void *cls,
|
|||||||
&collectable->withdraw_fee),
|
&collectable->withdraw_fee),
|
||||||
GNUNET_PQ_result_spec_end
|
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;
|
collectable->h_coin_envelope = *h_blind;
|
||||||
return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
|
return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
|
||||||
"get_withdraw_info",
|
"get_withdraw_info",
|
||||||
params,
|
params,
|
||||||
rs);
|
rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2876,6 +2895,9 @@ postgres_have_deposit (void *cls,
|
|||||||
GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
|
GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
};
|
};
|
||||||
|
struct GNUNET_PQ_QueryParam no_params[] = {
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
struct TALER_EXCHANGEDB_Deposit deposit2;
|
struct TALER_EXCHANGEDB_Deposit deposit2;
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
TALER_PQ_result_spec_amount ("amount_with_fee",
|
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||||
@ -2892,6 +2914,10 @@ postgres_have_deposit (void *cls,
|
|||||||
};
|
};
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
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,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Getting deposits for coin %s\n",
|
"Getting deposits for coin %s\n",
|
||||||
TALER_B2S (&deposit->coin.coin_pub));
|
TALER_B2S (&deposit->coin.coin_pub));
|
||||||
|
@ -1995,6 +1995,10 @@ run (void *cls)
|
|||||||
|
|
||||||
result = 10;
|
result = 10;
|
||||||
deposit2 = deposit;
|
deposit2 = deposit;
|
||||||
|
FAILIF (GNUNET_OK !=
|
||||||
|
plugin->start (plugin->cls,
|
||||||
|
session,
|
||||||
|
"test-2"));
|
||||||
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
|
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
|
||||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
@ -2010,6 +2014,9 @@ run (void *cls)
|
|||||||
GNUNET_YES));
|
GNUNET_YES));
|
||||||
FAILIF (GNUNET_OK !=
|
FAILIF (GNUNET_OK !=
|
||||||
test_melting (session));
|
test_melting (session));
|
||||||
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||||
|
plugin->commit (plugin->cls,
|
||||||
|
session));
|
||||||
|
|
||||||
|
|
||||||
/* test insert_refund! */
|
/* test insert_refund! */
|
||||||
|
Loading…
Reference in New Issue
Block a user