diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-11-23 13:40:13 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-11-23 13:40:13 +0100 |
commit | 0429b0cede718e3306e088993023dbe3b47c3382 (patch) | |
tree | a23a061faacecfa0837cd4846c87a6f39f6db4af /src/exchangedb/pg_batch_reserves_in_insert.c | |
parent | 505ea0a0431d54dd8be76cb6ca6c7846db04d76f (diff) | |
parent | d3b46de9f82574cdb85ae2ad7a7a5cb5390471f2 (diff) | |
download | exchange-0429b0cede718e3306e088993023dbe3b47c3382.tar.gz exchange-0429b0cede718e3306e088993023dbe3b47c3382.tar.bz2 exchange-0429b0cede718e3306e088993023dbe3b47c3382.zip |
Merge branch 'master' of git+ssh://git.taler.net/exchange
Diffstat (limited to 'src/exchangedb/pg_batch_reserves_in_insert.c')
-rw-r--r-- | src/exchangedb/pg_batch_reserves_in_insert.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.c b/src/exchangedb/pg_batch_reserves_in_insert.c new file mode 100644 index 000000000..4a1a2792e --- /dev/null +++ b/src/exchangedb/pg_batch_reserves_in_insert.c @@ -0,0 +1,150 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file exchangedb/pg_batch_reserves_in_insert.c + * @brief Implementation of the reserves_in_insert function for Postgres + * @author JOSEPHxu + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_batch_reserves_in_insert.h" +#include "pg_helper.h" +#include "pg_start.h" +#include "pg_rollback.h" +#include "pg_start_read_committed.h" +#include "pg_commit.h" +#include "pg_reserves_get.h" +#include "pg_reserves_update.h" +#include "pg_setup_wire_target.h" +#include "pg_event_notify.h" + + +/** + * Generate event notification for the reserve + * change. + * + * @param pg plugin state + * @param reserve_pub reserve to notfiy on + */ +static void +notify_on_reserve (struct PostgresClosure *pg, + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct TALER_ReserveEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING), + .reserve_pub = *reserve_pub + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Notifying on reserve!\n"); + TEH_PG_event_notify (pg, + &rep.header, + NULL, + 0); +} + + +enum GNUNET_DB_QueryStatus +TEH_PG_batch_reserves_in_insert (void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs1; + struct GNUNET_TIME_Timestamp expiry; + struct GNUNET_TIME_Timestamp gc; + struct TALER_PaytoHashP h_payto; + uint64_t reserve_uuid; + bool conflicted; + bool transaction_duplicate; + struct GNUNET_TIME_Timestamp reserve_expiration + = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); + + PREPARE (pg, + "reserve_create", + "SELECT " + "out_reserve_found AS conflicted" + ",transaction_duplicate" + ",ruuid AS reserve_uuid" + " FROM batch_reserves_in" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); + expiry = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (reserves->execution_time.abs_time, + pg->idle_reserve_expiration_time)); + gc = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + pg->legal_reserve_expiration_time)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating reserve %s with expiration in %s\n", + TALER_B2S (&(reserves->reserve_pub)), + GNUNET_STRINGS_relative_time_to_string ( + pg->idle_reserve_expiration_time, + GNUNET_NO)); + /* Optimistically assume this is a new reserve, create balance for the first + time; we do this before adding the actual transaction to "reserves_in", + as for a new reserve it can't be a duplicate 'add' operation, and as + the 'add' operation needs the reserve entry as a foreign key. */ + for (unsigned int i=0;i<reserves_length;i++) + { + const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i]; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub), /*$1*/ + GNUNET_PQ_query_param_timestamp (&expiry), /*$4*/ + GNUNET_PQ_query_param_timestamp (&gc), /*$5*/ + GNUNET_PQ_query_param_uint64 (&reserve->wire_reference), /*6*/ + TALER_PQ_query_param_amount (&reserve->balance), /*7+8*/ + GNUNET_PQ_query_param_string (reserve->exchange_account_name), /*9*/ + GNUNET_PQ_query_param_timestamp (&reserve->execution_time), /*10*/ + GNUNET_PQ_query_param_auto_from_type (&h_payto), /*11*/ + GNUNET_PQ_query_param_string (reserve->sender_account_details),/*12*/ + GNUNET_PQ_query_param_timestamp (&reserve_expiration),/*13*/ + GNUNET_PQ_query_param_end + }; + /* We should get all our results into results[]*/ + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("reserve_uuid", + &reserve_uuid), + GNUNET_PQ_result_spec_bool ("conflicted", + &conflicted), + GNUNET_PQ_result_spec_bool ("transaction_duplicate", + &transaction_duplicate), + GNUNET_PQ_result_spec_end + }; + + TALER_payto_hash (reserve->sender_account_details, + &h_payto); + /* Note: query uses 'on conflict do nothing' */ + qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserve_create", + params, + rs); + if (qs1 < 0) + return qs1; + notify_on_reserve (pg, + &reserve->reserve_pub); + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1); + results[i] = (transaction_duplicate) + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + if ( (! conflicted) && transaction_duplicate) + TEH_PG_rollback(pg); + } + return reserves_length; +} |