GNUnet  0.10.x
container_multipeermap.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_util_lib.h"
28 
29 #define LOG(kind, ...) \
30  GNUNET_log_from (kind, "util-container-multipeermap", __VA_ARGS__)
31 
38 #define NEXT_CACHE_SIZE 16
39 
43 struct BigMapEntry
44 {
45 
49  void *value;
50 
54  struct BigMapEntry *next;
55 
60 };
61 
62 
66 struct SmallMapEntry
67 {
68 
72  void *value;
73 
77  struct SmallMapEntry *next;
78 
82  const struct GNUNET_PeerIdentity *key;
83 };
84 
85 
89 union MapEntry
90 {
94  struct SmallMapEntry *sme;
95 
99  struct BigMapEntry *bme;
100 };
101 
102 
107 {
111  union MapEntry *map;
112 
116  unsigned int size;
117 
121  unsigned int map_length;
122 
128 
133  unsigned int modification_counter;
134 
140  union MapEntry next_cache[NEXT_CACHE_SIZE];
141 
146  unsigned int next_cache_off;
147 };
148 
149 
155 {
159  union MapEntry me;
160 
164  unsigned int idx;
165 
170  unsigned int modification_counter;
171 
176 };
177 
178 
195 GNUNET_CONTAINER_multipeermap_create (unsigned int len, int do_not_copy_keys)
196 {
198 
199  GNUNET_assert (len > 0);
201  map->map = GNUNET_malloc_large (len * sizeof (union MapEntry));
202  if (NULL == map->map)
203  {
204  GNUNET_free (map);
205  return NULL;
206  }
207  map->map_length = len;
208  map->use_small_entries = do_not_copy_keys;
209  return map;
210 }
211 
212 
219 void
222 {
223  GNUNET_assert (0 == map->next_cache_off);
224  for (unsigned int i = 0; i < map->map_length; i++)
225  {
226  union MapEntry me;
227 
228  me = map->map[i];
229  if (map->use_small_entries)
230  {
231  struct SmallMapEntry *sme;
232  struct SmallMapEntry *nxt;
233 
234  nxt = me.sme;
235  while (NULL != (sme = nxt))
236  {
237  nxt = sme->next;
238  GNUNET_free (sme);
239  }
240  me.sme = NULL;
241  }
242  else
243  {
244  struct BigMapEntry *bme;
245  struct BigMapEntry *nxt;
246 
247  nxt = me.bme;
248  while (NULL != (bme = nxt))
249  {
250  nxt = bme->next;
251  GNUNET_free (bme);
252  }
253  me.bme = NULL;
254  }
255  }
256  GNUNET_free (map->map);
257  GNUNET_free (map);
258 }
259 
260 
268 static unsigned int
270  const struct GNUNET_PeerIdentity *key)
271 {
272  unsigned int kx;
273 
274  GNUNET_assert (NULL != map);
275  GNUNET_memcpy (&kx, key, sizeof (kx));
276  return kx % map->map_length;
277 }
278 
279 
286 unsigned int
288  const struct GNUNET_CONTAINER_MultiPeerMap *map)
289 {
290  return map->size;
291 }
292 
293 
304 void *
306  const struct GNUNET_CONTAINER_MultiPeerMap *map,
307  const struct GNUNET_PeerIdentity *key)
308 {
309  union MapEntry me;
310 
311  me = map->map[idx_of (map, key)];
312  if (map->use_small_entries)
313  {
314  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
315  if (0 == GNUNET_memcmp (key, sme->key))
316  return sme->value;
317  }
318  else
319  {
320  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
321  if (0 == GNUNET_memcmp (key, &bme->key))
322  return bme->value;
323  }
324  return NULL;
325 }
326 
327 
337 int
341  void *it_cls)
342 {
343  int count;
344  union MapEntry me;
345  union MapEntry *ce;
346  struct GNUNET_PeerIdentity kc;
347 
348  count = 0;
349  GNUNET_assert (NULL != map);
350  ce = &map->next_cache[map->next_cache_off];
352  for (unsigned int i = 0; i < map->map_length; i++)
353  {
354  me = map->map[i];
355  if (map->use_small_entries)
356  {
357  struct SmallMapEntry *sme;
358 
359  ce->sme = me.sme;
360  while (NULL != (sme = ce->sme))
361  {
362  ce->sme = sme->next;
363  if (NULL != it)
364  {
365  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
366  {
368  return GNUNET_SYSERR;
369  }
370  }
371  count++;
372  }
373  }
374  else
375  {
376  struct BigMapEntry *bme;
377 
378  ce->bme = me.bme;
379  while (NULL != (bme = ce->bme))
380  {
381  ce->bme = bme->next;
382  if (NULL != it)
383  {
384  kc = bme->key;
385  if (GNUNET_OK != it (it_cls, &kc, bme->value))
386  {
388  return GNUNET_SYSERR;
389  }
390  }
391  count++;
392  }
393  }
394  }
396  return count;
397 }
398 
399 
407 static void
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 
424 static void
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 
445 int
447  const struct GNUNET_PeerIdentity *key,
448  const void *value)
449 {
450  union MapEntry me;
451  unsigned int i;
452 
453  map->modification_counter++;
454  i = idx_of (map, key);
455  me = map->map[i];
456  if (map->use_small_entries)
457  {
458  struct SmallMapEntry *p = NULL;
459 
460  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
461  {
462  if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
463  {
464  if (NULL == p)
465  map->map[i].sme = sme->next;
466  else
467  p->next = sme->next;
468  update_next_cache_sme (map, sme);
469  GNUNET_free (sme);
470  map->size--;
471  return GNUNET_YES;
472  }
473  p = sme;
474  }
475  }
476  else
477  {
478  struct BigMapEntry *p = NULL;
479 
480  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
481  {
482  if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
483  {
484  if (NULL == p)
485  map->map[i].bme = bme->next;
486  else
487  p->next = bme->next;
488  update_next_cache_bme (map, bme);
489  GNUNET_free (bme);
490  map->size--;
491  return GNUNET_YES;
492  }
493  p = bme;
494  }
495  }
496  return GNUNET_NO;
497 }
498 
499 
508 int
511  const struct GNUNET_PeerIdentity *key)
512 {
513  union MapEntry me;
514  unsigned int i;
515  int ret;
516 
517  map->modification_counter++;
518 
519  ret = 0;
520  i = idx_of (map, key);
521  me = map->map[i];
522  if (map->use_small_entries)
523  {
524  struct SmallMapEntry *sme;
525  struct SmallMapEntry *p;
526 
527  p = NULL;
528  sme = me.sme;
529  while (NULL != sme)
530  {
531  if (0 == GNUNET_memcmp (key, sme->key))
532  {
533  if (NULL == p)
534  map->map[i].sme = sme->next;
535  else
536  p->next = sme->next;
537  update_next_cache_sme (map, sme);
538  GNUNET_free (sme);
539  map->size--;
540  if (NULL == p)
541  sme = map->map[i].sme;
542  else
543  sme = p->next;
544  ret++;
545  }
546  else
547  {
548  p = sme;
549  sme = sme->next;
550  }
551  }
552  }
553  else
554  {
555  struct BigMapEntry *bme;
556  struct BigMapEntry *p;
557 
558  p = NULL;
559  bme = me.bme;
560  while (NULL != bme)
561  {
562  if (0 == GNUNET_memcmp (key, &bme->key))
563  {
564  if (NULL == p)
565  map->map[i].bme = bme->next;
566  else
567  p->next = bme->next;
568  update_next_cache_bme (map, bme);
569  GNUNET_free (bme);
570  map->size--;
571  if (NULL == p)
572  bme = map->map[i].bme;
573  else
574  bme = p->next;
575  ret++;
576  }
577  else
578  {
579  p = bme;
580  bme = bme->next;
581  }
582  }
583  }
584  return ret;
585 }
586 
587 
597 int
599  const struct GNUNET_CONTAINER_MultiPeerMap *map,
600  const struct GNUNET_PeerIdentity *key)
601 {
602  union MapEntry me;
603 
604  me = map->map[idx_of (map, key)];
605  if (map->use_small_entries)
606  {
607  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
608  if (0 == GNUNET_memcmp (key, sme->key))
609  return GNUNET_YES;
610  }
611  else
612  {
613  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
614  if (0 == GNUNET_memcmp (key, &bme->key))
615  return GNUNET_YES;
616  }
617  return GNUNET_NO;
618 }
619 
620 
631 int
633  const struct GNUNET_CONTAINER_MultiPeerMap *map,
634  const struct GNUNET_PeerIdentity *key,
635  const void *value)
636 {
637  union MapEntry me;
638 
639  me = map->map[idx_of (map, key)];
640  if (map->use_small_entries)
641  {
642  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
643  if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
644  return GNUNET_YES;
645  }
646  else
647  {
648  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
649  if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
650  return GNUNET_YES;
651  }
652  return GNUNET_NO;
653 }
654 
655 
661 static void
663 {
664  union MapEntry *old_map;
665  union MapEntry *new_map;
666  unsigned int old_len;
667  unsigned int new_len;
668  unsigned int idx;
669 
670  old_map = map->map;
671  old_len = map->map_length;
672  GNUNET_assert (0 != old_len);
673  new_len = old_len * 2;
674  if (0 == new_len) /* 2^31 * 2 == 0 */
675  new_len = old_len; /* never use 0 */
676  if (new_len == old_len)
677  return; /* nothing changed */
678  new_map = GNUNET_malloc_large (new_len * sizeof (union MapEntry));
679  if (NULL == new_map)
680  return; /* grow not possible */
681  map->modification_counter++;
682  map->map_length = new_len;
683  map->map = new_map;
684  for (unsigned int i = 0; i < old_len; i++)
685  {
686  if (map->use_small_entries)
687  {
688  struct SmallMapEntry *sme;
689 
690  while (NULL != (sme = old_map[i].sme))
691  {
692  old_map[i].sme = sme->next;
693  idx = idx_of (map, sme->key);
694  sme->next = new_map[idx].sme;
695  new_map[idx].sme = sme;
696  }
697  }
698  else
699  {
700  struct BigMapEntry *bme;
701 
702  while (NULL != (bme = old_map[i].bme))
703  {
704  old_map[i].bme = bme->next;
705  idx = idx_of (map, &bme->key);
706  bme->next = new_map[idx].bme;
707  new_map[idx].bme = bme;
708  }
709  }
710  }
711  GNUNET_free (old_map);
712 }
713 
714 
727 int
729  const struct GNUNET_PeerIdentity *key,
730  void *value,
732 {
733  union MapEntry me;
734  unsigned int i;
735 
736  i = idx_of (map, key);
739  {
740  me = map->map[i];
741  if (map->use_small_entries)
742  {
743  struct SmallMapEntry *sme;
744 
745  for (sme = me.sme; NULL != sme; sme = sme->next)
746  if (0 == GNUNET_memcmp (key, sme->key))
747  {
749  return GNUNET_SYSERR;
750  sme->value = value;
751  return GNUNET_NO;
752  }
753  }
754  else
755  {
756  struct BigMapEntry *bme;
757 
758  for (bme = me.bme; NULL != bme; bme = bme->next)
759  if (0 == GNUNET_memcmp (key, &bme->key))
760  {
762  return GNUNET_SYSERR;
763  bme->value = value;
764  return GNUNET_NO;
765  }
766  }
767  }
768  if (map->size / 3 >= map->map_length / 4)
769  {
770  grow (map);
771  i = idx_of (map, key);
772  }
773  if (map->use_small_entries)
774  {
775  struct SmallMapEntry *sme;
776 
777  sme = GNUNET_new (struct SmallMapEntry);
778  sme->key = key;
779  sme->value = value;
780  sme->next = map->map[i].sme;
781  map->map[i].sme = sme;
782  }
783  else
784  {
785  struct BigMapEntry *bme;
786 
787  bme = GNUNET_new (struct BigMapEntry);
788  bme->key = *key;
789  bme->value = value;
790  bme->next = map->map[i].bme;
791  map->map[i].bme = bme;
792  }
793  map->size++;
794  return GNUNET_OK;
795 }
796 
797 
808 int
811  const struct GNUNET_PeerIdentity *key,
813  void *it_cls)
814 {
815  int count;
816  union MapEntry me;
817  union MapEntry *ce;
818 
819  ce = &map->next_cache[map->next_cache_off];
821  count = 0;
822  me = map->map[idx_of (map, key)];
823  if (map->use_small_entries)
824  {
825  struct SmallMapEntry *sme;
826 
827  ce->sme = me.sme;
828  while (NULL != (sme = ce->sme))
829  {
830  ce->sme = sme->next;
831  if (0 != GNUNET_memcmp (key, sme->key))
832  continue;
833  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
834  {
836  return GNUNET_SYSERR;
837  }
838  count++;
839  }
840  }
841  else
842  {
843  struct BigMapEntry *bme;
844 
845  ce->bme = me.bme;
846  while (NULL != (bme = ce->bme))
847  {
848  ce->bme = bme->next;
849  if (0 != GNUNET_memcmp (key, &bme->key))
850  continue;
851  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
852  {
854  return GNUNET_SYSERR;
855  }
856  count++;
857  }
858  }
860  return count;
861 }
862 
863 
875 unsigned int
877  const struct GNUNET_CONTAINER_MultiPeerMap *map,
879  void *it_cls)
880 {
881  unsigned int off;
882  union MapEntry me;
883 
884  if (0 == map->size)
885  return 0;
886  if (NULL == it)
887  return 1;
889  for (unsigned int idx = 0; idx < map->map_length; idx++)
890  {
891  me = map->map[idx];
892  if (map->use_small_entries)
893  {
894  struct SmallMapEntry *sme;
895  struct SmallMapEntry *nxt;
896 
897  nxt = me.sme;
898  while (NULL != (sme = nxt))
899  {
900  nxt = sme->next;
901  if (0 == off)
902  {
903  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
904  return GNUNET_SYSERR;
905  return 1;
906  }
907  off--;
908  }
909  }
910  else
911  {
912  struct BigMapEntry *bme;
913  struct BigMapEntry *nxt;
914 
915  nxt = me.bme;
916  while (NULL != (bme = nxt))
917  {
918  nxt = bme->next;
919  if (0 == off)
920  {
921  if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
922  return GNUNET_SYSERR;
923  return 1;
924  }
925  off--;
926  }
927  }
928  }
929  GNUNET_break (0);
930  return GNUNET_SYSERR;
931 }
932 
933 
948  const struct GNUNET_CONTAINER_MultiPeerMap *map)
949 {
951 
953  iter->map = map;
955  iter->me = map->map[0];
956  return iter;
957 }
958 
959 
974 int
977  struct GNUNET_PeerIdentity *key,
978  const void **value)
979 {
980  /* make sure the map has not been modified */
982 
983  /* look for the next entry, skipping empty buckets */
984  while (1)
985  {
986  if (iter->idx >= iter->map->map_length)
987  return GNUNET_NO;
988  if (GNUNET_YES == iter->map->use_small_entries)
989  {
990  if (NULL != iter->me.sme)
991  {
992  if (NULL != key)
993  *key = *iter->me.sme->key;
994  if (NULL != value)
995  *value = iter->me.sme->value;
996  iter->me.sme = iter->me.sme->next;
997  return GNUNET_YES;
998  }
999  }
1000  else
1001  {
1002  if (NULL != iter->me.bme)
1003  {
1004  if (NULL != key)
1005  *key = iter->me.bme->key;
1006  if (NULL != value)
1007  *value = iter->me.bme->value;
1008  iter->me.bme = iter->me.bme->next;
1009  return GNUNET_YES;
1010  }
1011  }
1012  iter->idx += 1;
1013  if (iter->idx < iter->map->map_length)
1014  iter->me = iter->map->map[iter->idx];
1015  }
1016 }
1017 
1018 
1024 void
1027 {
1028  GNUNET_free (iter);
1029 }
1030 
1031 
1032 /* end of container_multipeermap.c */
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
GNUNET_CONTAINER_MultiHashMapOption
Options for storing values in the HashMap.
struct SmallMapEntry * next
If there is a hash collision, we create a linked list.
void * value
Value of the entry.
int GNUNET_CONTAINER_multipeermap_remove_all(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Remove all entries for the given key from the map.
static void grow(struct GNUNET_CONTAINER_MultiPeerMap *map)
Grow the given map to a more appropriate size.
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...
unsigned int GNUNET_CONTAINER_multipeermap_get_random(const struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Call it on a random value from the map, or not at all if the map is empty.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
static void update_next_cache_bme(struct GNUNET_CONTAINER_MultiPeerMap *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...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned int size
Number of entries in the map.
static void update_next_cache_sme(struct GNUNET_CONTAINER_MultiPeerMap *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...
void GNUNET_CONTAINER_multipeermap_iterator_destroy(struct GNUNET_CONTAINER_MultiPeerMapIterator *iter)
Destroy a multipeermap iterator.
int(* GNUNET_CONTAINER_PeerMapIterator)(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
const struct GNUNET_HashCode * key
Key for the entry.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
int GNUNET_CONTAINER_multipeermap_iterator_next(struct GNUNET_CONTAINER_MultiPeerMapIterator *iter, struct GNUNET_PeerIdentity *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
#define GNUNET_NO
Definition: gnunet_common.h:81
void * value
Value of the entry.
const struct GNUNET_PeerIdentity * key
Key for 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.
unsigned int idx
Current bucket index.
struct SmallMapEntry * sme
Variant used if map entries only contain a pointer to the key.
unsigned int modification_counter
Modification counter as observed on the map when the iterator was created.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_malloc_large(size)
Wrapper around malloc.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct BigMapEntry * next
If there is a hash collision, we create a linked list.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
static struct GNUNET_CONTAINER_MultiPeerMap * map
Handle to the map used to store old latency values for peers.
union MapEntry next_cache[16]
Map entries indicating iteration positions currently in use by GNUNET_CONTAINER_multihashmap_get_mult...
#define GNUNET_memcpy(dst, src, n)
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_...
Entry in the map.
union MapEntry * map
All of our buckets.
Randomness for IVs etc.
Internal representation of the hash map.
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
unsigned int modification_counter
Counts the destructive modifications (grow, remove) to the map, so that iterators can check if they a...
static unsigned int idx_of(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Compute the index of the bucket for the given key.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
union MapEntry me
Position in the bucket &#39;idx&#39;.
Allow multiple values with the same key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
The identity of the host (wraps the signing key of the peer).
int GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
An entry in the hash map with just a pointer to the key.
unsigned int next_cache_off
Offset of next_cache entries in use, must be smaller than NEXT_CACHE_SIZE.
#define NEXT_CACHE_SIZE
Maximum recursion depth for callbacks of GNUNET_CONTAINER_multihashmap_get_multiple() themselve s aga...
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
struct GNUNET_CONTAINER_MultiPeerMapIterator * GNUNET_CONTAINER_multipeermap_iterator_create(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Create an iterator for a multipeermap.
An entry in the hash map with the full key.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct BigMapEntry * bme
Variant used if map entries contain the full key.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
unsigned int map_length
Length of the "map" array.
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_HashCode key
Key for the entry.
const struct GNUNET_CONTAINER_MultiPeerMap * map
Map that we are iterating over.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...