gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant] branch master updated: move code towards m


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch master updated: move code towards more modern PQ API
Date: Sat, 10 Jun 2017 21:47:26 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new e90fc12  move code towards more modern PQ API
e90fc12 is described below

commit e90fc12253479a5c96a89aa1be2e7c600d8eeb92
Author: Christian Grothoff <address@hidden>
AuthorDate: Sat Jun 10 21:47:24 2017 +0200

    move code towards more modern PQ API
---
 doc/version.texi                           |   4 +-
 src/backenddb/plugin_merchantdb_postgres.c | 360 +++++++++++++++--------------
 2 files changed, 191 insertions(+), 173 deletions(-)

diff --git a/doc/version.texi b/doc/version.texi
index acbfcb4..efa990a 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,4 @@
address@hidden UPDATED 31 May 2017
address@hidden UPDATED-MONTH May 2017
address@hidden UPDATED 3 June 2017
address@hidden UPDATED-MONTH June 2017
 @set EDITION 0.3.0
 @set VERSION 0.3.0
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index ee2180d..a0b2820 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014, 2015, 2016, 2017 INRIA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Lesser General Public License as published by the Free 
Software
@@ -182,55 +182,6 @@ postgres_rollback (void *cls)
   PQclear (result);
 }
 
-/**
- * Check the @a result's error code to see what happened.
- * Also logs errors.
- *
- * @param pg `struct PostgresClosure`
- * @param result result to check
- * @return #GNUNET_OK if the request/transaction succeeded
- *         #GNUNET_NO if it failed but could succeed if retried
- *         #GNUNET_SYSERR on hard errors
- */
-static int
-evaluate_pq_result (struct PostgresClosure *pg,
-                    PGresult *result)
-{
-  if (PGRES_COMMAND_OK !=
-      PQresultStatus (result))
-  {
-    const char *sqlstate;
-
-    sqlstate = PQresultErrorField (result,
-                                   PG_DIAG_SQLSTATE);
-    if (NULL == sqlstate)
-    {
-      /* very unexpected... */
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    if ( (0 == strcmp (sqlstate,
-                       PQ_DIAG_SQLSTATE_DEADLOCK)) || /*FIXME: no threads, 
really needed?*/
-         (0 == strcmp (sqlstate,
-                       PQ_DIAG_SQLSTATE_SERIALIZATION_FAILURE)) )
-    {
-      /* These two can be retried and have a fair chance of working
-         the next time */
-      QUERY_ERR (result, pg->conn);
-      return GNUNET_NO;
-    }
-    BREAK_DB_ERR(result);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-
-  /**
-   * NOTE: this function equals 99% the one from the exchange codebase.
-   * The difference is that here we don't use the session->state field (
-   * see original code: exchange/src/exchangedb/plugin_exchangedb_postgres.c).
-   * Good/bad?
-   */
-}
 
 /**
  * Commit the current transaction of a database connection.
@@ -244,23 +195,23 @@ static int
 postgres_commit (void *cls)
 {
   struct PostgresClosure *pg = cls;
-  PGresult *result;
-  int ret;
-
-  result = PQexec (pg->conn,
-                   "COMMIT");
-  ret = evaluate_pq_result (pg,
-                            result);
-  GNUNET_break (GNUNET_SYSERR != ret);
-  PQclear (result);
-  return ret;
+  enum GNUNET_PQ_QueryStatus ret;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
 
-  /**
-   * NOTE: this function equals 99% the one from the exchange codebase.
-   * The difference is that here we don't use the session->state field (
-   * see original code: exchange/src/exchangedb/plugin_exchangedb_postgres.c).
-   * Good/bad?
-   */
+  ret = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                            "end_transaction",
+                                            params);
+  switch (ret)
+  {
+  case GNUNET_PQ_STATUS_HARD_ERROR:
+    return GNUNET_SYSERR;
+  case GNUNET_PQ_STATUS_SOFT_ERROR:
+    return GNUNET_NO;
+  default:
+    return GNUNET_OK;
+  }
 }
 
 
@@ -323,7 +274,7 @@ postgres_initialize (void *cls)
                             ",exchange_proof BYTEA NOT NULL"
                             ",PRIMARY KEY (h_contract_terms, coin_pub)"
                             ");"),
