LCOV - code coverage report
Current view: top level - auditordb - plugin_auditordb_postgres.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 306 410 74.6 %
Date: 2017-11-25 11:31:41 Functions: 45 51 88.2 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2017 GNUnet e.V.
       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             : /**
      18             :  * @file plugin_auditordb_postgres.c
      19             :  * @brief Low-level (statement-level) Postgres database access for the auditor
      20             :  * @author Christian Grothoff
      21             :  * @author Gabor X Toth
      22             :  */
      23             : #include "platform.h"
      24             : #include "taler_pq_lib.h"
      25             : #include "taler_auditordb_plugin.h"
      26             : #include <pthread.h>
      27             : #include <libpq-fe.h>
      28             : 
      29             : 
      30             : #define LOG(kind,...) GNUNET_log_from (kind, "taler-auditordb-postgres", __VA_ARGS__)
      31             : 
      32             : 
      33             : /**
      34             :  * Handle for a database session (per-thread, for transactions).
      35             :  */
      36             : struct TALER_AUDITORDB_Session
      37             : {
      38             :   /**
      39             :    * Postgres connection handle.
      40             :    */
      41             :   PGconn *conn;
      42             : };
      43             : 
      44             : 
      45             : /**
      46             :  * Type of the "cls" argument given to each of the functions in
      47             :  * our API.
      48             :  */
      49             : struct PostgresClosure
      50             : {
      51             : 
      52             :   /**
      53             :    * Thread-local database connection.
      54             :    * Contains a pointer to `PGconn` or NULL.
      55             :    */
      56             :   pthread_key_t db_conn_threadlocal;
      57             : 
      58             :   /**
      59             :    * Database connection string, as read from
      60             :    * the configuration.
      61             :    */
      62             :   char *connection_cfg_str;
      63             : };
      64             : 
      65             : 
      66             : /**
      67             :  * Function called by libpq whenever it wants to log something.
      68             :  * We already log whenever we care, so this function does nothing
      69             :  * and merely exists to silence the libpq logging.
      70             :  *
      71             :  * @param arg NULL
      72             :  * @param res information about some libpq event
      73             :  */
      74             : static void
      75          31 : pq_notice_receiver_cb (void *arg,
      76             :                        const PGresult *res)
      77             : {
      78             :   /* do nothing, intentionally */
      79          31 : }
      80             : 
      81             : 
      82             : /**
      83             :  * Function called by libpq whenever it wants to log something.
      84             :  * We log those using the Taler logger.
      85             :  *
      86             :  * @param arg NULL
      87             :  * @param message information about some libpq event
      88             :  */
      89             : static void
      90           0 : pq_notice_processor_cb (void *arg,
      91             :                         const char *message)
      92             : {
      93           0 :   LOG (GNUNET_ERROR_TYPE_INFO,
      94             :        "%s",
      95             :        message);
      96           0 : }
      97             : 
      98             : 
      99             : /**
     100             :  * Establish connection to the Postgres database
     101             :  * and initialize callbacks for logging.
     102             :  *
     103             :  * @param pc configuration to use
     104             :  * @return NULL on error
     105             :  */
     106             : static PGconn *
     107          10 : connect_to_postgres (struct PostgresClosure *pc)
     108             : {
     109             :   PGconn *conn;
     110             : 
     111          10 :   conn = PQconnectdb (pc->connection_cfg_str);
     112          10 :   if (CONNECTION_OK !=
     113          10 :       PQstatus (conn))
     114             :   {
     115           0 :     TALER_LOG_ERROR ("Database connection failed: %s\n",
     116             :                      PQerrorMessage (conn));
     117           0 :     GNUNET_break (0);
     118           0 :     return NULL;
     119             :   }
     120          10 :   PQsetNoticeReceiver (conn,
     121             :                        &pq_notice_receiver_cb,
     122             :                        NULL);
     123          10 :   PQsetNoticeProcessor (conn,
     124             :                         &pq_notice_processor_cb,
     125             :                         NULL);
     126          10 :   return conn;
     127             : }
     128             : 
     129             : 
     130             : /**
     131             :  * Drop all Taler tables.  This should only be used by testcases.
     132             :  *
     133             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     134             :  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
     135             :  */
     136             : static int
     137           2 : postgres_drop_tables (void *cls)
     138             : {
     139           2 :   struct PostgresClosure *pc = cls;
     140           2 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     141             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_predicted_result;"),
     142             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_historic_ledger;"),
     143             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_historic_losses;"),
     144             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_historic_denomination_revenue;"),
     145             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_balance_summary;"),
     146             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_denomination_pending;"),
     147             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_reserve_balance;"),
     148             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_wire_fee_balance;"),
     149             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_reserves;"),
     150             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_progress;"),
     151             :     GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS wire_auditor_progress;"),
     152             :     GNUNET_PQ_EXECUTE_STATEMENT_END
     153             :   };
     154             :   PGconn *conn;
     155             :   int ret;
     156             : 
     157           2 :   conn = connect_to_postgres (pc);
     158           2 :   if (NULL == conn)
     159           0 :     return GNUNET_SYSERR;
     160           2 :   LOG (GNUNET_ERROR_TYPE_INFO,
     161             :        "Dropping ALL tables\n");
     162           2 :   ret = GNUNET_PQ_exec_statements (conn,
     163             :                                    es);
     164             :   /* TODO: we probably need a bit more fine-grained control
     165             :      over drops for the '-r' option of taler-auditor; also,
     166             :      for the testcase, we currently fail to drop the
     167             :      auditor_denominations table... */
     168           2 :   PQfinish (conn);
     169           2 :   return ret;
     170             : }
     171             : 
     172             : 
     173             : /**
     174             :  * Create the necessary tables if they are not present
     175             :  *
     176             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     177             :  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
     178             :  */
     179             : static int
     180           4 : postgres_create_tables (void *cls)
     181             : {
     182           4 :   struct PostgresClosure *pc = cls;
     183           4 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     184             :     /* Table with all of the denomination keys that the auditor
     185             :        is aware of. */
     186             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_denominations"
     187             :                             "(denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)"
     188             :                             ",master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
     189             :                             ",valid_from INT8 NOT NULL"
     190             :                             ",expire_withdraw INT8 NOT NULL"
     191             :                             ",expire_deposit INT8 NOT NULL"
     192             :                             ",expire_legal INT8 NOT NULL"
     193             :                             ",coin_val INT8 NOT NULL" /* value of this denom */
     194             :                             ",coin_frac INT4 NOT NULL" /* fractional value of this denom */
     195             :                             ",coin_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" /* assuming same currency for fees */
     196             :                             ",fee_withdraw_val INT8 NOT NULL"
     197             :                             ",fee_withdraw_frac INT4 NOT NULL"
     198             :                             ",fee_withdraw_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     199             :                             ",fee_deposit_val INT8 NOT NULL"
     200             :                             ",fee_deposit_frac INT4 NOT NULL"
     201             :                             ",fee_deposit_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     202             :                             ",fee_refresh_val INT8 NOT NULL"
     203             :                             ",fee_refresh_frac INT4 NOT NULL"
     204             :                             ",fee_refresh_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     205             :                             ",fee_refund_val INT8 NOT NULL"
     206             :                             ",fee_refund_frac INT4 NOT NULL"
     207             :                             ",fee_refund_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     208             :                             ")"),
     209             :     /* Table indicating up to which transactions the auditor has
     210             :        processed the exchange database.  Used for SELECTing the
     211             :        statements to process.  We basically trace the exchange's
     212             :        operations by the 6 primary tables: reserves_in,
     213             :        reserves_out, deposits, refresh_sessions, refunds and prewire. The
     214             :        other tables of the exchange DB just provide supporting
     215             :        evidence which is checked alongside the audit of these
     216             :        five tables.  The 6 indices below include the last serial
     217             :        ID from the respective tables that we have processed. Thus,
     218             :        we need to select those table entries that are strictly
     219             :        larger (and process in monotonically increasing order). */
     220             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_progress"
     221             :                             "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
     222             :                             ",last_reserve_in_serial_id INT8 NOT NULL DEFAULT 0"
     223             :                             ",last_reserve_out_serial_id INT8 NOT NULL DEFAULT 0"
     224             :                             ",last_reserve_payback_serial_id INT8 NOT NULL DEFAULT 0"
     225             :                             ",last_reserve_close_serial_id INT8 NOT NULL DEFAULT 0"
     226             :                             ",last_withdraw_serial_id INT8 NOT NULL DEFAULT 0"
     227             :                             ",last_deposit_serial_id INT8 NOT NULL DEFAULT 0"
     228             :                             ",last_melt_serial_id INT8 NOT NULL DEFAULT 0"
     229             :                             ",last_refund_serial_id INT8 NOT NULL DEFAULT 0"
     230             :                             ",last_wire_out_serial_id INT8 NOT NULL DEFAULT 0"
     231             :                             ")"),
     232             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS wire_auditor_progress"
     233             :                             "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
     234             :                             ",last_wire_reserve_in_serial_id INT8 NOT NULL DEFAULT 0"
     235             :                             ",last_wire_wire_out_serial_id INT8 NOT NULL DEFAULT 0"
     236             :                             ",last_timestamp INT8 NOT NULL"
     237             :                             ",wire_in_off BYTEA"
     238             :                             ",wire_out_off BYTEA"
     239             :                             ")"),
     240             :     /* Table with all of the customer reserves and their respective
     241             :        balances that the auditor is aware of.
     242             :        "last_reserve_out_serial_id" marks the last withdrawal from
     243             :        "reserves_out" about this reserve that the auditor is aware of,
     244             :        and "last_reserve_in_serial_id" is the last "reserve_in"
     245             :        operation about this reserve that the auditor is aware of. */
     246             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_reserves"
     247             :                             "(reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32)"
     248             :                             ",master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
     249             :                             ",reserve_balance_val INT8 NOT NULL"
     250             :                             ",reserve_balance_frac INT4 NOT NULL"
     251             :                             ",reserve_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     252             :                             ",withdraw_fee_balance_val INT8 NOT NULL"
     253             :                             ",withdraw_fee_balance_frac INT4 NOT NULL"
     254             :                             ",withdraw_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     255             :                             ",expiration_date INT8 NOT NULL"
     256             :                             ",auditor_reserves_rowid BIGSERIAL UNIQUE"
     257             :                             ")"),
     258             :     GNUNET_PQ_make_try_execute ("CREATE INDEX auditor_reserves_by_reserve_pub "
     259             :                                 "ON auditor_reserves(reserve_pub)"),
     260             :     /* Table with the sum of the balances of all customer reserves
     261             :        (by exchange's master public key) */
     262             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_reserve_balance"
     263             :                             "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
     264             :                             ",reserve_balance_val INT8 NOT NULL"
     265             :                             ",reserve_balance_frac INT4 NOT NULL"
     266             :                             ",reserve_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     267             :                             ",withdraw_fee_balance_val INT8 NOT NULL"
     268             :                             ",withdraw_fee_balance_frac INT4 NOT NULL"
     269             :                             ",withdraw_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     270             :                             ")"),
     271             :     /* Table with the sum of the balances of all wire fees
     272             :        (by exchange's master public key) */
     273             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_wire_fee_balance"
     274             :                             "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
     275             :                             ",wire_fee_balance_val INT8 NOT NULL"
     276             :                             ",wire_fee_balance_frac INT4 NOT NULL"
     277             :                             ",wire_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     278             :                             ")"),
     279             :     /* Table with all of the outstanding denomination coins that the
     280             :        exchange is aware of.  "last_deposit_serial_id" marks the
     281             :        deposit_serial_id from "deposits" about this denomination key
     282             :        that the auditor is aware of; "last_melt_serial_id" marks the
     283             :        last melt from "refresh_sessions" that the auditor is aware
     284             :        of; "refund_serial_id" tells us the last entry in "refunds"
     285             :        for this denom_pub that the auditor is aware of. */
     286             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_denomination_pending"
     287             :                             "(denom_pub_hash BYTEA PRIMARY KEY"
     288             :                             " REFERENCES auditor_denominations (denom_pub_hash) ON DELETE CASCADE"
     289             :                             ",denom_balance_val INT8 NOT NULL"
     290             :                             ",denom_balance_frac INT4 NOT NULL"
     291             :                             ",denom_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     292             :                             ",denom_risk_val INT8 NOT NULL"
     293             :                             ",denom_risk_frac INT4 NOT NULL"
     294             :                             ",denom_risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     295             :                             ")"),
     296             :     /* Table with the sum of the outstanding coins from
     297             :        "auditor_denomination_pending" (denom_pubs must belong to the
     298             :        respective's exchange's master public key); it represents the
     299             :        auditor_balance_summary of the exchange at this point (modulo
     300             :        unexpected historic_loss-style events where denomination keys are
     301             :        compromised) */
     302             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_balance_summary"
     303             :                             "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
     304             :                             ",denom_balance_val INT8 NOT NULL"
     305             :                             ",denom_balance_frac INT4 NOT NULL"
     306             :                             ",denom_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     307             :                             ",deposit_fee_balance_val INT8 NOT NULL"
     308             :                             ",deposit_fee_balance_frac INT4 NOT NULL"
     309             :                             ",deposit_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     310             :                             ",melt_fee_balance_val INT8 NOT NULL"
     311             :                             ",melt_fee_balance_frac INT4 NOT NULL"
     312             :                             ",melt_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     313             :                             ",refund_fee_balance_val INT8 NOT NULL"
     314             :                             ",refund_fee_balance_frac INT4 NOT NULL"
     315             :                             ",refund_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     316             :                             ",risk_val INT8 NOT NULL"
     317             :                             ",risk_frac INT4 NOT NULL"
     318             :                             ",risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     319             :                             ")"),
     320             :     /* Table with historic profits; basically, when a denom_pub has
     321             :        expired and everything associated with it is garbage collected,
     322             :        the final profits end up in here; note that the "denom_pub" here
     323             :        is not a foreign key, we just keep it as a reference point.
     324             :        "revenue_balance" is the sum of all of the profits we made on the
     325             :        coin except for withdraw fees (which are in
     326             :        historic_reserve_revenue); the deposit, melt and refund fees are given
     327             :        individually; the delta to the revenue_balance is from coins that
     328             :        were withdrawn but never deposited prior to expiration. */
     329             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_denomination_revenue"
     330             :                             "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
     331             :                             ",denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)"
     332             :                             ",revenue_timestamp INT8 NOT NULL"
     333             :                             ",revenue_balance_val INT8 NOT NULL"
     334             :                             ",revenue_balance_frac INT4 NOT NULL"
     335             :                             ",revenue_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     336             :                             ")"),
     337             :     /* Table with historic losses; basically, when we need to
     338             :        invalidate a denom_pub because the denom_priv was
     339             :        compromised, we incur a loss. These losses are totaled
     340             :        up here. (NOTE: the 'bankrupcy' protocol is not yet
     341             :        implemented, so right now this table is not used.)  */
     342             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_losses"
     343             :                             "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
     344             :                             ",denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)"
     345             :                             ",loss_timestamp INT8 NOT NULL"
     346             :                             ",loss_balance_val INT8 NOT NULL"
     347             :                             ",loss_balance_frac INT4 NOT NULL"
     348             :                             ",loss_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     349             :                             ")"),
     350             :     /* Table with historic profits from reserves; we eventually
     351             :        GC "auditor_historic_reserve_revenue", and then store the totals
     352             :        in here (by time intervals). */
     353             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_reserve_summary"
     354             :                             "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
     355             :                             ",start_date INT8 NOT NULL"
     356             :                             ",end_date INT8 NOT NULL"
     357             :                             ",reserve_profits_val INT8 NOT NULL"
     358             :                             ",reserve_profits_frac INT4 NOT NULL"
     359             :                             ",reserve_profits_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     360             :                             ")"),
     361             :     GNUNET_PQ_make_try_execute ("CREATE INDEX auditor_historic_reserve_summary_by_master_pub_start_date "
     362             :                                 "ON auditor_historic_reserve_summary(master_pub,start_date)"),
     363             :     /* Table with historic business ledger; basically, when the exchange
     364             :        operator decides to use operating costs for anything but wire
     365             :        transfers to merchants, it goes in here.  This happens when the
     366             :        operator users transaction fees for business expenses. "purpose"
     367             :        is free-form but should be a human-readable wire transfer
     368             :        identifier.   This is NOT yet used and outside of the scope of
     369             :        the core auditing logic. However, once we do take fees to use
     370             :        operating costs, and if we still want "auditor_predicted_result" to match
     371             :        the tables overall, we'll need a command-line tool to insert rows
     372             :        into this table and update "auditor_predicted_result" accordingly.
     373             :        (So this table for now just exists as a reminder of what we'll
     374             :        need in the long term.) */
     375             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_ledger"
     376             :                             "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
     377             :                             ",purpose VARCHAR NOT NULL"
     378             :                             ",timestamp INT8 NOT NULL"
     379             :                             ",balance_val INT8 NOT NULL"
     380             :                             ",balance_frac INT4 NOT NULL"
     381             :                             ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     382             :                             ")"),
     383             :     GNUNET_PQ_make_try_execute ("CREATE INDEX history_ledger_by_master_pub_and_time "
     384             :                                 "ON auditor_historic_ledger(master_pub,timestamp)"),
     385             :     /* Table with the sum of the ledger, auditor_historic_revenue,
     386             :        auditor_historic_losses and the auditor_reserve_balance.  This is the
     387             :        final amount that the exchange should have in its bank account
     388             :        right now. */
     389             :     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_predicted_result"
     390             :                             "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
     391             :                             ",balance_val INT8 NOT NULL"
     392             :                             ",balance_frac INT4 NOT NULL"
     393             :                             ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
     394             :                             ")"),
     395             :     GNUNET_PQ_EXECUTE_STATEMENT_END
     396             :   };
     397             :   PGconn *conn;
     398             :   int ret;
     399             : 
     400           4 :   conn = connect_to_postgres (pc);
     401           4 :   if (NULL == conn)
     402           0 :     return GNUNET_SYSERR;
     403           4 :   ret = GNUNET_PQ_exec_statements (conn,
     404             :                                    es);
     405           4 :   PQfinish (conn);
     406           4 :   return ret;
     407             : }
     408             : 
     409             : 
     410             : /**
     411             :  * Setup prepared statements.
     412             :  *
     413             :  * @param db_conn connection handle to initialize
     414             :  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
     415             :  */
     416             : static int
     417           4 : postgres_prepare (PGconn *db_conn)
     418             : {
     419           4 :   struct GNUNET_PQ_PreparedStatement ps[] = {
     420             :     /* used in #postgres_commit */
     421             :     GNUNET_PQ_make_prepare ("do_commit",
     422             :                             "COMMIT",
     423             :                             0),
     424             :     /* Used in #postgres_insert_denomination_info() */
     425             :     GNUNET_PQ_make_prepare ("auditor_denominations_insert",
     426             :                             "INSERT INTO auditor_denominations "
     427             :                             "(denom_pub_hash"
     428             :                             ",master_pub"
     429             :                             ",valid_from"
     430             :                             ",expire_withdraw"
     431             :                             ",expire_deposit"
     432             :                             ",expire_legal"
     433             :                             ",coin_val"
     434             :                             ",coin_frac"
     435             :                             ",coin_curr"
     436             :                             ",fee_withdraw_val"
     437             :                             ",fee_withdraw_frac"
     438             :                             ",fee_withdraw_curr"
     439             :                             ",fee_deposit_val"
     440             :                             ",fee_deposit_frac"
     441             :                             ",fee_deposit_curr"
     442             :                             ",fee_refresh_val"
     443             :                             ",fee_refresh_frac"
     444             :                             ",fee_refresh_curr"
     445             :                             ",fee_refund_val"
     446             :                             ",fee_refund_frac"
     447             :                             ",fee_refund_curr"
     448             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);",
     449             :                             21),
     450             :     /* Used in #postgres_insert_denomination_info() */
     451             :     GNUNET_PQ_make_prepare ("auditor_denominations_select",
     452             :                             "SELECT"
     453             :                             " denom_pub_hash"
     454             :                             ",valid_from"
     455             :                             ",expire_withdraw"
     456             :                             ",expire_deposit"
     457             :                             ",expire_legal"
     458             :                             ",coin_val"
     459             :                             ",coin_frac"
     460             :                             ",coin_curr"
     461             :                             ",fee_withdraw_val"
     462             :                             ",fee_withdraw_frac"
     463             :                             ",fee_withdraw_curr"
     464             :                             ",fee_deposit_val"
     465             :                             ",fee_deposit_frac"
     466             :                             ",fee_deposit_curr"
     467             :                             ",fee_refresh_val"
     468             :                             ",fee_refresh_frac"
     469             :                             ",fee_refresh_curr"
     470             :                             ",fee_refund_val"
     471             :                             ",fee_refund_frac"
     472             :                             ",fee_refund_curr"
     473             :                             " FROM auditor_denominations"
     474             :                             " WHERE master_pub=$1;",
     475             :                             1),
     476             :     /* Used in #postgres_insert_auditor_progress() */
     477             :     GNUNET_PQ_make_prepare ("auditor_progress_insert",
     478             :                             "INSERT INTO auditor_progress "
     479             :                             "(master_pub"
     480             :                             ",last_reserve_in_serial_id"
     481             :                             ",last_reserve_out_serial_id"
     482             :                             ",last_reserve_payback_serial_id"
     483             :                             ",last_reserve_close_serial_id"
     484             :                             ",last_withdraw_serial_id"
     485             :                             ",last_deposit_serial_id"
     486             :                             ",last_melt_serial_id"
     487             :                             ",last_refund_serial_id"
     488             :                             ",last_wire_out_serial_id"
     489             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
     490             :                             10),
     491             :     /* Used in #postgres_update_auditor_progress() */
     492             :     GNUNET_PQ_make_prepare ("auditor_progress_update",
     493             :                             "UPDATE auditor_progress SET "
     494             :                             " last_reserve_in_serial_id=$1"
     495             :                             ",last_reserve_out_serial_id=$2"
     496             :                             ",last_reserve_payback_serial_id=$3"
     497             :                             ",last_reserve_close_serial_id=$4"
     498             :                             ",last_withdraw_serial_id=$5"
     499             :                             ",last_deposit_serial_id=$6"
     500             :                             ",last_melt_serial_id=$7"
     501             :                             ",last_refund_serial_id=$8"
     502             :                             ",last_wire_out_serial_id=$9"
     503             :                             " WHERE master_pub=$10",
     504             :                             10),
     505             :     /* Used in #postgres_get_auditor_progress() */
     506             :     GNUNET_PQ_make_prepare ("auditor_progress_select",
     507             :                             "SELECT"
     508             :                             " last_reserve_in_serial_id"
     509             :                             ",last_reserve_out_serial_id"
     510             :                             ",last_reserve_payback_serial_id"
     511             :                             ",last_reserve_close_serial_id"
     512             :                             ",last_withdraw_serial_id"
     513             :                             ",last_deposit_serial_id"
     514             :                             ",last_melt_serial_id"
     515             :                             ",last_refund_serial_id"
     516             :                             ",last_wire_out_serial_id"
     517             :                             " FROM auditor_progress"
     518             :                             " WHERE master_pub=$1;",
     519             :                             1),
     520             :     /* Used in #postgres_insert_wire_auditor_progress() */
     521             :     GNUNET_PQ_make_prepare ("wire_auditor_progress_insert",
     522             :                             "INSERT INTO wire_auditor_progress "
     523             :                             "(master_pub"
     524             :                             ",last_wire_reserve_in_serial_id"
     525             :                             ",last_wire_wire_out_serial_id"
     526             :                             ",last_timestamp"
     527             :                             ",wire_in_off"
     528             :                             ",wire_out_off"
     529             :                             ") VALUES ($1,$2,$3,$4,$5,$6);",
     530             :                             6),
     531             :     /* Used in #postgres_update_wire_auditor_progress() */
     532             :     GNUNET_PQ_make_prepare ("wire_auditor_progress_update",
     533             :                             "UPDATE wire_auditor_progress SET "
     534             :                             " last_wire_reserve_in_serial_id=$1"
     535             :                             ",last_wire_wire_out_serial_id=$2"
     536             :                             ",last_timestamp=$3"
     537             :                             ",wire_in_off=$4"
     538             :                             ",wire_out_off=$5"
     539             :                             " WHERE master_pub=$6",
     540             :                             6),
     541             :     /* Used in #postgres_get_wire_auditor_progress() */
     542             :     GNUNET_PQ_make_prepare ("wire_auditor_progress_select",
     543             :                             "SELECT"
     544             :                             " last_wire_reserve_in_serial_id"
     545             :                             ",last_wire_wire_out_serial_id"
     546             :                             ",last_timestamp"
     547             :                             ",wire_in_off"
     548             :                             ",wire_out_off"
     549             :                             " FROM wire_auditor_progress"
     550             :                             " WHERE master_pub=$1;",
     551             :                             1),
     552             :     /* Used in #postgres_insert_reserve_info() */
     553             :     GNUNET_PQ_make_prepare ("auditor_reserves_insert",
     554             :                             "INSERT INTO auditor_reserves "
     555             :                             "(reserve_pub"
     556             :                             ",master_pub"
     557             :                             ",reserve_balance_val"
     558             :                             ",reserve_balance_frac"
     559             :                             ",reserve_balance_curr"
     560             :                             ",withdraw_fee_balance_val"
     561             :                             ",withdraw_fee_balance_frac"
     562             :                             ",withdraw_fee_balance_curr"
     563             :                             ",expiration_date"
     564             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
     565             :                             9),
     566             :     /* Used in #postgres_update_reserve_info() */
     567             :     GNUNET_PQ_make_prepare ("auditor_reserves_update",
     568             :                             "UPDATE auditor_reserves SET"
     569             :                             " reserve_balance_val=$1"
     570             :                             ",reserve_balance_frac=$2"
     571             :                             ",reserve_balance_curr=$3"
     572             :                             ",withdraw_fee_balance_val=$4"
     573             :                             ",withdraw_fee_balance_frac=$5"
     574             :                             ",withdraw_fee_balance_curr=$6"
     575             :                             ",expiration_date=$7"
     576             :                             " WHERE reserve_pub=$8 AND master_pub=$9;",
     577             :                             9),
     578             :     /* Used in #postgres_get_reserve_info() */
     579             :     GNUNET_PQ_make_prepare ("auditor_reserves_select",
     580             :                             "SELECT"
     581             :                             " reserve_balance_val"
     582             :                             ",reserve_balance_frac"
     583             :                             ",reserve_balance_curr"
     584             :                             ",withdraw_fee_balance_val"
     585             :                             ",withdraw_fee_balance_frac"
     586             :                             ",withdraw_fee_balance_curr"
     587             :                             ",expiration_date"
     588             :                             ",auditor_reserves_rowid"
     589             :                             " FROM auditor_reserves"
     590             :                             " WHERE reserve_pub=$1 AND master_pub=$2;",
     591             :                             2),
     592             :     /* Used in #postgres_del_reserve_info() */
     593             :     GNUNET_PQ_make_prepare ("auditor_reserves_delete",
     594             :                             "DELETE"
     595             :                             " FROM auditor_reserves"
     596             :                             " WHERE reserve_pub=$1 AND master_pub=$2;",
     597             :                             2),
     598             :     /* Used in #postgres_insert_reserve_summary() */
     599             :     GNUNET_PQ_make_prepare ("auditor_reserve_balance_insert",
     600             :                             "INSERT INTO auditor_reserve_balance"
     601             :                             "(master_pub"
     602             :                             ",reserve_balance_val"
     603             :                             ",reserve_balance_frac"
     604             :                             ",reserve_balance_curr"
     605             :                             ",withdraw_fee_balance_val"
     606             :                             ",withdraw_fee_balance_frac"
     607             :                             ",withdraw_fee_balance_curr"
     608             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7)",
     609             :                             7),
     610             :     /* Used in #postgres_update_reserve_summary() */
     611             :     GNUNET_PQ_make_prepare ("auditor_reserve_balance_update",
     612             :                             "UPDATE auditor_reserve_balance SET"
     613             :                             " reserve_balance_val=$1"
     614             :                             ",reserve_balance_frac=$2"
     615             :                             ",reserve_balance_curr=$3"
     616             :                             ",withdraw_fee_balance_val=$4"
     617             :                             ",withdraw_fee_balance_frac=$5"
     618             :                             ",withdraw_fee_balance_curr=$6"
     619             :                             " WHERE master_pub=$7;",
     620             :                             7),
     621             :     /* Used in #postgres_get_reserve_summary() */
     622             :     GNUNET_PQ_make_prepare ("auditor_reserve_balance_select",
     623             :                             "SELECT"
     624             :                             " reserve_balance_val"
     625             :                             ",reserve_balance_frac"
     626             :                             ",reserve_balance_curr"
     627             :                             ",withdraw_fee_balance_val"
     628             :                             ",withdraw_fee_balance_frac"
     629             :                             ",withdraw_fee_balance_curr"
     630             :                             " FROM auditor_reserve_balance"
     631             :                             " WHERE master_pub=$1;",
     632             :                             1),
     633             :     /* Used in #postgres_insert_wire_fee_summary() */
     634             :     GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_insert",
     635             :                             "INSERT INTO auditor_wire_fee_balance"
     636             :                             "(master_pub"
     637             :                             ",wire_fee_balance_val"
     638             :                             ",wire_fee_balance_frac"
     639             :                             ",wire_fee_balance_curr"
     640             :                             ") VALUES ($1,$2,$3,$4)",
     641             :                             4),
     642             :     /* Used in #postgres_update_wire_fee_summary() */
     643             :     GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_update",
     644             :                             "UPDATE auditor_wire_fee_balance SET"
     645             :                             " wire_fee_balance_val=$1"
     646             :                             ",wire_fee_balance_frac=$2"
     647             :                             ",wire_fee_balance_curr=$3"
     648             :                             " WHERE master_pub=$4;",
     649             :                             4),
     650             :     /* Used in #postgres_get_wire_fee_summary() */
     651             :     GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_select",
     652             :                             "SELECT"
     653             :                             " wire_fee_balance_val"
     654             :                             ",wire_fee_balance_frac"
     655             :                             ",wire_fee_balance_curr"
     656             :                             " FROM auditor_wire_fee_balance"
     657             :                             " WHERE master_pub=$1;",
     658             :                             1),
     659             :     /* Used in #postgres_insert_denomination_balance() */
     660             :     GNUNET_PQ_make_prepare ("auditor_denomination_pending_insert",
     661             :                             "INSERT INTO auditor_denomination_pending "
     662             :                             "(denom_pub_hash"
     663             :                             ",denom_balance_val"
     664             :                             ",denom_balance_frac"
     665             :                             ",denom_balance_curr"
     666             :                             ",denom_risk_val"
     667             :                             ",denom_risk_frac"
     668             :                             ",denom_risk_curr"
     669             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7);",
     670             :                             7),
     671             :     /* Used in #postgres_update_denomination_balance() */
     672             :     GNUNET_PQ_make_prepare ("auditor_denomination_pending_update",
     673             :                             "UPDATE auditor_denomination_pending SET"
     674             :                             " denom_balance_val=$1"
     675             :                             ",denom_balance_frac=$2"
     676             :                             ",denom_balance_curr=$3"
     677             :                             ",denom_risk_val=$4"
     678             :                             ",denom_risk_frac=$5"
     679             :                             ",denom_risk_curr=$6"
     680             :                             " WHERE denom_pub_hash=$7",
     681             :                             7),
     682             :     /* Used in #postgres_get_denomination_balance() */
     683             :     GNUNET_PQ_make_prepare ("auditor_denomination_pending_select",
     684             :                             "SELECT"
     685             :                             " denom_balance_val"
     686             :                             ",denom_balance_frac"
     687             :                             ",denom_balance_curr"
     688             :                             ",denom_risk_val"
     689             :                             ",denom_risk_frac"
     690             :                             ",denom_risk_curr"
     691             :                             " FROM auditor_denomination_pending"
     692             :                             " WHERE denom_pub_hash=$1",
     693             :                             1),
     694             :     /* Used in #postgres_insert_balance_summary() */
     695             :     GNUNET_PQ_make_prepare ("auditor_balance_summary_insert",
     696             :                             "INSERT INTO auditor_balance_summary "
     697             :                             "(master_pub"
     698             :                             ",denom_balance_val"
     699             :                             ",denom_balance_frac"
     700             :                             ",denom_balance_curr"
     701             :                             ",deposit_fee_balance_val"
     702             :                             ",deposit_fee_balance_frac"
     703             :                             ",deposit_fee_balance_curr"
     704             :                             ",melt_fee_balance_val"
     705             :                             ",melt_fee_balance_frac"
     706             :                             ",melt_fee_balance_curr"
     707             :                             ",refund_fee_balance_val"
     708             :                             ",refund_fee_balance_frac"
     709             :                             ",refund_fee_balance_curr"
     710             :                             ",risk_val"
     711             :                             ",risk_frac"
     712             :                             ",risk_curr"
     713             :                             ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);",
     714             :                             16),
     715             :     /* Used in #postgres_update_balance_summary() */
     716             :     GNUNET_PQ_make_prepare ("auditor_balance_summary_update",
     717             :                             "UPDATE auditor_balance_summary SET"
     718             :                             " denom_balance_val=$1"
     719             :                             ",denom_balance_frac=$2"
     720             :                             ",denom_balance_curr=$3"
     721             :                             ",deposit_fee_balance_val=$4"
     722             :                             ",deposit_fee_balance_frac=$5"
     723             :                             ",deposit_fee_balance_curr=$6"
     724             :                             ",melt_fee_balance_val=$7"
     725             :                             ",melt_fee_balance_frac=$8"
     726             :                             ",melt_fee_balance_curr=$9"
     727             :                             ",refund_fee_balance_val=$10"
     728             :                             ",refund_fee_balance_frac=$11"
     729             :                             ",refund_fee_balance_curr=$12"
     730             :                             ",risk_val=$13"
     731             :                             ",risk_frac=$14"
     732             :                             ",risk_curr=$15"
     733             :                             " WHERE master_pub=$16;",
     734             :                             16),
     735             :     /* Used in #postgres_get_balance_summary() */
     736             :     GNUNET_PQ_make_prepare ("auditor_balance_summary_select",
     737             :                             "SELECT"
     738             :                             " denom_balance_val"
     739             :                             ",denom_balance_frac"
     740             :                             ",denom_balance_curr"
     741             :                             ",deposit_fee_balance_val"
     742             :                             ",deposit_fee_balance_frac"
     743             :                             ",deposit_fee_balance_curr"
     744             :                             ",melt_fee_balance_val"
     745             :                             ",melt_fee_balance_frac"
     746             :                             ",melt_fee_balance_curr"
     747             :                             ",refund_fee_balance_val"
     748             :                             ",refund_fee_balance_frac"
     749             :                             ",refund_fee_balance_curr"
     750             :                             ",risk_val"
     751             :                             ",risk_frac"
     752             :                             ",risk_curr"
     753             :                             " FROM auditor_balance_summary"
     754             :                             " WHERE master_pub=$1;",
     755             :                             1),
     756             :     /* Used in #postgres_insert_historic_denom_revenue() */
     757             :     GNUNET_PQ_make_prepare ("auditor_historic_denomination_revenue_insert",
     758             :                             "INSERT INTO auditor_historic_denomination_revenue"
     759             :                             "(master_pub"
     760             :                             ",denom_pub_hash"
     761             :                             ",revenue_timestamp"
     762             :                             ",revenue_balance_val"
     763             :                             ",revenue_balance_frac"
     764             :                             ",revenue_balance_curr"
     765             :                             ") VALUES ($1,$2,$3,$4,$5,$6);",
     766             :                             6),
     767             :     /* Used in #postgres_select_historic_denom_revenue() */
     768             :     GNUNET_PQ_make_prepare ("auditor_historic_denomination_revenue_select",
     769             :                             "SELECT"
     770             :                             " denom_pub_hash"
     771             :                             ",revenue_timestamp"
     772             :                             ",revenue_balance_val"
     773             :                             ",revenue_balance_frac"
     774             :                             ",revenue_balance_curr"
     775             :                             " FROM auditor_historic_denomination_revenue"
     776             :                             " WHERE master_pub=$1;",
     777             :                             1),
     778             :     /* Used in #postgres_insert_historic_losses() */
     779             :     GNUNET_PQ_make_prepare ("auditor_historic_losses_insert",
     780             :                             "INSERT INTO auditor_historic_losses"
     781             :                             "(master_pub"
     782             :                             ",denom_pub_hash"
     783             :                             ",loss_timestamp"
     784             :                             ",loss_balance_val"
     785             :                             ",loss_balance_frac"
     786             :                             ",loss_balance_curr"
     787             :                             ") VALUES ($1,$2,$3,$4,$5,$6);",
     788             :                             6),
     789             :     /* Used in #postgres_select_historic_losses() */
     790             :     GNUNET_PQ_make_prepare ("auditor_historic_losses_select",
     791             :                             "SELECT"
     792             :                             " denom_pub_hash"
     793             :                             ",loss_timestamp"
     794             :                             ",loss_balance_val"
     795             :                             ",loss_balance_frac"
     796             :                             ",loss_balance_curr"
     797             :                             " FROM auditor_historic_losses"
     798             :                             " WHERE master_pub=$1;",
     799             :                             1),
     800             :     /* Used in #postgres_insert_historic_reserve_revenue() */
     801             :     GNUNET_PQ_make_prepare ("auditor_historic_reserve_summary_insert",
     802             :                             "INSERT INTO auditor_historic_reserve_summary"
     803             :                             "(master_pub"
     804             :                             ",start_date"
     805             :                             ",end_date"
     806             :                             ",reserve_profits_val"
     807             :                             ",reserve_profits_frac"
     808             :                             ",reserve_profits_curr"
     809             :                             ") VALUES ($1,$2,$3,$4,$5,$6);",
     810             :                             6),
     811             :     /* Used in #postgres_select_historic_reserve_revenue() */
     812             :     GNUNET_PQ_make_prepare ("auditor_historic_reserve_summary_select",
     813             :                             "SELECT"
     814             :                             " start_date"
     815             :                             ",end_date"
     816             :                             ",reserve_profits_val"
     817             :                             ",reserve_profits_frac"
     818             :                             ",reserve_profits_curr"
     819             :                             " FROM auditor_historic_reserve_summary"
     820             :                             " WHERE master_pub=$1;",
     821             :                             1),
     822             :     /* Used in #postgres_insert_predicted_result() */
     823             :     GNUNET_PQ_make_prepare ("auditor_predicted_result_insert",
     824             :                             "INSERT INTO auditor_predicted_result"
     825             :                             "(master_pub"
     826             :                             ",balance_val"
     827             :                             ",balance_frac"
     828             :                             ",balance_curr"
     829             :                             ") VALUES ($1,$2,$3,$4);",
     830             :                             4),
     831             :     /* Used in #postgres_update_predicted_result() */
     832             :     GNUNET_PQ_make_prepare ("auditor_predicted_result_update",
     833             :                             "UPDATE auditor_predicted_result SET"
     834             :                             " balance_val=$1"
     835             :                             ",balance_frac=$2"
     836             :                             ",balance_curr=$3"
     837             :                             " WHERE master_pub=$4;",
     838             :                             4),
     839             :     /* Used in #postgres_get_predicted_balance() */
     840             :     GNUNET_PQ_make_prepare ("auditor_predicted_result_select",
     841             :                             "SELECT"
     842             :                             " balance_val"
     843             :                             ",balance_frac"
     844             :                             ",balance_curr"
     845             :                             " FROM auditor_predicted_result"
     846             :                             " WHERE master_pub=$1;",
     847             :                             1),
     848             :     GNUNET_PQ_PREPARED_STATEMENT_END
     849             :   };
     850             : 
     851           4 :   return GNUNET_PQ_prepare_statements (db_conn,
     852             :                                        ps);
     853             : }
     854             : 
     855             : 
     856             : /**
     857             :  * Close thread-local database connection when a thread is destroyed.
     858             :  *
     859             :  * @param cls closure we get from pthreads (the db handle)
     860             :  */
     861             : static void
     862           0 : db_conn_destroy (void *cls)
     863             : {
     864           0 :   struct TALER_AUDITORDB_Session *session = cls;
     865             :   PGconn *db_conn;
     866             : 
     867           0 :   if (NULL == session)
     868           0 :     return;
     869           0 :   db_conn = session->conn;
     870           0 :   if (NULL != db_conn)
     871           0 :     PQfinish (db_conn);
     872           0 :   GNUNET_free (session);
     873             : }
     874             : 
     875             : 
     876             : /**
     877             :  * Get the thread-local database-handle.
     878             :  * Connect to the db if the connection does not exist yet.
     879             :  *
     880             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     881             :  * @return the database connection, or NULL on error
     882             :  */
     883             : static struct TALER_AUDITORDB_Session *
     884           4 : postgres_get_session (void *cls)
     885             : {
     886           4 :   struct PostgresClosure *pc = cls;
     887             :   PGconn *db_conn;
     888             :   struct TALER_AUDITORDB_Session *session;
     889             : 
     890           4 :   if (NULL != (session = pthread_getspecific (pc->db_conn_threadlocal)))
     891             :   {
     892           0 :     if (CONNECTION_BAD == PQstatus (session->conn))
     893             :     {
     894             :       /**
     895             :        * Reset the thread-local database-handle.  Disconnects from the
     896             :        * DB.  Needed after the database server restarts as we need to
     897             :        * properly reconnect. */
     898           0 :       GNUNET_assert (0 == pthread_setspecific (pc->db_conn_threadlocal,
     899             :                                               NULL));
     900           0 :       PQfinish (session->conn);
     901           0 :       GNUNET_free (session);
     902             :     }
     903             :     else
     904             :     {
     905           0 :       return session;
     906             :     }
     907             :   }
     908           4 :   db_conn = connect_to_postgres (pc);
     909           4 :   if (NULL == db_conn)
     910           0 :     return NULL;
     911           4 :   if (GNUNET_OK !=
     912           4 :       postgres_prepare (db_conn))
     913             :   {
     914           0 :     GNUNET_break (0);
     915           0 :     PQfinish (db_conn);
     916           0 :     return NULL;
     917             :   }
     918           4 :   session = GNUNET_new (struct TALER_AUDITORDB_Session);
     919           4 :   session->conn = db_conn;
     920           4 :   if (0 != pthread_setspecific (pc->db_conn_threadlocal,
     921             :                                 session))
     922             :   {
     923           0 :     GNUNET_break (0);
     924           0 :     PQfinish (db_conn);
     925           0 :     GNUNET_free (session);
     926           0 :     return NULL;
     927             :   }
     928           4 :   return session;
     929             : }
     930             : 
     931             : 
     932             : /**
     933             :  * Start a transaction.
     934             :  *
     935             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     936             :  * @param session the database connection
     937             :  * @return #GNUNET_OK on success
     938             :  */
     939             : static int
     940           2 : postgres_start (void *cls,
     941             :                 struct TALER_AUDITORDB_Session *session)
     942             : {
     943             :   PGresult *result;
     944             : 
     945           2 :   result = PQexec (session->conn,
     946             :                    "START TRANSACTION ISOLATION LEVEL SERIALIZABLE");
     947           2 :   if (PGRES_COMMAND_OK !=
     948           2 :       PQresultStatus (result))
     949             :   {
     950           0 :     TALER_LOG_ERROR ("Failed to start transaction: %s\n",
     951             :                      PQresultErrorMessage (result));
     952           0 :     GNUNET_break (0);
     953           0 :     PQclear (result);
     954           0 :     return GNUNET_SYSERR;
     955             :   }
     956           2 :   PQclear (result);
     957           2 :   return GNUNET_OK;
     958             : }
     959             : 
     960             : 
     961             : /**
     962             :  * Roll back the current transaction of a database connection.
     963             :  *
     964             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     965             :  * @param session the database connection
     966             :  * @return #GNUNET_OK on success
     967             :  */
     968             : static void
     969           2 : postgres_rollback (void *cls,
     970             :                    struct TALER_AUDITORDB_Session *session)
     971             : {
     972             :   PGresult *result;
     973             : 
     974           2 :   result = PQexec (session->conn,
     975             :                    "ROLLBACK");
     976           2 :   GNUNET_break (PGRES_COMMAND_OK ==
     977             :                 PQresultStatus (result));
     978           2 :   PQclear (result);
     979           2 : }
     980             : 
     981             : 
     982             : /**
     983             :  * Commit the current transaction of a database connection.
     984             :  *
     985             :  * @param cls the `struct PostgresClosure` with the plugin-specific state
     986             :  * @param session the database connection
     987             :  * @return transaction status code
     988             :  */
     989             : enum GNUNET_DB_QueryStatus
     990           1 : postgres_commit (void *cls,
     991             :                  struct TALER_AUDITORDB_Session *session)
     992             : {
     993           1 :   struct GNUNET_PQ_QueryParam params[] = {
     994             :     GNUNET_PQ_query_param_end
     995             :   };
     996             : 
     997           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
     998             :                                              "do_commit",
     999             :                                              params);
    1000             : }
    1001             : 
    1002             : 
    1003             : /**
    1004             :  * Function called to perform "garbage collection" on the
    1005             :  * database, expiring records we no longer require.
    1006             :  *
    1007             :  * @param cls closure
    1008             :  * @return #GNUNET_OK on success,
    1009             :  *         #GNUNET_SYSERR on DB errors
    1010             :  */
    1011             : static int
    1012           0 : postgres_gc (void *cls)
    1013             : {
    1014           0 :   struct PostgresClosure *pc = cls;
    1015             :   struct GNUNET_TIME_Absolute now;
    1016           0 :   struct GNUNET_PQ_QueryParam params_time[] = {
    1017             :     GNUNET_PQ_query_param_absolute_time (&now),
    1018             :     GNUNET_PQ_query_param_end
    1019             :   };
    1020             :   PGconn *conn;
    1021             :   enum GNUNET_DB_QueryStatus qs;
    1022             : 
    1023           0 :   now = GNUNET_TIME_absolute_get ();
    1024           0 :   conn = connect_to_postgres (pc);
    1025           0 :   if (NULL == conn)
    1026           0 :     return GNUNET_SYSERR;
    1027           0 :   if (GNUNET_OK !=
    1028           0 :       postgres_prepare (conn))
    1029             :   {
    1030           0 :     PQfinish (conn);
    1031           0 :     return GNUNET_SYSERR;
    1032             :   }
    1033             :   /* FIXME: this is obviously not going to be this easy... */
    1034           0 :   qs = GNUNET_PQ_eval_prepared_non_select (conn,
    1035             :                                            "gc_auditor",
    1036             :                                            params_time);
    1037           0 :   if (0 > qs)
    1038             :   {
    1039           0 :     GNUNET_break (0);
    1040           0 :     PQfinish (conn);
    1041           0 :     return GNUNET_SYSERR;
    1042             :   }
    1043           0 :   PQfinish (conn);
    1044           0 :   return GNUNET_OK;
    1045             : }
    1046             : 
    1047             : 
    1048             : /**
    1049             :  * Insert information about a denomination key and in particular
    1050             :  * the properties (value, fees, expiration times) the coins signed
    1051             :  * with this key have.
    1052             :  *
    1053             :  * @param cls the @e cls of this struct with the plugin-specific state
    1054             :  * @param session connection to use
    1055             :  * @param issue issuing information with value, fees and other info about the denomination
    1056             :  * @return operation status result
    1057             :  */
    1058             : static enum GNUNET_DB_QueryStatus
    1059          14 : postgres_insert_denomination_info (void *cls,
    1060             :                                    struct TALER_AUDITORDB_Session *session,
    1061             :                                    const struct TALER_DenominationKeyValidityPS *issue)
    1062             : {
    1063         154 :   struct GNUNET_PQ_QueryParam params[] = {
    1064          14 :     GNUNET_PQ_query_param_auto_from_type (&issue->denom_hash),
    1065          14 :     GNUNET_PQ_query_param_auto_from_type (&issue->master),
    1066          14 :     GNUNET_PQ_query_param_absolute_time_nbo (&issue->start),
    1067          14 :     GNUNET_PQ_query_param_absolute_time_nbo (&issue->expire_withdraw),
    1068          14 :     GNUNET_PQ_query_param_absolute_time_nbo (&issue->expire_deposit),
    1069          14 :     GNUNET_PQ_query_param_absolute_time_nbo (&issue->expire_legal),
    1070          14 :     TALER_PQ_query_param_amount_nbo (&issue->value),
    1071          14 :     TALER_PQ_query_param_amount_nbo (&issue->fee_withdraw),
    1072          14 :     TALER_PQ_query_param_amount_nbo (&issue->fee_deposit),
    1073          14 :     TALER_PQ_query_param_amount_nbo (&issue->fee_refresh),
    1074          14 :     TALER_PQ_query_param_amount_nbo (&issue->fee_refund),
    1075             :     GNUNET_PQ_query_param_end
    1076             :   };
    1077             : 
    1078             :   /* check fees match coin currency */
    1079          14 :   GNUNET_assert (GNUNET_YES ==
    1080             :                  TALER_amount_cmp_currency_nbo (&issue->value,
    1081             :                                                 &issue->fee_withdraw));
    1082          14 :   GNUNET_assert (GNUNET_YES ==
    1083             :                  TALER_amount_cmp_currency_nbo (&issue->value,
    1084             :                                                 &issue->fee_deposit));
    1085          14 :   GNUNET_assert (GNUNET_YES ==
    1086             :                  TALER_amount_cmp_currency_nbo (&issue->value,
    1087             :                                                 &issue->fee_refresh));
    1088          14 :   GNUNET_assert (GNUNET_YES ==
    1089             :                  TALER_amount_cmp_currency_nbo (&issue->value,
    1090             :                                                &issue->fee_refund));
    1091          14 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1092             :                                              "auditor_denominations_insert",
    1093             :                                              params);
    1094             : }
    1095             : 
    1096             : 
    1097             : /**
    1098             :  * Closure for #denomination_info_cb().
    1099             :  */
    1100             : struct DenominationInfoContext
    1101             : {
    1102             : 
    1103             :   /**
    1104             :    * Master public key that is being used.
    1105             :    */
    1106             :   const struct TALER_MasterPublicKeyP *master_pub;
    1107             : 
    1108             :   /**
    1109             :    * Function to call for each denomination.
    1110             :    */
    1111             :   TALER_AUDITORDB_DenominationInfoDataCallback cb;
    1112             : 
    1113             :   /**
    1114             :    * Closure for @e cb
    1115             :    */
    1116             :   void *cb_cls;
    1117             : 
    1118             :   /**
    1119             :    * Query status to return.
    1120             :    */
    1121             :   enum GNUNET_DB_QueryStatus qs;
    1122             : };
    1123             : 
    1124             : 
    1125             : /**
    1126             :  * Helper function for #postgres_select_denomination_info().
    1127             :  * To be called with the results of a SELECT statement
    1128             :  * that has returned @a num_results results.
    1129             :  *
    1130             :  * @param cls closure of type `struct DenominationInfoContext *`
    1131             :  * @param result the postgres result
    1132             :  * @param num_result the number of results in @a result
    1133             :  */
    1134             : static void
    1135           1 : denomination_info_cb (void *cls,
    1136             :                       PGresult *result,
    1137             :                       unsigned int num_results)
    1138             : {
    1139           1 :   struct DenominationInfoContext *dic = cls;
    1140             : 
    1141           4 :   for (unsigned int i = 0; i < num_results; i++)
    1142             :   {
    1143           2 :     struct TALER_DenominationKeyValidityPS issue = {
    1144           1 :       .master = *dic->master_pub
    1145             :     };
    1146           1 :     struct GNUNET_PQ_ResultSpec rs[] = {
    1147             :       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &issue.denom_hash),
    1148             :       GNUNET_PQ_result_spec_absolute_time_nbo ("valid_from", &issue.start),
    1149             :       GNUNET_PQ_result_spec_absolute_time_nbo ("expire_withdraw", &issue.expire_withdraw),
    1150             :       GNUNET_PQ_result_spec_absolute_time_nbo ("expire_deposit", &issue.expire_deposit),
    1151             :       GNUNET_PQ_result_spec_absolute_time_nbo ("expire_legal", &issue.expire_legal),
    1152             :       TALER_PQ_result_spec_amount_nbo ("coin", &issue.value),
    1153             :       TALER_PQ_result_spec_amount_nbo ("fee_withdraw", &issue.fee_withdraw),
    1154             :       TALER_PQ_result_spec_amount_nbo ("fee_deposit", &issue.fee_deposit),
    1155             :       TALER_PQ_result_spec_amount_nbo ("fee_refresh", &issue.fee_refresh),
    1156             :       TALER_PQ_result_spec_amount_nbo ("fee_refund", &issue.fee_refund),
    1157             :       GNUNET_PQ_result_spec_end
    1158             :     };
    1159             : 
    1160           1 :     if (GNUNET_OK !=
    1161           1 :         GNUNET_PQ_extract_result (result,
    1162             :                                   rs,
    1163             :                                   i))
    1164             :     {
    1165           0 :       GNUNET_break (0);
    1166           0 :       dic->qs = GNUNET_DB_STATUS_HARD_ERROR;
    1167           0 :       return;
    1168             :     }
    1169           1 :     dic->qs = i + 1;
    1170           1 :     if (GNUNET_OK !=
    1171           1 :         dic->cb (dic->cb_cls,
    1172             :                  &issue))
    1173           0 :       return;
    1174             :   }
    1175             : }
    1176             : 
    1177             : 
    1178             : /**
    1179             :  * Get information about denomination keys of a particular exchange.
    1180             :  *
    1181             :  * @param cls the @e cls of this struct with the plugin-specific state
    1182             :  * @param session connection to use
    1183             :  * @param master_pub master public key of the exchange
    1184             :  * @param cb function to call with the results
    1185             :  * @param cb_cls closure for @a cb
    1186             :  * @return transaction status code
    1187             :  */
    1188             : static enum GNUNET_DB_QueryStatus
    1189           1 : postgres_select_denomination_info (void *cls,
    1190             :                                    struct TALER_AUDITORDB_Session *session,
    1191             :                                    const struct TALER_MasterPublicKeyP *master_pub,
    1192             :                                    TALER_AUDITORDB_DenominationInfoDataCallback cb,
    1193             :                                    void *cb_cls)
    1194             : {
    1195           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1196             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1197             :     GNUNET_PQ_query_param_end
    1198             :   };
    1199           1 :   struct DenominationInfoContext dic = {
    1200             :     .master_pub = master_pub,
    1201             :     .cb = cb,
    1202             :     .cb_cls = cb_cls
    1203             :   };
    1204             :   enum GNUNET_DB_QueryStatus qs;
    1205             : 
    1206           1 :   qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
    1207             :                                              "auditor_denominations_select",
    1208             :                                              params,
    1209             :                                              &denomination_info_cb,
    1210             :                                              &dic);
    1211           1 :   if (qs > 0)
    1212           1 :     return dic.qs;
    1213           0 :   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
    1214           0 :   return qs;
    1215             : }
    1216             : 
    1217             : 
    1218             : /**
    1219             :  * Insert information about the auditor's progress with an exchange's
    1220             :  * data.
    1221             :  *
    1222             :  * @param cls the @e cls of this struct with the plugin-specific state
    1223             :  * @param session connection to use
    1224             :  * @param master_pub master key of the exchange
    1225             :  * @param pp where is the auditor in processing
    1226             :  * @return transaction status code
    1227             :  */
    1228             : static enum GNUNET_DB_QueryStatus
    1229           1 : postgres_insert_auditor_progress (void *cls,
    1230             :                                   struct TALER_AUDITORDB_Session *session,
    1231             :                                   const struct TALER_MasterPublicKeyP *master_pub,
    1232             :                                   const struct TALER_AUDITORDB_ProgressPoint *pp)
    1233             : {
    1234          10 :   struct GNUNET_PQ_QueryParam params[] = {
    1235             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1236           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
    1237           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id),
    1238           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_payback_serial_id),
    1239           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_close_serial_id),
    1240           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_withdraw_serial_id),
    1241           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_deposit_serial_id),
    1242           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_melt_serial_id),
    1243           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_refund_serial_id),
    1244           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
    1245             :     GNUNET_PQ_query_param_end
    1246             :   };
    1247             : 
    1248           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1249             :                                              "auditor_progress_insert",
    1250             :                                              params);
    1251             : }
    1252             : 
    1253             : 
    1254             : /**
    1255             :  * Update information about the progress of the auditor.  There
    1256             :  * must be an existing record for the exchange.
    1257             :  *
    1258             :  * @param cls the @e cls of this struct with the plugin-specific state
    1259             :  * @param session connection to use
    1260             :  * @param master_pub master key of the exchange
    1261             :  * @param pp where is the auditor in processing
    1262             :  * @return transaction status code
    1263             :  */
    1264             : static enum GNUNET_DB_QueryStatus
    1265           1 : postgres_update_auditor_progress (void *cls,
    1266             :                                   struct TALER_AUDITORDB_Session *session,
    1267             :                                   const struct TALER_MasterPublicKeyP *master_pub,
    1268             :                                   const struct TALER_AUDITORDB_ProgressPoint *pp)
    1269             : {
    1270           9 :   struct GNUNET_PQ_QueryParam params[] = {
    1271           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
    1272           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id),
    1273           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_payback_serial_id),
    1274           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_close_serial_id),
    1275           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_withdraw_serial_id),
    1276           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_deposit_serial_id),
    1277           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_melt_serial_id),
    1278           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_refund_serial_id),
    1279           1 :     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
    1280             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1281             :     GNUNET_PQ_query_param_end
    1282             :   };
    1283             : 
    1284           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1285             :                                              "auditor_progress_update",
    1286             :                                              params);
    1287             : }
    1288             : 
    1289             : 
    1290             : /**
    1291             :  * Get information about the progress of the auditor.
    1292             :  *
    1293             :  * @param cls the @e cls of this struct with the plugin-specific state
    1294             :  * @param session connection to use
    1295             :  * @param master_pub master key of the exchange
    1296             :  * @param[out] pp set to where the auditor is in processing
    1297             :  * @return transaction status code
    1298             :  */
    1299             : static enum GNUNET_DB_QueryStatus
    1300           1 : postgres_get_auditor_progress (void *cls,
    1301             :                                struct TALER_AUDITORDB_Session *session,
    1302             :                                const struct TALER_MasterPublicKeyP *master_pub,
    1303             :                                struct TALER_AUDITORDB_ProgressPoint *pp)
    1304             : {
    1305           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1306             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1307             :     GNUNET_PQ_query_param_end
    1308             :   };
    1309           9 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1310           1 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id",
    1311             :                                   &pp->last_reserve_in_serial_id),
    1312           1 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id",
    1313             :                                   &pp->last_reserve_out_serial_id),
    1314           1 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_payback_serial_id",
    1315             :                                   &pp->last_reserve_payback_serial_id),
    1316           1 :     GNUNET_PQ_result_spec_uint64 ("last_reserve_close_serial_id",
    1317             :                                   &pp->last_reserve_close_serial_id),
    1318           1 :     GNUNET_PQ_result_spec_uint64 ("last_withdraw_serial_id",
    1319             :                                   &pp->last_withdraw_serial_id),
    1320           1 :     GNUNET_PQ_result_spec_uint64 ("last_deposit_serial_id",
    1321             :                                   &pp->last_deposit_serial_id),
    1322           1 :     GNUNET_PQ_result_spec_uint64 ("last_melt_serial_id",
    1323             :                                   &pp->last_melt_serial_id),
    1324           1 :     GNUNET_PQ_result_spec_uint64 ("last_refund_serial_id",
    1325             :                                   &pp->last_refund_serial_id),
    1326           1 :     GNUNET_PQ_result_spec_uint64 ("last_wire_out_serial_id",
    1327             :                                   &pp->last_wire_out_serial_id),
    1328             :     GNUNET_PQ_result_spec_end
    1329             :   };
    1330             : 
    1331           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    1332             :                                                    "auditor_progress_select",
    1333             :                                                    params,
    1334             :                                                    rs);
    1335             : }
    1336             : 
    1337             : 
    1338             : /**
    1339             :  * Insert information about the auditor's progress with an exchange's
    1340             :  * data.
    1341             :  *
    1342             :  * @param cls the @e cls of this struct with the plugin-specific state
    1343             :  * @param session connection to use
    1344             :  * @param master_pub master key of the exchange
    1345             :  * @param pp where is the auditor in processing
    1346             :  * @return transaction status code
    1347             :  */
    1348             : static enum GNUNET_DB_QueryStatus
    1349           0 : postgres_insert_wire_auditor_progress (void *cls,
    1350             :                                        struct TALER_AUDITORDB_Session *session,
    1351             :                                        const struct TALER_MasterPublicKeyP *master_pub,
    1352             :                                        const struct TALER_AUDITORDB_WireProgressPoint *pp,
    1353             :                                        const void *in_wire_off,
    1354             :                                        const void *out_wire_off,
    1355             :                                        size_t wire_off_size)
    1356             : {
    1357           0 :   struct GNUNET_PQ_QueryParam params[] = {
    1358             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1359           0 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
    1360           0 :     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
    1361           0 :     GNUNET_PQ_query_param_absolute_time (&pp->last_timestamp),
    1362             :     GNUNET_PQ_query_param_fixed_size (in_wire_off,
    1363             :                                       wire_off_size),
    1364             :     GNUNET_PQ_query_param_fixed_size (out_wire_off,
    1365             :                                       wire_off_size),
    1366             :     GNUNET_PQ_query_param_end
    1367             :   };
    1368             : 
    1369           0 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1370             :                                              "wire_auditor_progress_insert",
    1371             :                                              params);
    1372             : }
    1373             : 
    1374             : 
    1375             : /**
    1376             :  * Update information about the progress of the auditor.  There
    1377             :  * must be an existing record for the exchange.
    1378             :  *
    1379             :  * @param cls the @e cls of this struct with the plugin-specific state
    1380             :  * @param session connection to use
    1381             :  * @param master_pub master key of the exchange
    1382             :  * @param pp where is the auditor in processing
    1383             :  * @return transaction status code
    1384             :  */
    1385             : static enum GNUNET_DB_QueryStatus
    1386           0 : postgres_update_wire_auditor_progress (void *cls,
    1387             :                                        struct TALER_AUDITORDB_Session *session,
    1388             :                                        const struct TALER_MasterPublicKeyP *master_pub,
    1389             :                                        const struct TALER_AUDITORDB_WireProgressPoint *pp,
    1390             :                                        const void *in_wire_off,
    1391             :                                        const void *out_wire_off,
    1392             :                                        size_t wire_off_size)
    1393             : {
    1394           0 :   struct GNUNET_PQ_QueryParam params[] = {
    1395           0 :     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
    1396           0 :     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
    1397           0 :     GNUNET_PQ_query_param_absolute_time (&pp->last_timestamp),
    1398             :     GNUNET_PQ_query_param_fixed_size (in_wire_off,
    1399             :                                       wire_off_size),
    1400             :     GNUNET_PQ_query_param_fixed_size (out_wire_off,
    1401             :                                       wire_off_size),
    1402             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1403             :     GNUNET_PQ_query_param_end
    1404             :   };
    1405             : 
    1406           0 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1407             :                                              "wire_auditor_progress_update",
    1408             :                                              params);
    1409             : }
    1410             : 
    1411             : 
    1412             : /**
    1413             :  * Get information about the progress of the auditor.
    1414             :  *
    1415             :  * @param cls the @e cls of this struct with the plugin-specific state
    1416             :  * @param session connection to use
    1417             :  * @param master_pub master key of the exchange
    1418             :  * @param[out] pp set to where the auditor is in processing
    1419             :  * @return transaction status code
    1420             :  */
    1421             : static enum GNUNET_DB_QueryStatus
    1422           0 : postgres_get_wire_auditor_progress (void *cls,
    1423             :                                     struct TALER_AUDITORDB_Session *session,
    1424             :                                     const struct TALER_MasterPublicKeyP *master_pub,
    1425             :                                     struct TALER_AUDITORDB_WireProgressPoint *pp,
    1426             :                                     void **in_wire_off,
    1427             :                                     void **out_wire_off,
    1428             :                                     size_t *wire_off_size)
    1429             : {
    1430             :   size_t xsize;
    1431             :   enum GNUNET_DB_QueryStatus qs;
    1432           0 :   struct GNUNET_PQ_QueryParam params[] = {
    1433             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1434             :     GNUNET_PQ_query_param_end
    1435             :   };
    1436           0 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1437           0 :     GNUNET_PQ_result_spec_uint64 ("last_wire_reserve_in_serial_id",
    1438             :                                   &pp->last_reserve_in_serial_id),
    1439           0 :     GNUNET_PQ_result_spec_uint64 ("last_wire_wire_out_serial_id",
    1440             :                                   &pp->last_wire_out_serial_id),
    1441           0 :     GNUNET_PQ_result_spec_absolute_time ("last_timestamp",
    1442             :                                          &pp->last_timestamp),
    1443             :     GNUNET_PQ_result_spec_variable_size ("wire_in_off",
    1444             :                                          in_wire_off,
    1445             :                                          wire_off_size),
    1446             :     GNUNET_PQ_result_spec_variable_size ("wire_out_off",
    1447             :                                          out_wire_off,
    1448             :                                          &xsize),
    1449             :     GNUNET_PQ_result_spec_end
    1450             :   };
    1451             : 
    1452           0 :   qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    1453             :                                                  "wire_auditor_progress_select",
    1454             :                                                  params,
    1455             :                                                  rs);
    1456           0 :   if (qs <= 0)
    1457             :   {
    1458           0 :     *wire_off_size = 0;
    1459           0 :     xsize = 0;
    1460             :   }
    1461           0 :   GNUNET_assert (xsize == *wire_off_size);
    1462           0 :   return qs;
    1463             : }
    1464             : 
    1465             : 
    1466             : /**
    1467             :  * Insert information about a reserve.  There must not be an
    1468             :  * existing record for the reserve.
    1469             :  *
    1470             :  * @param cls the @e cls of this struct with the plugin-specific state
    1471             :  * @param session connection to use
    1472             :  * @param reserve_pub public key of the reserve
    1473             :  * @param master_pub master public key of the exchange
    1474             :  * @param reserve_balance amount stored in the reserve
    1475             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1476             :  *                             due to withdrawals from this reserve
    1477             :  * @param expiration_date expiration date of the reserve
    1478             :  * @return transaction status code
    1479             :  */
    1480             : static enum GNUNET_DB_QueryStatus
    1481           1 : postgres_insert_reserve_info (void *cls,
    1482             :                               struct TALER_AUDITORDB_Session *session,
    1483             :                               const struct TALER_ReservePublicKeyP *reserve_pub,
    1484             :                               const struct TALER_MasterPublicKeyP *master_pub,
    1485             :                               const struct TALER_Amount *reserve_balance,
    1486             :                               const struct TALER_Amount *withdraw_fee_balance,
    1487             :                               struct GNUNET_TIME_Absolute expiration_date)
    1488             : {
    1489           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1490             :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1491             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1492             :     TALER_PQ_query_param_amount (reserve_balance),
    1493             :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1494             :     GNUNET_PQ_query_param_absolute_time (&expiration_date),
    1495             :     GNUNET_PQ_query_param_end
    1496             :   };
    1497             : 
    1498           1 :   GNUNET_assert (GNUNET_YES ==
    1499             :                  TALER_amount_cmp_currency (reserve_balance,
    1500             :                                             withdraw_fee_balance));
    1501             : 
    1502           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1503             :                                              "auditor_reserves_insert",
    1504             :                                              params);
    1505             : }
    1506             : 
    1507             : 
    1508             : /**
    1509             :  * Update information about a reserve.  Destructively updates an
    1510             :  * existing record, which must already exist.
    1511             :  *
    1512             :  * @param cls the @e cls of this struct with the plugin-specific state
    1513             :  * @param session connection to use
    1514             :  * @param reserve_pub public key of the reserve
    1515             :  * @param master_pub master public key of the exchange
    1516             :  * @param reserve_balance amount stored in the reserve
    1517             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1518             :  *                             due to withdrawals from this reserve
    1519             :  * @param expiration_date expiration date of the reserve
    1520             :  * @return transaction status code
    1521             :  */
    1522             : static enum GNUNET_DB_QueryStatus
    1523           1 : postgres_update_reserve_info (void *cls,
    1524             :                               struct TALER_AUDITORDB_Session *session,
    1525             :                               const struct TALER_ReservePublicKeyP *reserve_pub,
    1526             :                               const struct TALER_MasterPublicKeyP *master_pub,
    1527             :                               const struct TALER_Amount *reserve_balance,
    1528             :                               const struct TALER_Amount *withdraw_fee_balance,
    1529             :                               struct GNUNET_TIME_Absolute expiration_date)
    1530             : {
    1531           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1532             :     TALER_PQ_query_param_amount (reserve_balance),
    1533             :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1534             :     GNUNET_PQ_query_param_absolute_time (&expiration_date),
    1535             :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1536             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1537             :     GNUNET_PQ_query_param_end
    1538             :   };
    1539             : 
    1540           1 :   GNUNET_assert (GNUNET_YES ==
    1541             :                  TALER_amount_cmp_currency (reserve_balance,
    1542             :                                             withdraw_fee_balance));
    1543             : 
    1544           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1545             :                                              "auditor_reserves_update",
    1546             :                                              params);
    1547             : }
    1548             : 
    1549             : 
    1550             : /**
    1551             :  * Delete information about a reserve.
    1552             :  *
    1553             :  * @param cls the @e cls of this struct with the plugin-specific state
    1554             :  * @param session connection to use
    1555             :  * @param reserve_pub public key of the reserve
    1556             :  * @param master_pub master public key of the exchange
    1557             :  * @return transaction status code
    1558             :  */
    1559             : static enum GNUNET_DB_QueryStatus
    1560           1 : postgres_del_reserve_info (void *cls,
    1561             :                            struct TALER_AUDITORDB_Session *session,
    1562             :                            const struct TALER_ReservePublicKeyP *reserve_pub,
    1563             :                            const struct TALER_MasterPublicKeyP *master_pub)
    1564             : {
    1565           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1566             :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1567             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1568             :     GNUNET_PQ_query_param_end
    1569             :   };
    1570             : 
    1571           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1572             :                                              "auditor_reserves_delete",
    1573             :                                              params);
    1574             : }
    1575             : 
    1576             : 
    1577             : /**
    1578             :  * Get information about a reserve.
    1579             :  *
    1580             :  * @param cls the @e cls of this struct with the plugin-specific state
    1581             :  * @param session connection to use
    1582             :  * @param reserve_pub public key of the reserve
    1583             :  * @param master_pub master public key of the exchange
    1584             :  * @param[out] rowid which row did we get the information from
    1585             :  * @param[out] reserve_balance amount stored in the reserve
    1586             :  * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
    1587             :  *                             due to withdrawals from this reserve
    1588             :  * @param[out] expiration_date expiration date of the reserve
    1589             :  * @return transaction status code
    1590             :  */
    1591             : static enum GNUNET_DB_QueryStatus
    1592           1 : postgres_get_reserve_info (void *cls,
    1593             :                            struct TALER_AUDITORDB_Session *session,
    1594             :                            const struct TALER_ReservePublicKeyP *reserve_pub,
    1595             :                            const struct TALER_MasterPublicKeyP *master_pub,
    1596             :                            uint64_t *rowid,
    1597             :                            struct TALER_Amount *reserve_balance,
    1598             :                            struct TALER_Amount *withdraw_fee_balance,
    1599             :                            struct GNUNET_TIME_Absolute *expiration_date)
    1600             : {
    1601           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1602             :     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
    1603             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1604             :     GNUNET_PQ_query_param_end
    1605             :   };
    1606           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1607             :     TALER_PQ_result_spec_amount ("reserve_balance", reserve_balance),
    1608             :     TALER_PQ_result_spec_amount ("withdraw_fee_balance", withdraw_fee_balance),
    1609             :     GNUNET_PQ_result_spec_absolute_time ("expiration_date", expiration_date),
    1610             :     GNUNET_PQ_result_spec_uint64 ("auditor_reserves_rowid", rowid),
    1611             :     GNUNET_PQ_result_spec_end
    1612             :   };
    1613             : 
    1614           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    1615             :                                                    "auditor_reserves_select",
    1616             :                                                    params,
    1617             :                                                    rs);
    1618             : }
    1619             : 
    1620             : 
    1621             : /**
    1622             :  * Insert information about all reserves.  There must not be an
    1623             :  * existing record for the @a master_pub.
    1624             :  *
    1625             :  * @param cls the @e cls of this struct with the plugin-specific state
    1626             :  * @param session connection to use
    1627             :  * @param master_pub master public key of the exchange
    1628             :  * @param reserve_balance amount stored in the reserve
    1629             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1630             :  *                             due to withdrawals from this reserve
    1631             :  * @return transaction status code
    1632             :  */
    1633             : static enum GNUNET_DB_QueryStatus
    1634           1 : postgres_insert_reserve_summary (void *cls,
    1635             :                                  struct TALER_AUDITORDB_Session *session,
    1636             :                                  const struct TALER_MasterPublicKeyP *master_pub,
    1637             :                                  const struct TALER_Amount *reserve_balance,
    1638             :                                  const struct TALER_Amount *withdraw_fee_balance)
    1639             : {
    1640           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1641             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1642             :     TALER_PQ_query_param_amount (reserve_balance),
    1643             :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1644             :     GNUNET_PQ_query_param_end
    1645             :   };
    1646             : 
    1647           1 :   GNUNET_assert (GNUNET_YES ==
    1648             :                  TALER_amount_cmp_currency (reserve_balance,
    1649             :                                             withdraw_fee_balance));
    1650             : 
    1651           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1652             :                                              "auditor_reserve_balance_insert",
    1653             :                                              params);
    1654             : }
    1655             : 
    1656             : 
    1657             : /**
    1658             :  * Update information about all reserves.  Destructively updates an
    1659             :  * existing record, which must already exist.
    1660             :  *
    1661             :  * @param cls the @e cls of this struct with the plugin-specific state
    1662             :  * @param session connection to use
    1663             :  * @param master_pub master public key of the exchange
    1664             :  * @param reserve_balance amount stored in the reserve
    1665             :  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    1666             :  *                             due to withdrawals from this reserve
    1667             :  * @return transaction status code
    1668             :  */
    1669             : static enum GNUNET_DB_QueryStatus
    1670           1 : postgres_update_reserve_summary (void *cls,
    1671             :                                  struct TALER_AUDITORDB_Session *session,
    1672             :                                  const struct TALER_MasterPublicKeyP *master_pub,
    1673             :                                  const struct TALER_Amount *reserve_balance,
    1674             :                                  const struct TALER_Amount *withdraw_fee_balance)
    1675             : {
    1676           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1677             :     TALER_PQ_query_param_amount (reserve_balance),
    1678             :     TALER_PQ_query_param_amount (withdraw_fee_balance),
    1679             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1680             :     GNUNET_PQ_query_param_end
    1681             :   };
    1682             : 
    1683           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1684             :                                              "auditor_reserve_balance_update",
    1685             :                                              params);
    1686             : }
    1687             : 
    1688             : 
    1689             : /**
    1690             :  * Get summary information about all reserves.
    1691             :  *
    1692             :  * @param cls the @e cls of this struct with the plugin-specific state
    1693             :  * @param session connection to use
    1694             :  * @param master_pub master public key of the exchange
    1695             :  * @param[out] reserve_balance amount stored in the reserve
    1696             :  * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
    1697             :  *                             due to withdrawals from this reserve
    1698             :  * @return transaction status code
    1699             :  */
    1700             : static enum GNUNET_DB_QueryStatus
    1701           1 : postgres_get_reserve_summary (void *cls,
    1702             :                               struct TALER_AUDITORDB_Session *session,
    1703             :                               const struct TALER_MasterPublicKeyP *master_pub,
    1704             :                               struct TALER_Amount *reserve_balance,
    1705             :                               struct TALER_Amount *withdraw_fee_balance)
    1706             : {
    1707           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1708             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1709             :     GNUNET_PQ_query_param_end
    1710             :   };
    1711           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1712             :     TALER_PQ_result_spec_amount ("reserve_balance", reserve_balance),
    1713             :     TALER_PQ_result_spec_amount ("withdraw_fee_balance", withdraw_fee_balance),
    1714             : 
    1715             :     GNUNET_PQ_result_spec_end
    1716             :   };
    1717             : 
    1718           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    1719             :                                                    "auditor_reserve_balance_select",
    1720             :                                                    params,
    1721             :                                                    rs);
    1722             : }
    1723             : 
    1724             : 
    1725             : /**
    1726             :  * Insert information about exchange's wire fee balance. There must not be an
    1727             :  * existing record for the same @a master_pub.
    1728             :  *
    1729             :  * @param cls the @e cls of this struct with the plugin-specific state
    1730             :  * @param session connection to use
    1731             :  * @param master_pub master public key of the exchange
    1732             :  * @param wire_fee_balance amount the exchange gained in wire fees
    1733             :  * @return transaction status code
    1734             :  */
    1735             : static enum GNUNET_DB_QueryStatus
    1736           1 : postgres_insert_wire_fee_summary (void *cls,
    1737             :                                   struct TALER_AUDITORDB_Session *session,
    1738             :                                   const struct TALER_MasterPublicKeyP *master_pub,
    1739             :                                   const struct TALER_Amount *wire_fee_balance)
    1740             : {
    1741           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1742             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1743             :     TALER_PQ_query_param_amount (wire_fee_balance),
    1744             :     GNUNET_PQ_query_param_end
    1745             :   };
    1746             : 
    1747           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1748             :                                              "auditor_wire_fee_balance_insert",
    1749             :                                              params);
    1750             : }
    1751             : 
    1752             : 
    1753             : /**
    1754             :  * Insert information about exchange's wire fee balance.  Destructively updates an
    1755             :  * existing record, which must already exist.
    1756             :  *
    1757             :  * @param cls the @e cls of this struct with the plugin-specific state
    1758             :  * @param session connection to use
    1759             :  * @param master_pub master public key of the exchange
    1760             :  * @param wire_fee_balance amount the exchange gained in wire fees
    1761             :  * @return transaction status code
    1762             :  */
    1763             : static enum GNUNET_DB_QueryStatus
    1764           1 : postgres_update_wire_fee_summary (void *cls,
    1765             :                                   struct TALER_AUDITORDB_Session *session,
    1766             :                                   const struct TALER_MasterPublicKeyP *master_pub,
    1767             :                                   const struct TALER_Amount *wire_fee_balance)
    1768             : {
    1769           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1770             :     TALER_PQ_query_param_amount (wire_fee_balance),
    1771             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1772             :     GNUNET_PQ_query_param_end
    1773             :   };
    1774             : 
    1775           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1776             :                                              "auditor_wire_fee_balance_update",
    1777             :                                              params);
    1778             : }
    1779             : 
    1780             : 
    1781             : /**
    1782             :  * Get summary information about an exchanges wire fee balance.
    1783             :  *
    1784             :  * @param cls the @e cls of this struct with the plugin-specific state
    1785             :  * @param session connection to use
    1786             :  * @param master_pub master public key of the exchange
    1787             :  * @param[out] wire_fee_balance set amount the exchange gained in wire fees
    1788             :  * @return transaction status code
    1789             :  */
    1790             : static enum GNUNET_DB_QueryStatus
    1791           1 : postgres_get_wire_fee_summary (void *cls,
    1792             :                                struct TALER_AUDITORDB_Session *session,
    1793             :                                const struct TALER_MasterPublicKeyP *master_pub,
    1794             :                                struct TALER_Amount *wire_fee_balance)
    1795             : {
    1796           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1797             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1798             :     GNUNET_PQ_query_param_end
    1799             :   };
    1800           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1801             :     TALER_PQ_result_spec_amount ("wire_fee_balance", wire_fee_balance),
    1802             : 
    1803             :     GNUNET_PQ_result_spec_end
    1804             :   };
    1805             : 
    1806           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    1807             :                                                    "auditor_wire_fee_balance_select",
    1808             :                                                    params,
    1809             :                                                    rs);
    1810             : }
    1811             : 
    1812             : 
    1813             : /**
    1814             :  * Insert information about a denomination key's balances.  There
    1815             :  * must not be an existing record for the denomination key.
    1816             :  *
    1817             :  * @param cls the @e cls of this struct with the plugin-specific state
    1818             :  * @param session connection to use
    1819             :  * @param denom_pub_hash hash of the denomination public key
    1820             :  * @param denom_balance value of coins outstanding with this denomination key
    1821             :  * @param denom_risk value of coins issued with this denomination key
    1822             :  * @return transaction status code
    1823             :  */
    1824             : static enum GNUNET_DB_QueryStatus
    1825           1 : postgres_insert_denomination_balance (void *cls,
    1826             :                                       struct TALER_AUDITORDB_Session *session,
    1827             :                                       const struct GNUNET_HashCode *denom_pub_hash,
    1828             :                                       const struct TALER_Amount *denom_balance,
    1829             :                                       const struct TALER_Amount *denom_risk)
    1830             : {
    1831           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1832             :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    1833             :     TALER_PQ_query_param_amount (denom_balance),
    1834             :     TALER_PQ_query_param_amount (denom_risk),
    1835             :     GNUNET_PQ_query_param_end
    1836             :   };
    1837             : 
    1838           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1839             :                                              "auditor_denomination_pending_insert",
    1840             :                                              params);
    1841             : }
    1842             : 
    1843             : 
    1844             : /**
    1845             :  * Update information about a denomination key's balances.  There
    1846             :  * must be an existing record for the denomination key.
    1847             :  *
    1848             :  * @param cls the @e cls of this struct with the plugin-specific state
    1849             :  * @param session connection to use
    1850             :  * @param denom_pub_hash hash of the denomination public key
    1851             :  * @param denom_balance value of coins outstanding with this denomination key
    1852             :  * @param denom_risk value of coins issued with this denomination key
    1853             :  * @return transaction status code
    1854             :  */
    1855             : static enum GNUNET_DB_QueryStatus
    1856           1 : postgres_update_denomination_balance (void *cls,
    1857             :                                       struct TALER_AUDITORDB_Session *session,
    1858             :                                       const struct GNUNET_HashCode *denom_pub_hash,
    1859             :                                       const struct TALER_Amount *denom_balance,
    1860             :                                       const struct TALER_Amount *denom_risk)
    1861             : {
    1862           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1863             :     TALER_PQ_query_param_amount (denom_balance),
    1864             :     TALER_PQ_query_param_amount (denom_risk),
    1865             :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    1866             :     GNUNET_PQ_query_param_end
    1867             :   };
    1868             : 
    1869           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1870             :                                              "auditor_denomination_pending_update",
    1871             :                                              params);
    1872             : }
    1873             : 
    1874             : 
    1875             : /**
    1876             :  * Get information about a denomination key's balances.
    1877             :  *
    1878             :  * @param cls the @e cls of this struct with the plugin-specific state
    1879             :  * @param session connection to use
    1880             :  * @param denom_pub_hash hash of the denomination public key
    1881             :  * @param[out] denom_balance value of coins outstanding with this denomination key
    1882             :  * @param[out] denom_risk value of coins issued with this denomination key
    1883             :  * @return transaction status code
    1884             :  */
    1885             : static enum GNUNET_DB_QueryStatus
    1886           1 : postgres_get_denomination_balance (void *cls,
    1887             :                                    struct TALER_AUDITORDB_Session *session,
    1888             :                                    const struct GNUNET_HashCode *denom_pub_hash,
    1889             :                                    struct TALER_Amount *denom_balance,
    1890             :                                    struct TALER_Amount *denom_risk)
    1891             : {
    1892           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1893             :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    1894             :     GNUNET_PQ_query_param_end
    1895             :   };
    1896           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    1897             :     TALER_PQ_result_spec_amount ("denom_balance", denom_balance),
    1898             :     TALER_PQ_result_spec_amount ("denom_risk", denom_risk),
    1899             :     GNUNET_PQ_result_spec_end
    1900             :   };
    1901             : 
    1902           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    1903             :                                                    "auditor_denomination_pending_select",
    1904             :                                                    params,
    1905             :                                                    rs);
    1906             : }
    1907             : 
    1908             : 
    1909             : /**
    1910             :  * Insert information about an exchange's denomination balances.  There
    1911             :  * must not be an existing record for the exchange.
    1912             :  *
    1913             :  * @param cls the @e cls of this struct with the plugin-specific state
    1914             :  * @param session connection to use
    1915             :  * @param master_pub master key of the exchange
    1916             :  * @param denom_balance value of coins outstanding with this denomination key
    1917             :  * @param deposit_fee_balance total deposit fees collected for this DK
    1918             :  * @param melt_fee_balance total melt fees collected for this DK
    1919             :  * @param refund_fee_balance total refund fees collected for this DK
    1920             :  * @param risk maximum risk exposure of the exchange
    1921             :  * @return transaction status code
    1922             :  */
    1923             : static enum GNUNET_DB_QueryStatus
    1924           1 : postgres_insert_balance_summary (void *cls,
    1925             :                                  struct TALER_AUDITORDB_Session *session,
    1926             :                                  const struct TALER_MasterPublicKeyP *master_pub,
    1927             :                                  const struct TALER_Amount *denom_balance,
    1928             :                                  const struct TALER_Amount *deposit_fee_balance,
    1929             :                                  const struct TALER_Amount *melt_fee_balance,
    1930             :                                  const struct TALER_Amount *refund_fee_balance,
    1931             :                                  const struct TALER_Amount *risk)
    1932             : {
    1933           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1934             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1935             :     TALER_PQ_query_param_amount (denom_balance),
    1936             :     TALER_PQ_query_param_amount (deposit_fee_balance),
    1937             :     TALER_PQ_query_param_amount (melt_fee_balance),
    1938             :     TALER_PQ_query_param_amount (refund_fee_balance),
    1939             :     TALER_PQ_query_param_amount (risk),
    1940             :     GNUNET_PQ_query_param_end
    1941             :   };
    1942             : 
    1943           1 :   GNUNET_assert (GNUNET_YES ==
    1944             :                  TALER_amount_cmp_currency (denom_balance,
    1945             :                                             deposit_fee_balance));
    1946             : 
    1947           1 :   GNUNET_assert (GNUNET_YES ==
    1948             :                  TALER_amount_cmp_currency (denom_balance,
    1949             :                                             melt_fee_balance));
    1950             : 
    1951           1 :   GNUNET_assert (GNUNET_YES ==
    1952             :                  TALER_amount_cmp_currency (denom_balance,
    1953             :                                             refund_fee_balance));
    1954             : 
    1955           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1956             :                                              "auditor_balance_summary_insert",
    1957             :                                              params);
    1958             : }
    1959             : 
    1960             : 
    1961             : /**
    1962             :  * Update information about an exchange's denomination balances.  There
    1963             :  * must be an existing record for the exchange.
    1964             :  *
    1965             :  * @param cls the @e cls of this struct with the plugin-specific state
    1966             :  * @param session connection to use
    1967             :  * @param master_pub master key of the exchange
    1968             :  * @param denom_balance value of coins outstanding with this denomination key
    1969             :  * @param deposit_fee_balance total deposit fees collected for this DK
    1970             :  * @param melt_fee_balance total melt fees collected for this DK
    1971             :  * @param refund_fee_balance total refund fees collected for this DK
    1972             :  * @param risk maximum risk exposure of the exchange
    1973             :  * @return transaction status code
    1974             :  */
    1975             : static enum GNUNET_DB_QueryStatus
    1976           1 : postgres_update_balance_summary (void *cls,
    1977             :                                  struct TALER_AUDITORDB_Session *session,
    1978             :                                  const struct TALER_MasterPublicKeyP *master_pub,
    1979             :                                  const struct TALER_Amount *denom_balance,
    1980             :                                  const struct TALER_Amount *deposit_fee_balance,
    1981             :                                  const struct TALER_Amount *melt_fee_balance,
    1982             :                                  const struct TALER_Amount *refund_fee_balance,
    1983             :                                  const struct TALER_Amount *risk)
    1984             : {
    1985           1 :   struct GNUNET_PQ_QueryParam params[] = {
    1986             :     TALER_PQ_query_param_amount (denom_balance),
    1987             :     TALER_PQ_query_param_amount (deposit_fee_balance),
    1988             :     TALER_PQ_query_param_amount (melt_fee_balance),
    1989             :     TALER_PQ_query_param_amount (refund_fee_balance),
    1990             :     TALER_PQ_query_param_amount (risk),
    1991             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    1992             :     GNUNET_PQ_query_param_end
    1993             :   };
    1994             : 
    1995           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    1996             :                                              "auditor_balance_summary_update",
    1997             :                                              params);
    1998             : }
    1999             : 
    2000             : 
    2001             : /**
    2002             :  * Get information about an exchange's denomination balances.
    2003             :  *
    2004             :  * @param cls the @e cls of this struct with the plugin-specific state
    2005             :  * @param session connection to use
    2006             :  * @param master_pub master key of the exchange
    2007             :  * @param[out] denom_balance value of coins outstanding with this denomination key
    2008             :  * @param[out] deposit_fee_balance total deposit fees collected for this DK
    2009             :  * @param[out] melt_fee_balance total melt fees collected for this DK
    2010             :  * @param[out] refund_fee_balance total refund fees collected for this DK
    2011             :  * @param[out] risk maximum risk exposure of the exchange
    2012             :  * @return transaction status code
    2013             :  */
    2014             : static enum GNUNET_DB_QueryStatus
    2015           1 : postgres_get_balance_summary (void *cls,
    2016             :                               struct TALER_AUDITORDB_Session *session,
    2017             :                               const struct TALER_MasterPublicKeyP *master_pub,
    2018             :                               struct TALER_Amount *denom_balance,
    2019             :                               struct TALER_Amount *deposit_fee_balance,
    2020             :                               struct TALER_Amount *melt_fee_balance,
    2021             :                               struct TALER_Amount *refund_fee_balance,
    2022             :                               struct TALER_Amount *risk)
    2023             : {
    2024           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2025             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2026             :     GNUNET_PQ_query_param_end
    2027             :   };
    2028           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2029             :     TALER_PQ_result_spec_amount ("denom_balance", denom_balance),
    2030             :     TALER_PQ_result_spec_amount ("deposit_fee_balance", deposit_fee_balance),
    2031             :     TALER_PQ_result_spec_amount ("melt_fee_balance", melt_fee_balance),
    2032             :     TALER_PQ_result_spec_amount ("refund_fee_balance", refund_fee_balance),
    2033             :     TALER_PQ_result_spec_amount ("risk", risk),
    2034             :     GNUNET_PQ_result_spec_end
    2035             :   };
    2036             : 
    2037           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    2038             :                                                    "auditor_balance_summary_select",
    2039             :                                                    params,
    2040             :                                                    rs);
    2041             : }
    2042             : 
    2043             : 
    2044             : /**
    2045             :  * Insert information about an exchange's historic
    2046             :  * revenue about a denomination key.
    2047             :  *
    2048             :  * @param cls the @e cls of this struct with the plugin-specific state
    2049             :  * @param session connection to use
    2050             :  * @param master_pub master key of the exchange
    2051             :  * @param denom_pub_hash hash of the denomination key
    2052             :  * @param revenue_timestamp when did this profit get realized
    2053             :  * @param revenue_balance what was the total profit made from
    2054             :  *                        deposit fees, melting fees, refresh fees
    2055             :  *                        and coins that were never returned?
    2056             :  * @return transaction status code
    2057             :  */
    2058             : static enum GNUNET_DB_QueryStatus
    2059           2 : postgres_insert_historic_denom_revenue (void *cls,
    2060             :                                         struct TALER_AUDITORDB_Session *session,
    2061             :                                         const struct TALER_MasterPublicKeyP *master_pub,
    2062             :                                         const struct GNUNET_HashCode *denom_pub_hash,
    2063             :                                         struct GNUNET_TIME_Absolute revenue_timestamp,
    2064             :                                         const struct TALER_Amount *revenue_balance)
    2065             : {
    2066           2 :   struct GNUNET_PQ_QueryParam params[] = {
    2067             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2068             :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    2069             :     GNUNET_PQ_query_param_absolute_time (&revenue_timestamp),
    2070             :     TALER_PQ_query_param_amount (revenue_balance),
    2071             :     GNUNET_PQ_query_param_end
    2072             :   };
    2073             : 
    2074           2 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    2075             :                                              "auditor_historic_denomination_revenue_insert",
    2076             :                                              params);
    2077             : }
    2078             : 
    2079             : 
    2080             : /**
    2081             :  * Closure for #historic_denom_revenue_cb().
    2082             :  */
    2083             : struct HistoricDenomRevenueContext
    2084             : {
    2085             :   /**
    2086             :    * Function to call for each result.
    2087             :    */
    2088             :   TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb;
    2089             : 
    2090             :   /**
    2091             :    * Closure for @e cb.
    2092             :    */
    2093             :   void *cb_cls;
    2094             : 
    2095             :   /**
    2096             :    * Number of results processed.
    2097             :    */
    2098             :   enum GNUNET_DB_QueryStatus qs;
    2099             : };
    2100             : 
    2101             : 
    2102             : /**
    2103             :  * Helper function for #postgres_select_historic_denom_revenue().
    2104             :  * To be called with the results of a SELECT statement
    2105             :  * that has returned @a num_results results.
    2106             :  *
    2107             :  * @param cls closure of type `struct HistoricRevenueContext *`
    2108             :  * @param result the postgres result
    2109             :  * @param num_result the number of results in @a result
    2110             :  */
    2111             : static void
    2112           1 : historic_denom_revenue_cb (void *cls,
    2113             :                            PGresult *result,
    2114             :                            unsigned int num_results)
    2115             : {
    2116           1 :   struct HistoricDenomRevenueContext *hrc = cls;
    2117             : 
    2118           3 :   for (unsigned int i = 0; i < num_results; i++)
    2119             :   {
    2120             :     struct GNUNET_HashCode denom_pub_hash;
    2121             :     struct GNUNET_TIME_Absolute revenue_timestamp;
    2122             :     struct TALER_Amount revenue_balance;
    2123           2 :     struct GNUNET_PQ_ResultSpec rs[] = {
    2124             :       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash),
    2125             :       GNUNET_PQ_result_spec_absolute_time ("revenue_timestamp", &revenue_timestamp),
    2126             :       TALER_PQ_result_spec_amount ("revenue_balance", &revenue_balance),
    2127             :       GNUNET_PQ_result_spec_end
    2128             :     };
    2129             : 
    2130           2 :     if (GNUNET_OK !=
    2131           2 :         GNUNET_PQ_extract_result (result,
    2132             :                                   rs,
    2133             :                                   i))
    2134             :     {
    2135           0 :       GNUNET_break (0);
    2136           0 :       hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    2137           0 :       return;
    2138             :     }
    2139             : 
    2140           2 :     hrc->qs = i + 1;
    2141           2 :     if (GNUNET_OK !=
    2142           2 :         hrc->cb (hrc->cb_cls,
    2143             :                  &denom_pub_hash,
    2144             :                  revenue_timestamp,
    2145             :                  &revenue_balance))
    2146           0 :       break;
    2147             :   }
    2148             : }
    2149             : 
    2150             : 
    2151             : /**
    2152             :  * Obtain all of the historic denomination key revenue
    2153             :  * of the given @a master_pub.
    2154             :  *
    2155             :  * @param cls the @e cls of this struct with the plugin-specific state
    2156             :  * @param session connection to use
    2157             :  * @param master_pub master key of the exchange
    2158             :  * @param cb function to call with the results
    2159             :  * @param cb_cls closure for @a cb
    2160             :  * @return transaction status code
    2161             :  */
    2162             : static enum GNUNET_DB_QueryStatus
    2163           1 : postgres_select_historic_denom_revenue (void *cls,
    2164             :                                         struct TALER_AUDITORDB_Session *session,
    2165             :                                         const struct TALER_MasterPublicKeyP *master_pub,
    2166             :                                         TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,
    2167             :                                         void *cb_cls)
    2168             : {
    2169           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2170             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2171             :     GNUNET_PQ_query_param_end
    2172             :   };
    2173           1 :   struct HistoricDenomRevenueContext hrc = {
    2174             :     .cb = cb,
    2175             :     .cb_cls = cb_cls
    2176             :   };
    2177             :   enum GNUNET_DB_QueryStatus qs;
    2178             : 
    2179           1 :   qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
    2180             :                                              "auditor_historic_denomination_revenue_select",
    2181             :                                              params,
    2182             :                                              &historic_denom_revenue_cb,
    2183             :                                              &hrc);
    2184           1 :   if (qs <= 0)
    2185           0 :     return qs;
    2186           1 :   return hrc.qs;
    2187             : }
    2188             : 
    2189             : 
    2190             : /**
    2191             :  * Insert information about an exchange's historic
    2192             :  * losses (from compromised denomination keys).
    2193             :  *
    2194             :  * Note yet used, need to implement exchange's bankrupcy
    2195             :  * protocol (and tables!) first.
    2196             :  *
    2197             :  * @param cls the @e cls of this struct with the plugin-specific state
    2198             :  * @param session connection to use
    2199             :  * @param master_pub master key of the exchange
    2200             :  * @param denom_pub_hash hash of the denomination key
    2201             :  * @param loss_timestamp when did this profit get realized
    2202             :  * @param loss_balance what was the total loss
    2203             :  * @return transaction status code
    2204             :  */
    2205             : static enum GNUNET_DB_QueryStatus
    2206           2 : postgres_insert_historic_losses (void *cls,
    2207             :                                  struct TALER_AUDITORDB_Session *session,
    2208             :                                  const struct TALER_MasterPublicKeyP *master_pub,
    2209             :                                  const struct GNUNET_HashCode *denom_pub_hash,
    2210             :                                  struct GNUNET_TIME_Absolute loss_timestamp,
    2211             :                                  const struct TALER_Amount *loss_balance)
    2212             : {
    2213           2 :   struct GNUNET_PQ_QueryParam params[] = {
    2214             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2215             :     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
    2216             :     GNUNET_PQ_query_param_absolute_time (&loss_timestamp),
    2217             :     TALER_PQ_query_param_amount (loss_balance),
    2218             :     GNUNET_PQ_query_param_end
    2219             :   };
    2220             : 
    2221           2 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    2222             :                                              "auditor_historic_losses_insert",
    2223             :                                              params);
    2224             : }
    2225             : 
    2226             : 
    2227             : /**
    2228             :  * Closure for #losses_cb.
    2229             :  */
    2230             : struct LossContext
    2231             : {
    2232             :   /**
    2233             :    * Function to call for each result.
    2234             :    */
    2235             :   TALER_AUDITORDB_HistoricLossesDataCallback cb;
    2236             : 
    2237             :   /**
    2238             :    * Closure for @e cb.
    2239             :    */
    2240             :   void *cb_cls;
    2241             : 
    2242             :   /**
    2243             :    * Status code to return.
    2244             :    */
    2245             :   enum GNUNET_DB_QueryStatus qs;
    2246             : };
    2247             : 
    2248             : 
    2249             : /**
    2250             :  * Helper function for #postgres_select_historic_denom_revenue().
    2251             :  * To be called with the results of a SELECT statement
    2252             :  * that has returned @a num_results results.
    2253             :  *
    2254             :  * @param cls closure of type `struct HistoricRevenueContext *`
    2255             :  * @param result the postgres result
    2256             :  * @param num_result the number of results in @a result
    2257             :  */
    2258             : static void
    2259           1 : losses_cb (void *cls,
    2260             :            PGresult *result,
    2261             :            unsigned int num_results)
    2262             : {
    2263           1 :   struct LossContext *lctx = cls;
    2264             : 
    2265           3 :   for (unsigned int i = 0; i < num_results; i++)
    2266             :   {
    2267             :     struct GNUNET_HashCode denom_pub_hash;
    2268             :     struct GNUNET_TIME_Absolute loss_timestamp;
    2269             :     struct TALER_Amount loss_balance;
    2270           2 :     struct GNUNET_PQ_ResultSpec rs[] = {
    2271             :       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash),
    2272             :       GNUNET_PQ_result_spec_absolute_time ("loss_timestamp", &loss_timestamp),
    2273             :       TALER_PQ_result_spec_amount ("loss_balance", &loss_balance),
    2274             :       GNUNET_PQ_result_spec_end
    2275             :     };
    2276             : 
    2277           2 :     if (GNUNET_OK !=
    2278           2 :         GNUNET_PQ_extract_result (result,
    2279             :                                   rs,
    2280             :                                   i))
    2281             :     {
    2282           0 :       GNUNET_break (0);
    2283           0 :       lctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
    2284           0 :       return;
    2285             :     }
    2286           2 :     lctx->qs = i + 1;
    2287           2 :     if (GNUNET_OK !=
    2288           2 :         lctx->cb (lctx->cb_cls,
    2289             :                   &denom_pub_hash,
    2290             :                   loss_timestamp,
    2291             :                   &loss_balance))
    2292           0 :       break;
    2293             :   }
    2294             : }
    2295             : 
    2296             : 
    2297             : /**
    2298             :  * Obtain all of the historic denomination key losses
    2299             :  * of the given @a master_pub.
    2300             :  *
    2301             :  * @param cls the @e cls of this struct with the plugin-specific state
    2302             :  * @param session connection to use
    2303             :  * @param master_pub master key of the exchange
    2304             :  * @param cb function to call with the results
    2305             :  * @param cb_cls closure for @a cb
    2306             :  * @return transaction status code
    2307             :  */
    2308             : static enum GNUNET_DB_QueryStatus
    2309           1 : postgres_select_historic_losses (void *cls,
    2310             :                                  struct TALER_AUDITORDB_Session *session,
    2311             :                                  const struct TALER_MasterPublicKeyP *master_pub,
    2312             :                                  TALER_AUDITORDB_HistoricLossesDataCallback cb,
    2313             :                                  void *cb_cls)
    2314             : {
    2315           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2316             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2317             :     GNUNET_PQ_query_param_end
    2318             :   };
    2319           1 :   struct LossContext lctx = {
    2320             :     .cb = cb,
    2321             :     .cb_cls = cb_cls
    2322             :   };
    2323             :   enum GNUNET_DB_QueryStatus qs;
    2324             : 
    2325           1 :   qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
    2326             :                                              "auditor_historic_losses_select",
    2327             :                                              params,
    2328             :                                              &losses_cb,
    2329             :                                              &lctx);
    2330           1 :   if (qs <= 0)
    2331           0 :     return qs;
    2332           1 :   return lctx.qs;
    2333             : }
    2334             : 
    2335             : 
    2336             : /**
    2337             :  * Insert information about an exchange's historic revenue from reserves.
    2338             :  *
    2339             :  * @param cls the @e cls of this struct with the plugin-specific state
    2340             :  * @param session connection to use
    2341             :  * @param master_pub master key of the exchange
    2342             :  * @param start_time beginning of aggregated time interval
    2343             :  * @param end_time end of aggregated time interval
    2344             :  * @param reserve_profits total profits made
    2345             :  * @return transaction status code
    2346             :  */
    2347             : static enum GNUNET_DB_QueryStatus
    2348           2 : postgres_insert_historic_reserve_revenue (void *cls,
    2349             :                                           struct TALER_AUDITORDB_Session *session,
    2350             :                                           const struct TALER_MasterPublicKeyP *master_pub,
    2351             :                                           struct GNUNET_TIME_Absolute start_time,
    2352             :                                           struct GNUNET_TIME_Absolute end_time,
    2353             :                                           const struct TALER_Amount *reserve_profits)
    2354             : {
    2355           2 :   struct GNUNET_PQ_QueryParam params[] = {
    2356             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2357             :     GNUNET_PQ_query_param_absolute_time (&start_time),
    2358             :     GNUNET_PQ_query_param_absolute_time (&end_time),
    2359             :     TALER_PQ_query_param_amount (reserve_profits),
    2360             :     GNUNET_PQ_query_param_end
    2361             :   };
    2362             : 
    2363           2 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    2364             :                                              "auditor_historic_reserve_summary_insert",
    2365             :                                              params);
    2366             : }
    2367             : 
    2368             : 
    2369             : /**
    2370             :  * Closure for #historic_reserve_revenue_cb().
    2371             :  */
    2372             : struct HistoricReserveRevenueContext
    2373             : {
    2374             :   /**
    2375             :    * Function to call for each result.
    2376             :    */
    2377             :   TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb;
    2378             : 
    2379             :   /**
    2380             :    * Closure for @e cb.
    2381             :    */
    2382             :   void *cb_cls;
    2383             : 
    2384             :   /**
    2385             :    * Number of results processed.
    2386             :    */
    2387             :   enum GNUNET_DB_QueryStatus qs;
    2388             : };
    2389             : 
    2390             : 
    2391             : /**
    2392             :  * Helper function for #postgres_select_historic_reserve_revenue().
    2393             :  * To be called with the results of a SELECT statement
    2394             :  * that has returned @a num_results results.
    2395             :  *
    2396             :  * @param cls closure of type `struct HistoricRevenueContext *`
    2397             :  * @param result the postgres result
    2398             :  * @param num_result the number of results in @a result
    2399             :  */
    2400             : static void
    2401           1 : historic_reserve_revenue_cb (void *cls,
    2402             :                              PGresult *result,
    2403             :                              unsigned int num_results)
    2404             : {
    2405           1 :   struct HistoricReserveRevenueContext *hrc = cls;
    2406             : 
    2407           3 :   for (unsigned int i = 0; i < num_results; i++)
    2408             :   {
    2409             :     struct GNUNET_TIME_Absolute start_date;
    2410             :     struct GNUNET_TIME_Absolute end_date;
    2411             :     struct TALER_Amount reserve_profits;
    2412           2 :     struct GNUNET_PQ_ResultSpec rs[] = {
    2413             :       GNUNET_PQ_result_spec_absolute_time ("start_date", &start_date),
    2414             :       GNUNET_PQ_result_spec_absolute_time ("end_date", &end_date),
    2415             :       TALER_PQ_result_spec_amount ("reserve_profits", &reserve_profits),
    2416             :       GNUNET_PQ_result_spec_end
    2417             :     };
    2418             : 
    2419           2 :     if (GNUNET_OK !=
    2420           2 :         GNUNET_PQ_extract_result (result,
    2421             :                                   rs,
    2422             :                                   i))
    2423             :     {
    2424           0 :       GNUNET_break (0);
    2425           0 :       hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    2426           0 :       return;
    2427             :     }
    2428           2 :     hrc->qs = i + 1;
    2429           2 :     if (GNUNET_OK !=
    2430           2 :         hrc->cb (hrc->cb_cls,
    2431             :                  start_date,
    2432             :                  end_date,
    2433             :                  &reserve_profits))
    2434           0 :       break;
    2435             :   }
    2436             : }
    2437             : 
    2438             : 
    2439             : /**
    2440             :  * Return information about an exchange's historic revenue from reserves.
    2441             :  *
    2442             :  * @param cls the @e cls of this struct with the plugin-specific state
    2443             :  * @param session connection to use
    2444             :  * @param master_pub master key of the exchange
    2445             :  * @param cb function to call with results
    2446             :  * @param cb_cls closure for @a cb
    2447             :  * @return transaction status code
    2448             :  */
    2449             : static enum GNUNET_DB_QueryStatus
    2450           1 : postgres_select_historic_reserve_revenue (void *cls,
    2451             :                                           struct TALER_AUDITORDB_Session *session,
    2452             :                                           const struct TALER_MasterPublicKeyP *master_pub,
    2453             :                                           TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,
    2454             :                                           void *cb_cls)
    2455             : {
    2456           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2457             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2458             :     GNUNET_PQ_query_param_end
    2459             :   };
    2460             :   enum GNUNET_DB_QueryStatus qs;
    2461           1 :   struct HistoricReserveRevenueContext hrc = {
    2462             :     .cb = cb,
    2463             :     .cb_cls = cb_cls
    2464             :   };
    2465             : 
    2466           1 :   qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
    2467             :                                              "auditor_historic_reserve_summary_select",
    2468             :                                              params,
    2469             :                                              &historic_reserve_revenue_cb,
    2470             :                                              &hrc);
    2471           1 :   if (0 >= qs)
    2472           0 :     return qs;
    2473           1 :   return hrc.qs;
    2474             : }
    2475             : 
    2476             : 
    2477             : /**
    2478             :  * Insert information about the predicted exchange's bank
    2479             :  * account balance.
    2480             :  *
    2481             :  * @param cls the @e cls of this struct with the plugin-specific state
    2482             :  * @param session connection to use
    2483             :  * @param master_pub master key of the exchange
    2484             :  * @param balance what the bank account balance of the exchange should show
    2485             :  * @return transaction status code
    2486             :  */
    2487             : static enum GNUNET_DB_QueryStatus
    2488           1 : postgres_insert_predicted_result (void *cls,
    2489             :                                   struct TALER_AUDITORDB_Session *session,
    2490             :                                   const struct TALER_MasterPublicKeyP *master_pub,
    2491             :                                   const struct TALER_Amount *balance)
    2492             : {
    2493           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2494             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2495             :     TALER_PQ_query_param_amount (balance),
    2496             :     GNUNET_PQ_query_param_end
    2497             :   };
    2498             : 
    2499           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    2500             :                                              "auditor_predicted_result_insert",
    2501             :                                              params);
    2502             : }
    2503             : 
    2504             : 
    2505             : /**
    2506             :  * Update information about an exchange's predicted balance.  There
    2507             :  * must be an existing record for the exchange.
    2508             :  *
    2509             :  * @param cls the @e cls of this struct with the plugin-specific state
    2510             :  * @param session connection to use
    2511             :  * @param master_pub master key of the exchange
    2512             :  * @param balance what the bank account balance of the exchange should show
    2513             :  * @return transaction status code
    2514             :  */
    2515             : static enum GNUNET_DB_QueryStatus
    2516           1 : postgres_update_predicted_result (void *cls,
    2517             :                                   struct TALER_AUDITORDB_Session *session,
    2518             :                                   const struct TALER_MasterPublicKeyP *master_pub,
    2519             :                                   const struct TALER_Amount *balance)
    2520             : {
    2521           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2522             :     TALER_PQ_query_param_amount (balance),
    2523             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2524             :     GNUNET_PQ_query_param_end
    2525             :   };
    2526             : 
    2527           1 :   return GNUNET_PQ_eval_prepared_non_select (session->conn,
    2528             :                                              "auditor_predicted_result_update",
    2529             :                                              params);
    2530             : }
    2531             : 
    2532             : 
    2533             : /**
    2534             :  * Get an exchange's predicted balance.
    2535             :  *
    2536             :  * @param cls the @e cls of this struct with the plugin-specific state
    2537             :  * @param session connection to use
    2538             :  * @param master_pub master key of the exchange
    2539             :  * @param[out] balance expected bank account balance of the exchange
    2540             :  * @return transaction status code
    2541             :  */
    2542             : static enum GNUNET_DB_QueryStatus
    2543           1 : postgres_get_predicted_balance (void *cls,
    2544             :                                 struct TALER_AUDITORDB_Session *session,
    2545             :                                 const struct TALER_MasterPublicKeyP *master_pub,
    2546             :                                 struct TALER_Amount *balance)
    2547             : {
    2548           1 :   struct GNUNET_PQ_QueryParam params[] = {
    2549             :     GNUNET_PQ_query_param_auto_from_type (master_pub),
    2550             :     GNUNET_PQ_query_param_end
    2551             :   };
    2552           1 :   struct GNUNET_PQ_ResultSpec rs[] = {
    2553             :     TALER_PQ_result_spec_amount ("balance", balance),
    2554             : 
    2555             :     GNUNET_PQ_result_spec_end
    2556             :   };
    2557             : 
    2558           1 :   return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
    2559             :                                                    "auditor_predicted_result_select",
    2560             :                                                    params,
    2561             :                                                    rs);
    2562             : }
    2563             : 
    2564             : 
    2565             : /**
    2566             :  * Initialize Postgres database subsystem.
    2567             :  *
    2568             :  * @param cls a configuration instance
    2569             :  * @return NULL on error, otherwise a `struct TALER_AUDITORDB_Plugin`
    2570             :  */
    2571             : void *
    2572           4 : libtaler_plugin_auditordb_postgres_init (void *cls)
    2573             : {
    2574           4 :   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    2575             :   struct PostgresClosure *pg;
    2576             :   struct TALER_AUDITORDB_Plugin *plugin;
    2577             :   const char *ec;
    2578             : 
    2579           4 :   pg = GNUNET_new (struct PostgresClosure);
    2580           4 :   if (0 != pthread_key_create (&pg->db_conn_threadlocal,
    2581             :                                &db_conn_destroy))
    2582             :   {
    2583           0 :     TALER_LOG_ERROR ("Cannnot create pthread key.\n");
    2584           0 :     GNUNET_free (pg);
    2585           0 :     return NULL;
    2586             :   }
    2587           4 :   ec = getenv ("TALER_AUDITORDB_POSTGRES_CONFIG");
    2588           4 :   if (NULL != ec)
    2589             :   {
    2590           4 :     pg->connection_cfg_str = GNUNET_strdup (ec);
    2591             :   }
    2592             :   else
    2593             :   {
    2594           0 :     if (GNUNET_OK !=
    2595           0 :         GNUNET_CONFIGURATION_get_value_string (cfg,
    2596             :                                                "auditordb-postgres",
    2597             :                                                "db_conn_str",
    2598             :                                                &pg->connection_cfg_str))
    2599             :     {
    2600           0 :       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    2601             :                                  "auditordb-postgres",
    2602             :                                  "db_conn_str");
    2603           0 :       GNUNET_free (pg);
    2604           0 :       return NULL;
    2605             :     }
    2606             :   }
    2607           4 :   plugin = GNUNET_new (struct TALER_AUDITORDB_Plugin);
    2608           4 :   plugin->cls = pg;
    2609           4 :   plugin->get_session = &postgres_get_session;
    2610           4 :   plugin->drop_tables = &postgres_drop_tables;
    2611           4 :   plugin->create_tables = &postgres_create_tables;
    2612           4 :   plugin->start = &postgres_start;
    2613           4 :   plugin->commit = &postgres_commit;
    2614           4 :   plugin->rollback = &postgres_rollback;
    2615           4 :   plugin->gc = &postgres_gc;
    2616             : 
    2617           4 :   plugin->select_denomination_info = &postgres_select_denomination_info;
    2618           4 :   plugin->insert_denomination_info = &postgres_insert_denomination_info;
    2619             : 
    2620           4 :   plugin->get_auditor_progress = &postgres_get_auditor_progress;
    2621           4 :   plugin->update_auditor_progress = &postgres_update_auditor_progress;
    2622           4 :   plugin->insert_auditor_progress = &postgres_insert_auditor_progress;
    2623             : 
    2624           4 :   plugin->get_wire_auditor_progress = &postgres_get_wire_auditor_progress;
    2625           4 :   plugin->update_wire_auditor_progress = &postgres_update_wire_auditor_progress;
    2626           4 :   plugin->insert_wire_auditor_progress = &postgres_insert_wire_auditor_progress;
    2627             : 
    2628           4 :   plugin->del_reserve_info = &postgres_del_reserve_info;
    2629           4 :   plugin->get_reserve_info = &postgres_get_reserve_info;
    2630           4 :   plugin->update_reserve_info = &postgres_update_reserve_info;
    2631           4 :   plugin->insert_reserve_info = &postgres_insert_reserve_info;
    2632             : 
    2633           4 :   plugin->get_reserve_summary = &postgres_get_reserve_summary;
    2634           4 :   plugin->update_reserve_summary = &postgres_update_reserve_summary;
    2635           4 :   plugin->insert_reserve_summary = &postgres_insert_reserve_summary;
    2636             : 
    2637           4 :   plugin->get_wire_fee_summary = &postgres_get_wire_fee_summary;
    2638           4 :   plugin->update_wire_fee_summary = &postgres_update_wire_fee_summary;
    2639           4 :   plugin->insert_wire_fee_summary = &postgres_insert_wire_fee_summary;
    2640             : 
    2641           4 :   plugin->get_denomination_balance = &postgres_get_denomination_balance;
    2642           4 :   plugin->update_denomination_balance = &postgres_update_denomination_balance;
    2643           4 :   plugin->insert_denomination_balance = &postgres_insert_denomination_balance;
    2644             : 
    2645           4 :   plugin->get_balance_summary = &postgres_get_balance_summary;
    2646           4 :   plugin->update_balance_summary = &postgres_update_balance_summary;
    2647           4 :   plugin->insert_balance_summary = &postgres_insert_balance_summary;
    2648             : 
    2649           4 :   plugin->select_historic_denom_revenue = &postgres_select_historic_denom_revenue;
    2650           4 :   plugin->insert_historic_denom_revenue = &postgres_insert_historic_denom_revenue;
    2651             : 
    2652           4 :   plugin->select_historic_losses = &postgres_select_historic_losses;
    2653           4 :   plugin->insert_historic_losses = &postgres_insert_historic_losses;
    2654             : 
    2655           4 :   plugin->select_historic_reserve_revenue = &postgres_select_historic_reserve_revenue;
    2656           4 :   plugin->insert_historic_reserve_revenue = &postgres_insert_historic_reserve_revenue;
    2657             : 
    2658           4 :   plugin->get_predicted_balance = &postgres_get_predicted_balance;
    2659           4 :   plugin->update_predicted_result = &postgres_update_predicted_result;
    2660           4 :   plugin->insert_predicted_result = &postgres_insert_predicted_result;
    2661             : 
    2662           4 :   return plugin;
    2663             : }
    2664             : 
    2665             : 
    2666             : /**
    2667             :  * Shutdown Postgres database subsystem.
    2668             :  *
    2669             :  * @param cls a `struct TALER_AUDITORDB_Plugin`
    2670             :  * @return NULL (always)
    2671             :  */
    2672             : void *
    2673           4 : libtaler_plugin_auditordb_postgres_done (void *cls)
    2674             : {
    2675           4 :   struct TALER_AUDITORDB_Plugin *plugin = cls;
    2676           4 :   struct PostgresClosure *pg = plugin->cls;
    2677             : 
    2678           4 :   GNUNET_free (pg->connection_cfg_str);
    2679           4 :   GNUNET_free (pg);
    2680           4 :   GNUNET_free (plugin);
    2681           4 :   return NULL;
    2682             : }
    2683             : 
    2684             : /* end of plugin_auditordb_postgres.c */

Generated by: LCOV version 1.13