GNUnet  0.10.x
container_multihashmap.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2008, 2012 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
26 #include "platform.h"
27 #include "gnunet_container_lib.h"
28 
29 #define LOG(kind, ...) \
30  GNUNET_log_from (kind, "util-container-multihashmap", __VA_ARGS__)
31 
38 #define NEXT_CACHE_SIZE 16
39 
40 
45 {
46 
50  void *value;
51 
55  struct BigMapEntry *next;
56 
61 };
62 
63 
68 {
69 
73  void *value;
74 
79 
83  const struct GNUNET_HashCode *key;
84 };
85 
86 
90 union MapEntry
91 {
95  struct SmallMapEntry *sme;
96 
100  struct BigMapEntry *bme;
101 };
102 
103 
108 {
112  union MapEntry *map;
113 
117  unsigned int size;
118 
122  unsigned int map_length;
123 
129 
134  unsigned int modification_counter;
135 
141  union MapEntry next_cache[NEXT_CACHE_SIZE];
142 
147  unsigned int next_cache_off;
148 };
149 
150 
156 {
160  union MapEntry me;
161 
165  unsigned int idx;
166 
171  unsigned int modification_counter;
172 
177 };
178 
179 
196 GNUNET_CONTAINER_multihashmap_create (unsigned int len, int do_not_copy_keys)
197 {
199 
200  GNUNET_assert (len > 0);
202  if (len * sizeof (union MapEntry) > GNUNET_MAX_MALLOC_CHECKED)
203  {
204  size_t s;
205  /* application *explicitly* requested very large map, hopefully
206  it checks the return value... */
207  s = len * sizeof (union MapEntry);
208  if ((s / sizeof (union MapEntry)) != len)
209  return NULL; /* integer overflow on multiplication */
210  if (NULL == (hm->map = GNUNET_malloc_large (s)))
211  {
212  /* out of memory */
214  "Out of memory allocating large hash map (%u entries)\n",
215  len);
216  GNUNET_free (hm);
217  return NULL;
218  }
219  }
220  else
221  {
222  hm->map = GNUNET_new_array (len, union MapEntry);
223  }
224  hm->map_length = len;
225  hm->use_small_entries = do_not_copy_keys;
226  return hm;
227 }
228 
229 
236 void
239 {
240  GNUNET_assert (0 == map->next_cache_off);
241  for (unsigned int i = 0; i < map->map_length; i++)
242  {
243  union MapEntry me;
244 
245  me = map->map[i];
246  if (map->use_small_entries)
247  {
248  struct SmallMapEntry *sme;
249  struct SmallMapEntry *nxt;
250 
251  nxt = me.sme;
252  while (NULL != (sme = nxt))
253  {
254  nxt = sme->next;
255  GNUNET_free (sme);
256  }
257  me.sme = NULL;
258  }
259  else
260  {
261  struct BigMapEntry *bme;
262  struct BigMapEntry *nxt;
263 
264  nxt = me.bme;
265  while (NULL != (bme = nxt))
266  {
267  nxt = bme->next;
268  GNUNET_free (bme);
269  }
270  me.bme = NULL;
271  }
272  }
273  GNUNET_free (map->map);
274  GNUNET_free (map);
275 }
276 
277 
285 static unsigned int
287  const struct GNUNET_HashCode *key)
288 {
289  GNUNET_assert (map != NULL);
290  return (*(unsigned int *) key) % map->map_length;
291 }
292 
293 
300 unsigned int
302  const struct GNUNET_CONTAINER_MultiHashMap *map)
303 {
304  return map->size;
305 }
306 
307 
318 void *
320  const struct GNUNET_CONTAINER_MultiHashMap *map,
321  const struct GNUNET_HashCode *key)
322 {
323  union MapEntry me;
324 
325  me = map->map[idx_of (map, key)];
326  if (map->use_small_entries)
327  {
328  struct SmallMapEntry *sme;
329 
330  for (sme = me.sme; NULL != sme; sme = sme->next)
331  if (0 == GNUNET_memcmp (key, sme->key))
332  return sme->value;
333  }
334  else
335  {
336  struct BigMapEntry *bme;
337 
338  for (bme = me.bme; NULL != bme; bme = bme->next)
339  if (0 == GNUNET_memcmp (key, &bme->key))
340  return bme->value;
341  }
342  return NULL;
343 }
344 
345 
355 int
359  void *it_cls)
360 {
361  int count;
362  union MapEntry me;
363  union MapEntry *ce;
364  struct GNUNET_HashCode kc;
365 
366  GNUNET_assert (NULL != map);
367  ce = &map->next_cache[map->next_cache_off];
369  count = 0;
370  for (unsigned i = 0; i < map->map_length; i++)
371  {
372  me = map->map[i];
373  if (map->use_small_entries)
374  {
375  struct SmallMapEntry *sme;
376 
377  ce->sme = me.sme;
378  while (NULL != (sme = ce->sme))
379  {
380  ce->sme = sme->next;
381  if (NULL != it)
382  {
383  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
384  {
386  return GNUNET_SYSERR;
387  }
388  }
389  count++;
390  }
391  }
392  else
393  {
394  struct BigMapEntry *bme;
395 
396  ce->bme = me.bme;
397  while (NULL != (bme = ce->bme))
398  {
399  ce->bme = bme->next;
400  if (NULL != it)
401  {
402  kc = bme->key;
403  if (GNUNET_OK != it (it_cls, &kc, bme->value))
404  {
406  return GNUNET_SYSERR;
407  }
408  }
409  count++;
410  }
411  }
412  }
414  return count;
415 }
416 
417 
425 static void
427  const struct BigMapEntry *bme)
428 {
429  for (unsigned int i = 0; i < map->next_cache_off; i++)
430  if (map->next_cache[i].bme == bme)
431  map->next_cache[i].bme = bme->next;
432 }
433 
434 
442 static void
444  const struct SmallMapEntry *sme)
445 {
446  for (unsigned int i = 0; i < map->next_cache_off; i++)
447  if (map->next_cache[i].sme == sme)
448  map->next_cache[i].sme = sme->next;
449 }
450 
451 
463 int
465  const struct GNUNET_HashCode *key,
466  const void *value)
467 {
468  union MapEntry me;
469  unsigned int i;
470 
471  map->modification_counter++;
472 
473  i = idx_of (map, key);
474  me = map->map[i];
475  if (map->use_small_entries)
476  {
477  struct SmallMapEntry *p;
478 
479  p = NULL;
480  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
481  {
482  if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
483  {
484  if (NULL == p)
485  map->map[i].sme = sme->next;
486  else
487  p->next = sme->next;
488  update_next_cache_sme (map, sme);
489  GNUNET_free (sme);
490  map->size--;
491  return GNUNET_YES;
492  }
493  p = sme;
494  }
495  }
496  else
497  {
498  struct BigMapEntry *p;
499 
500  p = NULL;
501  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
502  {
503  if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
504  {
505  if (NULL == p)
506  map->map[i].bme = bme->next;
507  else
508  p->next = bme->next;
509  update_next_cache_bme (map, bme);
510  GNUNET_free (bme);
511  map->size--;
512  return GNUNET_YES;
513  }
514  p = bme;
515  }
516  }
517  return GNUNET_NO;
518 }
519 
520 
529 int
532  const struct GNUNET_HashCode *key)
533 {
534  union MapEntry me;
535  unsigned int i;
536  int ret;
537 
538  map->modification_counter++;
539 
540  ret = 0;
541  i = idx_of (map, key);
542  me = map->map[i];
543  if (map->use_small_entries)
544  {
545  struct SmallMapEntry *sme;
546  struct SmallMapEntry *p;
547 
548  p = NULL;
549  sme = me.sme;
550  while (NULL != sme)
551  {
552  if (0 == GNUNET_memcmp (key, sme->key))
553  {
554  if (NULL == p)
555  map->map[i].sme = sme->next;
556  else
557  p->next = sme->next;
558  update_next_cache_sme (map, sme);
559  GNUNET_free (sme);
560  map->size--;
561  if (NULL == p)
562  sme = map->map[i].sme;
563  else
564  sme = p->next;
565  ret++;
566  }
567  else
568  {
569  p = sme;
570  sme = sme->next;
571  }
572  }
573  }
574  else
575  {
576  struct BigMapEntry *bme;
577  struct BigMapEntry *p;
578 
579  p = NULL;
580  bme = me.bme;
581  while (NULL != bme)
582  {
583  if (0 == GNUNET_memcmp (key, &bme->key))
584  {
585  if (NULL == p)
586  map->map[i].bme = bme->next;
587  else
588  p->next = bme->next;
589  update_next_cache_bme (map, bme);
590  GNUNET_free (bme);
591  map->size--;
592  if (NULL == p)
593  bme = map->map[i].bme;
594  else
595  bme = p->next;
596  ret++;
597  }
598  else
599  {
600  p = bme;
601  bme = bme->next;
602  }
603  }
604  }
605  return ret;
606 }
607 
608 
617 static int
618 remove_all (void *cls, const struct GNUNET_HashCode *key, void *value)
619 {
620  struct GNUNET_CONTAINER_MultiHashMap *map = cls;
621 
623  GNUNET_CONTAINER_multihashmap_remove (map, key, value));
624  return GNUNET_OK;
625 }
626 
627 
636 unsigned int
638 {
639  unsigned int ret;
640 
641  ret = map->size;
643  return ret;
644 }
645 
646 
656 int
658  const struct GNUNET_CONTAINER_MultiHashMap *map,
659  const struct GNUNET_HashCode *key)
660 {
661  union MapEntry me;
662 
663  me = map->map[idx_of (map, key)];
664  if (map->use_small_entries)
665  {
666  struct SmallMapEntry *sme;
667 
668  for (sme = me.sme; NULL != sme; sme = sme->next)
669  if (0 == GNUNET_memcmp (key, sme->key))
670  return GNUNET_YES;
671  }
672  else
673  {
674  struct BigMapEntry *bme;
675 
676  for (bme = me.bme; NULL != bme; bme = bme->next)
677  if (0 == GNUNET_memcmp (key, &bme->key))
678  return GNUNET_YES;
679  }
680  return GNUNET_NO;
681 }
682 
683 
694 int
696  const struct GNUNET_CONTAINER_MultiHashMap *map,
697  const struct GNUNET_HashCode *key,
698  const void *value)
699 {
700  union MapEntry me;
701 
702  me = map->map[idx_of (map, key)];
703  if (map->use_small_entries)
704  {
705  struct SmallMapEntry *sme;
706 
707  for (sme = me.sme; NULL != sme; sme = sme->next)
708  if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
709  return GNUNET_YES;
710  }
711  else
712  {
713  struct BigMapEntry *bme;
714 
715  for (bme = me.bme; NULL != bme; bme = bme->next)
716  if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
717  return GNUNET_YES;
718  }
719  return GNUNET_NO;
720 }
721 
722 
728 static void
730 {
731  union MapEntry *old_map;
732  union MapEntry *new_map;
733  unsigned int old_len;
734  unsigned int new_len;
735  unsigned int idx;
736 
737  old_map = map->map;
738  old_len = map->map_length;
739  GNUNET_assert (0 != old_len);
740  new_len = old_len * 2;
741  if (0 == new_len) /* 2^31 * 2 == 0 */
742  new_len = old_len; /* never use 0 */
743  if (new_len == old_len)
744  return; /* nothing changed */
745  new_map = GNUNET_malloc_large (new_len * sizeof (union MapEntry));
746  if (NULL == new_map)
747  return; /* grow not possible */
748  map->modification_counter++;
749  map->map_length = new_len;
750  map->map = new_map;
751  for (unsigned int i = 0; i < old_len; i++)
752  {
753  if (map->use_small_entries)
754  {
755  struct SmallMapEntry *sme;
756 
757  while (NULL != (sme = old_map[i].sme))
758  {
759  old_map[i].sme = sme->next;
760  idx = idx_of (map, sme->key);
761  sme->next = new_map[idx].sme;
762  new_map[idx].sme = sme;
763  }
764  }
765  else
766  {
767  struct BigMapEntry *bme;
768 
769  while (NULL != (bme = old_map[i].bme))
770  {
771  old_map[i].bme = bme->next;
772  idx = idx_of (map, &bme->key);
773  bme->next = new_map[idx].bme;
774  new_map[idx].bme = bme;
775  }
776  }
777  }
778  GNUNET_free (old_map);
779 }
780 
781 
794 int
796  const struct GNUNET_HashCode *key,
797  void *value,
799 {
800  union MapEntry me;
801  unsigned int i;
802 
803  i = idx_of (map, key);
806  {
807  me = map->map[i];
808  if (map->use_small_entries)
809  {
810  struct SmallMapEntry *sme;
811 
812  for (sme = me.sme; NULL != sme; sme = sme->next)
813  if (0 == GNUNET_memcmp (key, sme->key))
814  {
816  return GNUNET_SYSERR;
817  sme->value = value;
818  return GNUNET_NO;
819  }
820  }
821  else
822  {
823  struct BigMapEntry *bme;
824 
825  for (bme = me.bme; NULL != bme; bme = bme->next)
826  if (0 == GNUNET_memcmp (key, &bme->key))
827  {
829  return GNUNET_SYSERR;
830  bme->value = value;
831  return GNUNET_NO;
832  }
833  }
834  }
835  if (map->size / 3 >= map->map_length / 4)
836  {
837  grow (map);
838  i = idx_of (map, key);
839  }
840  if (map->use_small_entries)
841  {
842  struct SmallMapEntry *sme;
843 
844  sme = GNUNET_new (struct SmallMapEntry);
845  sme->key = key;
846  sme->value = value;
847  sme->next = map->map[i].sme;
848  map->map[i].sme = sme;
849  }
850  else
851  {
852  struct BigMapEntry *bme;
853 
854  bme = GNUNET_new (struct BigMapEntry);
855  bme->key = *key;
856  bme->value = value;
857  bme->next = map->map[i].bme;
858  map->map[i].bme = bme;
859  }
860  map->size++;
861  return GNUNET_OK;
862 }
863 
864 
875 int
878  const struct GNUNET_HashCode *key,
880  void *it_cls)
881 {
882  int count;
883  union MapEntry *me;
884  union MapEntry *ce;
885 
886  ce = &map->next_cache[map->next_cache_off];
888  count = 0;
889  me = &map->map[idx_of (map, key)];
890  if (map->use_small_entries)
891  {
892  struct SmallMapEntry *sme;
893 
894  ce->sme = me->sme;
895  while (NULL != (sme = ce->sme))
896  {
897  ce->sme = sme->next;
898  if (0 != GNUNET_memcmp (key, sme->key))
899  continue;
900  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
901  {
903  return GNUNET_SYSERR;
904  }
905  count++;
906  }
907  }
908  else
909  {
910  struct BigMapEntry *bme;
911 
912  ce->bme = me->bme;
913  while (NULL != (bme = ce->bme))
914  {
915  ce->bme = bme->next;
916  if (0 != GNUNET_memcmp (key, &bme->key))
917  continue;
918  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
919  {
921  return GNUNET_SYSERR;
922  }
923  count++;
924  }
925  }
927  return count;
928 }
929 
930 
942 unsigned int
944  const struct GNUNET_CONTAINER_MultiHashMap *map,
946  void *it_cls)
947 {
948  unsigned int off;
949  unsigned int idx;
950  union MapEntry me;
951 
952  if (0 == map->size)
953  return 0;
954  if (NULL == it)
955  return 1;
957  for (idx = 0; idx < map->map_length; idx++)
958  {
959  me = map->map[idx];
960  if (map->use_small_entries)
961  {
962  struct SmallMapEntry *sme;
963  struct SmallMapEntry *nxt;
964 
965  nxt = me.sme;
966  while (NULL != (sme = nxt))
967  {
968  nxt = sme->next;
969  if (0 == off)
970  {
971  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
972  return GNUNET_SYSERR;
973  return 1;
974  }
975  off--;
976  }
977  }
978  else
979  {
980  struct BigMapEntry *bme;
981  struct BigMapEntry *nxt;
982 
983  nxt = me.bme;
984  while (NULL != (bme = nxt))
985  {
986  nxt = bme->next;
987  if (0 == off)
988  {
989  if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
990  return GNUNET_SYSERR;
991  return 1;
992  }
993  off--;
994  }
995  }
996  }
997  GNUNET_break (0);
998  return GNUNET_SYSERR;
999 }
1000 
1001 
1016  const struct GNUNET_CONTAINER_MultiHashMap *map)
1017 {
1019 
1021  iter->map = map;
1023  iter->me = map->map[0];
1024  return iter;
1025 }
1026 
1027 
1042 int
1045  struct GNUNET_HashCode *key,
1046  const void **value)
1047 {
1048  /* make sure the map has not been modified */
1050 
1051  /* look for the next entry, skipping empty buckets */
1052  while (1)
1053  {
1054  if (iter->idx >= iter->map->map_length)
1055  return GNUNET_NO;
1056  if (GNUNET_YES == iter->map->use_small_entries)
1057  {
1058  if (NULL != iter->me.sme)
1059  {
1060  if (NULL != key)
1061  *key = *iter->me.sme->key;
1062  if (NULL != value)
1063  *value = iter->me.sme->value;
1064  iter->me.sme = iter->me.sme->next;
1065  return GNUNET_YES;
1066  }
1067  }
1068  else
1069  {
1070  if (NULL != iter->me.bme)
1071  {
1072  if (NULL != key)
1073  *key = iter->me.bme->key;
1074  if (NULL != value)
1075  *value = iter->me.bme->value;
1076  iter->me.bme = iter->me.bme->next;
1077  return GNUNET_YES;
1078  }
1079  }
1080  iter->idx += 1;
1081  if (iter->idx < iter->map->map_length)
1082  iter->me = iter->map->map[iter->idx];
1083  }
1084 }
1085 
1086 
1092 void
1095 {
1096  GNUNET_free (iter);
1097 }
1098 
1099 
1100 /* end of container_multihashmap.c */
union MapEntry * map
All of our buckets.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
unsigned int size
Number of entries in the map.
union MapEntry me
Position in the bucket idx.
GNUNET_CONTAINER_MultiHashMapOption
Options for storing values in the HashMap.
struct SmallMapEntry * next
If there is a hash collision, we create a linked list.
unsigned int modification_counter
Counts the destructive modifications (grow, remove) to the map, so that iterators can check if they a...
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
const struct GNUNET_CONTAINER_MultiHashMap * map
Map that we are iterating over.
void * value
Value of the entry.
static int remove_all(void *cls, const struct GNUNET_HashCode *key, void *value)
Callback used to remove all entries from the map.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
unsigned int next_cache_off
Offset of next_cache entries in use, must be smaller than NEXT_CACHE_SIZE.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int(* GNUNET_CONTAINER_HashMapIterator)(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over hash map entries.
const struct GNUNET_HashCode * key
Key for the entry.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_HashMapIterator it, void *it_cls)
Iterate over all entries in the map.
#define GNUNET_NO
Definition: gnunet_common.h:81
void * value
Value of the entry.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int GNUNET_CONTAINER_multihashmap_remove_all(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Remove all entries for the given key from the map.
struct SmallMapEntry * sme
Variant used if map entries only contain a pointer to the key.
int GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL)...
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_malloc_large(size)
Wrapper around malloc.
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
union MapEntry next_cache[16]
Map entries indicating iteration positions currently in use by GNUNET_CONTAINER_multihashmap_get_mult...
struct BigMapEntry * next
If there is a hash collision, we create a linked list.
static struct GNUNET_CONTAINER_MultiPeerMap * map
Handle to the map used to store old latency values for peers.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
static void update_next_cache_sme(struct GNUNET_CONTAINER_MultiHashMap *map, const struct SmallMapEntry *sme)
We are about to free() the sme, make sure it is not in the list of next values for any iterator in th...
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
#define NEXT_CACHE_SIZE
Maximum recursion depth for callbacks of GNUNET_CONTAINER_multihashmap_get_multiple() themselve s aga...
unsigned int map_length
Length of the "map" array.
unsigned int GNUNET_CONTAINER_multihashmap_clear(struct GNUNET_CONTAINER_MultiHashMap *map)
Remove all entries from the map.
Entry in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
Randomness for IVs etc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
unsigned int idx
Current bucket index.
A 512-bit hashcode.
static void update_next_cache_bme(struct GNUNET_CONTAINER_MultiHashMap *map, const struct BigMapEntry *bme)
We are about to free() the bme, make sure it is not in the list of next values for any iterator in th...
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
int use_small_entries
GNUNET_NO if the map entries are of type &#39;struct BigMapEntry&#39;, GNUNET_YES if the map entries are of t...
int GNUNET_CONTAINER_multihashmap_contains_value(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Check if the map contains the given value under the given key.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static void grow(struct GNUNET_CONTAINER_MultiHashMap *map)
Grow the given map to a more appropriate size.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
static unsigned int idx_of(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Compute the index of the bucket for the given key.
Allow multiple values with the same key.
An entry in the hash map with just a pointer to the key.
unsigned int GNUNET_CONTAINER_multihashmap_get_random(const struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_HashMapIterator it, void *it_cls)
Call it on a random value from the map, or not at all if the map is empty.
int GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_HashMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
#define GNUNET_log(kind,...)
An entry in the hash map with the full key.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
unsigned int modification_counter
Modification counter as observed on the map when the iterator was created.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct BigMapEntry * bme
Variant used if map entries contain the full key.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_HashCode key
Key for the entry.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...