summaryrefslogtreecommitdiff
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.c334
1 files changed, 171 insertions, 163 deletions
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index face566a1..f176e3568 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -27,16 +27,19 @@
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_datacache_plugin.h" 28#include "gnunet_datacache_plugin.h"
29 29
30#define LOG(kind, ...) GNUNET_log_from(kind, "datacache-heap", __VA_ARGS__) 30#define LOG(kind, ...) GNUNET_log_from (kind, "datacache-heap", __VA_ARGS__)
31 31
32#define LOG_STRERROR_FILE(kind, op, fn) GNUNET_log_from_strerror_file(kind, "datacache-heap", op, fn) 32#define LOG_STRERROR_FILE(kind, op, fn) GNUNET_log_from_strerror_file (kind, \
33 "datacache-heap", \
34 op, fn)
33 35
34#define NUM_HEAPS 24 36#define NUM_HEAPS 24
35 37
36/** 38/**
37 * Context for all functions in this plugin. 39 * Context for all functions in this plugin.
38 */ 40 */
39struct Plugin { 41struct Plugin
42{
40 /** 43 /**
41 * Our execution environment. 44 * Our execution environment.
42 */ 45 */
@@ -57,7 +60,8 @@ struct Plugin {
57/** 60/**
58 * Entry in the hash map. 61 * Entry in the hash map.
59 */ 62 */
60struct Value { 63struct Value
64{
61 /** 65 /**
62 * Key for the entry. 66 * Key for the entry.
63 */ 67 */
@@ -106,7 +110,8 @@ struct Value {
106/** 110/**
107 * Closure for #put_cb(). 111 * Closure for #put_cb().
108 */ 112 */
109struct PutContext { 113struct PutContext
114{
110 /** 115 /**
111 * Expiration time for the new value. 116 * Expiration time for the new value.
112 */ 117 */
@@ -154,39 +159,39 @@ struct PutContext {
154 * @return #GNUNET_YES if not found (to continue to iterate) 159 * @return #GNUNET_YES if not found (to continue to iterate)
155 */ 160 */
156static int 161static int
157put_cb(void *cls, 162put_cb (void *cls,
158 const struct GNUNET_HashCode *key, 163 const struct GNUNET_HashCode *key,
159 void *value) 164 void *value)
160{ 165{
161 struct PutContext *put_ctx = cls; 166 struct PutContext *put_ctx = cls;
162 struct Value *val = value; 167 struct Value *val = value;
163 168
164 if ((val->size == put_ctx->size) && 169 if ((val->size == put_ctx->size) &&
165 (val->type == put_ctx->type) && 170 (val->type == put_ctx->type) &&
166 (0 == memcmp(&val[1], 171 (0 == memcmp (&val[1],
167 put_ctx->data, 172 put_ctx->data,
168 put_ctx->size))) 173 put_ctx->size)))
169 { 174 {
170 put_ctx->found = GNUNET_YES; 175 put_ctx->found = GNUNET_YES;
171 val->discard_time = GNUNET_TIME_absolute_max(val->discard_time, 176 val->discard_time = GNUNET_TIME_absolute_max (val->discard_time,
172 put_ctx->discard_time); 177 put_ctx->discard_time);
173 /* replace old path with new path */ 178 /* replace old path with new path */
174 GNUNET_array_grow(val->path_info, 179 GNUNET_array_grow (val->path_info,
175 val->path_info_len, 180 val->path_info_len,
176 put_ctx->path_info_len); 181 put_ctx->path_info_len);
177 GNUNET_memcpy(val->path_info, 182 GNUNET_memcpy (val->path_info,
178 put_ctx->path_info, 183 put_ctx->path_info,
179 put_ctx->path_info_len * sizeof(struct GNUNET_PeerIdentity)); 184 put_ctx->path_info_len * sizeof(struct GNUNET_PeerIdentity));
180 GNUNET_CONTAINER_heap_update_cost(val->hn, 185 GNUNET_CONTAINER_heap_update_cost (val->hn,
181 val->discard_time.abs_value_us); 186 val->discard_time.abs_value_us);
182 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 187 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
183 "Got same value for key %s and type %d (size %u vs %u)\n", 188 "Got same value for key %s and type %d (size %u vs %u)\n",
184 GNUNET_h2s(key), 189 GNUNET_h2s (key),
185 val->type, 190 val->type,
186 (unsigned int)val->size, 191 (unsigned int) val->size,
187 (unsigned int)put_ctx->size); 192 (unsigned int) put_ctx->size);
188 return GNUNET_NO; 193 return GNUNET_NO;
189 } 194 }
190 return GNUNET_YES; 195 return GNUNET_YES;
191} 196}
192 197
@@ -206,15 +211,15 @@ put_cb(void *cls,
206 * @return 0 if duplicate, -1 on error, number of bytes used otherwise 211 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
207 */ 212 */
208static ssize_t 213static ssize_t
209heap_plugin_put(void *cls, 214heap_plugin_put (void *cls,
210 const struct GNUNET_HashCode *key, 215 const struct GNUNET_HashCode *key,
211 uint32_t xor_distance, 216 uint32_t xor_distance,
212 size_t size, 217 size_t size,
213 const char *data, 218 const char *data,
214 enum GNUNET_BLOCK_Type type, 219 enum GNUNET_BLOCK_Type type,
215 struct GNUNET_TIME_Absolute discard_time, 220 struct GNUNET_TIME_Absolute discard_time,
216 unsigned int path_info_len, 221 unsigned int path_info_len,
217 const struct GNUNET_PeerIdentity *path_info) 222 const struct GNUNET_PeerIdentity *path_info)
218{ 223{
219 struct Plugin *plugin = cls; 224 struct Plugin *plugin = cls;
220 struct Value *val; 225 struct Value *val;
@@ -227,16 +232,16 @@ heap_plugin_put(void *cls,
227 put_ctx.path_info_len = path_info_len; 232 put_ctx.path_info_len = path_info_len;
228 put_ctx.discard_time = discard_time; 233 put_ctx.discard_time = discard_time;
229 put_ctx.type = type; 234 put_ctx.type = type;
230 GNUNET_CONTAINER_multihashmap_get_multiple(plugin->map, 235 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map,
231 key, 236 key,
232 &put_cb, 237 &put_cb,
233 &put_ctx); 238 &put_ctx);
234 if (GNUNET_YES == put_ctx.found) 239 if (GNUNET_YES == put_ctx.found)
235 return 0; 240 return 0;
236 val = GNUNET_malloc(sizeof(struct Value) + size); 241 val = GNUNET_malloc (sizeof(struct Value) + size);
237 GNUNET_memcpy(&val[1], 242 GNUNET_memcpy (&val[1],
238 data, 243 data,
239 size); 244 size);
240 val->key = *key; 245 val->key = *key;
241 val->type = type; 246 val->type = type;
242 val->discard_time = discard_time; 247 val->discard_time = discard_time;
@@ -245,19 +250,19 @@ heap_plugin_put(void *cls,
245 val->distance = NUM_HEAPS - 1; 250 val->distance = NUM_HEAPS - 1;
246 else 251 else
247 val->distance = xor_distance; 252 val->distance = xor_distance;
248 GNUNET_array_grow(val->path_info, 253 GNUNET_array_grow (val->path_info,
249 val->path_info_len, 254 val->path_info_len,
250 path_info_len); 255 path_info_len);
251 GNUNET_memcpy(val->path_info, 256 GNUNET_memcpy (val->path_info,
252 path_info, 257 path_info,
253 path_info_len * sizeof(struct GNUNET_PeerIdentity)); 258 path_info_len * sizeof(struct GNUNET_PeerIdentity));
254 (void)GNUNET_CONTAINER_multihashmap_put(plugin->map, 259 (void) GNUNET_CONTAINER_multihashmap_put (plugin->map,
255 &val->key, 260 &val->key,
261 val,
262 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
263 val->hn = GNUNET_CONTAINER_heap_insert (plugin->heaps[val->distance],
256 val, 264 val,
257 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 265 val->discard_time.abs_value_us);
258 val->hn = GNUNET_CONTAINER_heap_insert(plugin->heaps[val->distance],
259 val,
260 val->discard_time.abs_value_us);
261 return size + OVERHEAD; 266 return size + OVERHEAD;
262} 267}
263 268
@@ -265,7 +270,8 @@ heap_plugin_put(void *cls,
265/** 270/**
266 * Closure for #get_cb(). 271 * Closure for #get_cb().
267 */ 272 */
268struct GetContext { 273struct GetContext
274{
269 /** 275 /**
270 * Function to call for each result. 276 * Function to call for each result.
271 */ 277 */
@@ -299,9 +305,9 @@ struct GetContext {
299 * @return #GNUNET_YES to continue to iterate 305 * @return #GNUNET_YES to continue to iterate
300 */ 306 */
301static int 307static int
302get_cb(void *cls, 308get_cb (void *cls,
303 const struct GNUNET_HashCode *key, 309 const struct GNUNET_HashCode *key,
304 void *value) 310 void *value)
305{ 311{
306 struct GetContext *get_ctx = cls; 312 struct GetContext *get_ctx = cls;
307 struct Value *val = value; 313 struct Value *val = value;
@@ -311,17 +317,17 @@ get_cb(void *cls,
311 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type)) 317 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type))
312 return GNUNET_OK; 318 return GNUNET_OK;
313 if (0 == 319 if (0 ==
314 GNUNET_TIME_absolute_get_remaining(val->discard_time).rel_value_us) 320 GNUNET_TIME_absolute_get_remaining (val->discard_time).rel_value_us)
315 return GNUNET_OK; 321 return GNUNET_OK;
316 if (NULL != get_ctx->iter) 322 if (NULL != get_ctx->iter)
317 ret = get_ctx->iter(get_ctx->iter_cls, 323 ret = get_ctx->iter (get_ctx->iter_cls,
318 key, 324 key,
319 val->size, 325 val->size,
320 (const char *)&val[1], 326 (const char *) &val[1],
321 val->type, 327 val->type,
322 val->discard_time, 328 val->discard_time,
323 val->path_info_len, 329 val->path_info_len,
324 val->path_info); 330 val->path_info);
325 else 331 else
326 ret = GNUNET_YES; 332 ret = GNUNET_YES;
327 get_ctx->cnt++; 333 get_ctx->cnt++;
@@ -341,11 +347,11 @@ get_cb(void *cls,
341 * @return the number of results found 347 * @return the number of results found
342 */ 348 */
343static unsigned int 349static unsigned int
344heap_plugin_get(void *cls, 350heap_plugin_get (void *cls,
345 const struct GNUNET_HashCode *key, 351 const struct GNUNET_HashCode *key,
346 enum GNUNET_BLOCK_Type type, 352 enum GNUNET_BLOCK_Type type,
347 GNUNET_DATACACHE_Iterator iter, 353 GNUNET_DATACACHE_Iterator iter,
348 void *iter_cls) 354 void *iter_cls)
349{ 355{
350 struct Plugin *plugin = cls; 356 struct Plugin *plugin = cls;
351 struct GetContext get_ctx; 357 struct GetContext get_ctx;
@@ -354,10 +360,10 @@ heap_plugin_get(void *cls,
354 get_ctx.iter = iter; 360 get_ctx.iter = iter;
355 get_ctx.iter_cls = iter_cls; 361 get_ctx.iter_cls = iter_cls;
356 get_ctx.cnt = 0; 362 get_ctx.cnt = 0;
357 GNUNET_CONTAINER_multihashmap_get_multiple(plugin->map, 363 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map,
358 key, 364 key,
359 &get_cb, 365 &get_cb,
360 &get_ctx); 366 &get_ctx);
361 return get_ctx.cnt; 367 return get_ctx.cnt;
362} 368}
363 369
@@ -370,28 +376,28 @@ heap_plugin_get(void *cls,
370 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 376 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
371 */ 377 */
372static int 378static int
373heap_plugin_del(void *cls) 379heap_plugin_del (void *cls)
374{ 380{
375 struct Plugin *plugin = cls; 381 struct Plugin *plugin = cls;
376 struct Value *val; 382 struct Value *val;
377 383
378 for (unsigned int i = 0; i < NUM_HEAPS; i++) 384 for (unsigned int i = 0; i < NUM_HEAPS; i++)
379 { 385 {
380 val = GNUNET_CONTAINER_heap_remove_root(plugin->heaps[i]); 386 val = GNUNET_CONTAINER_heap_remove_root (plugin->heaps[i]);
381 if (NULL != val) 387 if (NULL != val)
382 break; 388 break;
383 } 389 }
384 if (NULL == val) 390 if (NULL == val)
385 return GNUNET_SYSERR; 391 return GNUNET_SYSERR;
386 GNUNET_assert(GNUNET_YES == 392 GNUNET_assert (GNUNET_YES ==
387 GNUNET_CONTAINER_multihashmap_remove(plugin->map, 393 GNUNET_CONTAINER_multihashmap_remove (plugin->map,
388 &val->key, 394 &val->key,
389 val)); 395 val));
390 plugin->env->delete_notify(plugin->env->cls, 396 plugin->env->delete_notify (plugin->env->cls,
391 &val->key, 397 &val->key,
392 val->size + OVERHEAD); 398 val->size + OVERHEAD);
393 GNUNET_free_non_null(val->path_info); 399 GNUNET_free_non_null (val->path_info);
394 GNUNET_free(val); 400 GNUNET_free (val);
395 return GNUNET_OK; 401 return GNUNET_OK;
396} 402}
397 403
@@ -405,9 +411,9 @@ heap_plugin_del(void *cls)
405 * @return the number of results found 411 * @return the number of results found
406 */ 412 */
407static unsigned int 413static unsigned int
408heap_plugin_get_random(void *cls, 414heap_plugin_get_random (void *cls,
409 GNUNET_DATACACHE_Iterator iter, 415 GNUNET_DATACACHE_Iterator iter,
410 void *iter_cls) 416 void *iter_cls)
411{ 417{
412 struct Plugin *plugin = cls; 418 struct Plugin *plugin = cls;
413 struct GetContext get_ctx; 419 struct GetContext get_ctx;
@@ -416,9 +422,9 @@ heap_plugin_get_random(void *cls,
416 get_ctx.iter = iter; 422 get_ctx.iter = iter;
417 get_ctx.iter_cls = iter_cls; 423 get_ctx.iter_cls = iter_cls;
418 get_ctx.cnt = 0; 424 get_ctx.cnt = 0;
419 GNUNET_CONTAINER_multihashmap_get_random(plugin->map, 425 GNUNET_CONTAINER_multihashmap_get_random (plugin->map,
420 &get_cb, 426 &get_cb,
421 &get_ctx); 427 &get_ctx);
422 return get_ctx.cnt; 428 return get_ctx.cnt;
423} 429}
424 430
@@ -426,7 +432,8 @@ heap_plugin_get_random(void *cls,
426/** 432/**
427 * Closure for #find_closest(). 433 * Closure for #find_closest().
428 */ 434 */
429struct GetClosestContext { 435struct GetClosestContext
436{
430 struct Value **values; 437 struct Value **values;
431 438
432 unsigned int num_results; 439 unsigned int num_results;
@@ -436,32 +443,32 @@ struct GetClosestContext {
436 443
437 444
438static int 445static int
439find_closest(void *cls, 446find_closest (void *cls,
440 const struct GNUNET_HashCode *key, 447 const struct GNUNET_HashCode *key,
441 void *value) 448 void *value)
442{ 449{
443 struct GetClosestContext *gcc = cls; 450 struct GetClosestContext *gcc = cls;
444 struct Value *val = value; 451 struct Value *val = value;
445 unsigned int j; 452 unsigned int j;
446 453
447 if (1 != GNUNET_CRYPTO_hash_cmp(key, 454 if (1 != GNUNET_CRYPTO_hash_cmp (key,
448 gcc->key)) 455 gcc->key))
449 return GNUNET_OK; /* useless */ 456 return GNUNET_OK; /* useless */
450 j = gcc->num_results; 457 j = gcc->num_results;
451 for (unsigned int i = 0; i < gcc->num_results; i++) 458 for (unsigned int i = 0; i < gcc->num_results; i++)
459 {
460 if (NULL == gcc->values[i])
461 {
462 j = i;
463 break;
464 }
465 if (1 == GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key,
466 key))
452 { 467 {
453 if (NULL == gcc->values[i]) 468 j = i;
454 { 469 break;
455 j = i;
456 break;
457 }
458 if (1 == GNUNET_CRYPTO_hash_cmp(&gcc->values[i]->key,
459 key))
460 {
461 j = i;
462 break;
463 }
464 } 470 }
471 }
465 if (j == gcc->num_results) 472 if (j == gcc->num_results)
466 return GNUNET_OK; 473 return GNUNET_OK;
467 gcc->values[j] = val; 474 gcc->values[j] = val;
@@ -483,11 +490,11 @@ find_closest(void *cls,
483 * @return the number of results found 490 * @return the number of results found
484 */ 491 */
485static unsigned int 492static unsigned int
486heap_plugin_get_closest(void *cls, 493heap_plugin_get_closest (void *cls,
487 const struct GNUNET_HashCode *key, 494 const struct GNUNET_HashCode *key,
488 unsigned int num_results, 495 unsigned int num_results,
489 GNUNET_DATACACHE_Iterator iter, 496 GNUNET_DATACACHE_Iterator iter,
490 void *iter_cls) 497 void *iter_cls)
491{ 498{
492 struct Plugin *plugin = cls; 499 struct Plugin *plugin = cls;
493 struct Value *values[num_results]; 500 struct Value *values[num_results];
@@ -497,22 +504,22 @@ heap_plugin_get_closest(void *cls,
497 .key = key 504 .key = key
498 }; 505 };
499 506
500 GNUNET_CONTAINER_multihashmap_iterate(plugin->map, 507 GNUNET_CONTAINER_multihashmap_iterate (plugin->map,
501 &find_closest, 508 &find_closest,
502 &gcc); 509 &gcc);
503 for (unsigned int i = 0; i < num_results; i++) 510 for (unsigned int i = 0; i < num_results; i++)
504 { 511 {
505 if (NULL == values[i]) 512 if (NULL == values[i])
506 return i; 513 return i;
507 iter(iter_cls, 514 iter (iter_cls,
508 &values[i]->key, 515 &values[i]->key,
509 values[i]->size, 516 values[i]->size,
510 (void *)&values[i][1], 517 (void *) &values[i][1],
511 values[i]->type, 518 values[i]->type,
512 values[i]->discard_time, 519 values[i]->discard_time,
513 values[i]->path_info_len, 520 values[i]->path_info_len,
514 values[i]->path_info); 521 values[i]->path_info);
515 } 522 }
516 return num_results; 523 return num_results;
517} 524}
518 525
@@ -524,27 +531,28 @@ heap_plugin_get_closest(void *cls,
524 * @return the plugin's closure (our `struct Plugin`) 531 * @return the plugin's closure (our `struct Plugin`)
525 */ 532 */
526void * 533void *
527libgnunet_plugin_datacache_heap_init(void *cls) 534libgnunet_plugin_datacache_heap_init (void *cls)
528{ 535{
529 struct GNUNET_DATACACHE_PluginEnvironment *env = cls; 536 struct GNUNET_DATACACHE_PluginEnvironment *env = cls;
530 struct GNUNET_DATACACHE_PluginFunctions *api; 537 struct GNUNET_DATACACHE_PluginFunctions *api;
531 struct Plugin *plugin; 538 struct Plugin *plugin;
532 539
533 plugin = GNUNET_new(struct Plugin); 540 plugin = GNUNET_new (struct Plugin);
534 plugin->map = GNUNET_CONTAINER_multihashmap_create(1024, /* FIXME: base on quota! */ 541 plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */
535 GNUNET_YES); 542 GNUNET_YES);
536 for (unsigned int i = 0; i < NUM_HEAPS; i++) 543 for (unsigned int i = 0; i < NUM_HEAPS; i++)
537 plugin->heaps[i] = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN); 544 plugin->heaps[i] = GNUNET_CONTAINER_heap_create (
545 GNUNET_CONTAINER_HEAP_ORDER_MIN);
538 plugin->env = env; 546 plugin->env = env;
539 api = GNUNET_new(struct GNUNET_DATACACHE_PluginFunctions); 547 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions);
540 api->cls = plugin; 548 api->cls = plugin;
541 api->get = &heap_plugin_get; 549 api->get = &heap_plugin_get;
542 api->put = &heap_plugin_put; 550 api->put = &heap_plugin_put;
543 api->del = &heap_plugin_del; 551 api->del = &heap_plugin_del;
544 api->get_random = &heap_plugin_get_random; 552 api->get_random = &heap_plugin_get_random;
545 api->get_closest = &heap_plugin_get_closest; 553 api->get_closest = &heap_plugin_get_closest;
546 LOG(GNUNET_ERROR_TYPE_INFO, 554 LOG (GNUNET_ERROR_TYPE_INFO,
547 _("Heap datacache running\n")); 555 _ ("Heap datacache running\n"));
548 return api; 556 return api;
549} 557}
550 558
@@ -556,28 +564,28 @@ libgnunet_plugin_datacache_heap_init(void *cls)
556 * @return NULL 564 * @return NULL
557 */ 565 */
558void * 566void *
559libgnunet_plugin_datacache_heap_done(void *cls) 567libgnunet_plugin_datacache_heap_done (void *cls)
560{ 568{
561 struct GNUNET_DATACACHE_PluginFunctions *api = cls; 569 struct GNUNET_DATACACHE_PluginFunctions *api = cls;
562 struct Plugin *plugin = api->cls; 570 struct Plugin *plugin = api->cls;
563 struct Value *val; 571 struct Value *val;
564 572
565 for (unsigned int i = 0; i < NUM_HEAPS; i++) 573 for (unsigned int i = 0; i < NUM_HEAPS; i++)
574 {
575 while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->heaps[i])))
566 { 576 {
567 while (NULL != (val = GNUNET_CONTAINER_heap_remove_root(plugin->heaps[i]))) 577 GNUNET_assert (GNUNET_YES ==
568 { 578 GNUNET_CONTAINER_multihashmap_remove (plugin->map,
569 GNUNET_assert(GNUNET_YES == 579 &val->key,
570 GNUNET_CONTAINER_multihashmap_remove(plugin->map, 580 val));
571 &val->key, 581 GNUNET_free_non_null (val->path_info);
572 val)); 582 GNUNET_free (val);
573 GNUNET_free_non_null(val->path_info);
574 GNUNET_free(val);
575 }
576 GNUNET_CONTAINER_heap_destroy(plugin->heaps[i]);
577 } 583 }
578 GNUNET_CONTAINER_multihashmap_destroy(plugin->map); 584 GNUNET_CONTAINER_heap_destroy (plugin->heaps[i]);
579 GNUNET_free(plugin); 585 }
580 GNUNET_free(api); 586 GNUNET_CONTAINER_multihashmap_destroy (plugin->map);
587 GNUNET_free (plugin);
588 GNUNET_free (api);
581 return NULL; 589 return NULL;
582} 590}
583 591