GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
ibf.c File Reference
#include "platform.h"
#include "ibf.h"
#include "gnunet_util_lib.h"
Include dependency graph for ibf.c:

Go to the source code of this file.

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "setu", __VA_ARGS__)
 
#define IBF_KEY_HASH_VAL(k)
 Compute the key's hash from the key.
 

Functions

struct IBF_Key ibf_key_from_hashcode (const struct GNUNET_HashCode *hash)
 Create a key from a hashcode.
 
void ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst)
 Create a hashcode from a key, by replicating the key until the hascode is filled.
 
struct InvertibleBloomFilteribf_create (uint32_t size, uint8_t hash_num)
 Create an invertible bloom filter.
 
static void ibf_get_indices (const struct InvertibleBloomFilter *ibf, struct IBF_Key key, int *dst)
 Store unique bucket indices for the specified key in dst.
 
static void ibf_insert_into (struct InvertibleBloomFilter *ibf, struct IBF_Key key, const int *buckets, int side)
 
void ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
 Insert a key into an IBF.
 
void ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
 Remove a key from an IBF.
 
static int ibf_is_empty (struct InvertibleBloomFilter *ibf)
 Test is the IBF is empty, i.e.
 
int ibf_decode (struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id)
 Decode and remove an element from the IBF, if possible.
 
uint8_t ibf_get_max_counter (struct InvertibleBloomFilter *ibf)
 Returns the minimal bytes needed to store the counter of the IBF.
 
void ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start, uint64_t count, void *buf, uint8_t counter_max_length)
 Write buckets from an ibf to a buffer.
 
void pack_counter (const struct InvertibleBloomFilter *ibf, uint32_t start, uint64_t count, uint8_t *buf, uint8_t counter_max_length)
 Packs the counter to transmit only the smallest possible amount of bytes and preventing overflow of the counter.
 
void unpack_counter (const struct InvertibleBloomFilter *ibf, uint32_t start, uint64_t count, uint8_t *buf, uint8_t counter_max_length)
 Unpacks the counter to transmit only the smallest possible amount of bytes and preventing overflow of the counter.
 
void ibf_read_slice (const void *buf, uint32_t start, uint64_t count, struct InvertibleBloomFilter *ibf, uint8_t counter_max_length)
 Read buckets from a buffer into an ibf.
 
void ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
 Subtract ibf2 from ibf1, storing the result in ibf1.
 
struct InvertibleBloomFilteribf_dup (const struct InvertibleBloomFilter *ibf)
 Create a copy of an IBF, the copy has to be destroyed properly.
 
void ibf_destroy (struct InvertibleBloomFilter *ibf)
 Destroy all resources associated with the invertible bloom filter.
 

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "setu", __VA_ARGS__)

Definition at line 31 of file ibf.c.

◆ IBF_KEY_HASH_VAL

