summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-05-15 17:24:27 +0200
committerChristian Grothoff <christian@grothoff.org>2015-05-15 17:24:27 +0200
commitd080e59e272e307b9ebc267f2c4dd2941cd79436 (patch)
treefceb6637439e4786d643f9235028f960cc9ab0e5
parent33f5242ac4105d8631d659447989cb718459b081 (diff)
downloadexchange-d080e59e272e307b9ebc267f2c4dd2941cd79436.tar.gz
exchange-d080e59e272e307b9ebc267f2c4dd2941cd79436.tar.bz2
exchange-d080e59e272e307b9ebc267f2c4dd2941cd79436.zip
resolve #3717
-rw-r--r--src/include/taler_mintdb_plugin.h4
-rw-r--r--src/mint-tools/taler-mint-reservemod.c40
-rw-r--r--src/mintdb/plugin_mintdb_postgres.c23
3 files changed, 53 insertions, 14 deletions
diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h
index af641b186..1f4707b4d 100644
--- a/src/include/taler_mintdb_plugin.h
+++ b/src/include/taler_mintdb_plugin.h
@@ -685,7 +685,9 @@ struct TALER_MINTDB_Plugin
/**
* Insert a incoming transaction into reserves. New reserves are
- * also created through this function.
+ * also created through this function. Note that this API call
+ * starts (and stops) its own transaction scope (so the application
+ * must not do so).
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param db the database connection handle
diff --git a/src/mint-tools/taler-mint-reservemod.c b/src/mint-tools/taler-mint-reservemod.c
index 8607c6dbf..645a2f32e 100644
--- a/src/mint-tools/taler-mint-reservemod.c
+++ b/src/mint-tools/taler-mint-reservemod.c
@@ -98,6 +98,9 @@ main (int argc, char *const *argv)
{
fprintf (stderr,
"Mint directory not given\n");
+ GNUNET_free_non_null (add_str);
+ GNUNET_free_non_null (details);
+ GNUNET_free_non_null (reserve_pub_str);
return 1;
}
if ((NULL == reserve_pub_str) ||
@@ -109,6 +112,9 @@ main (int argc, char *const *argv)
{
fprintf (stderr,
"Parsing reserve key invalid\n");
+ GNUNET_free_non_null (add_str);
+ GNUNET_free_non_null (details);
+ GNUNET_free_non_null (reserve_pub_str);
return 1;
}
if ( (NULL == add_str) ||
@@ -119,6 +125,9 @@ main (int argc, char *const *argv)
fprintf (stderr,
"Failed to parse currency amount `%s'\n",
add_str);
+ GNUNET_free_non_null (add_str);
+ GNUNET_free_non_null (details);
+ GNUNET_free_non_null (reserve_pub_str);
return 1;
}
@@ -126,7 +135,9 @@ main (int argc, char *const *argv)
{
fprintf (stderr,
"No wiring details given (justification required)\n");
- return 1;
+ GNUNET_free_non_null (add_str);
+ GNUNET_free_non_null (reserve_pub_str);
+ return 1;
}
cfg = TALER_config_load (mint_directory);
@@ -134,7 +145,10 @@ main (int argc, char *const *argv)
{
fprintf (stderr,
"Failed to load mint configuration\n");
- return 1;
+ GNUNET_free_non_null (add_str);
+ GNUNET_free_non_null (details);
+ GNUNET_free_non_null (reserve_pub_str);
+ return 1;
}
ret = 1;
if (NULL ==
@@ -154,24 +168,32 @@ main (int argc, char *const *argv)
goto cleanup;
}
expiration = GNUNET_TIME_relative_to_absolute (RESERVE_EXPIRATION);
- if (GNUNET_OK !=
- plugin->reserves_in_insert (plugin->cls,
- session,
- &reserve_pub,
- &add_value,
- details,
- expiration))
+ ret = plugin->reserves_in_insert (plugin->cls,
+ session,
+ &reserve_pub,
+ &add_value,
+ details,
+ expiration);
+ if (GNUNET_SYSERR == ret)
{
fprintf (stderr,
"Failed to update reserve.\n");
goto cleanup;
}
+ if (GNUNET_NO == ret)
+ {
+ fprintf (stderr,
+ "Record exists, reserve not updated.\n");
+ }
ret = 0;
cleanup:
if (NULL != plugin)
TALER_MINTDB_plugin_unload (plugin);
if (NULL != cfg)
GNUNET_CONFIGURATION_destroy (cfg);
+ GNUNET_free_non_null (add_str);
+ GNUNET_free_non_null (details);
+ GNUNET_free_non_null (reserve_pub_str);
return ret;
}
diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c
index 45599f6e9..baf94ddab 100644
--- a/src/mintdb/plugin_mintdb_postgres.c
+++ b/src/mintdb/plugin_mintdb_postgres.c
@@ -986,7 +986,8 @@ postgres_reserves_update (void *cls,
/**
* Insert a incoming transaction into reserves. New reserves are also created
- * through this function.
+ * through this function. Note that this API call starts (and stops) its
+ * own transaction scope (so the application must not do so).
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session the database connection handle
@@ -1025,9 +1026,8 @@ postgres_reserves_in_insert (void *cls,
&reserve);
if (GNUNET_SYSERR == reserve_exists)
{
- postgres_rollback (cls,
- session);
- return GNUNET_SYSERR;
+ GNUNET_break (0);
+ goto rollback;
}
if (GNUNET_NO == reserve_exists)
{
@@ -1084,6 +1084,21 @@ postgres_reserves_in_insert (void *cls,
params);
if (PGRES_COMMAND_OK != PQresultStatus(result))
{
+ const char *efield;
+
+ efield = PQresultErrorField (result,
+ PG_DIAG_SQLSTATE);
+ if ( (PGRES_FATAL_ERROR == PQresultStatus(result)) &&
+ (NULL != strstr ("23505", /* unique violation */
+ efield)) )
+ {
+ /* This means we had the same reserve/justification/details
+ before */
+ PQclear (result);
+ postgres_rollback (cls,
+ session);
+ return GNUNET_NO;
+ }
QUERY_ERR (result);
goto rollback;
}