diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-06-05 21:26:27 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-06-05 21:26:27 +0200 |
commit | 2f0015b80385364ffbacca71504a96a46db6f0e0 (patch) | |
tree | 251b2f5a0329c668fd75fda2ad367c29c2316dc1 /src/exchangedb | |
parent | 466a7b7018c0a53a27e1d431019f6b5f7b3562e4 (diff) | |
download | exchange-2f0015b80385364ffbacca71504a96a46db6f0e0.tar.xz |
add locking to avoid transaction retries
Diffstat (limited to 'src/exchangedb')
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 34 | ||||
-rw-r--r-- | src/exchangedb/test_exchangedb.c | 7 |
2 files changed, 37 insertions, 4 deletions
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 35b9aa57d..9788c67ab 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -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,12 +2413,17 @@ 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", - params, - rs); + "get_withdraw_info", + params, + rs); } @@ -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)); diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index db40f3653..cab05f08c 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -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! */ |