-  GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_proofs ("
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_proofs ("
                           " exchange_uri VARCHAR NOT NULL"
                           ",wtid BYTEA CHECK (LENGTH(wtid)=32)"
                           ",execution_time INT8 NOT NULL"
@@ -413,11 +364,14 @@ postgres_initialize (void *cls)
                             " h_contract_terms=$1"
                             " AND merchant_pub=$2",
                             2),
+    GNUNET_PQ_make_prepare ("end_transaction",
+                            "COMMIT",
+                            0),
 
     /*NOTE: minimal version, to be expanded on a needed basis*/
     GNUNET_PQ_make_prepare ("find_refunds",
                             "SELECT"
-                            " refund_amount_val" 
+                            " refund_amount_val"
                             ",refund_amount_frac"
                             ",refund_amount_curr"
                             " FROM merchant_refunds"
@@ -1763,72 +1717,98 @@ postgres_get_refunds_from_contract_terms_hash (void 
*cls,
   return GNUNET_OK;
 }
 
+
 /**
- * Function called when some backoffice staff decides to award or
- * increase the refund on an existing contract.
- *
- * @param cls closure
- * @param h_contract_terms
- * @param merchant_pub merchant's instance public key
- * @param refund maximum refund to return to the customer for this contract
- * @param reason 0-terminated UTF-8 string giving the reason why the customer
- *               got a refund (free form, business-specific)
- * @return #GNUNET_OK if the refund is accepted
- *         #GNUNET_NO if the refund is at or below the previous refund amount
- *         #GNUNET_SYSERR on database error, i.e. contract unknown, DB on fire,
- *               (FIXME: distinguish hard/soft? who does retries?)
+ * Closure for #process_refund_cb.
  */
-int
-postgres_increase_refund_for_contract (void *cls,
-                                       const struct GNUNET_HashCode 
*h_contract_terms,
-                                       const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                                       const struct TALER_Amount *refund,
-                                       const char *reason)
+struct FindRefundContext
 {
+  struct TALER_Amount refunded_amount;
 
-  struct PostgresClosure *pg = cls;
-  PGresult *result;
-  unsigned int i;
+  int err;
+};
 
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_end
-  };
 
-  if (GNUNET_OK !=
-      postgres_start (cls))
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure, our `struct FindRefundContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+process_refund_cb (void *cls,
+                   PGresult *result,
+                   unsigned int num_results)
+{
+  struct FindRefundContext *ictx = cls;
+
+  for (unsigned int i=0; i<num_results; i++)
   {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
+    /*Sum up refund*/
+    struct TALER_Amount acc;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_result_spec_amount ("refund_amount",
+                                   &acc),
+      GNUNET_PQ_result_spec_end
+    };
 
-  result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_deposits",
-                                    params);
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+      ictx->err = GNUNET_SYSERR;
 
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
+    if (GNUNET_SYSERR ==
+        TALER_amount_add (&ictx->refunded_amount,
+                          &ictx->refunded_amount,
+                          &acc))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not add amounts\n");
+      ictx->err = GNUNET_SYSERR;
+    }
   }
+}
 
-  if (0 == PQntuples (result))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unknown contract: %s (merchant_pub: %s), no refund 
possible\n",
-                GNUNET_h2s (h_contract_terms),
-                TALER_B2S (merchant_pub));
-    return GNUNET_SYSERR;
-  }
 
-  for (i=0;i<PQntuples (result);i++)
+/**
+ * Closure for #process_deposits_cb.
+ */
+struct InsertRefundContext
+{
+  struct PostgresClosure *pg;
+
+  int err;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure, our `struct InsertRefundContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+process_deposits_cb (void *cls,
+                     PGresult *result,
+                     unsigned int num_results)
+{
+  struct InsertRefundContext *ctx = cls;
+
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_Amount amount_with_fee;
-    struct TALER_Amount refunded_amount;
-
+    struct FindRefundContext ictx;
+    enum GNUNET_PQ_QueryStatus ires;
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&coin_pub),
+      GNUNET_PQ_query_param_end
+    };
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &coin_pub),
@@ -1843,53 +1823,23 @@ postgres_increase_refund_for_contract (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      ctx->err = GNUNET_SYSERR;
+      return;
     }
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&coin_pub),
-      GNUNET_PQ_query_param_end
-    };
 
