diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-11-17 13:28:15 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-11-17 13:28:15 +0100 |
commit | 741831e87b3b189d3f75bdd9fa2ccc9a8d2ba8e2 (patch) | |
tree | d8737d801c2e7a5f52ae0a05b4069f9a673a234d /src/exchange | |
parent | 8e0f06c86bdc6880bc24334e65b7920c8310ecdd (diff) | |
download | exchange-741831e87b3b189d3f75bdd9fa2ccc9a8d2ba8e2.tar.gz exchange-741831e87b3b189d3f75bdd9fa2ccc9a8d2ba8e2.tar.bz2 exchange-741831e87b3b189d3f75bdd9fa2ccc9a8d2ba8e2.zip |
bank API refactoring for #7276 (incomplete)
Diffstat (limited to 'src/exchange')
-rw-r--r-- | src/exchange/taler-exchange-httpd_batch-deposit.c | 1 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_deposit.c | 36 | ||||
-rw-r--r-- | src/exchange/taler-exchange-wirewatch.c | 307 |
3 files changed, 172 insertions, 172 deletions
diff --git a/src/exchange/taler-exchange-httpd_batch-deposit.c b/src/exchange/taler-exchange-httpd_batch-deposit.c index 7a3ea0fa4..0545c393b 100644 --- a/src/exchange/taler-exchange-httpd_batch-deposit.c +++ b/src/exchange/taler-exchange-httpd_batch-deposit.c @@ -290,7 +290,6 @@ batch_deposit_transaction (void *cls, mhd_ret); if (qs < 0) return qs; - qs = TEH_plugin->do_deposit ( TEH_plugin->cls, deposit, diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 455888a89..740db7c1f 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -74,20 +74,20 @@ reply_deposit_success ( struct TALER_ExchangeSignatureP sig; enum TALER_ErrorCode ec; - if (TALER_EC_NONE != - (ec = TALER_exchange_online_deposit_confirmation_sign ( - &TEH_keys_exchange_sign_, - h_contract_terms, - h_wire, - h_policy, - exchange_timestamp, - wire_deadline, - refund_deadline, - amount_without_fee, - coin_pub, - merchant, - &pub, - &sig))) + ec = TALER_exchange_online_deposit_confirmation_sign ( + &TEH_keys_exchange_sign_, + h_contract_terms, + h_wire, + h_policy, + exchange_timestamp, + wire_deadline, + refund_deadline, + amount_without_fee, + coin_pub, + merchant, + &pub, + &sig); + if (TALER_EC_NONE != ec) { return TALER_MHD_reply_with_ec (connection, ec, @@ -187,8 +187,6 @@ deposit_transaction (void *cls, mhd_ret); if (qs < 0) return qs; - - /* If the deposit has a policy associated to it, persist it. This will * insert or update the record. */ if (dc->has_policy) @@ -203,16 +201,14 @@ deposit_transaction (void *cls, if (qs < 0) return qs; } - - qs = TEH_plugin->do_deposit ( TEH_plugin->cls, dc->deposit, dc->known_coin_id, &dc->h_payto, (dc->has_policy) - ? &dc->policy_details_serial_id - : NULL, + ? &dc->policy_details_serial_id + : NULL, &dc->exchange_timestamp, &balance_ok, &in_conflict); diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index 146f2ee72..d84344fc8 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -606,187 +606,192 @@ do_commit (struct WireAccount *wa) /** - * Callbacks of this type are used to serve the result of asking - * the bank for the transaction history. + * We got incoming transaction details from the bank. Add them + * to the database. * - * @param cls closure with the `struct WioreAccount *` we are processing - * @param http_status HTTP status code from the server - * @param ec taler error code - * @param serial_id identification of the position at which we are querying - * @param details details about the wire transfer - * @param json raw JSON response - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration + * @param wa wire account we are handling + * @param details array of transaction details + * @param details_length length of the @a details array + * @return true on success */ -static enum GNUNET_GenericReturnValue -history_cb (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - const struct TALER_BANK_CreditDetails *details, - const json_t *json) +static bool +process_reply (struct WireAccount *wa, + const struct TALER_BANK_CreditDetails *details, + unsigned int details_length) { - struct WireAccount *wa = cls; - enum GNUNET_DB_QueryStatus qs; + uint64_t lroff = wa->latest_row_off; - (void) json; - GNUNET_assert (NULL == task); - if (NULL == details) + /* check serial IDs for range constraints */ + for (unsigned int i = 0; i<details_length; i++) { - wa->hh = NULL; - if ( (! ( (MHD_HTTP_NOT_FOUND == http_status) && - (ignore_account_404) ) ) && - ( (MHD_HTTP_NO_CONTENT != http_status) && - ( (TALER_EC_NONE != ec) || - (MHD_HTTP_OK != http_status) ) ) ) + const struct TALER_BANK_CreditDetails *cd = &details[i]; + + if (cd->serial_id < lroff) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error fetching history: %s (%u)\n", - TALER_ErrorCode_get_hint (ec), - http_status); - if (! (exit_on_error || test_mode) ) - { - account_completed (wa); - return GNUNET_OK; - } + "Serial ID %llu not monotonic (got %llu before). Failing!\n", + (unsigned long long) cd->serial_id, + (unsigned long long) lroff); + db_plugin->rollback (db_plugin->cls); GNUNET_SCHEDULER_shutdown (); - return GNUNET_OK; + wa->hh = NULL; + return false; } - if (wa->started_transaction) + if (cd->serial_id >= wa->max_row_off) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "End of list. Committing progress on %s of (%llu,%llu]!\n", - wa->job_name, - (unsigned long long) wa->batch_start, - (unsigned long long) wa->latest_row_off); - do_commit (wa); - return GNUNET_OK; /* will be ignored anyway */ + /* We got 'limit' transactions back from the bank, so we should not + introduce any delay before the next call. */ + wa->delay = false; } - /* We did not even start a transaction. */ - if ( (wa->delay) && - (test_mode) && - (NULL == wa->next) ) + if (cd->serial_id > wa->shard_end) { - /* We exit on idle */ + /* we are *past* the current shard (likely because the serial_id of the + shard_end happens to not exist in the DB). So commit and stop this + iteration! */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Shutdown due to test mode!\n"); - GNUNET_SCHEDULER_shutdown (); - return GNUNET_OK; + "Serial ID %llu past shard end at %llu, ending iteration early!\n", + (unsigned long long) cd->serial_id, + (unsigned long long) wa->shard_end); + details_length = i; + wa->delay = false; + break; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "No transactions in history response, moving on.\n"); - account_completed (wa); - return GNUNET_OK; /* will be ignored anyway */ + lroff = cd->serial_id; } - - /* We did get 'details' from the bank. Do sanity checks before inserting. */ - if (serial_id < wa->latest_row_off) + if (0 == details_length) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Serial ID %llu not monotonic (got %llu before). Failing!\n", - (unsigned long long) serial_id, - (unsigned long long) wa->latest_row_off); - GNUNET_SCHEDULER_shutdown (); - wa->hh = NULL; - return GNUNET_SYSERR; + /* Server should have used 204, not 200! */ + GNUNET_break_op (0); + return true; } - /* If we got 'limit' transactions back from the bank, - we should not introduce any delay before the next - call. */ - if (serial_id >= wa->max_row_off) - wa->delay = false; - if (serial_id > wa->shard_end) + if (GNUNET_OK != + db_plugin->start_read_committed (db_plugin->cls, + "wirewatch check for incoming wire transfers")) { - /* we are *past* the current shard (likely because the serial_id of the - shard_end happens to not exist in the DB). So commit and stop this - iteration! */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Serial ID %llu past shard end at %llu, ending iteration early!\n", - (unsigned long long) serial_id, - (unsigned long long) wa->shard_end); - wa->latest_row_off = serial_id - 1; /* excluding serial_id! */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start database transaction!\n"); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); wa->hh = NULL; - if (wa->started_transaction) - { - GNUNET_assert (NULL == task); - do_commit (wa); - } - else - { - GNUNET_assert (NULL == task); - if (check_shard_done (wa)) - account_completed (wa); - else - task = GNUNET_SCHEDULER_add_now (&continue_with_shard, - wa); - } - return GNUNET_SYSERR; + return false; } - if (! wa->started_transaction) + wa->started_transaction = true; + + for (unsigned int i = 0; i<details_length; i++) { - if (GNUNET_OK != - db_plugin->start_read_committed (db_plugin->cls, - "wirewatch check for incoming wire transfers")) + const struct TALER_BANK_CreditDetails *cd = &details[i]; + enum GNUNET_DB_QueryStatus qs; + + /* FIXME #7276: Consider using Postgres multi-valued insert here, + for up to 15x speed-up according to + https://dba.stackexchange.com/questions/224989/multi-row-insert-vs-transactional-single-row-inserts#225006 + (Note: this may require changing both the + plugin API as well as modifying how this function is called.) */ + qs = db_plugin->reserves_in_insert (db_plugin->cls, + &cd->reserve_pub, + &cd->amount, + cd->execution_date, + cd->debit_account_uri, + wa->ai->section_name, + cd->serial_id); + switch (qs) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to start database transaction!\n"); - global_ret = EXIT_FAILURE; + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + db_plugin->rollback (db_plugin->cls); + wa->started_transaction = false; GNUNET_SCHEDULER_shutdown (); wa->hh = NULL; - return GNUNET_SYSERR; + return false; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got DB soft error for reserves_in_insert. Rolling back.\n"); + handle_soft_error (wa); + wa->hh = NULL; + return true; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* Either wirewatch was freshly started after the system was + shutdown and we're going over an incomplete shard again + after being restarted, or the shard lock period was too + short (number of workers set incorrectly?) and a 2nd + wirewatcher has been stealing our work while we are still + at it. */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Attempted to import transaction %llu (%s) twice. " + "This should happen rarely (if not, ask for support).\n", + (unsigned long long) cd->serial_id, + wa->job_name); + db_plugin->rollback (db_plugin->cls); + wa->latest_row_off = cd->serial_id; + wa->started_transaction = false; + /* already existed, ok, let's just continue */ + return true; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + wa->latest_row_off = cd->serial_id; + /* normal case */ + break; } - wa->started_transaction = true; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Adding wire transfer over %s with (hashed) subject `%s'\n", - TALER_amount2s (&details->amount), - TALER_B2S (&details->reserve_pub)); - /* FIXME #7276: Consider using Postgres multi-valued insert here, - for up to 15x speed-up according to - https://dba.stackexchange.com/questions/224989/multi-row-insert-vs-transactional-single-row-inserts#225006 - (Note: this may require changing both the - plugin API as well as modifying how this function is called.) */ - qs = db_plugin->reserves_in_insert (db_plugin->cls, - &details->reserve_pub, - &details->amount, - details->execution_date, - details->debit_account_uri, - wa->ai->section_name, - serial_id); - switch (qs) + do_commit (wa); + if (check_shard_done (wa)) + account_completed (wa); + else + task = GNUNET_SCHEDULER_add_now (&continue_with_shard, + wa); + return true; +} + + +/** + * Callbacks of this type are used to serve the result of asking + * the bank for the transaction history. + * + * @param cls closure with the `struct WireAccount *` we are processing + * @param reply response we got from the bank + */ +static void +history_cb (void *cls, + const struct TALER_BANK_CreditHistoryResponse *reply) +{ + struct WireAccount *wa = cls; + bool ok; + + GNUNET_assert (NULL == task); + wa->hh = NULL; + switch (reply->http_status) { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - db_plugin->rollback (db_plugin->cls); - wa->started_transaction = false; - GNUNET_SCHEDULER_shutdown (); - wa->hh = NULL; - return GNUNET_SYSERR; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Got DB soft error for reserves_in_insert. Rolling back.\n"); - handle_soft_error (wa); - wa->hh = NULL; - return GNUNET_SYSERR; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* Either wirewatch was freshly started after the system was - shutdown and we're going over an incomplete shard again - after being restarted, or the shard lock period was too - short (number of workers set incorrectly?) and a 2nd - wirewatcher has been stealing our work while we are still - at it. */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Attempted to import transaction %llu (%s) twice. " - "This should happen rarely (if not, ask for support).\n", - (unsigned long long) serial_id, - wa->job_name); - /* already existed, ok, let's just continue */ + case 0: + ok = false; + case MHD_HTTP_OK: + ok = process_reply (wa, + reply->details.success.details, + reply->details.success.details_length); break; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* normal case */ + case MHD_HTTP_NO_CONTENT: + ok = true; + break; + case MHD_HTTP_NOT_FOUND: + ok = ignore_account_404; + break; + default: + ok = false; break; } - wa->latest_row_off = serial_id; - return GNUNET_OK; + + if (! ok) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error fetching history: %s (%u)\n", + TALER_ErrorCode_get_hint (reply->ec), + reply->http_status); + if (! (exit_on_error || test_mode) ) + { + account_completed (wa); + return; + } + GNUNET_SCHEDULER_shutdown (); + return; + } } |