diff options
Diffstat (limited to 'src/rps/gnunet-service-rps_sampler.c')
-rw-r--r-- | src/rps/gnunet-service-rps_sampler.c | 648 |
1 files changed, 2 insertions, 646 deletions
diff --git a/src/rps/gnunet-service-rps_sampler.c b/src/rps/gnunet-service-rps_sampler.c index 2cd4cb996..9629a29a1 100644 --- a/src/rps/gnunet-service-rps_sampler.c +++ b/src/rps/gnunet-service-rps_sampler.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "gnunet_statistics_service.h" | 26 | #include "gnunet_statistics_service.h" |
27 | #include "rps.h" | 27 | #include "rps.h" |
28 | 28 | ||
29 | #include "rps-sampler_common.h" | ||
29 | #include "gnunet-service-rps_sampler.h" | 30 | #include "gnunet-service-rps_sampler.h" |
30 | #include "gnunet-service-rps_sampler_elem.h" | 31 | #include "gnunet-service-rps_sampler_elem.h" |
31 | 32 | ||
@@ -53,17 +54,6 @@ | |||
53 | // TODO care about invalid input of the caller (size 0 or less...) | 54 | // TODO care about invalid input of the caller (size 0 or less...) |
54 | 55 | ||
55 | /** | 56 | /** |
56 | * Callback that is called from _get_rand_peer() when the PeerID is ready. | ||
57 | * | ||
58 | * @param cls the closure given alongside this function. | ||
59 | * @param id the PeerID that was returned | ||
60 | */ | ||
61 | typedef void | ||
62 | (*RPS_sampler_rand_peer_ready_cont) (void *cls, | ||
63 | const struct GNUNET_PeerIdentity *id); | ||
64 | |||
65 | |||
66 | /** | ||
67 | * @brief Callback called each time a new peer was put into the sampler | 57 | * @brief Callback called each time a new peer was put into the sampler |
68 | * | 58 | * |
69 | * @param cls A possibly given closure | 59 | * @param cls A possibly given closure |
@@ -101,49 +91,6 @@ struct SamplerNotifyUpdateCTX | |||
101 | 91 | ||
102 | 92 | ||
103 | /** | 93 | /** |
104 | * Closure for #sampler_mod_get_rand_peer() and #sampler_get_rand_peer | ||
105 | */ | ||
106 | struct GetPeerCls | ||
107 | { | ||
108 | /** | ||
109 | * DLL | ||
110 | */ | ||
111 | struct GetPeerCls *next; | ||
112 | struct GetPeerCls *prev; | ||
113 | |||
114 | /** | ||
115 | * The #RPS_SamplerRequestHandle this single request belongs to. | ||
116 | */ | ||
117 | struct RPS_SamplerRequestHandle *req_handle; | ||
118 | |||
119 | /** | ||
120 | * The task for this function. | ||
121 | */ | ||
122 | struct GNUNET_SCHEDULER_Task *get_peer_task; | ||
123 | |||
124 | /** | ||
125 | * @brief Context to the given callback. | ||
126 | */ | ||
127 | struct SamplerNotifyUpdateCTX *notify_ctx; | ||
128 | |||
129 | /** | ||
130 | * The callback | ||
131 | */ | ||
132 | RPS_sampler_rand_peer_ready_cont cont; | ||
133 | |||
134 | /** | ||
135 | * The closure to the callback @e cont | ||
136 | */ | ||
137 | void *cont_cls; | ||
138 | |||
139 | /** | ||
140 | * The address of the id to be stored at | ||
141 | */ | ||
142 | struct GNUNET_PeerIdentity *id; | ||
143 | }; | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Type of function used to differentiate between modified and not modified | 94 | * Type of function used to differentiate between modified and not modified |
148 | * Sampler. | 95 | * Sampler. |
149 | */ | 96 | */ |
@@ -162,61 +109,6 @@ sampler_get_rand_peer (void *cls); | |||
162 | 109 | ||
163 | 110 | ||
164 | /** | 111 | /** |
165 | * Get one random peer out of the sampled peers. | ||
166 | * | ||
167 | * We might want to reinitialise this sampler after giving the | ||
168 | * corrsponding peer to the client. | ||
169 | */ | ||
170 | static void | ||
171 | sampler_mod_get_rand_peer (void *cls); | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Sampler with its own array of SamplerElements | ||
176 | */ | ||
177 | struct RPS_Sampler | ||
178 | { | ||
179 | /** | ||
180 | * Number of sampler elements we hold. | ||
181 | */ | ||
182 | unsigned int sampler_size; | ||
183 | //size_t size; | ||
184 | |||
185 | /** | ||
186 | * All sampler elements in one array. | ||
187 | */ | ||
188 | struct RPS_SamplerElement **sampler_elements; | ||
189 | |||
190 | /** | ||
191 | * Maximum time a round takes | ||
192 | * | ||
193 | * Used in the context of RPS | ||
194 | */ | ||
195 | struct GNUNET_TIME_Relative max_round_interval; | ||
196 | |||
197 | /** | ||
198 | * Stores the function to return peers. Which one it is depends on whether | ||
199 | * the Sampler is the modified one or not. | ||
200 | */ | ||
201 | RPS_get_peers_type get_peers; | ||
202 | |||
203 | /** | ||
204 | * Head and tail for the DLL to store the #RPS_SamplerRequestHandle | ||
205 | */ | ||
206 | struct RPS_SamplerRequestHandle *req_handle_head; | ||
207 | struct RPS_SamplerRequestHandle *req_handle_tail; | ||
208 | |||
209 | struct SamplerNotifyUpdateCTX *notify_ctx_head; | ||
210 | struct SamplerNotifyUpdateCTX *notify_ctx_tail; | ||
211 | #ifdef TO_FILE | ||
212 | /** | ||
213 | * File name to log to | ||
214 | */ | ||
215 | char *file_name; | ||
216 | #endif /* TO_FILE */ | ||
217 | }; | ||
218 | |||
219 | /** | ||
220 | * Closure to _get_n_rand_peers_ready_cb() | 112 | * Closure to _get_n_rand_peers_ready_cb() |
221 | */ | 113 | */ |
222 | struct RPS_SamplerRequestHandle | 114 | struct RPS_SamplerRequestHandle |
@@ -292,189 +184,6 @@ static uint32_t client_get_index; | |||
292 | 184 | ||
293 | 185 | ||
294 | /** | 186 | /** |
295 | * @brief Add a callback that will be called when the next peer is inserted | ||
296 | * into the sampler | ||
297 | * | ||
298 | * @param sampler The sampler on which update it will be called | ||
299 | * @param notify_cb The callback | ||
300 | * @param cls Closure given to the callback | ||
301 | * | ||
302 | * @return The context containing callback and closure | ||
303 | */ | ||
304 | struct SamplerNotifyUpdateCTX * | ||
305 | sampler_notify_on_update (struct RPS_Sampler *sampler, | ||
306 | SamplerNotifyUpdateCB notify_cb, | ||
307 | void *cls) | ||
308 | { | ||
309 | struct SamplerNotifyUpdateCTX *notify_ctx; | ||
310 | |||
311 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
312 | "Inserting new context for notification\n"); | ||
313 | notify_ctx = GNUNET_new (struct SamplerNotifyUpdateCTX); | ||
314 | notify_ctx->notify_cb = notify_cb; | ||
315 | notify_ctx->cls = cls; | ||
316 | GNUNET_CONTAINER_DLL_insert (sampler->notify_ctx_head, | ||
317 | sampler->notify_ctx_tail, | ||
318 | notify_ctx); | ||
319 | return notify_ctx; | ||
320 | } | ||
321 | |||
322 | |||
323 | /** | ||
324 | * Callback to _get_rand_peer() used by _get_n_rand_peers(). | ||
325 | * | ||
326 | * Checks whether all n peers are available. If they are, | ||
327 | * give those back. | ||
328 | */ | ||
329 | static void | ||
330 | check_n_peers_ready (void *cls, | ||
331 | const struct GNUNET_PeerIdentity *id) | ||
332 | { | ||
333 | struct RPS_SamplerRequestHandle *req_handle = cls; | ||
334 | (void) id; | ||
335 | |||
336 | req_handle->cur_num_peers++; | ||
337 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
338 | "Got %" PRIX32 ". of %" PRIX32 " peers\n", | ||
339 | req_handle->cur_num_peers, req_handle->num_peers); | ||
340 | |||
341 | if (req_handle->num_peers == req_handle->cur_num_peers) | ||
342 | { /* All peers are ready -- return those to the client */ | ||
343 | GNUNET_assert (NULL != req_handle->callback); | ||
344 | |||
345 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
346 | "returning %" PRIX32 " peers to the client\n", | ||
347 | req_handle->num_peers); | ||
348 | req_handle->callback (req_handle->ids, req_handle->num_peers, req_handle->cls); | ||
349 | |||
350 | RPS_sampler_request_cancel (req_handle); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | |||
355 | /** | ||
356 | * Get the size of the sampler. | ||
357 | * | ||
358 | * @param sampler the sampler to return the size of. | ||
359 | * @return the size of the sampler | ||
360 | */ | ||
361 | unsigned int | ||
362 | RPS_sampler_get_size (struct RPS_Sampler *sampler) | ||
363 | { | ||
364 | return sampler->sampler_size; | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Grow or shrink the size of the sampler. | ||
370 | * | ||
371 | * @param sampler the sampler to resize. | ||
372 | * @param new_size the new size of the sampler | ||
373 | */ | ||
374 | static void | ||
375 | sampler_resize (struct RPS_Sampler *sampler, unsigned int new_size) | ||
376 | { | ||
377 | unsigned int old_size; | ||
378 | uint32_t i; | ||
379 | |||
380 | // TODO check min and max size | ||
381 | |||
382 | old_size = sampler->sampler_size; | ||
383 | |||
384 | if (old_size > new_size) | ||
385 | { /* Shrinking */ | ||
386 | |||
387 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
388 | "Shrinking sampler %d -> %d\n", | ||
389 | old_size, | ||
390 | new_size); | ||
391 | |||
392 | to_file (sampler->file_name, | ||
393 | "Shrinking sampler %d -> %d", | ||
394 | old_size, | ||
395 | new_size); | ||
396 | |||
397 | for (i = new_size ; i < old_size ; i++) | ||
398 | { | ||
399 | to_file (sampler->file_name, | ||
400 | "-%" PRIu32 ": %s", | ||
401 | i, | ||
402 | sampler->sampler_elements[i]->file_name); | ||
403 | RPS_sampler_elem_destroy (sampler->sampler_elements[i]); | ||
404 | } | ||
405 | |||
406 | GNUNET_array_grow (sampler->sampler_elements, | ||
407 | sampler->sampler_size, | ||
408 | new_size); | ||
409 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
410 | "sampler->sampler_elements now points to %p\n", | ||
411 | sampler->sampler_elements); | ||
412 | |||
413 | } | ||
414 | else if (old_size < new_size) | ||
415 | { /* Growing */ | ||
416 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
417 | "Growing sampler %d -> %d\n", | ||
418 | old_size, | ||
419 | new_size); | ||
420 | |||
421 | to_file (sampler->file_name, | ||
422 | "Growing sampler %d -> %d", | ||
423 | old_size, | ||
424 | new_size); | ||
425 | |||
426 | GNUNET_array_grow (sampler->sampler_elements, | ||
427 | sampler->sampler_size, | ||
428 | new_size); | ||
429 | |||
430 | for (i = old_size ; i < new_size ; i++) | ||
431 | { /* Add new sampler elements */ | ||
432 | sampler->sampler_elements[i] = RPS_sampler_elem_create (); | ||
433 | |||
434 | to_file (sampler->file_name, | ||
435 | "+%" PRIu32 ": %s", | ||
436 | i, | ||
437 | sampler->sampler_elements[i]->file_name); | ||
438 | } | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Size remains the same -- nothing to do\n"); | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | GNUNET_assert (sampler->sampler_size == new_size); | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * Grow or shrink the size of the sampler. | ||
452 | * | ||
453 | * @param sampler the sampler to resize. | ||
454 | * @param new_size the new size of the sampler | ||
455 | */ | ||
456 | void | ||
457 | RPS_sampler_resize (struct RPS_Sampler *sampler, unsigned int new_size) | ||
458 | { | ||
459 | GNUNET_assert (0 < new_size); | ||
460 | sampler_resize (sampler, new_size); | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
465 | * Empty the sampler. | ||
466 | * | ||
467 | * @param sampler the sampler to empty. | ||
468 | * @param new_size the new size of the sampler | ||
469 | */ | ||
470 | static void | ||
471 | sampler_empty (struct RPS_Sampler *sampler) | ||
472 | { | ||
473 | sampler_resize (sampler, 0); | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | ||
478 | * Initialise a tuple of sampler elements. | 187 | * Initialise a tuple of sampler elements. |
479 | * | 188 | * |
480 | * @param init_size the size the sampler is initialised with | 189 | * @param init_size the size the sampler is initialised with |
@@ -514,119 +223,6 @@ RPS_sampler_init (size_t init_size, | |||
514 | } | 223 | } |
515 | 224 | ||
516 | /** | 225 | /** |
517 | * Initialise a modified tuple of sampler elements. | ||
518 | * | ||
519 | * @param init_size the size the sampler is initialised with | ||
520 | * @param max_round_interval maximum time a round takes | ||
521 | * @return a handle to a sampler that consists of sampler elements. | ||
522 | */ | ||
523 | struct RPS_Sampler * | ||
524 | RPS_sampler_mod_init (size_t init_size, | ||
525 | struct GNUNET_TIME_Relative max_round_interval) | ||
526 | { | ||
527 | struct RPS_Sampler *sampler; | ||
528 | |||
529 | sampler = RPS_sampler_init (init_size, max_round_interval); | ||
530 | sampler->get_peers = sampler_mod_get_rand_peer; | ||
531 | |||
532 | #ifdef TO_FILE | ||
533 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
534 | "Initialised modified sampler %s\n", | ||
535 | sampler->file_name); | ||
536 | to_file (sampler->file_name, | ||
537 | "This is a modified sampler"); | ||
538 | #endif /* TO_FILE */ | ||
539 | |||
540 | return sampler; | ||
541 | } | ||
542 | |||
543 | |||
544 | /** | ||
545 | * @brief Notify about update of the sampler. | ||
546 | * | ||
547 | * Call the callbacks that are waiting for notification on updates to the | ||
548 | * sampler. | ||
549 | * | ||
550 | * @param sampler The sampler the updates are waiting for | ||
551 | */ | ||
552 | static void | ||
553 | notify_update (struct RPS_Sampler *sampler) | ||
554 | { | ||
555 | struct SamplerNotifyUpdateCTX *tmp_notify_head; | ||
556 | struct SamplerNotifyUpdateCTX *tmp_notify_tail; | ||
557 | |||
558 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
559 | "Calling callbacks waiting for update notification.\n"); | ||
560 | tmp_notify_head = sampler->notify_ctx_head; | ||
561 | tmp_notify_tail = sampler->notify_ctx_tail; | ||
562 | sampler->notify_ctx_head = NULL; | ||
563 | sampler->notify_ctx_tail = NULL; | ||
564 | for (struct SamplerNotifyUpdateCTX *notify_iter = tmp_notify_head; | ||
565 | NULL != tmp_notify_head; | ||
566 | notify_iter = tmp_notify_head) | ||
567 | { | ||
568 | GNUNET_assert (NULL != notify_iter->notify_cb); | ||
569 | GNUNET_CONTAINER_DLL_remove (tmp_notify_head, | ||
570 | tmp_notify_tail, | ||
571 | notify_iter); | ||
572 | notify_iter->notify_cb (notify_iter->cls); | ||
573 | GNUNET_free (notify_iter); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | |||
578 | /** | ||
579 | * Update every sampler element of this sampler with given peer | ||
580 | * | ||
581 | * @param sampler the sampler to update. | ||
582 | * @param id the PeerID that is put in the sampler | ||
583 | */ | ||
584 | void | ||
585 | RPS_sampler_update (struct RPS_Sampler *sampler, | ||
586 | const struct GNUNET_PeerIdentity *id) | ||
587 | { | ||
588 | to_file (sampler->file_name, | ||
589 | "Got %s", | ||
590 | GNUNET_i2s_full (id)); | ||
591 | |||
592 | for (uint32_t i = 0; i < sampler->sampler_size; i++) | ||
593 | { | ||
594 | RPS_sampler_elem_next (sampler->sampler_elements[i], | ||
595 | id); | ||
596 | } | ||
597 | notify_update (sampler); | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Reinitialise all previously initialised sampler elements with the given value. | ||
603 | * | ||
604 | * Used to get rid of a PeerID. | ||
605 | * | ||
606 | * @param sampler the sampler to reinitialise a sampler element in. | ||
607 | * @param id the id of the sampler elements to update. | ||
608 | */ | ||
609 | void | ||
610 | RPS_sampler_reinitialise_by_value (struct RPS_Sampler *sampler, | ||
611 | const struct GNUNET_PeerIdentity *id) | ||
612 | { | ||
613 | uint32_t i; | ||
614 | |||
615 | for (i = 0; i < sampler->sampler_size; i++) | ||
616 | { | ||
617 | if (0 == GNUNET_CRYPTO_cmp_peer_identity(id, | ||
618 | &(sampler->sampler_elements[i]->peer_id)) ) | ||
619 | { | ||
620 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Reinitialising sampler\n"); | ||
621 | to_file (sampler->sampler_elements[i]->file_name, | ||
622 | "--- non-active"); | ||
623 | RPS_sampler_elem_reinit (sampler->sampler_elements[i]); | ||
624 | } | ||
625 | } | ||
626 | } | ||
627 | |||
628 | |||
629 | /** | ||
630 | * Get one random peer out of the sampled peers. | 226 | * Get one random peer out of the sampled peers. |
631 | * | 227 | * |
632 | * We might want to reinitialise this sampler after giving the | 228 | * We might want to reinitialise this sampler after giving the |
@@ -658,7 +254,7 @@ sampler_get_rand_peer (void *cls) | |||
658 | 254 | ||
659 | gpc->notify_ctx = | 255 | gpc->notify_ctx = |
660 | sampler_notify_on_update (sampler, | 256 | sampler_notify_on_update (sampler, |
661 | &sampler_mod_get_rand_peer, | 257 | &sampler_get_rand_peer, |
662 | gpc); | 258 | gpc); |
663 | return; | 259 | return; |
664 | } | 260 | } |
@@ -673,244 +269,4 @@ sampler_get_rand_peer (void *cls) | |||
673 | } | 269 | } |
674 | 270 | ||
675 | 271 | ||
676 | /** | ||
677 | * Get one random peer out of the sampled peers. | ||
678 | * | ||
679 | * This reinitialises the queried sampler element. | ||
680 | */ | ||
681 | static void | ||
682 | sampler_mod_get_rand_peer (void *cls) | ||
683 | { | ||
684 | struct GetPeerCls *gpc = cls; | ||
685 | struct RPS_SamplerElement *s_elem; | ||
686 | struct GNUNET_TIME_Relative last_request_diff; | ||
687 | struct RPS_Sampler *sampler; | ||
688 | |||
689 | gpc->get_peer_task = NULL; | ||
690 | gpc->notify_ctx = NULL; | ||
691 | sampler = gpc->req_handle->sampler; | ||
692 | |||
693 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Single peer was requested\n"); | ||
694 | |||
695 | /* Cycle the #client_get_index one step further */ | ||
696 | client_get_index = (client_get_index + 1) % sampler->sampler_size; | ||
697 | |||
698 | s_elem = sampler->sampler_elements[client_get_index]; | ||
699 | *gpc->id = s_elem->peer_id; | ||
700 | GNUNET_assert (NULL != s_elem); | ||
701 | |||
702 | if (EMPTY == s_elem->is_empty) | ||
703 | { | ||
704 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
705 | "Sampler_mod element empty, rescheduling.\n"); | ||
706 | GNUNET_assert (NULL == gpc->notify_ctx); | ||
707 | gpc->notify_ctx = | ||
708 | sampler_notify_on_update (sampler, | ||
709 | &sampler_mod_get_rand_peer, | ||
710 | gpc); | ||
711 | return; | ||
712 | } | ||
713 | |||
714 | /* Check whether we may use this sampler to give it back to the client */ | ||
715 | if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != s_elem->last_client_request.abs_value_us) | ||
716 | { | ||
717 | // TODO remove this condition at least for the client sampler | ||
718 | last_request_diff = | ||
719 | GNUNET_TIME_absolute_get_difference (s_elem->last_client_request, | ||
720 | GNUNET_TIME_absolute_get ()); | ||
721 | /* We're not going to give it back now if it was | ||
722 | * already requested by a client this round */ | ||
723 | if (last_request_diff.rel_value_us < sampler->max_round_interval.rel_value_us) | ||
724 | { | ||
725 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
726 | "Last client request on this sampler was less than max round interval ago -- scheduling for later\n"); | ||
727 | ///* How many time remains untile the next round has started? */ | ||
728 | //inv_last_request_diff = | ||
729 | // GNUNET_TIME_absolute_get_difference (last_request_diff, | ||
730 | // sampler->max_round_interval); | ||
731 | // add a little delay | ||
732 | /* Schedule it one round later */ | ||
733 | GNUNET_assert (NULL == gpc->notify_ctx); | ||
734 | gpc->notify_ctx = | ||
735 | sampler_notify_on_update (sampler, | ||
736 | &sampler_mod_get_rand_peer, | ||
737 | gpc); | ||
738 | return; | ||
739 | } | ||
740 | } | ||
741 | if (2 > s_elem->num_peers) | ||
742 | { | ||
743 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
744 | "This s_elem saw less than two peers -- scheduling for later\n"); | ||
745 | GNUNET_assert (NULL == gpc->notify_ctx); | ||
746 | gpc->notify_ctx = | ||
747 | sampler_notify_on_update (sampler, | ||
748 | &sampler_mod_get_rand_peer, | ||
749 | gpc); | ||
750 | return; | ||
751 | } | ||
752 | /* More reasons to wait could be added here */ | ||
753 | |||
754 | // GNUNET_STATISTICS_set (stats, | ||
755 | // "# client sampler element input", | ||
756 | // s_elem->num_peers, | ||
757 | // GNUNET_NO); | ||
758 | // GNUNET_STATISTICS_set (stats, | ||
759 | // "# client sampler element change", | ||
760 | // s_elem->num_change, | ||
761 | // GNUNET_NO); | ||
762 | |||
763 | RPS_sampler_elem_reinit (s_elem); | ||
764 | s_elem->last_client_request = GNUNET_TIME_absolute_get (); | ||
765 | |||
766 | GNUNET_CONTAINER_DLL_remove (gpc->req_handle->gpc_head, | ||
767 | gpc->req_handle->gpc_tail, | ||
768 | gpc); | ||
769 | gpc->cont (gpc->cont_cls, gpc->id); | ||
770 | GNUNET_free (gpc); | ||
771 | } | ||
772 | |||
773 | |||
774 | /** | ||
775 | * Get n random peers out of the sampled peers. | ||
776 | * | ||
777 | * We might want to reinitialise this sampler after giving the | ||
778 | * corrsponding peer to the client. | ||
779 | * Random with or without consumption? | ||
780 | * | ||
781 | * @param sampler the sampler to get peers from. | ||
782 | * @param cb callback that will be called once the ids are ready. | ||
783 | * @param cls closure given to @a cb | ||
784 | * @param for_client #GNUNET_YES if result is used for client, | ||
785 | * #GNUNET_NO if used internally | ||
786 | * @param num_peers the number of peers requested | ||
787 | */ | ||
788 | struct RPS_SamplerRequestHandle * | ||
789 | RPS_sampler_get_n_rand_peers (struct RPS_Sampler *sampler, | ||
790 | uint32_t num_peers, | ||
791 | RPS_sampler_n_rand_peers_ready_cb cb, | ||
792 | void *cls) | ||
793 | { | ||
794 | uint32_t i; | ||
795 | struct RPS_SamplerRequestHandle *req_handle; | ||
796 | struct GetPeerCls *gpc; | ||
797 | |||
798 | GNUNET_assert (0 != sampler->sampler_size); | ||
799 | if (0 == num_peers) | ||
800 | return NULL; | ||
801 | |||
802 | // TODO check if we have too much (distinct) sampled peers | ||
803 | req_handle = GNUNET_new (struct RPS_SamplerRequestHandle); | ||
804 | req_handle->num_peers = num_peers; | ||
805 | req_handle->cur_num_peers = 0; | ||
806 | req_handle->ids = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity); | ||
807 | req_handle->sampler = sampler; | ||
808 | req_handle->callback = cb; | ||
809 | req_handle->cls = cls; | ||
810 | GNUNET_CONTAINER_DLL_insert (sampler->req_handle_head, | ||
811 | sampler->req_handle_tail, | ||
812 | req_handle); | ||
813 | |||
814 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
815 | "Scheduling requests for %" PRIu32 " peers\n", num_peers); | ||
816 | |||
817 | for (i = 0; i < num_peers; i++) | ||
818 | { | ||
819 | gpc = GNUNET_new (struct GetPeerCls); | ||
820 | gpc->req_handle = req_handle; | ||
821 | gpc->cont = check_n_peers_ready; | ||
822 | gpc->cont_cls = req_handle; | ||
823 | gpc->id = &req_handle->ids[i]; | ||
824 | |||
825 | GNUNET_CONTAINER_DLL_insert (req_handle->gpc_head, | ||
826 | req_handle->gpc_tail, | ||
827 | gpc); | ||
828 | // maybe add a little delay | ||
829 | gpc->get_peer_task = GNUNET_SCHEDULER_add_now (sampler->get_peers, | ||
830 | gpc); | ||
831 | } | ||
832 | return req_handle; | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * Cancle a request issued through #RPS_sampler_n_rand_peers_ready_cb. | ||
837 | * | ||
838 | * @param req_handle the handle to the request | ||
839 | */ | ||
840 | void | ||
841 | RPS_sampler_request_cancel (struct RPS_SamplerRequestHandle *req_handle) | ||
842 | { | ||
843 | struct GetPeerCls *i; | ||
844 | |||
845 | while (NULL != (i = req_handle->gpc_head) ) | ||
846 | { | ||
847 | GNUNET_CONTAINER_DLL_remove (req_handle->gpc_head, | ||
848 | req_handle->gpc_tail, | ||
849 | i); | ||
850 | if (NULL != i->get_peer_task) | ||
851 | { | ||
852 | GNUNET_SCHEDULER_cancel (i->get_peer_task); | ||
853 | } | ||
854 | if (NULL != i->notify_ctx) | ||
855 | { | ||
856 | GNUNET_CONTAINER_DLL_remove (req_handle->sampler->notify_ctx_head, | ||
857 | req_handle->sampler->notify_ctx_tail, | ||
858 | i->notify_ctx); | ||
859 | GNUNET_free (i->notify_ctx); | ||
860 | } | ||
861 | GNUNET_free (i); | ||
862 | } | ||
863 | GNUNET_free (req_handle->ids); | ||
864 | GNUNET_CONTAINER_DLL_remove (req_handle->sampler->req_handle_head, | ||
865 | req_handle->sampler->req_handle_tail, | ||
866 | req_handle); | ||
867 | GNUNET_free (req_handle); | ||
868 | } | ||
869 | |||
870 | |||
871 | /** | ||
872 | * Counts how many Samplers currently hold a given PeerID. | ||
873 | * | ||
874 | * @param sampler the sampler to count ids in. | ||
875 | * @param id the PeerID to count. | ||
876 | * | ||
877 | * @return the number of occurrences of id. | ||
878 | */ | ||
879 | uint32_t | ||
880 | RPS_sampler_count_id (struct RPS_Sampler *sampler, | ||
881 | const struct GNUNET_PeerIdentity *id) | ||
882 | { | ||
883 | uint32_t count; | ||
884 | uint32_t i; | ||
885 | |||
886 | count = 0; | ||
887 | for ( i = 0 ; i < sampler->sampler_size ; i++ ) | ||
888 | { | ||
889 | if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&sampler->sampler_elements[i]->peer_id, id) | ||
890 | && EMPTY != sampler->sampler_elements[i]->is_empty) | ||
891 | count++; | ||
892 | } | ||
893 | return count; | ||
894 | } | ||
895 | |||
896 | |||
897 | /** | ||
898 | * Cleans the sampler. | ||
899 | */ | ||
900 | void | ||
901 | RPS_sampler_destroy (struct RPS_Sampler *sampler) | ||
902 | { | ||
903 | if (NULL != sampler->req_handle_head) | ||
904 | { | ||
905 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
906 | "There are still pending requests. Going to remove them.\n"); | ||
907 | while (NULL != sampler->req_handle_head) | ||
908 | { | ||
909 | RPS_sampler_request_cancel (sampler->req_handle_head); | ||
910 | } | ||
911 | } | ||
912 | sampler_empty (sampler); | ||
913 | GNUNET_free (sampler); | ||
914 | } | ||
915 | |||
916 | /* end of gnunet-service-rps.c */ | 272 | /* end of gnunet-service-rps.c */ |