summaryrefslogtreecommitdiff
path: root/src/set/ibf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/set/ibf.c')
-rw-r--r--src/set/ibf.c280
1 files changed, 145 insertions, 135 deletions
diff --git a/src/set/ibf.c b/src/set/ibf.c
index a573ef6b4..7c7adaa3c 100644
--- a/src/set/ibf.c
+++ b/src/set/ibf.c
@@ -30,7 +30,8 @@
30 * Compute the key's hash from the key. 30 * Compute the key's hash from the key.
31 * Redefine to use a different hash function. 31 * Redefine to use a different hash function.
32 */ 32 */
33#define IBF_KEY_HASH_VAL(k) (GNUNET_CRYPTO_crc32_n(&(k), sizeof(struct IBF_KeyHash))) 33#define IBF_KEY_HASH_VAL(k) (GNUNET_CRYPTO_crc32_n (&(k), sizeof(struct \
34 IBF_KeyHash)))
34 35
35/** 36/**
36 * Create a key from a hashcode. 37 * Create a key from a hashcode.
@@ -39,9 +40,9 @@
39 * @return a key 40 * @return a key
40 */ 41 */
41struct IBF_Key 42struct IBF_Key
42ibf_key_from_hashcode(const struct GNUNET_HashCode *hash) 43ibf_key_from_hashcode (const struct GNUNET_HashCode *hash)
43{ 44{
44 return *(struct IBF_Key *)hash; 45 return *(struct IBF_Key *) hash;
45} 46}
46 47
47/** 48/**
@@ -52,14 +53,15 @@ ibf_key_from_hashcode(const struct GNUNET_HashCode *hash)
52 * @param dst hashcode to store the result in 53 * @param dst hashcode to store the result in
53 */ 54 */
54void 55void
55ibf_hashcode_from_key(struct IBF_Key key, 56ibf_hashcode_from_key (struct IBF_Key key,
56 struct GNUNET_HashCode *dst) 57 struct GNUNET_HashCode *dst)
57{ 58{
58 struct IBF_Key *p; 59 struct IBF_Key *p;
59 unsigned int i; 60 unsigned int i;
60 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode) / sizeof(struct IBF_Key); 61 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode)
62 / sizeof(struct IBF_Key);
61 63
62 p = (struct IBF_Key *)dst; 64 p = (struct IBF_Key *) dst;
63 for (i = 0; i < keys_per_hashcode; i++) 65 for (i = 0; i < keys_per_hashcode; i++)
64 *p++ = key; 66 *p++ = key;
65} 67}
@@ -73,34 +75,34 @@ ibf_hashcode_from_key(struct IBF_Key key,
73 * @return the newly created invertible bloom filter, NULL on error 75 * @return the newly created invertible bloom filter, NULL on error
74 */ 76 */
75struct InvertibleBloomFilter * 77struct InvertibleBloomFilter *
76ibf_create(uint32_t size, uint8_t hash_num) 78ibf_create (uint32_t size, uint8_t hash_num)
77{ 79{
78 struct InvertibleBloomFilter *ibf; 80 struct InvertibleBloomFilter *ibf;
79 81
80 GNUNET_assert(0 != size); 82 GNUNET_assert (0 != size);
81 83
82 ibf = GNUNET_new(struct InvertibleBloomFilter); 84 ibf = GNUNET_new (struct InvertibleBloomFilter);
83 ibf->count = GNUNET_malloc_large(size * sizeof(uint8_t)); 85 ibf->count = GNUNET_malloc_large (size * sizeof(uint8_t));
84 if (NULL == ibf->count) 86 if (NULL == ibf->count)
85 { 87 {
86 GNUNET_free(ibf); 88 GNUNET_free (ibf);
87 return NULL; 89 return NULL;
88 } 90 }
89 ibf->key_sum = GNUNET_malloc_large(size * sizeof(struct IBF_Key)); 91 ibf->key_sum = GNUNET_malloc_large (size * sizeof(struct IBF_Key));
90 if (NULL == ibf->key_sum) 92 if (NULL == ibf->key_sum)
91 { 93 {
92 GNUNET_free(ibf->count); 94 GNUNET_free (ibf->count);
93 GNUNET_free(ibf); 95 GNUNET_free (ibf);
94 return NULL; 96 return NULL;
95 } 97 }
96 ibf->key_hash_sum = GNUNET_malloc_large(size * sizeof(struct IBF_KeyHash)); 98 ibf->key_hash_sum = GNUNET_malloc_large (size * sizeof(struct IBF_KeyHash));
97 if (NULL == ibf->key_hash_sum) 99 if (NULL == ibf->key_hash_sum)
98 { 100 {
99 GNUNET_free(ibf->key_sum); 101 GNUNET_free (ibf->key_sum);
100 GNUNET_free(ibf->count); 102 GNUNET_free (ibf->count);
101 GNUNET_free(ibf); 103 GNUNET_free (ibf);
102 return NULL; 104 return NULL;
103 } 105 }
104 ibf->size = size; 106 ibf->size = size;
105 ibf->hash_num = hash_num; 107 ibf->hash_num = hash_num;
106 108
@@ -112,45 +114,45 @@ ibf_create(uint32_t size, uint8_t hash_num)
112 * Store unique bucket indices for the specified key in dst. 114 * Store unique bucket indices for the specified key in dst.
113 */ 115 */
114static void 116static void
115ibf_get_indices(const struct InvertibleBloomFilter *ibf, 117ibf_get_indices (const struct InvertibleBloomFilter *ibf,
116 struct IBF_Key key, 118 struct IBF_Key key,
117 int *dst) 119 int *dst)
118{ 120{
119 uint32_t filled; 121 uint32_t filled;
120 uint32_t i; 122 uint32_t i;
121 uint32_t bucket; 123 uint32_t bucket;
122 124
123 bucket = GNUNET_CRYPTO_crc32_n(&key, sizeof key); 125 bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key);
124 for (i = 0, filled = 0; filled < ibf->hash_num; i++) 126 for (i = 0, filled = 0; filled < ibf->hash_num; i++)
125 { 127 {
126 unsigned int j; 128 unsigned int j;
127 uint64_t x; 129 uint64_t x;
128 for (j = 0; j < filled; j++) 130 for (j = 0; j < filled; j++)
129 if (dst[j] == bucket) 131 if (dst[j] == bucket)
130 goto try_next; 132 goto try_next;
131 dst[filled++] = bucket % ibf->size; 133 dst[filled++] = bucket % ibf->size;
132try_next:; 134try_next:;
133 x = ((uint64_t)bucket << 32) | i; 135 x = ((uint64_t) bucket << 32) | i;
134 bucket = GNUNET_CRYPTO_crc32_n(&x, sizeof x); 136 bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x);
135 } 137 }
136} 138}
137 139
138 140
139static void 141static void
140ibf_insert_into(struct InvertibleBloomFilter *ibf, 142ibf_insert_into (struct InvertibleBloomFilter *ibf,
141 struct IBF_Key key, 143 struct IBF_Key key,
142 const int *buckets, int side) 144 const int *buckets, int side)
143{ 145{
144 int i; 146 int i;
145 147
146 for (i = 0; i < ibf->hash_num; i++) 148 for (i = 0; i < ibf->hash_num; i++)
147 { 149 {
148 const int bucket = buckets[i]; 150 const int bucket = buckets[i];
149 ibf->count[bucket].count_val += side; 151 ibf->count[bucket].count_val += side;
150 ibf->key_sum[bucket].key_val ^= key.key_val; 152 ibf->key_sum[bucket].key_val ^= key.key_val;
151 ibf->key_hash_sum[bucket].key_hash_val 153 ibf->key_hash_sum[bucket].key_hash_val
152 ^= IBF_KEY_HASH_VAL(key); 154 ^= IBF_KEY_HASH_VAL (key);
153 } 155 }
154} 156}
155 157
156 158
@@ -161,13 +163,13 @@ ibf_insert_into(struct InvertibleBloomFilter *ibf,
161 * @param key the element's hash code 163 * @param key the element's hash code
162 */ 164 */
163void 165void
164ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key) 166ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
165{ 167{
166 int buckets[ibf->hash_num]; 168 int buckets[ibf->hash_num];
167 169
168 GNUNET_assert(ibf->hash_num <= ibf->size); 170 GNUNET_assert (ibf->hash_num <= ibf->size);
169 ibf_get_indices(ibf, key, buckets); 171 ibf_get_indices (ibf, key, buckets);
170 ibf_insert_into(ibf, key, buckets, 1); 172 ibf_insert_into (ibf, key, buckets, 1);
171} 173}
172 174
173 175
@@ -178,13 +180,13 @@ ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
178 * @param key the element's hash code 180 * @param key the element's hash code
179 */ 181 */
180void 182void
181ibf_remove(struct InvertibleBloomFilter *ibf, struct IBF_Key key) 183ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
182{ 184{
183 int buckets[ibf->hash_num]; 185 int buckets[ibf->hash_num];
184 186
185 GNUNET_assert(ibf->hash_num <= ibf->size); 187 GNUNET_assert (ibf->hash_num <= ibf->size);
186 ibf_get_indices(ibf, key, buckets); 188 ibf_get_indices (ibf, key, buckets);
187 ibf_insert_into(ibf, key, buckets, -1); 189 ibf_insert_into (ibf, key, buckets, -1);
188} 190}
189 191
190 192
@@ -192,19 +194,19 @@ ibf_remove(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
192 * Test is the IBF is empty, i.e. all counts, keys and key hashes are zero. 194 * Test is the IBF is empty, i.e. all counts, keys and key hashes are zero.
193 */ 195 */
194static int 196static int
195ibf_is_empty(struct InvertibleBloomFilter *ibf) 197ibf_is_empty (struct InvertibleBloomFilter *ibf)
196{ 198{
197 int i; 199 int i;
198 200
199 for (i = 0; i < ibf->size; i++) 201 for (i = 0; i < ibf->size; i++)
200 { 202 {
201 if (0 != ibf->count[i].count_val) 203 if (0 != ibf->count[i].count_val)
202 return GNUNET_NO; 204 return GNUNET_NO;
203 if (0 != ibf->key_hash_sum[i].key_hash_val) 205 if (0 != ibf->key_hash_sum[i].key_hash_val)
204 return GNUNET_NO; 206 return GNUNET_NO;
205 if (0 != ibf->key_sum[i].key_val) 207 if (0 != ibf->key_sum[i].key_val)
206 return GNUNET_NO; 208 return GNUNET_NO;
207 } 209 }
208 return GNUNET_YES; 210 return GNUNET_YES;
209} 211}
210 212
@@ -222,53 +224,53 @@ ibf_is_empty(struct InvertibleBloomFilter *ibf)
222 * GNUNET_SYSERR if the decoding has failed 224 * GNUNET_SYSERR if the decoding has failed
223 */ 225 */
224int 226int
225ibf_decode(struct InvertibleBloomFilter *ibf, 227ibf_decode (struct InvertibleBloomFilter *ibf,
226 int *ret_side, struct IBF_Key *ret_id) 228 int *ret_side, struct IBF_Key *ret_id)
227{ 229{
228 struct IBF_KeyHash hash; 230 struct IBF_KeyHash hash;
229 int i; 231 int i;
230 int buckets[ibf->hash_num]; 232 int buckets[ibf->hash_num];
231 233
232 GNUNET_assert(NULL != ibf); 234 GNUNET_assert (NULL != ibf);
233 235
234 for (i = 0; i < ibf->size; i++) 236 for (i = 0; i < ibf->size; i++)
235 { 237 {
236 int j; 238 int j;
237 int hit; 239 int hit;
238 240
239 /* we can only decode from pure buckets */ 241 /* we can only decode from pure buckets */
240 if ((1 != ibf->count[i].count_val) && (-1 != ibf->count[i].count_val)) 242 if ((1 != ibf->count[i].count_val) && (-1 != ibf->count[i].count_val))
241 continue; 243 continue;
242 244
243 hash.key_hash_val = IBF_KEY_HASH_VAL(ibf->key_sum[i]); 245 hash.key_hash_val = IBF_KEY_HASH_VAL (ibf->key_sum[i]);
244 246
245 /* test if the hash matches the key */ 247 /* test if the hash matches the key */
246 if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val) 248 if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val)
247 continue; 249 continue;
248 250
249 /* test if key in bucket hits its own location, 251 /* test if key in bucket hits its own location,
250 * if not, the key hash was subject to collision */ 252 * if not, the key hash was subject to collision */
251 hit = GNUNET_NO; 253 hit = GNUNET_NO;
252 ibf_get_indices(ibf, ibf->key_sum[i], buckets); 254 ibf_get_indices (ibf, ibf->key_sum[i], buckets);
253 for (j = 0; j < ibf->hash_num; j++) 255 for (j = 0; j < ibf->hash_num; j++)
254 if (buckets[j] == i) 256 if (buckets[j] == i)
255 hit = GNUNET_YES; 257 hit = GNUNET_YES;
256 258
257 if (GNUNET_NO == hit) 259 if (GNUNET_NO == hit)
258 continue; 260 continue;
259 261
260 if (NULL != ret_side) 262 if (NULL != ret_side)
261 *ret_side = ibf->count[i].count_val; 263 *ret_side = ibf->count[i].count_val;
262 if (NULL != ret_id) 264 if (NULL != ret_id)
263 *ret_id = ibf->key_sum[i]; 265 *ret_id = ibf->key_sum[i];
264 266
265 /* insert on the opposite side, effectively removing the element */ 267 /* insert on the opposite side, effectively removing the element */
266 ibf_insert_into(ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val); 268 ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val);
267 269
268 return GNUNET_YES; 270 return GNUNET_YES;
269 } 271 }
270 272
271 if (GNUNET_YES == ibf_is_empty(ibf)) 273 if (GNUNET_YES == ibf_is_empty (ibf))
272 return GNUNET_NO; 274 return GNUNET_NO;
273 return GNUNET_SYSERR; 275 return GNUNET_SYSERR;
274} 276}
@@ -284,25 +286,27 @@ ibf_decode(struct InvertibleBloomFilter *ibf,
284 * @param buf buffer to write the data to 286 * @param buf buffer to write the data to
285 */ 287 */
286void 288void
287ibf_write_slice(const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf) 289ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start,
290 uint32_t count, void *buf)
288{ 291{
289 struct IBF_Key *key_dst; 292 struct IBF_Key *key_dst;
290 struct IBF_KeyHash *key_hash_dst; 293 struct IBF_KeyHash *key_hash_dst;
291 struct IBF_Count *count_dst; 294 struct IBF_Count *count_dst;
292 295
293 GNUNET_assert(start + count <= ibf->size); 296 GNUNET_assert (start + count <= ibf->size);
294 297
295 /* copy keys */ 298 /* copy keys */
296 key_dst = (struct IBF_Key *)buf; 299 key_dst = (struct IBF_Key *) buf;
297 GNUNET_memcpy(key_dst, ibf->key_sum + start, count * sizeof *key_dst); 300 GNUNET_memcpy (key_dst, ibf->key_sum + start, count * sizeof *key_dst);
298 key_dst += count; 301 key_dst += count;
299 /* copy key hashes */ 302 /* copy key hashes */
300 key_hash_dst = (struct IBF_KeyHash *)key_dst; 303 key_hash_dst = (struct IBF_KeyHash *) key_dst;
301 GNUNET_memcpy(key_hash_dst, ibf->key_hash_sum + start, count * sizeof *key_hash_dst); 304 GNUNET_memcpy (key_hash_dst, ibf->key_hash_sum + start, count
305 * sizeof *key_hash_dst);
302 key_hash_dst += count; 306 key_hash_dst += count;
303 /* copy counts */ 307 /* copy counts */
304 count_dst = (struct IBF_Count *)key_hash_dst; 308 count_dst = (struct IBF_Count *) key_hash_dst;
305 GNUNET_memcpy(count_dst, ibf->count + start, count * sizeof *count_dst); 309 GNUNET_memcpy (count_dst, ibf->count + start, count * sizeof *count_dst);
306} 310}
307 311
308 312
@@ -315,26 +319,28 @@ ibf_write_slice(const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_
315 * @param ibf the ibf to read from 319 * @param ibf the ibf to read from
316 */ 320 */
317void 321void
318ibf_read_slice(const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf) 322ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct
323 InvertibleBloomFilter *ibf)
319{ 324{
320 struct IBF_Key *key_src; 325 struct IBF_Key *key_src;
321 struct IBF_KeyHash *key_hash_src; 326 struct IBF_KeyHash *key_hash_src;
322 struct IBF_Count *count_src; 327 struct IBF_Count *count_src;
323 328
324 GNUNET_assert(count > 0); 329 GNUNET_assert (count > 0);
325 GNUNET_assert(start + count <= ibf->size); 330 GNUNET_assert (start + count <= ibf->size);
326 331
327 /* copy keys */ 332 /* copy keys */
328 key_src = (struct IBF_Key *)buf; 333 key_src = (struct IBF_Key *) buf;
329 GNUNET_memcpy(ibf->key_sum + start, key_src, count * sizeof *key_src); 334 GNUNET_memcpy (ibf->key_sum + start, key_src, count * sizeof *key_src);
330 key_src += count; 335 key_src += count;
331 /* copy key hashes */ 336 /* copy key hashes */
332 key_hash_src = (struct IBF_KeyHash *)key_src; 337 key_hash_src = (struct IBF_KeyHash *) key_src;
333 GNUNET_memcpy(ibf->key_hash_sum + start, key_hash_src, count * sizeof *key_hash_src); 338 GNUNET_memcpy (ibf->key_hash_sum + start, key_hash_src, count
339 * sizeof *key_hash_src);
334 key_hash_src += count; 340 key_hash_src += count;
335 /* copy counts */ 341 /* copy counts */
336 count_src = (struct IBF_Count *)key_hash_src; 342 count_src = (struct IBF_Count *) key_hash_src;
337 GNUNET_memcpy(ibf->count + start, count_src, count * sizeof *count_src); 343 GNUNET_memcpy (ibf->count + start, count_src, count * sizeof *count_src);
338} 344}
339 345
340 346
@@ -346,19 +352,20 @@ ibf_read_slice(const void *buf, uint32_t start, uint32_t count, struct Invertibl
346 * @param ibf2 IBF that will be subtracted from ibf1 352 * @param ibf2 IBF that will be subtracted from ibf1
347 */ 353 */
348void 354void
349ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2) 355ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct
356 InvertibleBloomFilter *ibf2)
350{ 357{
351 int i; 358 int i;
352 359
353 GNUNET_assert(ibf1->size == ibf2->size); 360 GNUNET_assert (ibf1->size == ibf2->size);
354 GNUNET_assert(ibf1->hash_num == ibf2->hash_num); 361 GNUNET_assert (ibf1->hash_num == ibf2->hash_num);
355 362
356 for (i = 0; i < ibf1->size; i++) 363 for (i = 0; i < ibf1->size; i++)
357 { 364 {
358 ibf1->count[i].count_val -= ibf2->count[i].count_val; 365 ibf1->count[i].count_val -= ibf2->count[i].count_val;
359 ibf1->key_hash_sum[i].key_hash_val ^= ibf2->key_hash_sum[i].key_hash_val; 366 ibf1->key_hash_sum[i].key_hash_val ^= ibf2->key_hash_sum[i].key_hash_val;
360 ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val; 367 ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val;
361 } 368 }
362} 369}
363 370
364 371
@@ -368,16 +375,19 @@ ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFil
368 * @param ibf the IBF to copy 375 * @param ibf the IBF to copy
369 */ 376 */
370struct InvertibleBloomFilter * 377struct InvertibleBloomFilter *
371ibf_dup(const struct InvertibleBloomFilter *ibf) 378ibf_dup (const struct InvertibleBloomFilter *ibf)
372{ 379{
373 struct InvertibleBloomFilter *copy; 380 struct InvertibleBloomFilter *copy;
374 381
375 copy = GNUNET_malloc(sizeof *copy); 382 copy = GNUNET_malloc (sizeof *copy);
376 copy->hash_num = ibf->hash_num; 383 copy->hash_num = ibf->hash_num;
377 copy->size = ibf->size; 384 copy->size = ibf->size;
378 copy->key_hash_sum = GNUNET_memdup(ibf->key_hash_sum, ibf->size * sizeof(struct IBF_KeyHash)); 385 copy->key_hash_sum = GNUNET_memdup (ibf->key_hash_sum, ibf->size
379 copy->key_sum = GNUNET_memdup(ibf->key_sum, ibf->size * sizeof(struct IBF_Key)); 386 * sizeof(struct IBF_KeyHash));
380 copy->count = GNUNET_memdup(ibf->count, ibf->size * sizeof(struct IBF_Count)); 387 copy->key_sum = GNUNET_memdup (ibf->key_sum, ibf->size * sizeof(struct
388 IBF_Key));
389 copy->count = GNUNET_memdup (ibf->count, ibf->size * sizeof(struct
390 IBF_Count));
381 return copy; 391 return copy;
382} 392}
383 393
@@ -389,10 +399,10 @@ ibf_dup(const struct InvertibleBloomFilter *ibf)
389 * @param ibf the intertible bloom filter to destroy 399 * @param ibf the intertible bloom filter to destroy
390 */ 400 */
391void 401void
392ibf_destroy(struct InvertibleBloomFilter *ibf) 402ibf_destroy (struct InvertibleBloomFilter *ibf)
393{ 403{
394 GNUNET_free(ibf->key_sum); 404 GNUNET_free (ibf->key_sum);
395 GNUNET_free(ibf->key_hash_sum); 405 GNUNET_free (ibf->key_hash_sum);
396 GNUNET_free(ibf->count); 406 GNUNET_free (ibf->count);
397 GNUNET_free(ibf); 407 GNUNET_free (ibf);
398} 408}