-implement reserve closure in test
This commit is contained in:
parent
4fc77b9dbf
commit
09310cc66e
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2016-2021 Taler Systems SA
|
Copyright (C) 2016-2022 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU Affero General Public License as published by the Free Software
|
terms of the GNU Affero General Public License as published by the Free Software
|
||||||
@ -431,11 +431,18 @@ run_reserve_closures (void *cls)
|
|||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Checking for reserves to close by date %s\n",
|
"Checking for reserves to close by date %s\n",
|
||||||
GNUNET_TIME_timestamp2s (now));
|
GNUNET_TIME_timestamp2s (now));
|
||||||
qs = db_plugin->get_expired_reserves (db_plugin->cls,
|
qs = db_plugin->get_unfinished_close_requests (db_plugin->cls,
|
||||||
now,
|
&expired_reserve_cb,
|
||||||
&expired_reserve_cb,
|
NULL);
|
||||||
NULL);
|
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||||
GNUNET_assert (1 >= qs);
|
{
|
||||||
|
/* Try expired reserves as well */
|
||||||
|
qs = db_plugin->get_expired_reserves (
|
||||||
|
db_plugin->cls,
|
||||||
|
now,
|
||||||
|
&expired_reserve_cb,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
switch (qs)
|
switch (qs)
|
||||||
{
|
{
|
||||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||||
|
@ -70,6 +70,8 @@ endif
|
|||||||
libtaler_plugin_exchangedb_postgres_la_SOURCES = \
|
libtaler_plugin_exchangedb_postgres_la_SOURCES = \
|
||||||
plugin_exchangedb_postgres.c pg_helper.h \
|
plugin_exchangedb_postgres.c pg_helper.h \
|
||||||
pg_do_reserve_open.c pg_do_reserve_open.h \
|
pg_do_reserve_open.c pg_do_reserve_open.h \
|
||||||
|
pg_get_expired_reserves.c pg_get_expired_reserves.h \
|
||||||
|
pg_get_unfinished_close_requests.c pg_get_unfinished_close_requests.h \
|
||||||
pg_insert_close_request.c pg_insert_close_request.h \
|
pg_insert_close_request.c pg_insert_close_request.h \
|
||||||
pg_insert_records_by_table.c pg_insert_records_by_table.h \
|
pg_insert_records_by_table.c pg_insert_records_by_table.h \
|
||||||
pg_insert_reserve_open_deposit.c pg_insert_reserve_open_deposit.h \
|
pg_insert_reserve_open_deposit.c pg_insert_reserve_open_deposit.h \
|
||||||
|
@ -51,32 +51,28 @@ prepare (struct GNUNET_PQ_Context *conn)
|
|||||||
"(hc"
|
"(hc"
|
||||||
",expiration_date"
|
",expiration_date"
|
||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2);",
|
"($1, $2);"),
|
||||||
2),
|
|
||||||
/* Used in #postgres_iterate_denomination_info() */
|
/* Used in #postgres_iterate_denomination_info() */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"bm_select",
|
"bm_select",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" expiration_date"
|
" expiration_date"
|
||||||
" FROM benchmap"
|
" FROM benchmap"
|
||||||
" WHERE hc=$1;",
|
" WHERE hc=$1;"),
|
||||||
1),
|
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"bhm_insert",
|
"bhm_insert",
|
||||||
"INSERT INTO benchhmap "
|
"INSERT INTO benchhmap "
|
||||||
"(hc"
|
"(hc"
|
||||||
",expiration_date"
|
",expiration_date"
|
||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2);",
|
"($1, $2);"),
|
||||||
2),
|
|
||||||
/* Used in #postgres_iterate_denomination_info() */
|
/* Used in #postgres_iterate_denomination_info() */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"bhm_select",
|
"bhm_select",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" expiration_date"
|
" expiration_date"
|
||||||
" FROM benchhmap"
|
" FROM benchhmap"
|
||||||
" WHERE hc=$1;",
|
" WHERE hc=$1;"),
|
||||||
1),
|
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"bem_insert",
|
"bem_insert",
|
||||||
"INSERT INTO benchemap "
|
"INSERT INTO benchemap "
|
||||||
@ -84,16 +80,14 @@ prepare (struct GNUNET_PQ_Context *conn)
|
|||||||
",ihc"
|
",ihc"
|
||||||
",expiration_date"
|
",expiration_date"
|
||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3);",
|
"($1, $2, $3);"),
|
||||||
3),
|
|
||||||
/* Used in #postgres_iterate_denomination_info() */
|
/* Used in #postgres_iterate_denomination_info() */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"bem_select",
|
"bem_select",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" expiration_date"
|
" expiration_date"
|
||||||
" FROM benchemap"
|
" FROM benchemap"
|
||||||
" WHERE ihc=$1 AND hc=$2;",
|
" WHERE ihc=$1 AND hc=$2;"),
|
||||||
2),
|
|
||||||
GNUNET_PQ_PREPARED_STATEMENT_END
|
GNUNET_PQ_PREPARED_STATEMENT_END
|
||||||
};
|
};
|
||||||
enum GNUNET_GenericReturnValue ret;
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
@ -502,57 +502,6 @@ END
|
|||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
|
||||||
--------------------------- reserves_close_requests -------------------------------
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION create_table_reserves_close_requests(
|
|
||||||
IN shard_suffix VARCHAR DEFAULT NULL
|
|
||||||
)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE plpgsql
|
|
||||||
AS $$
|
|
||||||
DECLARE
|
|
||||||
table_name VARCHAR default 'reserves_close_requests';
|
|
||||||
BEGIN
|
|
||||||
|
|
||||||
PERFORM create_partitioned_table(
|
|
||||||
'CREATE TABLE IF NOT EXISTS %I'
|
|
||||||
'(close_request_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE / PRIMARY KEY'
|
|
||||||
',reserve_pub BYTEA NOT NULL' -- REFERENCES reserves (reserve_pub) ON DELETE CASCADE'
|
|
||||||
',execution_date INT8 NOT NULL'
|
|
||||||
',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
|
|
||||||
',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
|
|
||||||
') %s ;'
|
|
||||||
,table_name
|
|
||||||
,'PARTITION BY HASH (reserve_pub)'
|
|
||||||
,shard_suffix
|
|
||||||
);
|
|
||||||
|
|
||||||
table_name = concat_ws('_', table_name, shard_suffix);
|
|
||||||
|
|
||||||
EXECUTE FORMAT (
|
|
||||||
'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_close_request_uuid_index '
|
|
||||||
'ON ' || table_name || ' '
|
|
||||||
'(close_request_uuid);'
|
|
||||||
);
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION add_constraints_to_reserves_close_requests_partition(
|
|
||||||
IN partition_suffix VARCHAR
|
|
||||||
)
|
|
||||||
RETURNS void
|
|
||||||
LANGUAGE plpgsql
|
|
||||||
AS $$
|
|
||||||
BEGIN
|
|
||||||
EXECUTE FORMAT (
|
|
||||||
'ALTER TABLE reserves_close_requests_' || partition_suffix || ' '
|
|
||||||
'ADD CONSTRAINT reserves_close_' || partition_suffix || '_close_request_uuid_pkey '
|
|
||||||
'PRIMARY KEY (close_request_uuid)'
|
|
||||||
);
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
|
|
||||||
|
|
||||||
---------------------------- reserves_out -------------------------------
|
---------------------------- reserves_out -------------------------------
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION create_table_reserves_out(
|
CREATE OR REPLACE FUNCTION create_table_reserves_out(
|
||||||
@ -1752,16 +1701,57 @@ BEGIN
|
|||||||
',close_fee_val INT8 NOT NULL'
|
',close_fee_val INT8 NOT NULL'
|
||||||
',close_fee_frac INT4 NOT NULL'
|
',close_fee_frac INT4 NOT NULL'
|
||||||
',payto_uri VARCHAR NOT NULL'
|
',payto_uri VARCHAR NOT NULL'
|
||||||
|
',done BOOL NOT NULL DEFAULT(FALSE)'
|
||||||
',PRIMARY KEY (reserve_pub,close_timestamp)'
|
',PRIMARY KEY (reserve_pub,close_timestamp)'
|
||||||
') %s ;'
|
') %s ;'
|
||||||
,table_name
|
,table_name
|
||||||
,'PARTITION BY HASH (reserve_pub)'
|
,'PARTITION BY HASH (reserve_pub)'
|
||||||
,shard_suffix
|
,shard_suffix
|
||||||
);
|
);
|
||||||
|
|
||||||
END
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION add_constraints_to_close_requests(
|
||||||
|
IN partition_suffix VARCHAR
|
||||||
|
)
|
||||||
|
RETURNS VOID
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
table_name VARCHAR DEFAULT 'close_requests';
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
EXECUTE FORMAT (
|
||||||
|
'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_close_request_uuid_index '
|
||||||
|
'ON ' || table_name || ' '
|
||||||
|
'(close_request_serial_id);'
|
||||||
|
);
|
||||||
|
EXECUTE FORMAT (
|
||||||
|
'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_close_request_done_index '
|
||||||
|
'ON ' || table_name || ' '
|
||||||
|
'(done);'
|
||||||
|
);
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION add_constraints_to_close_requests_partition(
|
||||||
|
IN partition_suffix VARCHAR
|
||||||
|
)
|
||||||
|
RETURNS void
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
BEGIN
|
||||||
|
EXECUTE FORMAT (
|
||||||
|
'ALTER TABLE close_requests_' || partition_suffix || ' '
|
||||||
|
'ADD CONSTRAINT close_requests_' || partition_suffix || '_close_request_uuid_pkey '
|
||||||
|
'UNIQUE (close_request_serial_id)'
|
||||||
|
);
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------- purse_deposits -------------------------------
|
------------------------------- purse_deposits -------------------------------
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION create_table_purse_deposits(
|
CREATE OR REPLACE FUNCTION create_table_purse_deposits(
|
||||||
|
@ -269,22 +269,6 @@ CREATE TABLE IF NOT EXISTS reserves_open_deposits_default
|
|||||||
SELECT add_constraints_to_reserves_open_deposits_partition('default');
|
SELECT add_constraints_to_reserves_open_deposits_partition('default');
|
||||||
|
|
||||||
|
|
||||||
-- ------------------------------ reserves_close_requests ----------------------------------------
|
|
||||||
|
|
||||||
SELECT create_table_reserves_close_requests();
|
|
||||||
|
|
||||||
COMMENT ON TABLE reserves_close_requests
|
|
||||||
IS 'explicit requests by clients to affect an immediate closure of a reserve';
|
|
||||||
COMMENT ON COLUMN reserves_close_requests.wire_target_h_payto
|
|
||||||
IS 'Identifies the credited bank account. Optional.';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS reserves_close_requests_default
|
|
||||||
PARTITION OF reserves_close_requests
|
|
||||||
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
|
|
||||||
|
|
||||||
SELECT add_constraints_to_reserves_close_requests_partition('default');
|
|
||||||
|
|
||||||
|
|
||||||
-- ------------------------------ reserves_out ----------------------------------------
|
-- ------------------------------ reserves_out ----------------------------------------
|
||||||
|
|
||||||
SELECT create_table_reserves_out();
|
SELECT create_table_reserves_out();
|
||||||
@ -1284,11 +1268,14 @@ COMMENT ON COLUMN close_requests.reserve_sig
|
|||||||
IS 'Signature affirming that the reserve is to be closed';
|
IS 'Signature affirming that the reserve is to be closed';
|
||||||
COMMENT ON COLUMN close_requests.close_val
|
COMMENT ON COLUMN close_requests.close_val
|
||||||
IS 'Balance of the reserve at the time of closing, to be wired to the associated bank account (minus the closing fee)';
|
IS 'Balance of the reserve at the time of closing, to be wired to the associated bank account (minus the closing fee)';
|
||||||
|
COMMENT ON COLUMN close_requests.payto_uri
|
||||||
|
IS 'Identifies the credited bank account. Optional.';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS close_requests_default
|
CREATE TABLE IF NOT EXISTS close_requests_default
|
||||||
PARTITION OF close_requests
|
PARTITION OF close_requests
|
||||||
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
|
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
|
||||||
|
|
||||||
|
SELECT add_constraints_to_close_requests_partition('default');
|
||||||
|
|
||||||
-- ------------------------------ purse_deposits ----------------------------------------
|
-- ------------------------------ purse_deposits ----------------------------------------
|
||||||
|
|
||||||
|
173
src/exchangedb/pg_get_expired_reserves.c
Normal file
173
src/exchangedb/pg_get_expired_reserves.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
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 pg_get_expired_reserves.c
|
||||||
|
* @brief Low-level (statement-level) Postgres database access for the exchange
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include "taler_error_codes.h"
|
||||||
|
#include "taler_dbevents.h"
|
||||||
|
#include "taler_pq_lib.h"
|
||||||
|
#include "pg_get_expired_reserves.h"
|
||||||
|
#include "pg_helper.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for #reserve_expired_cb().
|
||||||
|
*/
|
||||||
|
struct ExpiredReserveContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Function to call for each expired reserve.
|
||||||
|
*/
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure to give to @e rec.
|
||||||
|
*/
|
||||||
|
void *rec_cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin context.
|
||||||
|
*/
|
||||||
|
struct PostgresClosure *pg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to #GNUNET_SYSERR on error.
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue status;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called with the results of a SELECT statement
|
||||||
|
* that has returned @a num_results results.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param result the postgres result
|
||||||
|
* @param num_results the number of results in @a result
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
reserve_expired_cb (void *cls,
|
||||||
|
PGresult *result,
|
||||||
|
unsigned int num_results)
|
||||||
|
{
|
||||||
|
struct ExpiredReserveContext *erc = cls;
|
||||||
|
struct PostgresClosure *pg = erc->pg;
|
||||||
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
|
||||||
|
ret = GNUNET_OK;
|
||||||
|
for (unsigned int i = 0; i<num_results; i++)
|
||||||
|
{
|
||||||
|
struct GNUNET_TIME_Timestamp exp_date;
|
||||||
|
char *account_details;
|
||||||
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
|
struct TALER_Amount remaining_balance;
|
||||||
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
|
GNUNET_PQ_result_spec_timestamp ("expiration_date",
|
||||||
|
&exp_date),
|
||||||
|
GNUNET_PQ_result_spec_string ("account_details",
|
||||||
|
&account_details),
|
||||||
|
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
|
||||||
|
&reserve_pub),
|
||||||
|
TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
|
||||||
|
&remaining_balance),
|
||||||
|
GNUNET_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_PQ_extract_result (result,
|
||||||
|
rs,
|
||||||
|
i))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
ret = GNUNET_SYSERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = erc->rec (erc->rec_cls,
|
||||||
|
&reserve_pub,
|
||||||
|
&remaining_balance,
|
||||||
|
account_details,
|
||||||
|
exp_date);
|
||||||
|
GNUNET_PQ_cleanup_result (rs);
|
||||||
|
if (GNUNET_OK != ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
erc->status = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
TEH_PG_get_expired_reserves (void *cls,
|
||||||
|
struct GNUNET_TIME_Timestamp now,
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec,
|
||||||
|
void *rec_cls)
|
||||||
|
{
|
||||||
|
struct PostgresClosure *pg = cls;
|
||||||
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
|
GNUNET_PQ_query_param_timestamp (&now),
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
|
struct ExpiredReserveContext ectx = {
|
||||||
|
.rec = rec,
|
||||||
|
.rec_cls = rec_cls,
|
||||||
|
.pg = pg,
|
||||||
|
.status = GNUNET_OK
|
||||||
|
};
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
|
PREPARE (pg,
|
||||||
|
"get_expired_reserves",
|
||||||
|
"WITH ed AS MATERIALIZED ( "
|
||||||
|
" SELECT * "
|
||||||
|
" FROM reserves "
|
||||||
|
" WHERE expiration_date <= $1 "
|
||||||
|
" AND (current_balance_val != 0 OR current_balance_frac != 0) "
|
||||||
|
" ORDER BY expiration_date ASC "
|
||||||
|
" LIMIT 1 "
|
||||||
|
") "
|
||||||
|
"SELECT "
|
||||||
|
" ed.expiration_date "
|
||||||
|
" ,payto_uri AS account_details "
|
||||||
|
" ,ed.reserve_pub "
|
||||||
|
" ,current_balance_val "
|
||||||
|
" ,current_balance_frac "
|
||||||
|
"FROM ( "
|
||||||
|
" SELECT "
|
||||||
|
" * "
|
||||||
|
" FROM reserves_in "
|
||||||
|
" WHERE reserve_pub = ( "
|
||||||
|
" SELECT reserve_pub FROM ed) "
|
||||||
|
" ) ri "
|
||||||
|
"JOIN wire_targets wt ON (ri.wire_source_h_payto = wt.wire_target_h_payto) "
|
||||||
|
"JOIN ed ON (ri.reserve_pub = ed.reserve_pub);");
|
||||||
|
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
|
||||||
|
"get_expired_reserves",
|
||||||
|
params,
|
||||||
|
&reserve_expired_cb,
|
||||||
|
&ectx);
|
||||||
|
switch (ectx.status)
|
||||||
|
{
|
||||||
|
case GNUNET_SYSERR:
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
case GNUNET_NO:
|
||||||
|
return GNUNET_DB_STATUS_SOFT_ERROR;
|
||||||
|
case GNUNET_OK:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return qs;
|
||||||
|
}
|
45
src/exchangedb/pg_get_expired_reserves.h
Normal file
45
src/exchangedb/pg_get_expired_reserves.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
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 pg_get_expired_reserves.h
|
||||||
|
* @brief implementation of the get_expired_reserves function
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#ifndef PG_GET_EXPIRED_RESERVES_H
|
||||||
|
#define PG_GET_EXPIRED_RESERVES_H
|
||||||
|
|
||||||
|
#include "taler_util.h"
|
||||||
|
#include "taler_json_lib.h"
|
||||||
|
#include "taler_exchangedb_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain information about expired reserves and their
|
||||||
|
* remaining balances.
|
||||||
|
*
|
||||||
|
* @param cls closure of the plugin
|
||||||
|
* @param now timestamp based on which we decide expiration
|
||||||
|
* @param rec function to call on expired reserves
|
||||||
|
* @param rec_cls closure for @a rec
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
TEH_PG_get_expired_reserves (void *cls,
|
||||||
|
struct GNUNET_TIME_Timestamp now,
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec,
|
||||||
|
void *rec_cls);
|
||||||
|
|
||||||
|
#endif
|
162
src/exchangedb/pg_get_unfinished_close_requests.c
Normal file
162
src/exchangedb/pg_get_unfinished_close_requests.c
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
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 pg_get_unfinished_close_requests.c
|
||||||
|
* @brief Low-level (statement-level) Postgres database access for the exchange
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include "taler_error_codes.h"
|
||||||
|
#include "taler_dbevents.h"
|
||||||
|
#include "taler_pq_lib.h"
|
||||||
|
#include "pg_get_unfinished_close_requests.h"
|
||||||
|
#include "pg_helper.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for #reserve_close_cb().
|
||||||
|
*/
|
||||||
|
struct CloseReserveContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Function to call for each to be closed reserve.
|
||||||
|
*/
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure to give to @e rec.
|
||||||
|
*/
|
||||||
|
void *rec_cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin context.
|
||||||
|
*/
|
||||||
|
struct PostgresClosure *pg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to #GNUNET_SYSERR on error.
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue status;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called with the results of a SELECT statement
|
||||||
|
* that has returned @a num_results results.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param result the postgres result
|
||||||
|
* @param num_results the number of results in @a result
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
reserve_cb (void *cls,
|
||||||
|
PGresult *result,
|
||||||
|
unsigned int num_results)
|
||||||
|
{
|
||||||
|
struct CloseReserveContext *erc = cls;
|
||||||
|
struct PostgresClosure *pg = erc->pg;
|
||||||
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
|
||||||
|
ret = GNUNET_OK;
|
||||||
|
for (unsigned int i = 0; i<num_results; i++)
|
||||||
|
{
|
||||||
|
struct GNUNET_TIME_Timestamp exp_date;
|
||||||
|
char *account_details;
|
||||||
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
|
struct TALER_Amount remaining_balance;
|
||||||
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
|
GNUNET_PQ_result_spec_timestamp ("expiration_date",
|
||||||
|
&exp_date),
|
||||||
|
GNUNET_PQ_result_spec_string ("account_details",
|
||||||
|
&account_details),
|
||||||
|
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
|
||||||
|
&reserve_pub),
|
||||||
|
TALER_PQ_RESULT_SPEC_AMOUNT ("close",
|
||||||
|
&remaining_balance),
|
||||||
|
GNUNET_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_PQ_extract_result (result,
|
||||||
|
rs,
|
||||||
|
i))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
ret = GNUNET_SYSERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = erc->rec (erc->rec_cls,
|
||||||
|
&reserve_pub,
|
||||||
|
&remaining_balance,
|
||||||
|
account_details,
|
||||||
|
exp_date);
|
||||||
|
GNUNET_PQ_cleanup_result (rs);
|
||||||
|
if (GNUNET_OK != ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
erc->status = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
TEH_PG_get_unfinished_close_requests (
|
||||||
|
void *cls,
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec,
|
||||||
|
void *rec_cls)
|
||||||
|
{
|
||||||
|
struct PostgresClosure *pg = cls;
|
||||||
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
|
struct CloseReserveContext ectx = {
|
||||||
|
.rec = rec,
|
||||||
|
.rec_cls = rec_cls,
|
||||||
|
.pg = pg,
|
||||||
|
.status = GNUNET_OK
|
||||||
|
};
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
|
PREPARE (pg,
|
||||||
|
"get_unfinished_close_requests",
|
||||||
|
"UPDATE close_requests AS rc"
|
||||||
|
" SET done=TRUE"
|
||||||
|
" WHERE done=FALSE"
|
||||||
|
" RETURNING"
|
||||||
|
" reserve_pub"
|
||||||
|
" ,close_timestamp AS expiration_date"
|
||||||
|
" ,close_val"
|
||||||
|
" ,close_frac"
|
||||||
|
" ,(SELECT payto_uri"
|
||||||
|
" FROM reserves_in ri"
|
||||||
|
" JOIN wire_targets wt ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
|
||||||
|
" WHERE ri.reserve_pub=rc.reserve_pub)"
|
||||||
|
" AS account_details;");
|
||||||
|
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
|
||||||
|
"get_unfinished_close_requests",
|
||||||
|
params,
|
||||||
|
&reserve_cb,
|
||||||
|
&ectx);
|
||||||
|
switch (ectx.status)
|
||||||
|
{
|
||||||
|
case GNUNET_SYSERR:
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
case GNUNET_NO:
|
||||||
|
return GNUNET_DB_STATUS_SOFT_ERROR;
|
||||||
|
case GNUNET_OK:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return qs;
|
||||||
|
}
|
46
src/exchangedb/pg_get_unfinished_close_requests.h
Normal file
46
src/exchangedb/pg_get_unfinished_close_requests.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
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 pg_get_unfinished_close_requests.h
|
||||||
|
* @brief implementation of the get_unfinished_close_requests function
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#ifndef PG_GET_UNFINISHED_CLOSE_REQUESTS_H
|
||||||
|
#define PG_GET_UNFINISHED_CLOSE_REQUESTS_H
|
||||||
|
|
||||||
|
#include "taler_util.h"
|
||||||
|
#include "taler_json_lib.h"
|
||||||
|
#include "taler_exchangedb_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain information about force-closed reserves
|
||||||
|
* where the close was not yet done (and their remaining
|
||||||
|
* balances). Updates the returned reserve's close
|
||||||
|
* status to "done".
|
||||||
|
*
|
||||||
|
* @param cls closure of the plugin
|
||||||
|
* @param rec function to call on expired reserves
|
||||||
|
* @param rec_cls closure for @a rec
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
TEH_PG_get_unfinished_close_requests (
|
||||||
|
void *cls,
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec,
|
||||||
|
void *rec_cls);
|
||||||
|
|
||||||
|
#endif
|
@ -429,46 +429,6 @@ irbt_cb_table_reserves_open_deposits (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function called with reserves_close records to insert into table.
|
|
||||||
*
|
|
||||||
* @param pg plugin context
|
|
||||||
* @param td record to insert
|
|
||||||
*/
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
irbt_cb_table_reserves_close_requests (
|
|
||||||
struct PostgresClosure *pg,
|
|
||||||
const struct TALER_EXCHANGEDB_TableData *td)
|
|
||||||
{
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_uint64 (&td->serial),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (
|
|
||||||
&td->details.reserves_close_requests.reserve_pub),
|
|
||||||
GNUNET_PQ_query_param_timestamp (
|
|
||||||
&td->details.reserves_close_requests.execution_date),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (
|
|
||||||
&td->details.reserves_close_requests.reserve_sig),
|
|
||||||
GNUNET_PQ_query_param_auto_from_type (
|
|
||||||
&td->details.reserves_close_requests.wire_target_h_payto),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
|
|
||||||
PREPARE (pg,
|
|
||||||
"insert_into_table_reserves_close_requests",
|
|
||||||
"INSERT INTO reserves_close_requests"
|
|
||||||
"(close_request_uuid"
|
|
||||||
",reserve_pub"
|
|
||||||
",execution_date"
|
|
||||||
",reserve_sig"
|
|
||||||
",wire_target_h_payto"
|
|
||||||
") VALUES "
|
|
||||||
"($1, $2, $3, $4, $5);");
|
|
||||||
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
|
||||||
"insert_into_table_reserves_close_requests",
|
|
||||||
params);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called with reserves_close records to insert into table.
|
* Function called with reserves_close records to insert into table.
|
||||||
*
|
*
|
||||||
@ -1582,6 +1542,10 @@ irbt_cb_table_close_requests (struct PostgresClosure *pg,
|
|||||||
&td->details.close_requests.reserve_sig),
|
&td->details.close_requests.reserve_sig),
|
||||||
TALER_PQ_query_param_amount (
|
TALER_PQ_query_param_amount (
|
||||||
&td->details.close_requests.close),
|
&td->details.close_requests.close),
|
||||||
|
TALER_PQ_query_param_amount (
|
||||||
|
&td->details.close_requests.close_fee),
|
||||||
|
GNUNET_PQ_query_param_string (
|
||||||
|
td->details.close_requests.payto_uri),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1594,8 +1558,11 @@ irbt_cb_table_close_requests (struct PostgresClosure *pg,
|
|||||||
",reserve_sig"
|
",reserve_sig"
|
||||||
",close_val"
|
",close_val"
|
||||||
",close_frac"
|
",close_frac"
|
||||||
|
",close_fee_val"
|
||||||
|
",close_fee_frac"
|
||||||
|
",payto_uri"
|
||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3, $4, $5, $6);");
|
"($1, $2, $3, $4, $5, $6, $7, $8, $9);");
|
||||||
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
||||||
"insert_into_table_close_requests",
|
"insert_into_table_close_requests",
|
||||||
params);
|
params);
|
||||||
@ -1883,9 +1850,6 @@ TEH_PG_insert_records_by_table (void *cls,
|
|||||||
case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
|
case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
|
||||||
rh = &irbt_cb_table_reserves_open_deposits;
|
rh = &irbt_cb_table_reserves_open_deposits;
|
||||||
break;
|
break;
|
||||||
case TALER_EXCHANGEDB_RT_RESERVES_CLOSE_REQUESTS:
|
|
||||||
rh = &irbt_cb_table_reserves_close_requests;
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_RT_RESERVES_OUT:
|
case TALER_EXCHANGEDB_RT_RESERVES_OUT:
|
||||||
rh = &irbt_cb_table_reserves_out;
|
rh = &irbt_cb_table_reserves_out;
|
||||||
break;
|
break;
|
||||||
|
@ -1867,12 +1867,21 @@ lrbt_cb_table_close_requests (void *cls,
|
|||||||
GNUNET_PQ_result_spec_auto_from_type (
|
GNUNET_PQ_result_spec_auto_from_type (
|
||||||
"reserve_pub",
|
"reserve_pub",
|
||||||
&td.details.close_requests.reserve_pub),
|
&td.details.close_requests.reserve_pub),
|
||||||
|
GNUNET_PQ_result_spec_timestamp (
|
||||||
|
"close_timestamp",
|
||||||
|
&td.details.close_requests.close_timestamp),
|
||||||
GNUNET_PQ_result_spec_auto_from_type (
|
GNUNET_PQ_result_spec_auto_from_type (
|
||||||
"reserve_sig",
|
"reserve_sig",
|
||||||
&td.details.close_requests.reserve_sig),
|
&td.details.close_requests.reserve_sig),
|
||||||
TALER_PQ_RESULT_SPEC_AMOUNT (
|
TALER_PQ_RESULT_SPEC_AMOUNT (
|
||||||
"close",
|
"close",
|
||||||
&td.details.close_requests.close),
|
&td.details.close_requests.close),
|
||||||
|
TALER_PQ_RESULT_SPEC_AMOUNT (
|
||||||
|
"close_fee",
|
||||||
|
&td.details.close_requests.close_fee),
|
||||||
|
GNUNET_PQ_result_spec_string (
|
||||||
|
"payto_uri",
|
||||||
|
&td.details.close_requests.payto_uri),
|
||||||
GNUNET_PQ_result_spec_end
|
GNUNET_PQ_result_spec_end
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,14 +133,6 @@ TEH_PG_lookup_serial_by_table (void *cls,
|
|||||||
" ORDER BY open_request_uuid DESC"
|
" ORDER BY open_request_uuid DESC"
|
||||||
" LIMIT 1;");
|
" LIMIT 1;");
|
||||||
break;
|
break;
|
||||||
case TALER_EXCHANGEDB_RT_RESERVES_CLOSE_REQUESTS:
|
|
||||||
XPREPARE ("select_serial_by_table_reserves_close_requests",
|
|
||||||
"SELECT"
|
|
||||||
" close_request_uuid AS serial"
|
|
||||||
" FROM reserves_close_requests"
|
|
||||||
" ORDER BY close_request_uuid DESC"
|
|
||||||
" LIMIT 1;");
|
|
||||||
break;
|
|
||||||
case TALER_EXCHANGEDB_RT_RESERVES_OUT:
|
case TALER_EXCHANGEDB_RT_RESERVES_OUT:
|
||||||
XPREPARE ("select_serial_by_table_reserves_out",
|
XPREPARE ("select_serial_by_table_reserves_out",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include "taler_exchangedb_plugin.h"
|
#include "taler_exchangedb_plugin.h"
|
||||||
#include "pg_helper.h"
|
#include "pg_helper.h"
|
||||||
#include "pg_do_reserve_open.h"
|
#include "pg_do_reserve_open.h"
|
||||||
|
#include "pg_get_expired_reserves.h"
|
||||||
|
#include "pg_get_unfinished_close_requests.h"
|
||||||
#include "pg_insert_close_request.h"
|
#include "pg_insert_close_request.h"
|
||||||
#include "pg_insert_records_by_table.h"
|
#include "pg_insert_records_by_table.h"
|
||||||
#include "pg_insert_reserve_open_deposit.h"
|
#include "pg_insert_reserve_open_deposit.h"
|
||||||
@ -2344,32 +2346,6 @@ prepare_statements (struct PostgresClosure *pg)
|
|||||||
" FROM history_requests"
|
" FROM history_requests"
|
||||||
" WHERE reserve_pub=$1"
|
" WHERE reserve_pub=$1"
|
||||||
" AND request_timestamp>=$2;"),
|
" AND request_timestamp>=$2;"),
|
||||||
/* Used in #postgres_get_expired_reserves() */
|
|
||||||
GNUNET_PQ_make_prepare (
|
|
||||||
"get_expired_reserves",
|
|
||||||
"WITH ed AS MATERIALIZED ( "
|
|
||||||
" SELECT * "
|
|
||||||
" FROM reserves "
|
|
||||||
" WHERE expiration_date <= $1 "
|
|
||||||
" AND (current_balance_val != 0 OR current_balance_frac != 0) "
|
|
||||||
" ORDER BY expiration_date ASC "
|
|
||||||
" LIMIT 1 "
|
|
||||||
") "
|
|
||||||
"SELECT "
|
|
||||||
" ed.expiration_date "
|
|
||||||
" ,payto_uri AS account_details "
|
|
||||||
" ,ed.reserve_pub "
|
|
||||||
" ,current_balance_val "
|
|
||||||
" ,current_balance_frac "
|
|
||||||
"FROM ( "
|
|
||||||
" SELECT "
|
|
||||||
" * "
|
|
||||||
" FROM reserves_in "
|
|
||||||
" WHERE reserve_pub = ( "
|
|
||||||
" SELECT reserve_pub FROM ed) "
|
|
||||||
" ) ri "
|
|
||||||
"JOIN wire_targets wt ON (ri.wire_source_h_payto = wt.wire_target_h_payto) "
|
|
||||||
"JOIN ed ON (ri.reserve_pub = ed.reserve_pub);"),
|
|
||||||
/* Used in #postgres_get_coin_transactions() to obtain recoup transactions
|
/* Used in #postgres_get_coin_transactions() to obtain recoup transactions
|
||||||
for a coin */
|
for a coin */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
@ -8550,138 +8526,6 @@ postgres_insert_global_fee (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closure for #reserve_expired_cb().
|
|
||||||
*/
|
|
||||||
struct ExpiredReserveContext
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Function to call for each expired reserve.
|
|
||||||
*/
|
|
||||||
TALER_EXCHANGEDB_ReserveExpiredCallback rec;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closure to give to @e rec.
|
|
||||||
*/
|
|
||||||
void *rec_cls;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin context.
|
|
||||||
*/
|
|
||||||
struct PostgresClosure *pg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to #GNUNET_SYSERR on error.
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue status;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to be called with the results of a SELECT statement
|
|
||||||
* that has returned @a num_results results.
|
|
||||||
*
|
|
||||||
* @param cls closure
|
|
||||||
* @param result the postgres result
|
|
||||||
* @param num_results the number of results in @a result
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
reserve_expired_cb (void *cls,
|
|
||||||
PGresult *result,
|
|
||||||
unsigned int num_results)
|
|
||||||
{
|
|
||||||
struct ExpiredReserveContext *erc = cls;
|
|
||||||
struct PostgresClosure *pg = erc->pg;
|
|
||||||
enum GNUNET_GenericReturnValue ret;
|
|
||||||
|
|
||||||
ret = GNUNET_OK;
|
|
||||||
for (unsigned int i = 0; i<num_results; i++)
|
|
||||||
{
|
|
||||||
struct GNUNET_TIME_Timestamp exp_date;
|
|
||||||
char *account_details;
|
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
|
||||||
struct TALER_Amount remaining_balance;
|
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
|
||||||
GNUNET_PQ_result_spec_timestamp ("expiration_date",
|
|
||||||
&exp_date),
|
|
||||||
GNUNET_PQ_result_spec_string ("account_details",
|
|
||||||
&account_details),
|
|
||||||
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
|
|
||||||
&reserve_pub),
|
|
||||||
TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
|
|
||||||
&remaining_balance),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_PQ_extract_result (result,
|
|
||||||
rs,
|
|
||||||
i))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
ret = GNUNET_SYSERR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ret = erc->rec (erc->rec_cls,
|
|
||||||
&reserve_pub,
|
|
||||||
&remaining_balance,
|
|
||||||
account_details,
|
|
||||||
exp_date);
|
|
||||||
GNUNET_PQ_cleanup_result (rs);
|
|
||||||
if (GNUNET_OK != ret)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
erc->status = ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain information about expired reserves and their
|
|
||||||
* remaining balances.
|
|
||||||
*
|
|
||||||
* @param cls closure of the plugin
|
|
||||||
* @param now timestamp based on which we decide expiration
|
|
||||||
* @param rec function to call on expired reserves
|
|
||||||
* @param rec_cls closure for @a rec
|
|
||||||
* @return transaction status
|
|
||||||
*/
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
postgres_get_expired_reserves (void *cls,
|
|
||||||
struct GNUNET_TIME_Timestamp now,
|
|
||||||
TALER_EXCHANGEDB_ReserveExpiredCallback rec,
|
|
||||||
void *rec_cls)
|
|
||||||
{
|
|
||||||
struct PostgresClosure *pg = cls;
|
|
||||||
struct GNUNET_PQ_QueryParam params[] = {
|
|
||||||
GNUNET_PQ_query_param_timestamp (&now),
|
|
||||||
GNUNET_PQ_query_param_end
|
|
||||||
};
|
|
||||||
struct ExpiredReserveContext ectx = {
|
|
||||||
.rec = rec,
|
|
||||||
.rec_cls = rec_cls,
|
|
||||||
.pg = pg,
|
|
||||||
.status = GNUNET_OK
|
|
||||||
};
|
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
|
||||||
|
|
||||||
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
|
|
||||||
"get_expired_reserves",
|
|
||||||
params,
|
|
||||||
&reserve_expired_cb,
|
|
||||||
&ectx);
|
|
||||||
switch (ectx.status)
|
|
||||||
{
|
|
||||||
case GNUNET_SYSERR:
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
case GNUNET_NO:
|
|
||||||
return GNUNET_DB_STATUS_SOFT_ERROR;
|
|
||||||
case GNUNET_OK:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return qs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert reserve close operation into database.
|
* Insert reserve close operation into database.
|
||||||
*
|
*
|
||||||
@ -15118,7 +14962,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
|||||||
plugin->get_wire_fee = &postgres_get_wire_fee;
|
plugin->get_wire_fee = &postgres_get_wire_fee;
|
||||||
plugin->get_global_fee = &postgres_get_global_fee;
|
plugin->get_global_fee = &postgres_get_global_fee;
|
||||||
plugin->get_global_fees = &postgres_get_global_fees;
|
plugin->get_global_fees = &postgres_get_global_fees;
|
||||||
plugin->get_expired_reserves = &postgres_get_expired_reserves;
|
|
||||||
plugin->insert_reserve_closed = &postgres_insert_reserve_closed;
|
plugin->insert_reserve_closed = &postgres_insert_reserve_closed;
|
||||||
plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert;
|
plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert;
|
||||||
plugin->wire_prepare_data_mark_finished =
|
plugin->wire_prepare_data_mark_finished =
|
||||||
@ -15290,6 +15133,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
|||||||
/* NEW style, sort alphabetically! */
|
/* NEW style, sort alphabetically! */
|
||||||
plugin->do_reserve_open
|
plugin->do_reserve_open
|
||||||
= &TEH_PG_do_reserve_open;
|
= &TEH_PG_do_reserve_open;
|
||||||
|
plugin->get_expired_reserves
|
||||||
|
= &TEH_PG_get_expired_reserves;
|
||||||
|
plugin->get_unfinished_close_requests
|
||||||
|
= &TEH_PG_get_unfinished_close_requests;
|
||||||
plugin->insert_records_by_table
|
plugin->insert_records_by_table
|
||||||
= &TEH_PG_insert_records_by_table;
|
= &TEH_PG_insert_records_by_table;
|
||||||
plugin->insert_reserve_open_deposit
|
plugin->insert_reserve_open_deposit
|
||||||
|
@ -50,9 +50,6 @@ BEGIN
|
|||||||
PERFORM create_table_reserves_open_deposits(shard_suffix);
|
PERFORM create_table_reserves_open_deposits(shard_suffix);
|
||||||
PERFORM add_constraints_to_reserves_open_deposits_partition(shard_suffix);
|
PERFORM add_constraints_to_reserves_open_deposits_partition(shard_suffix);
|
||||||
|
|
||||||
PERFORM create_table_reserves_close_requests(shard_suffix);
|
|
||||||
PERFORM add_constraints_to_reserves_close_requests_partition(shard_suffix);
|
|
||||||
|
|
||||||
PERFORM create_table_reserves_out(shard_suffix);
|
PERFORM create_table_reserves_out(shard_suffix);
|
||||||
PERFORM add_constraints_to_reserves_out_partition(shard_suffix);
|
PERFORM add_constraints_to_reserves_out_partition(shard_suffix);
|
||||||
|
|
||||||
@ -119,6 +116,8 @@ BEGIN
|
|||||||
PERFORM create_table_history_requests(shard_suffix);
|
PERFORM create_table_history_requests(shard_suffix);
|
||||||
|
|
||||||
PERFORM create_table_close_requests(shard_suffix);
|
PERFORM create_table_close_requests(shard_suffix);
|
||||||
|
PERFORM add_constraints_to_close_requests_partition(shard_suffix);
|
||||||
|
|
||||||
|
|
||||||
PERFORM create_table_purse_deposits(shard_suffix);
|
PERFORM create_table_purse_deposits(shard_suffix);
|
||||||
PERFORM add_constraints_to_purse_deposits_partition(shard_suffix);
|
PERFORM add_constraints_to_purse_deposits_partition(shard_suffix);
|
||||||
|
@ -202,7 +202,6 @@ enum TALER_EXCHANGEDB_ReplicatedTable
|
|||||||
TALER_EXCHANGEDB_RT_RESERVES_CLOSE,
|
TALER_EXCHANGEDB_RT_RESERVES_CLOSE,
|
||||||
TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS,
|
TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS,
|
||||||
TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS,
|
TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS,
|
||||||
TALER_EXCHANGEDB_RT_RESERVES_CLOSE_REQUESTS,
|
|
||||||
TALER_EXCHANGEDB_RT_RESERVES_OUT,
|
TALER_EXCHANGEDB_RT_RESERVES_OUT,
|
||||||
TALER_EXCHANGEDB_RT_AUDITORS,
|
TALER_EXCHANGEDB_RT_AUDITORS,
|
||||||
TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS,
|
TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS,
|
||||||
@ -337,14 +336,6 @@ struct TALER_EXCHANGEDB_TableData
|
|||||||
struct TALER_Amount contribution;
|
struct TALER_Amount contribution;
|
||||||
} reserves_open_deposits;
|
} reserves_open_deposits;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
|
||||||
struct GNUNET_TIME_Timestamp execution_date;
|
|
||||||
struct TALER_ReserveSignatureP reserve_sig;
|
|
||||||
struct TALER_PaytoHashP wire_target_h_payto;
|
|
||||||
} reserves_close_requests;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
@ -587,6 +578,8 @@ struct TALER_EXCHANGEDB_TableData
|
|||||||
struct GNUNET_TIME_Timestamp close_timestamp;
|
struct GNUNET_TIME_Timestamp close_timestamp;
|
||||||
struct TALER_ReserveSignatureP reserve_sig;
|
struct TALER_ReserveSignatureP reserve_sig;
|
||||||
struct TALER_Amount close;
|
struct TALER_Amount close;
|
||||||
|
struct TALER_Amount close_fee;
|
||||||
|
char *payto_uri;
|
||||||
} close_requests;
|
} close_requests;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
@ -4110,6 +4103,24 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
void *rec_cls);
|
void *rec_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain information about force-closed reserves
|
||||||
|
* where the close was not yet done (and their remaining
|
||||||
|
* balances). Updates the returned reserve's close
|
||||||
|
* status to "done".
|
||||||
|
*
|
||||||
|
* @param cls closure of the plugin
|
||||||
|
* @param rec function to call on (to be) closed reserves
|
||||||
|
* @param rec_cls closure for @a rec
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
(*get_unfinished_close_requests)(
|
||||||
|
void *cls,
|
||||||
|
TALER_EXCHANGEDB_ReserveExpiredCallback rec,
|
||||||
|
void *rec_cls);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert reserve open coin deposit data into database.
|
* Insert reserve open coin deposit data into database.
|
||||||
* Subtracts the @a coin_total from the coin's balance.
|
* Subtracts the @a coin_total from the coin's balance.
|
||||||
|
@ -446,8 +446,6 @@ run (void *cls,
|
|||||||
"create-reserve-101",
|
"create-reserve-101",
|
||||||
NULL, /* to origin */
|
NULL, /* to origin */
|
||||||
MHD_HTTP_OK),
|
MHD_HTTP_OK),
|
||||||
#if FIXME
|
|
||||||
/* reserve close logic is not yet implemented, hence this fails: */
|
|
||||||
TALER_TESTING_cmd_exec_closer ("close-reserves-101",
|
TALER_TESTING_cmd_exec_closer ("close-reserves-101",
|
||||||
config_file,
|
config_file,
|
||||||
"EUR:1.02",
|
"EUR:1.02",
|
||||||
@ -459,7 +457,6 @@ run (void *cls,
|
|||||||
"create-reserve-101",
|
"create-reserve-101",
|
||||||
"EUR:0",
|
"EUR:0",
|
||||||
MHD_HTTP_OK),
|
MHD_HTTP_OK),
|
||||||
#endif
|
|
||||||
TALER_TESTING_cmd_end ()
|
TALER_TESTING_cmd_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user