gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated: address #5010 for /


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: address #5010 for /refresh/link
Date: Tue, 20 Jun 2017 13:40:27 +0200

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 39db1ae  address #5010 for /refresh/link
39db1ae is described below

commit 39db1ae5dbbd12c0f452cfa56119d9a95f9b1b22
Author: Christian Grothoff <address@hidden>
AuthorDate: Tue Jun 20 13:40:17 2017 +0200

    address #5010 for /refresh/link
---
 src/exchange/taler-exchange-httpd_refresh_link.c | 172 ++++++++++-------
 src/exchangedb/plugin_exchangedb_postgres.c      | 229 ++++++++++++++---------
 src/exchangedb/test_exchangedb.c                 |  11 +-
 src/include/taler_exchangedb_plugin.h            |  14 +-
 4 files changed, 264 insertions(+), 162 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c 
b/src/exchange/taler-exchange-httpd_refresh_link.c
index c85431f..0be6998 100644
--- a/src/exchange/taler-exchange-httpd_refresh_link.c
+++ b/src/exchange/taler-exchange-httpd_refresh_link.c
@@ -56,6 +56,11 @@ struct HTD_Context
 {
 
   /**
+   * Public key of the coin that we are tracing.
+   */
+  struct TALER_CoinSpendPublicKeyP coin_pub;
+
+  /**
    * Session link data we collect.
    */
   struct TEH_RESPONSE_LinkSessionInfo *sessions;
@@ -100,18 +105,18 @@ reply_refresh_link_success (struct MHD_Connection 
*connection,
                            unsigned int num_sessions,
                            const struct TEH_RESPONSE_LinkSessionInfo *sessions)
 {
-  json_t *root;
   json_t *mlist;
   int res;
-  unsigned int i;
 
   mlist = json_array ();
-  for (i=0;i<num_sessions;i++)
+  for (unsigned int i=0;i<num_sessions;i++)
   {
-    const struct TALER_EXCHANGEDB_LinkDataList *pos;
     json_t *list = json_array ();
+    json_t *root;
 
-    for (pos = sessions[i].ldl; NULL != pos; pos = pos->next)
+    for (const struct TALER_EXCHANGEDB_LinkDataList *pos = sessions[i].ldl;
+        NULL != pos;
+        pos = pos->next)
     {
       json_t *obj;
 
@@ -163,24 +168,24 @@ handle_transfer_data (void *cls,
   struct HTD_Context *ctx = cls;
   struct TALER_EXCHANGEDB_LinkDataList *ldl;
   struct TEH_RESPONSE_LinkSessionInfo *lsi;
+  enum GNUNET_DB_QueryStatus qs;
 
-  if (GNUNET_OK != ctx->status)
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != ctx->status)
     return;
-  ldl = TEH_plugin->get_link_data_list (TEH_plugin->cls,
-                                        ctx->session,
-                                        session_hash);
-  if (NULL == ldl)
+  ldl = NULL;
+  qs = TEH_plugin->get_link_data_list (TEH_plugin->cls,
+                                      ctx->session,
+                                      session_hash,
+                                      &ldl);
+  if (qs <= 0) 
   {
-    ctx->status = GNUNET_NO;
-    if (MHD_NO ==
-        TEH_RESPONSE_reply_json_pack (ctx->connection,
-                                      MHD_HTTP_NOT_FOUND,
-                                      "{s:s}",
-                                      "error",
-                                      "link data not found (link)"))
-      ctx->status = GNUNET_SYSERR;
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      ctx->status = GNUNET_DB_STATUS_HARD_ERROR;
+    else
+      ctx->status = qs;
     return;
   }
+  GNUNET_assert (NULL != ldl);
   GNUNET_array_grow (ctx->sessions,
                      ctx->num_sessions,
                      ctx->num_sessions + 1);
@@ -191,61 +196,80 @@ handle_transfer_data (void *cls,
 
 
 /**
+ * Free session data kept in @a ctx
+ *
+ * @param ctx context to clean up
+ */
+static void
+purge_context (struct HTD_Context *ctx)
+{
+  for (unsigned int i=0;i<ctx->num_sessions;i++)
+    TEH_plugin->free_link_data_list (TEH_plugin->cls,
+                                    ctx->sessions[i].ldl);
+  GNUNET_free_non_null (ctx->sessions);
+  ctx->sessions = NULL;
+  ctx->num_sessions = 0;
+}
+
+
+/**
  * Execute a "/refresh/link".  Returns the linkage information that
  * will allow the owner of a coin to follow the refresh trail to
  * the refreshed coin.
  *
- * @param connection the MHD connection to handle
- * @param coin_pub public key of the coin to link
- * @return MHD result code
+ * 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
+ * it returns the soft error code, the function MAY be called again to
+ * retry and MUST not queue a MHD response.
+ *
+ * @param cls closure
+ * @param connection MHD request which triggered the transaction
+ * @param session database session to use
+ * @param[out] mhd_ret set to MHD response status for @a connection,
+ *             if transaction failed (!)
+ * @return transaction status
  */
-static int
-execute_refresh_link (struct MHD_Connection *connection,
-                     const struct TALER_CoinSpendPublicKeyP *coin_pub)
+static enum GNUNET_DB_QueryStatus
+refresh_link_transaction (void *cls,
+                         struct MHD_Connection *connection,
+                         struct TALER_EXCHANGEDB_Session *session,
+                         int *mhd_ret)
 {
-  struct HTD_Context ctx;
-  int res;
-  unsigned int i;
+  struct HTD_Context *ctx = cls;
+  enum GNUNET_DB_QueryStatus qs;
 
-  if (NULL == (ctx.session = TEH_plugin->get_session (TEH_plugin->cls)))
-  {
-    GNUNET_break (0);
-    return TEH_RESPONSE_reply_internal_db_error (connection,
-                                                TALER_EC_DB_SETUP_FAILED);
-  }
-  ctx.connection = connection;
-  ctx.num_sessions = 0;
-  ctx.sessions = NULL;
-  ctx.status = GNUNET_OK;
-  res = TEH_plugin->get_transfer (TEH_plugin->cls,
-                                  ctx.session,
-                                  coin_pub,
-                                  &handle_transfer_data,
-                                  &ctx);
-  if (GNUNET_SYSERR == ctx.status)
+  ctx->session = session;
+  ctx->status = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  qs = TEH_plugin->get_transfer (TEH_plugin->cls,
+                                session,
+                                &ctx->coin_pub,
+                                &handle_transfer_data,
+                                ctx);
+  ctx->session = NULL;
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   {
-    res = MHD_NO;
-    goto cleanup;
+    *mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection,
+                                              
TALER_EC_REFRESH_LINK_COIN_UNKNOWN,
+                                              "coin_pub");
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  if (GNUNET_NO == ctx.status)
+  if (0 < qs)
   {
-    res = MHD_YES;
-    goto cleanup;
+    qs = ctx->status;
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+    {
+      *mhd_ret = TEH_RESPONSE_reply_json_pack (ctx->connection,
+                                              MHD_HTTP_NOT_FOUND,
+                                              "{s:s}",
+                                              "error",
+                                              "link data not found (link)");
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    return qs;
   }
-  GNUNET_assert (GNUNET_OK == ctx.status);
-  if (0 == ctx.num_sessions)
-    return TEH_RESPONSE_reply_arg_unknown (connection,
-                                          TALER_EC_REFRESH_LINK_COIN_UNKNOWN,
-                                           "coin_pub");
-  res = reply_refresh_link_success (connection,
-                                   ctx.num_sessions,
-                                   ctx.sessions);
- cleanup:
-  for (i=0;i<ctx.num_sessions;i++)
-    TEH_plugin->free_link_data_list (TEH_plugin->cls,
-                                     ctx.sessions[i].ldl);
-  GNUNET_free_non_null (ctx.sessions);
-  return res;
+  purge_context (ctx);
+  return qs;
 }
 
 
@@ -267,19 +291,35 @@ TEH_REFRESH_handler_refresh_link (struct 
TEH_RequestHandler *rh,
                                   const char *upload_data,
                                   size_t *upload_data_size)
 {
-  struct TALER_CoinSpendPublicKeyP coin_pub;
+  int mhd_ret;
   int res;
+  struct HTD_Context ctx;
 
+  memset (&ctx,
+         0,
+         sizeof (ctx));
   res = TEH_PARSE_mhd_request_arg_data (connection,
                                         "coin_pub",
-                                        &coin_pub,
+                                        &ctx.coin_pub,
                                         sizeof (struct 
TALER_CoinSpendPublicKeyP));
   if (GNUNET_SYSERR == res)
     return MHD_NO;
   if (GNUNET_OK != res)
     return MHD_YES;
-  return execute_refresh_link (connection,
-                              &coin_pub);
+  if (GNUNET_OK !=
+      TEH_DB_run_transaction (connection,
+                             &mhd_ret,
+                             &refresh_link_transaction,
+                             &ctx))
+  {
+    purge_context (&ctx);
+    return mhd_ret;
+  }
+  mhd_ret = reply_refresh_link_success (connection,
+                                       ctx.num_sessions,
+                                       ctx.sessions);
+  purge_context (&ctx);
+  return mhd_ret;
 }
 
 
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index b029db5..b11eec1 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3895,45 +3895,38 @@ postgres_insert_refresh_out (void *cls,
 
 
 /**
- * Obtain the link data of a coin, that is the encrypted link
- * information, the denomination keys and the signatures.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param session database connection
- * @param session_hash refresh session to get linkage data for
- * @return all known link data for the session
+ * Closure for #add_ldl().
  */
-static struct TALER_EXCHANGEDB_LinkDataList *
-postgres_get_link_data_list (void *cls,
-                             struct TALER_EXCHANGEDB_Session *session,
-                             const struct GNUNET_HashCode *session_hash)
+struct LinkDataContext
 {
+  /** 
+   * List we are building.
+   */ 
   struct TALER_EXCHANGEDB_LinkDataList *ldl;
-  int nrows;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (session_hash),
-    GNUNET_PQ_query_param_end
-  };
-  PGresult *result;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "get_link",
-                                   params);
-  ldl = NULL;
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return NULL;
-  }
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    PQclear (result);
-    return NULL;
-  }
+  /**
+   * Status, set to #GNUNET_SYSERR on errors,
+   */
+  int status;
+};
+
 
-  for (int i = nrows-1; i >= 0; i--)
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct LinkDataContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+add_ldl (void *cls,
+        PGresult *result,
+        unsigned int num_results)
+{
+  struct LinkDataContext *ldc = cls;
+  
+  for (int i = num_results - 1; i >= 0; i--)
   {
     struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
     struct GNUNET_CRYPTO_RsaSignature *sig;
@@ -3954,71 +3947,98 @@ postgres_get_link_data_list (void *cls,
                                     rs,
                                     i))
       {
-       PQclear (result);
        GNUNET_break (0);
        common_free_link_data_list (cls,
-                                   ldl);
+                                   ldc->ldl);
+       ldc->ldl = NULL;
        GNUNET_free (pos);
-       return NULL;
+       ldc->status = GNUNET_SYSERR;
+       return;
       }
     }
-    pos->next = ldl;
+    pos->next = ldc->ldl;
     pos->denom_pub.rsa_public_key = denom_pub;
     pos->ev_sig.rsa_signature = sig;
-    ldl = pos;
+    ldc->ldl = pos;
   }
-  PQclear (result);
-  return ldl;
 }
 
 
 /**
- * Obtain shared secret and transfer public key from the public key of
- * the coin.  This information and the link information returned by
- * #postgres_get_link_data_list() enable the owner of an old coin to
- * determine the private keys of the new coins after the melt.
+ * Obtain the link data of a coin, that is the encrypted link
+ * information, the denomination keys and the signatures.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @param session database connection
- * @param coin_pub public key of the coin
- * @param tdc function to call for each session the coin was melted into
- * @param tdc_cls closure for @a tdc
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO on failure (not found)
- *         #GNUNET_SYSERR on internal failure (database issue)
+ * @param session_hash refresh session to get linkage data for
+ * @param[out] ldlp set to all known link data for the session
+ * @return transaction status code
  */
