diff options
Diffstat (limited to 'src/util/container_multishortmap.c')
-rw-r--r-- | src/util/container_multishortmap.c | 286 |
1 files changed, 183 insertions, 103 deletions
diff --git a/src/util/container_multishortmap.c b/src/util/container_multishortmap.c index f815b6238..050fd21f9 100644 --- a/src/util/container_multishortmap.c +++ b/src/util/container_multishortmap.c | |||
@@ -27,6 +27,15 @@ | |||
27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multishortmap", __VA_ARGS__) | 27 | #define LOG(kind,...) GNUNET_log_from (kind, "util-container-multishortmap", __VA_ARGS__) |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * Maximum recursion depth for callbacks of | ||
31 | * #GNUNET_CONTAINER_multihashmap_get_multiple() themselve s | ||
32 | * again calling #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
33 | * Should be totally excessive, but if violated we die. | ||
34 | */ | ||
35 | #define NEXT_CACHE_SIZE 16 | ||
36 | |||
37 | |||
38 | /** | ||
30 | * An entry in the hash map with the full key. | 39 | * An entry in the hash map with the full key. |
31 | */ | 40 | */ |
32 | struct BigMapEntry | 41 | struct BigMapEntry |
@@ -112,8 +121,8 @@ struct GNUNET_CONTAINER_MultiShortmap | |||
112 | unsigned int map_length; | 121 | unsigned int map_length; |
113 | 122 | ||
114 | /** | 123 | /** |
115 | * GNUNET_NO if the map entries are of type 'struct BigMapEntry', | 124 | * #GNUNET_NO if the map entries are of type 'struct BigMapEntry', |
116 | * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. | 125 | * #GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. |
117 | */ | 126 | */ |
118 | int use_small_entries; | 127 | int use_small_entries; |
119 | 128 | ||
@@ -122,6 +131,20 @@ struct GNUNET_CONTAINER_MultiShortmap | |||
122 | * to the map, so that iterators can check if they are still valid. | 131 | * to the map, so that iterators can check if they are still valid. |
123 | */ | 132 | */ |
124 | unsigned int modification_counter; | 133 | unsigned int modification_counter; |
134 | |||
135 | /** | ||
136 | * Map entries indicating iteration positions currently | ||
137 | * in use by #GNUNET_CONTAINER_multihashmap_get_multiple(). | ||
138 | * Only used up to @e next_cache_off. | ||
139 | */ | ||
140 | union MapEntry next_cache[NEXT_CACHE_SIZE]; | ||
141 | |||
142 | /** | ||
143 | * Offset of @e next_cache entries in use, must be smaller | ||
144 | * than #NEXT_CACHE_SIZE. | ||
145 | */ | ||
146 | unsigned int next_cache_off; | ||
147 | |||
125 | }; | 148 | }; |
126 | 149 | ||
127 | 150 | ||
@@ -177,7 +200,8 @@ GNUNET_CONTAINER_multishortmap_create (unsigned int len, | |||
177 | 200 | ||
178 | GNUNET_assert (len > 0); | 201 | GNUNET_assert (len > 0); |
179 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmap); | 202 | map = GNUNET_new (struct GNUNET_CONTAINER_MultiShortmap); |
180 | map->map = GNUNET_malloc (len * sizeof (union MapEntry)); | 203 | map->map = GNUNET_new_array (len, |
204 | union MapEntry); | ||
181 | map->map_length = len; | 205 | map->map_length = len; |
182 | map->use_small_entries = do_not_copy_keys; | 206 | map->use_small_entries = do_not_copy_keys; |
183 | return map; | 207 | return map; |
@@ -191,14 +215,13 @@ GNUNET_CONTAINER_multishortmap_create (unsigned int len, | |||
191 | * @param map the map | 215 | * @param map the map |
192 | */ | 216 | */ |
193 | void | 217 | void |
194 | GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap | 218 | GNUNET_CONTAINER_multishortmap_destroy (struct GNUNET_CONTAINER_MultiShortmap *map) |
195 | *map) | ||
196 | { | 219 | { |
197 | unsigned int i; | 220 | GNUNET_assert (0 == map->next_cache_off); |
198 | union MapEntry me; | 221 | for (unsigned int i = 0; i < map->map_length; i++) |
199 | |||
200 | for (i = 0; i < map->map_length; i++) | ||
201 | { | 222 | { |
223 | union MapEntry me; | ||
224 | |||
202 | me = map->map[i]; | 225 | me = map->map[i]; |
203 | if (map->use_small_entries) | 226 | if (map->use_small_entries) |
204 | { | 227 | { |
@@ -283,18 +306,18 @@ GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap | |||
283 | me = map->map[idx_of (map, key)]; | 306 | me = map->map[idx_of (map, key)]; |
284 | if (map->use_small_entries) | 307 | if (map->use_small_entries) |
285 | { | 308 | { |
286 | struct SmallMapEntry *sme; | 309 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
287 | 310 | if (0 == memcmp (key, | |
288 | for (sme = me.sme; NULL != sme; sme = sme->next) | 311 | sme->key, |
289 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 312 | sizeof (struct GNUNET_ShortHashCode))) |
290 | return sme->value; | 313 | return sme->value; |
291 | } | 314 | } |
292 | else | 315 | else |
293 | { | 316 | { |
294 | struct BigMapEntry *bme; | 317 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
295 | 318 | if (0 == memcmp (key, | |
296 | for (bme = me.bme; NULL != bme; bme = bme->next) | 319 | &bme->key, |
297 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 320 | sizeof (struct GNUNET_ShortHashCode))) |
298 | return bme->value; | 321 | return bme->value; |
299 | } | 322 | } |
300 | return NULL; | 323 | return NULL; |
@@ -311,33 +334,37 @@ GNUNET_CONTAINER_multishortmap_get (const struct GNUNET_CONTAINER_MultiShortmap | |||
311 | * #GNUNET_SYSERR if it aborted iteration | 334 | * #GNUNET_SYSERR if it aborted iteration |
312 | */ | 335 | */ |
313 | int | 336 | int |
314 | GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShortmap *map, | 337 | GNUNET_CONTAINER_multishortmap_iterate (struct GNUNET_CONTAINER_MultiShortmap *map, |
315 | GNUNET_CONTAINER_ShortmapIterator it, | 338 | GNUNET_CONTAINER_ShortmapIterator it, |
316 | void *it_cls) | 339 | void *it_cls) |
317 | { | 340 | { |
318 | int count; | 341 | int count; |
319 | unsigned int i; | ||
320 | union MapEntry me; | 342 | union MapEntry me; |
343 | union MapEntry *ce; | ||
321 | struct GNUNET_ShortHashCode kc; | 344 | struct GNUNET_ShortHashCode kc; |
322 | 345 | ||
323 | count = 0; | 346 | count = 0; |
324 | GNUNET_assert (NULL != map); | 347 | GNUNET_assert (NULL != map); |
325 | for (i = 0; i < map->map_length; i++) | 348 | ce = &map->next_cache[map->next_cache_off]; |
349 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
350 | for (unsigned int i = 0; i < map->map_length; i++) | ||
326 | { | 351 | { |
327 | me = map->map[i]; | 352 | me = map->map[i]; |
328 | if (map->use_small_entries) | 353 | if (map->use_small_entries) |
329 | { | 354 | { |
330 | struct SmallMapEntry *sme; | 355 | struct SmallMapEntry *sme; |
331 | struct SmallMapEntry *nxt; | 356 | |
332 | 357 | ce->sme = me.sme; | |
333 | nxt = me.sme; | 358 | while (NULL != (sme = ce->sme)) |
334 | while (NULL != (sme = nxt)) | ||
335 | { | 359 | { |
336 | nxt = sme->next; | 360 | ce->sme = sme->next; |
337 | if (NULL != it) | 361 | if ( (NULL != it) && |
362 | (GNUNET_OK != it (it_cls, | ||
363 | sme->key, | ||
364 | sme->value)) ) | ||
338 | { | 365 | { |
339 | if (GNUNET_OK != it (it_cls, sme->key, sme->value)) | 366 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); |
340 | return GNUNET_SYSERR; | 367 | return GNUNET_SYSERR; |
341 | } | 368 | } |
342 | count++; | 369 | count++; |
343 | } | 370 | } |
@@ -345,27 +372,66 @@ GNUNET_CONTAINER_multishortmap_iterate (const struct GNUNET_CONTAINER_MultiShort | |||
345 | else | 372 | else |
346 | { | 373 | { |
347 | struct BigMapEntry *bme; | 374 | struct BigMapEntry *bme; |
348 | struct BigMapEntry *nxt; | ||
349 | 375 | ||
350 | nxt = me.bme; | 376 | ce->bme = me.bme; |
351 | while (NULL != (bme = nxt)) | 377 | while (NULL != (bme = ce->bme)) |
352 | { | 378 | { |
353 | nxt = bme->next; | 379 | ce->bme = bme->next; |
354 | if (NULL != it) | 380 | if (NULL != it) |
355 | { | 381 | { |
356 | kc = bme->key; | 382 | kc = bme->key; |
357 | if (GNUNET_OK != it (it_cls, &kc, bme->value)) | 383 | if (GNUNET_OK != it (it_cls, |
384 | &kc, | ||
385 | bme->value)) | ||
386 | { | ||
387 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
358 | return GNUNET_SYSERR; | 388 | return GNUNET_SYSERR; |
389 | } | ||
359 | } | 390 | } |
360 | count++; | 391 | count++; |
361 | } | 392 | } |
362 | } | 393 | } |
363 | } | 394 | } |
395 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
364 | return count; | 396 | return count; |
365 | } | 397 | } |
366 | 398 | ||
367 | 399 | ||
368 | /** | 400 | /** |
401 | * We are about to free() the @a bme, make sure it is not in | ||
402 | * the list of next values for any iterator in the @a map's next_cache. | ||
403 | * | ||
404 | * @param map the map to check | ||
405 | * @param bme the entry that is about to be free'd | ||
406 | */ | ||
407 | static void | ||
408 | update_next_cache_bme (struct GNUNET_CONTAINER_MultiShortmap *map, | ||
409 | const struct BigMapEntry *bme) | ||
410 | { | ||
411 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
412 | if (map->next_cache[i].bme == bme) | ||
413 | map->next_cache[i].bme = bme->next; | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * We are about to free() the @a sme, make sure it is not in | ||
419 | * the list of next values for any iterator in the @a map's next_cache. | ||
420 | * | ||
421 | * @param map the map to check | ||
422 | * @param sme the entry that is about to be free'd | ||
423 | */ | ||
424 | static void | ||
425 | update_next_cache_sme (struct GNUNET_CONTAINER_MultiShortmap *map, | ||
426 | const struct SmallMapEntry *sme) | ||
427 | { | ||
428 | for (unsigned int i=0;i<map->next_cache_off;i++) | ||
429 | if (map->next_cache[i].sme == sme) | ||
430 | map->next_cache[i].sme = sme->next; | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
369 | * Remove the given key-value pair from the map. Note that if the | 435 | * Remove the given key-value pair from the map. Note that if the |
370 | * key-value pair is in the map multiple times, only one of the pairs | 436 | * key-value pair is in the map multiple times, only one of the pairs |
371 | * will be removed. | 437 | * will be removed. |
@@ -385,24 +451,25 @@ GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *ma | |||
385 | unsigned int i; | 451 | unsigned int i; |
386 | 452 | ||
387 | map->modification_counter++; | 453 | map->modification_counter++; |
388 | |||
389 | i = idx_of (map, key); | 454 | i = idx_of (map, key); |
390 | me = map->map[i]; | 455 | me = map->map[i]; |
391 | if (map->use_small_entries) | 456 | if (map->use_small_entries) |
392 | { | 457 | { |
393 | struct SmallMapEntry *sme; | 458 | struct SmallMapEntry *p = NULL; |
394 | struct SmallMapEntry *p; | 459 | |
395 | 460 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) | |
396 | p = NULL; | ||
397 | for (sme = me.sme; NULL != sme; sme = sme->next) | ||
398 | { | 461 | { |
399 | if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) && | 462 | if ((0 == memcmp (key, |
463 | sme->key, | ||
464 | sizeof (struct GNUNET_ShortHashCode))) && | ||
400 | (value == sme->value)) | 465 | (value == sme->value)) |
401 | { | 466 | { |
402 | if (NULL == p) | 467 | if (NULL == p) |
403 | map->map[i].sme = sme->next; | 468 | map->map[i].sme = sme->next; |
404 | else | 469 | else |
405 | p->next = sme->next; | 470 | p->next = sme->next; |
471 | update_next_cache_sme (map, | ||
472 | sme); | ||
406 | GNUNET_free (sme); | 473 | GNUNET_free (sme); |
407 | map->size--; | 474 | map->size--; |
408 | return GNUNET_YES; | 475 | return GNUNET_YES; |
@@ -412,19 +479,21 @@ GNUNET_CONTAINER_multishortmap_remove (struct GNUNET_CONTAINER_MultiShortmap *ma | |||
412 | } | 479 | } |
413 | else | 480 | else |
414 | { | 481 | { |
415 | struct BigMapEntry *bme; | 482 | struct BigMapEntry *p = NULL; |
416 | struct BigMapEntry *p; | 483 | |
417 | 484 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) | |
418 | p = NULL; | ||
419 | for (bme = me.bme; NULL != bme; bme = bme->next) | ||
420 | { | 485 | { |
421 | if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) && | 486 | if ((0 == memcmp (key, |
487 | &bme->key, | ||
488 | sizeof (struct GNUNET_ShortHashCode))) && | ||
422 | (value == bme->value)) | 489 | (value == bme->value)) |
423 | { | 490 | { |
424 | if (NULL == p) | 491 | if (NULL == p) |
425 | map->map[i].bme = bme->next; | 492 | map->map[i].bme = bme->next; |
426 | else | 493 | else |
427 | p->next = bme->next; | 494 | p->next = bme->next; |
495 | update_next_cache_bme (map, | ||
496 | bme); | ||
428 | GNUNET_free (bme); | 497 | GNUNET_free (bme); |
429 | map->size--; | 498 | map->size--; |
430 | return GNUNET_YES; | 499 | return GNUNET_YES; |
@@ -472,6 +541,8 @@ GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap | |||
472 | map->map[i].sme = sme->next; | 541 | map->map[i].sme = sme->next; |
473 | else | 542 | else |
474 | p->next = sme->next; | 543 | p->next = sme->next; |
544 | update_next_cache_sme (map, | ||
545 | sme); | ||
475 | GNUNET_free (sme); | 546 | GNUNET_free (sme); |
476 | map->size--; | 547 | map->size--; |
477 | if (NULL == p) | 548 | if (NULL == p) |
@@ -502,6 +573,8 @@ GNUNET_CONTAINER_multishortmap_remove_all (struct GNUNET_CONTAINER_MultiShortmap | |||
502 | map->map[i].bme = bme->next; | 573 | map->map[i].bme = bme->next; |
503 | else | 574 | else |
504 | p->next = bme->next; | 575 | p->next = bme->next; |
576 | update_next_cache_bme (map, | ||
577 | bme); | ||
505 | GNUNET_free (bme); | 578 | GNUNET_free (bme); |
506 | map->size--; | 579 | map->size--; |
507 | if (NULL == p) | 580 | if (NULL == p) |
@@ -539,18 +612,18 @@ GNUNET_CONTAINER_multishortmap_contains (const struct GNUNET_CONTAINER_MultiShor | |||
539 | me = map->map[idx_of (map, key)]; | 612 | me = map->map[idx_of (map, key)]; |
540 | if (map->use_small_entries) | 613 | if (map->use_small_entries) |
541 | { | 614 | { |
542 | struct SmallMapEntry *sme; | 615 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
543 | 616 | if (0 == memcmp (key, | |
544 | for (sme = me.sme; NULL != sme; sme = sme->next) | 617 | sme->key, |
545 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 618 | sizeof (struct GNUNET_ShortHashCode))) |
546 | return GNUNET_YES; | 619 | return GNUNET_YES; |
547 | } | 620 | } |
548 | else | 621 | else |
549 | { | 622 | { |
550 | struct BigMapEntry *bme; | 623 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
551 | 624 | if (0 == memcmp (key, | |
552 | for (bme = me.bme; NULL != bme; bme = bme->next) | 625 | &bme->key, |
553 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 626 | sizeof (struct GNUNET_ShortHashCode))) |
554 | return GNUNET_YES; | 627 | return GNUNET_YES; |
555 | } | 628 | } |
556 | return GNUNET_NO; | 629 | return GNUNET_NO; |
@@ -577,19 +650,19 @@ GNUNET_CONTAINER_multishortmap_contains_value (const struct GNUNET_CONTAINER_Mul | |||
577 | me = map->map[idx_of (map, key)]; | 650 | me = map->map[idx_of (map, key)]; |
578 | if (map->use_small_entries) | 651 | if (map->use_small_entries) |
579 | { | 652 | { |
580 | struct SmallMapEntry *sme; | 653 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
581 | 654 | if ( (0 == memcmp (key, | |
582 | for (sme = me.sme; NULL != sme; sme = sme->next) | 655 | sme->key, |
583 | if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) && | 656 | sizeof (struct GNUNET_ShortHashCode))) && |
584 | (sme->value == value) ) | 657 | (sme->value == value) ) |
585 | return GNUNET_YES; | 658 | return GNUNET_YES; |
586 | } | 659 | } |
587 | else | 660 | else |
588 | { | 661 | { |
589 | struct BigMapEntry *bme; | 662 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
590 | 663 | if ( (0 == memcmp (key, | |
591 | for (bme = me.bme; NULL != bme; bme = bme->next) | 664 | &bme->key, |
592 | if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) && | 665 | sizeof (struct GNUNET_ShortHashCode))) && |
593 | (bme->value == value) ) | 666 | (bme->value == value) ) |
594 | return GNUNET_YES; | 667 | return GNUNET_YES; |
595 | } | 668 | } |
@@ -610,17 +683,17 @@ grow (struct GNUNET_CONTAINER_MultiShortmap *map) | |||
610 | unsigned int old_len; | 683 | unsigned int old_len; |
611 | unsigned int new_len; | 684 | unsigned int new_len; |
612 | unsigned int idx; | 685 | unsigned int idx; |
613 | unsigned int i; | ||
614 | 686 | ||
615 | map->modification_counter++; | 687 | map->modification_counter++; |
616 | 688 | ||
617 | old_map = map->map; | 689 | old_map = map->map; |
618 | old_len = map->map_length; | 690 | old_len = map->map_length; |
619 | new_len = old_len * 2; | 691 | new_len = old_len * 2; |
620 | new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len); | 692 | new_map = GNUNET_new_array (new_len, |
693 | union MapEntry); | ||
621 | map->map_length = new_len; | 694 | map->map_length = new_len; |
622 | map->map = new_map; | 695 | map->map = new_map; |
623 | for (i = 0; i < old_len; i++) | 696 | for (unsigned int i = 0; i < old_len; i++) |
624 | { | 697 | { |
625 | if (map->use_small_entries) | 698 | if (map->use_small_entries) |
626 | { | 699 | { |
@@ -660,7 +733,7 @@ grow (struct GNUNET_CONTAINER_MultiShortmap *map) | |||
660 | * @param opt options for put | 733 | * @param opt options for put |
661 | * @return #GNUNET_OK on success, | 734 | * @return #GNUNET_OK on success, |
662 | * #GNUNET_NO if a value was replaced (with REPLACE) | 735 | * #GNUNET_NO if a value was replaced (with REPLACE) |
663 | * #GNUNET_SYSERR if GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the | 736 | * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the |
664 | * value already exists | 737 | * value already exists |
665 | */ | 738 | */ |
666 | int | 739 | int |
@@ -679,10 +752,10 @@ GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map, | |||
679 | me = map->map[i]; | 752 | me = map->map[i]; |
680 | if (map->use_small_entries) | 753 | if (map->use_small_entries) |
681 | { | 754 | { |
682 | struct SmallMapEntry *sme; | 755 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
683 | 756 | if (0 == memcmp (key, | |
684 | for (sme = me.sme; NULL != sme; sme = sme->next) | 757 | sme->key, |
685 | if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 758 | sizeof (struct GNUNET_ShortHashCode))) |
686 | { | 759 | { |
687 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) | 760 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) |
688 | return GNUNET_SYSERR; | 761 | return GNUNET_SYSERR; |
@@ -692,10 +765,10 @@ GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map, | |||
692 | } | 765 | } |
693 | else | 766 | else |
694 | { | 767 | { |
695 | struct BigMapEntry *bme; | 768 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
696 | 769 | if (0 == memcmp (key, | |
697 | for (bme = me.bme; NULL != bme; bme = bme->next) | 770 | &bme->key, |
698 | if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 771 | sizeof (struct GNUNET_ShortHashCode))) |
699 | { | 772 | { |
700 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) | 773 | if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) |
701 | return GNUNET_SYSERR; | 774 | return GNUNET_SYSERR; |
@@ -745,48 +818,66 @@ GNUNET_CONTAINER_multishortmap_put (struct GNUNET_CONTAINER_MultiShortmap *map, | |||
745 | * #GNUNET_SYSERR if it aborted iteration | 818 | * #GNUNET_SYSERR if it aborted iteration |
746 | */ | 819 | */ |
747 | int | 820 | int |
748 | GNUNET_CONTAINER_multishortmap_get_multiple (const struct GNUNET_CONTAINER_MultiShortmap *map, | 821 | GNUNET_CONTAINER_multishortmap_get_multiple (struct GNUNET_CONTAINER_MultiShortmap *map, |
749 | const struct GNUNET_ShortHashCode *key, | 822 | const struct GNUNET_ShortHashCode *key, |
750 | GNUNET_CONTAINER_ShortmapIterator it, | 823 | GNUNET_CONTAINER_ShortmapIterator it, |
751 | void *it_cls) | 824 | void *it_cls) |
752 | { | 825 | { |
753 | int count; | 826 | int count; |
754 | union MapEntry me; | 827 | union MapEntry me; |
828 | union MapEntry *ce; | ||
755 | 829 | ||
830 | ce = &map->next_cache[map->next_cache_off]; | ||
831 | GNUNET_assert (++map->next_cache_off < NEXT_CACHE_SIZE); | ||
756 | count = 0; | 832 | count = 0; |
757 | me = map->map[idx_of (map, key)]; | 833 | me = map->map[idx_of (map, key)]; |
758 | if (map->use_small_entries) | 834 | if (map->use_small_entries) |
759 | { | 835 | { |
760 | struct SmallMapEntry *sme; | 836 | struct SmallMapEntry *sme; |
761 | struct SmallMapEntry *nxt; | ||
762 | 837 | ||
763 | nxt = me.sme; | 838 | ce->sme = me.sme; |
764 | while (NULL != (sme = nxt)) | 839 | while (NULL != (sme = ce->sme)) |
765 | { | 840 | { |
766 | nxt = sme->next; | 841 | ce->sme = sme->next; |
767 | if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_ShortHashCode))) | 842 | if (0 != memcmp (key, |
843 | sme->key, | ||
844 | sizeof (struct GNUNET_ShortHashCode))) | ||
768 | continue; | 845 | continue; |
769 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) | 846 | if ( (NULL != it) && |
847 | (GNUNET_OK != it (it_cls, | ||
848 | key, | ||
849 | sme->value)) ) | ||
850 | { | ||
851 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
770 | return GNUNET_SYSERR; | 852 | return GNUNET_SYSERR; |
853 | } | ||
771 | count++; | 854 | count++; |
772 | } | 855 | } |
773 | } | 856 | } |
774 | else | 857 | else |
775 | { | 858 | { |
776 | struct BigMapEntry *bme; | 859 | struct BigMapEntry *bme; |
777 | struct BigMapEntry *nxt; | ||
778 | 860 | ||
779 | nxt = me.bme; | 861 | ce->bme = me.bme; |
780 | while (NULL != (bme = nxt)) | 862 | while (NULL != (bme = ce->bme)) |
781 | { | 863 | { |
782 | nxt = bme->next; | 864 | ce->bme = bme->next; |
783 | if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_ShortHashCode))) | 865 | if (0 != memcmp (key, |
866 | &bme->key, | ||
867 | sizeof (struct GNUNET_ShortHashCode))) | ||
784 | continue; | 868 | continue; |
785 | if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) | 869 | if ( (NULL != it) && |
870 | (GNUNET_OK != it (it_cls, | ||
871 | key, | ||
872 | bme->value)) ) | ||
873 | { | ||
874 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
786 | return GNUNET_SYSERR; | 875 | return GNUNET_SYSERR; |
876 | } | ||
787 | count++; | 877 | count++; |
788 | } | 878 | } |
789 | } | 879 | } |
880 | GNUNET_assert (--map->next_cache_off < NEXT_CACHE_SIZE); | ||
790 | return count; | 881 | return count; |
791 | } | 882 | } |
792 | 883 | ||
@@ -808,7 +899,6 @@ GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiSh | |||
808 | void *it_cls) | 899 | void *it_cls) |
809 | { | 900 | { |
810 | unsigned int off; | 901 | unsigned int off; |
811 | unsigned int idx; | ||
812 | union MapEntry me; | 902 | union MapEntry me; |
813 | 903 | ||
814 | if (0 == map->size) | 904 | if (0 == map->size) |
@@ -817,18 +907,13 @@ GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiSh | |||
817 | return 1; | 907 | return 1; |
818 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | 908 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, |
819 | map->size); | 909 | map->size); |
820 | for (idx = 0; idx < map->map_length; idx++) | 910 | for (unsigned int idx = 0; idx < map->map_length; idx++) |
821 | { | 911 | { |
822 | me = map->map[idx]; | 912 | me = map->map[idx]; |
823 | if (map->use_small_entries) | 913 | if (map->use_small_entries) |
824 | { | 914 | { |
825 | struct SmallMapEntry *sme; | 915 | for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next) |
826 | struct SmallMapEntry *nxt; | ||
827 | |||
828 | nxt = me.sme; | ||
829 | while (NULL != (sme = nxt)) | ||
830 | { | 916 | { |
831 | nxt = sme->next; | ||
832 | if (0 == off) | 917 | if (0 == off) |
833 | { | 918 | { |
834 | if (GNUNET_OK != it (it_cls, | 919 | if (GNUNET_OK != it (it_cls, |
@@ -842,13 +927,8 @@ GNUNET_CONTAINER_multishortmap_get_random (const struct GNUNET_CONTAINER_MultiSh | |||
842 | } | 927 | } |
843 | else | 928 | else |
844 | { | 929 | { |
845 | struct BigMapEntry *bme; | 930 | for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next) |
846 | struct BigMapEntry *nxt; | ||
847 | |||
848 | nxt = me.bme; | ||
849 | while (NULL != (bme = nxt)) | ||
850 | { | 931 | { |
851 | nxt = bme->next; | ||
852 | if (0 == off) | 932 | if (0 == off) |
853 | { | 933 | { |
854 | if (GNUNET_OK != it (it_cls, | 934 | if (GNUNET_OK != it (it_cls, |