LCOV - code coverage report
Current view: top level - auditordb - plugin_auditordb_postgres.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 303 383 79.1 %
Date: 2017-09-17 17:24:28 Functions: 45 48 93.8 %

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

Generated by: LCOV version 1.13