gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-exchange] 02/02: fix #5281 for exchange: do prefligh


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] 02/02: fix #5281 for exchange: do preflight check that an old transaction is no longer running by accident
Date: Mon, 12 Mar 2018 11:33:16 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

commit a166ca7fece8bbe3c66dcf0217cc81d20d185ab0
Author: Christian Grothoff <address@hidden>
AuthorDate: Mon Mar 12 11:33:10 2018 +0100

    fix #5281 for exchange: do preflight check that an old transaction is no 
longer running by accident
---
 src/auditor/taler-auditor.c                        | 11 ++--
 src/auditor/taler-wire-auditor.c                   |  5 +-
 src/exchange/taler-exchange-aggregator.c           | 19 ++++---
 src/exchange/taler-exchange-httpd_db.c             |  7 ++-
 src/exchange/taler-exchange-httpd_db.h             |  4 +-
 src/exchange/taler-exchange-httpd_deposit.c        |  1 +
 src/exchange/taler-exchange-httpd_keystate.c       |  2 +
 src/exchange/taler-exchange-httpd_payback.c        |  1 +
 src/exchange/taler-exchange-httpd_refresh_link.c   |  1 +
 src/exchange/taler-exchange-httpd_refresh_melt.c   |  1 +
 src/exchange/taler-exchange-httpd_refresh_reveal.c |  1 +
 src/exchange/taler-exchange-httpd_refund.c         |  1 +
 src/exchange/taler-exchange-httpd_reserve_status.c |  3 +-
 .../taler-exchange-httpd_reserve_withdraw.c        |  1 +
 .../taler-exchange-httpd_track_transaction.c       | 17 +++---
 src/exchange/taler-exchange-httpd_track_transfer.c |  5 +-
 src/exchange/taler-exchange-wirewatch.c            |  5 +-
 src/exchange/test_taler_exchange_aggregator.c      |  6 ++-
 src/exchangedb/perf_taler_exchangedb_interpreter.c |  3 +-
 src/exchangedb/plugin_exchangedb_postgres.c        | 62 ++++++++++++++++++++--
 src/exchangedb/test_exchangedb.c                   | 21 ++++++--
 src/include/taler_exchangedb_plugin.h              | 20 ++++++-
 22 files changed, 157 insertions(+), 40 deletions(-)

diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index e807378..b8f6c62 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -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);
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
index 8ba38d3..55a2a05 100644
--- a/src/auditor/taler-wire-auditor.c
+++ b/src/auditor/taler-wire-auditor.c
@@ -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);
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index d5d4305..49cbb2b 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -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");
diff --git a/src/exchange/taler-exchange-httpd_db.c 
b/src/exchange/taler-exchange-httpd_db.c
index bd7777c..7817de9 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -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)
diff --git a/src/exchange/taler-exchange-httpd_db.h 
b/src/exchange/taler-exchange-httpd_db.h
index 7e342c8..2a42bcd 100644
--- a/src/exchange/taler-exchange-httpd_db.h
+++ b/src/exchange/taler-exchange-httpd_db.h
@@ -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);
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 542c56c..277430b 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 0428b10..042773b 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_payback.c 
b/src/exchange/taler-exchange-httpd_payback.c
index e6fade4..6f910b5 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c 
b/src/exchange/taler-exchange-httpd_refresh_link.c
index aee2336..0ec505a 100644
--- a/src/exchange/taler-exchange-httpd_refresh_link.c
+++ b/src/exchange/taler-exchange-httpd_refresh_link.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 400d2bb..384589d 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c 
b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index 4a7cd33..b045184 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_refund.c 
b/src/exchange/taler-exchange-httpd_refund.c
index 986c9d3..97cd935 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_reserve_status.c 
b/src/exchange/taler-exchange-httpd_reserve_status.c
index f87afa5..998460d 100644
--- a/src/exchange/taler-exchange-httpd_reserve_status.c
+++ b/src/exchange/taler-exchange-httpd_reserve_status.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c 
b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
index 11265b4..3f2bc31 100644
--- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_track_transaction.c 
b/src/exchange/taler-exchange-httpd_track_transaction.c
index 13a1066..fdda22b 100644
--- a/src/exchange/taler-exchange-httpd_track_transaction.c
+++ b/src/exchange/taler-exchange-httpd_track_transaction.c
@@ -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))
diff --git a/src/exchange/taler-exchange-httpd_track_transfer.c 
b/src/exchange/taler-exchange-httpd_track_transfer.c
index 38c6c29..493febc 100644
--- a/src/exchange/taler-exchange-httpd_track_transfer.c
+++ b/src/exchange/taler-exchange-httpd_track_transfer.c
@@ -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))
diff --git a/src/exchange/taler-exchange-wirewatch.c 
b/src/exchange/taler-exchange-wirewatch.c
index 856a620..e9f9276 100644
--- a/src/exchange/taler-exchange-wirewatch.c
+++ b/src/exchange/taler-exchange-wirewatch.c
@@ -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");
diff --git a/src/exchange/test_taler_exchange_aggregator.c 
b/src/exchange/test_taler_exchange_aggregator.c
index 3265bf2..0335bcd 100644
--- a/src/exchange/test_taler_exchange_aggregator.c
+++ b/src/exchange/test_taler_exchange_aggregator.c
@@ -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,
diff --git a/src/exchangedb/perf_taler_exchangedb_interpreter.c 
b/src/exchangedb/perf_taler_exchangedb_interpreter.c
index b9bf9c3..8a81bef 100644
--- a/src/exchangedb/perf_taler_exchangedb_interpreter.c
+++ b/src/exchangedb/perf_taler_exchangedb_interpreter.c
@@ -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:
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index a4f32cd..d6a9b28 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -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;
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index a0eb50f..36f0cce 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -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;
 
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index ae38856..3367755 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -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);
 
 
   /**
@@ -1172,6 +1175,19 @@ struct TALER_EXCHANGEDB_Plugin
 
 
   /**
+   * 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.
    *
    * @param cls the @e cls of this struct with the plugin-specific state
@@ -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

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]