summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd.c')
-rw-r--r--src/backend/taler-merchant-httpd.c196
1 files changed, 146 insertions, 50 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 104d7435..577672b9 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -22,6 +22,7 @@
* @author Florian Dold
*/
#include "platform.h"
+#include <taler/taler_dbevents.h>
#include <taler/taler_bank_service.h>
#include <taler/taler_exchange_service.h>
#include "taler-merchant-httpd_auditors.h"
@@ -101,6 +102,11 @@ int TMH_force_audit;
struct TALER_MERCHANTDB_Plugin *TMH_db;
/**
+ * Event handler for instance settings changes.
+ */
+static struct GNUNET_DB_EventHandler *instance_eh;
+
+/**
* Hashmap pointing at merchant instances by 'id'. An 'id' is
* just a string that identifies a merchant instance. When a frontend
* needs to specify an instance to the backend, it does so by 'id'
@@ -241,22 +247,14 @@ TMH_compute_auth (const char *token,
*
* @param[in,out] mi merchant instance to update and possibly free
*/
-void
-TMH_instance_decref (struct TMH_MerchantInstance *mi)
+static void
+instance_decref (struct TMH_MerchantInstance *mi)
{
struct TMH_WireMethod *wm;
- struct GNUNET_HashCode h_instance;
mi->rc--;
if (0 != mi->rc)
return;
- GNUNET_CRYPTO_hash (mi->settings.id,
- strlen (mi->settings.id),
- &h_instance);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (TMH_by_id_map,
- &h_instance,
- mi));
TMH_force_get_orders_resume (mi);
while (NULL != (wm = (mi->wm_head)))
{
@@ -277,22 +275,27 @@ TMH_instance_decref (struct TMH_MerchantInstance *mi)
/**
- * Callback that frees all the instances in the hashmap
+ * Callback that frees an instances removing
+ * it from the global hashmap.
*
* @param cls closure, NULL
* @param key current key
* @param value a `struct TMH_MerchantInstance`
*/
-static int
-instance_free_cb (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
+int
+TMH_instance_free_cb (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
{
struct TMH_MerchantInstance *mi = value;
(void) cls;
(void) key;
- TMH_instance_decref (mi);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (TMH_by_id_map,
+ &mi->h_instance,
+ mi));
+ instance_decref (mi);
return GNUNET_YES;
}
@@ -732,6 +735,11 @@ do_shutdown (void *cls)
mhd = NULL;
}
TMH_RESERVES_done ();
+ if (NULL != instance_eh)
+ {
+ TMH_db->event_listen_cancel (instance_eh);
+ instance_eh = NULL;
+ }
if (NULL != TMH_db)
{
TALER_MERCHANTDB_plugin_unload (TMH_db);
@@ -755,7 +763,7 @@ do_shutdown (void *cls)
if (NULL != TMH_by_id_map)
{
GNUNET_CONTAINER_multihashmap_iterate (TMH_by_id_map,
- &instance_free_cb,
+ &TMH_instance_free_cb,
NULL);
GNUNET_CONTAINER_multihashmap_destroy (TMH_by_id_map);
TMH_by_id_map = NULL;
@@ -799,7 +807,7 @@ handle_mhd_completion_callback (void *cls,
if (NULL != hc->request_body)
json_decref (hc->request_body);
if (NULL != hc->instance)
- TMH_instance_decref (hc->instance);
+ instance_decref (hc->instance);
memset (&hc->async_scope_id,
0,
sizeof (struct GNUNET_AsyncScopeId));
@@ -914,8 +922,6 @@ struct TMH_MerchantInstance *
TMH_lookup_instance (const char *instance_id)
{
struct GNUNET_HashCode h_instance;
- struct TMH_MerchantInstance *mi;
- struct GNUNET_TIME_Relative age;
if (NULL == instance_id)
instance_id = "default";
@@ -928,16 +934,8 @@ TMH_lookup_instance (const char *instance_id)
instance_id);
/* We're fine if that returns NULL, the calling routine knows how
to handle that */
- mi = GNUNET_CONTAINER_multihashmap_get (TMH_by_id_map,
- &h_instance);
- if (NULL == mi)
- return mi;
- age = GNUNET_TIME_absolute_get_duration (mi->staleness);
- if (age.rel_value_us > INSTANCE_STALENESS.rel_value_us)
- {
- // FIXME: referesh from DB
- }
- return mi;
+ return GNUNET_CONTAINER_multihashmap_get (TMH_by_id_map,
+ &h_instance);
}
@@ -950,7 +948,6 @@ TMH_lookup_instance (const char *instance_id)
int
TMH_add_instance (struct TMH_MerchantInstance *mi)
{
- struct GNUNET_HashCode h_instance;
const char *id;
int ret;
@@ -959,13 +956,13 @@ TMH_add_instance (struct TMH_MerchantInstance *mi)
id = "default";
GNUNET_CRYPTO_hash (id,
strlen (id),
- &h_instance);
+ &mi->h_instance);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Looking for by-id key %s of `%s' in hashmap\n",
- GNUNET_h2s (&h_instance),
+ GNUNET_h2s (&mi->h_instance),
id);
ret = GNUNET_CONTAINER_multihashmap_put (TMH_by_id_map,
- &h_instance,
+ &mi->h_instance,
mi,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
if (GNUNET_OK == ret)
@@ -2043,6 +2040,15 @@ add_instance_cb (void *cls,
struct TMH_MerchantInstance *mi;
(void) cls;
+ mi = TMH_lookup_instance (is->id);
+ if (NULL != mi)
+ {
+ /* (outdated) entry exists, remove old entry */
+ (void) TMH_instance_free_cb (NULL,
+ &mi->h_instance,
+ mi);
+ }
+
mi = GNUNET_new (struct TMH_MerchantInstance);
mi->settings = *is;
mi->auth = *ias;
@@ -2055,7 +2061,6 @@ add_instance_cb (void *cls,
else
mi->deleted = true;
mi->merchant_pub = *merchant_pub;
- mi->staleness = GNUNET_TIME_absolute_get ();
for (unsigned int i = 0; i<accounts_length; i++)
{
const struct TALER_MERCHANTDB_AccountDetails *acc = &accounts[i];
@@ -2078,6 +2083,98 @@ add_instance_cb (void *cls,
/**
+ * Trigger (re)loading of instance settings from DB.
+ *
+ * @param cls NULL
+ * @param extra ID of the instance that changed, NULL
+ * to load all instances (will not handle purges!)
+ * @param extra_len number of bytes in @a extra
+ */
+static void
+load_instances (void *cls,
+ const void *extra,
+ size_t extra_len)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ const char *id = extra;
+
+ (void) cls;
+ (void) extra;
+ (void) extra_len;
+ if ( (NULL != extra) &&
+ ( (0 == extra_len) ||
+ ('\0' != id[extra_len - 1]) ) )
+ {
+ GNUNET_break (0); /* bogus notification */
+ extra = NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received instance settings notification: reload `%s'\n",
+ id);
+ if (NULL == extra)
+ {
+ qs = TMH_db->lookup_instances (TMH_db->cls,
+ false,
+ &add_instance_cb,
+ NULL);
+ }
+ else
+ {
+ struct TMH_MerchantInstance *mi;
+
+ /* This must be done here to handle instance
+ purging, as for purged instances, the DB
+ lookup below will otherwise do nothing */
+ mi = TMH_lookup_instance (id);
+ if (NULL != mi)
+ {
+ (void) TMH_instance_free_cb (NULL,
+ &mi->h_instance,
+ mi);
+ }
+ qs = TMH_db->lookup_instance (TMH_db->cls,
+ id,
+ false,
+ &add_instance_cb,
+ NULL);
+ }
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+}
+
+
+/**
+ * A transaction modified an instance setting
+ * (or created/deleted/purged one). Notify all
+ * backends about the change.
+ *
+ * @param id ID of the instance that changed
+ */
+void
+TMH_reload_instances (const char *id)
+{
+ struct GNUNET_DB_EventHeaderP es = {
+ es.size = ntohs (sizeof (es)),
+ es.type = ntohs (sizeof (TALER_DBEVENT_MERCHANT_INSTANCE_SETTINGS))
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Generating instance settings notification: reload `%s'\n",
+ id);
+ TMH_db->event_notify (TMH_db->cls,
+ &es,
+ id,
+ (NULL == id)
+ ? 0
+ : strlen (id) + 1);
+}
+
+
+/**
* Main function that will be run by the scheduler.
*
* @param cls closure
@@ -2175,8 +2272,8 @@ run (void *cls,
return;
}
if (NULL ==
- (TMH_by_id_map = GNUNET_CONTAINER_multihashmap_create (1,
- GNUNET_NO)))
+ (TMH_by_id_map = GNUNET_CONTAINER_multihashmap_create (4,
+ GNUNET_YES)))
{
GNUNET_SCHEDULER_shutdown ();
return;
@@ -2195,21 +2292,20 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
- /* load instances */
{
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TMH_db->lookup_instances (TMH_db->cls,
- false,
- &add_instance_cb,
- NULL);
- if (0 > qs)
- {
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
+ struct GNUNET_DB_EventHeaderP es = {
+ es.size = ntohs (sizeof (es)),
+ es.type = ntohs (sizeof (TALER_DBEVENT_MERCHANT_INSTANCE_SETTINGS))
+ };
+
+ instance_eh = TMH_db->event_listen (TMH_db->cls,
+ &es,
+ &load_instances,
+ NULL);
}
+ load_instances (NULL,
+ NULL,
+ 0);
/* start watching reserves */
TMH_RESERVES_init ();
fh = TALER_MHD_bind (cfg,