summaryrefslogtreecommitdiff
path: root/src/mint/taler-mint-aggregator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mint/taler-mint-aggregator.c')
-rw-r--r--src/mint/taler-mint-aggregator.c914
1 files changed, 0 insertions, 914 deletions
diff --git a/src/mint/taler-mint-aggregator.c b/src/mint/taler-mint-aggregator.c
deleted file mode 100644
index 5e05c8673..000000000
--- a/src/mint/taler-mint-aggregator.c
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2016 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file taler-mint-aggregator.c
- * @brief Process that aggregates outgoing transactions and executes them
- * @author Christian Grothoff
- *
- * TODO:
- * - simplify global_ret: make it a global!
- * - handle shutdown more nicely (call 'cancel' method on wire transfers)
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include <pthread.h>
-#include "taler_mintdb_lib.h"
-#include "taler_mintdb_plugin.h"
-#include "taler_wire_lib.h"
-
-/**
- * Which currency is used by this mint?
- */
-static char *mint_currency_string;
-
-/**
- * Which wireformat should be supported by this aggregator?
- */
-static char *mint_wireformat;
-
-/**
- * Base directory of the mint (global)
- */
-static char *mint_directory;
-
-/**
- * The mint's configuration (global)
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Our DB plugin.
- */
-static struct TALER_MINTDB_Plugin *db_plugin;
-
-/**
- * Our wire plugin.
- */
-static struct TALER_WIRE_Plugin *wire_plugin;
-
-/**
- * Task for the main #run() function.
- */
-static struct GNUNET_SCHEDULER_Task *task;
-
-/**
- * Limit on the number of transactions we aggregate at once. Note
- * that the limit must be big enough to ensure that when transactions
- * of the smallest possible unit are aggregated, they do surpass the
- * "tiny" threshold beyond which we never trigger a wire transaction!
- *
- * TODO: make configurable (via config file or command line option)
- */
-static unsigned int aggregation_limit = 10000;
-
-
-/**
- * Load configuration parameters for the mint
- * server into the corresponding global variables.
- *
- * @param mint_directory the mint's directory
- * @return #GNUNET_OK on success
- */
-static int
-mint_serve_process_config (const char *mint_directory)
-{
- char *type;
-
- cfg = TALER_config_load (mint_directory);
- if (NULL == cfg)
- {
- fprintf (stderr,
- "Failed to load mint configuration\n");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "mint",
- "currency",
- &mint_currency_string))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "mint",
- "currency");
- return GNUNET_SYSERR;
- }
- if (strlen (mint_currency_string) >= TALER_CURRENCY_LEN)
- {
- fprintf (stderr,
- "Currency `%s' longer than the allowed limit of %u characters.",
- mint_currency_string,
- (unsigned int) TALER_CURRENCY_LEN);
- return GNUNET_SYSERR;
- }
- if (NULL != mint_wireformat)
- GNUNET_CONFIGURATION_set_value_string (cfg,
- "mint",
- "wireformat",
- mint_wireformat);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "mint",
- "wireformat",
- &type))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "mint",
- "wireformat");
- return GNUNET_SYSERR;
- }
-
- if (NULL ==
- (db_plugin = TALER_MINTDB_plugin_load (cfg)))
- {
- fprintf (stderr,
- "Failed to initialize DB subsystem\n");
- GNUNET_free (type);
- return GNUNET_SYSERR;
- }
-
- if (NULL ==
- (wire_plugin = TALER_WIRE_plugin_load (cfg,
- type)))
- {
- fprintf (stderr,
- "Failed to load wire plugin for `%s'\n",
- type);
- GNUNET_free (type);
- return GNUNET_SYSERR;
- }
- GNUNET_free (type);
-
- return GNUNET_OK;
-}
-
-
-/**
- * Information about one aggregation process to
- * be executed.
- */
-struct AggregationUnit
-{
- /**
- * Public key of the merchant.
- */
- struct TALER_MerchantPublicKeyP merchant_pub;
-
- /**
- * Total amount to be transferred.
- */
- struct TALER_Amount total_amount;
-
- /**
- * Hash of @e wire.
- */
- struct GNUNET_HashCode h_wire;
-
- /**
- * Wire transfer identifier we use.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Row ID of the transaction that started it all.
- */
- unsigned long long row_id;
-
- /**
- * The current time.
- */
- struct GNUNET_TIME_Absolute execution_time;
-
- /**
- * Wire details of the merchant.
- */
- json_t *wire;
-
- /**
- * Database session for all of our transactions.
- */
- struct TALER_MINTDB_Session *session;
-
- /**
- * Wire preparation handle.
- */
- struct TALER_WIRE_PrepareHandle *ph;
-
- /**
- * Array of #aggregation_limit row_ids from the
- * aggregation.
- */
- unsigned long long *additional_rows;
-
- /**
- * Pointer to global return value. Closure for #run().
- */
- int *global_ret;
-
- /**
- * Offset specifying how many #additional_rows are in use.
- */
- unsigned int rows_offset;
-
- /**
- * Set to #GNUNET_YES if we have to abort due to failure.
- */
- int failed;
-
-};
-
-
-/**
- * Function called with details about deposits that have been made,
- * with the goal of executing the corresponding wire transaction.
- *
- * @param cls closure with the `struct AggregationUnit`
- * @param row_id identifies database entry
- * @param merchant_pub public key of the merchant
- * @param coin_pub public key of the coin
- * @param amount_with_fee amount that was deposited including fee
- * @param deposit_fee amount the mint gets to keep as transaction fees
- * @param transaction_id unique transaction ID chosen by the merchant
- * @param h_contract hash of the contract between merchant and customer
- * @param wire_deadline by which the merchant adviced that he would like the
- * wire transfer to be executed
- * @param wire wire details for the merchant
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
- */
-static int
-deposit_cb (void *cls,
- unsigned long long row_id,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *amount_with_fee,
- const struct TALER_Amount *deposit_fee,
- uint64_t transaction_id,
- const struct GNUNET_HashCode *h_contract,
- struct GNUNET_TIME_Absolute wire_deadline,
- const json_t *wire)
-{
- struct AggregationUnit *au = cls;
-
- au->merchant_pub = *merchant_pub;
- if (GNUNET_OK !=
- TALER_amount_subtract (&au->total_amount,
- amount_with_fee,
- deposit_fee))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Fatally malformed record at %llu\n",
- row_id);
- return GNUNET_SYSERR;
- }
- au->row_id = row_id;
- au->wire = (json_t *) wire;
- au->execution_time = GNUNET_TIME_absolute_get ();
- TALER_hash_json (au->wire,
- &au->h_wire);
- json_incref (au->wire);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &au->wtid,
- sizeof (au->wtid));
- if (GNUNET_OK !=
- db_plugin->insert_aggregation_tracking (db_plugin->cls,
- au->session,
- &au->wtid,
- merchant_pub,
- &au->h_wire,
- h_contract,
- transaction_id,
- au->execution_time,
- coin_pub,
- amount_with_fee,
- deposit_fee))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- db_plugin->mark_deposit_done (db_plugin->cls,
- au->session,
- row_id))
- {
- GNUNET_break (0);
- au->failed = GNUNET_YES;
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-
-/**
- * Function called with details about another deposit we
- * can aggregate into an existing aggregation unit.
- *
- * @param cls closure with the `struct AggregationUnit`
- * @param row_id identifies database entry
- * @param merchant_pub public key of the merchant
- * @param coin_pub public key of the coin
- * @param amount_with_fee amount that was deposited including fee
- * @param deposit_fee amount the mint gets to keep as transaction fees
- * @param transaction_id unique transaction ID chosen by the merchant
- * @param h_contract hash of the contract between merchant and customer
- * @param wire_deadline by which the merchant adviced that he would like the
- * wire transfer to be executed
- * @param wire wire details for the merchant
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
- */
-static int
-aggregate_cb (void *cls,
- unsigned long long row_id,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *amount_with_fee,
- const struct TALER_Amount *deposit_fee,
- uint64_t transaction_id,
- const struct GNUNET_HashCode *h_contract,
- struct GNUNET_TIME_Absolute wire_deadline,
- const json_t *wire)
-{
- struct AggregationUnit *au = cls;
- struct TALER_Amount delta;
-
- GNUNET_break (0 ==
- memcmp (&au->merchant_pub,
- merchant_pub,
- sizeof (struct TALER_MerchantPublicKeyP)));
- /* compute contribution of this coin after fees */
- if (GNUNET_OK !=
- TALER_amount_subtract (&delta,
- amount_with_fee,
- deposit_fee))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Fatally malformed record at %llu\n",
- row_id);
- return GNUNET_SYSERR;
- }
- /* add to total */
- if (GNUNET_OK !=
- TALER_amount_add (&au->total_amount,
- &au->total_amount,
- &delta))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Overflow or currency incompatibility during aggregation at %llu\n",
- row_id);
- /* Skip this one, but keep going! */
- return GNUNET_OK;
- }
- if (au->rows_offset >= aggregation_limit)
- {
- /* Bug: we asked for at most #aggregation_limit results! */
- GNUNET_break (0);
- /* Skip this one, but keep going. */
- return GNUNET_OK;
- }
- if (NULL == au->additional_rows)
- au->additional_rows = GNUNET_new_array (aggregation_limit,
- unsigned long long);
- /* "append" to our list of rows */
- au->additional_rows[au->rows_offset++] = row_id;
- /* insert into aggregation tracking table */
- if (GNUNET_OK !=
- db_plugin->insert_aggregation_tracking (db_plugin->cls,
- au->session,
- &au->wtid,
- merchant_pub,
- &au->h_wire,
- h_contract,
- transaction_id,
- au->execution_time,
- coin_pub,
- amount_with_fee,
- deposit_fee))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- db_plugin->mark_deposit_done (db_plugin->cls,
- au->session,
- row_id))
- {
- GNUNET_break (0);
- au->failed = GNUNET_YES;
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function to be called with the prepared transfer data.
- *
- * @param cls closure with the `struct AggregationUnit`
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size);
-
-
-/**
- * Main work function that queries the DB and aggregates transactions
- * into larger wire transfers.
- *
- * @param cls pointer to an `int` which we will return from main()
- * @param tc scheduler context
- */
-static void
-run_aggregation (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- int *global_ret = cls;
- struct TALER_MINTDB_Session *session;
- struct AggregationUnit *au;
- unsigned int i;
- int ret;
-
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- if (NULL == (session = db_plugin->get_session (db_plugin->cls,
- GNUNET_NO)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to obtain database session!\n");
- *global_ret = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_OK !=
- db_plugin->start (db_plugin->cls,
- session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to start database transaction!\n");
- *global_ret = GNUNET_SYSERR;
- return;
- }
- au = GNUNET_new (struct AggregationUnit);
- au->session = session;
- ret = db_plugin->get_ready_deposit (db_plugin->cls,
- session,
- &deposit_cb,
- au);
- if (GNUNET_OK != ret)
- {
- GNUNET_free (au);
- db_plugin->rollback (db_plugin->cls,
- session);
- if (0 != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to execute deposit iteration!\n");
- *global_ret = GNUNET_SYSERR;
- return;
- }
- /* nothing to do, sleep for a minute and try again */
- task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
- &run_aggregation,
- global_ret);
- return;
- }
- /* Now try to find other deposits to aggregate */
- ret = db_plugin->iterate_matching_deposits (db_plugin->cls,
- session,
- &au->h_wire,
- &au->merchant_pub,
- &aggregate_cb,
- au,
- aggregation_limit);
- if ( (GNUNET_SYSERR == ret) ||
- (GNUNET_YES == au->failed) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to execute deposit iteration!\n");
- GNUNET_free_non_null (au->additional_rows);
- GNUNET_free (au);
- db_plugin->rollback (db_plugin->cls,
- session);
- *global_ret = GNUNET_SYSERR;
- return;
- }
- /* Round to the unit supported by the wire transfer method */
- GNUNET_assert (GNUNET_SYSERR !=
- wire_plugin->amount_round (wire_plugin->cls,
- &au->total_amount));
- /* Check if after rounding down, we still have an amount to transfer */
- if ( (0 == au->total_amount.value) &&
- (0 == au->total_amount.fraction) )
- {
- /* Rollback ongoing transaction, as we will not use the respective
- WTID and thus need to remove the tracking data */
- db_plugin->rollback (db_plugin->cls,
- session);
- /* Start another transaction to mark all* of the selected deposits
- *as minor! */
- if (GNUNET_OK !=
- db_plugin->start (db_plugin->cls,
- session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to start database transaction!\n");
- *global_ret = GNUNET_SYSERR;
- GNUNET_free_non_null (au->additional_rows);
- GNUNET_free (au);
- return;
- }
- /* Mark transactions by row_id as minor */
- ret = GNUNET_OK;
- if (GNUNET_OK !=
- db_plugin->mark_deposit_tiny (db_plugin->cls,
- session,
- au->row_id))
- ret = GNUNET_SYSERR;
- else
- for (i=0;i<au->rows_offset;i++)
- if (GNUNET_OK !=
- db_plugin->mark_deposit_tiny (db_plugin->cls,
- session,
- au->additional_rows[i]))
- ret = GNUNET_SYSERR;
- /* commit */
- if (GNUNET_OK !=
- db_plugin->commit (db_plugin->cls,
- session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to commit database transaction!\n");
- }
- GNUNET_free_non_null (au->additional_rows);
- GNUNET_free (au);
- /* start again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- return;
- }
- au->global_ret = global_ret;
- au->ph = wire_plugin->prepare_wire_transfer (wire_plugin->cls,
- au->wire,
- &au->total_amount,
- &au->wtid,
- &prepare_cb,
- au);
- /* FIXME: currently we have no clean-up plan on
- shutdown to call prepare_wire_transfer_cancel!
- Maybe make 'au' global? */
- if (NULL == au->ph)
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- session);
- GNUNET_free_non_null (au->additional_rows);
- GNUNET_free (au);
- /* start again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- return;
- }
- /* otherwise we continue with #prepare_cb(), see below */
-}
-
-
-/**
- * Execute the wire transfers that we have committed to
- * do.
- *
- * @param cls pointer to an `int` which we will return from main()
- * @param tc scheduler context
- */
-static void
-run_transfers (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Function to be called with the prepared transfer data.
- *
- * @param cls closure with the `struct AggregationUnit`
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
- const char *buf,
- size_t buf_size)
-{
- struct AggregationUnit *au = cls;
- int *global_ret = au->global_ret;
- struct TALER_MINTDB_Session *session = au->session;
-
- GNUNET_free_non_null (au->additional_rows);
- GNUNET_free (au);
- if (NULL == buf)
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- session);
- /* start again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- return;
- }
-
- /* Commit our intention to execute the wire transfer! */
- if (GNUNET_OK !=
- db_plugin->wire_prepare_data_insert (db_plugin->cls,
- session,
- mint_wireformat,
- buf,
- buf_size))
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- session);
- /* start again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- return;
- }
-
- /* Now we can finally commit the overall transaction, as we are
- again consistent if all of this passes. */
- if (GNUNET_OK !=
- db_plugin->commit (db_plugin->cls,
- session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to commit database transaction!\n");
- /* try again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- return;
- }
-
- /* run alternative task: actually do wire transfer! */
- task = GNUNET_SCHEDULER_add_now (&run_transfers,
- &global_ret);
-}
-
-
-/**
- * Data we keep to #run_transfers().
- */
-struct WirePrepareData
-{
-
- /**
- * Database session for all of our transactions.
- */
- struct TALER_MINTDB_Session *session;
-
- /**
- * Wire execution handle.
- */
- struct TALER_WIRE_ExecuteHandle *eh;
-
- /**
- * Pointer to global return value. Closure for #run().
- */
- int *global_ret;
-
-
- /**
- * Row ID of the transfer.
- */
- unsigned long long row_id;
-
-};
-
-
-/**
- * Function called with the result from the execute step.
- *
- * @param cls closure with the `struct WirePrepareData`
- * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-wire_confirm_cb (void *cls,
- int success,
- const char *emsg)
-{
- struct WirePrepareData *wpd = cls;
- int *global_ret = wpd->global_ret;
- struct TALER_MINTDB_Session *session = wpd->session;
-
- wpd->eh = NULL;
- if (GNUNET_SYSERR == success)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire transaction failed: %s\n",
- emsg);
- db_plugin->rollback (db_plugin->cls,
- session);
- *global_ret = GNUNET_SYSERR;
- GNUNET_free (wpd);
- return;
- }
- if (GNUNET_OK !=
- db_plugin->wire_prepare_data_mark_finished (db_plugin->cls,
- session,
- wpd->row_id))
- {
- GNUNET_break (0); /* why!? */
- db_plugin->rollback (db_plugin->cls,
- session);
- *global_ret = GNUNET_SYSERR;
- GNUNET_free (wpd);
- return;
- }
- GNUNET_free (wpd);
- if (GNUNET_OK !=
- db_plugin->commit (db_plugin->cls,
- session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to commit database transaction!\n");
- /* try again */
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- return;
- }
- /* continue with #run_transfers(), just to guard
- against the unlikely case that there are more. */
- task = GNUNET_SCHEDULER_add_now (&run_transfers,
- &global_ret);
-
-}
-
-
-/**
- * Callback with data about a prepared transaction.
- *
- * @param cls closure with the `struct WirePrepareData`
- * @param rowid row identifier used to mark prepared transaction as done
- * @param buf transaction data that was persisted, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-wire_prepare_cb (void *cls,
- unsigned long long rowid,
- const char *buf,
- size_t buf_size)
-{
- struct WirePrepareData *wpd = cls;
- int *global_ret = wpd->global_ret;
-
- wpd->row_id = rowid;
- wpd->eh = wire_plugin->execute_wire_transfer (wire_plugin->cls,
- buf,
- buf_size,
- &wire_confirm_cb,
- wpd);
- /* FIXME: currently we have no clean-up plan on
- shutdown to call execute_wire_transfer_cancel!
- Maybe make 'wpd' global? */
- if (NULL == wpd->eh)
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- wpd->session);
- *global_ret = GNUNET_SYSERR;
- GNUNET_free (wpd);
- return;
- }
-}
-
-
-/**
- * Execute the wire transfers that we have committed to
- * do.
- *
- * @param cls pointer to an `int` which we will return from main()
- * @param tc scheduler context
- */
-static void
-run_transfers (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- int *global_ret = cls;
- int ret;
- struct WirePrepareData *wpd;
- struct TALER_MINTDB_Session *session;
-
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
- if (NULL == (session = db_plugin->get_session (db_plugin->cls,
- GNUNET_NO)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to obtain database session!\n");
- *global_ret = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_OK !=
- db_plugin->start (db_plugin->cls,
- session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to start database transaction!\n");
- *global_ret = GNUNET_SYSERR;
- return;
- }
- wpd = GNUNET_new (struct WirePrepareData);
- wpd->session = session;
- wpd->global_ret = global_ret;
- ret = db_plugin->wire_prepare_data_get (db_plugin->cls,
- session,
- mint_wireformat,
- &wire_prepare_cb,
- wpd);
- if (GNUNET_SYSERR == ret)
- {
- GNUNET_break (0); /* why? how to best recover? */
- db_plugin->rollback (db_plugin->cls,
- session);
- *global_ret = GNUNET_SYSERR;
- GNUNET_free (wpd);
- return;
- }
- if (GNUNET_NO == ret)
- {
- /* no more prepared wire transfers, go back to aggregation! */
- db_plugin->rollback (db_plugin->cls,
- session);
- task = GNUNET_SCHEDULER_add_now (&run_aggregation,
- global_ret);
- GNUNET_free (wpd);
- return;
- }
- /* otherwise, continues in #wire_prepare_cb() */
-}
-
-
-/**
- * The main function of the taler-mint-httpd server ("the mint").
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc,
- char *const *argv)
-{
- static const struct GNUNET_GETOPT_CommandLineOption options[] = {
- {'d', "mint-dir", "DIR",
- "mint directory with configuration and keys for operating the mint", 1,
- &GNUNET_GETOPT_set_filename, &mint_directory},
- {'f', "format", "WIREFORMAT",
- "wireformat to use, overrides WIREFORMAT option in [mint] section", 1,
- &GNUNET_GETOPT_set_filename, &mint_wireformat},
- TALER_GETOPT_OPTION_HELP ("background process that aggregates and executes wire transfers to merchants"),
- GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION),
- GNUNET_GETOPT_OPTION_END
- };
- int ret = GNUNET_OK;
-
- GNUNET_assert (GNUNET_OK ==
- GNUNET_log_setup ("taler-mint-aggregator",
- "INFO",
- NULL));
- if (0 >=
- GNUNET_GETOPT_run ("taler-mint-aggregator",
- options,
- argc, argv))
- return 1;
- if (NULL == mint_directory)
- {
- fprintf (stderr,
- "Mint directory not specified\n");
- return 1;
- }
- if (GNUNET_OK !=
- mint_serve_process_config (mint_directory))
- {
- return 1;
- }
-
- GNUNET_SCHEDULER_run (&run_transfers, &ret);
-
- TALER_MINTDB_plugin_unload (db_plugin);
- TALER_WIRE_plugin_unload (wire_plugin);
- return (GNUNET_SYSERR == ret) ? 1 : 0;
-}
-
-/* end of taler-mint-aggregator.c */