aboutsummaryrefslogtreecommitdiff
path: root/src/setu/gnunet-service-setu_strata_estimator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/setu/gnunet-service-setu_strata_estimator.c')
-rw-r--r--src/setu/gnunet-service-setu_strata_estimator.c362
1 files changed, 268 insertions, 94 deletions
diff --git a/src/setu/gnunet-service-setu_strata_estimator.c b/src/setu/gnunet-service-setu_strata_estimator.c
index 7c9a4deb6..7981cc847 100644
--- a/src/setu/gnunet-service-setu_strata_estimator.c
+++ b/src/setu/gnunet-service-setu_strata_estimator.c
@@ -22,6 +22,7 @@
22 * @brief invertible bloom filter 22 * @brief invertible bloom filter
23 * @author Florian Dold 23 * @author Florian Dold
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * @author Elias Summermatter
25 */ 26 */
26#include "platform.h" 27#include "platform.h"
27#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
@@ -30,6 +31,82 @@
30 31
31 32
32/** 33/**
34 * Should we try compressing the strata estimator? This will
35 * break compatibility with the 0.10.1-network.
36 */
37#define FAIL_10_1_COMPATIBILTIY 1
38
39/**
40 * Number of strata estimators in memory NOT transmitted
41 */
42
43#define MULTI_SE_BASE_COUNT 8
44
45/**
46 * The avg size of 1 se
47 * Based on the bsc thesis of Elias Summermatter (2021)
48 */
49
50#define AVG_BYTE_SIZE_SE 4221
51
52/**
53 * Calculates the optimal number of strata Estimators to send
54 * @param avg_element_size
55 * @param element_count
56 * @return
57 */
58uint8_t
59determine_strata_count (uint64_t avg_element_size, uint64_t element_count)
60{
61 uint64_t base_size = avg_element_size * element_count;
62 /* >67kb total size of elements in set */
63 if (base_size < AVG_BYTE_SIZE_SE * 16)
64 return 1;
65 /* >270kb total size of elements in set */
66 if (base_size < AVG_BYTE_SIZE_SE * 64)
67 return 2;
68 /* >1mb total size of elements in set */
69 if (base_size < AVG_BYTE_SIZE_SE * 256)
70 return 4;
71 return 8;
72}
73
74
75/**
76 * Modify an IBF key @a k_in based on the @a salt, returning a
77 * salted key in @a k_out.
78 */
79static void
80salt_key (const struct IBF_Key *k_in,
81 uint32_t salt,
82 struct IBF_Key *k_out)
83{
84 int s = (salt * 7) % 64;
85 uint64_t x = k_in->key_val;
86
87 /* rotate ibf key */
88 x = (x >> s) | (x << (64 - s));
89 k_out->key_val = x;
90}
91
92
93/**
94 * Reverse modification done in the salt_key function
95 */
96static void
97unsalt_key (const struct IBF_Key *k_in,
98 uint32_t salt,
99 struct IBF_Key *k_out)
100{
101 int s = (salt * 7) % 64;
102 uint64_t x = k_in->key_val;
103
104 x = (x << s) | (x >> (64 - s));
105 k_out->key_val = x;
106}
107
108
109/**
33 * Write the given strata estimator to the buffer. 110 * Write the given strata estimator to the buffer.
34 * 111 *
35 * @param se strata estimator to serialize 112 * @param se strata estimator to serialize
@@ -37,21 +114,33 @@
37 * @return number of bytes written to @a buf 114 * @return number of bytes written to @a buf
38 */ 115 */
39size_t 116size_t
40strata_estimator_write (const struct StrataEstimator *se, 117strata_estimator_write (struct MultiStrataEstimator *se,
118 uint16_t se_ibf_total_size,
119 uint8_t number_se_send,
41 void *buf) 120 void *buf)
42{ 121{
43 char *sbuf = buf; 122 char *sbuf = buf;
123 unsigned int i;
44 size_t osize; 124 size_t osize;
125 uint64_t sbuf_offset = 0;
126 se->size = number_se_send;
45 127
46 GNUNET_assert (NULL != se); 128 GNUNET_assert (NULL != se);
47 for (unsigned int i = 0; i < se->strata_count; i++) 129 for (uint8_t strata_ctr = 0; strata_ctr < number_se_send; strata_ctr++)
48 { 130 {
49 ibf_write_slice (se->strata[i], 131 for (i = 0; i < se->stratas[strata_ctr]->strata_count; i++)
50 0, 132 {
51 se->ibf_size, 133 ibf_write_slice (se->stratas[strata_ctr]->strata[i],
52 &sbuf[se->ibf_size * IBF_BUCKET_SIZE * i]); 134 0,
135 se->stratas[strata_ctr]->ibf_size,
136 &sbuf[sbuf_offset],
137 8);
138 sbuf_offset += se->stratas[strata_ctr]->ibf_size * IBF_BUCKET_SIZE;
139 }
53 } 140 }
54 osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count; 141 osize = ((se_ibf_total_size / 8) * number_se_send) * IBF_BUCKET_SIZE
142 * se->stratas[0]->strata_count;
143#if FAIL_10_1_COMPATIBILTIY
55 { 144 {
56 char *cbuf; 145 char *cbuf;
57 size_t nsize; 146 size_t nsize;
@@ -62,13 +151,12 @@ strata_estimator_write (const struct StrataEstimator *se,
62 &cbuf, 151 &cbuf,
63 &nsize)) 152 &nsize))
64 { 153 {
65 GNUNET_memcpy (buf, 154 GNUNET_memcpy (buf, cbuf, nsize);
66 cbuf,
67 nsize);
68 osize = nsize; 155 osize = nsize;
69 GNUNET_free (cbuf); 156 GNUNET_free (cbuf);
70 } 157 }
71 } 158 }
159#endif
72 return osize; 160 return osize;
73} 161}
74 162
@@ -87,15 +175,19 @@ int
87strata_estimator_read (const void *buf, 175strata_estimator_read (const void *buf,
88 size_t buf_len, 176 size_t buf_len,
89 int is_compressed, 177 int is_compressed,
90 struct StrataEstimator *se) 178 uint8_t number_se_received,
179 uint16_t se_ibf_total_size,
180 struct MultiStrataEstimator *se)
91{ 181{
182 unsigned int i;
92 size_t osize; 183 size_t osize;
93 char *dbuf; 184 char *dbuf;
94 185
95 dbuf = NULL; 186 dbuf = NULL;
96 if (GNUNET_YES == is_compressed) 187 if (GNUNET_YES == is_compressed)
97 { 188 {
98 osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count; 189 osize = ((se_ibf_total_size / 8) * number_se_received) * IBF_BUCKET_SIZE
190 * se->stratas[0]->strata_count;
99 dbuf = GNUNET_decompress (buf, 191 dbuf = GNUNET_decompress (buf,
100 buf_len, 192 buf_len,
101 osize); 193 osize);
@@ -108,18 +200,25 @@ strata_estimator_read (const void *buf,
108 buf_len = osize; 200 buf_len = osize;
109 } 201 }
110 202
111 if (buf_len != se->strata_count * se->ibf_size * IBF_BUCKET_SIZE) 203 if (buf_len != se->stratas[0]->strata_count * ((se_ibf_total_size / 8)
204 * number_se_received)
205 * IBF_BUCKET_SIZE)
112 { 206 {
113 GNUNET_break (0); /* very odd error */ 207 GNUNET_break (0); /* very odd error */
114 GNUNET_free (dbuf); 208 GNUNET_free (dbuf);
115 return GNUNET_SYSERR; 209 return GNUNET_SYSERR;
116 } 210 }
117 211
118 for (unsigned int i = 0; i < se->strata_count; i++) 212 for (uint8_t strata_ctr = 0; strata_ctr < number_se_received; strata_ctr++)
119 { 213 {
120 ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]); 214 for (i = 0; i < se->stratas[strata_ctr]->strata_count; i++)
121 buf += se->ibf_size * IBF_BUCKET_SIZE; 215 {
216 ibf_read_slice (buf, 0, se->stratas[strata_ctr]->ibf_size,
217 se->stratas[strata_ctr]->strata[i], 8);
218 buf += se->stratas[strata_ctr]->ibf_size * IBF_BUCKET_SIZE;
219 }
122 } 220 }
221 se->size = number_se_received;
123 GNUNET_free (dbuf); 222 GNUNET_free (dbuf);
124 return GNUNET_OK; 223 return GNUNET_OK;
125} 224}
@@ -132,38 +231,61 @@ strata_estimator_read (const void *buf,
132 * @param key key to add 231 * @param key key to add
133 */ 232 */
134void 233void
135strata_estimator_insert (struct StrataEstimator *se, 234strata_estimator_insert (struct MultiStrataEstimator *se,
136 struct IBF_Key key) 235 struct IBF_Key key)
137{ 236{
138 uint64_t v;
139 unsigned int i;
140 237
141 v = key.key_val; 238
142 /* count trailing '1'-bits of v */ 239 /* count trailing '1'-bits of v */
143 for (i = 0; v & 1; v >>= 1, i++) 240 for (int strata_ctr = 0; strata_ctr < MULTI_SE_BASE_COUNT; strata_ctr++)
144 /* empty */; 241 {
145 ibf_insert (se->strata[i], key); 242 unsigned int i;
243 uint64_t v;
244
245 struct IBF_Key salted_key;
246 salt_key (&key,
247 strata_ctr * (64 / MULTI_SE_BASE_COUNT),
248 &salted_key);
249 v = salted_key.key_val;
250 for (i = 0; v & 1; v >>= 1, i++)
251 {
252 ibf_insert (se->stratas[strata_ctr]->strata[i], salted_key);
253 }
254 }
255 /* empty */;
256
146} 257}
147 258
148 259
149/** 260/**
150 * Remove a key from the strata estimator. 261 * Remove a key from the strata estimator. (NOT USED)
151 * 262 *
152 * @param se strata estimator to remove the key from 263 * @param se strata estimator to remove the key from
153 * @param key key to remove 264 * @param key key to remove
154 */ 265 */
155void 266void
156strata_estimator_remove (struct StrataEstimator *se, 267strata_estimator_remove (struct MultiStrataEstimator *se,
157 struct IBF_Key key) 268 struct IBF_Key key)
158{ 269{
159 uint64_t v;
160 unsigned int i;
161 270
162 v = key.key_val;
163 /* count trailing '1'-bits of v */ 271 /* count trailing '1'-bits of v */
164 for (i = 0; v & 1; v >>= 1, i++) 272 for (int strata_ctr = 0; strata_ctr < se->size; strata_ctr++)
165 /* empty */; 273 {
166 ibf_remove (se->strata[i], key); 274 uint64_t v;
275 unsigned int i;
276
277 struct IBF_Key unsalted_key;
278 unsalt_key (&key,
279 strata_ctr * (64 / MULTI_SE_BASE_COUNT),
280 &unsalted_key);
281
282 v = unsalted_key.key_val;
283 for (i = 0; v & 1; v >>= 1, i++)
284 {
285 /* empty */;
286 ibf_remove (se->stratas[strata_ctr]->strata[i], unsalted_key);
287 }
288 }
167} 289}
168 290
169 291
@@ -175,29 +297,42 @@ strata_estimator_remove (struct StrataEstimator *se,
175 * @param ibf_hashnum hashnum parameter of each ibf 297 * @param ibf_hashnum hashnum parameter of each ibf
176 * @return a freshly allocated, empty strata estimator, NULL on error 298 * @return a freshly allocated, empty strata estimator, NULL on error
177 */ 299 */
178struct StrataEstimator * 300struct MultiStrataEstimator *
179strata_estimator_create (unsigned int strata_count, 301strata_estimator_create (unsigned int strata_count,
180 uint32_t ibf_size, 302 uint32_t ibf_size,
181 uint8_t ibf_hashnum) 303 uint8_t ibf_hashnum)
182{ 304{
183 struct StrataEstimator *se; 305 struct MultiStrataEstimator *se;
184 306 unsigned int i;
185 se = GNUNET_new (struct StrataEstimator); 307 unsigned int j;
186 se->strata_count = strata_count; 308 se = GNUNET_new (struct MultiStrataEstimator);
187 se->ibf_size = ibf_size; 309
188 se->strata = GNUNET_new_array (strata_count, 310 se->size = MULTI_SE_BASE_COUNT;
189 struct InvertibleBloomFilter *); 311 se->stratas = GNUNET_new_array (MULTI_SE_BASE_COUNT,struct StrataEstimator *);
190 for (unsigned int i = 0; i < strata_count; i++) 312
313 uint8_t ibf_prime_sizes[] = {79,79,79,79,79,79,79,79};
314
315 for (uint8_t strata_ctr = 0; strata_ctr < MULTI_SE_BASE_COUNT; strata_ctr++)
191 { 316 {
192 se->strata[i] = ibf_create (ibf_size, ibf_hashnum); 317 se->stratas[strata_ctr] = GNUNET_new (struct StrataEstimator);
193 if (NULL == se->strata[i]) 318 se->stratas[strata_ctr]->strata_count = strata_count;
319 se->stratas[strata_ctr]->ibf_size = ibf_prime_sizes[strata_ctr];
320 se->stratas[strata_ctr]->strata = GNUNET_new_array (strata_count * 4,
321 struct
322 InvertibleBloomFilter *);
323 for (i = 0; i < strata_count; i++)
194 { 324 {
195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 325 se->stratas[strata_ctr]->strata[i] = ibf_create (
196 "Failed to allocate memory for strata estimator\n"); 326 ibf_prime_sizes[strata_ctr], ibf_hashnum);
197 for (unsigned int j = 0; j < i; j++) 327 if (NULL == se->stratas[strata_ctr]->strata[i])
198 ibf_destroy (se->strata[i]); 328 {
199 GNUNET_free (se); 329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 return NULL; 330 "Failed to allocate memory for strata estimator\n");
331 for (j = 0; j < i; j++)
332 ibf_destroy (se->stratas[strata_ctr]->strata[i]);
333 GNUNET_free (se);
334 return NULL;
335 }
201 } 336 }
202 } 337 }
203 return se; 338 return se;
@@ -213,46 +348,71 @@ strata_estimator_create (unsigned int strata_count,
213 * @param se2 second strata estimator 348 * @param se2 second strata estimator
214 * @return the estimated difference 349 * @return the estimated difference
215 */ 350 */
216unsigned int 351void
217strata_estimator_difference (const struct StrataEstimator *se1, 352strata_estimator_difference (const struct MultiStrataEstimator *se1,
218 const struct StrataEstimator *se2) 353 const struct MultiStrataEstimator *se2)
219{ 354{
220 unsigned int count; 355 int avg_local_diff = 0;
356 int avg_remote_diff = 0;
357 uint8_t number_of_estimators = se1->size;
221 358
222 GNUNET_assert (se1->strata_count == se2->strata_count); 359 for (uint8_t strata_ctr = 0; strata_ctr < number_of_estimators; strata_ctr++)
223 count = 0;
224 for (int i = se1->strata_count - 1; i >= 0; i--)
225 { 360 {
226 struct InvertibleBloomFilter *diff; 361 GNUNET_assert (se1->stratas[strata_ctr]->strata_count ==
227 /* number of keys decoded from the ibf */ 362 se2->stratas[strata_ctr]->strata_count);
228 363
229 /* FIXME: implement this without always allocating new IBFs */ 364
230 diff = ibf_dup (se1->strata[i]); 365 for (int i = se1->stratas[strata_ctr]->strata_count - 1; i >= 0; i--)
231 ibf_subtract (diff,
232 se2->strata[i]);
233 for (int ibf_count = 0; GNUNET_YES; ibf_count++)
234 { 366 {
235 int more; 367 struct InvertibleBloomFilter *diff;
368 /* number of keys decoded from the ibf */
236 369
237 more = ibf_decode (diff, 370 /* FIXME: implement this without always allocating new IBFs */
238 NULL, 371 diff = ibf_dup (se1->stratas[strata_ctr]->strata[i]);
239 NULL); 372 diff->local_decoded_count = 0;
240 if (GNUNET_NO == more) 373 diff->remote_decoded_count = 0;
241 { 374
242 count += ibf_count; 375 ibf_subtract (diff, se2->stratas[strata_ctr]->strata[i]);
243 break; 376
244 } 377 for (int ibf_count = 0; GNUNET_YES; ibf_count++)
245 /* Estimate if decoding fails or would not terminate */
246 if ( (GNUNET_SYSERR == more) ||
247 (ibf_count > diff->size) )
248 { 378 {
249 ibf_destroy (diff); 379 int more;
250 return count * (1 << (i + 1)); 380
381 more = ibf_decode (diff, NULL, NULL);
382 if (GNUNET_NO == more)
383 {
384 se1->stratas[strata_ctr]->strata[0]->local_decoded_count +=
385 diff->local_decoded_count;
386 se1->stratas[strata_ctr]->strata[0]->remote_decoded_count +=
387 diff->remote_decoded_count;
388 break;
389 }
390 /* Estimate if decoding fails or would not terminate */
391 if ((GNUNET_SYSERR == more) || (ibf_count > diff->size))
392 {
393 se1->stratas[strata_ctr]->strata[0]->local_decoded_count =
394 se1->stratas[strata_ctr]->strata[0]->local_decoded_count * (1 << (i
395 +
396 1));
397 se1->stratas[strata_ctr]->strata[0]->remote_decoded_count =
398 se1->stratas[strata_ctr]->strata[0]->remote_decoded_count * (1 << (i
399 +
400 1));
401 ibf_destroy (diff);
402 goto break_all_counting_loops;
403 }
251 } 404 }
405 ibf_destroy (diff);
252 } 406 }
253 ibf_destroy (diff); 407break_all_counting_loops:;
408 avg_local_diff += se1->stratas[strata_ctr]->strata[0]->local_decoded_count;
409 avg_remote_diff +=
410 se1->stratas[strata_ctr]->strata[0]->remote_decoded_count;
254 } 411 }
255 return count; 412 se1->stratas[0]->strata[0]->local_decoded_count = avg_local_diff
413 / number_of_estimators;
414 se1->stratas[0]->strata[0]->remote_decoded_count = avg_remote_diff
415 / number_of_estimators;
256} 416}
257 417
258 418
@@ -262,18 +422,28 @@ strata_estimator_difference (const struct StrataEstimator *se1,
262 * @param se the strata estimator to copy 422 * @param se the strata estimator to copy
263 * @return the copy 423 * @return the copy
264 */ 424 */
265struct StrataEstimator * 425struct MultiStrataEstimator *
266strata_estimator_dup (struct StrataEstimator *se) 426strata_estimator_dup (struct MultiStrataEstimator *se)
267{ 427{
268 struct StrataEstimator *c; 428 struct MultiStrataEstimator *c;
269 429 unsigned int i;
270 c = GNUNET_new (struct StrataEstimator); 430
271 c->strata_count = se->strata_count; 431 c = GNUNET_new (struct MultiStrataEstimator);
272 c->ibf_size = se->ibf_size; 432 c->stratas = GNUNET_new_array (MULTI_SE_BASE_COUNT,struct StrataEstimator *);
273 c->strata = GNUNET_new_array (se->strata_count, 433 for (uint8_t strata_ctr = 0; strata_ctr < MULTI_SE_BASE_COUNT; strata_ctr++)
274 struct InvertibleBloomFilter *); 434 {
275 for (unsigned int i = 0; i < se->strata_count; i++) 435 c->stratas[strata_ctr] = GNUNET_new (struct StrataEstimator);
276 c->strata[i] = ibf_dup (se->strata[i]); 436 c->stratas[strata_ctr]->strata_count =
437 se->stratas[strata_ctr]->strata_count;
438 c->stratas[strata_ctr]->ibf_size = se->stratas[strata_ctr]->ibf_size;
439 c->stratas[strata_ctr]->strata = GNUNET_new_array (
440 se->stratas[strata_ctr]->strata_count,
441 struct
442 InvertibleBloomFilter *);
443 for (i = 0; i < se->stratas[strata_ctr]->strata_count; i++)
444 c->stratas[strata_ctr]->strata[i] = ibf_dup (
445 se->stratas[strata_ctr]->strata[i]);
446 }
277 return c; 447 return c;
278} 448}
279 449
@@ -284,10 +454,14 @@ strata_estimator_dup (struct StrataEstimator *se)
284 * @param se strata estimator to destroy. 454 * @param se strata estimator to destroy.
285 */ 455 */
286void 456void
287strata_estimator_destroy (struct StrataEstimator *se) 457strata_estimator_destroy (struct MultiStrataEstimator *se)
288{ 458{
289 for (unsigned int i = 0; i < se->strata_count; i++) 459 unsigned int i;
290 ibf_destroy (se->strata[i]); 460 for (uint8_t strata_ctr = 0; strata_ctr < MULTI_SE_BASE_COUNT; strata_ctr++)
291 GNUNET_free (se->strata); 461 {
462 for (i = 0; i < se->stratas[strata_ctr]->strata_count; i++)
463 ibf_destroy (se->stratas[strata_ctr]->strata[i]);
464 GNUNET_free (se->stratas[strata_ctr]->strata);
465 }
292 GNUNET_free (se); 466 GNUNET_free (se);
293} 467}