#define IBF_KEY_HASH_VAL (   k)
Value:
(GNUNET_CRYPTO_crc32_n (&(k), sizeof(struct \
int32_t GNUNET_CRYPTO_crc32_n(const void *buf, size_t len)
Compute the CRC32 checksum for the first len bytes of the buffer.
Definition crypto_crc.c:99
Hash of an IBF key.
Definition ibf.h:55

Compute the key's hash from the key.

Redefine to use a different hash function.

Definition at line 38 of file ibf.c.

48{
49 return *(struct IBF_Key *) hash;
50}
51
52
60void
62 struct GNUNET_HashCode *dst)
63{
64 struct IBF_Key *p;
65 unsigned int i;
66 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode)
67 / sizeof(struct IBF_Key);
68
69 p = (struct IBF_Key *) dst;
70 for (i = 0; i < keys_per_hashcode; i++)
71 *p++ = key;
72}
73
74
83ibf_create (uint32_t size, uint8_t hash_num)
84{
85 struct InvertibleBloomFilter *ibf;
86
87 GNUNET_assert (0 != size);
88
89 ibf = GNUNET_new (struct InvertibleBloomFilter);
90 ibf->count = GNUNET_malloc_large (size * sizeof(uint64_t));
91 if (NULL == ibf->count)
92 {
93 GNUNET_free (ibf);
94 return NULL;
95 }
96 ibf->key_sum = GNUNET_malloc_large (size * sizeof(struct IBF_Key));
97 if (NULL == ibf->key_sum)
98 {
99 GNUNET_free (ibf->count);
100 GNUNET_free (ibf);
101 return NULL;
102 }
103 ibf->key_hash_sum = GNUNET_malloc_large (size * sizeof(struct IBF_KeyHash));
104 if (NULL == ibf->key_hash_sum)
105 {
106 GNUNET_free (ibf->key_sum);
107 GNUNET_free (ibf->count);
108 GNUNET_free (ibf);
109 return NULL;
110 }
111 ibf->size = size;
112 ibf->hash_num = hash_num;
113
114 return ibf;
115}
116
117
121static void
122ibf_get_indices (const struct InvertibleBloomFilter *ibf,
123 struct IBF_Key key,
124 int *dst)
125{
126 uint32_t filled;
127 uint32_t i;
128 uint32_t bucket;
129
130 bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key);
131 for (i = 0, filled = 0; filled < ibf->hash_num; i++)
132 {
133 uint64_t x;
134
135 for (unsigned int j = 0; j < filled; j++)
136 if (dst[j] == bucket % ibf->size)
137 goto try_next;
138 dst[filled++] = bucket % ibf->size;
139try_next:
140 x = ((uint64_t) bucket << 32) | i;
141 bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x);
142 }
143}
144
145
146static void
148 struct IBF_Key key,
149 const int *buckets,
150 int side)
151{
152 for (unsigned int i = 0; i < ibf->hash_num; i++)
153 {
154 const int bucket = buckets[i];
155
156 ibf->count[bucket].count_val += side;
157 ibf->key_sum[bucket].key_val ^= key.key_val;
158 ibf->key_hash_sum[bucket].key_hash_val
160 }
161}
162
163
170void
172 struct IBF_Key key)
173{
174 int buckets[ibf->hash_num];
175
176 GNUNET_assert (ibf->hash_num <= ibf->size);
177 ibf_get_indices (ibf, key, buckets);
178 ibf_insert_into (ibf, key, buckets, 1);
179}
180
181
188void
190 struct IBF_Key key)
191{
192 int buckets[ibf->hash_num];
193
194 GNUNET_assert (ibf->hash_num <= ibf->size);
195 ibf_get_indices (ibf, key, buckets);
196 ibf_insert_into (ibf, key, buckets, -1);
197}
198
199
203static int
205{
206 for (uint32_t i = 0; i < ibf->size; i++)
207 {
208 if (0 != ibf->count[i].count_val)
209 return GNUNET_NO;
210 if (0 != ibf->key_hash_sum[i].key_hash_val)
211 return GNUNET_NO;
212 if (0 != ibf->key_sum[i].key_val)
213 return GNUNET_NO;
214 }
215 return GNUNET_YES;
216}
217
218
219int
221 int *ret_side,
222 struct IBF_Key *ret_id)
223{
224 struct IBF_KeyHash hash;
225 int buckets[ibf->hash_num];
226
227 for (uint32_t i = 0; i < ibf->size; i++)
228 {
229 int hit;
230
231 /* we can only decode from pure buckets */
232 if ( (1 != ibf->count[i].count_val) &&
233 (-1 != ibf->count[i].count_val) )
234 continue;
235
236 hash.key_hash_val = IBF_KEY_HASH_VAL (ibf->key_sum[i]);
237
238 /* test if the hash matches the key */
239 if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val)
240 continue;
241
242 /* test if key in bucket hits its own location,
243 * if not, the key hash was subject to collision */
244 hit = GNUNET_NO;
245 ibf_get_indices (ibf, ibf->key_sum[i], buckets);
246 for (int j = 0; j < ibf->hash_num; j++)
247 if (buckets[j] == i)
248 hit = GNUNET_YES;
249
250 if (GNUNET_NO == hit)
251 continue;
252
253 if (1 == ibf->count[i].count_val)
254 {
256 }
257 else
258 {
259 ibf->local_decoded_count++;
260 }
261
262
263 if (NULL != ret_side)
264 *ret_side = ibf->count[i].count_val;
265 if (NULL != ret_id)
266 *ret_id = ibf->key_sum[i];
267
268 /* insert on the opposite side, effectively removing the element */
269 ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val);
270
271 return GNUNET_YES;
272 }
273
274 if (GNUNET_YES == ibf_is_empty (ibf))
275 return GNUNET_NO;
276 return GNUNET_SYSERR;
277}
278
279
285uint8_t
287{
288 long long max_counter = 0;
289 for (uint64_t i = 0; i < ibf->size; i++)
290 {
291 if (ibf->count[i].count_val > max_counter)
292 {
293 max_counter = ibf->count[i].count_val;
294 }
295 }
296 return 64 - __builtin_clzll (max_counter);
297}
298
299
310void
311ibf_write_slice (const struct InvertibleBloomFilter *ibf,
312 uint32_t start,
313 uint64_t count,
314 void *buf,
315 uint8_t counter_max_length)
316{
317 struct IBF_Key *key_dst;
318 struct IBF_KeyHash *key_hash_dst;
319
320 GNUNET_assert (start + count <= ibf->size);
321
322 /* copy keys */
323 key_dst = (struct IBF_Key *) buf;
324 GNUNET_memcpy (key_dst,
325 ibf->key_sum + start,
326 count * sizeof(*key_dst));
327 key_dst += count;
328 /* copy key hashes */
329 key_hash_dst = (struct IBF_KeyHash *) key_dst;
330 GNUNET_memcpy (key_hash_dst,
331 ibf->key_hash_sum + start,
332 count * sizeof(*key_hash_dst));
333 key_hash_dst += count;
334
335 /* pack and copy counter */
336 pack_counter (ibf,
337 start,
338 count,
339 (uint8_t *) key_hash_dst,
340 counter_max_length);
341
342
343}
344
345
346void
347pack_counter (const struct InvertibleBloomFilter *ibf,
348 uint32_t start,
349 uint64_t count,
350 uint8_t *buf,
351 uint8_t counter_max_length)
352{
353 uint8_t store_size = 0;
354 uint8_t store = 0;
355 uint16_t byte_ctr = 0;
356
360 for (uint64_t i = start; i< (count + start);)
361 {
362 uint64_t count_val_to_write = ibf->count[i].count_val;
363 uint8_t count_len_to_write = counter_max_length;
364
368 while ((count_len_to_write + store_size) >= 8)
369 {
370 uint8_t bit_shift = 0;
371
376 if ((store_size > 0) || (count_len_to_write > 8))
377 {
378 uint8_t bit_unused = 8 - store_size;
379 bit_shift = count_len_to_write - bit_unused;
380 store = store << bit_unused;
381 }
382
383 buf[byte_ctr] = ((count_val_to_write >> bit_shift) | store) & 0xFF;
384 byte_ctr++;
385 count_len_to_write -= (8 - store_size);
386 count_val_to_write = count_val_to_write & ((1ULL <<
387 count_len_to_write) - 1);
388 store = 0;
389 store_size = 0;
390 }
391 store = (store << count_len_to_write) | count_val_to_write;
392 store_size = store_size + count_len_to_write;
393 count_len_to_write = 0;
394 i++;
395 }
396
400 if (store_size > 0)
401 {
402 buf[byte_ctr] = store << (8 - store_size);
403 byte_ctr++;
404 }
405
406}
407
408
409void
410unpack_counter (const struct InvertibleBloomFilter *ibf,
411 uint32_t start,
412 uint64_t count,
413 uint8_t *buf,
414 uint8_t counter_max_length)
415{
416 uint64_t ibf_counter_ctr = 0;
417 uint64_t store = 0;
418 uint64_t store_bit_ctr = 0;
419 uint64_t byte_ctr = 0;
420
424 while (true)
425 {
426 uint8_t byte_read = buf[byte_ctr];
427 uint8_t bit_to_read_left = 8;
428 byte_ctr++;
429
433 while (true)
434 {
438 if (ibf_counter_ctr > (count - 1))
439 return;
440
441 /*
442 * Unpack the counter
443 */
444 if ((store_bit_ctr + bit_to_read_left) >= counter_max_length)
445 {
446 uint8_t bytes_used = counter_max_length - store_bit_ctr;
447 if (store_bit_ctr > 0)
448 {
449 store = store << bytes_used;
450 }
451 {
452 uint8_t bytes_to_shift = bit_to_read_left - bytes_used;
453 uint64_t counter_part = byte_read >> bytes_to_shift;
454 store = store | counter_part;
455 ibf->count[ibf_counter_ctr + start].count_val = store;
456 byte_read = byte_read & ((1 << bytes_to_shift) - 1);
457 bit_to_read_left -= bytes_used;
458 ibf_counter_ctr++;
459 store = 0;
460 store_bit_ctr = 0;
461 }
462 }
463 else
464 {
465 store_bit_ctr += bit_to_read_left;
466 if (0 == store)
467 {
468 store = byte_read;
469 }
470 else
471 {
472 store = store << bit_to_read_left;
473 store = store | byte_read;
474 }
475 break;
476 }
477 }
478 }
479}
480
481
491void
492ibf_read_slice (const void *buf,
493 uint32_t start,
494 uint64_t count,
495 struct InvertibleBloomFilter *ibf,
496 uint8_t counter_max_length)
497{
498 struct IBF_Key *key_src;
499 struct IBF_KeyHash *key_hash_src;
500 struct IBF_Count *count_src;
501
502 GNUNET_assert (count > 0);
503 GNUNET_assert (start + count <= ibf->size);
504
505 /* copy keys */
506 key_src = (struct IBF_Key *) buf;
508 key_src,
509 count * sizeof *key_src);
510 key_src += count;
511 /* copy key hashes */
512 key_hash_src = (struct IBF_KeyHash *) key_src;
514 key_hash_src,
515 count * sizeof *key_hash_src);
516 key_hash_src += count;
517
518 /* copy and unpack counts */
519 count_src = (struct IBF_Count *) key_hash_src;
520 unpack_counter (ibf,start,count,(uint8_t *) count_src,counter_max_length);
521}
522
523
531void
533 const struct InvertibleBloomFilter *ibf2)
534{
535 GNUNET_assert (ibf1->size == ibf2->size);
536 GNUNET_assert (ibf1->hash_num == ibf2->hash_num);
537
538 for (uint32_t i = 0; i < ibf1->size; i++)
539 {
540 ibf1->count[i].count_val -= ibf2->count[i].count_val;
542 ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val;
543 }
544}
545
546
553ibf_dup (const struct InvertibleBloomFilter *ibf)
554{
555 struct InvertibleBloomFilter *copy;
556
557 copy = GNUNET_malloc (sizeof *copy);
558 copy->hash_num = ibf->hash_num;
559 copy->size = ibf->size;
561 ibf->size * sizeof(struct IBF_KeyHash));
562 copy->key_sum = GNUNET_memdup (ibf->key_sum,
563 ibf->size * sizeof(struct IBF_Key));
564 copy->count = GNUNET_memdup (ibf->count,
565 ibf->size * sizeof(struct IBF_Count));
566 return copy;
567}
568
569
576void
578{
579 GNUNET_free (ibf->key_sum);
581 GNUNET_free (ibf->count);
582 GNUNET_free (ibf);
583}
void ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
Subtract ibf2 from ibf1, storing the result in ibf1.
Definition ibf.c:357
int ibf_decode(struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id)
Decode and remove an element from the IBF, if possible.
Definition ibf.c:229
void ibf_read_slice(const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf)
Read buckets from a buffer into an ibf.
Definition ibf.c:324
void ibf_write_slice(const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf)
Write buckets from an ibf to a buffer.
Definition ibf.c:291
#define IBF_KEY_HASH_VAL(k)
Compute the key's hash from the key.
Definition ibf.c:34
static void ibf_get_indices(const struct InvertibleBloomFilter *ibf, struct IBF_Key key, int *dst)
Store unique bucket indices for the specified key in dst.
Definition ibf.c:119
void ibf_hashcode_from_key(struct IBF_Key key, struct GNUNET_HashCode *dst)
Create a hashcode from a key, by replicating the key until the hascode is filled.
Definition ibf.c:58
void ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Insert a key into an IBF.
Definition ibf.c:168
struct InvertibleBloomFilter * ibf_dup(const struct InvertibleBloomFilter *ibf)
Create a copy of an IBF, the copy has to be destroyed properly.
Definition ibf.c:380
static void ibf_insert_into(struct InvertibleBloomFilter *ibf, struct IBF_Key key, const int *buckets, int side)
Definition ibf.c:144
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition ibf.c:80
static int ibf_is_empty(struct InvertibleBloomFilter *ibf)
Test is the IBF is empty, i.e.
Definition ibf.c:199
void ibf_remove(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Remove a key from an IBF.
Definition ibf.c:185
void ibf_destroy(struct InvertibleBloomFilter *ibf)
Destroy all resources associated with the invertible bloom filter.
Definition ibf.c:404
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned int hash_num
static struct GNUNET_OS_Process * p
Helper process we started.
Definition gnunet-uri.c:38
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#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.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
static unsigned int size
Size of the "table".
Definition peer.c:68
uint8_t ibf_get_max_counter(struct InvertibleBloomFilter *ibf)
Returns the minimal bytes needed to store the counter of the IBF.
Definition ibf.c:287
void unpack_counter(const struct InvertibleBloomFilter *ibf, uint32_t start, uint64_t count, uint8_t *buf, uint8_t counter_max_length)
Unpacks the counter to transmit only the smallest possible amount of bytes and preventing overflow of...
Definition ibf.c:411
void pack_counter(const struct InvertibleBloomFilter *ibf, uint32_t start, uint64_t count, uint8_t *buf, uint8_t counter_max_length)
Packs the counter to transmit only the smallest possible amount of bytes and preventing overflow of t...
Definition ibf.c:348
A 512-bit hashcode.
Type of the count field of IBF buckets.
Definition ibf.h:64
int8_t count_val
Definition ibf.h:65
uint32_t key_hash_val
Definition ibf.h:56
Keys that can be inserted into and removed from an IBF.
Definition ibf.h:46
uint64_t key_val
Definition ibf.h:47
Invertible bloom filter (IBF).
Definition ibf.h:83
int remote_decoded_count
If an IBF is decoded this count stores how many elements are on the remote site.
Definition ibf.h:108
int local_decoded_count
If an IBF is decoded this count stores how many elements are on the local site.
Definition ibf.h:101
struct IBF_KeyHash * key_hash_sum
Xor sums of the hashes of the keys of inserted elements.
Definition ibf.h:105
uint32_t size
How many cells does this IBF have?
Definition ibf.h:87
struct IBF_Count * count
How many times has a bucket been hit? Can be negative, as a result of IBF subtraction.
Definition ibf.h:112
struct IBF_Key * key_sum
Xor sums of the elements' keys, used to identify the elements.
Definition ibf.h:99
uint8_t hash_num
In how many cells do we hash one element? Usually 4 or 3.
Definition ibf.h:93

Function Documentation

◆ ibf_key_from_hashcode()

struct IBF_Key ibf_key_from_hashcode ( const struct GNUNET_HashCode hash)

Create a key from a hashcode.

Parameters
hashthe hashcode
Returns
a key

Definition at line 48 of file ibf.c.

49{
50 return *(struct IBF_Key *) hash;
51}

◆ ibf_hashcode_from_key()

void ibf_hashcode_from_key ( struct IBF_Key  key,
struct GNUNET_HashCode dst 
)

Create a hashcode from a key, by replicating the key until the hascode is filled.

Parameters
keythe key
dsthashcode to store the result in

Definition at line 62 of file ibf.c.

64{
65 struct IBF_Key *p;
66 unsigned int i;
67 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode)
68 / sizeof(struct IBF_Key);
69
70 p = (struct IBF_Key *) dst;
71 for (i = 0; i < keys_per_hashcode; i++)
72 *p++ = key;
73}

