diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-09-19 20:28:37 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-09-19 20:28:37 +0200 |
commit | cc47c5c701340c9be0acc6b7394aa2afad0cd0d3 (patch) | |
tree | b64bbcdc7b2dcabdbfe9a0c501e7964e63be55be /src/mintdb | |
parent | f8a730a0ab6db9ca37c652493b844a7a5ff503e0 (diff) | |
download | exchange-cc47c5c701340c9be0acc6b7394aa2afad0cd0d3.tar.gz exchange-cc47c5c701340c9be0acc6b7394aa2afad0cd0d3.tar.bz2 exchange-cc47c5c701340c9be0acc6b7394aa2afad0cd0d3.zip |
implement #3838 (as required for wire transfers)
Diffstat (limited to 'src/mintdb')
-rw-r--r-- | src/mintdb/plugin_mintdb_postgres.c | 123 |
1 files changed, 119 insertions, 4 deletions
diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index efb73a321..86db0a11e 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -426,7 +426,7 @@ postgres_create_tables (void *cls, /* This table contains the wire transfers the mint is supposed to execute to transmit funds to the merchants (and manage refunds). */ SQLEXEC("CREATE TABLE IF NOT EXISTS deposits " - "(id BIGSERIAL" + "(serial_id BIGSERIAL" ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)" ",denom_pub BYTEA NOT NULL REFERENCES denominations (pub)" ",denom_sig BYTEA NOT NULL" @@ -852,8 +852,8 @@ postgres_prepare (PGconn *db_conn) /* Used in #postgres_iterate_deposits() */ PREPARE ("deposits_iterate", "SELECT" - " id" - " amount_with_fee_val" + " serial_id" + ",amount_with_fee_val" ",amount_with_fee_frac" ",amount_with_fee_curr" ",deposit_fee_val" @@ -863,7 +863,8 @@ postgres_prepare (PGconn *db_conn) ",h_contract" ",wire" " FROM deposits" - " WHERE id>=$1" + " WHERE serial_id>=$1" + " ORDER BY serial_id ASC" " LIMIT $2;", 2, NULL); /* Used in #postgres_get_coin_transactions() to obtain information @@ -1895,6 +1896,119 @@ postgres_have_deposit (void *cls, /** + * Obtain information about deposits. Iterates over all deposits + * above a certain ID. Use a @a min_id of 0 to start at the beginning. + * This operation is executed in its own transaction in transaction + * mode "REPEATABLE READ", i.e. we should only see valid deposits. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param min_id deposit to start at + * @param limit maximum number of transactions to fetch + * @param deposit_cb function to call for each deposit + * @param deposit_cb_cls closure for @a deposit_cb + * @return number of rows processed, 0 if none exist, + * #GNUNET_SYSERR on error + */ +static int +postgres_iterate_deposits (void *cls, + struct TALER_MINTDB_Session *session, + uint64_t min_id, + uint32_t limit, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls) +{ + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_uint64 (&min_id), + TALER_PQ_query_param_uint32 (&limit), + TALER_PQ_query_param_end + }; + PGresult *result; + unsigned int i; + unsigned int n; + + if (GNUNET_OK != + postgres_start (cls, session)) + return GNUNET_SYSERR; + result = PQexec (session->conn, + "SET TRANSACTION REPEATABLE READ"); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + TALER_LOG_ERROR ("Failed to set transaction to REPEATABL EREAD: %s\n", + PQresultErrorMessage (result)); + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + result = TALER_PQ_exec_prepared (session->conn, + "deposits_iterate", + params); + if (PGRES_TUPLES_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + postgres_rollback (cls, session); + return GNUNET_SYSERR; + } + if (0 == (n = PQntuples (result))) + { + PQclear (result); + postgres_rollback (cls, session); + return 0; + } + for (i=0;i<n;i++) + { + struct TALER_Amount amount_with_fee; + struct TALER_Amount deposit_fee; + struct GNUNET_HashCode h_contract; + json_t *wire; + uint64_t transaction_id; + uint64_t id; + int ret; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_uint64 ("id", + &id), + TALER_PQ_result_spec_uint64 ("transaction_id", + &transaction_id), + TALER_PQ_result_spec_amount ("amount_with_fee", + &amount_with_fee), + TALER_PQ_result_spec_amount ("deposit_fee", + &deposit_fee), + TALER_PQ_result_spec_auto_from_type ("h_contract", + &h_contract), + TALER_PQ_result_spec_json ("wire", + &wire), + TALER_PQ_result_spec_end + }; + if (GNUNET_OK != + TALER_PQ_extract_result (result, rs, i)) + { + GNUNET_break (0); + PQclear (result); + postgres_rollback (cls, session); + return GNUNET_SYSERR; + } + ret = deposit_cb (deposit_cb_cls, + id, + &amount_with_fee, + &deposit_fee, + transaction_id, + &h_contract, + wire); + TALER_PQ_cleanup_result (rs); + PQclear (result); + if (GNUNET_OK != ret) + break; + } + postgres_rollback (cls, session); + return i; +} + + +/** * Insert information about deposited coin into the database. * * @param cls the `struct PostgresClosure` with the plugin-specific state @@ -3280,6 +3394,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_reserve_history = &postgres_get_reserve_history; plugin->free_reserve_history = &common_free_reserve_history; plugin->have_deposit = &postgres_have_deposit; + plugin->iterate_deposits = &postgres_iterate_deposits; plugin->insert_deposit = &postgres_insert_deposit; plugin->get_refresh_session = &postgres_get_refresh_session; |