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 {
47  void *value;
48 
52  struct BigMapEntry *next;
53 
58 };
59 
60 
64 struct SmallMapEntry {
68  void *value;
69 
73  struct SmallMapEntry *next;
74 
78  const struct GNUNET_PeerIdentity *key;
79 };
80 
81 
85 union MapEntry {
89  struct SmallMapEntry *sme;
90 
94  struct BigMapEntry *bme;
95 };
96 
97 
105  union MapEntry *map;
106 
110  unsigned int size;
111 
115  unsigned int map_length;
116 
122 
127  unsigned int modification_counter;
128 
134  union MapEntry next_cache[NEXT_CACHE_SIZE];
135 
140  unsigned int next_cache_off;
141 };
142 
143 
152  union MapEntry me;
153 
157  unsigned int idx;
158 
163  unsigned int modification_counter;
164 
169 };
170 
171 
188 GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
189 {
191 
192  GNUNET_assert(len > 0);
194  map->map = GNUNET_malloc_large(len * sizeof(union MapEntry));
195  if (NULL == map->map)
196  {
197  GNUNET_free(map);
198  return NULL;
199  }
200  map->map_length = len;
201  map->use_small_entries = do_not_copy_keys;
202  return map;
203 }
204 
205 
212 void
215 {
216  GNUNET_assert(0 == map->next_cache_off);
217  for (unsigned int i = 0; i < map->map_length; i++)
218  {
219  union MapEntry me;
220 
221  me = map->map[i];
222  if (map->use_small_entries)
223  {
224  struct SmallMapEntry *sme;
225  struct SmallMapEntry *nxt;
226 
227  nxt = me.sme;
228  while (NULL != (sme = nxt))
229  {
230  nxt = sme->next;
231  GNUNET_free(sme);
232  }
233  me.sme = NULL;
234  }
235  else
236  {
237  struct BigMapEntry *bme;
238  struct BigMapEntry *nxt;
239 
240  nxt = me.bme;
241  while (NULL != (bme = nxt))
242  {
243  nxt = bme->next;
244  GNUNET_free(bme);
245  }
246  me.bme = NULL;
247  }
248  }
249  GNUNET_free(map->map);
250  GNUNET_free(map);
251 }
252 
253 
261 static unsigned int
263  const struct GNUNET_PeerIdentity *key)
264 {
265  unsigned int kx;
266 
267  GNUNET_assert(NULL != map);
268  GNUNET_memcpy(&kx, key, sizeof(kx));
269  return kx % map->map_length;
270 }
271 
272 
279 unsigned int
281  const struct GNUNET_CONTAINER_MultiPeerMap *map)
282 {
283  return map->size;
284 }
285 
286 
297 void *
299  const struct GNUNET_CONTAINER_MultiPeerMap *map,
300  const struct GNUNET_PeerIdentity *key)
301 {
302  union MapEntry me;
303 
304  me = map->map[idx_of(map, key)];
305  if (map->use_small_entries)
306  {
307  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
308  if (0 == GNUNET_memcmp(key, sme->key))
309  return sme->value;
310  }
311  else
312  {
313  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
314  if (0 == GNUNET_memcmp(key, &bme->key))
315  return bme->value;
316  }
317  return NULL;
318 }
319 
320 
330 int
334  void *it_cls)
335 {
336  int count;
337  union MapEntry me;
338  union MapEntry *ce;
339  struct GNUNET_PeerIdentity kc;
340 
341  count = 0;
342  GNUNET_assert(NULL != map);
343  ce = &map->next_cache[map->next_cache_off];
345  for (unsigned int i = 0; i < map->map_length; i++)
346  {
347  me = map->map[i];
348  if (map->use_small_entries)
349  {
350  struct SmallMapEntry *sme;
351 
352  ce->sme = me.sme;
353  while (NULL != (sme = ce->sme))
354  {
355  ce->sme = sme->next;
356  if (NULL != it)
357  {
358  if (GNUNET_OK != it(it_cls, sme->key, sme->value))
359  {
361  return GNUNET_SYSERR;
362  }
363  }
364  count++;
365  }
366  }
367  else
368  {
369  struct BigMapEntry *bme;
370 
371  ce->bme = me.bme;
372  while (NULL != (bme = ce->bme))
373  {
374  ce->bme = bme->next;
375  if (NULL != it)
376  {
377  kc = bme->key;
378  if (GNUNET_OK != it(it_cls, &kc, bme->value))
379  {
381  return GNUNET_SYSERR;
382  }
383  }
384  count++;
385  }
386  }
387  }
389  return count;
390 }
391 
392 
400 static void
402  const struct BigMapEntry *bme)
403 {
404  for (unsigned int i = 0; i < map->next_cache_off; i++)
405  if (map->next_cache[i].bme == bme)
406  map->next_cache[i].bme = bme->next;
407 }
408 
409 
417 static void
419  const struct SmallMapEntry *sme)
420 {
421  for (unsigned int i = 0; i < map->next_cache_off; i++)
422  if (map->next_cache[i].sme == sme)
423  map->next_cache[i].sme = sme->next;
424 }
425 
426 
438 int
440  const struct GNUNET_PeerIdentity *key,
441  const void *value)
442 {
443  union MapEntry me;
444  unsigned int i;
445 
446  map->modification_counter++;
447  i = idx_of(map, key);
448  me = map->map[i];
449  if (map->use_small_entries)
450  {
451  struct SmallMapEntry *p = NULL;
452 
453  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
454  {
455  if ((0 == GNUNET_memcmp(key, sme->key)) && (value == sme->value))
456  {
457  if (NULL == p)
458  map->map[i].sme = sme->next;
459  else
460  p->next = sme->next;
461  update_next_cache_sme(map, sme);
462  GNUNET_free(sme);
463  map->size--;
464  return GNUNET_YES;
465  }
466  p = sme;
467  }
468  }
469  else
470  {
471  struct BigMapEntry *p = NULL;
472 
473  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
474  {
475  if ((0 == GNUNET_memcmp(key, &bme->key)) && (value == bme->value))
476  {
477  if (NULL == p)
478  map->map[i].bme = bme->next;
479  else
480  p->next = bme->next;
481  update_next_cache_bme(map, bme);
482  GNUNET_free(bme);
483  map->size--;
484  return GNUNET_YES;
485  }
486  p = bme;
487  }
488  }
489  return GNUNET_NO;
490 }
491 
492 
501 int
504  const struct GNUNET_PeerIdentity *key)
505 {
506  union MapEntry me;
507  unsigned int i;
508  int ret;
509 
510  map->modification_counter++;
511 
512  ret = 0;
513  i = idx_of(map, key);
514  me = map->map[i];
515  if (map->use_small_entries)
516  {
517  struct SmallMapEntry *sme;
518  struct SmallMapEntry *p;
519 
520  p = NULL;
521  sme = me.sme;
522  while (NULL != sme)
523  {
524  if (0 == GNUNET_memcmp(key, sme->key))
525  {
526  if (NULL == p)
527  map->map[i].sme = sme->next;
528  else
529  p->next = sme->next;
530  update_next_cache_sme(map, sme);
531  GNUNET_free(sme);
532  map->size--;
533  if (NULL == p)
534  sme = map->map[i].sme;
535  else
536  sme = p->next;
537  ret++;
538  }
539  else
540  {
541  p = sme;
542  sme = sme->next;
543  }
544  }
545  }
546  else
547  {
548  struct BigMapEntry *bme;
549  struct BigMapEntry *p;
550 
551  p = NULL;
552  bme = me.bme;
553  while (NULL != bme)
554  {
555  if (0 == GNUNET_memcmp(key, &bme->key))
556  {
557  if (NULL == p)
558  map->map[i].bme = bme->next;
559  else
560  p->next = bme->next;
561  update_next_cache_bme(map, bme);
562  GNUNET_free(bme);
563  map->size--;
564  if (NULL == p)
565  bme = map->map[i].bme;
566  else
567  bme = p->next;
568  ret++;
569  }
570  else
571  {
572  p = bme;
573  bme = bme->next;
574  }
575  }
576  }
577  return ret;
578 }
579 
580 
590 int
592  const struct GNUNET_CONTAINER_MultiPeerMap *map,
593  const struct GNUNET_PeerIdentity *key)
594 {
595  union MapEntry me;
596 
597  me = map->map[idx_of(map, key)];
598  if (map->use_small_entries)
599  {
600  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
601  if (0 == GNUNET_memcmp(key, sme->key))
602  return GNUNET_YES;
603  }
604  else
605  {
606  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
607  if (0 == GNUNET_memcmp(key, &bme->key))
608  return GNUNET_YES;
609  }
610  return GNUNET_NO;
611 }
612 
613 
624 int
626  const struct GNUNET_CONTAINER_MultiPeerMap *map,
627  const struct GNUNET_PeerIdentity *key,
628  const void *value)
629 {
630  union MapEntry me;
631 
632  me = map->map[idx_of(map, key)];
633  if (map->use_small_entries)
634  {
635  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
636  if ((0 == GNUNET_memcmp(key, sme->key)) && (sme->value == value))
637  return GNUNET_YES;
638  }
639  else
640  {
641  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
642  if ((0 == GNUNET_memcmp(key, &bme->key)) && (bme->value == value))
643  return GNUNET_YES;
644  }
645  return GNUNET_NO;
646 }
647 
648 
654 static void
656 {
657  union MapEntry *old_map;
658  union MapEntry *new_map;
659  unsigned int old_len;
660  unsigned int new_len;
661  unsigned int idx;
662 
663  old_map = map->map;
664  old_len = map->map_length;
665  GNUNET_assert(0 != old_len);
666  new_len = old_len * 2;
667  if (0 == new_len) /* 2^31 * 2 == 0 */
668  new_len = old_len; /* never use 0 */
669  if (new_len == old_len)
670  return; /* nothing changed */
671  new_map = GNUNET_malloc_large(new_len * sizeof(union MapEntry));
672  if (NULL == new_map)
673  return; /* grow not possible */
674  map->modification_counter++;
675  map->map_length = new_len;
676  map->map = new_map;
677  for (unsigned int i = 0; i < old_len; i++)
678  {
679  if (map->use_small_entries)
680  {
681  struct SmallMapEntry *sme;
682 
683  while (NULL != (sme = old_map[i].sme))
684  {
685  old_map[i].sme = sme->next;
686  idx = idx_of(map, sme->key);
687  sme->next = new_map[idx].sme;
688  new_map[idx].sme = sme;
689  }
690  }
691  else
692  {
693  struct BigMapEntry *bme;
694 
695  while (NULL != (bme = old_map[i].bme))
696  {
697  old_map[i].bme = bme->next;
698  idx = idx_of(map, &bme->key);
699  bme->next = new_map[idx].bme;
700  new_map[idx].bme = bme;
701  }
702  }
703  }
704  GNUNET_free(old_map);
705 }
706 
707 
720 int
722  const struct GNUNET_PeerIdentity *key,
723  void *value,
725 {
726  union MapEntry me;
727  unsigned int i;
728 
729  i = idx_of(map, key);
732  {
733  me = map->map[i];
734  if (map->use_small_entries)
735  {
736  struct SmallMapEntry *sme;
737 
738  for (sme = me.sme; NULL != sme; sme = sme->next)
739  if (0 == GNUNET_memcmp(key, sme->key))
740  {
742  return GNUNET_SYSERR;
743  sme->value = value;
744  return GNUNET_NO;
745  }
746  }
747  else
748  {
749  struct BigMapEntry *bme;
750 
751  for (bme = me.bme; NULL != bme; bme = bme->next)
752  if (0 == GNUNET_memcmp(key, &bme->key))
753  {
755  return GNUNET_SYSERR;
756  bme->value = value;
757  return GNUNET_NO;
758  }
759  }
760  }
761  if (map->size / 3 >= map->map_length / 4)
762  {
763  grow(map);
764  i = idx_of(map, key);
765  }
766  if (map->use_small_entries)
767  {
768  struct SmallMapEntry *sme;
769 
770  sme = GNUNET_new(struct SmallMapEntry);
771  sme->key = key;
772  sme->value = value;
773  sme->next = map->map[i].sme;
774  map->map[i].sme = sme;
775  }
776  else
777  {
778  struct BigMapEntry *bme;
779 
780  bme = GNUNET_new(struct BigMapEntry);
781  bme->key = *key;
782  bme->value = value;
783  bme->next = map->map[i].bme;
784  map->map[i].bme = bme;
785  }
786  map->size++;
787  return GNUNET_OK;
788 }
789 
790 
801 int
804  const struct GNUNET_PeerIdentity *key,
806  void *it_cls)
807 {
808  int count;
809  union MapEntry me;
810  union MapEntry *ce;
811 
812  ce = &map->next_cache[map->next_cache_off];
814  count = 0;
815  me = map->map[idx_of(map, key)];
816  if (map->use_small_entries)
817  {
818  struct SmallMapEntry *sme;
819 
820  ce->sme = me.sme;
821  while (NULL != (sme = ce->sme))
822  {
823  ce->sme = sme->next;
824  if (0 != GNUNET_memcmp(key, sme->key))
825  continue;
826  if ((NULL != it) && (GNUNET_OK != it(it_cls, key, sme->value)))
827  {
829  return GNUNET_SYSERR;
830  }
831  count++;
832  }
833  }
834  else
835  {
836  struct BigMapEntry *bme;
837 
838  ce->bme = me.bme;
839  while (NULL != (bme = ce->bme))
840  {
841  ce->bme = bme->next;
842  if (0 != GNUNET_memcmp(key, &bme->key))
843  continue;
844  if ((NULL != it) && (GNUNET_OK != it(it_cls, key, bme->value)))
845  {
847  return GNUNET_SYSERR;
848  }
849  count++;
850  }
851  }
853  return count;
854 }
855 
856 
868 unsigned int
870  const struct GNUNET_CONTAINER_MultiPeerMap *map,
872  void *it_cls)
873 {
874  unsigned int off;
875  union MapEntry me;
876 
877  if (0 == map->size)
878  return 0;
879  if (NULL == it)
880  return 1;
882  for (unsigned int idx = 0; idx < map->map_length; idx++)
883  {
884  me = map->map[idx];
885  if (map->use_small_entries)
886  {
887  struct SmallMapEntry *sme;
888  struct SmallMapEntry *nxt;
889 
890  nxt = me.sme;
891  while (NULL != (sme = nxt))
892  {
893  nxt = sme->next;
894  if (0 == off)
895  {
896  if (GNUNET_OK != it(it_cls, sme->key, sme->value))
897  return GNUNET_SYSERR;
898  return 1;
899  }
900  off--;
901  }
902  }
903  else
904  {
905  struct BigMapEntry *bme;
906  struct BigMapEntry *nxt;
907 
908  nxt = me.bme;
909  while (NULL != (bme = nxt))
910  {
911  nxt = bme->next;
912  if (0 == off)
913  {
914  if (GNUNET_OK != it(it_cls, &bme->key, bme->value))
915  return GNUNET_SYSERR;
916  return 1;
917  }
918  off--;
919  }
920  }
921  }
922  GNUNET_break(0);
923  return GNUNET_SYSERR;
924 }
925 
926 
941  const struct GNUNET_CONTAINER_MultiPeerMap *map)
942 {
944 
946  iter->map = map;
948  iter->me = map->map[0];
949  return iter;
950 }
951 
952 
967 int
970  struct GNUNET_PeerIdentity *key,
971  const void **value)
972 {
973  /* make sure the map has not been modified */
975 
976  /* look for the next entry, skipping empty buckets */
977  while (1)
978  {
979  if (iter->idx >= iter->map->map_length)
980  return GNUNET_NO;
981  if (GNUNET_YES == iter->map->use_small_entries)
982  {
983  if (NULL != iter->me.sme)
984  {
985  if (NULL != key)
986  *key = *iter->me.sme->key;
987  if (NULL != value)
988  *value = iter->me.sme->value;
989  iter->me.sme = iter->me.sme->next;
990  return GNUNET_YES;
991  }
992  }
993  else
994  {
995  if (NULL != iter->me.bme)
996  {
997  if (NULL != key)
998  *key = iter->me.bme->key;
999  if (NULL != value)
1000  *value = iter->me.bme->value;
1001  iter->me.bme = iter->me.bme->next;
1002  return GNUNET_YES;
1003  }
1004  }
1005  iter->idx += 1;
1006  if (iter->idx < iter->map->map_length)
1007  iter->me = iter->map->map[iter->idx];
1008  }
1009 }
1010 
1011 
1017 void
1020 {
1021  GNUNET_free(iter);
1022 }
1023 
1024 
1025 /* 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.
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.
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...
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...