References key, and p.

◆ ibf_create()

struct InvertibleBloomFilter * ibf_create ( uint32_t  size,
uint8_t  hash_num 
)

Create an invertible bloom filter.

Parameters
sizenumber of IBF buckets
hash_numnumber of buckets one element is hashed in
Returns
the newly created invertible bloom filter, NULL on error

Definition at line 84 of file ibf.c.

85{
86 struct InvertibleBloomFilter *ibf;
87
88 GNUNET_assert (0 != size);
89
90 ibf = GNUNET_new (struct InvertibleBloomFilter);
91 ibf->count = GNUNET_malloc_large (size * sizeof(uint64_t));
92 if (NULL == ibf->count)
93 {
94 GNUNET_free (ibf);
95 return NULL;
96 }
97 ibf->key_sum = GNUNET_malloc_large (size * sizeof(struct IBF_Key));
98 if (NULL == ibf->key_sum)
99 {
100 GNUNET_free (ibf->count);
101 GNUNET_free (ibf);
102 return NULL;
103 }
104 ibf->key_hash_sum = GNUNET_malloc_large (size * sizeof(struct IBF_KeyHash));
105 if (NULL == ibf->key_hash_sum)
106 {
107 GNUNET_free (ibf->key_sum);
108 GNUNET_free (ibf->count);
109 GNUNET_free (ibf);
110 return NULL;
111 }
112 ibf->size = size;
113 ibf->hash_num = hash_num;
114
115 return ibf;
116}

