From fe6d7a5ae1b883f818538e1c0392624de5e88275 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 12 Jun 2015 10:46:42 +0200 Subject: ensure DKI information is in database before we start to use it (#3808) --- src/include/taler_mintdb_plugin.h | 2 +- src/mint/taler-mint-httpd.c | 23 ++++++++----- src/mint/taler-mint-httpd_keystate.c | 64 ++++++++++++++++++++++++++++++++++-- src/mintdb/plugin_mintdb_postgres.c | 9 +++-- 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 25d747a2d..7cbc3505d 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -690,7 +690,7 @@ struct TALER_MINTDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion connection to use * @param denom_pub the public key used for signing coins of this denomination - * @param[out] issue set to issue information with value, fees and other info about the coin + * @param[out] issue set to issue information with value, fees and other info about the coin, can be NULL * @return #GNUNET_OK on success; #GNUNET_NO if no record was found, #GNUNET_SYSERR on failure */ int diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index b9146c5d8..0d221444f 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -251,7 +251,7 @@ handle_mhd_request (void *cls, "Only POST is allowed", 0, &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, #endif - + { NULL, NULL, NULL, NULL, 0, 0 } }; static struct TMH_RequestHandler h404 = @@ -314,8 +314,9 @@ mint_serve_process_config (const char *mint_directory) "currency", &TMH_mint_currency_string)) { - fprintf (stderr, - "No currency given in mint configuration."); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "currency"); return GNUNET_SYSERR; } if (strlen (TMH_mint_currency_string) >= TALER_CURRENCY_LEN) @@ -332,8 +333,9 @@ mint_serve_process_config (const char *mint_directory) "wireformat", &TMH_expected_wire_format)) { - fprintf (stderr, - "No wireformat given in mint configuration."); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "wireformat"); return GNUNET_SYSERR; } if (GNUNET_OK != @@ -342,8 +344,9 @@ mint_serve_process_config (const char *mint_directory) "master_public_key", &TMH_master_public_key_str)) { - fprintf (stderr, - "No master public key given in mint configuration."); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "master_public_key"); return GNUNET_SYSERR; } if (GNUNET_OK != @@ -372,8 +375,10 @@ mint_serve_process_config (const char *mint_directory) "port", &port)) { - fprintf (stderr, - "Missing or invalid configuration for the port of the mint\n"); + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "mint", + "port", + "port number required"); return GNUNET_SYSERR; } diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 07b83ac85..1d40b3103 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -23,6 +23,7 @@ #include "platform.h" #include #include "taler-mint-httpd_keystate.h" +#include "taler_mintdb_plugin.h" /** @@ -176,8 +177,10 @@ TALER_MINT_conf_duration_provide () "lookahead_provide", &rel)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "mint_keys.lookahead_provide not valid or not given\n"); + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "lookahead_provide", + "time value required"); GNUNET_assert (0); } return rel; @@ -204,6 +207,7 @@ reload_keys_denom_iter (void *cls, struct GNUNET_TIME_Absolute horizon; struct GNUNET_HashCode denom_key_hash; struct TALER_MINTDB_DenominationKeyIssueInformation *d2; + struct TALER_MINTDB_Session *session; int res; horizon = GNUNET_TIME_relative_to_absolute (TALER_MINT_conf_duration_provide ()); @@ -230,6 +234,62 @@ reload_keys_denom_iter (void *cls, GNUNET_CRYPTO_hash_context_read (ctx->hash_context, &denom_key_hash, sizeof (struct GNUNET_HashCode)); + session = TMH_plugin->get_session (TMH_plugin->cls, + GNUNET_NO); + /* Try to insert DKI into DB until we succeed; note that if the DB + failure is persistent, this code may loop forever (as there is no + sane alternative, we cannot continue without the DKI being in the + DB). */ + res = GNUNET_SYSERR; + while (GNUNET_OK != res) + { + res = TMH_plugin->start (TMH_plugin->cls, + session); + if (GNUNET_OK != res) + { + /* Transaction start failed!? Very bad error, log and retry */ + GNUNET_break (0); + continue; + } + res = TMH_plugin->get_denomination_info (TMH_plugin->cls, + session, + &dki->denom_pub, + NULL); + if (GNUNET_SYSERR == res) + { + /* Fetch failed!? Very bad error, log and retry */ + GNUNET_break (0); + TMH_plugin->rollback (TMH_plugin->cls, + session); + continue; + } + if (GNUNET_OK == res) + { + /* Record exists, we're good, just exit */ + TMH_plugin->rollback (TMH_plugin->cls, + session); + break; + } + res = TMH_plugin->insert_denomination_info (TMH_plugin->cls, + session, + &dki->denom_pub, + &dki->issue); + if (GNUNET_OK != res) + { + /* Insert failed!? Very bad error, log and retry */ + GNUNET_break (0); + TMH_plugin->rollback (TMH_plugin->cls, + session); + continue; + } + res = TMH_plugin->commit (TMH_plugin->cls, + session); + /* If commit succeeded, we're done, otherwise we retry; this + time without logging, as theroetically commits can fail + in a transactional DB due to concurrent activities that + cannot be reconciled. This should be rare for DKIs, but + as it is possible we just retry until we succeed. */ + } d2 = GNUNET_memdup (dki, sizeof (struct TALER_MINTDB_DenominationKeyIssueInformation)); diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index 144732087..b1dffc68c 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -1105,7 +1105,7 @@ postgres_insert_denomination_info (void *cls, * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion connection to use * @param denom_pub the public key used for signing coins of this denomination - * @param[out] issue set to issue information with value, fees and other info about the coin + * @param[out] issue set to issue information with value, fees and other info about the coin, can be NULL * @return #GNUNET_OK on success; #GNUNET_NO if no record was found, #GNUNET_SYSERR on failure */ static int @@ -1121,7 +1121,7 @@ postgres_get_denomination_info (void *cls, }; result = TALER_PQ_exec_prepared (session->conn, - "reserve_get", + "denomination_get", params); if (PGRES_TUPLES_OK != PQresultStatus (result)) { @@ -1140,6 +1140,11 @@ postgres_get_denomination_info (void *cls, PQclear (result); return GNUNET_SYSERR; } + if (NULL == issue) + { + PQclear (result); + return GNUNET_OK; + } { struct TALER_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_auto_from_type ("master_pub", -- cgit v1.2.3