GNUnet  0.11.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 {
49  void *value;
50 
54  struct BigMapEntry *next;
55 
60 };
61 
62 
67 {
71  void *value;
72 
77 
81  const struct GNUNET_HashCode *key;
82 };
83 
84 
88 union MapEntry
89 {
93  struct SmallMapEntry *sme;
94 
98  struct BigMapEntry *bme;
99 };
100 
101 
106 {
110  union MapEntry *map;
111 
115  unsigned int size;
116 
120  unsigned int map_length;
121 
127 
132  unsigned int modification_counter;
133 
139  union MapEntry next_cache[NEXT_CACHE_SIZE];
140 
145  unsigned int next_cache_off;
146 };
147 
148 
154 {
158  union MapEntry me;
159 
163  unsigned int idx;
164 
169  unsigned int modification_counter;
170 
175 };
176 
177 
194 GNUNET_CONTAINER_multihashmap_create (unsigned int len, int do_not_copy_keys)
195 {
197 
198  GNUNET_assert (len > 0);
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)))
209  {
210  /* out of memory */
212  "Out of memory allocating large hash map (%u entries)\n",
213  len);
214  GNUNET_free (hm);
215  return NULL;
216  }
217  }
218  else
219  {
220  hm->map = GNUNET_new_array (len, union MapEntry);
221  }
222  hm->map_length = len;
223  hm->use_small_entries = do_not_copy_keys;
224  return hm;
225 }
226 
227 
234 void
237 {
238  GNUNET_assert (0 == map->next_cache_off);
239  for (unsigned int i = 0; i < map->map_length; i++)
240  {
241  union MapEntry me;
242 
243  me = map->map[i];
244  if (map->use_small_entries)
245  {
246  struct SmallMapEntry *sme;
247  struct SmallMapEntry *nxt;
248 
249  nxt = me.sme;
250  while (NULL != (sme = nxt))
251  {
252  nxt = sme->next;
253  GNUNET_free (sme);
254  }
255  me.sme = NULL;
256  }
257  else
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);
273 }
274 
275 
283 static unsigned int
285  const struct GNUNET_HashCode *key)
286 {
287  GNUNET_assert (map != NULL);
288  return (*(unsigned int *) key) % map->map_length;
289 }
290 
291 
298 unsigned int
300  const struct GNUNET_CONTAINER_MultiHashMap *map)
301 {
302  return map->size;
303 }
304 
305 
316 void *
318  const struct GNUNET_CONTAINER_MultiHashMap *map,
319  const struct GNUNET_HashCode *key)
320 {
321  union MapEntry me;
322 
323  me = map->map[idx_of (map, key)];
324  if (map->use_small_entries)
325  {
326  struct SmallMapEntry *sme;
327 
328  for (sme = me.sme; NULL != sme; sme = sme->next)
329  if (0 == GNUNET_memcmp (key, sme->key))
330  return sme->value;
331  }
332  else
333  {
334  struct BigMapEntry *bme;
335 
336  for (bme = me.bme; NULL != bme; bme = bme->next)
337  if (0 == GNUNET_memcmp (key, &bme->key))
338  return bme->value;
339  }
340  return NULL;
341 }
342 
343 
353 int
357  void *it_cls)
358 {
359  int count;
360  union MapEntry me;
361  union MapEntry *ce;
362  struct GNUNET_HashCode kc;
363 
364  GNUNET_assert (NULL != map);
365  ce = &map->next_cache[map->next_cache_off];
367  count = 0;
368  for (unsigned i = 0; i < map->map_length; i++)
369  {
370  me = map->map[i];
371  if (map->use_small_entries)
372  {
373  struct SmallMapEntry *sme;
374 
375  ce->sme = me.sme;
376  while (NULL != (sme = ce->sme))
377  {
378  ce->sme = sme->next;
379  if (NULL != it)
380  {
381  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
382  {
384  return GNUNET_SYSERR;
385  }
386  }
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)
399  {
400  kc = bme->key;
401  if (GNUNET_OK != it (it_cls, &kc, bme->value))
402  {
404  return GNUNET_SYSERR;
405  }
406  }
407  count++;
408  }
409  }
410  }
412  return count;
413 }
414 
415 
423 static void
425  const struct BigMapEntry *bme)
426 {
427  for (unsigned int i = 0; i < map->next_cache_off; i++)
428  if (map->next_cache[i].bme == bme)
429  map->next_cache[i].bme = bme->next;
430 }
431 
432 
440 static void
442  const struct SmallMapEntry *sme)
443 {
444  for (unsigned int i = 0; i < map->next_cache_off; i++)
445  if (map->next_cache[i].sme == sme)
446  map->next_cache[i].sme = sme->next;
447 }
448 
449 
461 int
463  const struct GNUNET_HashCode *key,
464  const void *value)
465 {
466  union MapEntry me;
467  unsigned int i;
468 
469  map->modification_counter++;
470 
471  i = idx_of (map, key);
472  me = map->map[i];
473  if (map->use_small_entries)
474  {
475  struct SmallMapEntry *p;
476 
477  p = NULL;
478  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
479  {
480  if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
481  {
482  if (NULL == p)
483  map->map[i].sme = sme->next;
484  else
485  p->next = sme->next;
486  update_next_cache_sme (map, sme);
487  GNUNET_free (sme);
488  map->size--;
489  return GNUNET_YES;
490  }
491  p = sme;
492  }
493  }
494  else
495  {
496  struct BigMapEntry *p;
497 
498  p = NULL;
499  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
500  {
501  if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
502  {
503  if (NULL == p)
504  map->map[i].bme = bme->next;
505  else
506  p->next = bme->next;
507  update_next_cache_bme (map, bme);
508  GNUNET_free (bme);
509  map->size--;
510  return GNUNET_YES;
511  }
512  p = bme;
513  }
514  }
515  return GNUNET_NO;
516 }
517 
518 
527 int
530  const struct GNUNET_HashCode *key)
531 {
532  union MapEntry me;
533  unsigned int i;
534  int ret;
535 
536  map->modification_counter++;
537 
538  ret = 0;
539  i = idx_of (map, key);
540  me = map->map[i];
541  if (map->use_small_entries)
542  {
543  struct SmallMapEntry *sme;
544  struct SmallMapEntry *p;
545 
546  p = NULL;
547  sme = me.sme;
548  while (NULL != sme)
549  {
550  if (0 == GNUNET_memcmp (key, sme->key))
551  {
552  if (NULL == p)
553  map->map[i].sme = sme->next;
554  else
555  p->next = sme->next;
556  update_next_cache_sme (map, sme);
557  GNUNET_free (sme);
558  map->size--;
559  if (NULL == p)
560  sme = map->map[i].sme;
561  else
562  sme = p->next;
563  ret++;
564  }
565  else
566  {
567  p = sme;
568  sme = sme->next;
569  }
570  }
571  }
572  else
573  {
574  struct BigMapEntry *bme;
575  struct BigMapEntry *p;
576 
577  p = NULL;
578  bme = me.bme;
579  while (NULL != bme)
580  {
581  if (0 == GNUNET_memcmp (key, &bme->key))
582  {
583  if (NULL == p)
584  map->map[i].bme = bme->next;
585  else
586  p->next = bme->next;
587  update_next_cache_bme (map, bme);
588  GNUNET_free (bme);
589  map->size--;
590  if (NULL == p)
591  bme = map->map[i].bme;
592  else
593  bme = p->next;
594  ret++;
595  }
596  else
597  {
598  p = bme;
599  bme = bme->next;
600  }
601  }
602  }
603  return ret;
604 }
605 
606 
615 static int
616 remove_all (void *cls, const struct GNUNET_HashCode *key, void *value)
617 {
618  struct GNUNET_CONTAINER_MultiHashMap *map = cls;
619 
621  GNUNET_CONTAINER_multihashmap_remove (map, key, value));
622  return GNUNET_OK;
623 }
624 
625 
634 unsigned int
636 {
637  unsigned int ret;
638 
639  ret = map->size;
641  return ret;
642 }
643 
644 
654 int
656  const struct GNUNET_CONTAINER_MultiHashMap *map,
657  const struct GNUNET_HashCode *key)
658 {
659  union MapEntry me;
660 
661  me = map->map[idx_of (map, key)];
662  if (map->use_small_entries)
663  {
664  struct SmallMapEntry *sme;
665 
666  for (sme = me.sme; NULL != sme; sme = sme->next)
667  if (0 == GNUNET_memcmp (key, sme->key))
668  return GNUNET_YES;
669  }
670  else
671  {
672  struct BigMapEntry *bme;
673 
674  for (bme = me.bme; NULL != bme; bme = bme->next)
675  if (0 == GNUNET_memcmp (key, &bme->key))
676  return GNUNET_YES;
677  }
678  return GNUNET_NO;
679 }
680 
681 
692 int
694  const struct GNUNET_CONTAINER_MultiHashMap *map,
695  const struct GNUNET_HashCode *key,
696  const void *value)
697 {
698  union MapEntry me;
699 
700  me = map->map[idx_of (map, key)];
701  if (map->use_small_entries)
702  {
703  struct SmallMapEntry *sme;
704 
705  for (sme = me.sme; NULL != sme; sme = sme->next)
706  if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
707  return GNUNET_YES;
708  }
709  else
710  {
711  struct BigMapEntry *bme;
712 
713  for (bme = me.bme; NULL != bme; bme = bme->next)
714  if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
715  return GNUNET_YES;
716  }
717  return GNUNET_NO;
718 }
719 
720 
726 static void
728 {
729  union MapEntry *old_map;
730  union MapEntry *new_map;
731  unsigned int old_len;
732  unsigned int new_len;
733  unsigned int idx;
734 
735  old_map = map->map;
736  old_len = map->map_length;
737  GNUNET_assert (0 != old_len);
738  new_len = old_len * 2;
739  if (0 == new_len) /* 2^31 * 2 == 0 */
740  new_len = old_len; /* never use 0 */
741  if (new_len == old_len)
742  return; /* nothing changed */
743  new_map = GNUNET_malloc_large (new_len * sizeof(union MapEntry));
744  if (NULL == new_map)
745  return; /* grow not possible */
746  map->modification_counter++;
747  map->map_length = new_len;
748  map->map = new_map;
749  for (unsigned int i = 0; i < old_len; i++)
750  {
751  if (map->use_small_entries)
752  {
753  struct SmallMapEntry *sme;
754 
755  while (NULL != (sme = old_map[i].sme))
756  {
757  old_map[i].sme = sme->next;
758  idx = idx_of (map, sme->key);
759  sme->next = new_map[idx].sme;
760  new_map[idx].sme = sme;
761  }
762  }
763  else
764  {
765  struct BigMapEntry *bme;
766 
767  while (NULL != (bme = old_map[i].bme))
768  {
769  old_map[i].bme = bme->next;
770  idx = idx_of (map, &bme->key);
771  bme->next = new_map[idx].bme;
772  new_map[idx].bme = bme;
773  }
774  }
775  }
776  GNUNET_free (old_map);
777 }
778 
779 
792 int
794  const struct GNUNET_HashCode *key,
795  void *value,
797 {
798  union MapEntry me;
799  unsigned int i;
800 
801  i = idx_of (map, key);
804  {
805  me = map->map[i];
806  if (map->use_small_entries)
807  {
808  struct SmallMapEntry *sme;
809 
810  for (sme = me.sme; NULL != sme; sme = sme->next)
811  if (0 == GNUNET_memcmp (key, sme->key))
812  {
814  return GNUNET_SYSERR;
815  sme->value = value;
816  return GNUNET_NO;
817  }
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))
825  {
827  return GNUNET_SYSERR;
828  bme->value = value;
829  return GNUNET_NO;
830  }
831  }
832  }
833  if (map->size / 3 >= map->map_length / 4)
834  {
835  grow (map);
836  i = idx_of (map, key);
837  }
838  if (map->use_small_entries)
839  {
840  struct SmallMapEntry *sme;
841 
842  sme = GNUNET_new (struct SmallMapEntry);
843  sme->key = key;
844  sme->value = value;
845  sme->next = map->map[i].sme;
846  map->map[i].sme = sme;
847  }
848  else
849  {
850  struct BigMapEntry *bme;
851 
852  bme = GNUNET_new (struct BigMapEntry);
853  bme->key = *key;
854  bme->value = value;
855  bme->next = map->map[i].bme;
856  map->map[i].bme = bme;
857  }
858  map->size++;
859  return GNUNET_OK;
860 }
861 
862 
873 int
876  const struct GNUNET_HashCode *key,
878  void *it_cls)
879 {
880  int count;
881  union MapEntry *me;
882  union MapEntry *ce;
883 
884  ce = &map->next_cache[map->next_cache_off];
886  count = 0;
887  me = &map->map[idx_of (map, key)];
888  if (map->use_small_entries)
889  {
890  struct SmallMapEntry *sme;
891 
892  ce->sme = me->sme;
893  while (NULL != (sme = ce->sme))
894  {
895  ce->sme = sme->next;
896  if (0 != GNUNET_memcmp (key, sme->key))
897  continue;
898  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
899  {
901  return GNUNET_SYSERR;
902  }
903  count++;
904  }
905  }
906  else
907  {
908  struct BigMapEntry *bme;
909 
910  ce->bme = me->bme;
911  while (NULL != (bme = ce->bme))
912  {
913  ce->bme = bme->next;
914  if (0 != GNUNET_memcmp (key, &bme->key))
915  continue;
916  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
917  {
919  return GNUNET_SYSERR;
920  }
921  count++;
922  }
923  }
925  return count;
926 }
927 
928 
940 unsigned int
942  const struct GNUNET_CONTAINER_MultiHashMap *map,
944  void *it_cls)
945 {
946  unsigned int off;
947  unsigned int idx;
948  union MapEntry me;
949 
950  if (0 == map->size)
951  return 0;
952  if (NULL == it)
953  return 1;
955  for (idx = 0; idx < map->map_length; idx++)
956  {
957  me = map->map[idx];
958  if (map->use_small_entries)
959  {
960  struct SmallMapEntry *sme;
961  struct SmallMapEntry *nxt;
962 
963  nxt = me.sme;
964  while (NULL != (sme = nxt))
965  {
966  nxt = sme->next;
967  if (0 == off)
968  {
969  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
970  return GNUNET_SYSERR;
971  return 1;
972  }
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)
986  {
987  if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
988  return GNUNET_SYSERR;
989  return 1;
990  }
991  off--;
992  }
993  }
994  }
995  GNUNET_break (0);
996  return GNUNET_SYSERR;
997 }
998 
999 
1014  const struct GNUNET_CONTAINER_MultiHashMap *map)
1015 {
1017 
1019  iter->map = map;
1021  iter->me = map->map[0];
1022  return iter;
1023 }
1024 
1025 
1040 int
1043  struct GNUNET_HashCode *key,
1044  const void **value)
1045 {
1046  /* make sure the map has not been modified */
1048 
1049  /* look for the next entry, skipping empty buckets */
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)
1055  {
1056  if (NULL != iter->me.sme)
1057  {
1058  if (NULL != key)
1059  *key = *iter->me.sme->key;
1060  if (NULL != value)
1061  *value = iter->me.sme->value;
1062  iter->me.sme = iter->me.sme->next;
1063  return GNUNET_YES;
1064  }
1065  }
1066  else
1067  {
1068  if (NULL != iter->me.bme)
1069  {
1070  if (NULL != key)
1071  *key = iter->me.bme->key;
1072  if (NULL != value)
1073  *value = iter->me.bme->value;
1074  iter->me.bme = iter->me.bme->next;
1075  return GNUNET_YES;
1076  }
1077  }
1078  iter->idx += 1;
1079  if (iter->idx < iter->map->map_length)
1080  iter->me = iter->map->map[iter->idx];
1081  }
1082 }
1083 
1084 
1090 void
1093 {
1094  GNUNET_free (iter);
1095 }
1096 
1097 
1098 /* end of container_multihashmap.c */
int(* GNUNET_CONTAINER_MulitHashMapIteratorCallback)(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over hash map entries.
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
const struct GNUNET_HashCode * key
Key for the entry.
#define GNUNET_NO
Definition: gnunet_common.h:78
void * value
Value of the entry.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#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)...
#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.
unsigned int GNUNET_CONTAINER_multihashmap_get_random(const struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Call it on a random value from the map, or not at all if the map is empty.
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:76
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.
int GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MulitHashMapIteratorCallback 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:77
struct BigMapEntry * bme
Variant used if map entries contain the full key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
#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...