fix #5281 for exchange: do preflight check that an old transaction is no longer running by accident
This commit is contained in:
parent
1ae2ba3d0a
commit
a166ca7fec
@ -1890,7 +1890,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Detected applicable deposit of %s\n",
|
||||
TALER_amount2s (&amount_without_fee));
|
||||
deposit_fee = fee;
|
||||
deposit_fee = fee;
|
||||
}
|
||||
/* Check that the fees given in the transaction list and in dki match */
|
||||
TALER_amount_ntoh (&tmp,
|
||||
@ -2006,7 +2006,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
merchant_gain,
|
||||
deposit_fee));
|
||||
}
|
||||
|
||||
|
||||
/* Calculate total balance change, i.e. expenditures minus refunds */
|
||||
if (GNUNET_SYSERR ==
|
||||
TALER_amount_subtract (&spent,
|
||||
@ -3906,8 +3906,11 @@ transact (Analysis analysis,
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
edb->preflight (edb->cls,
|
||||
esession);
|
||||
ret = edb->start (edb->cls,
|
||||
esession);
|
||||
esession,
|
||||
"auditor");
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -3918,7 +3921,7 @@ transact (Analysis analysis,
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
|
||||
{
|
||||
qs = edb->commit (edb->cls,
|
||||
esession);
|
||||
esession);
|
||||
if (0 > qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
|
@ -1412,8 +1412,11 @@ run (void *cls,
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
edb->preflight (edb->cls,
|
||||
esession);
|
||||
ret = edb->start (edb->cls,
|
||||
esession);
|
||||
esession,
|
||||
"wire auditor");
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
|
@ -618,7 +618,7 @@ refund_by_coin_cb (void *cls,
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about deposits that have been made,
|
||||
@ -675,7 +675,7 @@ deposit_cb (void *cls,
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
GNUNET_assert (NULL == au->wire);
|
||||
au->wire = json_incref ((json_t *) wire);
|
||||
if (GNUNET_OK !=
|
||||
@ -810,7 +810,7 @@ aggregate_cb (void *cls,
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
if (au->rows_offset >= aggregation_limit)
|
||||
{
|
||||
/* Bug: we asked for at most #aggregation_limit results! */
|
||||
@ -1203,9 +1203,12 @@ run_reserve_closures (void *cls)
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
db_plugin->preflight (db_plugin->cls,
|
||||
session);
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
session))
|
||||
session,
|
||||
"aggregator reserve closures"))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to start database transaction!\n");
|
||||
@ -1413,7 +1416,8 @@ run_aggregation (void *cls)
|
||||
transaction to mark all* of the selected deposits as minor! */
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
session))
|
||||
session,
|
||||
"aggregator mark tiny transactions"))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to start database transaction!\n");
|
||||
@ -1767,9 +1771,12 @@ run_transfers (void *cls)
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
db_plugin->preflight (db_plugin->cls,
|
||||
session);
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
session))
|
||||
session,
|
||||
"aggregator run transfer"))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to start database transaction!\n");
|
||||
|
@ -41,6 +41,7 @@
|
||||
* errors, generates an error message for @a connection.
|
||||
*
|
||||
* @param connection MHD connection to run @a cb for
|
||||
* @param name name of the transaction (for debugging)
|
||||
* @param[out] set to MHD response code, if transaction failed
|
||||
* @param cb callback implementing transaction logic
|
||||
* @param cb_cls closure for @a cb, must be read-only!
|
||||
@ -48,6 +49,7 @@
|
||||
*/
|
||||
int
|
||||
TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
const char *name,
|
||||
int *mhd_ret,
|
||||
TEH_DB_TransactionCallback cb,
|
||||
void *cb_cls)
|
||||
@ -64,13 +66,16 @@ TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TEH_plugin->preflight (TEH_plugin->cls,
|
||||
session);
|
||||
for (unsigned int retries = 0;retries < MAX_TRANSACTION_COMMIT_RETRIES; retries++)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_plugin->start (TEH_plugin->cls,
|
||||
session))
|
||||
session,
|
||||
name))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
if (NULL != mhd_ret)
|
||||
|
@ -52,8 +52,9 @@ typedef enum GNUNET_DB_QueryStatus
|
||||
* attempts to commit the transaction. Upon soft failures,
|
||||
* retries @a cb a few times. Upon hard or persistent soft
|
||||
* errors, generates an error message for @a connection.
|
||||
*
|
||||
*
|
||||
* @param connection MHD connection to run @a cb for
|
||||
* @param name name of the transaction (for debugging)
|
||||
* @param[out] set to MHD response code, if transaction failed
|
||||
* @param cb callback implementing transaction logic
|
||||
* @param cb_cls closure for @a cb, must be read-only!
|
||||
@ -61,6 +62,7 @@ typedef enum GNUNET_DB_QueryStatus
|
||||
*/
|
||||
int
|
||||
TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
const char *name,
|
||||
int *mhd_ret,
|
||||
TEH_DB_TransactionCallback cb,
|
||||
void *cb_cls);
|
||||
|
@ -289,6 +289,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
|
||||
dc.deposit = deposit;
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"execute deposit",
|
||||
&mhd_ret,
|
||||
&deposit_transaction,
|
||||
&dc))
|
||||
|
@ -711,6 +711,7 @@ reload_keys_denom_iter (void *cls,
|
||||
arc.revocation_master_sig = revocation_master_sig;
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (NULL,
|
||||
"add denomination key revocations",
|
||||
NULL,
|
||||
&add_revocations_transaction,
|
||||
&arc))
|
||||
@ -739,6 +740,7 @@ reload_keys_denom_iter (void *cls,
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (NULL,
|
||||
"add denomination key",
|
||||
NULL,
|
||||
&add_denomination_transaction,
|
||||
(void *) dki))
|
||||
|
@ -396,6 +396,7 @@ verify_and_execute_payback (struct MHD_Connection *connection,
|
||||
pc.coin = coin;
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run payback",
|
||||
&mhd_ret,
|
||||
&payback_transaction,
|
||||
&pc))
|
||||
|
@ -203,6 +203,7 @@ TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh,
|
||||
ctx.mlist = json_array ();
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run link",
|
||||
&mhd_ret,
|
||||
&refresh_link_transaction,
|
||||
&ctx))
|
||||
|
@ -364,6 +364,7 @@ handle_refresh_melt (struct MHD_Connection *connection,
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run melt",
|
||||
&mhd_ret,
|
||||
&refresh_melt_transaction,
|
||||
rmc))
|
||||
|
@ -587,6 +587,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
|
||||
/* do transactional work */
|
||||
if (GNUNET_OK ==
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run reveal",
|
||||
&res,
|
||||
&refresh_reveal_transaction,
|
||||
rctx))
|
||||
|
@ -452,6 +452,7 @@ verify_and_execute_refund (struct MHD_Connection *connection,
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run refund",
|
||||
&mhd_ret,
|
||||
&refund_transaction,
|
||||
(void *) refund))
|
||||
|
@ -78,7 +78,7 @@ struct ReserveStatusContext
|
||||
|
||||
|
||||
/**
|
||||
* Function implementing /reserve/status transaction.
|
||||
* Function implementing /reserve/status transaction.
|
||||
* Execute a /reserve/status. Given the public key of a reserve,
|
||||
* return the associated transaction history. Runs the
|
||||
* transaction logic; IF it returns a non-error code, the transaction
|
||||
@ -144,6 +144,7 @@ TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh,
|
||||
rsc.rh = NULL;
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"get reserve status",
|
||||
&mhd_ret,
|
||||
&reserve_status_transaction,
|
||||
&rsc))
|
||||
|
@ -492,6 +492,7 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run reserve withdraw",
|
||||
&mhd_ret,
|
||||
&withdraw_transaction,
|
||||
&wc))
|
||||
|
@ -120,25 +120,25 @@ struct DepositWtidContext
|
||||
* Public key of the merchant.
|
||||
*/
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub;
|
||||
|
||||
|
||||
/**
|
||||
* Set by #handle_wtid data to the wire transfer ID.
|
||||
*/
|
||||
*/
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
|
||||
|
||||
/**
|
||||
* Set by #handle_wtid data to the coin's contribution to the wire transfer.
|
||||
*/
|
||||
*/
|
||||
struct TALER_Amount coin_contribution;
|
||||
|
||||
|
||||
/**
|
||||
* Set by #handle_wtid data to the fee charged to the coin.
|
||||
*/
|
||||
*/
|
||||
struct TALER_Amount coin_fee;
|
||||
|
||||
/**
|
||||
* Set by #handle_wtid data to the wire transfer execution time.
|
||||
*/
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute execution_time;
|
||||
|
||||
/**
|
||||
@ -289,9 +289,10 @@ check_and_handle_track_transaction_request (struct MHD_Connection *connection,
|
||||
ctx.pending = GNUNET_NO;
|
||||
ctx.tps = tps;
|
||||
ctx.merchant_pub = merchant_pub;
|
||||
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"handle track transaction",
|
||||
&mhd_ret,
|
||||
&track_transaction_transaction,
|
||||
&ctx))
|
||||
|
@ -141,7 +141,7 @@ reply_track_transfer_details (struct MHD_Connection *connection,
|
||||
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
|
||||
"no keys");
|
||||
}
|
||||
|
||||
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_OK,
|
||||
"{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||
@ -327,7 +327,7 @@ handle_transaction_data (void *cls,
|
||||
/**
|
||||
* Execute a "/track/transfer". Returns the transaction information
|
||||
* associated with the given wire transfer identifier.
|
||||
*
|
||||
*
|
||||
* If it returns a non-error code, the transaction logic MUST
|
||||
* NOT queue a MHD response. IF it returns an hard error, the
|
||||
* transaction logic MUST queue a MHD response and set @a mhd_ret. IF
|
||||
@ -474,6 +474,7 @@ TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh,
|
||||
return MHD_YES; /* parse error */
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"run track transfer",
|
||||
&mhd_ret,
|
||||
&track_transfer_transaction,
|
||||
&ctx))
|
||||
|
@ -422,9 +422,12 @@ find_transfers (void *cls)
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
db_plugin->preflight (db_plugin->cls,
|
||||
session);
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
session))
|
||||
session,
|
||||
"wirewatch check for incoming wire transfers"))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to start database transaction!\n");
|
||||
|
@ -447,7 +447,8 @@ do_deposit (struct Command *cmd)
|
||||
/* finally, actually perform the DB operation */
|
||||
if ( (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session)) ||
|
||||
session,
|
||||
"aggregator-test-1")) ||
|
||||
(GNUNET_OK !=
|
||||
plugin->insert_deposit (plugin->cls,
|
||||
session,
|
||||
@ -1150,7 +1151,8 @@ run (void *cls)
|
||||
&issue.properties.denom_hash);
|
||||
if ( (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session)) ||
|
||||
session,
|
||||
"aggregator-test-2")) ||
|
||||
(GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_denomination_info (plugin->cls,
|
||||
session,
|
||||
|
@ -1159,7 +1159,8 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
||||
case PERF_TALER_EXCHANGEDB_CMD_START_TRANSACTION:
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
state->plugin->start (state->plugin->cls,
|
||||
state->session));
|
||||
state->session,
|
||||
"perf-interpreter"));
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_COMMIT_TRANSACTION:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V.
|
||||
Copyright (C) 2014, 2015, 2016, 2017, 2018 GNUnet e.V.
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -60,6 +60,11 @@ struct TALER_EXCHANGEDB_Session
|
||||
*/
|
||||
PGconn *conn;
|
||||
|
||||
/**
|
||||
* Name of the current transaction, for debugging.
|
||||
*/
|
||||
const char *transaction_name;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -1533,11 +1538,14 @@ postgres_get_session (void *cls)
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param session the database connection
|
||||
* @param name unique name identifying the transaction (for debugging)
|
||||
* must point to a constant
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
postgres_start (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session)
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const char *name)
|
||||
{
|
||||
PGresult *result;
|
||||
ExecStatusType ex;
|
||||
@ -1552,9 +1560,11 @@ postgres_start (void *cls,
|
||||
PQerrorMessage (session->conn));
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
session->transaction_name = NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
PQclear (result);
|
||||
session->transaction_name = name;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -1577,6 +1587,7 @@ postgres_rollback (void *cls,
|
||||
GNUNET_break (PGRES_COMMAND_OK ==
|
||||
PQresultStatus (result));
|
||||
PQclear (result);
|
||||
session->transaction_name = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -1594,10 +1605,50 @@ postgres_commit (void *cls,
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
return GNUNET_PQ_eval_prepared_non_select (session->conn,
|
||||
"do_commit",
|
||||
params);
|
||||
qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
|
||||
"do_commit",
|
||||
params);
|
||||
session->transaction_name = NULL;
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do a pre-flight check that we are not in an uncommitted transaction.
|
||||
* If we are, try to commit the previous transaction and output a warning.
|
||||
* Does not return anything, as we will continue regardless of the outcome.
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param session the database connection
|
||||
*/
|
||||
static void
|
||||
postgres_preflight (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session)
|
||||
{
|
||||
PGresult *result;
|
||||
ExecStatusType status;
|
||||
|
||||
if (NULL == session->transaction_name)
|
||||
return; /* all good */
|
||||
result = PQexec (session->conn,
|
||||
"COMMIT");
|
||||
status = PQresultStatus (result);
|
||||
if (PGRES_COMMAND_OK == status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"BUG: Preflight check committed transaction `%s'!\n",
|
||||
session->transaction_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"BUG: Preflight check failed to commit transaction `%s'!\n",
|
||||
session->transaction_name);
|
||||
}
|
||||
session->transaction_name = NULL;
|
||||
PQclear (result);
|
||||
}
|
||||
|
||||
|
||||
@ -6363,6 +6414,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
||||
plugin->create_tables = &postgres_create_tables;
|
||||
plugin->start = &postgres_start;
|
||||
plugin->commit = &postgres_commit;
|
||||
plugin->preflight = &postgres_preflight;
|
||||
plugin->rollback = &postgres_rollback;
|
||||
plugin->insert_denomination_info = &postgres_insert_denomination_info;
|
||||
plugin->get_denomination_info = &postgres_get_denomination_info;
|
||||
|
@ -1545,7 +1545,8 @@ run (void *cls)
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session));
|
||||
session,
|
||||
"test-1"));
|
||||
|
||||
/* test DB is empty */
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
@ -1909,7 +1910,8 @@ run (void *cls)
|
||||
session));
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session));
|
||||
session,
|
||||
"test-2"));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->mark_deposit_tiny (plugin->cls,
|
||||
session,
|
||||
@ -1928,7 +1930,8 @@ run (void *cls)
|
||||
&deposit));
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session));
|
||||
session,
|
||||
"test-3"));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->test_deposit_done (plugin->cls,
|
||||
session,
|
||||
@ -1992,9 +1995,12 @@ run (void *cls)
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->commit (plugin->cls,
|
||||
session));
|
||||
plugin->preflight (plugin->cls,
|
||||
session);
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session));
|
||||
session,
|
||||
"test-4"));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->insert_denomination_revocation (plugin->cls,
|
||||
session,
|
||||
@ -2002,9 +2008,12 @@ run (void *cls)
|
||||
&master_sig));
|
||||
plugin->rollback (plugin->cls,
|
||||
session);
|
||||
plugin->preflight (plugin->cls,
|
||||
session);
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->start (plugin->cls,
|
||||
session));
|
||||
session,
|
||||
"test-5"));
|
||||
{
|
||||
struct TALER_MasterSignatureP msig;
|
||||
uint64_t rev_rowid;
|
||||
@ -2164,6 +2173,8 @@ run (void *cls)
|
||||
FAILIF (GNUNET_OK !=
|
||||
test_wire_fees (session));
|
||||
|
||||
plugin->preflight (plugin->cls,
|
||||
session);
|
||||
|
||||
result = 0;
|
||||
|
||||
|
@ -1152,11 +1152,14 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to use
|
||||
* @param name unique name identifying the transaction (for debugging),
|
||||
* must point to a constant
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
(*start) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session);
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const char *name);
|
||||
|
||||
|
||||
/**
|
||||
@ -1171,6 +1174,19 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
struct TALER_EXCHANGEDB_Session *session);
|
||||
|
||||
|
||||
/**
|
||||
* Do a pre-flight check that we are not in an uncommitted transaction.
|
||||
* If we are, try to commit the previous transaction and output a warning.
|
||||
* Does not return anything, as we will continue regardless of the outcome.
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param session the database connection
|
||||
*/
|
||||
void
|
||||
(*preflight) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session);
|
||||
|
||||
|
||||
/**
|
||||
* Abort/rollback a transaction.
|
||||
*
|
||||
@ -1397,7 +1413,7 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
TALER_EXCHANGEDB_RefundCoinCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mark a deposit as tiny, thereby declaring that it cannot be
|
||||
|
Loading…
Reference in New Issue
Block a user