GNUnet  0.11.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 {
48  void *value;
49 
53  struct BigMapEntry *next;
54 
59 };
60 
61 
65 struct SmallMapEntry
66 {
70  void *value;
71 
75  struct SmallMapEntry *next;
76 
80  const struct GNUNET_PeerIdentity *key;
81 };
82 
83 
87 union MapEntry
88 {
92  struct SmallMapEntry *sme;
93 
97  struct BigMapEntry *bme;
98 };
99 
100 
105 {
109  union MapEntry *map;
110 
114  unsigned int size;
115 
119  unsigned int map_length;
120 
126 
131  unsigned int modification_counter;
132 
138  union MapEntry next_cache[NEXT_CACHE_SIZE];
139 
144  unsigned int next_cache_off;
145 };
146 
147 
153 {
157  union MapEntry me;
158 
162  unsigned int idx;
163 
168  unsigned int modification_counter;
169 
174 };
175 
176 
193 GNUNET_CONTAINER_multipeermap_create (unsigned int len, int do_not_copy_keys)
194 {
196 
197  GNUNET_assert (len > 0);
199  map->map = GNUNET_malloc_large (len * sizeof(union MapEntry));
200  if (NULL == map->map)
201  {
202  GNUNET_free (map);
203  return NULL;
204  }
205  map->map_length = len;
206  map->use_small_entries = do_not_copy_keys;
207  return map;
208 }
209 
210 
217 void
220 {
221  GNUNET_assert (0 == map->next_cache_off);
222  for (unsigned int i = 0; i < map->map_length; i++)
223  {
224  union MapEntry me;
225 
226  me = map->map[i];
227  if (map->use_small_entries)
228  {
229  struct SmallMapEntry *sme;
230  struct SmallMapEntry *nxt;
231 
232  nxt = me.sme;
233  while (NULL != (sme = nxt))
234  {
235  nxt = sme->next;
236  GNUNET_free (sme);
237  }
238  me.sme = NULL;
239  }
240  else
241  {
242  struct BigMapEntry *bme;
243  struct BigMapEntry *nxt;
244 
245  nxt = me.bme;
246  while (NULL != (bme = nxt))
247  {
248  nxt = bme->next;
249  GNUNET_free (bme);
250  }
251  me.bme = NULL;
252  }
253  }
254  GNUNET_free (map->map);
255  GNUNET_free (map);
256 }
257 
258 
266 static unsigned int
268  const struct GNUNET_PeerIdentity *key)
269 {
270  unsigned int kx;
271 
272  GNUNET_assert (NULL != map);
273  GNUNET_memcpy (&kx, key, sizeof(kx));
274  return kx % map->map_length;
275 }
276 
277 
284 unsigned int
286  const struct GNUNET_CONTAINER_MultiPeerMap *map)
287 {
288  return map->size;
289 }
290 
291 
302 void *
304  const struct GNUNET_CONTAINER_MultiPeerMap *map,
305  const struct GNUNET_PeerIdentity *key)
306 {
307  union MapEntry me;
308 
309  me = map->map[idx_of (map, key)];
310  if (map->use_small_entries)
311  {
312  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
313  if (0 == GNUNET_memcmp (key, sme->key))
314  return sme->value;
315  }
316  else
317  {
318  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
319  if (0 == GNUNET_memcmp (key, &bme->key))
320  return bme->value;
321  }
322  return NULL;
323 }
324 
325 
335 int
339  void *it_cls)
340 {
341  int count;
342  union MapEntry me;
343  union MapEntry *ce;
344  struct GNUNET_PeerIdentity kc;
345 
346  count = 0;
347  GNUNET_assert (NULL != map);
348  ce = &map->next_cache[map->next_cache_off];
350  for (unsigned int i = 0; i < map->map_length; i++)
351  {
352  me = map->map[i];
353  if (map->use_small_entries)
354  {
355  struct SmallMapEntry *sme;
356 
357  ce->sme = me.sme;
358  while (NULL != (sme = ce->sme))
359  {
360  ce->sme = sme->next;
361  if (NULL != it)
362  {
363  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
364  {
366  return GNUNET_SYSERR;
367  }
368  }
369  count++;
370  }
371  }
372  else
373  {
374  struct BigMapEntry *bme;
375 
376  ce->bme = me.bme;
377  while (NULL != (bme = ce->bme))
378  {
379  ce->bme = bme->next;
380  if (NULL != it)
381  {
382  kc = bme->key;
383  if (GNUNET_OK != it (it_cls, &kc, bme->value))
384  {
386  return GNUNET_SYSERR;
387  }
388  }
389  count++;
390  }
391  }
392  }
394  return count;
395 }
396 
397 
405 static void
407  const struct BigMapEntry *bme)
408 {
409  for (unsigned int i = 0; i < map->next_cache_off; i++)
410  if (map->next_cache[i].bme == bme)
411  map->next_cache[i].bme = bme->next;
412 }
413 
414 
422 static void
424  const struct SmallMapEntry *sme)
425 {
426  for (unsigned int i = 0; i < map->next_cache_off; i++)
427  if (map->next_cache[i].sme == sme)
428  map->next_cache[i].sme = sme->next;
429 }
430 
431 
443 int
445  const struct GNUNET_PeerIdentity *key,
446  const void *value)
447 {
448  union MapEntry me;
449  unsigned int i;
450 
451  map->modification_counter++;
452  i = idx_of (map, key);
453  me = map->map[i];
454  if (map->use_small_entries)
455  {
456  struct SmallMapEntry *p = NULL;
457 
458  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
459  {
460  if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
461  {
462  if (NULL == p)
463  map->map[i].sme = sme->next;
464  else
465  p->next = sme->next;
466  update_next_cache_sme (map, sme);
467  GNUNET_free (sme);
468  map->size--;
469  return GNUNET_YES;
470  }
471  p = sme;
472  }
473  }
474  else
475  {
476  struct BigMapEntry *p = NULL;
477 
478  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
479  {
480  if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
481  {
482  if (NULL == p)
483  map->map[i].bme = bme->next;
484  else
485  p->next = bme->next;
486  update_next_cache_bme (map, bme);
487  GNUNET_free (bme);
488  map->size--;
489  return GNUNET_YES;
490  }
491  p = bme;
492  }
493  }
494  return GNUNET_NO;
495 }
496 
497 
506 int
509  const struct GNUNET_PeerIdentity *key)
510 {
511  union MapEntry me;
512  unsigned int i;
513  int ret;
514 
515  map->modification_counter++;
516 
517  ret = 0;
518  i = idx_of (map, key);
519  me = map->map[i];
520  if (map->use_small_entries)
521  {
522  struct SmallMapEntry *sme;
523  struct SmallMapEntry *p;
524 
525  p = NULL;
526  sme = me.sme;
527  while (NULL != sme)
528  {
529  if (0 == GNUNET_memcmp (key, sme->key))
530  {
531  if (NULL == p)
532  map->map[i].sme = sme->next;
533  else
534  p->next = sme->next;
535  update_next_cache_sme (map, sme);
536  GNUNET_free (sme);
537  map->size--;
538  if (NULL == p)
539  sme = map->map[i].sme;
540  else
541  sme = p->next;
542  ret++;
543  }
544  else
545  {
546  p = sme;
547  sme = sme->next;
548  }
549  }
550  }
551  else
552  {
553  struct BigMapEntry *bme;
554  struct BigMapEntry *p;
555 
556  p = NULL;
557  bme = me.bme;
558  while (NULL != bme)
559  {
560  if (0 == GNUNET_memcmp (key, &bme->key))
561  {
562  if (NULL == p)
563  map->map[i].bme = bme->next;
564  else
565  p->next = bme->next;
566  update_next_cache_bme (map, bme);
567  GNUNET_free (bme);
568  map->size--;
569  if (NULL == p)
570  bme = map->map[i].bme;
571  else
572  bme = p->next;
573  ret++;
574  }
575  else
576  {
577  p = bme;
578  bme = bme->next;
579  }
580  }
581  }
582  return ret;
583 }
584 
585 
595 int
597  const struct GNUNET_CONTAINER_MultiPeerMap *map,
598  const struct GNUNET_PeerIdentity *key)
599 {
600  union MapEntry me;
601 
602  me = map->map[idx_of (map, key)];
603  if (map->use_small_entries)
604  {
605  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
606  if (0 == GNUNET_memcmp (key, sme->key))
607  return GNUNET_YES;
608  }
609  else
610  {
611  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
612  if (0 == GNUNET_memcmp (key, &bme->key))
613  return GNUNET_YES;
614  }
615  return GNUNET_NO;
616 }
617 
618 
629 int
631  const struct GNUNET_CONTAINER_MultiPeerMap *map,
632  const struct GNUNET_PeerIdentity *key,
633  const void *value)
634 {
635  union MapEntry me;
636 
637  me = map->map[idx_of (map, key)];
638  if (map->use_small_entries)
639  {
640  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
641  if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
642  return GNUNET_YES;
643  }
644  else
645  {
646  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
647  if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
648  return GNUNET_YES;
649  }
650  return GNUNET_NO;
651 }
652 
653 
659 static void
661 {
662  union MapEntry *old_map;
663  union MapEntry *new_map;
664  unsigned int old_len;
665  unsigned int new_len;
666  unsigned int idx;
667 
668  old_map = map->map;
669  old_len = map->map_length;
670  GNUNET_assert (0 != old_len);
671  new_len = old_len * 2;
672  if (0 == new_len) /* 2^31 * 2 == 0 */
673  new_len = old_len; /* never use 0 */
674  if (new_len == old_len)
675  return; /* nothing changed */
676  new_map = GNUNET_malloc_large (new_len * sizeof(union MapEntry));
677  if (NULL == new_map)
678  return; /* grow not possible */
679  map->modification_counter++;
680  map->map_length = new_len;
681  map->map = new_map;
682  for (unsigned int i = 0; i < old_len; i++)
683  {
684  if (map->use_small_entries)
685  {
686  struct SmallMapEntry *sme;
687 
688  while (NULL != (sme = old_map[i].sme))
689  {
690  old_map[i].sme = sme->next;
691  idx = idx_of (map, sme->key);
692  sme->next = new_map[idx].sme;
693  new_map[idx].sme = sme;
694  }
695  }
696  else
697  {
698  struct BigMapEntry *bme;
699 
700  while (NULL != (bme = old_map[i].bme))
701  {
702  old_map[i].bme = bme->next;
703  idx = idx_of (map, &bme->key);
704  bme->next = new_map[idx].bme;
705  new_map[idx].bme = bme;
706  }
707  }
708  }
709  GNUNET_free (old_map);
710 }
711 
712 
725 int
727  const struct GNUNET_PeerIdentity *key,
728  void *value,
730 {
731  union MapEntry me;
732  unsigned int i;
733 
734  i = idx_of (map, key);
737  {
738  me = map->map[i];
739  if (map->use_small_entries)
740  {
741  struct SmallMapEntry *sme;
742 
743  for (sme = me.sme; NULL != sme; sme = sme->next)
744  if (0 == GNUNET_memcmp (key, sme->key))
745  {
747  return GNUNET_SYSERR;
748  sme->value = value;
749  return GNUNET_NO;
750  }
751  }
752  else
753  {
754  struct BigMapEntry *bme;
755 
756  for (bme = me.bme; NULL != bme; bme = bme->next)
757  if (0 == GNUNET_memcmp (key, &bme->key))
758  {
760  return GNUNET_SYSERR;
761  bme->value = value;
762  return GNUNET_NO;
763  }
764  }
765  }
766  if (map->size / 3 >= map->map_length / 4)
767  {
768  grow (map);
769  i = idx_of (map, key);
770  }
771  if (map->use_small_entries)
772  {
773  struct SmallMapEntry *sme;
774 
775  sme = GNUNET_new (struct SmallMapEntry);
776  sme->key = key;
777  sme->value = value;
778  sme->next = map->map[i].sme;
779  map->map[i].sme = sme;
780  }
781  else
782  {
783  struct BigMapEntry *bme;
784 
785  bme = GNUNET_new (struct BigMapEntry);
786  bme->key = *key;
787  bme->value = value;
788  bme->next = map->map[i].bme;
789  map->map[i].bme = bme;
790  }
791  map->size++;
792  return GNUNET_OK;
793 }
794 
795 
806 int
809  const struct GNUNET_PeerIdentity *key,
811  void *it_cls)
812 {
813  int count;
814  union MapEntry me;
815  union MapEntry *ce;
816 
817  ce = &map->next_cache[map->next_cache_off];
819  count = 0;
820  me = map->map[idx_of (map, key)];
821  if (map->use_small_entries)
822  {
823  struct SmallMapEntry *sme;
824 
825  ce->sme = me.sme;
826  while (NULL != (sme = ce->sme))
827  {
828  ce->sme = sme->next;
829  if (0 != GNUNET_memcmp (key, sme->key))
830  continue;
831  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
832  {
834  return GNUNET_SYSERR;
835  }
836  count++;
837  }
838  }
839  else
840  {
841  struct BigMapEntry *bme;
842 
843  ce->bme = me.bme;
844  while (NULL != (bme = ce->bme))
845  {
846  ce->bme = bme->next;
847  if (0 != GNUNET_memcmp (key, &bme->key))
848  continue;
849  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
850  {
852  return GNUNET_SYSERR;
853  }
854  count++;
855  }
856  }
858  return count;
859 }
860 
861 
873 unsigned int
875  const struct GNUNET_CONTAINER_MultiPeerMap *map,
877  void *it_cls)
878 {
879  unsigned int off;
880  union MapEntry me;
881 
882  if (0 == map->size)
883  return 0;
884  if (NULL == it)
885  return 1;
887  for (unsigned int idx = 0; idx < map->map_length; idx++)
888  {
889  me = map->map[idx];
890  if (map->use_small_entries)
891  {
892  struct SmallMapEntry *sme;
893  struct SmallMapEntry *nxt;
894 
895  nxt = me.sme;
896  while (NULL != (sme = nxt))
897  {
898  nxt = sme->next;
899  if (0 == off)
900  {
901  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
902  return GNUNET_SYSERR;
903  return 1;
904  }
905  off--;
906  }
907  }
908  else
909  {
910  struct BigMapEntry *bme;
911  struct BigMapEntry *nxt;
912 
913  nxt = me.bme;
914  while (NULL != (bme = nxt))
915  {
916  nxt = bme->next;
917  if (0 == off)
918  {
919  if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
920  return GNUNET_SYSERR;
921  return 1;
922  }
923  off--;
924  }
925  }
926  }
927  GNUNET_break (0);
928  return GNUNET_SYSERR;
929 }
930 
931 
946  const struct GNUNET_CONTAINER_MultiPeerMap *map)
947 {
949 
951  iter->map = map;
953  iter->me = map->map[0];
954  return iter;
955 }
956 
957 
972 int
975  struct GNUNET_PeerIdentity *key,
976  const void **value)
977 {
978  /* make sure the map has not been modified */
980 
981  /* look for the next entry, skipping empty buckets */
982  while (1)
983  {
984  if (iter->idx >= iter->map->map_length)
985  return GNUNET_NO;
986  if (GNUNET_YES == iter->map->use_small_entries)
987  {
988  if (NULL != iter->me.sme)
989  {
990  if (NULL != key)
991  *key = *iter->me.sme->key;
992  if (NULL != value)
993  *value = iter->me.sme->value;
994  iter->me.sme = iter->me.sme->next;
995  return GNUNET_YES;
996  }
997  }
998  else
999  {
1000  if (NULL != iter->me.bme)
1001  {
1002  if (NULL != key)
1003  *key = iter->me.bme->key;
1004  if (NULL != value)
1005  *value = iter->me.bme->value;
1006  iter->me.bme = iter->me.bme->next;
1007  return GNUNET_YES;
1008  }
1009  }
1010  iter->idx += 1;
1011  if (iter->idx < iter->map->map_length)
1012  iter->me = iter->map->map[iter->idx];
1013  }
1014 }
1015 
1016 
1022 void
1025 {
1026  GNUNET_free (iter);
1027 }
1028 
1029 
1030 /* 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...
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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:78
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:75
#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.
#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...
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:76
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:77
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...