References InvertibleBloomFilter::count, GNUNET_assert, GNUNET_free, GNUNET_malloc_large, GNUNET_new, hash_num, InvertibleBloomFilter::hash_num, InvertibleBloomFilter::key_hash_sum, InvertibleBloomFilter::key_sum, InvertibleBloomFilter::size, and size.

◆ ibf_get_indices()

static void ibf_get_indices ( const struct InvertibleBloomFilter ibf,
struct IBF_Key  key,
int *  dst 
)
static

Store unique bucket indices for the specified key in dst.

Definition at line 123 of file ibf.c.

126{
127 uint32_t filled;
128 uint32_t i;
129 uint32_t bucket;
130
131 bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key);
132 for (i = 0, filled = 0; filled < ibf->hash_num; i++)
133 {
134 uint64_t x;
135
136 for (unsigned int j = 0; j < filled; j++)
137 if (dst[j] == bucket % ibf->size)
138 goto try_next;
139 dst[filled++] = bucket % ibf->size;
140try_next:
141 x = ((uint64_t) bucket << 32) | i;
142 bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x);
143 }
144}

References GNUNET_CRYPTO_crc32_n(), InvertibleBloomFilter::hash_num, key, and InvertibleBloomFilter::size.

Here is the call graph for this function:

◆ ibf_insert_into()

