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 
44 struct BigMapEntry {
48  void *value;
49 
53  struct BigMapEntry *next;
54 
59 };
60 
61 
65 struct SmallMapEntry {
69  void *value;
70 
75 
79  const struct GNUNET_HashCode *key;
80 };
81 
82 
86 union MapEntry {
90  struct SmallMapEntry *sme;
91 
95  struct BigMapEntry *bme;
96 };
97 
98 
106  union MapEntry *map;
107 
111  unsigned int size;
112 
116  unsigned int map_length;
117 
123 
128  unsigned int modification_counter;
129 
135  union MapEntry next_cache[NEXT_CACHE_SIZE];
136 
141  unsigned int next_cache_off;
142 };
143 
144 
153  union MapEntry me;
154 
158  unsigned int idx;
159 
164  unsigned int modification_counter;
165 
170 };
171 
172 
189 GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
190 {
192 
193  GNUNET_assert(len > 0);
195  if (len * sizeof(union MapEntry) > GNUNET_MAX_MALLOC_CHECKED)
196  {
197  size_t s;
198  /* application *explicitly* requested very large map, hopefully
199  it checks the return value... */
200  s = len * sizeof(union MapEntry);
201  if ((s / sizeof(union MapEntry)) != len)
202  return NULL; /* integer overflow on multiplication */
203  if (NULL == (hm->map = GNUNET_malloc_large(s)))
204  {
205  /* out of memory */
207  "Out of memory allocating large hash map (%u entries)\n",
208  len);
209  GNUNET_free(hm);
210  return NULL;
211  }
212  }
213  else
214  {
215  hm->map = GNUNET_new_array(len, union MapEntry);
216  }
217  hm->map_length = len;
218  hm->use_small_entries = do_not_copy_keys;
219  return hm;
220 }
221 
222 
229 void
232 {
233  GNUNET_assert(0 == map->next_cache_off);
234  for (unsigned int i = 0; i < map->map_length; i++)
235  {
236  union MapEntry me;
237 
238  me = map->map[i];
239  if (map->use_small_entries)
240  {
241  struct SmallMapEntry *sme;
242  struct SmallMapEntry *nxt;
243 
244  nxt = me.sme;
245  while (NULL != (sme = nxt))
246  {
247  nxt = sme->next;
248  GNUNET_free(sme);
249  }
250  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  }
266  GNUNET_free(map->map);
267  GNUNET_free(map);
268 }
269 
270 
278 static unsigned int
280  const struct GNUNET_HashCode *key)
281 {
282  GNUNET_assert(map != NULL);
283  return (*(unsigned int *)key) % map->map_length;
284 }
285 
286 
293 unsigned int
295  const struct GNUNET_CONTAINER_MultiHashMap *map)
296 {
297  return map->size;
298 }
299 
300 
311 void *
313  const struct GNUNET_CONTAINER_MultiHashMap *map,
314  const struct GNUNET_HashCode *key)
315 {
316  union MapEntry me;
317 
318  me = map->map[idx_of(map, key)];
319  if (map->use_small_entries)
320  {
321  struct SmallMapEntry *sme;
322 
323  for (sme = me.sme; NULL != sme; sme = sme->next)
324  if (0 == GNUNET_memcmp(key, sme->key))
325  return sme->value;
326  }
327  else
328  {
329  struct BigMapEntry *bme;
330 
331  for (bme = me.bme; NULL != bme; bme = bme->next)
332  if (0 == GNUNET_memcmp(key, &bme->key))
333  return bme->value;
334  }
335  return NULL;
336 }
337 
338 
348 int
352  void *it_cls)
353 {
354  int count;
355  union MapEntry me;
356  union MapEntry *ce;
357  struct GNUNET_HashCode kc;
358 
359  GNUNET_assert(NULL != map);
360  ce = &map->next_cache[map->next_cache_off];
362  count = 0;
363  for (unsigned i = 0; i < map->map_length; i++)
364  {
365  me = map->map[i];
366  if (map->use_small_entries)
367  {
368  struct SmallMapEntry *sme;
369 
370  ce->sme = me.sme;
371  while (NULL != (sme = ce->sme))
372  {
373  ce->sme = sme->next;
374  if (NULL != it)
375  {
376  if (GNUNET_OK != it(it_cls, sme->key, sme->value))
377  {
379  return GNUNET_SYSERR;
380  }
381  }
382  count++;
383  }
384  }
385  else
386  {
387  struct BigMapEntry *bme;
388 
389  ce->bme = me.bme;
390  while (NULL != (bme = ce->bme))
391  {
392  ce->bme = bme->next;
393  if (NULL != it)
394  {
395  kc = bme->key;
396  if (GNUNET_OK != it(it_cls, &kc, bme->value))
397  {
399  return GNUNET_SYSERR;
400  }
401  }
402  count++;
403  }
404  }
405  }
407  return count;
408 }
409 
410 
418 static void
420  const struct BigMapEntry *bme)
421 {
422  for (unsigned int i = 0; i < map->next_cache_off; i++)
423  if (map->next_cache[i].bme == bme)
424  map->next_cache[i].bme = bme->next;
425 }
426 
427 
435 static void
437  const struct SmallMapEntry *sme)
438 {
439  for (unsigned int i = 0; i < map->next_cache_off; i++)
440  if (map->next_cache[i].sme == sme)
441  map->next_cache[i].sme = sme->next;
442 }
443 
444 
456 int
458  const struct GNUNET_HashCode *key,
459  const void *value)
460 {
461  union MapEntry me;
462  unsigned int i;
463 
464  map->modification_counter++;
465 
466  i = idx_of(map, key);
467  me = map->map[i];
468  if (map->use_small_entries)
469  {
470  struct SmallMapEntry *p;
471 
472  p = NULL;
473  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
474  {
475  if ((0 == GNUNET_memcmp(key, sme->key)) && (value == sme->value))
476  {
477  if (NULL == p)
478  map->map[i].sme = sme->next;
479  else
480  p->next = sme->next;
481  update_next_cache_sme(map, sme);
482  GNUNET_free(sme);
483  map->size--;
484  return GNUNET_YES;
485  }
486  p = sme;
487  }
488  }
489  else
490  {
491  struct BigMapEntry *p;
492 
493  p = NULL;
494  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
495  {
496  if ((0 == GNUNET_memcmp(key, &bme->key)) && (value == bme->value))
497  {
498  if (NULL == p)
499  map->map[i].bme = bme->next;
500  else
501  p->next = bme->next;
502  update_next_cache_bme(map, bme);
503  GNUNET_free(bme);
504  map->size--;
505  return GNUNET_YES;
506  }
507  p = bme;
508  }
509  }
510  return GNUNET_NO;
511 }
512 
513 
522 int
525  const struct GNUNET_HashCode *key)
526 {
527  union MapEntry me;
528  unsigned int i;
529  int ret;
530 
531  map->modification_counter++;
532 
533  ret = 0;
534  i = idx_of(map, key);
535  me = map->map[i];
536  if (map->use_small_entries)
537  {
538  struct SmallMapEntry *sme;
539  struct SmallMapEntry *p;
540 
541  p = NULL;
542  sme = me.sme;
543  while (NULL != sme)
544  {
545  if (0 == GNUNET_memcmp(key, sme->key))
546  {
547  if (NULL == p)
548  map->map[i].sme = sme->next;
549  else
550  p->next = sme->next;
551  update_next_cache_sme(map, sme);
552  GNUNET_free(sme);
553  map->size--;
554  if (NULL == p)
555  sme = map->map[i].sme;
556  else
557  sme = p->next;
558  ret++;
559  }
560  else
561  {
562  p = sme;
563  sme = sme->next;
564  }
565  }
566  }
567  else
568  {
569  struct BigMapEntry *bme;
570  struct BigMapEntry *p;
571 
572  p = NULL;
573  bme = me.bme;
574  while (NULL != bme)
575  {
576  if (0 == GNUNET_memcmp(key, &bme->key))
577  {
578  if (NULL == p)
579  map->map[i].bme = bme->next;
580  else
581  p->next = bme->next;
582  update_next_cache_bme(map, bme);
583  GNUNET_free(bme);
584  map->size--;
585  if (NULL == p)
586  bme = map->map[i].bme;
587  else
588  bme = p->next;
589  ret++;
590  }
591  else
592  {
593  p = bme;
594  bme = bme->next;
595  }
596  }
597  }
598  return ret;
599 }
600 
601 
610 static int
611 remove_all(void *cls, const struct GNUNET_HashCode *key, void *value)
612 {
613  struct GNUNET_CONTAINER_MultiHashMap *map = cls;
614 
616  GNUNET_CONTAINER_multihashmap_remove(map, key, value));
617  return GNUNET_OK;
618 }
619 
620 
629 unsigned int
631 {
632  unsigned int ret;
633 
634  ret = map->size;
636  return ret;
637 }
638 
639 
649 int
651  const struct GNUNET_CONTAINER_MultiHashMap *map,
652  const struct GNUNET_HashCode *key)
653 {
654  union MapEntry me;
655 
656  me = map->map[idx_of(map, key)];
657  if (map->use_small_entries)
658  {
659  struct SmallMapEntry *sme;
660 
661  for (sme = me.sme; NULL != sme; sme = sme->next)
662  if (0 == GNUNET_memcmp(key, sme->key))
663  return GNUNET_YES;
664  }
665  else
666  {
667  struct BigMapEntry *bme;
668 
669  for (bme = me.bme; NULL != bme; bme = bme->next)
670  if (0 == GNUNET_memcmp(key, &bme->key))
671  return GNUNET_YES;
672  }
673  return GNUNET_NO;
674 }
675 
676 
687 int
689  const struct GNUNET_CONTAINER_MultiHashMap *map,
690  const struct GNUNET_HashCode *key,
691  const void *value)
692 {
693  union MapEntry me;
694 
695  me = map->map[idx_of(map, key)];
696  if (map->use_small_entries)
697  {
698  struct SmallMapEntry *sme;
699 
700  for (sme = me.sme; NULL != sme; sme = sme->next)
701  if ((0 == GNUNET_memcmp(key, sme->key)) && (sme->value == value))
702  return GNUNET_YES;
703  }
704  else
705  {
706  struct BigMapEntry *bme;
707 
708  for (bme = me.bme; NULL != bme; bme = bme->next)
709  if ((0 == GNUNET_memcmp(key, &bme->key)) && (bme->value == value))
710  return GNUNET_YES;
711  }
712  return GNUNET_NO;
713 }
714 
715 
721 static void
723 {
724  union MapEntry *old_map;
725  union MapEntry *new_map;
726  unsigned int old_len;
727  unsigned int new_len;
728  unsigned int idx;
729 
730  old_map = map->map;
731  old_len = map->map_length;
732  GNUNET_assert(0 != old_len);
733  new_len = old_len * 2;
734  if (0 == new_len) /* 2^31 * 2 == 0 */
735  new_len = old_len; /* never use 0 */
736  if (new_len == old_len)
737  return; /* nothing changed */
738  new_map = GNUNET_malloc_large(new_len * sizeof(union MapEntry));
739  if (NULL == new_map)
740  return; /* grow not possible */
741  map->modification_counter++;
742  map->map_length = new_len;
743  map->map = new_map;
744  for (unsigned int i = 0; i < old_len; i++)
745  {
746  if (map->use_small_entries)
747  {
748  struct SmallMapEntry *sme;
749 
750  while (NULL != (sme = old_map[i].sme))
751  {
752  old_map[i].sme = sme->next;
753  idx = idx_of(map, sme->key);
754  sme->next = new_map[idx].sme;
755  new_map[idx].sme = sme;
756  }
757  }
758  else
759  {
760  struct BigMapEntry *bme;
761 
762  while (NULL != (bme = old_map[i].bme))
763  {
764  old_map[i].bme = bme->next;
765  idx = idx_of(map, &bme->key);
766  bme->next = new_map[idx].bme;
767  new_map[idx].bme = bme;
768  }
769  }
770  }
771  GNUNET_free(old_map);
772 }
773 
774 
787 int
789  const struct GNUNET_HashCode *key,
790  void *value,
792 {
793  union MapEntry me;
794  unsigned int i;
795 
796  i = idx_of(map, key);
799  {
800  me = map->map[i];
801  if (map->use_small_entries)
802  {
803  struct SmallMapEntry *sme;
804 
805  for (sme = me.sme; NULL != sme; sme = sme->next)
806  if (0 == GNUNET_memcmp(key, sme->key))
807  {
809  return GNUNET_SYSERR;
810  sme->value = value;
811  return GNUNET_NO;
812  }
813  }
814  else
815  {
816  struct BigMapEntry *bme;
817 
818  for (bme = me.bme; NULL != bme; bme = bme->next)
819  if (0 == GNUNET_memcmp(key, &bme->key))
820  {
822  return GNUNET_SYSERR;
823  bme->value = value;
824  return GNUNET_NO;
825  }
826  }
827  }
828  if (map->size / 3 >= map->map_length / 4)
829  {
830  grow(map);
831  i = idx_of(map, key);
832  }
833  if (map->use_small_entries)
834  {
835  struct SmallMapEntry *sme;
836 
837  sme = GNUNET_new(struct SmallMapEntry);
838  sme->key = key;
839  sme->value = value;
840  sme->next = map->map[i].sme;
841  map->map[i].sme = sme;
842  }
843  else
844  {
845  struct BigMapEntry *bme;
846 
847  bme = GNUNET_new(struct BigMapEntry);
848  bme->key = *key;
849  bme->value = value;
850  bme->next = map->map[i].bme;
851  map->map[i].bme = bme;
852  }
853  map->size++;
854  return GNUNET_OK;
855 }
856 
857 
868 int
871  const struct GNUNET_HashCode *key,
873  void *it_cls)
874 {
875  int count;
876  union MapEntry *me;
877  union MapEntry *ce;
878 
879  ce = &map->next_cache[map->next_cache_off];
881  count = 0;
882  me = &map->map[idx_of(map, key)];
883  if (map->use_small_entries)
884  {
885  struct SmallMapEntry *sme;
886 
887  ce->sme = me->sme;
888  while (NULL != (sme = ce->sme))
889  {
890  ce->sme = sme->next;
891  if (0 != GNUNET_memcmp(key, sme->key))
892  continue;
893  if ((NULL != it) && (GNUNET_OK != it(it_cls, key, sme->value)))
894  {
896  return GNUNET_SYSERR;
897  }
898  count++;
899  }
900  }
901  else
902  {
903  struct BigMapEntry *bme;
904 
905  ce->bme = me->bme;
906  while (NULL != (bme = ce->bme))
907  {
908  ce->bme = bme->next;
909  if (0 != GNUNET_memcmp(key, &bme->key))
910  continue;
911  if ((NULL != it) && (GNUNET_OK != it(it_cls, key, bme->value)))
912  {
914  return GNUNET_SYSERR;
915  }
916  count++;
917  }
918  }
920  return count;
921 }
922 
923 
935 unsigned int
937  const struct GNUNET_CONTAINER_MultiHashMap *map,
939  void *it_cls)
940 {
941  unsigned int off;
942  unsigned int idx;
943  union MapEntry me;
944 
945  if (0 == map->size)
946  return 0;
947  if (NULL == it)
948  return 1;
950  for (idx = 0; idx < map->map_length; idx++)
951  {
952  me = map->map[idx];
953  if (map->use_small_entries)
954  {
955  struct SmallMapEntry *sme;
956  struct SmallMapEntry *nxt;
957 
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  }
971  else
972  {
973  struct BigMapEntry *bme;
974  struct BigMapEntry *nxt;
975 
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  }
989  }
990  GNUNET_break(0);
991  return GNUNET_SYSERR;
992 }
993 
994 
1009  const struct GNUNET_CONTAINER_MultiHashMap *map)
1010 {
1012 
1014  iter->map = map;
1016  iter->me = map->map[0];
1017  return iter;
1018 }
1019 
1020 
1035 int
1038  struct GNUNET_HashCode *key,
1039  const void **value)
1040 {
1041  /* make sure the map has not been modified */
1043 
1044  /* look for the next entry, skipping empty buckets */
1045  while (1)
1046  {
1047  if (iter->idx >= iter->map->map_length)
1048  return GNUNET_NO;
1049  if (GNUNET_YES == iter->map->use_small_entries)
1050  {
1051  if (NULL != iter->me.sme)
1052  {
1053  if (NULL != key)
1054  *key = *iter->me.sme->key;
1055  if (NULL != value)
1056  *value = iter->me.sme->value;
1057  iter->me.sme = iter->me.sme->next;
1058  return GNUNET_YES;
1059  }
1060  }
1061  else
1062  {
1063  if (NULL != iter->me.bme)
1064  {
1065  if (NULL != key)
1066  *key = iter->me.bme->key;
1067  if (NULL != value)
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 
1079 
1085 void
1088 {
1089  GNUNET_free(iter);
1090 }
1091 
1092 
1093 /* 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.
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)...
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.
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...