GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
container_bloomfilter.c File Reference

data structure used to reduce disk accesses. More...

#include "platform.h"
#include "gnunet_util_lib.h"
Include dependency graph for container_bloomfilter.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_CONTAINER_BloomFilter
 

Macros

#define LOG(kind, ...)    GNUNET_log_from (kind, "util-container-bloomfilter", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)    GNUNET_log_from_strerror (kind, "util-container-bloomfilter", syscall)
 
#define LOG_STRERROR_FILE(kind, syscall, filename)
 
#define BUFFSIZE   65536
 

Typedefs

typedef enum GNUNET_GenericReturnValue(* 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 tested for the key.
 

Functions

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.
 
size_t GNUNET_CONTAINER_bloomfilter_get_size (const struct GNUNET_CONTAINER_BloomFilter *bf)
 Get size of the bloom filter.
 
struct GNUNET_CONTAINER_BloomFilterGNUNET_CONTAINER_bloomfilter_copy (const struct GNUNET_CONTAINER_BloomFilter *bf)
 Create a copy of a bloomfilter.
 
static void setBit (char *bitArray, unsigned int bitIdx)
 Sets a bit active in the bitArray.
 
static void clearBit (char *bitArray, unsigned int bitIdx)
 Clears a bit from bitArray.
 
static bool testBit (char *bitArray, unsigned int bitIdx)
 Checks if a bit is active in the bitArray.
 
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 counter was below 4 bit max (==15)).
 
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.
 
static enum GNUNET_GenericReturnValue make_empty_file (const struct GNUNET_DISK_FileHandle *fh, size_t size)
 Creates a file filled with zeroes.
 
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.
 
static enum GNUNET_GenericReturnValue incrementBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
 Callback: increment bit.
 
static enum GNUNET_GenericReturnValue decrementBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
 Callback: decrement bit.
 
static enum GNUNET_GenericReturnValue testBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
 Callback: test if all bits are set.
 
struct GNUNET_CONTAINER_BloomFilterGNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, unsigned int k)
 Load a Bloom filter from a file.
 
struct GNUNET_CONTAINER_BloomFilterGNUNET_CONTAINER_bloomfilter_init (const char *data, size_t size, unsigned int k)
 Create a Bloom filter from raw bits.
 
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_bloomfilter_get_raw_data (const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
 Copy the raw data of this Bloom filter into the given data array.
 
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 the drive).
 
void GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf)
 Reset a Bloom filter to empty.
 
bool 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_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
 Add an element to the filter.
 
enum GNUNET_GenericReturnValue 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.
 
enum GNUNET_GenericReturnValue 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.
 
void GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
 Remove an element from the filter.
 
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.
 

Detailed Description

data structure used to reduce disk accesses.

The idea basically: Create a signature for each element in the database. Add those signatures to a bit array. When doing a lookup, check if the bit array matches the signature of the requested element. If yes, address the disk, otherwise return 'not found'.

A property of the bloom filter is that sometimes we will have a match even if the element is not on the disk (then we do an unnecessary disk access), but what's most important is that we never get a single "false negative".

To be able to delete entries from the bloom filter, we maintain a 4 bit counter in the file on the drive (we still use only one bit in memory).

Author
Igor Wronsky
Christian Grothoff

Definition in file container_bloomfilter.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)     GNUNET_log_from (kind, "util-container-bloomfilter", __VA_ARGS__)

Definition at line 46 of file container_bloomfilter.c.

