diff --git a/contrib/gana b/contrib/gana index 836cdc706..f6948ba8f 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 836cdc706d849ec5965b3b7795fcefe95344a969 +Subproject commit f6948ba8fbcdfb648ed78ee81a392922ded36b99 diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c index 8b48e67fd..bbccd5688 100644 --- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c +++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c @@ -444,6 +444,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection, MHD_RESULT ret; struct TEH_KeyStateHandle *ksh; uint64_t melt_serial_id; + enum GNUNET_DB_QueryStatus qs; memset (dks, 0, sizeof (dks)); memset (rrcs, 0, sizeof (rrcs)); @@ -768,11 +769,20 @@ clean_age: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signatures ready, starting DB interaction\n"); - // FIXME: do all this (and the above) in ONE DB transaction! - /* Persist operation result in DB */ + for (unsigned int r = 0; rstart (TEH_plugin->cls, + "insert_refresh_reveal batch")) + { + GNUNET_break (0); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_START_FAILED, + NULL); + goto cleanup; + } for (unsigned int i = 0; inum_fresh_coins; i++) { struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i]; @@ -786,18 +796,47 @@ clean_age: TALER_CNC_KAPPA - 1, rctx->transfer_privs, &rctx->gamma_tp); + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + { + TEH_plugin->rollback (TEH_plugin->cls); + continue; + } /* 0 == qs is ok, as we did not check for repeated requests */ - if (0 > qs) + if (GNUNET_DB_STATUS_HARD_ERROR == qs) { GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls); ret = TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, "insert_refresh_reveal"); goto cleanup; } + qs = TEH_plugin->commit (TEH_plugin->cls); + if (qs >= 0) + break; /* success */ + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_COMMIT_FAILED, + NULL); + goto cleanup; + } + TEH_plugin->rollback (TEH_plugin->cls); + } + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + { + GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_SOFT_FAILURE, + NULL); + goto cleanup; } - /* Generate final (positive) response */ ret = reply_refreshes_reveal_success (connection, num_fresh_coins, diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 1839b13be..4175678a5 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -1263,7 +1263,8 @@ prepare_statements (struct PostgresClosure *pg) ") SELECT $1, $2, $3, " " denominations_serial, $5, $6, $7, $8" " FROM denominations" - " WHERE denom_pub_hash=$4;", + " WHERE denom_pub_hash=$4" + " ON CONFLICT DO NOTHING;", 8), /* Obtain information about the coins created in a refresh operation, used in #postgres_get_refresh_reveal() */ @@ -1293,7 +1294,8 @@ prepare_statements (struct PostgresClosure *pg) "(melt_serial_id" ",transfer_pub" ",transfer_privs" - ") VALUES ($1, $2, $3);", + ") VALUES ($1, $2, $3)" + " ON CONFLICT DO NOTHING;", 3), /* Used in #postgres_insert_refund() to store refund information */ GNUNET_PQ_make_prepare ( diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index f95ba75a4..52e684f62 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -635,8 +635,8 @@ struct TALER_EXCHANGEDB_Reserve struct TALER_EXCHANGEDB_DenominationKeyMetaData { /** - * Start time of the validity period for this key. - */ + * Start time of the validity period for this key. + */ struct GNUNET_TIME_Timestamp start; /**