static void ibf_insert_into ( struct InvertibleBloomFilter ibf,
struct IBF_Key  key,
const int *  buckets,
int  side 
)
static

Definition at line 148 of file ibf.c.

152{
153 for (unsigned int i = 0; i < ibf->hash_num; i++)
154 {
155 const int bucket = buckets[i];
156
157 ibf->count[bucket].count_val += side;
158 ibf->key_sum[bucket].key_val ^= key.key_val;
159 ibf->key_hash_sum[bucket].key_hash_val
161 }
162}

References InvertibleBloomFilter::count, IBF_Count::count_val, InvertibleBloomFilter::hash_num, IBF_KEY_HASH_VAL, key, InvertibleBloomFilter::key_hash_sum, IBF_KeyHash::key_hash_val, InvertibleBloomFilter::key_sum, and IBF_Key::key_val.

◆ ibf_insert()

void ibf_insert ( struct InvertibleBloomFilter ibf,
struct IBF_Key  key 
)

Insert a key into an IBF.

Parameters
ibfthe IBF
keythe element's hash code

Definition at line 172 of file ibf.c.

174{
175 int buckets[ibf->hash_num];
176
177 GNUNET_assert (ibf->hash_num <= ibf->size);
178 ibf_get_indices (ibf, key, buckets);
179 ibf_insert_into (ibf, key, buckets, 1);
180}

References GNUNET_assert, InvertibleBloomFilter::hash_num, ibf_get_indices(), ibf_insert_into(), key, and InvertibleBloomFilter::size.

Here is the call graph for this function:

◆ ibf_remove()

void ibf_remove ( struct InvertibleBloomFilter ibf,
struct IBF_Key  key 
)

Remove a key from an IBF.

Parameters
ibfthe IBF
keythe element's hash code

Definition at line 190 of file ibf.c.

192{
193 int buckets[ibf->hash_num];
194
195 GNUNET_assert (ibf->hash_num <= ibf->size);
196 ibf_get_indices (ibf, key, buckets);
197 ibf_insert_into (ibf, key, buckets, -1);
198}

References GNUNET_assert, InvertibleBloomFilter::hash_num, ibf_get_indices(), ibf_insert_into(), key, and InvertibleBloomFilter::size.