-    result = GNUNET_PQ_exec_prepared (pg->conn,
-                                      "find_refunds",
-                                      params);
-
-    if (PGRES_TUPLES_OK != PQresultStatus (result))
-    {
-      BREAK_DB_ERR (result);
-      goto rollback;
-    }
     TALER_amount_get_zero (amount_with_fee.currency,
-                           &refunded_amount);
-    if (0 < PQntuples (result))
-    {
-      for (i=0; PQntuples (result); i++)
-      {
-        /*Sum up refund*/
-        struct TALER_Amount acc;
-        struct GNUNET_PQ_ResultSpec rs[] = {
-          TALER_PQ_result_spec_amount ("refund_amount",
-                                       &acc),
-          GNUNET_PQ_result_spec_end
-        };
-
-        if (GNUNET_OK !=
-            GNUNET_PQ_extract_result (result,
-                                      rs,
-                                      i))
-          goto rollback;
-
-        if (GNUNET_SYSERR == TALER_amount_add (&refunded_amount,
-                                               &refunded_amount,
-                                               &acc))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Could not add amounts\n");
-          goto rollback;
-        }
-      }
-    }
+                           &ictx.refunded_amount);
+    ictx.err = GNUNET_OK; /* no error so far */
+    ires = GNUNET_PQ_eval_prepared_multi_select (ctx->pg->conn,
+                                                 "find_refunds",
+                                                 params,
+                                                 &process_refund_cb,
+                                                 &ictx);
+    if ( (GNUNET_OK != ictx.err) ||
+         (GNUNET_PQ_STATUS_HARD_ERROR == ires) )
+      goto rollback;
+    if (GNUNET_PQ_STATUS_SOFT_ERROR == ires)
+      goto rollback; // FIXME: #5010: actually rollback + retry!
 
     /**
      * FIXME:
@@ -1901,11 +1851,85 @@ postgres_increase_refund_for_contract (void *cls,
                 "Refund situation for coin '%s',  deposited: %s, refunded: 
%s\n",
                 TALER_B2S (&coin_pub),
                 TALER_amount_to_string (&amount_with_fee),
-                TALER_amount_to_string (&refunded_amount));
+                TALER_amount_to_string (&ictx.refunded_amount));
     /*NOTE: this makes testcase fail. To keep around until logic has been 
written*/
+    ctx->err = GNUNET_SYSERR;
+    return;
+  }
+
+ rollback:
+  ctx->err = GNUNET_SYSERR;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed transaction, doing rollback\n");
+  PQclear (result);
+  postgres_rollback (ctx->pg);
+  return;
+}
+
+
+
+/**
+ * Function called when some backoffice staff decides to award or
+ * increase the refund on an existing contract.
+ *
+ * @param cls closure
+ * @param h_contract_terms
+ * @param merchant_pub merchant's instance public key
+ * @param refund maximum refund to return to the customer for this contract
+ * @param reason 0-terminated UTF-8 string giving the reason why the customer
+ *               got a refund (free form, business-specific)
+ * @return #GNUNET_OK if the refund is accepted
+ *         #GNUNET_NO if the refund is at or below the previous refund amount
+ *         #GNUNET_SYSERR on database error, i.e. contract unknown, DB on fire,
+ *               (FIXME: distinguish hard/soft? who does retries?)
+ */
+static int
+postgres_increase_refund_for_contract (void *cls,
+                                       const struct GNUNET_HashCode 
*h_contract_terms,
+                                       const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                       const struct TALER_Amount *refund,
+                                       const char *reason)
+{
+  struct PostgresClosure *pg = cls;
+  struct InsertRefundContext ctx;
+  enum GNUNET_PQ_QueryStatus ret;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_end
+  };
+
+  if (GNUNET_OK !=
+      postgres_start (cls))
+  {
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
 
+  ctx.pg = pg;
+  ctx.err = GNUNET_OK;
+  ret = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                              "find_deposits",
+                                              params,
+                                              &process_deposits_cb,
+                                              &ctx);
+  switch (ret)
+  {
+  case GNUNET_PQ_STATUS_SUCCESS_NO_RESULTS:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unknown contract: %s (merchant_pub: %s), no refund 
possible\n",
+                GNUNET_h2s (h_contract_terms),
+                TALER_B2S (merchant_pub));
+    return GNUNET_SYSERR;
+  case GNUNET_PQ_STATUS_SOFT_ERROR:
+    return GNUNET_SYSERR; /* UGH, BUG #5010! */
+  case GNUNET_PQ_STATUS_HARD_ERROR:
+    return GNUNET_SYSERR;
+  default:
+    /* got one or more deposits */
+    break;
+  }
+
   if (GNUNET_OK != postgres_commit (cls))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1914,15 +1938,9 @@ postgres_increase_refund_for_contract (void *cls,
   }
 
   return GNUNET_OK;
-
-  rollback:
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed transaction, doing rollback\n");
-    PQclear (result);
-    postgres_rollback (pg);
-    return GNUNET_SYSERR;
 }
 
+
 /**
  * Lookup proof information about a wire transfer.
  *

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



reply via email to

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