LCOV - code coverage report
Current view: top level - backenddb - pg_insert_transfer_details.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.2 % 63 48
Test Date: 2025-11-06 19:31:41 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :    This file is part of TALER
       3              :    Copyright (C) 2022 Taler Systems SA
       4              : 
       5              :    TALER is free software; you can redistribute it and/or modify it under the
       6              :    terms of the GNU General Public License as published by the Free Software
       7              :    Foundation; either version 3, or (at your option) any later version.
       8              : 
       9              :    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10              :    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11              :    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12              : 
      13              :    You should have received a copy of the GNU General Public License along with
      14              :    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15              :  */
      16              : /**
      17              :  * @file backenddb/pg_insert_transfer_details.c
      18              :  * @brief Implementation of the insert_transfer_details function for Postgres
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "platform.h"
      22              : #include <taler/taler_error_codes.h>
      23              : #include <taler/taler_dbevents.h>
      24              : #include <taler/taler_pq_lib.h>
      25              : #include "pg_insert_transfer_details.h"
      26              : #include "pg_helper.h"
      27              : 
      28              : 
      29              : /**
      30              :  * How often do we re-try if we run into a DB serialization error?
      31              :  */
      32              : #define MAX_RETRIES 3
      33              : 
      34              : 
      35              : enum GNUNET_DB_QueryStatus
      36            8 : TMH_PG_insert_transfer_details (
      37              :   void *cls,
      38              :   const char *instance_id,
      39              :   const char *exchange_url,
      40              :   struct TALER_FullPayto payto_uri,
      41              :   const struct TALER_WireTransferIdentifierRawP *wtid,
      42              :   const struct TALER_EXCHANGE_TransferData *td)
      43            8 : {
      44            8 :   struct PostgresClosure *pg = cls;
      45            8 :   unsigned int len = td->details_length;
      46            8 :   struct TALER_Amount coin_values[GNUNET_NZL (len)];
      47            8 :   struct TALER_Amount deposit_fees[GNUNET_NZL (len)];
      48            8 :   const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (len)];
      49            8 :   const struct TALER_PrivateContractHashP *contract_terms[GNUNET_NZL (len)];
      50              :   enum GNUNET_DB_QueryStatus qs;
      51              :   bool duplicate;
      52              : 
      53           16 :   for (unsigned int i = 0; i<len; i++)
      54              :   {
      55            8 :     const struct TALER_TrackTransferDetails *tdd = &td->details[i];
      56              : 
      57            8 :     coin_values[i] = tdd->coin_value;
      58            8 :     deposit_fees[i] = tdd->coin_fee;
      59            8 :     coin_pubs[i] = &tdd->coin_pub;
      60            8 :     contract_terms[i] = &tdd->h_contract_terms;
      61              :   }
      62              : 
      63            8 :   check_connection (pg);
      64            8 :   PREPARE (pg,
      65              :            "insert_transfer_details",
      66              :            "SELECT"
      67              :            " out_no_instance"
      68              :            ",out_no_account"
      69              :            ",out_no_exchange"
      70              :            ",out_duplicate"
      71              :            ",out_conflict"
      72              :            " FROM merchant_do_insert_transfer_details"
      73              :            " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);");
      74              : 
      75            8 :   for (unsigned int retries = 0;
      76            8 :        retries < MAX_RETRIES;
      77            0 :        retries++)
      78              :   {
      79            8 :     if (GNUNET_OK !=
      80            8 :         TMH_PG_start (pg,
      81              :                       "insert transfer details"))
      82              :     {
      83            0 :       GNUNET_break (0);
      84            0 :       return GNUNET_DB_STATUS_HARD_ERROR;
      85              :     }
      86              : 
      87              :     {
      88            8 :       struct GNUNET_PQ_QueryParam params[] = {
      89            8 :         GNUNET_PQ_query_param_string (instance_id),
      90            8 :         GNUNET_PQ_query_param_string (exchange_url),
      91            8 :         GNUNET_PQ_query_param_string (payto_uri.full_payto),
      92            8 :         GNUNET_PQ_query_param_auto_from_type (wtid),
      93            8 :         GNUNET_PQ_query_param_timestamp (&td->execution_time),
      94            8 :         GNUNET_PQ_query_param_auto_from_type (&td->exchange_pub),
      95            8 :         GNUNET_PQ_query_param_auto_from_type (&td->exchange_sig),
      96            8 :         TALER_PQ_query_param_amount_with_currency (pg->conn,
      97              :                                                    &td->total_amount),
      98            8 :         TALER_PQ_query_param_amount_with_currency (pg->conn,
      99              :                                                    &td->wire_fee),
     100            8 :         TALER_PQ_query_param_array_amount_with_currency (
     101              :           len,
     102              :           coin_values,
     103              :           pg->conn),
     104            8 :         TALER_PQ_query_param_array_amount_with_currency (
     105              :           len,
     106              :           deposit_fees,
     107              :           pg->conn),
     108            8 :         GNUNET_PQ_query_param_array_ptrs_auto_from_type (
     109              :           len,
     110              :           coin_pubs,
     111              :           pg->conn),
     112            8 :         GNUNET_PQ_query_param_array_ptrs_auto_from_type (
     113              :           len,
     114              :           contract_terms,
     115              :           pg->conn),
     116              :         GNUNET_PQ_query_param_end
     117              :       };
     118              :       bool no_instance;
     119              :       bool no_account;
     120              :       bool no_exchange;
     121              :       bool conflict;
     122            8 :       struct GNUNET_PQ_ResultSpec rs[] = {
     123            8 :         GNUNET_PQ_result_spec_bool ("out_no_instance",
     124              :                                     &no_instance),
     125            8 :         GNUNET_PQ_result_spec_bool ("out_no_account",
     126              :                                     &no_account),
     127            8 :         GNUNET_PQ_result_spec_bool ("out_no_exchange",
     128              :                                     &no_exchange),
     129            8 :         GNUNET_PQ_result_spec_bool ("out_duplicate",
     130              :                                     &duplicate),
     131            8 :         GNUNET_PQ_result_spec_bool ("out_conflict",
     132              :                                     &conflict),
     133              :         GNUNET_PQ_result_spec_end
     134              :       };
     135              : 
     136            8 :       qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
     137              :                                                      "insert_transfer_details",
     138              :                                                      params,
     139              :                                                      rs);
     140            8 :       GNUNET_PQ_cleanup_query_params_closures (params);
     141            8 :       if (0 >= qs)
     142              :       {
     143            0 :         GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     144            0 :         TMH_PG_rollback (pg);
     145            0 :         if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
     146            0 :           continue;
     147            0 :         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     148              :                     "'insert_transfer_details' failed with status %d\n",
     149              :                     qs);
     150            0 :         return qs;
     151              :       }
     152            8 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     153              :                   "Transfer details inserted: %s%s%s%s%s\n",
     154              :                   no_instance ? "no instance " : "",
     155              :                   no_account ? "no account " : "",
     156              :                   no_exchange ? "no exchange ": "",
     157              :                   duplicate ? "duplicate ": "",
     158              :                   conflict ? "conflict" : "");
     159              :     }
     160              : 
     161            8 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     162              :                 "Committing transaction...\n");
     163            8 :     qs = TMH_PG_commit (pg);
     164            8 :     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     165            8 :       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     166            0 :     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     167            0 :     if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
     168            0 :       break;
     169              :   }
     170            0 :   if (duplicate)
     171            0 :     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
     172            0 :   return qs;
     173              : }
        

Generated by: LCOV version 2.0-1