58{
62 char *bitArray;
63
67 char *filename;
68
72 struct GNUNET_DISK_FileHandle *fh;
73
77 unsigned int addressesPerElement;
78
82 size_t bitArraySize;
83};
84
85
86size_t
88 const struct GNUNET_CONTAINER_BloomFilter *bf)
89{
90 if (bf == NULL)
91 return 0;
92 return bf->addressesPerElement;
93}
94
95
96size_t
98 const struct GNUNET_CONTAINER_BloomFilter *bf)
99{
100 if (bf == NULL)
101 return 0;
102 return bf->bitArraySize;
103}
104
105
108 const struct GNUNET_CONTAINER_BloomFilter *bf)
109{
111 bf->bitArraySize,
113}
114
115
123static void
124setBit (char *bitArray,
125 unsigned int bitIdx)
126{
127 size_t arraySlot;
128 unsigned int targetBit;
129
130 arraySlot = bitIdx / 8;
131 targetBit = (1L << (bitIdx % 8));
132 bitArray[arraySlot] |= targetBit;
133}
134
135
143static void
144clearBit (char *bitArray, unsigned int bitIdx)
145{
146 size_t slot;
147 unsigned int targetBit;
148
149 slot = bitIdx / 8;
150 targetBit = (1L << (bitIdx % 8));
151 bitArray[slot] = bitArray[slot] & (~targetBit);
152}
153
154
162static bool
163testBit (char *bitArray,
164 unsigned int bitIdx)
165{
166 size_t slot;
167 unsigned int targetBit;
168
169 slot = bitIdx / 8;
170 targetBit = (1L << (bitIdx % 8));
171 if (bitArray[slot] & targetBit)
172 return true;
173 return false;
174}
175
176
186static void
188 unsigned int bitIdx,
189 const struct GNUNET_DISK_FileHandle *fh)
190{
191 off_t fileSlot;
192 unsigned char value;
193 unsigned int high;
194 unsigned int low;
195 unsigned int targetLoc;
196
198 bitIdx);
200 return;
201 /* Update the counter file on disk */
202 fileSlot = bitIdx / 2;
203 targetLoc = bitIdx % 2;
204
205 GNUNET_assert (fileSlot ==
207 if (1 != GNUNET_DISK_file_read (fh, &value, 1))
208 value = 0;
209 low = value & 0xF;
210 high = (value & (~0xF)) >> 4;
211
212 if (targetLoc == 0)
213 {
214 if (low < 0xF)
215 low++;
216 }
217 else
218 {
219 if (high < 0xF)
220 high++;
221 }
222 value = ((high << 4) | low);
223 GNUNET_assert (fileSlot ==
226}
227
228
237static void
239 unsigned int bitIdx,
240 const struct GNUNET_DISK_FileHandle *fh)
241{
242 off_t fileslot;
243 unsigned char value;
244 unsigned int high;
245 unsigned int low;
246 unsigned int targetLoc;
247
249 return; /* cannot decrement! */
250 /* Each char slot in the counter file holds two 4 bit counters */
251 fileslot = bitIdx / 2;
252 targetLoc = bitIdx % 2;
253 if (GNUNET_SYSERR ==
255 {
257 return;
258 }
259 if (1 != GNUNET_DISK_file_read (fh, &value, 1))
260 value = 0;
261 low = value & 0xF;
262 high = (value & 0xF0) >> 4;
263
264 /* decrement, but once we have reached the max, never go back! */
265 if (targetLoc == 0)
266 {
267 if ((low > 0) && (low < 0xF))
268 low--;
269 if (low == 0)
270 {
271 clearBit (bitArray, bitIdx);
272 }
273 }
274 else
275 {
276 if ((high > 0) && (high < 0xF))
277 high--;
278 if (high == 0)
279 {
280 clearBit (bitArray, bitIdx);
281 }
282 }
283 value = ((high << 4) | low);
284 if (GNUNET_SYSERR ==
286 {
288 return;
289 }
291}
292
293
294#define BUFFSIZE 65536
295
305 size_t size)
306{
307 char buffer[BUFFSIZE];
308 size_t bytesleft = size;
309 int res = 0;
310
312 return GNUNET_SYSERR;
313 memset (buffer, 0, sizeof(buffer));
315 while (bytesleft > 0)
316 {
317 if (bytesleft > sizeof(buffer))
318 {
319 res = GNUNET_DISK_file_write (fh, buffer, sizeof(buffer));
320 if (res >= 0)
321 bytesleft -= res;
322 }
323 else
324 {
325 res = GNUNET_DISK_file_write (fh, buffer, bytesleft);
326 if (res >= 0)
327 bytesleft -= res;
328 }
329 if (GNUNET_SYSERR == res)
330 return GNUNET_SYSERR;
331 }
332 return GNUNET_OK;
333}
334
335
336/* ************** GNUNET_CONTAINER_BloomFilter iterator ********* */
337
348typedef enum GNUNET_GenericReturnValue
349(*BitIterator)(void *cls,
350 const struct GNUNET_CONTAINER_BloomFilter *bf,
351 unsigned int bit);
352
353
363static void
365 BitIterator callback,
366 void *arg,
367 const struct GNUNET_HashCode *key)
368{
369 struct GNUNET_HashCode tmp = *key;
370 int bitCount;
371 unsigned int slot = 0;
372
373 bitCount = bf->addressesPerElement;
374 GNUNET_assert (bf->bitArraySize > 0);
375 GNUNET_assert (bf->bitArraySize * 8LL > bf->bitArraySize);
376 while (bitCount > 0)
377 {
378 while ( (0 != bitCount) &&
379 (slot < (sizeof(struct GNUNET_HashCode) / sizeof(uint32_t))) )
380 {
381 if (GNUNET_YES !=
382 callback (arg,
383 bf,
384 ntohl ((((uint32_t *) &tmp)[slot]))
385 % ((bf->bitArraySize * 8LL))))
386 return;
387 slot++;
388 bitCount--;
389 }
390 if (0 == bitCount)
391 break;
392 GNUNET_CRYPTO_hash (&tmp,
393 sizeof(tmp),
394 &tmp);
395 slot = 0;
396 }
397}
398
399
409incrementBitCallback (void *cls,
410 const struct GNUNET_CONTAINER_BloomFilter *bf,
411 unsigned int bit)
412{
413 struct GNUNET_CONTAINER_BloomFilter *b = cls;
414
416 bit,
417 bf->fh);
418 return GNUNET_YES;
419}
420
421
431decrementBitCallback (void *cls,
432 const struct GNUNET_CONTAINER_BloomFilter *bf,
433 unsigned int bit)
434{
435 struct GNUNET_CONTAINER_BloomFilter *b = cls;
436
438 bit,
439 bf->fh);
440 return GNUNET_YES;
441}
442
443
453testBitCallback (void *cls,
454 const struct GNUNET_CONTAINER_BloomFilter *bf,
455 unsigned int bit)
456{
457 bool *arg = cls;
458
459 if (! testBit (bf->bitArray, bit))
460 {
461 *arg = false;
462 return GNUNET_NO;
463 }
464 return GNUNET_YES;
465}
466
467
468/* *********************** INTERFACE **************** */
469
472 size_t size,
473 unsigned int k)
474{
476 char *rbuff;
477 off_t pos;
478 int i;
479 size_t ui;
480 off_t fsize;
481 int must_read;
482
483 GNUNET_assert (NULL != filename);
484 if ((k == 0) || (size == 0))
485 return NULL;
486 if (size < BUFFSIZE)
487 size = BUFFSIZE;
488 ui = 1;
489 while ((ui < size) && (ui * 2 > ui))
490 ui *= 2;
491 size = ui; /* make sure it's a power of 2 */
492
494 /* Try to open a bloomfilter file */
500 if (NULL != bf->fh)
501 {
502 /* file existed, try to read it! */
503 must_read = GNUNET_YES;
504 if (GNUNET_OK !=
506 &fsize))
507 {
509 GNUNET_free (bf);
510 return NULL;
511 }
512 if (0 == fsize)
513 {
514 /* found existing empty file, just overwrite */
515 if (GNUNET_OK !=
516 make_empty_file (bf->fh,
517 size * 4LL))
518 {
520 "write");
522 GNUNET_free (bf);
523 return NULL;
524 }
525 }
526 else if (fsize != ((off_t) size) * 4LL)
527 {
528 GNUNET_log (
530 _ (
531 "Size of file on disk is incorrect for this Bloom filter (want %llu, have %llu)\n"),
532 (unsigned long long) (size * 4LL),
533 (unsigned long long) fsize);
535 GNUNET_free (bf);
536 return NULL;
537 }
538 }
539 else
540 {
541 /* file did not exist, don't read, just create */
542 must_read = GNUNET_NO;
548 if (NULL == bf->fh)
549 {
550 GNUNET_free (bf);
551 return NULL;
552 }
553 if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL))
554 {
557 GNUNET_free (bf);
558 return NULL;
559 }
560 }
562 /* Alloc block */
564 if (NULL == bf->bitArray)
565 {
566 if (NULL != bf->fh)
568 GNUNET_free (bf->filename);
569 GNUNET_free (bf);
570 return NULL;
571 }
572 bf->bitArraySize = size;
573 bf->addressesPerElement = k;
574 if (GNUNET_YES != must_read)
575 return bf; /* already done! */
576 /* Read from the file what bits we can */
577 rbuff = GNUNET_malloc (BUFFSIZE);
578 pos = 0;
579 while (pos < ((off_t) size) * 8LL)
580 {
581 int res;
582
583 res = GNUNET_DISK_file_read (bf->fh, rbuff, BUFFSIZE);
584 if (res == -1)
585 {
587 GNUNET_free (rbuff);
588 GNUNET_free (bf->filename);
590 GNUNET_free (bf);
591 return NULL;
592 }
593 if (res == 0)
594 break; /* is ok! we just did not use that many bits yet */
595 for (i = 0; i < res; i++)
596 {
597 if ((rbuff[i] & 0x0F) != 0)
598 setBit (bf->bitArray, pos + i * 2);
599 if ((rbuff[i] & 0xF0) != 0)
600 setBit (bf->bitArray, pos + i * 2 + 1);
601 }
602 if (res < BUFFSIZE)
603 break;
604 pos += BUFFSIZE * 2; /* 2 bits per byte in the buffer */
605 }
606 GNUNET_free (rbuff);
607 return bf;
608}
609
610
613 size_t size,
614 unsigned int k)
615{
617
618 if ((0 == k) || (0 == size))
619 return NULL;
621 bf->filename = NULL;
622 bf->fh = NULL;
624 if (NULL == bf->bitArray)
625 {
626 GNUNET_free (bf);
627 return NULL;
628 }
629 bf->bitArraySize = size;
630 bf->addressesPerElement = k;
631 if (NULL != data)
633 return bf;
634}
635
636
639 const struct GNUNET_CONTAINER_BloomFilter *bf,
640 char *data,
641 size_t size)
642{
643 if (NULL == bf)
644 return GNUNET_SYSERR;
645 if (bf->bitArraySize != size)
646 return GNUNET_SYSERR;
648 return GNUNET_OK;
649}
650
651
652void
654{
655 if (NULL == bf)
656 return;
657 if (bf->fh != NULL)
659 GNUNET_free (bf->filename);
660 GNUNET_free (bf->bitArray);
661 GNUNET_free (bf);
662}
663
664
665void
667{
668 if (NULL == bf)
669 return;
670
671 memset (bf->bitArray, 0, bf->bitArraySize);
672 if (bf->filename != NULL)
673 make_empty_file (bf->fh, bf->bitArraySize * 4LL);
674}
675
676
677bool
679 const struct GNUNET_CONTAINER_BloomFilter *bf,
680 const struct GNUNET_HashCode *e)
681{
682 bool res;
683
684 if (NULL == bf)
685 return true;
686 res = true;
687 iterateBits (bf,
689 &res,
690 e);
691 return res;
692}
693
694
695void
697 const struct GNUNET_HashCode *e)
698{
699 if (NULL == bf)
700 return;
701 iterateBits (bf,
703 bf,
704 e);
705}
706
707
710 const char *data,
711 size_t size)
712{
713 unsigned int i;
714 unsigned int n;
715 unsigned long long *fc;
716 const unsigned long long *dc;
717
718 if (NULL == bf)
719 return GNUNET_YES;
720 if (bf->bitArraySize != size)
721 return GNUNET_SYSERR;
722 fc = (unsigned long long *) bf->bitArray;
723 dc = (const unsigned long long *) data;
724 n = size / sizeof(unsigned long long);
725
726 for (i = 0; i < n; i++)
727 fc[i] |= dc[i];
728 for (i = n * sizeof(unsigned long long); i < size; i++)
729 bf->bitArray[i] |= data[i];
730 return GNUNET_OK;
731}
732
733
737 const struct GNUNET_CONTAINER_BloomFilter *to_or)
738{
739 unsigned int i;
740 unsigned int n;
741 unsigned long long *fc;
742 const unsigned long long *dc;
743 size_t size;
744
745 if (NULL == bf)
746 return GNUNET_OK;
747 if (bf->bitArraySize != to_or->bitArraySize)
748 {
749 GNUNET_break (0);
750 return GNUNET_SYSERR;
751 }
752 size = bf->bitArraySize;
753 fc = (unsigned long long *) bf->bitArray;
754 dc = (const unsigned long long *) to_or->bitArray;
755 n = size / sizeof(unsigned long long);
756
757 for (i = 0; i < n; i++)
758 fc[i] |= dc[i];
759 for (i = n * sizeof(unsigned long long); i < size; i++)
760 bf->bitArray[i] |= to_or->bitArray[i];
761 return GNUNET_OK;
762}
763
764
765void
767 const struct GNUNET_HashCode *e)
768{
769 if (NULL == bf)
770 return;
771 if (NULL == bf->filename)
772 return;
773 iterateBits (bf,
775 bf,
776 e);
777}
778
779
780void
783 void *iterator_cls,
784 size_t size,
785 unsigned int k)
786{
787 struct GNUNET_HashCode hc;
788 unsigned int i;
789
790 GNUNET_free (bf->bitArray);
791 i = 1;
792 while (i < size)
793 i *= 2;
794 size = i; /* make sure it's a power of 2 */
795 bf->addressesPerElement = k;
796 bf->bitArraySize = size;
798 if (NULL != bf->filename)
799 make_empty_file (bf->fh, bf->bitArraySize * 4LL);
800 while (GNUNET_YES == iterator (iterator_cls, &hc))
802}
803
804
805/* end of container_bloomfilter.c */
#define BUFFSIZE
static enum GNUNET_GenericReturnValue make_empty_file(const struct GNUNET_DISK_FileHandle *fh, size_t size)
Creates a file filled with zeroes.
static enum GNUNET_GenericReturnValue testBitCallback(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Callback: test if all bits are set.
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 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.
static enum GNUNET_GenericReturnValue incrementBitCallback(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Callback: increment bit.
static void clearBit(char *bitArray, unsigned int bitIdx)
Clears a bit from bitArray.
#define LOG_STRERROR_FILE(kind, syscall, filename)
static void setBit(char *bitArray, unsigned int bitIdx)
Sets a bit active in the bitArray.
enum GNUNET_GenericReturnValue(* 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 ...
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.
static bool testBit(char *bitArray, unsigned int bitIdx)
Checks if a bit is active in the bitArray.
static enum GNUNET_GenericReturnValue decrementBitCallback(void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
Callback: decrement bit.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_DownloadContext * dc
static char * filename
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
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.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
bool GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_copy(const struct GNUNET_CONTAINER_BloomFilter *bf)
Create a copy of a bloomfilter.
void GNUNET_CONTAINER_bloomfilter_clear(struct GNUNET_CONTAINER_BloomFilter *bf)
Reset a Bloom filter to empty.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this Bloom filter into the given data array.
int(* GNUNET_CONTAINER_HashCodeIterator)(void *cls, struct GNUNET_HashCode *next)
Iterator over struct GNUNET_HashCode.
enum GNUNET_GenericReturnValue 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.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load(const char *filename, size_t size, unsigned int k)
Load a Bloom filter from a file.
enum GNUNET_GenericReturnValue 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.
size_t GNUNET_CONTAINER_bloomfilter_get_size(const struct GNUNET_CONTAINER_BloomFilter *bf)
Get size of the bloom filter.
void GNUNET_CONTAINER_bloomfilter_remove(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Remove an element from the 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...
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:1258
enum GNUNET_GenericReturnValue 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:533
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:710
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:219
enum GNUNET_GenericReturnValue GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition disk.c:199
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1332
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:673
enum GNUNET_GenericReturnValue GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition disk.c:206
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_OPEN_READWRITE
Open the file for both reading and writing.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_SEEK_SET
Seek an absolute position (from the start of the file).
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_malloc_large(size)
Wrapper around malloc.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
size_t bitArraySize
Size of bitArray in bytes.
unsigned int addressesPerElement
How many bits we set for each stored element.
struct GNUNET_DISK_FileHandle * fh
The bit counter file on disk.
char * bitArray
The actual bloomfilter bit array.
char * filename
Filename of the filter.
Handle used to access files (and pipes).
A 512-bit hashcode.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)     GNUNET_log_from_strerror (kind, "util-container-bloomfilter", syscall)

Definition at line 49 of file container_bloomfilter.c.

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  syscall,
  filename 
)
Value:
"util-container-bloomfilter", \
syscall, \
#define GNUNET_log_from_strerror_file(level, component, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...

Definition at line 52 of file container_bloomfilter.c.

◆ BUFFSIZE

#define BUFFSIZE   65536

Definition at line 295 of file container_bloomfilter.c.

Typedef Documentation

◆ BitIterator

typedef enum GNUNET_GenericReturnValue(* 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 tested for the key.

Parameters
clsclosure
bfthe filter to manipulate
bitthe current bit
Returns
GNUNET_YES to continue, GNUNET_NO to stop early

Definition at line 305 of file container_bloomfilter.c.

Function Documentation

◆ setBit()

static void setBit ( char *  bitArray,
unsigned int  bitIdx 
)
static

Sets a bit active in the bitArray.

Increment bit-specific usage counter on disk only if below 4bit max (==15).

Parameters
bitArraymemory area to set the bit in
bitIdxwhich bit to set

Definition at line 125 of file container_bloomfilter.c.

127{
128 size_t arraySlot;
129 unsigned int targetBit;
130
131 arraySlot = bitIdx / 8;
132 targetBit = (1L << (bitIdx % 8));
133 bitArray[arraySlot] |= targetBit;
134}

References GNUNET_CONTAINER_BloomFilter::bitArray.

Referenced by GNUNET_CONTAINER_bloomfilter_load(), and incrementBit().

Here is the caller graph for this function:

◆ clearBit()

static void clearBit ( char *  bitArray,
unsigned int  bitIdx 
)
static

Clears a bit from bitArray.

Bit is cleared from the array only if the respective usage counter on the disk hits/is zero.

Parameters
bitArraymemory area to set the bit in
bitIdxwhich bit to unset

Definition at line 145 of file container_bloomfilter.c.

146{
147 size_t slot;
148 unsigned int targetBit;
149
150 slot = bitIdx / 8;
151 targetBit = (1L << (bitIdx % 8));
152 bitArray[slot] = bitArray[slot] & (~targetBit);
153}

References GNUNET_CONTAINER_BloomFilter::bitArray.

Referenced by decrementBit().

Here is the caller graph for this function:

◆ testBit()

static bool testBit ( char *  bitArray,
unsigned int  bitIdx 
)
static

Checks if a bit is active in the bitArray.

Parameters
bitArraymemory area to set the bit in
bitIdxwhich bit to test
Returns
true if the bit is set, false if not.

Definition at line 164 of file container_bloomfilter.c.

166{
167 size_t slot;
168 unsigned int targetBit;
169
170 slot = bitIdx / 8;
171 targetBit = (1L << (bitIdx % 8));
172 if (bitArray[slot] & targetBit)
173 return true;
174 return false;
175}

References GNUNET_CONTAINER_BloomFilter::bitArray.

Referenced by testBitCallback().

Here is the caller graph for this function:

◆ incrementBit()

static void incrementBit ( char *  bitArray,
unsigned int  bitIdx,
const struct GNUNET_DISK_FileHandle fh 
)
static

Sets a bit active in the bitArray and increments bit-specific usage counter on disk (but only if the counter was below 4 bit max (==15)).

Parameters
bitArraymemory area to set the bit in
bitIdxwhich bit to test
fhA file to keep the 4 bit address usage counters in

Definition at line 188 of file container_bloomfilter.c.

191{
192 off_t fileSlot;
193 unsigned char value;
194 unsigned int high;
195 unsigned int low;
196 unsigned int targetLoc;
197
198 setBit (bitArray,
199 bitIdx);
201 return;
202 /* Update the counter file on disk */
203 fileSlot = bitIdx / 2;
204 targetLoc = bitIdx % 2;
205
206 GNUNET_assert (fileSlot ==
208 if (1 != GNUNET_DISK_file_read (fh, &value, 1))
209 value = 0;
210 low = value & 0xF;
211 high = (value & (~0xF)) >> 4;
212
213 if (targetLoc == 0)
214 {
215 if (low < 0xF)
216 low++;
217 }
218 else
219 {
220 if (high < 0xF)
221 high++;
222 }
223 value = ((high << 4) | low);
224 GNUNET_assert (fileSlot ==
227}

References GNUNET_CONTAINER_BloomFilter::bitArray, GNUNET_CONTAINER_BloomFilter::fh, GNUNET_assert, GNUNET_DISK_file_read(), GNUNET_DISK_file_seek(), GNUNET_DISK_file_write(), GNUNET_DISK_handle_invalid(), GNUNET_DISK_SEEK_SET, setBit(), and value.

Referenced by incrementBitCallback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decrementBit()

static void decrementBit ( char *  bitArray,
unsigned int  bitIdx,
const struct GNUNET_DISK_FileHandle fh 
)
static

Clears a bit from bitArray if the respective usage counter on the disk hits/is zero.

Parameters
bitArraymemory area to set the bit in
bitIdxwhich bit to test
fhA file to keep the 4bit address usage counters in

Definition at line 239 of file container_bloomfilter.c.

242{
243 off_t fileslot;
244 unsigned char value;
245 unsigned int high;
246 unsigned int low;
247 unsigned int targetLoc;
248
250 return; /* cannot decrement! */
251 /* Each char slot in the counter file holds two 4 bit counters */
252 fileslot = bitIdx / 2;
253 targetLoc = bitIdx % 2;
254 if (GNUNET_SYSERR ==
256 {
258 return;
259 }
260 if (1 != GNUNET_DISK_file_read (fh, &value, 1))
261 value = 0;
262 low = value & 0xF;
263 high = (value & 0xF0) >> 4;
264
265 /* decrement, but once we have reached the max, never go back! */
266 if (targetLoc == 0)
267 {
268 if ((low > 0) && (low < 0xF))
269 low--;
270 if (low == 0)
271 {
272 clearBit (bitArray, bitIdx);
273 }
274 }
275 else
276 {
277 if ((high > 0) && (high < 0xF))
278 high--;
279 if (high == 0)
280 {
281 clearBit (bitArray, bitIdx);
282 }
283 }
284 value = ((high << 4) | low);
285 if (GNUNET_SYSERR ==
287 {
289 return;
290 }
292}

References GNUNET_CONTAINER_BloomFilter::bitArray, clearBit(), GNUNET_CONTAINER_BloomFilter::fh, GNUNET_assert, GNUNET_DISK_file_read(), GNUNET_DISK_file_seek(), GNUNET_DISK_file_write(), GNUNET_DISK_handle_invalid(), GNUNET_DISK_SEEK_SET, GNUNET_ERROR_TYPE_ERROR, GNUNET_log_strerror, GNUNET_SYSERR, and value.

Referenced by decrementBitCallback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_empty_file()

static enum GNUNET_GenericReturnValue make_empty_file ( const struct GNUNET_DISK_FileHandle fh,
size_t  size 
)
static

Creates a file filled with zeroes.

Parameters
fhthe file handle
sizethe size of the file
Returns
GNUNET_OK if created ok, GNUNET_SYSERR otherwise

Definition at line 305 of file container_bloomfilter.c.

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}

Referenced by GNUNET_CONTAINER_bloomfilter_clear(), GNUNET_CONTAINER_bloomfilter_load(), and GNUNET_CONTAINER_bloomfilter_resize().

Here is the caller graph for this function:

◆ iterateBits()

static void iterateBits ( const struct GNUNET_CONTAINER_BloomFilter bf,
BitIterator  callback,
void *  arg,
const struct GNUNET_HashCode key 
)
static

Call an iterator for each bit that the bloomfilter must test or set for this element.

Parameters
bfthe filter
callbackthe method to call
argextra argument to callback
keythe key for which we iterate over the BF bits

Definition at line 365 of file container_bloomfilter.c.

369{
370 struct GNUNET_HashCode tmp = *key;
371 int bitCount;
372 unsigned int slot = 0;
373
374 bitCount = bf->addressesPerElement;
375 GNUNET_assert (bf->bitArraySize > 0);
376 GNUNET_assert (bf->bitArraySize * 8LL > bf->bitArraySize);
377 while (bitCount > 0)
378 {
379 while ( (0 != bitCount) &&
380 (slot < (sizeof(struct GNUNET_HashCode) / sizeof(uint32_t))) )
381 {
382 if (GNUNET_YES !=
383 callback (arg,
384 bf,
385 ntohl ((((uint32_t *) &tmp)[slot]))
386 % ((bf->bitArraySize * 8LL))))
387 return;
388 slot++;
389 bitCount--;
390 }
391 if (0 == bitCount)
392 break;
393 GNUNET_CRYPTO_hash (&tmp,
394 sizeof(tmp),
395 &tmp);
396 slot = 0;
397 }
398}

References GNUNET_CONTAINER_BloomFilter::addressesPerElement, GNUNET_CONTAINER_BloomFilter::bitArraySize, GNUNET_assert, GNUNET_CRYPTO_hash(), GNUNET_YES, and key.

Referenced by GNUNET_CONTAINER_bloomfilter_add(), GNUNET_CONTAINER_bloomfilter_remove(), and GNUNET_CONTAINER_bloomfilter_test().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ incrementBitCallback()

static enum GNUNET_GenericReturnValue incrementBitCallback ( void *  cls,
const struct GNUNET_CONTAINER_BloomFilter bf,
unsigned int  bit 
)
static

Callback: increment bit.

Parameters
clspointer to writeable form of bf
bfthe filter to manipulate
bitthe bit to increment
Returns
GNUNET_YES

Definition at line 410 of file container_bloomfilter.c.

413{
414 struct GNUNET_CONTAINER_BloomFilter *b = cls;
415
417 bit,
418 bf->fh);
419 return GNUNET_YES;
420}

References GNUNET_CONTAINER_BloomFilter::bitArray, GNUNET_CONTAINER_BloomFilter::fh, GNUNET_YES, and incrementBit().

Referenced by GNUNET_CONTAINER_bloomfilter_add().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decrementBitCallback()

static enum GNUNET_GenericReturnValue decrementBitCallback ( void *  cls,
const struct GNUNET_CONTAINER_BloomFilter bf,
unsigned int  bit 
)
static

Callback: decrement bit.

Parameters
clspointer to writeable form of bf
bfthe filter to manipulate
bitthe bit to decrement
Returns
GNUNET_YES

Definition at line 432 of file container_bloomfilter.c.

435{
436 struct GNUNET_CONTAINER_BloomFilter *b = cls;
437
439 bit,
440 bf->fh);
441 return GNUNET_YES;
442}

References GNUNET_CONTAINER_BloomFilter::bitArray, decrementBit(), GNUNET_CONTAINER_BloomFilter::fh, and GNUNET_YES.

Referenced by GNUNET_CONTAINER_bloomfilter_remove().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ testBitCallback()

static enum GNUNET_GenericReturnValue testBitCallback ( void *  cls,
const struct GNUNET_CONTAINER_BloomFilter bf,
unsigned int  bit 
)
static

Callback: test if all bits are set.

Parameters
clspointer set to false if bit is not set
bfthe filter
bitthe bit to test
Returns
GNUNET_YES if the bit is set, GNUNET_NO if not

Definition at line 454 of file container_bloomfilter.c.

457{
458 bool *arg = cls;
459
460 if (! testBit (bf->bitArray, bit))
461 {
462 *arg = false;
463 return GNUNET_NO;
464 }
465 return GNUNET_YES;
466}

References GNUNET_CONTAINER_BloomFilter::bitArray, GNUNET_NO, GNUNET_YES, and testBit().

Referenced by GNUNET_CONTAINER_bloomfilter_test().

Here is the call graph for this function:
Here is the caller graph for this function: