GNUnet  0.10.x
container_bloomfilter.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001, 2002, 2003, 2004, 2006, 2008, 2011, 2012, 2018 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 */
42 #include "platform.h"
43 #include "gnunet_util_lib.h"
44 
45 #define LOG(kind,...) GNUNET_log_from (kind, "util-container-bloomfilter", __VA_ARGS__)
46 
47 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-container-bloomfilter", syscall)
48 
49 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-container-bloomfilter", syscall, filename)
50 
52 {
53 
57  char *bitArray;
58 
62  char *filename;
63 
68 
72  unsigned int addressesPerElement;
73 
77  size_t bitArraySize;
78 
79 };
80 
81 
88 size_t
90  *bf)
91 {
92  if (bf == NULL)
93  return 0;
94  return bf->addressesPerElement;
95 }
96 
97 
104 size_t
106  *bf)
107 {
108  if (bf == NULL)
109  return 0;
110  return bf->bitArraySize;
111 }
112 
113 
122  *bf)
123 {
125  bf->addressesPerElement);
126 }
127 
128 
136 static void
137 setBit (char *bitArray, unsigned int bitIdx)
138 {
139  size_t arraySlot;
140  unsigned int targetBit;
141 
142  arraySlot = bitIdx / 8;
143  targetBit = (1L << (bitIdx % 8));
144  bitArray[arraySlot] |= targetBit;
145 }
146 
154 static void
155 clearBit (char *bitArray, unsigned int bitIdx)
156 {
157  size_t slot;
158  unsigned int targetBit;
159 
160  slot = bitIdx / 8;
161  targetBit = (1L << (bitIdx % 8));
162  bitArray[slot] = bitArray[slot] & (~targetBit);
163 }
164 
172 static int
173 testBit (char *bitArray, unsigned int bitIdx)
174 {
175  size_t slot;
176  unsigned int targetBit;
177 
178  slot = bitIdx / 8;
179  targetBit = (1L << (bitIdx % 8));
180  if (bitArray[slot] & targetBit)
181  return GNUNET_YES;
182  else
183  return GNUNET_NO;
184 }
185 
195 static void
196 incrementBit (char *bitArray, unsigned int bitIdx,
197  const struct GNUNET_DISK_FileHandle *fh)
198 {
199  off_t fileSlot;
200  unsigned char value;
201  unsigned int high;
202  unsigned int low;
203  unsigned int targetLoc;
204 
205  setBit (bitArray, bitIdx);
207  return;
208  /* Update the counter file on disk */
209  fileSlot = bitIdx / 2;
210  targetLoc = bitIdx % 2;
211 
212  GNUNET_assert (fileSlot ==
214  if (1 != GNUNET_DISK_file_read (fh, &value, 1))
215  value = 0;
216  low = value & 0xF;
217  high = (value & (~0xF)) >> 4;
218 
219  if (targetLoc == 0)
220  {
221  if (low < 0xF)
222  low++;
223  }
224  else
225  {
226  if (high < 0xF)
227  high++;
228  }
229  value = ((high << 4) | low);
230  GNUNET_assert (fileSlot ==
232  GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1));
233 }
234 
243 static void
244 decrementBit (char *bitArray, unsigned int bitIdx,
245  const struct GNUNET_DISK_FileHandle *fh)
246 {
247  off_t fileslot;
248  unsigned char value;
249  unsigned int high;
250  unsigned int low;
251  unsigned int targetLoc;
252 
254  return; /* cannot decrement! */
255  /* Each char slot in the counter file holds two 4 bit counters */
256  fileslot = bitIdx / 2;
257  targetLoc = bitIdx % 2;
259  {
261  return;
262  }
263  if (1 != GNUNET_DISK_file_read (fh, &value, 1))
264  value = 0;
265  low = value & 0xF;
266  high = (value & 0xF0) >> 4;
267 
268  /* decrement, but once we have reached the max, never go back! */
269  if (targetLoc == 0)
270  {
271  if ((low > 0) && (low < 0xF))
272  low--;
273  if (low == 0)
274  {
275  clearBit (bitArray, bitIdx);
276  }
277  }
278  else
279  {
280  if ((high > 0) && (high < 0xF))
281  high--;
282  if (high == 0)
283  {
284  clearBit (bitArray, bitIdx);
285  }
286  }
287  value = ((high << 4) | low);
289  {
291  return;
292  }
293  GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1));
294 }
295 
296 #define BUFFSIZE 65536
297 
305 static int
307 {
308  char buffer[BUFFSIZE];
309  size_t bytesleft = size;
310  int res = 0;
311 
313  return GNUNET_SYSERR;
314  memset (buffer, 0, sizeof (buffer));
316  while (bytesleft > 0)
317  {
318  if (bytesleft > sizeof (buffer))
319  {
320  res = GNUNET_DISK_file_write (fh, buffer, sizeof (buffer));
321  if (res >= 0)
322  bytesleft -= res;
323  }
324  else
325  {
326  res = GNUNET_DISK_file_write (fh, buffer, bytesleft);
327  if (res >= 0)
328  bytesleft -= res;
329  }
330  if (GNUNET_SYSERR == res)
331  return GNUNET_SYSERR;
332  }
333  return GNUNET_OK;
334 }
335 
336 /* ************** GNUNET_CONTAINER_BloomFilter iterator ********* */
337 
348 typedef int (*BitIterator) (void *cls,
349  const struct GNUNET_CONTAINER_BloomFilter * bf,
350  unsigned int bit);
351 
352 
362 static void
364  BitIterator callback, void *arg, const struct GNUNET_HashCode *key)
365 {
366  struct GNUNET_HashCode tmp[2];
367  int bitCount;
368  unsigned int round;
369  unsigned int slot = 0;
370 
371  bitCount = bf->addressesPerElement;
372  tmp[0] = *key;
373  round = 0;
374  GNUNET_assert (bf->bitArraySize > 0);
375  GNUNET_assert (bf->bitArraySize * 8LL > bf->bitArraySize);
376  while (bitCount > 0)
377  {
378  while (slot < (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t)))
379  {
380  if (GNUNET_YES !=
381  callback (arg, bf,
382  ntohl ((((uint32_t *) & tmp[round & 1])[slot])) %
383  ((bf->bitArraySize * 8LL))))
384  return;
385  slot++;
386  bitCount--;
387  if (bitCount == 0)
388  break;
389  }
390  if (bitCount > 0)
391  {
392  GNUNET_CRYPTO_hash (&tmp[round & 1], sizeof (struct GNUNET_HashCode),
393  &tmp[(round + 1) & 1]);
394  round++;
395  slot = 0;
396  }
397  }
398 }
399 
400 
409 static int
411  unsigned int bit)
412 {
413  struct GNUNET_CONTAINER_BloomFilter *b = cls;
414 
415  incrementBit (b->bitArray, bit, bf->fh);
416  return GNUNET_YES;
417 }
418 
419 
428 static int
430  unsigned int bit)
431 {
432  struct GNUNET_CONTAINER_BloomFilter *b = cls;
433 
434  decrementBit (b->bitArray, bit, bf->fh);
435  return GNUNET_YES;
436 }
437 
438 
447 static int
448 testBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf,
449  unsigned int bit)
450 {
451  int *arg = cls;
452 
453  if (GNUNET_NO == testBit (bf->bitArray, bit))
454  {
455  *arg = GNUNET_NO;
456  return GNUNET_NO;
457  }
458  return GNUNET_YES;
459 }
460 
461 /* *********************** INTERFACE **************** */
462 
476  unsigned int k)
477 {
478  struct GNUNET_CONTAINER_BloomFilter *bf;
479  char *rbuff;
480  off_t pos;
481  int i;
482  size_t ui;
483  off_t fsize;
484  int must_read;
485 
486  GNUNET_assert (NULL != filename);
487  if ((k == 0) || (size == 0))
488  return NULL;
489  if (size < BUFFSIZE)
490  size = BUFFSIZE;
491  ui = 1;
492  while ( (ui < size) &&
493  (ui * 2 > ui) )
494  ui *= 2;
495  size = ui; /* make sure it's a power of 2 */
496 
498  /* Try to open a bloomfilter file */
499  if (GNUNET_YES == GNUNET_DISK_file_test (filename))
500  bf->fh =
501  GNUNET_DISK_file_open (filename,
505  if (NULL != bf->fh)
506  {
507  /* file existed, try to read it! */
508  must_read = GNUNET_YES;
509  if (GNUNET_OK !=
510  GNUNET_DISK_file_handle_size (bf->fh, &fsize))
511  {
513  GNUNET_free (bf);
514  return NULL;
515  }
516  if (0 == fsize)
517  {
518  /* found existing empty file, just overwrite */
519  if (GNUNET_OK !=
520  make_empty_file (bf->fh, size * 4LL))
521  {
523  "write");
525  GNUNET_free (bf);
526  return NULL;
527  }
528  }
529  else if (fsize != ((off_t) size) * 4LL)
530  {
532  _("Size of file on disk is incorrect for this Bloom filter (want %llu, have %llu)\n"),
533  (unsigned long long) (size * 4LL),
534  (unsigned long long) fsize);
536  GNUNET_free (bf);
537  return NULL;
538  }
539  }
540  else
541  {
542  /* file did not exist, don't read, just create */
543  must_read = GNUNET_NO;
544  bf->fh =
545  GNUNET_DISK_file_open (filename,
550  if (NULL == bf->fh)
551  {
552  GNUNET_free (bf);
553  return NULL;
554  }
555  if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL))
556  {
558  "write");
560  GNUNET_free (bf);
561  return NULL;
562  }
563  }
564  bf->filename = GNUNET_strdup (filename);
565  /* Alloc block */
566  bf->bitArray = GNUNET_malloc_large (size);
567  if (NULL == bf->bitArray)
568  {
569  if (NULL != bf->fh)
571  GNUNET_free (bf->filename);
572  GNUNET_free (bf);
573  return NULL;
574  }
575  bf->bitArraySize = size;
576  bf->addressesPerElement = k;
577  if (GNUNET_YES != must_read)
578  return bf; /* already done! */
579  /* Read from the file what bits we can */
580  rbuff = GNUNET_malloc (BUFFSIZE);
581  pos = 0;
582  while (pos < ((off_t) size) * 8LL)
583  {
584  int res;
585 
586  res = GNUNET_DISK_file_read (bf->fh,
587  rbuff,
588  BUFFSIZE);
589  if (res == -1)
590  {
592  "read",
593  bf->filename);
594  GNUNET_free (rbuff);
595  GNUNET_free (bf->filename);
597  GNUNET_free (bf);
598  return NULL;
599  }
600  if (res == 0)
601  break; /* is ok! we just did not use that many bits yet */
602  for (i = 0; i < res; i++)
603  {
604  if ((rbuff[i] & 0x0F) != 0)
605  setBit (bf->bitArray, pos + i * 2);
606  if ((rbuff[i] & 0xF0) != 0)
607  setBit (bf->bitArray, pos + i * 2 + 1);
608  }
609  if (res < BUFFSIZE)
610  break;
611  pos += BUFFSIZE * 2; /* 2 bits per byte in the buffer */
612  }
613  GNUNET_free (rbuff);
614  return bf;
615 }
616 
617 
633  unsigned int k)
634 {
635  struct GNUNET_CONTAINER_BloomFilter *bf;
636 
637  if ((0 == k) || (0 == size))
638  return NULL;
640  bf->filename = NULL;
641  bf->fh = NULL;
642  bf->bitArray = GNUNET_malloc_large (size);
643  if (NULL == bf->bitArray)
644  {
645  GNUNET_free (bf);
646  return NULL;
647  }
648  bf->bitArraySize = size;
649  bf->addressesPerElement = k;
650  if (NULL != data)
651  GNUNET_memcpy (bf->bitArray, data, size);
652  return bf;
653 }
654 
655 
665 int
668  char *data, size_t size)
669 {
670  if (NULL == bf)
671  return GNUNET_SYSERR;
672  if (bf->bitArraySize != size)
673  return GNUNET_SYSERR;
674  GNUNET_memcpy (data, bf->bitArray, size);
675  return GNUNET_OK;
676 }
677 
678 
686 void
688 {
689  if (NULL == bf)
690  return;
691  if (bf->fh != NULL)
694  GNUNET_free (bf->bitArray);
695  GNUNET_free (bf);
696 }
697 
698 
704 void
706 {
707  if (NULL == bf)
708  return;
709 
710  memset (bf->bitArray, 0, bf->bitArraySize);
711  if (bf->filename != NULL)
712  make_empty_file (bf->fh, bf->bitArraySize * 4LL);
713 }
714 
715 
723 int
725  const struct GNUNET_HashCode * e)
726 {
727  int res;
728 
729  if (NULL == bf)
730  return GNUNET_YES;
731  res = GNUNET_YES;
732  iterateBits (bf, &testBitCallback, &res, e);
733  return res;
734 }
735 
736 
743 void
745  const struct GNUNET_HashCode * e)
746 {
747  if (NULL == bf)
748  return;
749  iterateBits (bf, &incrementBitCallback, bf, e);
750 }
751 
752 
763 int
765  const char *data,
766  size_t size)
767 {
768  unsigned int i;
769  unsigned int n;
770  unsigned long long *fc;
771  const unsigned long long *dc;
772 
773  if (NULL == bf)
774  return GNUNET_YES;
775  if (bf->bitArraySize != size)
776  return GNUNET_SYSERR;
777  fc = (unsigned long long *) bf->bitArray;
778  dc = (const unsigned long long *) data;
779  n = size / sizeof (unsigned long long);
780 
781  for (i = 0; i < n; i++)
782  fc[i] |= dc[i];
783  for (i = n * sizeof (unsigned long long); i < size; i++)
784  bf->bitArray[i] |= data[i];
785  return GNUNET_OK;
786 }
787 
798 int
800  const struct GNUNET_CONTAINER_BloomFilter *to_or)
801 {
802  unsigned int i;
803  unsigned int n;
804  unsigned long long *fc;
805  const unsigned long long *dc;
806  size_t size;
807 
808  if (NULL == bf)
809  return GNUNET_OK;
810  if (bf->bitArraySize != to_or->bitArraySize)
811  {
812  GNUNET_break (0);
813  return GNUNET_SYSERR;
814  }
815  size = bf->bitArraySize;
816  fc = (unsigned long long *) bf->bitArray;
817  dc = (const unsigned long long *) to_or->bitArray;
818  n = size / sizeof (unsigned long long);
819 
820  for (i = 0; i < n; i++)
821  fc[i] |= dc[i];
822  for (i = n * sizeof (unsigned long long); i < size; i++)
823  bf->bitArray[i] |= to_or->bitArray[i];
824  return GNUNET_OK;
825 }
826 
827 
834 void
836  const struct GNUNET_HashCode *e)
837 {
838  if (NULL == bf)
839  return;
840  if (NULL == bf->filename)
841  return;
842  iterateBits (bf,
844  bf,
845  e);
846 }
847 
859 void
862  void *iterator_cls,
863  size_t size,
864  unsigned int k)
865 {
866  struct GNUNET_HashCode hc;
867  unsigned int i;
868 
869  GNUNET_free (bf->bitArray);
870  i = 1;
871  while (i < size)
872  i *= 2;
873  size = i; /* make sure it's a power of 2 */
874  bf->addressesPerElement = k;
875  bf->bitArraySize = size;
876  bf->bitArray = GNUNET_malloc (size);
877  if (NULL != bf->filename)
878  make_empty_file (bf->fh,
879  bf->bitArraySize * 4LL);
880  while (GNUNET_YES == iterator (iterator_cls,
881  &hc))
883  &hc);
884 }
885 
886 /* end of container_bloomfilter.c */
static int testBitCallback(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Callback: test if all bits are set.
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:669
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a bloom filter from raw bits.
Create file if it doesn&#39;t exist.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1817
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:881
static void decrementBit(char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh)
Clears a bit from bitArray if the respective usage counter on the disk hits/is zero.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static int make_empty_file(const struct GNUNET_DISK_FileHandle *fh, size_t size)
Creates a file filled with zeroes.
unsigned int addressesPerElement
How many bits we set for each stored element.
#define LOG_STRERROR_FILE(kind, syscall, filename)
size_t GNUNET_CONTAINER_bloomfilter_get_size(const struct GNUNET_CONTAINER_BloomFilter *bf)
Get size of the bloom filter.
static struct Experiment * e
#define GNUNET_NO
Definition: gnunet_common.h:81
char * filename
Filename of the filter.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static int incrementBitCallback(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Callback: increment bit.
off_t GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h, off_t offset, enum GNUNET_DISK_Seek whence)
Move the read/write pointer in a file.
Definition: disk.c:241
#define GNUNET_malloc_large(size)
Wrapper around malloc.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:191
int GNUNET_CONTAINER_bloomfilter_or2(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_CONTAINER_BloomFilter *to_or)
Or the entries of the given raw data array with the data of the given bloom filter.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static void clearBit(char *bitArray, unsigned int bitIdx)
Clears a bit from bitArray.
#define GNUNET_memcpy(dst, src, n)
void GNUNET_CONTAINER_bloomfilter_remove(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Remove an element from the filter.
static char * value
Value of the record to add/remove.
int GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:1049
size_t bitArraySize
Size of bitArray in bytes.
static void iterateBits(const struct GNUNET_CONTAINER_BloomFilter *bf, BitIterator callback, void *arg, const struct GNUNET_HashCode *key)
Call an iterator for each bit that the bloomfilter must test or set for this element.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load(const char *filename, size_t size, unsigned int k)
Load a bloom-filter from a file.
A 512-bit hashcode.
static int decrementBitCallback(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Callback: decrement bit.
size_t GNUNET_CONTAINER_bloomfilter_get_element_addresses(const struct GNUNET_CONTAINER_BloomFilter *bf)
Get the number of the addresses set per element in the bloom filter.
static int res
void GNUNET_CONTAINER_bloomfilter_clear(struct GNUNET_CONTAINER_BloomFilter *bf)
Reset a bloom filter to empty.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_CONTAINER_bloomfilter_or(struct GNUNET_CONTAINER_BloomFilter *bf, const char *data, size_t size)
Or the entries of the given raw data array with the data of the given bloom filter.
int GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this bloomfilter into the given data array.
char * bitArray
The actual bloomfilter bit array.
struct GNUNET_DISK_FileHandle * fh
The bit counter file on disk.
static void setBit(char *bitArray, unsigned int bitIdx)
Sets a bit active in the bitArray.
Seek an absolute position (from the start of the file).
int GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition: disk.c:208
#define GNUNET_log(kind,...)
Open the file for both reading and writing.
static void incrementBit(char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh)
Sets a bit active in the bitArray and increments bit-specific usage counter on disk (but only if the ...
static int testBit(char *bitArray, unsigned int bitIdx)
Checks if a bit is active in the bitArray.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_copy(const struct GNUNET_CONTAINER_BloomFilter *bf)
Copy an existing memory.
int(* GNUNET_CONTAINER_HashCodeIterator)(void *cls, struct GNUNET_HashCode *next)
Iterator over struct GNUNET_HashCode.
#define BUFFSIZE
uint32_t data
The data value.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1673
Handle used to access files (and pipes).
void GNUNET_CONTAINER_bloomfilter_resize(struct GNUNET_CONTAINER_BloomFilter *bf, GNUNET_CONTAINER_HashCodeIterator iterator, void *iterator_cls, size_t size, unsigned int k)
Resize a bloom filter.
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
#define GNUNET_malloc(size)
Wrapper around malloc.
static struct GNUNET_FS_DownloadContext * dc
#define GNUNET_free(ptr)
Wrapper around free.
int(* BitIterator)(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Iterator (callback) method to be called by the bloomfilter iterator on each bit that is to be set or ...