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