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.c164
1 files changed, 126 insertions, 38 deletions
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index 49e60bca1..494d1ae17 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -2,20 +2,18 @@
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2012, 2015 GNUnet e.V. 3 Copyright (C) 2012, 2015 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software: you can redistribute it and/or modify it
6 it under the terms of the GNU General Public License as published 6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation; either version 3, or (at your 7 by the Free Software Foundation, either version 3 of the License,
8 option) any later version. 8 or (at your option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with GNUnet; see the file COPYING. If not, write to the 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/ 17*/
20 18
21/** 19/**
@@ -31,7 +29,7 @@
31 29
32#define LOG_STRERROR_FILE(kind,op,fn) GNUNET_log_from_strerror_file (kind, "datacache-heap", op, fn) 30#define LOG_STRERROR_FILE(kind,op,fn) GNUNET_log_from_strerror_file (kind, "datacache-heap", op, fn)
33 31
34 32#define NUM_HEAPS 24
35 33
36/** 34/**
37 * Context for all functions in this plugin. 35 * Context for all functions in this plugin.
@@ -49,9 +47,9 @@ struct Plugin
49 struct GNUNET_CONTAINER_MultiHashMap *map; 47 struct GNUNET_CONTAINER_MultiHashMap *map;
50 48
51 /** 49 /**
52 * Heap for expirations. 50 * Heaps sorted by distance.
53 */ 51 */
54 struct GNUNET_CONTAINER_Heap *heap; 52 struct GNUNET_CONTAINER_Heap *heaps[NUM_HEAPS];
55 53
56}; 54};
57 55
@@ -92,6 +90,11 @@ struct Value
92 unsigned int path_info_len; 90 unsigned int path_info_len;
93 91
94 /** 92 /**
93 * How close is the hash to us? Determines which heap we are in!
94 */
95 uint32_t distance;
96
97 /**
95 * Type of the block. 98 * Type of the block.
96 */ 99 */
97 enum GNUNET_BLOCK_Type type; 100 enum GNUNET_BLOCK_Type type;
@@ -118,11 +121,6 @@ struct PutContext
118 const char *data; 121 const char *data;
119 122
120 /** 123 /**
121 * Heap from the plugin.
122 */
123 struct GNUNET_CONTAINER_Heap *heap;
124
125 /**
126 * Path information. 124 * Path information.
127 */ 125 */
128 const struct GNUNET_PeerIdentity *path_info; 126 const struct GNUNET_PeerIdentity *path_info;
@@ -168,7 +166,9 @@ put_cb (void *cls,
168 166
169 if ( (val->size == put_ctx->size) && 167 if ( (val->size == put_ctx->size) &&
170 (val->type == put_ctx->type) && 168 (val->type == put_ctx->type) &&
171 (0 == memcmp (&val[1], put_ctx->data, put_ctx->size)) ) 169 (0 == memcmp (&val[1],
170 put_ctx->data,
171 put_ctx->size)) )
172 { 172 {
173 put_ctx->found = GNUNET_YES; 173 put_ctx->found = GNUNET_YES;
174 val->discard_time = GNUNET_TIME_absolute_max (val->discard_time, 174 val->discard_time = GNUNET_TIME_absolute_max (val->discard_time,
@@ -178,8 +178,8 @@ put_cb (void *cls,
178 val->path_info_len, 178 val->path_info_len,
179 put_ctx->path_info_len); 179 put_ctx->path_info_len);
180 GNUNET_memcpy (val->path_info, 180 GNUNET_memcpy (val->path_info,
181 put_ctx->path_info, 181 put_ctx->path_info,
182 put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity)); 182 put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity));
183 GNUNET_CONTAINER_heap_update_cost (val->hn, 183 GNUNET_CONTAINER_heap_update_cost (val->hn,
184 val->discard_time.abs_value_us); 184 val->discard_time.abs_value_us);
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -199,6 +199,7 @@ put_cb (void *cls,
199 * 199 *
200 * @param cls closure (our `struct Plugin`) 200 * @param cls closure (our `struct Plugin`)
201 * @param key key to store data under 201 * @param key key to store data under
202 * @param xor_distance how close is @a key to our PID?
202 * @param size number of bytes in @a data 203 * @param size number of bytes in @a data
203 * @param data data to store 204 * @param data data to store
204 * @param type type of the value 205 * @param type type of the value
@@ -210,6 +211,7 @@ put_cb (void *cls,
210static ssize_t 211static ssize_t
211heap_plugin_put (void *cls, 212heap_plugin_put (void *cls,
212 const struct GNUNET_HashCode *key, 213 const struct GNUNET_HashCode *key,
214 uint32_t xor_distance,
213 size_t size, 215 size_t size,
214 const char *data, 216 const char *data,
215 enum GNUNET_BLOCK_Type type, 217 enum GNUNET_BLOCK_Type type,
@@ -222,7 +224,6 @@ heap_plugin_put (void *cls,
222 struct PutContext put_ctx; 224 struct PutContext put_ctx;
223 225
224 put_ctx.found = GNUNET_NO; 226 put_ctx.found = GNUNET_NO;
225 put_ctx.heap = plugin->heap;
226 put_ctx.data = data; 227 put_ctx.data = data;
227 put_ctx.size = size; 228 put_ctx.size = size;
228 put_ctx.path_info = path_info; 229 put_ctx.path_info = path_info;
@@ -236,22 +237,28 @@ heap_plugin_put (void *cls,
236 if (GNUNET_YES == put_ctx.found) 237 if (GNUNET_YES == put_ctx.found)
237 return 0; 238 return 0;
238 val = GNUNET_malloc (sizeof (struct Value) + size); 239 val = GNUNET_malloc (sizeof (struct Value) + size);
239 GNUNET_memcpy (&val[1], data, size); 240 GNUNET_memcpy (&val[1],
241 data,
242 size);
240 val->key = *key; 243 val->key = *key;
241 val->type = type; 244 val->type = type;
242 val->discard_time = discard_time; 245 val->discard_time = discard_time;
243 val->size = size; 246 val->size = size;
247 if (xor_distance >= NUM_HEAPS)
248 val->distance = NUM_HEAPS - 1;
249 else
250 val->distance = xor_distance;
244 GNUNET_array_grow (val->path_info, 251 GNUNET_array_grow (val->path_info,
245 val->path_info_len, 252 val->path_info_len,
246 path_info_len); 253 path_info_len);
247 GNUNET_memcpy (val->path_info, 254 GNUNET_memcpy (val->path_info,
248 path_info, 255 path_info,
249 path_info_len * sizeof (struct GNUNET_PeerIdentity)); 256 path_info_len * sizeof (struct GNUNET_PeerIdentity));
250 (void) GNUNET_CONTAINER_multihashmap_put (plugin->map, 257 (void) GNUNET_CONTAINER_multihashmap_put (plugin->map,
251 &val->key, 258 &val->key,
252 val, 259 val,
253 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 260 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
254 val->hn = GNUNET_CONTAINER_heap_insert (plugin->heap, 261 val->hn = GNUNET_CONTAINER_heap_insert (plugin->heaps[val->distance],
255 val, 262 val,
256 val->discard_time.abs_value_us); 263 val->discard_time.abs_value_us);
257 return size + OVERHEAD; 264 return size + OVERHEAD;
@@ -307,6 +314,9 @@ get_cb (void *cls,
307 if ( (get_ctx->type != val->type) && 314 if ( (get_ctx->type != val->type) &&
308 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) ) 315 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
309 return GNUNET_OK; 316 return GNUNET_OK;
317 if (0 ==
318 GNUNET_TIME_absolute_get_remaining (val->discard_time).rel_value_us)
319 return GNUNET_OK;
310 if (NULL != get_ctx->iter) 320 if (NULL != get_ctx->iter)
311 ret = get_ctx->iter (get_ctx->iter_cls, 321 ret = get_ctx->iter (get_ctx->iter_cls,
312 key, 322 key,
@@ -369,7 +379,12 @@ heap_plugin_del (void *cls)
369 struct Plugin *plugin = cls; 379 struct Plugin *plugin = cls;
370 struct Value *val; 380 struct Value *val;
371 381
372 val = GNUNET_CONTAINER_heap_remove_root (plugin->heap); 382 for (unsigned int i=0;i<NUM_HEAPS;i++)
383 {
384 val = GNUNET_CONTAINER_heap_remove_root (plugin->heaps[i]);
385 if (NULL != val)
386 break;
387 }
373 if (NULL == val) 388 if (NULL == val)
374 return GNUNET_SYSERR; 389 return GNUNET_SYSERR;
375 GNUNET_assert (GNUNET_YES == 390 GNUNET_assert (GNUNET_YES ==
@@ -413,6 +428,53 @@ heap_plugin_get_random (void *cls,
413 428
414 429
415/** 430/**
431 * Closure for #find_closest().
432 */
433struct GetClosestContext
434{
435 struct Value **values;
436
437 unsigned int num_results;
438
439 const struct GNUNET_HashCode *key;
440};
441
442
443static int
444find_closest (void *cls,
445 const struct GNUNET_HashCode *key,
446 void *value)
447{
448 struct GetClosestContext *gcc = cls;
449 struct Value *val = value;
450 unsigned int j;
451
452 if (1 != GNUNET_CRYPTO_hash_cmp (key,
453 gcc->key))
454 return GNUNET_OK; /* useless */
455 j = gcc->num_results;
456 for (unsigned int i=0;i<gcc->num_results;i++)
457 {
458 if (NULL == gcc->values[i])
459 {
460 j = i;
461 break;
462 }
463 if (1 == GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key,
464 key))
465 {
466 j = i;
467 break;
468 }
469 }
470 if (j == gcc->num_results)
471 return GNUNET_OK;
472 gcc->values[j] = val;
473 return GNUNET_OK;
474}
475
476
477/**
416 * Iterate over the results that are "close" to a particular key in 478 * Iterate over the results that are "close" to a particular key in
417 * the datacache. "close" is defined as numerically larger than @a 479 * the datacache. "close" is defined as numerically larger than @a
418 * key (when interpreted as a circular address space), with small 480 * key (when interpreted as a circular address space), with small
@@ -432,8 +494,30 @@ heap_plugin_get_closest (void *cls,
432 GNUNET_DATACACHE_Iterator iter, 494 GNUNET_DATACACHE_Iterator iter,
433 void *iter_cls) 495 void *iter_cls)
434{ 496{
435 GNUNET_break (0); // not implemented! 497 struct Plugin *plugin = cls;
436 return 0; 498 struct Value *values[num_results];
499 struct GetClosestContext gcc = {
500 .values = values,
501 .num_results = num_results,
502 .key = key
503 };
504 GNUNET_CONTAINER_multihashmap_iterate (plugin->map,
505 &find_closest,
506 &gcc);
507 for (unsigned int i=0;i<num_results;i++)
508 {
509 if (NULL == values[i])
510 return i;
511 iter (iter_cls,
512 &values[i]->key,
513 values[i]->size,
514 (void *) &values[i][1],
515 values[i]->type,
516 values[i]->discard_time,
517 values[i]->path_info_len,
518 values[i]->path_info);
519 }
520 return num_results;
437} 521}
438 522
439 523
@@ -453,7 +537,8 @@ libgnunet_plugin_datacache_heap_init (void *cls)
453 plugin = GNUNET_new (struct Plugin); 537 plugin = GNUNET_new (struct Plugin);
454 plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */ 538 plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */
455 GNUNET_YES); 539 GNUNET_YES);
456 plugin->heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 540 for (unsigned int i=0;i<NUM_HEAPS;i++)
541 plugin->heaps[i] = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
457 plugin->env = env; 542 plugin->env = env;
458 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); 543 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions);
459 api->cls = plugin; 544 api->cls = plugin;
@@ -481,16 +566,19 @@ libgnunet_plugin_datacache_heap_done (void *cls)
481 struct Plugin *plugin = api->cls; 566 struct Plugin *plugin = api->cls;
482 struct Value *val; 567 struct Value *val;
483 568
484 while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->heap))) 569 for (unsigned int i=0;i<NUM_HEAPS;i++)
485 { 570 {
486 GNUNET_assert (GNUNET_YES == 571 while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->heaps[i])))
487 GNUNET_CONTAINER_multihashmap_remove (plugin->map, 572 {
488 &val->key, 573 GNUNET_assert (GNUNET_YES ==
489 val)); 574 GNUNET_CONTAINER_multihashmap_remove (plugin->map,
490 GNUNET_free_non_null (val->path_info); 575 &val->key,
491 GNUNET_free (val); 576 val));
577 GNUNET_free_non_null (val->path_info);
578 GNUNET_free (val);
579 }
580 GNUNET_CONTAINER_heap_destroy (plugin->heaps[i]);
492 } 581 }
493 GNUNET_CONTAINER_heap_destroy (plugin->heap);
494 GNUNET_CONTAINER_multihashmap_destroy (plugin->map); 582 GNUNET_CONTAINER_multihashmap_destroy (plugin->map);
495 GNUNET_free (plugin); 583 GNUNET_free (plugin);
496 GNUNET_free (api); 584 GNUNET_free (api);