-static int
-postgres_get_transfer (void *cls,
-                       struct TALER_EXCHANGEDB_Session *session,
-                       const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                       TALER_EXCHANGEDB_TransferDataCallback tdc,
-                       void *tdc_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_get_link_data_list (void *cls,
+                             struct TALER_EXCHANGEDB_Session *session,
+                             const struct GNUNET_HashCode *session_hash,
+                            struct TALER_EXCHANGEDB_LinkDataList **ldlp)
 {
+  struct LinkDataContext ldc;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (session_hash),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  int nrows;
+  enum GNUNET_DB_QueryStatus qs;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "get_transfer",
-                                   params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    /* no matches found */
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+  ldc.status = GNUNET_OK;
+  ldc.ldl = NULL;
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "get_link",
+                                            params,
+                                            &add_ldl,
+                                            &ldc);
+  *ldlp = ldc.ldl;
+  if (GNUNET_OK != ldc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
+ * Closure for #add_link().
+ */
+struct AddLinkContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_TransferDataCallback tdc;
+
+  /**
+   * Closure for @e tdc.
+   */
+  void *tdc_cls;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on errors.
+   */
+  int status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct AddLinkContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+add_link (void *cls,
+         PGresult *result,
+         unsigned int num_results)
+{
+  struct AddLinkContext *alc = cls;
+
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct GNUNET_HashCode session_hash;
     struct TALER_TransferPublicKeyP transfer_pub;
@@ -4033,16 +4053,55 @@ postgres_get_transfer (void *cls,
                                   rs,
                                   i))
     {
-      PQclear (result);
       GNUNET_break (0);
-      return GNUNET_SYSERR;
+      alc->status = GNUNET_SYSERR;
+      return;
     }
-    tdc (tdc_cls,
-         &session_hash,
-         &transfer_pub);
+    alc->tdc (alc->tdc_cls,
+             &session_hash,
+             &transfer_pub);
   }
-  PQclear (result);
-  return GNUNET_OK;
+}
+
+
+/**
+ * Obtain shared secret and transfer public key from the public key of
+ * the coin.  This information and the link information returned by
+ * #postgres_get_link_data_list() enable the owner of an old coin to
+ * determine the private keys of the new coins after the melt.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param session database connection
+ * @param coin_pub public key of the coin
+ * @param tdc function to call for each session the coin was melted into
+ * @param tdc_cls closure for @a tdc
+ * @return statement execution status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_get_transfer (void *cls,
+                       struct TALER_EXCHANGEDB_Session *session,
+                       const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                       TALER_EXCHANGEDB_TransferDataCallback tdc,
+                       void *tdc_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct AddLinkContext al_ctx;
+  enum GNUNET_DB_QueryStatus qs;
+
+  al_ctx.tdc = tdc;
+  al_ctx.tdc_cls = tdc_cls;
+  al_ctx.status = GNUNET_OK;
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "get_transfer",
+                                            params,
+                                            &add_link,
+                                            &al_ctx);
+  if (GNUNET_OK != al_ctx.status)
+    qs = GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 9a58a38..df730a0 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -530,6 +530,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
   struct TALER_DenominationSignature ev_sigs[MELT_NEW_COINS];
   unsigned int cnt;
   int ret;
+  enum GNUNET_DB_QueryStatus qs;
 
   ret = GNUNET_SYSERR;
   memset (ev_sigs, 0, sizeof (ev_sigs));
@@ -695,9 +696,11 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
     GNUNET_CRYPTO_rsa_signature_free (test_sig.rsa_signature);
   }
 
-  ldl = plugin->get_link_data_list (plugin->cls,
-                                    session,
-                                    &session_hash);
+  qs = plugin->get_link_data_list (plugin->cls,
+                                  session,
+                                  &session_hash,
+                                  &ldl);
+  FAILIF (0 >= qs);
   FAILIF (NULL == ldl);
   for (ldlp = ldl; NULL != ldlp; ldlp = ldlp->next)
   {
@@ -742,7 +745,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
     int ok;
 
     ok = GNUNET_NO;
-    FAILIF (GNUNET_OK !=
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
             plugin->get_transfer (plugin->cls,
                                   session,
                                   &meltp->coin.coin_pub,
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 23e80c0..0406c8d 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -1652,12 +1652,14 @@ struct TALER_EXCHANGEDB_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session database connection
    * @param session_hash session to get linkage data for
-   * @return all known link data for the session
+   * @param[out] ldldp set to all known link data for the session
+   * @return status of the transaction
    */
-  struct TALER_EXCHANGEDB_LinkDataList *
+  enum GNUNET_DB_QueryStatus
   (*get_link_data_list) (void *cls,
                          struct TALER_EXCHANGEDB_Session *session,
-                         const struct GNUNET_HashCode *session_hash);
+                         const struct GNUNET_HashCode *session_hash,
+                        struct TALER_EXCHANGEDB_LinkDataList **ldlp);
 
 
   /**
@@ -1682,11 +1684,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param coin_pub public key of the coin
    * @param tdc function to call for each session the coin was melted into
    * @param tdc_cls closure for @a tdc
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO on failure (not found)
-   *         #GNUNET_SYSERR on internal failure (database issue)
+   * @return statement execution status
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_transfer) (void *cls,
                    struct TALER_EXCHANGEDB_Session *session,
                    const struct TALER_CoinSpendPublicKeyP *coin_pub,

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



reply via email to

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