implement retries for a few more commands
This commit is contained in:
parent
1ee55ea838
commit
96c2fb8e10
@ -398,18 +398,20 @@ run (void *cls,
|
|||||||
create_reserve_label,
|
create_reserve_label,
|
||||||
AMOUNT_5,
|
AMOUNT_5,
|
||||||
MHD_HTTP_OK));
|
MHD_HTTP_OK));
|
||||||
unit[1] = TALER_TESTING_cmd_deposit
|
unit[1] =
|
||||||
("deposit",
|
TALER_TESTING_cmd_deposit_with_retry
|
||||||
is->exchange,
|
(TALER_TESTING_cmd_deposit
|
||||||
withdraw_label,
|
("deposit",
|
||||||
0, /* Index of the one withdrawn coin in the traits. */
|
is->exchange,
|
||||||
TALER_TESTING_make_wire_details
|
withdraw_label,
|
||||||
(USER_ACCOUNT_NUMBER,
|
0, /* Index of the one withdrawn coin in the traits. */
|
||||||
exchange_bank_account.hostname),
|
TALER_TESTING_make_wire_details
|
||||||
order_enc,
|
(USER_ACCOUNT_NUMBER,
|
||||||
GNUNET_TIME_UNIT_ZERO,
|
exchange_bank_account.hostname),
|
||||||
AMOUNT_1,
|
order_enc,
|
||||||
MHD_HTTP_OK);
|
GNUNET_TIME_UNIT_ZERO,
|
||||||
|
AMOUNT_1,
|
||||||
|
MHD_HTTP_OK));
|
||||||
|
|
||||||
if (eval_probability (REFRESH_PROBABILITY))
|
if (eval_probability (REFRESH_PROBABILITY))
|
||||||
{
|
{
|
||||||
@ -424,22 +426,28 @@ run (void *cls,
|
|||||||
"refresh-reveal-%u-%u",
|
"refresh-reveal-%u-%u",
|
||||||
i,
|
i,
|
||||||
j);
|
j);
|
||||||
unit[2] = TALER_TESTING_cmd_refresh_melt
|
unit[2] =
|
||||||
(melt_label,
|
TALER_TESTING_cmd_refresh_melt_with_retry
|
||||||
is->exchange,
|
(TALER_TESTING_cmd_refresh_melt
|
||||||
AMOUNT_4,
|
(melt_label,
|
||||||
withdraw_label,
|
is->exchange,
|
||||||
MHD_HTTP_OK);
|
AMOUNT_4,
|
||||||
unit[3] = TALER_TESTING_cmd_refresh_reveal
|
withdraw_label,
|
||||||
(reveal_label,
|
MHD_HTTP_OK));
|
||||||
is->exchange,
|
unit[3] =
|
||||||
melt_label,
|
TALER_TESTING_cmd_refresh_reveal_with_retry
|
||||||
MHD_HTTP_OK);
|
(TALER_TESTING_cmd_refresh_reveal
|
||||||
unit[4] = TALER_TESTING_cmd_refresh_link
|
(reveal_label,
|
||||||
("refresh-link",
|
is->exchange,
|
||||||
is->exchange,
|
melt_label,
|
||||||
reveal_label,
|
MHD_HTTP_OK));
|
||||||
MHD_HTTP_OK);
|
unit[4] =
|
||||||
|
TALER_TESTING_cmd_refresh_link_with_retry
|
||||||
|
(TALER_TESTING_cmd_refresh_link
|
||||||
|
("refresh-link",
|
||||||
|
is->exchange,
|
||||||
|
reveal_label,
|
||||||
|
MHD_HTTP_OK));
|
||||||
unit[5] = TALER_TESTING_cmd_end ();
|
unit[5] = TALER_TESTING_cmd_end ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -81,11 +81,6 @@ struct DepositState
|
|||||||
*/
|
*/
|
||||||
struct TALER_EXCHANGE_DepositHandle *dh;
|
struct TALER_EXCHANGE_DepositHandle *dh;
|
||||||
|
|
||||||
/**
|
|
||||||
* Expected HTTP response code.
|
|
||||||
*/
|
|
||||||
unsigned int expected_response_code;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interpreter state.
|
* Interpreter state.
|
||||||
*/
|
*/
|
||||||
@ -95,8 +90,60 @@ struct DepositState
|
|||||||
* Exchange connection.
|
* Exchange connection.
|
||||||
*/
|
*/
|
||||||
struct TALER_EXCHANGE_Handle *exchange;
|
struct TALER_EXCHANGE_Handle *exchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to try later.
|
||||||
|
*/
|
||||||
|
struct GNUNET_SCHEDULER_Task *retry_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long do we wait until we retry?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Relative backoff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected HTTP response code.
|
||||||
|
*/
|
||||||
|
unsigned int expected_response_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we retry on (transient) failures?
|
||||||
|
*/
|
||||||
|
int do_retry;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the command.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param cmd the command to execute.
|
||||||
|
* @param is the interpreter state.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
deposit_run (void *cls,
|
||||||
|
const struct TALER_TESTING_Command *cmd,
|
||||||
|
struct TALER_TESTING_Interpreter *is);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to re-try #deposit_run.
|
||||||
|
*
|
||||||
|
* @param cls a `struct DepositState`
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
do_retry (void *cls)
|
||||||
|
{
|
||||||
|
struct DepositState *ds = cls;
|
||||||
|
|
||||||
|
ds->retry_task = NULL;
|
||||||
|
deposit_run (ds,
|
||||||
|
NULL,
|
||||||
|
ds->is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to analyze the /deposit response, just used to
|
* Callback to analyze the /deposit response, just used to
|
||||||
* check if the response code is acceptable.
|
* check if the response code is acceptable.
|
||||||
@ -120,6 +167,27 @@ deposit_cb (void *cls,
|
|||||||
ds->dh = NULL;
|
ds->dh = NULL;
|
||||||
if (ds->expected_response_code != http_status)
|
if (ds->expected_response_code != http_status)
|
||||||
{
|
{
|
||||||
|
if (GNUNET_YES == ds->do_retry)
|
||||||
|
{
|
||||||
|
if ( (0 == http_status) ||
|
||||||
|
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
|
||||||
|
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Retrying deposit failed with %u/%d\n",
|
||||||
|
http_status,
|
||||||
|
(int) ec);
|
||||||
|
/* on DB conflicts, do not use backoff */
|
||||||
|
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
|
||||||
|
ds->backoff = GNUNET_TIME_UNIT_ZERO;
|
||||||
|
else
|
||||||
|
ds->backoff = GNUNET_TIME_STD_BACKOFF (ds->backoff);
|
||||||
|
ds->retry_task = GNUNET_SCHEDULER_add_delayed (ds->backoff,
|
||||||
|
&do_retry,
|
||||||
|
ds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unexpected response code %u to command %s in %s:%u\n",
|
"Unexpected response code %u to command %s in %s:%u\n",
|
||||||
http_status,
|
http_status,
|
||||||
@ -324,7 +392,11 @@ deposit_cleanup (void *cls,
|
|||||||
TALER_EXCHANGE_deposit_cancel (ds->dh);
|
TALER_EXCHANGE_deposit_cancel (ds->dh);
|
||||||
ds->dh = NULL;
|
ds->dh = NULL;
|
||||||
}
|
}
|
||||||
|
if (NULL != ds->retry_task)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (ds->retry_task);
|
||||||
|
ds->retry_task = NULL;
|
||||||
|
}
|
||||||
json_decref (ds->wire_details);
|
json_decref (ds->wire_details);
|
||||||
GNUNET_free (ds);
|
GNUNET_free (ds);
|
||||||
}
|
}
|
||||||
@ -441,3 +513,25 @@ TALER_TESTING_cmd_deposit
|
|||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a deposit command to enable retries when we get transient
|
||||||
|
* errors from the exchange.
|
||||||
|
*
|
||||||
|
* @param cmd a deposit command
|
||||||
|
* @return the command with retries enabled
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_deposit_with_retry (struct TALER_TESTING_Command cmd)
|
||||||
|
{
|
||||||
|
struct DepositState *ds;
|
||||||
|
|
||||||
|
GNUNET_assert (&deposit_run == cmd.run);
|
||||||
|
ds = cmd.cls;
|
||||||
|
ds->do_retry = GNUNET_YES;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end of testing_api_cmd_deposit.c */
|
||||||
|
@ -55,19 +55,6 @@ struct MeltDetails
|
|||||||
struct RefreshMeltState
|
struct RefreshMeltState
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
* if set to GNUNET_YES, then two /refresh/melt operations
|
|
||||||
* will be performed. This is needed to trigger the logic
|
|
||||||
* that manages those already-made requests. Note: it
|
|
||||||
* is not possible to just copy-and-paste a test refresh melt
|
|
||||||
* CMD to have the same effect, because every data preparation
|
|
||||||
* generates new planchets that (in turn) make the whole "hash"
|
|
||||||
* different from any previous one, therefore NOT allowing the
|
|
||||||
* exchange to pick any previous /rerfesh/melt operation from
|
|
||||||
* the database.
|
|
||||||
*/
|
|
||||||
unsigned int double_melt;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about coins to be melted.
|
* Information about coins to be melted.
|
||||||
*/
|
*/
|
||||||
@ -78,11 +65,6 @@ struct RefreshMeltState
|
|||||||
*/
|
*/
|
||||||
char *refresh_data;
|
char *refresh_data;
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of bytes in @e refresh_data.
|
|
||||||
*/
|
|
||||||
size_t refresh_data_length;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to a previous melt command.
|
* Reference to a previous melt command.
|
||||||
*/
|
*/
|
||||||
@ -103,16 +85,49 @@ struct RefreshMeltState
|
|||||||
*/
|
*/
|
||||||
struct TALER_TESTING_Interpreter *is;
|
struct TALER_TESTING_Interpreter *is;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of the denomination public keys
|
||||||
|
* corresponding to the @e fresh_amounts.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to try later.
|
||||||
|
*/
|
||||||
|
struct GNUNET_SCHEDULER_Task *retry_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long do we wait until we retry?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Relative backoff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of bytes in @e refresh_data.
|
||||||
|
*/
|
||||||
|
size_t refresh_data_length;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected HTTP response code.
|
* Expected HTTP response code.
|
||||||
*/
|
*/
|
||||||
unsigned int expected_response_code;
|
unsigned int expected_response_code;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of the denomination public keys
|
* if set to #GNUNET_YES, then two /refresh/melt operations
|
||||||
* corresponding to the @e fresh_amounts.
|
* will be performed. This is needed to trigger the logic
|
||||||
|
* that manages those already-made requests. Note: it
|
||||||
|
* is not possible to just copy-and-paste a test refresh melt
|
||||||
|
* CMD to have the same effect, because every data preparation
|
||||||
|
* generates new planchets that (in turn) make the whole "hash"
|
||||||
|
* different from any previous one, therefore NOT allowing the
|
||||||
|
* exchange to pick any previous /rerfesh/melt operation from
|
||||||
|
* the database.
|
||||||
*/
|
*/
|
||||||
struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
unsigned int double_melt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we retry on (transient) failures?
|
||||||
|
*/
|
||||||
|
int do_retry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set by the melt callback as it comes from the exchange.
|
* Set by the melt callback as it comes from the exchange.
|
||||||
@ -136,13 +151,6 @@ struct RefreshRevealState
|
|||||||
*/
|
*/
|
||||||
struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
|
struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of fresh coins withdrawn, set by the
|
|
||||||
* reveal callback as it comes from the exchange,
|
|
||||||
* it is the length of the @e fresh_coins array.
|
|
||||||
*/
|
|
||||||
unsigned int num_fresh_coins;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience struct to keep in one place all the
|
* Convenience struct to keep in one place all the
|
||||||
* data related to one fresh coin, set by the reveal callback
|
* data related to one fresh coin, set by the reveal callback
|
||||||
@ -160,10 +168,33 @@ struct RefreshRevealState
|
|||||||
*/
|
*/
|
||||||
struct TALER_TESTING_Interpreter *is;
|
struct TALER_TESTING_Interpreter *is;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to try later.
|
||||||
|
*/
|
||||||
|
struct GNUNET_SCHEDULER_Task *retry_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long do we wait until we retry?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Relative backoff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of fresh coins withdrawn, set by the
|
||||||
|
* reveal callback as it comes from the exchange,
|
||||||
|
* it is the length of the @e fresh_coins array.
|
||||||
|
*/
|
||||||
|
unsigned int num_fresh_coins;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected HTTP response code.
|
* Expected HTTP response code.
|
||||||
*/
|
*/
|
||||||
unsigned int expected_response_code;
|
unsigned int expected_response_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we retry on (transient) failures?
|
||||||
|
*/
|
||||||
|
int do_retry;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -192,13 +223,59 @@ struct RefreshLinkState
|
|||||||
*/
|
*/
|
||||||
struct TALER_TESTING_Interpreter *is;
|
struct TALER_TESTING_Interpreter *is;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to try later.
|
||||||
|
*/
|
||||||
|
struct GNUNET_SCHEDULER_Task *retry_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long do we wait until we retry?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Relative backoff;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected HTTP response code.
|
* Expected HTTP response code.
|
||||||
*/
|
*/
|
||||||
unsigned int expected_response_code;
|
unsigned int expected_response_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we retry on (transient) failures?
|
||||||
|
*/
|
||||||
|
int do_retry;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the command.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param cmd the command to execute.
|
||||||
|
* @param is the interpreter state.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
refresh_reveal_run (void *cls,
|
||||||
|
const struct TALER_TESTING_Command *cmd,
|
||||||
|
struct TALER_TESTING_Interpreter *is);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to re-try #refresh_reveal_run.
|
||||||
|
*
|
||||||
|
* @param cls a `struct RefreshRevealState`
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
do_reveal_retry (void *cls)
|
||||||
|
{
|
||||||
|
struct RefreshRevealState *rrs = cls;
|
||||||
|
|
||||||
|
rrs->retry_task = NULL;
|
||||||
|
refresh_reveal_run (rrs,
|
||||||
|
NULL,
|
||||||
|
rrs->is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "refresh reveal" request callback; it checks that the response
|
* "refresh reveal" request callback; it checks that the response
|
||||||
* code is expected and copies into its command's state the data
|
* code is expected and copies into its command's state the data
|
||||||
@ -231,6 +308,27 @@ reveal_cb (void *cls,
|
|||||||
rrs->rrh = NULL;
|
rrs->rrh = NULL;
|
||||||
if (rrs->expected_response_code != http_status)
|
if (rrs->expected_response_code != http_status)
|
||||||
{
|
{
|
||||||
|
if (GNUNET_YES == rrs->do_retry)
|
||||||
|
{
|
||||||
|
if ( (0 == http_status) ||
|
||||||
|
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
|
||||||
|
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Retrying refresh reveal failed with %u/%d\n",
|
||||||
|
http_status,
|
||||||
|
(int) ec);
|
||||||
|
/* on DB conflicts, do not use backoff */
|
||||||
|
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
|
||||||
|
rrs->backoff = GNUNET_TIME_UNIT_ZERO;
|
||||||
|
else
|
||||||
|
rrs->backoff = GNUNET_TIME_STD_BACKOFF (rrs->backoff);
|
||||||
|
rrs->retry_task = GNUNET_SCHEDULER_add_delayed (rrs->backoff,
|
||||||
|
&do_reveal_retry,
|
||||||
|
rrs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unexpected response code %u/%d to command %s in %s:%u\n",
|
"Unexpected response code %u/%d to command %s in %s:%u\n",
|
||||||
http_status,
|
http_status,
|
||||||
@ -258,16 +356,18 @@ reveal_cb (void *cls,
|
|||||||
(num_coins, struct FreshCoin);
|
(num_coins, struct FreshCoin);
|
||||||
|
|
||||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||||
unsigned int i;
|
|
||||||
if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
|
if (GNUNET_OK !=
|
||||||
(melt_cmd, 0, &fresh_pks))
|
TALER_TESTING_get_trait_denom_pub (melt_cmd,
|
||||||
|
0,
|
||||||
|
&fresh_pks))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
TALER_TESTING_interpreter_fail (rrs->is);
|
TALER_TESTING_interpreter_fail (rrs->is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<num_coins; i++)
|
for (unsigned int i=0; i<num_coins; i++)
|
||||||
{
|
{
|
||||||
struct FreshCoin *fc = &rrs->fresh_coins[i];
|
struct FreshCoin *fc = &rrs->fresh_coins[i];
|
||||||
|
|
||||||
@ -352,6 +452,11 @@ refresh_reveal_cleanup (void *cls,
|
|||||||
TALER_EXCHANGE_refresh_reveal_cancel (rrs->rrh);
|
TALER_EXCHANGE_refresh_reveal_cancel (rrs->rrh);
|
||||||
rrs->rrh = NULL;
|
rrs->rrh = NULL;
|
||||||
}
|
}
|
||||||
|
if (NULL != rrs->retry_task)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (rrs->retry_task);
|
||||||
|
rrs->retry_task = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int j=0; j < rrs->num_fresh_coins; j++)
|
for (unsigned int j=0; j < rrs->num_fresh_coins; j++)
|
||||||
GNUNET_CRYPTO_rsa_signature_free (rrs->fresh_coins[j].sig.rsa_signature);
|
GNUNET_CRYPTO_rsa_signature_free (rrs->fresh_coins[j].sig.rsa_signature);
|
||||||
@ -362,6 +467,36 @@ refresh_reveal_cleanup (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the command.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param cmd the command to execute.
|
||||||
|
* @param is the interpreter state.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
refresh_link_run (void *cls,
|
||||||
|
const struct TALER_TESTING_Command *cmd,
|
||||||
|
struct TALER_TESTING_Interpreter *is);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to re-try #refresh_link_run.
|
||||||
|
*
|
||||||
|
* @param cls a `struct RefreshLinkState`
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
do_link_retry (void *cls)
|
||||||
|
{
|
||||||
|
struct RefreshLinkState *rls = cls;
|
||||||
|
|
||||||
|
rls->retry_task = NULL;
|
||||||
|
refresh_link_run (rls,
|
||||||
|
NULL,
|
||||||
|
rls->is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "refresh link" operation callback, checks that HTTP response
|
* "refresh link" operation callback, checks that HTTP response
|
||||||
* code is expected _and_ that all the linked coins were actually
|
* code is expected _and_ that all the linked coins were actually
|
||||||
@ -402,6 +537,27 @@ link_cb (void *cls,
|
|||||||
rls->rlh = NULL;
|
rls->rlh = NULL;
|
||||||
if (rls->expected_response_code != http_status)
|
if (rls->expected_response_code != http_status)
|
||||||
{
|
{
|
||||||
|
if (GNUNET_YES == rls->do_retry)
|
||||||
|
{
|
||||||
|
if ( (0 == http_status) ||
|
||||||
|
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
|
||||||
|
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Retrying refresh link failed with %u/%d\n",
|
||||||
|
http_status,
|
||||||
|
(int) ec);
|
||||||
|
/* on DB conflicts, do not use backoff */
|
||||||
|
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
|
||||||
|
rls->backoff = GNUNET_TIME_UNIT_ZERO;
|
||||||
|
else
|
||||||
|
rls->backoff = GNUNET_TIME_STD_BACKOFF (rls->backoff);
|
||||||
|
rls->retry_task = GNUNET_SCHEDULER_add_delayed (rls->backoff,
|
||||||
|
&do_link_retry,
|
||||||
|
rls);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unexpected response code %u/%d to command %s in %s:%u\n",
|
"Unexpected response code %u/%d to command %s in %s:%u\n",
|
||||||
http_status,
|
http_status,
|
||||||
@ -514,11 +670,9 @@ refresh_link_run (void *cls,
|
|||||||
const struct TALER_TESTING_Command *cmd,
|
const struct TALER_TESTING_Command *cmd,
|
||||||
struct TALER_TESTING_Interpreter *is)
|
struct TALER_TESTING_Interpreter *is)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct RefreshLinkState *rls = cls;
|
struct RefreshLinkState *rls = cls;
|
||||||
struct RefreshRevealState *rrs;
|
struct RefreshRevealState *rrs;
|
||||||
struct RefreshMeltState *rms;
|
struct RefreshMeltState *rms;
|
||||||
|
|
||||||
const struct TALER_TESTING_Command *reveal_cmd;
|
const struct TALER_TESTING_Command *reveal_cmd;
|
||||||
const struct TALER_TESTING_Command *melt_cmd;
|
const struct TALER_TESTING_Command *melt_cmd;
|
||||||
const struct TALER_TESTING_Command *coin_cmd;
|
const struct TALER_TESTING_Command *coin_cmd;
|
||||||
@ -605,6 +759,41 @@ refresh_link_cleanup (void *cls,
|
|||||||
TALER_EXCHANGE_refresh_link_cancel (rls->rlh);
|
TALER_EXCHANGE_refresh_link_cancel (rls->rlh);
|
||||||
rls->rlh = NULL;
|
rls->rlh = NULL;
|
||||||
}
|
}
|
||||||
|
if (NULL != rls->retry_task)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (rls->retry_task);
|
||||||
|
rls->retry_task = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the command.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param cmd the command to execute.
|
||||||
|
* @param is the interpreter state.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
refresh_melt_run (void *cls,
|
||||||
|
const struct TALER_TESTING_Command *cmd,
|
||||||
|
struct TALER_TESTING_Interpreter *is);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task scheduled to re-try #refresh_melt_run.
|
||||||
|
*
|
||||||
|
* @param cls a `struct RefreshMeltState`
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
do_melt_retry (void *cls)
|
||||||
|
{
|
||||||
|
struct RefreshMeltState *rms = cls;
|
||||||
|
|
||||||
|
rms->retry_task = NULL;
|
||||||
|
refresh_melt_run (rms,
|
||||||
|
NULL,
|
||||||
|
rms->is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -634,6 +823,27 @@ melt_cb (void *cls,
|
|||||||
rms->rmh = NULL;
|
rms->rmh = NULL;
|
||||||
if (rms->expected_response_code != http_status)
|
if (rms->expected_response_code != http_status)
|
||||||
{
|
{
|
||||||
|
if (GNUNET_YES == rms->do_retry)
|
||||||
|
{
|
||||||
|
if ( (0 == http_status) ||
|
||||||
|
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
|
||||||
|
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Retrying refresh melt failed with %u/%d\n",
|
||||||
|
http_status,
|
||||||
|
(int) ec);
|
||||||
|
/* on DB conflicts, do not use backoff */
|
||||||
|
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
|
||||||
|
rms->backoff = GNUNET_TIME_UNIT_ZERO;
|
||||||
|
else
|
||||||
|
rms->backoff = GNUNET_TIME_STD_BACKOFF (rms->backoff);
|
||||||
|
rms->retry_task = GNUNET_SCHEDULER_add_delayed (rms->backoff,
|
||||||
|
&do_melt_retry,
|
||||||
|
rms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unexpected response code %u/%d to command %s in %s:%u\n",
|
"Unexpected response code %u/%d to command %s in %s:%u\n",
|
||||||
http_status,
|
http_status,
|
||||||
@ -668,7 +878,7 @@ melt_cb (void *cls,
|
|||||||
* @param cmd the command to execute.
|
* @param cmd the command to execute.
|
||||||
* @param is the interpreter state.
|
* @param is the interpreter state.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
refresh_melt_run (void *cls,
|
refresh_melt_run (void *cls,
|
||||||
const struct TALER_TESTING_Command *cmd,
|
const struct TALER_TESTING_Command *cmd,
|
||||||
struct TALER_TESTING_Interpreter *is)
|
struct TALER_TESTING_Interpreter *is)
|
||||||
@ -819,6 +1029,11 @@ refresh_melt_cleanup (void *cls,
|
|||||||
TALER_EXCHANGE_refresh_melt_cancel (rms->rmh);
|
TALER_EXCHANGE_refresh_melt_cancel (rms->rmh);
|
||||||
rms->rmh = NULL;
|
rms->rmh = NULL;
|
||||||
}
|
}
|
||||||
|
if (NULL != rms->retry_task)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (rms->retry_task);
|
||||||
|
rms->retry_task = NULL;
|
||||||
|
}
|
||||||
GNUNET_free_non_null (rms->fresh_pks);
|
GNUNET_free_non_null (rms->fresh_pks);
|
||||||
rms->fresh_pks = NULL;
|
rms->fresh_pks = NULL;
|
||||||
GNUNET_free_non_null (rms->refresh_data);
|
GNUNET_free_non_null (rms->refresh_data);
|
||||||
@ -894,10 +1109,10 @@ TALER_TESTING_cmd_refresh_melt
|
|||||||
cmd.run = &refresh_melt_run;
|
cmd.run = &refresh_melt_run;
|
||||||
cmd.cleanup = &refresh_melt_cleanup;
|
cmd.cleanup = &refresh_melt_cleanup;
|
||||||
cmd.traits = &refresh_melt_traits;
|
cmd.traits = &refresh_melt_traits;
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "refresh melt" CMD that does TWO /refresh/melt
|
* Create a "refresh melt" CMD that does TWO /refresh/melt
|
||||||
* requests. This was needed to test the replay of a valid melt
|
* requests. This was needed to test the replay of a valid melt
|
||||||
@ -938,10 +1153,28 @@ TALER_TESTING_cmd_refresh_melt_double
|
|||||||
cmd.run = &refresh_melt_run;
|
cmd.run = &refresh_melt_run;
|
||||||
cmd.cleanup = &refresh_melt_cleanup;
|
cmd.cleanup = &refresh_melt_cleanup;
|
||||||
cmd.traits = &refresh_melt_traits;
|
cmd.traits = &refresh_melt_traits;
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a "refresh melt" command to enable retries.
|
||||||
|
*
|
||||||
|
* @param cmd command
|
||||||
|
* @return modified command.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_refresh_melt_with_retry (struct TALER_TESTING_Command cmd)
|
||||||
|
{
|
||||||
|
struct RefreshMeltState *rms;
|
||||||
|
|
||||||
|
GNUNET_assert (&refresh_melt_run == cmd.run);
|
||||||
|
rms = cmd.cls;
|
||||||
|
rms->do_retry = GNUNET_YES;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offer internal data from a "refresh reveal" CMD.
|
* Offer internal data from a "refresh reveal" CMD.
|
||||||
*
|
*
|
||||||
@ -960,23 +1193,22 @@ refresh_reveal_traits (void *cls,
|
|||||||
{
|
{
|
||||||
struct RefreshRevealState *rrs = cls;
|
struct RefreshRevealState *rrs = cls;
|
||||||
unsigned int num_coins = rrs->num_fresh_coins;
|
unsigned int num_coins = rrs->num_fresh_coins;
|
||||||
#define NUM_TRAITS (num_coins * 3) + 3
|
#define NUM_TRAITS (num_coins * 3) + 3
|
||||||
struct TALER_TESTING_Trait traits[NUM_TRAITS];
|
struct TALER_TESTING_Trait traits[NUM_TRAITS];
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* Making coin privs traits */
|
/* Making coin privs traits */
|
||||||
for (i=0; i<num_coins; i++)
|
for (unsigned int i=0; i<num_coins; i++)
|
||||||
traits[i] = TALER_TESTING_make_trait_coin_priv
|
traits[i] = TALER_TESTING_make_trait_coin_priv
|
||||||
(i, &rrs->fresh_coins[i].coin_priv);
|
(i, &rrs->fresh_coins[i].coin_priv);
|
||||||
|
|
||||||
/* Making denom pubs traits */
|
/* Making denom pubs traits */
|
||||||
for (i=0; i<num_coins; i++)
|
for (unsigned int i=0; i<num_coins; i++)
|
||||||
traits[num_coins + i]
|
traits[num_coins + i]
|
||||||
= TALER_TESTING_make_trait_denom_pub
|
= TALER_TESTING_make_trait_denom_pub
|
||||||
(i, rrs->fresh_coins[i].pk);
|
(i, rrs->fresh_coins[i].pk);
|
||||||
|
|
||||||
/* Making denom sigs traits */
|
/* Making denom sigs traits */
|
||||||
for (i=0; i<num_coins; i++)
|
for (unsigned int i=0; i<num_coins; i++)
|
||||||
traits[(num_coins * 2) + i]
|
traits[(num_coins * 2) + i]
|
||||||
= TALER_TESTING_make_trait_denom_sig
|
= TALER_TESTING_make_trait_denom_sig
|
||||||
(i, &rrs->fresh_coins[i].sig);
|
(i, &rrs->fresh_coins[i].sig);
|
||||||
@ -998,6 +1230,7 @@ refresh_reveal_traits (void *cls,
|
|||||||
index);
|
index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "refresh reveal" command.
|
* Create a "refresh reveal" command.
|
||||||
*
|
*
|
||||||
@ -1028,7 +1261,24 @@ TALER_TESTING_cmd_refresh_reveal
|
|||||||
cmd.run = &refresh_reveal_run;
|
cmd.run = &refresh_reveal_run;
|
||||||
cmd.cleanup = &refresh_reveal_cleanup;
|
cmd.cleanup = &refresh_reveal_cleanup;
|
||||||
cmd.traits = &refresh_reveal_traits;
|
cmd.traits = &refresh_reveal_traits;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a "refresh reveal" command to enable retries.
|
||||||
|
*
|
||||||
|
* @param cmd command
|
||||||
|
* @return modified command.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd)
|
||||||
|
{
|
||||||
|
struct RefreshRevealState *rrs;
|
||||||
|
|
||||||
|
GNUNET_assert (&refresh_reveal_run == cmd.run);
|
||||||
|
rrs = cmd.cls;
|
||||||
|
rrs->do_retry = GNUNET_YES;
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,6 +1312,23 @@ TALER_TESTING_cmd_refresh_link
|
|||||||
cmd.label = label;
|
cmd.label = label;
|
||||||
cmd.run = &refresh_link_run;
|
cmd.run = &refresh_link_run;
|
||||||
cmd.cleanup = &refresh_link_cleanup;
|
cmd.cleanup = &refresh_link_cleanup;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a "refresh link" command to enable retries.
|
||||||
|
*
|
||||||
|
* @param cmd command
|
||||||
|
* @return modified command.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd)
|
||||||
|
{
|
||||||
|
struct RefreshLinkState *rls;
|
||||||
|
|
||||||
|
GNUNET_assert (&refresh_link_run == cmd.run);
|
||||||
|
rls = cmd.cls;
|
||||||
|
rls->do_retry = GNUNET_YES;
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
@ -169,15 +169,16 @@ reserve_withdraw_cb (void *cls,
|
|||||||
{
|
{
|
||||||
if (GNUNET_YES == ws->do_retry)
|
if (GNUNET_YES == ws->do_retry)
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
if ( (0 == http_status) ||
|
||||||
"Retrying withdraw failed with %u/%d\n",
|
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
|
||||||
http_status,
|
|
||||||
(int) ec);
|
|
||||||
if ( (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
|
|
||||||
(TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS == ec) ||
|
(TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS == ec) ||
|
||||||
(TALER_EC_WITHDRAW_RESERVE_UNKNOWN == ec) ||
|
(TALER_EC_WITHDRAW_RESERVE_UNKNOWN == ec) ||
|
||||||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
|
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
|
||||||
{
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Retrying withdraw failed with %u/%d\n",
|
||||||
|
http_status,
|
||||||
|
(int) ec);
|
||||||
/* on DB conflicts, do not use backoff */
|
/* on DB conflicts, do not use backoff */
|
||||||
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
|
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
|
||||||
ws->backoff = GNUNET_TIME_UNIT_ZERO;
|
ws->backoff = GNUNET_TIME_UNIT_ZERO;
|
||||||
|
@ -835,6 +835,17 @@ TALER_TESTING_cmd_deposit
|
|||||||
unsigned int expected_response_code);
|
unsigned int expected_response_code);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a deposit command to enable retries when we get transient
|
||||||
|
* errors from the exchange.
|
||||||
|
*
|
||||||
|
* @param cmd a deposit command
|
||||||
|
* @return the command with retries enabled
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_deposit_with_retry (struct TALER_TESTING_Command cmd);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "refresh melt" command.
|
* Create a "refresh melt" command.
|
||||||
*
|
*
|
||||||
@ -855,6 +866,7 @@ TALER_TESTING_cmd_refresh_melt
|
|||||||
const char *coin_reference,
|
const char *coin_reference,
|
||||||
unsigned int expected_response_code);
|
unsigned int expected_response_code);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "refresh melt" CMD that does TWO /refresh/melt
|
* Create a "refresh melt" CMD that does TWO /refresh/melt
|
||||||
* requests. This was needed to test the replay of a valid melt
|
* requests. This was needed to test the replay of a valid melt
|
||||||
@ -878,6 +890,16 @@ TALER_TESTING_cmd_refresh_melt_double
|
|||||||
unsigned int expected_response_code);
|
unsigned int expected_response_code);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a "refresh melt" command to enable retries.
|
||||||
|
*
|
||||||
|
* @param cmd command
|
||||||
|
* @return modified command.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_refresh_melt_with_retry (struct TALER_TESTING_Command cmd);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "refresh reveal" command.
|
* Create a "refresh reveal" command.
|
||||||
*
|
*
|
||||||
@ -896,6 +918,16 @@ TALER_TESTING_cmd_refresh_reveal
|
|||||||
unsigned int expected_response_code);
|
unsigned int expected_response_code);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a "refresh reveal" command to enable retries.
|
||||||
|
*
|
||||||
|
* @param cmd command
|
||||||
|
* @return modified command.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "refresh link" command.
|
* Create a "refresh link" command.
|
||||||
*
|
*
|
||||||
@ -914,6 +946,16 @@ TALER_TESTING_cmd_refresh_link
|
|||||||
unsigned int expected_response_code);
|
unsigned int expected_response_code);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a "refresh link" command to enable retries.
|
||||||
|
*
|
||||||
|
* @param cmd command
|
||||||
|
* @return modified command.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a "track transaction" command.
|
* Create a "track transaction" command.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user