Here is the call graph for this function:

◆ ibf_is_empty()

static int ibf_is_empty ( struct InvertibleBloomFilter ibf)
static

Test is the IBF is empty, i.e.

all counts, keys and key hashes are zero.

Definition at line 205 of file ibf.c.

206{
207 for (uint32_t i = 0; i < ibf->size; i++)
208 {
209 if (0 != ibf->count[i].count_val)
210 return GNUNET_NO;
211 if (0 != ibf->key_hash_sum[i].key_hash_val)
212 return GNUNET_NO;
213 if (0 != ibf->key_sum[i].key_val)
214 return GNUNET_NO;
215 }
216 return GNUNET_YES;
217}

References InvertibleBloomFilter::count, IBF_Count::count_val, GNUNET_NO, GNUNET_YES, InvertibleBloomFilter::key_hash_sum, IBF_KeyHash::key_hash_val, InvertibleBloomFilter::key_sum, IBF_Key::key_val, and InvertibleBloomFilter::size.

◆ ibf_decode()

int ibf_decode ( struct InvertibleBloomFilter ibf,
int *  ret_side,
struct IBF_Key ret_id 
)

Decode and remove an element from the IBF, if possible.

Parameters
ibfthe invertible bloom filter to decode
ret_sidesign of the cell's count where the decoded element came from. A negative sign indicates that the element was recovered resides in an IBF that was previously subtracted from.
ret_idreceives the hash code of the decoded element, if successful
Returns
GNUNET_YES if decoding an element was successful, GNUNET_NO if the IBF is empty, GNUNET_SYSERR if the decoding has failed
Parameters
ibfthe invertible bloom filter to decode
ret_sidesign of the cell's count where the decoded element came from. A negative sign indicates that the element was recovered resides in an IBF that was previously subtracted from.
ret_idreceives the hash code of the decoded element, if successful
Returns
GNUNET_YES if decoding an element was successful, GNUNET_NO if the IBF is empty, GNUNET_SYSERR if the decoding has failed

Definition at line 221 of file ibf.c.

224{
225 struct IBF_KeyHash hash;
226 int buckets[ibf->hash_num];
227
228 for (uint32_t i = 0; i < ibf->size; i++)
229 {
230 int hit;
231
232 /* we can only decode from pure buckets */
233 if ( (1 != ibf->count[i].count_val) &&
234 (-1 != ibf->count[i].count_val) )
235 continue;
236
237 hash.key_hash_val = IBF_KEY_HASH_VAL (ibf->key_sum[i]);
238
239 /* test if the hash matches the key */
240 if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val)
241 continue;
242
243 /* test if key in bucket hits its own location,
244 * if not, the key hash was subject to collision */
245 hit = GNUNET_NO;
246 ibf_get_indices (ibf, ibf->key_sum[i], buckets);
247 for (int j = 0; j < ibf->hash_num; j++)
248 if (buckets[j] == i)
249 hit = GNUNET_YES;
250
251 if (GNUNET_NO == hit)
252 continue;
253
254 if (1 == ibf->count[i].count_val)
255 {
257 }
258 else
259 {
260 ibf->local_decoded_count++;
261 }
262
263
264 if (NULL != ret_side)
265 *ret_side = ibf->count[i].count_val;
266 if (NULL != ret_id)
267 *ret_id = ibf->key_sum[i];
268
269 /* insert on the opposite side, effectively removing the element */
270 ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val);
271
272 return GNUNET_YES;
273 }
274
275 if (GNUNET_YES == ibf_is_empty (ibf))
276 return GNUNET_NO;
277 return GNUNET_SYSERR;
278}

References InvertibleBloomFilter::count, IBF_Count::count_val, GNUNET_NO, GNUNET_SYSERR, GNUNET_YES, InvertibleBloomFilter::hash_num, ibf_get_indices(), ibf_insert_into(), ibf_is_empty(), IBF_KEY_HASH_VAL, InvertibleBloomFilter::key_hash_sum, IBF_KeyHash::key_hash_val, InvertibleBloomFilter::key_sum, InvertibleBloomFilter::local_decoded_count, InvertibleBloomFilter::remote_decoded_count, and InvertibleBloomFilter::size.

Here is the call graph for this function:

◆ ibf_get_max_counter()

uint8_t ibf_get_max_counter ( struct InvertibleBloomFilter ibf)

Returns the minimal bytes needed to store the counter of the IBF.

Parameters
ibfthe IBF

Definition at line 287 of file ibf.c.

288{
289 long long max_counter = 0;
290 for (uint64_t i = 0; i < ibf->size; i++)
291 {
292 if (ibf->count[i].count_val > max_counter)
293 {
294 max_counter = ibf->count[i].count_val;
295 }
296 }
297 return 64 - __builtin_clzll (max_counter);
298}

References InvertibleBloomFilter::count, IBF_Count::count_val, and InvertibleBloomFilter::size.

Referenced by send_ibf().

Here is the caller graph for this function:

◆ ibf_write_slice()

