summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_track-transfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_track-transfer.c')
-rw-r--r--src/backend/taler-merchant-httpd_track-transfer.c118
1 files changed, 77 insertions, 41 deletions
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c
index 71fdda4e..d38cb662 100644
--- a/src/backend/taler-merchant-httpd_track-transfer.c
+++ b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2014, 2015, 2016 INRIA
+ (C) 2014-2017 INRIA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -37,6 +37,10 @@
*/
#define TRACK_TIMEOUT (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30))
+/**
+ * How often do we retry the simple INSERT database transaction?
+ */
+#define MAX_RETRIES 3
/**
* Context used for handing /track/transfer requests.
@@ -307,8 +311,9 @@ transform_response (const json_t *result,
GNUNET_CRYPTO_hash_from_string (key,
&h_key);
- if (NULL != (current_entry = GNUNET_CONTAINER_multihashmap_get (map,
- &h_key)))
+ if (NULL != (current_entry =
+ GNUNET_CONTAINER_multihashmap_get (map,
+ &h_key)))
{
/* The map already knows this h_contract_terms*/
if ( (GNUNET_SYSERR ==
@@ -496,8 +501,8 @@ wire_transfer_cb (void *cls,
const struct TALER_TrackTransferDetails *details)
{
struct TrackTransferContext *rctx = cls;
- int ret;
json_t *jresponse;
+ enum GNUNET_DB_QueryStatus qs;
rctx->wdh = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -515,17 +520,23 @@ wire_transfer_cb (void *cls,
"details", json));
return;
}
-
- if (GNUNET_OK !=
- db->store_transfer_to_proof (db->cls,
- rctx->uri,
- &rctx->wtid,
- execution_time,
- exchange_pub,
- json))
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
+ {
+ qs = db->store_transfer_to_proof (db->cls,
+ rctx->uri,
+ &rctx->wtid,
+ execution_time,
+ exchange_pub,
+ json);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (0 > qs)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to persist wire transfer proof in DB\n");
+ /* Special report if retries insufficient */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
resume_track_transfer_with_response
(rctx,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -540,16 +551,19 @@ wire_transfer_cb (void *cls,
rctx->current_offset = i;
rctx->current_detail = &details[i];
rctx->check_transfer_result = GNUNET_NO;
- ret = db->find_payments_by_hash_and_coin (db->cls,
- &details[i].h_contract_terms,
- &rctx->mi->pubkey,
- &details[i].coin_pub,
- &check_transfer,
- rctx);
- if (GNUNET_SYSERR == ret)
+ qs = db->find_payments_by_hash_and_coin (db->cls,
+ &details[i].h_contract_terms,
+ &rctx->mi->pubkey,
+ &details[i].coin_pub,
+ &check_transfer,
+ rctx);
+ if (0 > qs)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to obtain existing payment data from DB\n");
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
resume_track_transfer_with_response
(rctx,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -558,7 +572,7 @@ wire_transfer_cb (void *cls,
"details", "failed to obtain deposit data from local database"));
return;
}
- if (GNUNET_NO == ret)
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
/* The exchange says we made this deposit, but WE do not
recall making it! Well, let's say thanks and accept the
@@ -596,14 +610,21 @@ wire_transfer_cb (void *cls,
}
/* Response is consistent with the /deposit we made, remember
it for future reference */
- ret = db->store_coin_to_transfer (db->cls,
- &details[i].h_contract_terms,
- &details[i].coin_pub,
- &rctx->wtid);
- if (GNUNET_OK != ret)
+ for (unsigned int i=0;i<MAX_RETRIES;i++)
+ {
+ qs = db->store_coin_to_transfer (db->cls,
+ &details[i].h_contract_terms,
+ &details[i].coin_pub,
+ &rctx->wtid);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (0 > qs)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to persist coin to wire transfer mapping in DB\n");
+ /* Special report if retries insufficient */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
resume_track_transfer_with_response
(rctx,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -618,7 +639,9 @@ wire_transfer_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"About to call tracks transformator.\n");
- if (NULL == (jresponse = transform_response (json, rctx)))
+ if (NULL == (jresponse =
+ transform_response (json,
+ rctx)))
{
resume_track_transfer_with_response
(rctx,
@@ -712,12 +735,14 @@ proof_cb (void *cls,
struct TrackTransferContext *rctx = cls;
json_t *transformed_response;
- if (NULL == (transformed_response = transform_response (proof,
- rctx)))
+ if (NULL == (transformed_response =
+ transform_response (proof,
+ rctx)))
{
rctx->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- rctx->response = TMH_RESPONSE_make_internal_error (TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR,
- "Fail to elaborate response.");
+ rctx->response
+ = TMH_RESPONSE_make_internal_error (TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR,
+ "Fail to elaborate response.");
return;
}
@@ -751,6 +776,7 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
const char *uri;
const char *instance_str;
int ret;
+ enum GNUNET_DB_QueryStatus qs;
if (NULL == *connection_cls)
{
@@ -835,11 +861,21 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
}
/* Check if reply is already in database! */
- ret = db->find_proof_by_wtid (db->cls,
- rctx->uri,
- &rctx->wtid,
- &proof_cb,
- rctx);
+ qs = db->find_proof_by_wtid (db->cls,
+ rctx->uri,
+ &rctx->wtid,
+ &proof_cb,
+ rctx);
+ if (0 > qs)
+ {
+ /* Simple select queries should not cause serialization issues */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ return TMH_RESPONSE_reply_internal_error (connection,
+ TALER_EC_TRACK_TRANSFER_DB_FETCH_FAILED,
+ "Fail to query database about proofs");
+ }
if (0 != rctx->response_code)
{
ret = MHD_queue_response (connection,