aboutsummaryrefslogtreecommitdiff
path: root/src/block/block.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-02-20 17:19:47 +0100
committerChristian Grothoff <christian@grothoff.org>2017-02-20 17:19:47 +0100
commitf6f7fbbe98c110867febbcca647da8308be123c7 (patch)
treeaf69447cf4f08c417197685855c097c132aea8a1 /src/block/block.c
parenta3882b58f1c5976677aa65b0af8a48e8e946b06e (diff)
downloadgnunet-f6f7fbbe98c110867febbcca647da8308be123c7.tar.gz
gnunet-f6f7fbbe98c110867febbcca647da8308be123c7.zip
completed big block refactoring in preparation for SET-BLOCK integration
Diffstat (limited to 'src/block/block.c')
-rw-r--r--src/block/block.c145
1 files changed, 77 insertions, 68 deletions
diff --git a/src/block/block.c b/src/block/block.c
index d4f5462dd..b7a19ae90 100644
--- a/src/block/block.c
+++ b/src/block/block.c
@@ -162,6 +162,7 @@ GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
162 * Serialize state of a block group. 162 * Serialize state of a block group.
163 * 163 *
164 * @param bg group to serialize 164 * @param bg group to serialize
165 * @param[out] nonce set to the nonce of the @a bg
165 * @param[out] raw_data set to the serialized state 166 * @param[out] raw_data set to the serialized state
166 * @param[out] raw_data_size set to the number of bytes in @a raw_data 167 * @param[out] raw_data_size set to the number of bytes in @a raw_data
167 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not 168 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
@@ -169,9 +170,11 @@ GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
169 */ 170 */
170int 171int
171GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg, 172GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
173 uint32_t *nonce,
172 void **raw_data, 174 void **raw_data,
173 size_t *raw_data_size) 175 size_t *raw_data_size)
174{ 176{
177 *nonce = 0;
175 *raw_data = NULL; 178 *raw_data = NULL;
176 *raw_data_size = 0; 179 *raw_data_size = 0;
177 if (NULL == bg) 180 if (NULL == bg)
@@ -179,6 +182,7 @@ GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
179 if (NULL == bg->serialize_cb) 182 if (NULL == bg->serialize_cb)
180 return GNUNET_NO; 183 return GNUNET_NO;
181 return bg->serialize_cb (bg, 184 return bg->serialize_cb (bg,
185 nonce,
182 raw_data, 186 raw_data,
183 raw_data_size); 187 raw_data_size);
184} 188}
@@ -199,6 +203,41 @@ GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg)
199 203
200 204
201/** 205/**
206 * Try merging two block groups. Afterwards, @a bg1 should remain
207 * valid and contain the rules from both @a bg1 and @bg2, and
208 * @a bg2 should be destroyed (as part of this call). The latter
209 * should happen even if merging is not supported.
210 *
211 * @param[in,out] bg1 first group to merge, is updated
212 * @param bg2 second group to merge, is destroyed
213 * @return #GNUNET_OK on success,
214 * #GNUNET_NO if merge failed due to different nonce
215 * #GNUNET_SYSERR if merging is not supported
216 */
217int
218GNUNET_BLOCK_group_merge (struct GNUNET_BLOCK_Group *bg1,
219 struct GNUNET_BLOCK_Group *bg2)
220{
221 int ret;
222
223 if (NULL == bg2)
224 return GNUNET_OK;
225 if (NULL == bg1)
226 {
227 bg2->destroy_cb (bg2);
228 return GNUNET_OK;
229 }
230 if (NULL == bg1->merge_cb)
231 return GNUNET_SYSERR;
232 GNUNET_assert (bg1->merge_cb == bg1->merge_cb);
233 ret = bg1->merge_cb (bg1,
234 bg2);
235 bg2->destroy_cb (bg2);
236 return ret;
237}
238
239
240/**
202 * Find a plugin for the given type. 241 * Find a plugin for the given type.
203 * 242 *
204 * @param ctx context to search 243 * @param ctx context to search
@@ -244,19 +283,26 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
244 enum GNUNET_BLOCK_Type type, 283 enum GNUNET_BLOCK_Type type,
245 uint32_t nonce, 284 uint32_t nonce,
246 const void *raw_data, 285 const void *raw_data,
247 size_t raw_data_size) 286 size_t raw_data_size,
287 ...)
248{ 288{
249 struct GNUNET_BLOCK_PluginFunctions *plugin; 289 struct GNUNET_BLOCK_PluginFunctions *plugin;
290 struct GNUNET_BLOCK_Group *bg;
291 va_list ap;
250 292
251 plugin = find_plugin (ctx, 293 plugin = find_plugin (ctx,
252 type); 294 type);
253 if (NULL == plugin->create_group) 295 if (NULL == plugin->create_group)
254 return NULL; 296 return NULL;
255 return plugin->create_group (plugin->cls, 297 va_start (ap, raw_data_size);
256 type, 298 bg = plugin->create_group (plugin->cls,
257 nonce, 299 type,
258 raw_data, 300 nonce,
259 raw_data_size); 301 raw_data,
302 raw_data_size,
303 ap);
304 va_end (ap);
305 return bg;
260} 306}
261 307
262 308
@@ -269,10 +315,9 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
269 * 315 *
270 * @param ctx block contxt 316 * @param ctx block contxt
271 * @param type block type 317 * @param type block type
318 * @param block block group to use
272 * @param eo control flags 319 * @param eo control flags
273 * @param query original query (hash) 320 * @param query original query (hash)
274 * @param bf pointer to bloom filter associated with query; possibly updated (!)
275 * @param bf_mutator mutation value for @a bf
276 * @param xquery extended query data (can be NULL, depending on type) 321 * @param xquery extended query data (can be NULL, depending on type)
277 * @param xquery_size number of bytes in @a xquery 322 * @param xquery_size number of bytes in @a xquery
278 * @param reply_block response to validate 323 * @param reply_block response to validate
@@ -282,25 +327,24 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
282enum GNUNET_BLOCK_EvaluationResult 327enum GNUNET_BLOCK_EvaluationResult
283GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx, 328GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
284 enum GNUNET_BLOCK_Type type, 329 enum GNUNET_BLOCK_Type type,
330 struct GNUNET_BLOCK_Group *group,
285 enum GNUNET_BLOCK_EvaluationOptions eo, 331 enum GNUNET_BLOCK_EvaluationOptions eo,
286 const struct GNUNET_HashCode *query, 332 const struct GNUNET_HashCode *query,
287 struct GNUNET_CONTAINER_BloomFilter **bf,
288 int32_t bf_mutator,
289 const void *xquery, 333 const void *xquery,
290 size_t xquery_size, 334 size_t xquery_size,
291 const void *reply_block, 335 const void *reply_block,
292 size_t reply_block_size) 336 size_t reply_block_size)
293{ 337{
294 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, type); 338 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
339 type);
295 340
296 if (plugin == NULL) 341 if (NULL == plugin)
297 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; 342 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
298 return plugin->evaluate (plugin->cls, 343 return plugin->evaluate (plugin->cls,
299 type, 344 type,
345 group,
300 eo, 346 eo,
301 query, 347 query,
302 bf,
303 bf_mutator,
304 xquery, 348 xquery,
305 xquery_size, 349 xquery_size,
306 reply_block, 350 reply_block,
@@ -326,7 +370,8 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
326 size_t block_size, 370 size_t block_size,
327 struct GNUNET_HashCode *key) 371 struct GNUNET_HashCode *key)
328{ 372{
329 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, type); 373 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
374 type);
330 375
331 if (plugin == NULL) 376 if (plugin == NULL)
332 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; 377 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
@@ -335,65 +380,29 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
335 380
336 381
337/** 382/**
338 * How many bytes should a bloomfilter be if we have already seen 383 * Update block group to filter out the given results. Note that the
339 * entry_count responses? Note that #GNUNET_CONSTANTS_BLOOMFILTER_K 384 * use of a hash for seen results implies that the caller magically
340 * gives us the number of bits set per entry. Furthermore, we should 385 * knows how the specific block engine hashes for filtering
341 * not re-size the filter too often (to keep it cheap). 386 * duplicates, so this API may not always apply.
342 *
343 * Since other peers will also add entries but not resize the filter,
344 * we should generally pick a slightly larger size than what the
345 * strict math would suggest.
346 *
347 * @param entry_count expected number of entries in the Bloom filter
348 * @return must be a power of two and smaller or equal to 2^15.
349 */
350static size_t
351compute_bloomfilter_size (unsigned int entry_count)
352{
353 size_t size;
354 unsigned int ideal = (entry_count * GNUNET_CONSTANTS_BLOOMFILTER_K) / 4;
355 uint16_t max = 1 << 15;
356
357 if (entry_count > max)
358 return max;
359 size = 8;
360 while ((size < max) && (size < ideal))
361 size *= 2;
362 if (size > max)
363 return max;
364 return size;
365}
366
367
368/**
369 * Construct a bloom filter that would filter out the given
370 * results.
371 * 387 *
372 * @param bf_mutator mutation value to use 388 * @param bf_mutator mutation value to use
373 * @param seen_results results already seen 389 * @param seen_results results already seen
374 * @param seen_results_count number of entries in @a seen_results 390 * @param seen_results_count number of entries in @a seen_results
375 * @return NULL if seen_results_count is 0, otherwise a BF 391 * @return #GNUNET_SYSERR if not supported, #GNUNET_OK on success
376 * that would match the given results.
377 */ 392 */
378struct GNUNET_CONTAINER_BloomFilter * 393int
379GNUNET_BLOCK_construct_bloomfilter (int32_t bf_mutator, 394GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg,
380 const struct GNUNET_HashCode *seen_results, 395 const struct GNUNET_HashCode *seen_results,
381 unsigned int seen_results_count) 396 unsigned int seen_results_count)
382{ 397{
383 struct GNUNET_CONTAINER_BloomFilter *bf; 398 if (NULL == bg)
384 struct GNUNET_HashCode mhash; 399 return GNUNET_OK;
385 unsigned int i; 400 if (NULL == bg->mark_seen_cb)
386 size_t nsize; 401 return GNUNET_SYSERR;
387 402 bg->mark_seen_cb (bg,
388 nsize = compute_bloomfilter_size (seen_results_count); 403 seen_results,
389 bf = GNUNET_CONTAINER_bloomfilter_init (NULL, nsize, 404 seen_results_count);
390 GNUNET_CONSTANTS_BLOOMFILTER_K); 405 return GNUNET_OK;
391 for (i = 0; i < seen_results_count; i++)
392 {
393 GNUNET_BLOCK_mingle_hash (&seen_results[i], bf_mutator, &mhash);
394 GNUNET_CONTAINER_bloomfilter_add (bf, &mhash);
395 }
396 return bf;
397} 406}
398 407
399 408