aboutsummaryrefslogtreecommitdiff
path: root/src/datacache/plugin_datacache_heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datacache/plugin_datacache_heap.c')
-rw-r--r--src/datacache/plugin_datacache_heap.c117
1 files changed, 111 insertions, 6 deletions
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index 49e60bca1d..c32edf8e2e 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -53,6 +53,11 @@ struct Plugin
*/
struct GNUNET_CONTAINER_Heap *heap;
+ /**
+ * Heap from the plugin for "closest" values.
+ */
+ struct GNUNET_CONTAINER_Heap *cheap;
+
};
@@ -92,6 +97,11 @@ struct Value
unsigned int path_info_len;
/**
+ * Am I the closest peer? Determines which heap we are in!
+ */
+ int am_closest;
+
+ /**
* Type of the block.
*/
enum GNUNET_BLOCK_Type type;
@@ -118,6 +128,11 @@ struct PutContext
const char *data;
/**
+ * Heap from the plugin for "closest" values.
+ */
+ struct GNUNET_CONTAINER_Heap *cheap;
+
+ /**
* Heap from the plugin.
*/
struct GNUNET_CONTAINER_Heap *heap;
@@ -168,7 +183,9 @@ put_cb (void *cls,
if ( (val->size == put_ctx->size) &&
(val->type == put_ctx->type) &&
- (0 == memcmp (&val[1], put_ctx->data, put_ctx->size)) )
+ (0 == memcmp (&val[1],
+ put_ctx->data,
+ put_ctx->size)) )
{
put_ctx->found = GNUNET_YES;
val->discard_time = GNUNET_TIME_absolute_max (val->discard_time,
@@ -199,6 +216,7 @@ put_cb (void *cls,
*
* @param cls closure (our `struct Plugin`)
* @param key key to store data under
+ * @param am_closest are we the closest peer?
* @param size number of bytes in @a data
* @param data data to store
* @param type type of the value
@@ -210,6 +228,7 @@ put_cb (void *cls,
static ssize_t
heap_plugin_put (void *cls,
const struct GNUNET_HashCode *key,
+ int am_closest,
size_t size,
const char *data,
enum GNUNET_BLOCK_Type type,
@@ -223,6 +242,7 @@ heap_plugin_put (void *cls,
put_ctx.found = GNUNET_NO;
put_ctx.heap = plugin->heap;
+ put_ctx.cheap = plugin->cheap;
put_ctx.data = data;
put_ctx.size = size;
put_ctx.path_info = path_info;
@@ -241,17 +261,20 @@ heap_plugin_put (void *cls,
val->type = type;
val->discard_time = discard_time;
val->size = size;
+ val->am_closest = am_closest;
GNUNET_array_grow (val->path_info,
val->path_info_len,
path_info_len);
GNUNET_memcpy (val->path_info,
- path_info,
- path_info_len * sizeof (struct GNUNET_PeerIdentity));
+ path_info,
+ path_info_len * sizeof (struct GNUNET_PeerIdentity));
(void) GNUNET_CONTAINER_multihashmap_put (plugin->map,
&val->key,
val,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- val->hn = GNUNET_CONTAINER_heap_insert (plugin->heap,
+ val->hn = GNUNET_CONTAINER_heap_insert (am_closest
+ ? plugin->cheap
+ : plugin->heap,
val,
val->discard_time.abs_value_us);
return size + OVERHEAD;
@@ -371,6 +394,8 @@ heap_plugin_del (void *cls)
val = GNUNET_CONTAINER_heap_remove_root (plugin->heap);
if (NULL == val)
+ val = GNUNET_CONTAINER_heap_remove_root (plugin->cheap);
+ if (NULL == val)
return GNUNET_SYSERR;
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (plugin->map,
@@ -413,6 +438,53 @@ heap_plugin_get_random (void *cls,
/**
+ * Closure for #find_closest().
+ */
+struct GetClosestContext
+{
+ struct Value **values;
+
+ unsigned int num_results;
+
+ const struct GNUNET_HashCode *key;
+};
+
+
+static int
+find_closest (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GetClosestContext *gcc = cls;
+ struct Value *val = value;
+ unsigned int j;
+
+ if (1 != GNUNET_CRYPTO_hash_cmp (key,
+ gcc->key))
+ return GNUNET_OK; /* useless */
+ j = gcc->num_results;
+ for (unsigned int i=0;i<gcc->num_results;i++)
+ {
+ if (NULL == gcc->values[i])
+ {
+ j = i;
+ break;
+ }
+ if (1 == GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key,
+ key))
+ {
+ j = i;
+ break;
+ }
+ }
+ if (j == gcc->num_results)
+ return GNUNET_OK;
+ gcc->values[j] = val;
+ return GNUNET_OK;
+}
+
+
+/**
* Iterate over the results that are "close" to a particular key in
* the datacache. "close" is defined as numerically larger than @a
* key (when interpreted as a circular address space), with small
@@ -432,8 +504,30 @@ heap_plugin_get_closest (void *cls,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
- GNUNET_break (0); // not implemented!
- return 0;
+ struct Plugin *plugin = cls;
+ struct Value *values[num_results];
+ struct GetClosestContext gcc = {
+ .values = values,
+ .num_results = num_results,
+ .key = key
+ };
+ GNUNET_CONTAINER_multihashmap_iterate (plugin->map,
+ &find_closest,
+ &gcc);
+ for (unsigned int i=0;i<num_results;i++)
+ {
+ if (NULL == values[i])
+ return i;
+ iter (iter_cls,
+ &values[i]->key,
+ values[i]->size,
+ (void *) &values[i][1],
+ values[i]->type,
+ values[i]->discard_time,
+ values[i]->path_info_len,
+ values[i]->path_info);
+ }
+ return num_results;
}
@@ -454,6 +548,7 @@ libgnunet_plugin_datacache_heap_init (void *cls)
plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */
GNUNET_YES);
plugin->heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
+ plugin->cheap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
plugin->env = env;
api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions);
api->cls = plugin;
@@ -490,7 +585,17 @@ libgnunet_plugin_datacache_heap_done (void *cls)
GNUNET_free_non_null (val->path_info);
GNUNET_free (val);
}
+ while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->cheap)))
+ {
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (plugin->map,
+ &val->key,
+ val));
+ GNUNET_free_non_null (val->path_info);
+ GNUNET_free (val);
+ }
GNUNET_CONTAINER_heap_destroy (plugin->heap);
+ GNUNET_CONTAINER_heap_destroy (plugin->cheap);
GNUNET_CONTAINER_multihashmap_destroy (plugin->map);
GNUNET_free (plugin);
GNUNET_free (api);