void ibf_write_slice ( const struct InvertibleBloomFilter ibf,
uint32_t  start,
uint64_t  count,
void *  buf,
uint8_t  counter_max_length 
)

Write buckets from an ibf to a buffer.

Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.

Parameters
ibfthe ibf to write
startwith which bucket to start
counthow many buckets to write
bufbuffer to write the data to
maxbit length of a counter for unpacking

Definition at line 312 of file ibf.c.

317{
318 struct IBF_Key *key_dst;
319 struct IBF_KeyHash *key_hash_dst;
320
321 GNUNET_assert (start + count <= ibf->size);
322
323 /* copy keys */
324 key_dst = (struct IBF_Key *) buf;
325 GNUNET_memcpy (key_dst,
326 ibf->key_sum + start,
327 count * sizeof(*key_dst));
328 key_dst += count;
329 /* copy key hashes */
330 key_hash_dst = (struct IBF_KeyHash *) key_dst;
331 GNUNET_memcpy (key_hash_dst,
332 ibf->key_hash_sum + start,
333 count * sizeof(*key_hash_dst));
334 key_hash_dst += count;
335
336 /* pack and copy counter */
337 pack_counter (ibf,
338 start,
339 count,
340 (uint8_t *) key_hash_dst,
341 counter_max_length);
342
343
344}

References GNUNET_assert, GNUNET_memcpy, InvertibleBloomFilter::key_hash_sum, InvertibleBloomFilter::key_sum, pack_counter(), size, and start.

Here is the call graph for this function:

◆ pack_counter()

void pack_counter ( const struct InvertibleBloomFilter ibf,
uint32_t  start,
uint64_t  count,
uint8_t *  buf,
uint8_t  counter_max_length 
)

Packs the counter to transmit only the smallest possible amount of bytes and preventing overflow of the counter.

Parameters
ibfthe ibf to write
startwith which bucket to start
counthow many buckets to write
bufbuffer to write the data to
maxbit length of a counter for unpacking

Iterate over IBF bucket

Pack and compose counters to byte values

Shift bits if more than a byte has to be written or the store size is not empty

Pack data left in story before finishing

Definition at line 348 of file ibf.c.

353{
354 uint8_t store_size = 0;
355 uint8_t store = 0;
356 uint16_t byte_ctr = 0;
357
361 for (uint64_t i = start; i< (count + start);)
362 {
363 uint64_t count_val_to_write = ibf->count[i].count_val;
364 uint8_t count_len_to_write = counter_max_length;
365
369 while ((count_len_to_write + store_size) >= 8)
370 {
371 uint8_t bit_shift = 0;
372
377 if ((store_size > 0) || (count_len_to_write > 8))
378 {
379 uint8_t bit_unused = 8 - store_size;
380 bit_shift = count_len_to_write - bit_unused;
381 store = store << bit_unused;
382 }
383
384 buf[byte_ctr] = ((count_val_to_write >> bit_shift) | store) & 0xFF;
385 byte_ctr++;
386 count_len_to_write -= (8 - store_size);
387 count_val_to_write = count_val_to_write & ((1ULL <<
388 count_len_to_write) - 1);
389 store = 0;
390 store_size = 0;
391 }
392 store = (store << count_len_to_write) | count_val_to_write;
393 store_size = store_size + count_len_to_write;
394 count_len_to_write = 0;
395 i++;
396 }
397
401 if (store_size > 0)
402 {
403 buf[byte_ctr] = store << (8 - store_size);
404 byte_ctr++;
405 }
406
407}

References InvertibleBloomFilter::count, IBF_Count::count_val, and start.

Referenced by ibf_write_slice().

Here is the caller graph for this function:

◆ unpack_counter()

void unpack_counter ( const struct InvertibleBloomFilter ibf,
uint32_t  start,
uint64_t  count,
uint8_t *  buf,
uint8_t  counter_max_length 
)

Unpacks the counter to transmit only the smallest possible amount of bytes and preventing overflow of the counter.

Parameters
ibfthe ibf to write
startwith which bucket to start
counthow many buckets to write
bufbuffer to write the data to
maxbit length of a counter for unpacking

Iterate over received bytes

Pack data left in story before finishing

Stop decoding when end is reached

Definition at line 411 of file ibf.c.

416{
417 uint64_t ibf_counter_ctr = 0;
418 uint64_t store = 0;
419 uint64_t store_bit_ctr = 0;
420 uint64_t byte_ctr = 0;
421
425 while (true)
426 {
427 uint8_t byte_read = buf[byte_ctr];
428 uint8_t bit_to_read_left = 8;
429 byte_ctr++;
430
434 while (true)
435 {
439 if (ibf_counter_ctr > (count - 1))
440 return;
441
442 /*
443 * Unpack the counter
444 */
445 if ((store_bit_ctr + bit_to_read_left) >= counter_max_length)
446 {
447 uint8_t bytes_used = counter_max_length - store_bit_ctr;
448 if (store_bit_ctr > 0)
449 {
450 store = store << bytes_used;
451 }
452 {
453 uint8_t bytes_to_shift = bit_to_read_left - bytes_used;
454 uint64_t counter_part = byte_read >> bytes_to_shift;
455 store = store | counter_part;
456 ibf->count[ibf_counter_ctr + start].count_val = store;
457 byte_read = byte_read & ((1 << bytes_to_shift) - 1);
458 bit_to_read_left -= bytes_used;
459 ibf_counter_ctr++;
460 store = 0;
461 store_bit_ctr = 0;
462 }
463 }
464 else
465 {
466 store_bit_ctr += bit_to_read_left;
467 if (0 == store)
468 {
469 store = byte_read;
470 }
471 else
472 {
473 store = store << bit_to_read_left;
474 store = store | byte_read;
475 }
476 break;
477 }
478 }
479 }
480}

