aboutsummaryrefslogtreecommitdiff
path: root/src/util/container_multihashmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/container_multihashmap.c')
-rw-r--r--src/util/container_multihashmap.c879
1 files changed, 442 insertions, 437 deletions
diff --git a/src/util/container_multihashmap.c b/src/util/container_multihashmap.c
index 62e5311d8..7da34f1a1 100644
--- a/src/util/container_multihashmap.c
+++ b/src/util/container_multihashmap.c
@@ -27,7 +27,7 @@
27#include "gnunet_container_lib.h" 27#include "gnunet_container_lib.h"
28 28
29#define LOG(kind, ...) \ 29#define LOG(kind, ...) \
30 GNUNET_log_from(kind, "util-container-multihashmap", __VA_ARGS__) 30 GNUNET_log_from (kind, "util-container-multihashmap", __VA_ARGS__)
31 31
32/** 32/**
33 * Maximum recursion depth for callbacks of 33 * Maximum recursion depth for callbacks of
@@ -41,7 +41,8 @@
41/** 41/**
42 * An entry in the hash map with the full key. 42 * An entry in the hash map with the full key.
43 */ 43 */
44struct BigMapEntry { 44struct BigMapEntry
45{
45 /** 46 /**
46 * Value of the entry. 47 * Value of the entry.
47 */ 48 */
@@ -62,7 +63,8 @@ struct BigMapEntry {
62/** 63/**
63 * An entry in the hash map with just a pointer to the key. 64 * An entry in the hash map with just a pointer to the key.
64 */ 65 */
65struct SmallMapEntry { 66struct SmallMapEntry
67{
66 /** 68 /**
67 * Value of the entry. 69 * Value of the entry.
68 */ 70 */
@@ -83,7 +85,8 @@ struct SmallMapEntry {
83/** 85/**
84 * Entry in the map. 86 * Entry in the map.
85 */ 87 */
86union MapEntry { 88union MapEntry
89{
87 /** 90 /**
88 * Variant used if map entries only contain a pointer to the key. 91 * Variant used if map entries only contain a pointer to the key.
89 */ 92 */
@@ -99,7 +102,8 @@ union MapEntry {
99/** 102/**
100 * Internal representation of the hash map. 103 * Internal representation of the hash map.
101 */ 104 */
102struct GNUNET_CONTAINER_MultiHashMap { 105struct GNUNET_CONTAINER_MultiHashMap
106{
103 /** 107 /**
104 * All of our buckets. 108 * All of our buckets.
105 */ 109 */
@@ -146,7 +150,8 @@ struct GNUNET_CONTAINER_MultiHashMap {
146 * Cursor into a multihashmap. 150 * Cursor into a multihashmap.
147 * Allows to enumerate elements asynchronously. 151 * Allows to enumerate elements asynchronously.
148 */ 152 */
149struct GNUNET_CONTAINER_MultiHashMapIterator { 153struct GNUNET_CONTAINER_MultiHashMapIterator
154{
150 /** 155 /**
151 * Position in the bucket @e idx 156 * Position in the bucket @e idx
152 */ 157 */
@@ -186,34 +191,34 @@ struct GNUNET_CONTAINER_MultiHashMapIterator {
186 * @return NULL on error 191 * @return NULL on error
187 */ 192 */
188struct GNUNET_CONTAINER_MultiHashMap * 193struct GNUNET_CONTAINER_MultiHashMap *
189GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys) 194GNUNET_CONTAINER_multihashmap_create (unsigned int len, int do_not_copy_keys)
190{ 195{
191 struct GNUNET_CONTAINER_MultiHashMap *hm; 196 struct GNUNET_CONTAINER_MultiHashMap *hm;
192 197
193 GNUNET_assert(len > 0); 198 GNUNET_assert (len > 0);
194 hm = GNUNET_new(struct GNUNET_CONTAINER_MultiHashMap); 199 hm = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap);
195 if (len * sizeof(union MapEntry) > GNUNET_MAX_MALLOC_CHECKED) 200 if (len * sizeof(union MapEntry) > GNUNET_MAX_MALLOC_CHECKED)
201 {
202 size_t s;
203 /* application *explicitly* requested very large map, hopefully
204 it checks the return value... */
205 s = len * sizeof(union MapEntry);
206 if ((s / sizeof(union MapEntry)) != len)
207 return NULL; /* integer overflow on multiplication */
208 if (NULL == (hm->map = GNUNET_malloc_large (s)))
196 { 209 {
197 size_t s; 210 /* out of memory */
198 /* application *explicitly* requested very large map, hopefully 211 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
199 it checks the return value... */ 212 "Out of memory allocating large hash map (%u entries)\n",
200 s = len * sizeof(union MapEntry); 213 len);
201 if ((s / sizeof(union MapEntry)) != len) 214 GNUNET_free (hm);
202 return NULL; /* integer overflow on multiplication */ 215 return NULL;
203 if (NULL == (hm->map = GNUNET_malloc_large(s)))
204 {
205 /* out of memory */
206 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
207 "Out of memory allocating large hash map (%u entries)\n",
208 len);
209 GNUNET_free(hm);
210 return NULL;
211 }
212 } 216 }
217 }
213 else 218 else
214 { 219 {
215 hm->map = GNUNET_new_array(len, union MapEntry); 220 hm->map = GNUNET_new_array (len, union MapEntry);
216 } 221 }
217 hm->map_length = len; 222 hm->map_length = len;
218 hm->use_small_entries = do_not_copy_keys; 223 hm->use_small_entries = do_not_copy_keys;
219 return hm; 224 return hm;
@@ -227,44 +232,44 @@ GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
227 * @param map the map 232 * @param map the map
228 */ 233 */
229void 234void
230GNUNET_CONTAINER_multihashmap_destroy( 235GNUNET_CONTAINER_multihashmap_destroy (
231 struct GNUNET_CONTAINER_MultiHashMap *map) 236 struct GNUNET_CONTAINER_MultiHashMap *map)
232{ 237{
233 GNUNET_assert(0 == map->next_cache_off); 238 GNUNET_assert (0 == map->next_cache_off);
234 for (unsigned int i = 0; i < map->map_length; i++) 239 for (unsigned int i = 0; i < map->map_length; i++)
235 { 240 {
236 union MapEntry me; 241 union MapEntry me;
237 242
238 me = map->map[i]; 243 me = map->map[i];
239 if (map->use_small_entries) 244 if (map->use_small_entries)
240 { 245 {
241 struct SmallMapEntry *sme; 246 struct SmallMapEntry *sme;
242 struct SmallMapEntry *nxt; 247 struct SmallMapEntry *nxt;
243 248
244 nxt = me.sme; 249 nxt = me.sme;
245 while (NULL != (sme = nxt)) 250 while (NULL != (sme = nxt))
246 { 251 {
247 nxt = sme->next; 252 nxt = sme->next;
248 GNUNET_free(sme); 253 GNUNET_free (sme);
249 } 254 }
250 me.sme = NULL; 255 me.sme = NULL;
251 }
252 else
253 {
254 struct BigMapEntry *bme;
255 struct BigMapEntry *nxt;
256
257 nxt = me.bme;
258 while (NULL != (bme = nxt))
259 {
260 nxt = bme->next;
261 GNUNET_free(bme);
262 }
263 me.bme = NULL;
264 }
265 } 256 }
266 GNUNET_free(map->map); 257 else
267 GNUNET_free(map); 258 {
259 struct BigMapEntry *bme;
260 struct BigMapEntry *nxt;
261
262 nxt = me.bme;
263 while (NULL != (bme = nxt))
264 {
265 nxt = bme->next;
266 GNUNET_free (bme);
267 }
268 me.bme = NULL;
269 }
270 }
271 GNUNET_free (map->map);
272 GNUNET_free (map);
268} 273}
269 274
270 275
@@ -276,11 +281,11 @@ GNUNET_CONTAINER_multihashmap_destroy(
276 * @return offset into the "map" array of "map" 281 * @return offset into the "map" array of "map"
277 */ 282 */
278static unsigned int 283static unsigned int
279idx_of(const struct GNUNET_CONTAINER_MultiHashMap *map, 284idx_of (const struct GNUNET_CONTAINER_MultiHashMap *map,
280 const struct GNUNET_HashCode *key) 285 const struct GNUNET_HashCode *key)
281{ 286{
282 GNUNET_assert(map != NULL); 287 GNUNET_assert (map != NULL);
283 return (*(unsigned int *)key) % map->map_length; 288 return (*(unsigned int *) key) % map->map_length;
284} 289}
285 290
286 291
@@ -291,7 +296,7 @@ idx_of(const struct GNUNET_CONTAINER_MultiHashMap *map,
291 * @return the number of key value pairs 296 * @return the number of key value pairs
292 */ 297 */
293unsigned int 298unsigned int
294GNUNET_CONTAINER_multihashmap_size( 299GNUNET_CONTAINER_multihashmap_size (
295 const struct GNUNET_CONTAINER_MultiHashMap *map) 300 const struct GNUNET_CONTAINER_MultiHashMap *map)
296{ 301{
297 return map->size; 302 return map->size;
@@ -309,29 +314,29 @@ GNUNET_CONTAINER_multihashmap_size(
309 * key-value pairs with value NULL 314 * key-value pairs with value NULL
310 */ 315 */
311void * 316void *
312GNUNET_CONTAINER_multihashmap_get( 317GNUNET_CONTAINER_multihashmap_get (
313 const struct GNUNET_CONTAINER_MultiHashMap *map, 318 const struct GNUNET_CONTAINER_MultiHashMap *map,
314 const struct GNUNET_HashCode *key) 319 const struct GNUNET_HashCode *key)
315{ 320{
316 union MapEntry me; 321 union MapEntry me;
317 322
318 me = map->map[idx_of(map, key)]; 323 me = map->map[idx_of (map, key)];
319 if (map->use_small_entries) 324 if (map->use_small_entries)
320 { 325 {
321 struct SmallMapEntry *sme; 326 struct SmallMapEntry *sme;
322 327
323 for (sme = me.sme; NULL != sme; sme = sme->next) 328 for (sme = me.sme; NULL != sme; sme = sme->next)
324 if (0 == GNUNET_memcmp(key, sme->key)) 329 if (0 == GNUNET_memcmp (key, sme->key))
325 return sme->value; 330 return sme->value;
326 } 331 }
327 else 332 else
328 { 333 {
329 struct BigMapEntry *bme; 334 struct BigMapEntry *bme;
330 335
331 for (bme = me.bme; NULL != bme; bme = bme->next) 336 for (bme = me.bme; NULL != bme; bme = bme->next)
332 if (0 == GNUNET_memcmp(key, &bme->key)) 337 if (0 == GNUNET_memcmp (key, &bme->key))
333 return bme->value; 338 return bme->value;
334 } 339 }
335 return NULL; 340 return NULL;
336} 341}
337 342
@@ -346,7 +351,7 @@ GNUNET_CONTAINER_multihashmap_get(
346 * #GNUNET_SYSERR if it aborted iteration 351 * #GNUNET_SYSERR if it aborted iteration
347 */ 352 */
348int 353int
349GNUNET_CONTAINER_multihashmap_iterate( 354GNUNET_CONTAINER_multihashmap_iterate (
350 struct GNUNET_CONTAINER_MultiHashMap *map, 355 struct GNUNET_CONTAINER_MultiHashMap *map,
351 GNUNET_CONTAINER_MulitHashMapIteratorCallback it, 356 GNUNET_CONTAINER_MulitHashMapIteratorCallback it,
352 void *it_cls) 357 void *it_cls)
@@ -356,54 +361,54 @@ GNUNET_CONTAINER_multihashmap_iterate(
356 union MapEntry *ce; 361 union MapEntry *ce;
357 struct GNUNET_HashCode kc; 362 struct GNUNET_HashCode kc;
358 363
359 GNUNET_assert(NULL != map); 364 GNUNET_assert (NULL != map);
360 ce = &map->next_cache[map->next_cache_off]; 365 ce = &map->next_cache[map->next_cache_off];
361 GNUNET_assert(++map->next_cache_off < NEXT_CACHE_SIZE); 366 GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE);
362 count = 0; 367 count = 0;
363 for (unsigned i = 0; i < map->map_length; i++) 368 for (unsigned i = 0; i < map->map_length; i++)
369 {
370 me = map->map[i];
371 if (map->use_small_entries)
364 { 372 {
365 me = map->map[i]; 373 struct SmallMapEntry *sme;
366 if (map->use_small_entries) 374
375 ce->sme = me.sme;
376 while (NULL != (sme = ce->sme))
377 {
378 ce->sme = sme->next;
379 if (NULL != it)
367 { 380 {
368 struct SmallMapEntry *sme; 381 if (GNUNET_OK != it (it_cls, sme->key, sme->value))
369 382 {
370 ce->sme = me.sme; 383 GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE);
371 while (NULL != (sme = ce->sme)) 384 return GNUNET_SYSERR;
372 { 385 }
373 ce->sme = sme->next;
374 if (NULL != it)
375 {
376 if (GNUNET_OK != it(it_cls, sme->key, sme->value))
377 {
378 GNUNET_assert(--map->next_cache_off < NEXT_CACHE_SIZE);
379 return GNUNET_SYSERR;
380 }
381 }
382 count++;
383 }
384 } 386 }
385 else 387 count++;
388 }
389 }
390 else
391 {
392 struct BigMapEntry *bme;
393
394 ce->bme = me.bme;
395 while (NULL != (bme = ce->bme))
396 {
397 ce->bme = bme->next;
398 if (NULL != it)
386 { 399 {
387 struct BigMapEntry *bme; 400 kc = bme->key;
388 401 if (GNUNET_OK != it (it_cls, &kc, bme->value))
389 ce->bme = me.bme; 402 {
390 while (NULL != (bme = ce->bme)) 403 GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE);
391 { 404 return GNUNET_SYSERR;
392 ce->bme = bme->next; 405 }
393 if (NULL != it)
394 {
395 kc = bme->key;
396 if (GNUNET_OK != it(it_cls, &kc, bme->value))
397 {
398 GNUNET_assert(--map->next_cache_off < NEXT_CACHE_SIZE);
399 return GNUNET_SYSERR;
400 }
401 }
402 count++;
403 }
404 } 406 }
407 count++;
408 }
405 } 409 }
406 GNUNET_assert(--map->next_cache_off < NEXT_CACHE_SIZE); 410 }
411 GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE);
407 return count; 412 return count;
408} 413}
409 414
@@ -416,8 +421,8 @@ GNUNET_CONTAINER_multihashmap_iterate(
416 * @param bme the entry that is about to be free'd 421 * @param bme the entry that is about to be free'd
417 */ 422 */
418static void 423static void
419update_next_cache_bme(struct GNUNET_CONTAINER_MultiHashMap *map, 424update_next_cache_bme (struct GNUNET_CONTAINER_MultiHashMap *map,
420 const struct BigMapEntry *bme) 425 const struct BigMapEntry *bme)
421{ 426{
422 for (unsigned int i = 0; i < map->next_cache_off; i++) 427 for (unsigned int i = 0; i < map->next_cache_off; i++)
423 if (map->next_cache[i].bme == bme) 428 if (map->next_cache[i].bme == bme)
@@ -433,8 +438,8 @@ update_next_cache_bme(struct GNUNET_CONTAINER_MultiHashMap *map,
433 * @param sme the entry that is about to be free'd 438 * @param sme the entry that is about to be free'd
434 */ 439 */
435static void 440static void
436update_next_cache_sme(struct GNUNET_CONTAINER_MultiHashMap *map, 441update_next_cache_sme (struct GNUNET_CONTAINER_MultiHashMap *map,
437 const struct SmallMapEntry *sme) 442 const struct SmallMapEntry *sme)
438{ 443{
439 for (unsigned int i = 0; i < map->next_cache_off; i++) 444 for (unsigned int i = 0; i < map->next_cache_off; i++)
440 if (map->next_cache[i].sme == sme) 445 if (map->next_cache[i].sme == sme)
@@ -454,59 +459,59 @@ update_next_cache_sme(struct GNUNET_CONTAINER_MultiHashMap *map,
454 * is not in the map 459 * is not in the map
455 */ 460 */
456int 461int
457GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, 462GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map,
458 const struct GNUNET_HashCode *key, 463 const struct GNUNET_HashCode *key,
459 const void *value) 464 const void *value)
460{ 465{
461 union MapEntry me; 466 union MapEntry me;
462 unsigned int i; 467 unsigned int i;
463 468
464 map->modification_counter++; 469 map->modification_counter++;
465 470
466 i = idx_of(map, key); 471 i = idx_of (map, key);
467 me = map->map[i]; 472 me = map->map[i];
468 if (map->use_small_entries) 473 if (map->use_small_entries)
469 { 474 {
470 struct SmallMapEntry *p; 475 struct SmallMapEntry *p;
471 476
472 p = NULL; 477 p = NULL;
473 for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) 478 for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
474 { 479 {
475 if ((0 == GNUNET_memcmp(key, sme->key)) && (value == sme->value)) 480 if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
476 { 481 {
477 if (NULL == p) 482 if (NULL == p)
478 map->map[i].sme = sme->next; 483 map->map[i].sme = sme->next;
479 else 484 else
480 p->next = sme->next; 485 p->next = sme->next;
481 update_next_cache_sme(map, sme); 486 update_next_cache_sme (map, sme);
482 GNUNET_free(sme); 487 GNUNET_free (sme);
483 map->size--; 488 map->size--;
484 return GNUNET_YES; 489 return GNUNET_YES;
485 } 490 }
486 p = sme; 491 p = sme;
487 }
488 } 492 }
493 }
489 else 494 else
490 { 495 {
491 struct BigMapEntry *p; 496 struct BigMapEntry *p;
492 497
493 p = NULL; 498 p = NULL;
494 for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) 499 for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
495 { 500 {
496 if ((0 == GNUNET_memcmp(key, &bme->key)) && (value == bme->value)) 501 if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
497 { 502 {
498 if (NULL == p) 503 if (NULL == p)
499 map->map[i].bme = bme->next; 504 map->map[i].bme = bme->next;
500 else 505 else
501 p->next = bme->next; 506 p->next = bme->next;
502 update_next_cache_bme(map, bme); 507 update_next_cache_bme (map, bme);
503 GNUNET_free(bme); 508 GNUNET_free (bme);
504 map->size--; 509 map->size--;
505 return GNUNET_YES; 510 return GNUNET_YES;
506 } 511 }
507 p = bme; 512 p = bme;
508 }
509 } 513 }
514 }
510 return GNUNET_NO; 515 return GNUNET_NO;
511} 516}
512 517
@@ -520,7 +525,7 @@ GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map,
520 * @return number of values removed 525 * @return number of values removed
521 */ 526 */
522int 527int
523GNUNET_CONTAINER_multihashmap_remove_all( 528GNUNET_CONTAINER_multihashmap_remove_all (
524 struct GNUNET_CONTAINER_MultiHashMap *map, 529 struct GNUNET_CONTAINER_MultiHashMap *map,
525 const struct GNUNET_HashCode *key) 530 const struct GNUNET_HashCode *key)
526{ 531{
@@ -531,70 +536,70 @@ GNUNET_CONTAINER_multihashmap_remove_all(
531 map->modification_counter++; 536 map->modification_counter++;
532 537
533 ret = 0; 538 ret = 0;
534 i = idx_of(map, key); 539 i = idx_of (map, key);
535 me = map->map[i]; 540 me = map->map[i];
536 if (map->use_small_entries) 541 if (map->use_small_entries)
537 { 542 {
538 struct SmallMapEntry *sme; 543 struct SmallMapEntry *sme;
539 struct SmallMapEntry *p; 544 struct SmallMapEntry *p;
540 545
541 p = NULL; 546 p = NULL;
542 sme = me.sme; 547 sme = me.sme;
543 while (NULL != sme) 548 while (NULL != sme)
544 { 549 {
545 if (0 == GNUNET_memcmp(key, sme->key)) 550 if (0 == GNUNET_memcmp (key, sme->key))
546 { 551 {
547 if (NULL == p) 552 if (NULL == p)
548 map->map[i].sme = sme->next; 553 map->map[i].sme = sme->next;
549 else 554 else
550 p->next = sme->next; 555 p->next = sme->next;
551 update_next_cache_sme(map, sme); 556 update_next_cache_sme (map, sme);
552 GNUNET_free(sme); 557 GNUNET_free (sme);
553 map->size--; 558 map->size--;
554 if (NULL == p) 559 if (NULL == p)
555 sme = map->map[i].sme; 560 sme = map->map[i].sme;
556 else 561 else
557 sme = p->next; 562 sme = p->next;
558 ret++; 563 ret++;
559 } 564 }
560 else 565 else
561 { 566 {
562 p = sme; 567 p = sme;
563 sme = sme->next; 568 sme = sme->next;
564 } 569 }
565 }
566 } 570 }
571 }
567 else 572 else
568 { 573 {
569 struct BigMapEntry *bme; 574 struct BigMapEntry *bme;
570 struct BigMapEntry *p; 575 struct BigMapEntry *p;
571 576
572 p = NULL; 577 p = NULL;
573 bme = me.bme; 578 bme = me.bme;
574 while (NULL != bme) 579 while (NULL != bme)
575 { 580 {
576 if (0 == GNUNET_memcmp(key, &bme->key)) 581 if (0 == GNUNET_memcmp (key, &bme->key))
577 { 582 {
578 if (NULL == p) 583 if (NULL == p)
579 map->map[i].bme = bme->next; 584 map->map[i].bme = bme->next;
580 else 585 else
581 p->next = bme->next; 586 p->next = bme->next;
582 update_next_cache_bme(map, bme); 587 update_next_cache_bme (map, bme);
583 GNUNET_free(bme); 588 GNUNET_free (bme);
584 map->size--; 589 map->size--;
585 if (NULL == p) 590 if (NULL == p)
586 bme = map->map[i].bme; 591 bme = map->map[i].bme;
587 else 592 else
588 bme = p->next; 593 bme = p->next;
589 ret++; 594 ret++;
590 } 595 }
591 else 596 else
592 { 597 {
593 p = bme; 598 p = bme;
594 bme = bme->next; 599 bme = bme->next;
595 } 600 }
596 }
597 } 601 }
602 }
598 return ret; 603 return ret;
599} 604}
600 605
@@ -608,12 +613,12 @@ GNUNET_CONTAINER_multihashmap_remove_all(
608 * @return #GNUNET_OK (continue to iterate) 613 * @return #GNUNET_OK (continue to iterate)
609 */ 614 */
610static int 615static int
611remove_all(void *cls, const struct GNUNET_HashCode *key, void *value) 616remove_all (void *cls, const struct GNUNET_HashCode *key, void *value)
612{ 617{
613 struct GNUNET_CONTAINER_MultiHashMap *map = cls; 618 struct GNUNET_CONTAINER_MultiHashMap *map = cls;
614 619
615 GNUNET_assert(GNUNET_YES == 620 GNUNET_assert (GNUNET_YES ==
616 GNUNET_CONTAINER_multihashmap_remove(map, key, value)); 621 GNUNET_CONTAINER_multihashmap_remove (map, key, value));
617 return GNUNET_OK; 622 return GNUNET_OK;
618} 623}
619 624
@@ -627,12 +632,12 @@ remove_all(void *cls, const struct GNUNET_HashCode *key, void *value)
627 * @return number of values removed 632 * @return number of values removed
628 */ 633 */
629unsigned int 634unsigned int
630GNUNET_CONTAINER_multihashmap_clear(struct GNUNET_CONTAINER_MultiHashMap *map) 635GNUNET_CONTAINER_multihashmap_clear (struct GNUNET_CONTAINER_MultiHashMap *map)
631{ 636{
632 unsigned int ret; 637 unsigned int ret;
633 638
634 ret = map->size; 639 ret = map->size;
635 GNUNET_CONTAINER_multihashmap_iterate(map, &remove_all, map); 640 GNUNET_CONTAINER_multihashmap_iterate (map, &remove_all, map);
636 return ret; 641 return ret;
637} 642}
638 643
@@ -647,29 +652,29 @@ GNUNET_CONTAINER_multihashmap_clear(struct GNUNET_CONTAINER_MultiHashMap *map)
647 * #GNUNET_NO if not 652 * #GNUNET_NO if not
648 */ 653 */
649int 654int
650GNUNET_CONTAINER_multihashmap_contains( 655GNUNET_CONTAINER_multihashmap_contains (
651 const struct GNUNET_CONTAINER_MultiHashMap *map, 656 const struct GNUNET_CONTAINER_MultiHashMap *map,
652 const struct GNUNET_HashCode *key) 657 const struct GNUNET_HashCode *key)
653{ 658{
654 union MapEntry me; 659 union MapEntry me;
655 660
656 me = map->map[idx_of(map, key)]; 661 me = map->map[idx_of (map, key)];
657 if (map->use_small_entries) 662 if (map->use_small_entries)
658 { 663 {
659 struct SmallMapEntry *sme; 664 struct SmallMapEntry *sme;
660 665
661 for (sme = me.sme; NULL != sme; sme = sme->next) 666 for (sme = me.sme; NULL != sme; sme = sme->next)
662 if (0 == GNUNET_memcmp(key, sme->key)) 667 if (0 == GNUNET_memcmp (key, sme->key))
663 return GNUNET_YES; 668 return GNUNET_YES;
664 } 669 }
665 else 670 else
666 { 671 {
667 struct BigMapEntry *bme; 672 struct BigMapEntry *bme;
668 673
669 for (bme = me.bme; NULL != bme; bme = bme->next) 674 for (bme = me.bme; NULL != bme; bme = bme->next)
670 if (0 == GNUNET_memcmp(key, &bme->key)) 675 if (0 == GNUNET_memcmp (key, &bme->key))
671 return GNUNET_YES; 676 return GNUNET_YES;
672 } 677 }
673 return GNUNET_NO; 678 return GNUNET_NO;
674} 679}
675 680
@@ -685,30 +690,30 @@ GNUNET_CONTAINER_multihashmap_contains(
685 * #GNUNET_NO if not 690 * #GNUNET_NO if not
686 */ 691 */
687int 692int
688GNUNET_CONTAINER_multihashmap_contains_value( 693GNUNET_CONTAINER_multihashmap_contains_value (
689 const struct GNUNET_CONTAINER_MultiHashMap *map, 694 const struct GNUNET_CONTAINER_MultiHashMap *map,
690 const struct GNUNET_HashCode *key, 695 const struct GNUNET_HashCode *key,
691 const void *value) 696 const void *value)
692{ 697{
693 union MapEntry me; 698 union MapEntry me;
694 699
695 me = map->map[idx_of(map, key)]; 700 me = map->map[idx_of (map, key)];
696 if (map->use_small_entries) 701 if (map->use_small_entries)
697 { 702 {
698 struct SmallMapEntry *sme; 703 struct SmallMapEntry *sme;
699 704
700 for (sme = me.sme; NULL != sme; sme = sme->next) 705 for (sme = me.sme; NULL != sme; sme = sme->next)
701 if ((0 == GNUNET_memcmp(key, sme->key)) && (sme->value == value)) 706 if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
702 return GNUNET_YES; 707 return GNUNET_YES;
703 } 708 }
704 else 709 else
705 { 710 {
706 struct BigMapEntry *bme; 711 struct BigMapEntry *bme;
707 712
708 for (bme = me.bme; NULL != bme; bme = bme->next) 713 for (bme = me.bme; NULL != bme; bme = bme->next)
709 if ((0 == GNUNET_memcmp(key, &bme->key)) && (bme->value == value)) 714 if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
710 return GNUNET_YES; 715 return GNUNET_YES;
711 } 716 }
712 return GNUNET_NO; 717 return GNUNET_NO;
713} 718}
714 719
@@ -719,7 +724,7 @@ GNUNET_CONTAINER_multihashmap_contains_value(
719 * @param map the hash map to grow 724 * @param map the hash map to grow
720 */ 725 */
721static void 726static void
722grow(struct GNUNET_CONTAINER_MultiHashMap *map) 727grow (struct GNUNET_CONTAINER_MultiHashMap *map)
723{ 728{
724 union MapEntry *old_map; 729 union MapEntry *old_map;
725 union MapEntry *new_map; 730 union MapEntry *new_map;
@@ -729,46 +734,46 @@ grow(struct GNUNET_CONTAINER_MultiHashMap *map)
729 734
730 old_map = map->map; 735 old_map = map->map;
731 old_len = map->map_length; 736 old_len = map->map_length;
732 GNUNET_assert(0 != old_len); 737 GNUNET_assert (0 != old_len);
733 new_len = old_len * 2; 738 new_len = old_len * 2;
734 if (0 == new_len) /* 2^31 * 2 == 0 */ 739 if (0 == new_len) /* 2^31 * 2 == 0 */
735 new_len = old_len; /* never use 0 */ 740 new_len = old_len; /* never use 0 */
736 if (new_len == old_len) 741 if (new_len == old_len)
737 return; /* nothing changed */ 742 return; /* nothing changed */
738 new_map = GNUNET_malloc_large(new_len * sizeof(union MapEntry)); 743 new_map = GNUNET_malloc_large (new_len * sizeof(union MapEntry));
739 if (NULL == new_map) 744 if (NULL == new_map)
740 return; /* grow not possible */ 745 return; /* grow not possible */
741 map->modification_counter++; 746 map->modification_counter++;
742 map->map_length = new_len; 747 map->map_length = new_len;
743 map->map = new_map; 748 map->map = new_map;
744 for (unsigned int i = 0; i < old_len; i++) 749 for (unsigned int i = 0; i < old_len; i++)
750 {
751 if (map->use_small_entries)
745 { 752 {
746 if (map->use_small_entries) 753 struct SmallMapEntry *sme;
747 { 754
748 struct SmallMapEntry *sme; 755 while (NULL != (sme = old_map[i].sme))
749 756 {
750 while (NULL != (sme = old_map[i].sme)) 757 old_map[i].sme = sme->next;
751 { 758 idx = idx_of (map, sme->key);
752 old_map[i].sme = sme->next; 759 sme->next = new_map[idx].sme;
753 idx = idx_of(map, sme->key); 760 new_map[idx].sme = sme;
754 sme->next = new_map[idx].sme; 761 }
755 new_map[idx].sme = sme; 762 }
756 } 763 else
757 } 764 {
758 else 765 struct BigMapEntry *bme;
759 { 766
760 struct BigMapEntry *bme; 767 while (NULL != (bme = old_map[i].bme))
761 768 {
762 while (NULL != (bme = old_map[i].bme)) 769 old_map[i].bme = bme->next;
763 { 770 idx = idx_of (map, &bme->key);
764 old_map[i].bme = bme->next; 771 bme->next = new_map[idx].bme;
765 idx = idx_of(map, &bme->key); 772 new_map[idx].bme = bme;
766 bme->next = new_map[idx].bme; 773 }
767 new_map[idx].bme = bme;
768 }
769 }
770 } 774 }
771 GNUNET_free(old_map); 775 }
776 GNUNET_free (old_map);
772} 777}
773 778
774 779
@@ -785,71 +790,71 @@ grow(struct GNUNET_CONTAINER_MultiHashMap *map)
785 * value already exists 790 * value already exists
786 */ 791 */
787int 792int
788GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, 793GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map,
789 const struct GNUNET_HashCode *key, 794 const struct GNUNET_HashCode *key,
790 void *value, 795 void *value,
791 enum GNUNET_CONTAINER_MultiHashMapOption opt) 796 enum GNUNET_CONTAINER_MultiHashMapOption opt)
792{ 797{
793 union MapEntry me; 798 union MapEntry me;
794 unsigned int i; 799 unsigned int i;
795 800
796 i = idx_of(map, key); 801 i = idx_of (map, key);
797 if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) && 802 if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) &&
798 (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 803 (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
804 {
805 me = map->map[i];
806 if (map->use_small_entries)
799 { 807 {
800 me = map->map[i]; 808 struct SmallMapEntry *sme;
801 if (map->use_small_entries) 809
810 for (sme = me.sme; NULL != sme; sme = sme->next)
811 if (0 == GNUNET_memcmp (key, sme->key))
802 { 812 {
803 struct SmallMapEntry *sme; 813 if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
804 814 return GNUNET_SYSERR;
805 for (sme = me.sme; NULL != sme; sme = sme->next) 815 sme->value = value;
806 if (0 == GNUNET_memcmp(key, sme->key)) 816 return GNUNET_NO;
807 {
808 if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
809 return GNUNET_SYSERR;
810 sme->value = value;
811 return GNUNET_NO;
812 }
813 } 817 }
814 else 818 }
819 else
820 {
821 struct BigMapEntry *bme;
822
823 for (bme = me.bme; NULL != bme; bme = bme->next)
824 if (0 == GNUNET_memcmp (key, &bme->key))
815 { 825 {
816 struct BigMapEntry *bme; 826 if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
817 827 return GNUNET_SYSERR;
818 for (bme = me.bme; NULL != bme; bme = bme->next) 828 bme->value = value;
819 if (0 == GNUNET_memcmp(key, &bme->key)) 829 return GNUNET_NO;
820 {
821 if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)
822 return GNUNET_SYSERR;
823 bme->value = value;
824 return GNUNET_NO;
825 }
826 } 830 }
827 } 831 }
832 }
828 if (map->size / 3 >= map->map_length / 4) 833 if (map->size / 3 >= map->map_length / 4)
829 { 834 {
830 grow(map); 835 grow (map);
831 i = idx_of(map, key); 836 i = idx_of (map, key);
832 } 837 }
833 if (map->use_small_entries) 838 if (map->use_small_entries)
834 { 839 {
835 struct SmallMapEntry *sme; 840 struct SmallMapEntry *sme;
836 841
837 sme = GNUNET_new(struct SmallMapEntry); 842 sme = GNUNET_new (struct SmallMapEntry);
838 sme->key = key; 843 sme->key = key;
839 sme->value = value; 844 sme->value = value;
840 sme->next = map->map[i].sme; 845 sme->next = map->map[i].sme;
841 map->map[i].sme = sme; 846 map->map[i].sme = sme;
842 } 847 }
843 else 848 else
844 { 849 {
845 struct BigMapEntry *bme; 850 struct BigMapEntry *bme;
846 851
847 bme = GNUNET_new(struct BigMapEntry); 852 bme = GNUNET_new (struct BigMapEntry);
848 bme->key = *key; 853 bme->key = *key;
849 bme->value = value; 854 bme->value = value;
850 bme->next = map->map[i].bme; 855 bme->next = map->map[i].bme;
851 map->map[i].bme = bme; 856 map->map[i].bme = bme;
852 } 857 }
853 map->size++; 858 map->size++;
854 return GNUNET_OK; 859 return GNUNET_OK;
855} 860}
@@ -866,7 +871,7 @@ GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map,
866 * #GNUNET_SYSERR if it aborted iteration 871 * #GNUNET_SYSERR if it aborted iteration
867 */ 872 */
868int 873int
869GNUNET_CONTAINER_multihashmap_get_multiple( 874GNUNET_CONTAINER_multihashmap_get_multiple (
870 struct GNUNET_CONTAINER_MultiHashMap *map, 875 struct GNUNET_CONTAINER_MultiHashMap *map,
871 const struct GNUNET_HashCode *key, 876 const struct GNUNET_HashCode *key,
872 GNUNET_CONTAINER_MulitHashMapIteratorCallback it, 877 GNUNET_CONTAINER_MulitHashMapIteratorCallback it,
@@ -877,46 +882,46 @@ GNUNET_CONTAINER_multihashmap_get_multiple(
877 union MapEntry *ce; 882 union MapEntry *ce;
878 883
879 ce = &map->next_cache[map->next_cache_off]; 884 ce = &map->next_cache[map->next_cache_off];
880 GNUNET_assert(++map->next_cache_off < NEXT_CACHE_SIZE); 885 GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE);
881 count = 0; 886 count = 0;
882 me = &map->map[idx_of(map, key)]; 887 me = &map->map[idx_of (map, key)];
883 if (map->use_small_entries) 888 if (map->use_small_entries)
884 { 889 {
885 struct SmallMapEntry *sme; 890 struct SmallMapEntry *sme;
886 891
887 ce->sme = me->sme; 892 ce->sme = me->sme;
888 while (NULL != (sme = ce->sme)) 893 while (NULL != (sme = ce->sme))
889 { 894 {
890 ce->sme = sme->next; 895 ce->sme = sme->next;
891 if (0 != GNUNET_memcmp(key, sme->key)) 896 if (0 != GNUNET_memcmp (key, sme->key))
892 continue; 897 continue;
893 if ((NULL != it) && (GNUNET_OK != it(it_cls, key, sme->value))) 898 if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
894 { 899 {
895 GNUNET_assert(--map->next_cache_off < NEXT_CACHE_SIZE); 900 GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE);
896 return GNUNET_SYSERR; 901 return GNUNET_SYSERR;
897 } 902 }
898 count++; 903 count++;
899 }
900 } 904 }
905 }
901 else 906 else
902 { 907 {
903 struct BigMapEntry *bme; 908 struct BigMapEntry *bme;
904 909
905 ce->bme = me->bme; 910 ce->bme = me->bme;
906 while (NULL != (bme = ce->bme)) 911 while (NULL != (bme = ce->bme))
907 { 912 {
908 ce->bme = bme->next; 913 ce->bme = bme->next;
909 if (0 != GNUNET_memcmp(key, &bme->key)) 914 if (0 != GNUNET_memcmp (key, &bme->key))
910 continue; 915 continue;
911 if ((NULL != it) && (GNUNET_OK != it(it_cls, key, bme->value))) 916 if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
912 { 917 {
913 GNUNET_assert(--map->next_cache_off < NEXT_CACHE_SIZE); 918 GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE);
914 return GNUNET_SYSERR; 919 return GNUNET_SYSERR;
915 } 920 }
916 count++; 921 count++;
917 }
918 } 922 }
919 GNUNET_assert(--map->next_cache_off < NEXT_CACHE_SIZE); 923 }
924 GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE);
920 return count; 925 return count;
921} 926}
922 927
@@ -933,7 +938,7 @@ GNUNET_CONTAINER_multihashmap_get_multiple(
933 * @return the number of key value pairs processed, zero or one. 938 * @return the number of key value pairs processed, zero or one.
934 */ 939 */
935unsigned int 940unsigned int
936GNUNET_CONTAINER_multihashmap_get_random( 941GNUNET_CONTAINER_multihashmap_get_random (
937 const struct GNUNET_CONTAINER_MultiHashMap *map, 942 const struct GNUNET_CONTAINER_MultiHashMap *map,
938 GNUNET_CONTAINER_MulitHashMapIteratorCallback it, 943 GNUNET_CONTAINER_MulitHashMapIteratorCallback it,
939 void *it_cls) 944 void *it_cls)
@@ -946,48 +951,48 @@ GNUNET_CONTAINER_multihashmap_get_random(
946 return 0; 951 return 0;
947 if (NULL == it) 952 if (NULL == it)
948 return 1; 953 return 1;
949 off = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, map->size); 954 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, map->size);
950 for (idx = 0; idx < map->map_length; idx++) 955 for (idx = 0; idx < map->map_length; idx++)
956 {
957 me = map->map[idx];
958 if (map->use_small_entries)
951 { 959 {
952 me = map->map[idx]; 960 struct SmallMapEntry *sme;
953 if (map->use_small_entries) 961 struct SmallMapEntry *nxt;
962
963 nxt = me.sme;
964 while (NULL != (sme = nxt))
965 {
966 nxt = sme->next;
967 if (0 == off)
954 { 968 {
955 struct SmallMapEntry *sme; 969 if (GNUNET_OK != it (it_cls, sme->key, sme->value))
956 struct SmallMapEntry *nxt; 970 return GNUNET_SYSERR;
957 971 return 1;
958 nxt = me.sme;
959 while (NULL != (sme = nxt))
960 {
961 nxt = sme->next;
962 if (0 == off)
963 {
964 if (GNUNET_OK != it(it_cls, sme->key, sme->value))
965 return GNUNET_SYSERR;
966 return 1;
967 }
968 off--;
969 }
970 } 972 }
971 else 973 off--;
974 }
975 }
976 else
977 {
978 struct BigMapEntry *bme;
979 struct BigMapEntry *nxt;
980
981 nxt = me.bme;
982 while (NULL != (bme = nxt))
983 {
984 nxt = bme->next;
985 if (0 == off)
972 { 986 {
973 struct BigMapEntry *bme; 987 if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
974 struct BigMapEntry *nxt; 988 return GNUNET_SYSERR;
975 989 return 1;
976 nxt = me.bme;
977 while (NULL != (bme = nxt))
978 {
979 nxt = bme->next;
980 if (0 == off)
981 {
982 if (GNUNET_OK != it(it_cls, &bme->key, bme->value))
983 return GNUNET_SYSERR;
984 return 1;
985 }
986 off--;
987 }
988 } 990 }
991 off--;
992 }
989 } 993 }
990 GNUNET_break(0); 994 }
995 GNUNET_break (0);
991 return GNUNET_SYSERR; 996 return GNUNET_SYSERR;
992} 997}
993 998
@@ -1005,12 +1010,12 @@ GNUNET_CONTAINER_multihashmap_get_random(
1005 * @return an iterator over the given multihashmap 'map' 1010 * @return an iterator over the given multihashmap 'map'
1006 */ 1011 */
1007struct GNUNET_CONTAINER_MultiHashMapIterator * 1012struct GNUNET_CONTAINER_MultiHashMapIterator *
1008GNUNET_CONTAINER_multihashmap_iterator_create( 1013GNUNET_CONTAINER_multihashmap_iterator_create (
1009 const struct GNUNET_CONTAINER_MultiHashMap *map) 1014 const struct GNUNET_CONTAINER_MultiHashMap *map)
1010{ 1015{
1011 struct GNUNET_CONTAINER_MultiHashMapIterator *iter; 1016 struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
1012 1017
1013 iter = GNUNET_new(struct GNUNET_CONTAINER_MultiHashMapIterator); 1018 iter = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMapIterator);
1014 iter->map = map; 1019 iter->map = map;
1015 iter->modification_counter = map->modification_counter; 1020 iter->modification_counter = map->modification_counter;
1016 iter->me = map->map[0]; 1021 iter->me = map->map[0];
@@ -1033,47 +1038,47 @@ GNUNET_CONTAINER_multihashmap_iterator_create(
1033 * #GNUNET_NO if we are out of elements 1038 * #GNUNET_NO if we are out of elements
1034 */ 1039 */
1035int 1040int
1036GNUNET_CONTAINER_multihashmap_iterator_next( 1041GNUNET_CONTAINER_multihashmap_iterator_next (
1037 struct GNUNET_CONTAINER_MultiHashMapIterator *iter, 1042 struct GNUNET_CONTAINER_MultiHashMapIterator *iter,
1038 struct GNUNET_HashCode *key, 1043 struct GNUNET_HashCode *key,
1039 const void **value) 1044 const void **value)
1040{ 1045{
1041 /* make sure the map has not been modified */ 1046 /* make sure the map has not been modified */
1042 GNUNET_assert(iter->modification_counter == iter->map->modification_counter); 1047 GNUNET_assert (iter->modification_counter == iter->map->modification_counter);
1043 1048
1044 /* look for the next entry, skipping empty buckets */ 1049 /* look for the next entry, skipping empty buckets */
1045 while (1) 1050 while (1)
1051 {
1052 if (iter->idx >= iter->map->map_length)
1053 return GNUNET_NO;
1054 if (GNUNET_YES == iter->map->use_small_entries)
1046 { 1055 {
1047 if (iter->idx >= iter->map->map_length) 1056 if (NULL != iter->me.sme)
1048 return GNUNET_NO; 1057 {
1049 if (GNUNET_YES == iter->map->use_small_entries) 1058 if (NULL != key)
1050 { 1059 *key = *iter->me.sme->key;
1051 if (NULL != iter->me.sme) 1060 if (NULL != value)
1052 { 1061 *value = iter->me.sme->value;
1053 if (NULL != key) 1062 iter->me.sme = iter->me.sme->next;
1054 *key = *iter->me.sme->key; 1063 return GNUNET_YES;
1055 if (NULL != value) 1064 }
1056 *value = iter->me.sme->value; 1065 }
1057 iter->me.sme = iter->me.sme->next; 1066 else
1058 return GNUNET_YES; 1067 {
1059 } 1068 if (NULL != iter->me.bme)
1060 } 1069 {
1061 else 1070 if (NULL != key)
1062 { 1071 *key = iter->me.bme->key;
1063 if (NULL != iter->me.bme) 1072 if (NULL != value)
1064 { 1073 *value = iter->me.bme->value;
1065 if (NULL != key) 1074 iter->me.bme = iter->me.bme->next;
1066 *key = iter->me.bme->key; 1075 return GNUNET_YES;
1067 if (NULL != value) 1076 }
1068 *value = iter->me.bme->value;
1069 iter->me.bme = iter->me.bme->next;
1070 return GNUNET_YES;
1071 }
1072 }
1073 iter->idx += 1;
1074 if (iter->idx < iter->map->map_length)
1075 iter->me = iter->map->map[iter->idx];
1076 } 1077 }
1078 iter->idx += 1;
1079 if (iter->idx < iter->map->map_length)
1080 iter->me = iter->map->map[iter->idx];
1081 }
1077} 1082}
1078 1083
1079 1084
@@ -1083,10 +1088,10 @@ GNUNET_CONTAINER_multihashmap_iterator_next(
1083 * @param iter the iterator to destroy 1088 * @param iter the iterator to destroy
1084 */ 1089 */
1085void 1090void
1086GNUNET_CONTAINER_multihashmap_iterator_destroy( 1091GNUNET_CONTAINER_multihashmap_iterator_destroy (
1087 struct GNUNET_CONTAINER_MultiHashMapIterator *iter) 1092 struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
1088{ 1093{
1089 GNUNET_free(iter); 1094 GNUNET_free (iter);
1090} 1095}
1091 1096
1092 1097