References InvertibleBloomFilter::count, IBF_Count::count_val, and start.

Referenced by ibf_read_slice().

Here is the caller graph for this function:

◆ ibf_read_slice()

void ibf_read_slice ( const void *  buf,
uint32_t  start,
uint64_t  count,
struct InvertibleBloomFilter ibf,
uint8_t  counter_max_length 
)

Read buckets from a buffer into an ibf.

Parameters
bufpointer to the buffer to read from
startwhich bucket to start at
counthow many buckets to read
ibfthe ibf to read from
maxbit length of a counter for unpacking

Definition at line 493 of file ibf.c.

498{
499 struct IBF_Key *key_src;
500 struct IBF_KeyHash *key_hash_src;
501 struct IBF_Count *count_src;
502
503 GNUNET_assert (count > 0);
504 GNUNET_assert (start + count <= ibf->size);
505
506 /* copy keys */
507 key_src = (struct IBF_Key *) buf;
509 key_src,
510 count * sizeof *key_src);
511 key_src += count;
512 /* copy key hashes */
513 key_hash_src = (struct IBF_KeyHash *) key_src;
515 key_hash_src,
516 count * sizeof *key_hash_src);
517 key_hash_src += count;
518
519 /* copy and unpack counts */
520 count_src = (struct IBF_Count *) key_hash_src;
521 unpack_counter (ibf,start,count,(uint8_t *) count_src,counter_max_length);
522}

References GNUNET_assert, GNUNET_memcpy, InvertibleBloomFilter::key_hash_sum, InvertibleBloomFilter::key_sum, size, start, and unpack_counter().

Here is the call graph for this function:

◆ ibf_subtract()

void ibf_subtract ( struct InvertibleBloomFilter ibf1,
const struct InvertibleBloomFilter ibf2 
)

Subtract ibf2 from ibf1, storing the result in ibf1.

The two IBF's must have the same parameters size and hash_num.

Parameters
ibf1IBF that is subtracted from
ibf2IBF that will be subtracted from ibf1

Definition at line 533 of file ibf.c.

535{
536 GNUNET_assert (ibf1->size == ibf2->size);
537 GNUNET_assert (ibf1->hash_num == ibf2->hash_num);
538
539 for (uint32_t i = 0; i < ibf1->size; i++)
540 {
541 ibf1->count[i].count_val -= ibf2->count[i].count_val;
543 ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val;
544 }
545}

References InvertibleBloomFilter::count, IBF_Count::count_val, GNUNET_assert, InvertibleBloomFilter::hash_num, InvertibleBloomFilter::key_hash_sum, IBF_KeyHash::key_hash_val, InvertibleBloomFilter::key_sum, IBF_Key::key_val, and InvertibleBloomFilter::size.

◆ ibf_dup()

struct InvertibleBloomFilter * ibf_dup ( const struct InvertibleBloomFilter ibf)

Create a copy of an IBF, the copy has to be destroyed properly.

Parameters
ibfthe IBF to copy

Definition at line 554 of file ibf.c.

555{
556 struct InvertibleBloomFilter *copy;
557
558 copy = GNUNET_malloc (sizeof *copy);
559 copy->hash_num = ibf->hash_num;
560 copy->size = ibf->size;
562 ibf->size * sizeof(struct IBF_KeyHash));
563 copy->key_sum = GNUNET_memdup (ibf->key_sum,
564 ibf->size * sizeof(struct IBF_Key));
565 copy->count = GNUNET_memdup (ibf->count,
566 ibf->size * sizeof(struct IBF_Count));
567 return copy;
568}

References InvertibleBloomFilter::count, GNUNET_malloc, GNUNET_memdup, InvertibleBloomFilter::hash_num, InvertibleBloomFilter::key_hash_sum, InvertibleBloomFilter::key_sum, and InvertibleBloomFilter::size.

◆ ibf_destroy()

void ibf_destroy ( struct InvertibleBloomFilter ibf)

Destroy all resources associated with the invertible bloom filter.

No more ibf_*-functions may be called on ibf after calling destroy.

Parameters
ibfthe intertible bloom filter to destroy

Definition at line 578 of file ibf.c.

579{
580 GNUNET_free (ibf->key_sum);
582 GNUNET_free (ibf->count);
583 GNUNET_free (ibf);
584}

References InvertibleBloomFilter::count, GNUNET_free, InvertibleBloomFilter::key_hash_sum, and InvertibleBloomFilter::key_sum.