aboutsummaryrefslogtreecommitdiff
path: root/src/rps/gnunet-rps-profiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rps/gnunet-rps-profiler.c')
-rw-r--r--src/rps/gnunet-rps-profiler.c3199
1 files changed, 0 insertions, 3199 deletions
diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c
deleted file mode 100644
index 6d1236f08..000000000
--- a/src/rps/gnunet-rps-profiler.c
+++ /dev/null
@@ -1,3199 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file rps/test_rps.c
22 * @brief Testcase for the random peer sampling service. Starts
23 * a peergroup with a given number of peers, then waits to
24 * receive size pushes/pulls from each peer. Expects to wait
25 * for one message from each peer.
26 */
27#include "platform.h"
28// #include "rps_test_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testbed_service.h"
31
32#include "gnunet_rps_service.h"
33#include "rps-test_util.h"
34#include "gnunet-service-rps_sampler_elem.h"
35
36#include <inttypes.h>
37
38
39#define BIT(n) (1 << (n))
40
41/**
42 * How many peers do we start?
43 */
44static uint32_t num_peers;
45
46/**
47 * @brief number of bits required to represent the largest peer id
48 */
49static unsigned bits_needed;
50
51/**
52 * How long do we run the test?
53 */
54static struct GNUNET_TIME_Relative duration;
55
56/**
57 * When do we do a hard shutdown?
58 */
59static struct GNUNET_TIME_Relative timeout;
60
61
62// /**
63// * Portion of malicious peers
64// */
65// static double portion = .1;
66
67/**
68 * Type of malicious peer to test
69 */
70static unsigned int mal_type = 0;
71
72/**
73 * Handles to all of the running peers
74 */
75static struct GNUNET_TESTBED_Peer **testbed_peers;
76
77enum STAT_TYPE
78{
79 STAT_TYPE_ROUNDS, /* 0 */
80 STAT_TYPE_BLOCKS, /* 1 */
81 STAT_TYPE_BLOCKS_MANY_PUSH, /* 2 */
82 STAT_TYPE_BLOCKS_NO_PUSH, /* 3 */
83 STAT_TYPE_BLOCKS_NO_PULL, /* 4 */
84 STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL, /* 5 */
85 STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL, /* 6 */
86 STAT_TYPE_ISSUED_PUSH_SEND, /* 7 */
87 STAT_TYPE_ISSUED_PUSH_SEND_MH, /* 8 */
88 STAT_TYPE_ISSUED_PULL_REQ, /* 9 */
89 STAT_TYPE_ISSUED_PULL_REQ_MH, /* 10 */
90 STAT_TYPE_ISSUED_PULL_REP, /* 11 */
91 STAT_TYPE_SENT_PUSH_SEND, /* 12 */
92 STAT_TYPE_SENT_PULL_REQ, /* 13 */
93 STAT_TYPE_SENT_PULL_REQ_MH, /* 14 */
94 STAT_TYPE_SENT_PULL_REP, /* 15 */
95 STAT_TYPE_RECV_PUSH_SEND, /* 16 */
96 STAT_TYPE_RECV_PUSH_SEND_MH, /* 17 */
97 STAT_TYPE_RECV_PULL_REQ, /* 18 */
98 STAT_TYPE_RECV_PULL_REQ_MH, /* 19 */
99 STAT_TYPE_RECV_PULL_REP, /* 20 */
100 STAT_TYPE_RECV_PULL_REP_MH, /* 21 */
101 STAT_TYPE_VIEW_SIZE, /* 22 */
102 STAT_TYPE_KNOWN_PEERS, /* 23 */
103 STAT_TYPE_VALID_PEERS, /* 24 */
104 STAT_TYPE_LEARND_PEERS, /* 25 */
105 STAT_TYPE_PENDING_ONLINE_CHECKS, /* 26 */
106 STAT_TYPE_UNREQUESTED_PULL_REPLIES, /* 27 */
107 STAT_TYPE_PEERS_IN_PUSH_MAP, /* 28 */
108 STAT_TYPE_PEERS_IN_PULL_MAP, /* 29 */
109 STAT_TYPE_PEERS_IN_VIEW, /* 30 */
110 STAT_TYPE_VIEW_SIZE_AIM, /* 31 */
111 STAT_TYPE_MAX, /* 32 */
112};
113
114static char*stat_type_strings[] = {
115 "# rounds",
116 "# rounds blocked",
117 "# rounds blocked - too many pushes",
118 "# rounds blocked - no pushes",
119 "# rounds blocked - no pull replies",
120 "# rounds blocked - too many pushes, no pull replies",
121 "# rounds blocked - no pushes, no pull replies",
122 "# push send issued",
123 "# push send issued (multi-hop peer)",
124 "# pull request send issued",
125 "# pull request send issued (multi-hop peer)",
126 "# pull reply send issued",
127 "# pushes sent",
128 "# pull requests sent",
129 "# pull requests sent (multi-hop peer)",
130 "# pull replies sent",
131 "# push message received",
132 "# push message received (multi-hop peer)",
133 "# pull request message received",
134 "# pull request message received (multi-hop peer)",
135 "# pull reply messages received",
136 "# pull reply messages received (multi-hop peer)",
137 "view size",
138 "# known peers",
139 "# valid peers",
140 "# learnd peers",
141 "# pending online checks",
142 "# unrequested pull replies",
143 "# peers in push map at end of round",
144 "# peers in pull map at end of round",
145 "# peers in view at end of round",
146 "view size aim",
147};
148
149struct STATcls
150{
151 struct RPSPeer *rps_peer;
152 enum STAT_TYPE stat_type;
153};
154
155
156/**
157 * @brief Converts string representation to the corresponding #STAT_TYPE enum.
158 *
159 * @param stat_str string representation of statistics specifier
160 *
161 * @return corresponding enum
162 */
163enum STAT_TYPE
164stat_str_2_type (const char *stat_str)
165{
166 if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_NO_PULL],
167 stat_str,
168 strlen (stat_type_strings[STAT_TYPE_BLOCKS_NO_PULL])))
169 {
170 return STAT_TYPE_BLOCKS_NO_PULL;
171 }
172 else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL],
173 stat_str,
174 strlen (
175 stat_type_strings[STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL])))
176 {
177 return STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL;
178 }
179 else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_MANY_PUSH],
180 stat_str,
181 strlen (
182 stat_type_strings[STAT_TYPE_BLOCKS_MANY_PUSH])))
183 {
184 return STAT_TYPE_BLOCKS_MANY_PUSH;
185 }
186 else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL],
187 stat_str,
188 strlen (
189 stat_type_strings[STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL])))
190 {
191 return STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL;
192 }
193 else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_NO_PUSH],
194 stat_str,
195 strlen (stat_type_strings[STAT_TYPE_BLOCKS_NO_PUSH])))
196 {
197 return STAT_TYPE_BLOCKS_NO_PUSH;
198 }
199 else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS],
200 stat_str,
201 strlen (stat_type_strings[STAT_TYPE_BLOCKS])))
202 {
203 return STAT_TYPE_BLOCKS;
204 }
205 else if (0 == strncmp (stat_type_strings[STAT_TYPE_ROUNDS],
206 stat_str,
207 strlen (stat_type_strings[STAT_TYPE_ROUNDS])))
208 {
209 return STAT_TYPE_ROUNDS;
210 }
211 else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PUSH_SEND],
212 stat_str,
213 strlen (
214 stat_type_strings[STAT_TYPE_ISSUED_PUSH_SEND])))
215 {
216 return STAT_TYPE_ISSUED_PUSH_SEND;
217 }
218 else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PUSH_SEND_MH],
219 stat_str,
220 strlen (
221 stat_type_strings[STAT_TYPE_ISSUED_PUSH_SEND_MH])))
222 {
223 return STAT_TYPE_ISSUED_PUSH_SEND_MH;
224 }
225 else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PULL_REQ],
226 stat_str,
227 strlen (stat_type_strings[STAT_TYPE_ISSUED_PULL_REQ])))
228 {
229 return STAT_TYPE_ISSUED_PULL_REQ;
230 }
231 else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PULL_REQ_MH],
232 stat_str,
233 strlen (
234 stat_type_strings[STAT_TYPE_ISSUED_PULL_REQ_MH])))
235 {
236 return STAT_TYPE_ISSUED_PULL_REQ_MH;
237 }
238 else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PULL_REP],
239 stat_str,
240 strlen (stat_type_strings[STAT_TYPE_ISSUED_PULL_REP])))
241 {
242 return STAT_TYPE_ISSUED_PULL_REP;
243 }
244 else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PUSH_SEND],
245 stat_str,
246 strlen (stat_type_strings[STAT_TYPE_SENT_PUSH_SEND])))
247 {
248 return STAT_TYPE_SENT_PUSH_SEND;
249 }
250 else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PULL_REQ],
251 stat_str,
252 strlen (stat_type_strings[STAT_TYPE_SENT_PULL_REQ])))
253 {
254 return STAT_TYPE_SENT_PULL_REQ;
255 }
256 else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PULL_REQ_MH],
257 stat_str,
258 strlen (
259 stat_type_strings[STAT_TYPE_SENT_PULL_REQ_MH])))
260 {
261 return STAT_TYPE_SENT_PULL_REQ_MH;
262 }
263 else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PULL_REP],
264 stat_str,
265 strlen (stat_type_strings[STAT_TYPE_SENT_PULL_REP])))
266 {
267 return STAT_TYPE_SENT_PULL_REP;
268 }
269 else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PUSH_SEND],
270 stat_str,
271 strlen (stat_type_strings[STAT_TYPE_RECV_PUSH_SEND])))
272 {
273 return STAT_TYPE_RECV_PUSH_SEND;
274 }
275 else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PUSH_SEND_MH],
276 stat_str,
277 strlen (
278 stat_type_strings[STAT_TYPE_RECV_PUSH_SEND_MH])))
279 {
280 return STAT_TYPE_RECV_PUSH_SEND_MH;
281 }
282 else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REQ],
283 stat_str,
284 strlen (stat_type_strings[STAT_TYPE_RECV_PULL_REQ])))
285 {
286 return STAT_TYPE_RECV_PULL_REQ;
287 }
288 else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REQ_MH],
289 stat_str,
290 strlen (
291 stat_type_strings[STAT_TYPE_RECV_PULL_REQ_MH])))
292 {
293 return STAT_TYPE_RECV_PULL_REQ_MH;
294 }
295 else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REP],
296 stat_str,
297 strlen (stat_type_strings[STAT_TYPE_RECV_PULL_REP])))
298 {
299 return STAT_TYPE_RECV_PULL_REP;
300 }
301 else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REP_MH],
302 stat_str,
303 strlen (
304 stat_type_strings[STAT_TYPE_RECV_PULL_REP_MH])))
305 {
306 return STAT_TYPE_RECV_PULL_REP_MH;
307 }
308 else if (0 == strncmp (stat_type_strings[STAT_TYPE_VIEW_SIZE],
309 stat_str,
310 strlen (stat_type_strings[STAT_TYPE_VIEW_SIZE])))
311 {
312 return STAT_TYPE_VIEW_SIZE;
313 }
314 else if (0 == strncmp (stat_type_strings[STAT_TYPE_KNOWN_PEERS],
315 stat_str,
316 strlen (stat_type_strings[STAT_TYPE_KNOWN_PEERS])))
317 {
318 return STAT_TYPE_KNOWN_PEERS;
319 }
320 else if (0 == strncmp (stat_type_strings[STAT_TYPE_VALID_PEERS],
321 stat_str,
322 strlen (stat_type_strings[STAT_TYPE_VALID_PEERS])))
323 {
324 return STAT_TYPE_VALID_PEERS;
325 }
326 else if (0 == strncmp (stat_type_strings[STAT_TYPE_LEARND_PEERS],
327 stat_str,
328 strlen (stat_type_strings[STAT_TYPE_LEARND_PEERS])))
329 {
330 return STAT_TYPE_LEARND_PEERS;
331 }
332 else if (0 == strncmp (stat_type_strings[STAT_TYPE_PENDING_ONLINE_CHECKS],
333 stat_str,
334 strlen (
335 stat_type_strings[STAT_TYPE_PENDING_ONLINE_CHECKS])))
336 {
337 return STAT_TYPE_PENDING_ONLINE_CHECKS;
338 }
339 else if (0 == strncmp (stat_type_strings[STAT_TYPE_UNREQUESTED_PULL_REPLIES],
340 stat_str,
341 strlen (
342 stat_type_strings[STAT_TYPE_UNREQUESTED_PULL_REPLIES])))
343 {
344 return STAT_TYPE_UNREQUESTED_PULL_REPLIES;
345 }
346 else if (0 == strncmp (stat_type_strings[STAT_TYPE_PEERS_IN_PUSH_MAP],
347 stat_str,
348 strlen (
349 stat_type_strings[STAT_TYPE_PEERS_IN_PUSH_MAP])))
350 {
351 return STAT_TYPE_PEERS_IN_PUSH_MAP;
352 }
353 else if (0 == strncmp (stat_type_strings[STAT_TYPE_PEERS_IN_PULL_MAP],
354 stat_str,
355 strlen (
356 stat_type_strings[STAT_TYPE_PEERS_IN_PULL_MAP])))
357 {
358 return STAT_TYPE_PEERS_IN_PULL_MAP;
359 }
360 else if (0 == strncmp (stat_type_strings[STAT_TYPE_PEERS_IN_VIEW],
361 stat_str,
362 strlen (stat_type_strings[STAT_TYPE_PEERS_IN_VIEW])))
363 {
364 return STAT_TYPE_PEERS_IN_VIEW;
365 }
366 else if (0 == strncmp (stat_type_strings[STAT_TYPE_VIEW_SIZE_AIM],
367 stat_str,
368 strlen (stat_type_strings[STAT_TYPE_VIEW_SIZE_AIM])))
369 {
370 return STAT_TYPE_VIEW_SIZE_AIM;
371 }
372 return STAT_TYPE_MAX;
373}
374
375
376/**
377 * @brief Indicates whether peer should go off- or online
378 */
379enum PEER_ONLINE_DELTA
380{
381 /**
382 * @brief Indicates peer going online
383 */
384 PEER_GO_ONLINE = 1,
385 /**
386 * @brief Indicates peer going offline
387 */
388 PEER_GO_OFFLINE = -1,
389};
390
391/**
392 * Operation map entry
393 */
394struct OpListEntry
395{
396 /**
397 * DLL next ptr
398 */
399 struct OpListEntry *next;
400
401 /**
402 * DLL prev ptr
403 */
404 struct OpListEntry *prev;
405
406 /**
407 * The testbed operation
408 */
409 struct GNUNET_TESTBED_Operation *op;
410
411 /**
412 * Depending on whether we start or stop RPS service at the peer, set this to
413 * #PEER_GO_ONLINE (1) or #PEER_GO_OFFLINE (-1)
414 */
415 enum PEER_ONLINE_DELTA delta;
416
417 /**
418 * Index of the regarding peer
419 */
420 unsigned int index;
421};
422
423/**
424 * OpList DLL head
425 */
426static struct OpListEntry *oplist_head;
427
428/**
429 * OpList DLL tail
430 */
431static struct OpListEntry *oplist_tail;
432
433
434/**
435 * A pending reply: A request was sent and the reply is pending.
436 */
437struct PendingReply
438{
439 /**
440 * DLL next,prev ptr
441 */
442 struct PendingReply *next;
443 struct PendingReply *prev;
444
445 /**
446 * Handle to the request we are waiting for
447 */
448 struct GNUNET_RPS_Request_Handle_Single_Info *req_handle;
449
450 /**
451 * The peer that requested
452 */
453 struct RPSPeer *rps_peer;
454};
455
456
457/**
458 * A pending request: A request was not made yet but is scheduled for later.
459 */
460struct PendingRequest
461{
462 /**
463 * DLL next,prev ptr
464 */
465 struct PendingRequest *next;
466 struct PendingRequest *prev;
467
468 /**
469 * Handle to the request we are waiting for
470 */
471 struct GNUNET_SCHEDULER_Task *request_task;
472
473 /**
474 * The peer that requested
475 */
476 struct RPSPeer *rps_peer;
477};
478
479
480/**
481 * Information we track for each peer.
482 */
483struct RPSPeer
484{
485 /**
486 * Index of the peer.
487 */
488 uint32_t index;
489
490 /**
491 * Handle for RPS connect operation.
492 */
493 struct GNUNET_TESTBED_Operation *op;
494
495 /**
496 * Handle to RPS service.
497 */
498 struct GNUNET_RPS_Handle *rps_handle;
499
500 /**
501 * ID of the peer.
502 */
503 struct GNUNET_PeerIdentity *peer_id;
504
505 /**
506 * A request handle to check for an request
507 */
508 // struct GNUNET_RPS_Request_Handle *req_handle;
509
510 /**
511 * Peer on- or offline?
512 */
513 int online;
514
515 /**
516 * Number of Peer IDs to request during the whole test
517 */
518 unsigned int num_ids_to_request;
519
520 /**
521 * Pending requests DLL
522 */
523 struct PendingRequest *pending_req_head;
524 struct PendingRequest *pending_req_tail;
525
526 /**
527 * Number of pending requests
528 */
529 unsigned int num_pending_reqs;
530
531 /**
532 * Pending replies DLL
533 */
534 struct PendingReply *pending_rep_head;
535 struct PendingReply *pending_rep_tail;
536
537 /**
538 * Number of pending replies
539 */
540 unsigned int num_pending_reps;
541
542 /**
543 * Number of received PeerIDs
544 */
545 unsigned int num_recv_ids;
546
547 /**
548 * Pending operation on that peer
549 */
550 const struct OpListEntry *entry_op_manage;
551
552 /**
553 * Testbed operation to connect to statistics service
554 */
555 struct GNUNET_TESTBED_Operation *stat_op;
556
557 /**
558 * Handle to the statistics service
559 */
560 struct GNUNET_STATISTICS_Handle *stats_h;
561
562 /**
563 * @brief flags to indicate which statistics values have been already
564 * collected from the statistics service.
565 * Used to check whether we are able to shutdown.
566 */
567 uint32_t stat_collected_flags;
568
569 /**
570 * @brief File name of the file the stats are finally written to
571 */
572 const char *file_name_stats;
573
574 /**
575 * @brief File name of the file the stats are finally written to
576 */
577 const char *file_name_probs;
578
579 /**
580 * @brief File name of the file the stats are finally written to
581 */
582 const char *file_name_probs_hist;
583
584 /**
585 * @brief The current view
586 */
587 struct GNUNET_PeerIdentity *cur_view;
588
589 /**
590 * @brief Number of peers in the #cur_view.
591 */
592 uint32_t cur_view_count;
593
594 /**
595 * @brief Number of occurrences in other peer's view
596 */
597 uint32_t count_in_views;
598
599 /**
600 * @brief statistics values
601 */
602 uint64_t stats[STAT_TYPE_MAX];
603 /**
604 * @brief Handle for the statistics get request
605 */
606 struct GNUNET_STATISTICS_GetHandle *h_stat_get[STAT_TYPE_MAX];
607
608 /**
609 * @brief Keep the probabilities in cache for computing the probabilities
610 * with respect to history.
611 */
612 double *eval_probs_cache;
613};
614
615/**
616 * Information for all the peers.
617 */
618static struct RPSPeer *rps_peers;
619
620/**
621 * Peermap to get the index of a given peer ID quick.
622 */
623static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
624
625/**
626 * IDs of the peers.
627 */
628static struct GNUNET_PeerIdentity *rps_peer_ids;
629
630/**
631 * ID of the targeted peer.
632 */
633static struct GNUNET_PeerIdentity *target_peer;
634
635/**
636 * Number of online peers.
637 */
638static unsigned int num_peers_online;
639
640/**
641 * @brief The added sizes of the peer's views
642 */
643static unsigned int view_sizes;
644
645/**
646 * Return value from 'main'.
647 */
648static int ok;
649
650/**
651 * Identifier for the task that runs after the test to collect results
652 */
653static struct GNUNET_SCHEDULER_Task *post_test_task;
654
655/**
656 * Identifier for the shutdown task
657 */
658static struct GNUNET_SCHEDULER_Task *shutdown_task;
659
660
661/**
662 * Identifier for the churn task that runs periodically
663 */
664static struct GNUNET_SCHEDULER_Task *churn_task;
665
666/**
667 * Called to initialise the given RPSPeer
668 */
669typedef void (*InitPeer) (struct RPSPeer *rps_peer);
670
671/**
672 * @brief Called directly after connecting to the service
673 *
674 * @param rps_peer Specific peer the function is called on
675 * @param h the handle to the rps service
676 */
677typedef void (*PreTest) (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h);
678
679/**
680 * @brief Executes functions to test the api/service for a given peer
681 *
682 * Called from within #rps_connect_complete_cb ()
683 * Implemented by #churn_test_cb, #profiler_cb, #mal_cb, #single_req_cb,
684 * #delay_req_cb, #seed_big_cb, #single_peer_seed_cb, #seed_cb, #req_cancel_cb
685 *
686 * @param rps_peer the peer the task runs on
687 */
688typedef void (*MainTest) (struct RPSPeer *rps_peer);
689
690/**
691 * Callback called once the requested random peers are available
692 */
693typedef void (*ReplyHandle) (void *cls,
694 uint64_t n,
695 const struct GNUNET_PeerIdentity *recv_peers);
696
697/**
698 * Called directly before disconnecting from the service
699 */
700typedef void (*PostTest) (struct RPSPeer *peer);
701
702/**
703 * Function called after disconnect to evaluate test success
704 */
705typedef int (*EvaluationCallback) (void);
706
707/**
708 * @brief Do we have Churn?
709 */
710enum OPTION_CHURN
711{
712 /**
713 * @brief If we have churn this is set
714 */
715 HAVE_CHURN,
716 /**
717 * @brief If we have no churn this is set
718 */
719 HAVE_NO_CHURN,
720};
721
722/**
723 * @brief Is it ok to quit the test before the timeout?
724 */
725enum OPTION_QUICK_QUIT
726{
727 /**
728 * @brief It is ok for the test to quit before the timeout triggers
729 */
730 HAVE_QUICK_QUIT,
731
732 /**
733 * @brief It is NOT ok for the test to quit before the timeout triggers
734 */
735 HAVE_NO_QUICK_QUIT,
736};
737
738/**
739 * @brief Do we collect statistics at the end?
740 */
741enum OPTION_COLLECT_STATISTICS
742{
743 /**
744 * @brief We collect statistics at the end
745 */
746 COLLECT_STATISTICS,
747
748 /**
749 * @brief We do not collect statistics at the end
750 */
751 NO_COLLECT_STATISTICS,
752};
753
754/**
755 * @brief Do we collect views during run?
756 */
757enum OPTION_COLLECT_VIEW
758{
759 /**
760 * @brief We collect view during run
761 */
762 COLLECT_VIEW,
763
764 /**
765 * @brief We do not collect the view during run
766 */
767 NO_COLLECT_VIEW,
768};
769
770/**
771 * Structure to define a single test
772 */
773struct SingleTestRun
774{
775 /**
776 * Name of the test
777 */
778 char *name;
779
780 /**
781 * Called with a single peer in order to initialise that peer
782 */
783 InitPeer init_peer;
784
785 /**
786 * Called directly after connecting to the service
787 */
788 PreTest pre_test;
789
790 /**
791 * Main function for each peer
792 */
793 MainTest main_test;
794
795 /**
796 * Callback called once the requested peers are available
797 */
798 ReplyHandle reply_handle;
799
800 /**
801 * Called directly before disconnecting from the service
802 */
803 PostTest post_test;
804
805 /**
806 * Function to evaluate the test results
807 */
808 EvaluationCallback eval_cb;
809
810 /**
811 * Request interval
812 */
813 uint32_t request_interval;
814
815 /**
816 * Number of Requests to make.
817 */
818 uint32_t num_requests;
819
820 /**
821 * Run with (-out) churn
822 */
823 enum OPTION_CHURN have_churn;
824
825 /**
826 * Quit test before timeout?
827 */
828 enum OPTION_QUICK_QUIT have_quick_quit;
829
830 /**
831 * Collect statistics at the end?
832 */
833 enum OPTION_COLLECT_STATISTICS have_collect_statistics;
834
835 /**
836 * Collect view during run?
837 */
838 enum OPTION_COLLECT_VIEW have_collect_view;
839
840 /**
841 * @brief Mark which values from the statistics service to collect at the end
842 * of the run
843 */
844 uint32_t stat_collect_flags;
845} cur_test_run;
846
847/**
848 * Did we finish the test?
849 */
850static int post_test;
851
852/**
853 * Are we shutting down?
854 */
855static int in_shutdown;
856
857/**
858 * Append arguments to file
859 */
860static void
861tofile_ (const char *file_name, const char *line)
862{
863 struct GNUNET_DISK_FileHandle *f;
864 /* char output_buffer[512]; */
865 size_t size;
866 /* int size; */
867 size_t size2;
868
869 if (NULL == (f = GNUNET_DISK_file_open (file_name,
870 GNUNET_DISK_OPEN_APPEND
871 | GNUNET_DISK_OPEN_WRITE
872 | GNUNET_DISK_OPEN_CREATE,
873 GNUNET_DISK_PERM_USER_READ
874 | GNUNET_DISK_PERM_USER_WRITE
875 | GNUNET_DISK_PERM_GROUP_READ
876 | GNUNET_DISK_PERM_OTHER_READ)))
877 {
878 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
879 "Not able to open file %s\n",
880 file_name);
881 return;
882 }
883 /* size = GNUNET_snprintf (output_buffer,
884 sizeof (output_buffer),
885 "%llu %s\n",
886 GNUNET_TIME_absolute_get ().abs_value_us,
887 line);
888 if (0 > size)
889 {
890 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
891 "Failed to write string to buffer (size: %i)\n",
892 size);
893 return;
894 } */size = strlen (line) * sizeof(char);
895
896 size2 = GNUNET_DISK_file_write (f, line, size);
897 if (size != size2)
898 {
899 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
900 "Unable to write to file! (Size: %lu, size2: %lu)\n",
901 size,
902 size2);
903 if (GNUNET_YES != GNUNET_DISK_file_close (f))
904 {
905 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
906 "Unable to close file\n");
907 }
908 return;
909 }
910
911 if (GNUNET_YES != GNUNET_DISK_file_close (f))
912 {
913 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
914 "Unable to close file\n");
915 }
916}
917
918
919/**
920 * This function is used to facilitate writing important information to disk
921 */
922#define tofile(file_name, ...) do { \
923 char tmp_buf[512]; \
924 int size; \
925 size = GNUNET_snprintf (tmp_buf, sizeof(tmp_buf), __VA_ARGS__); \
926 if (0 > size) \
927 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
928 "Failed to create tmp_buf\n"); \
929 else \
930 tofile_ (file_name, tmp_buf); \
931} while (0);
932
933
934/**
935 * Write the ids and their according index in the given array to a file
936 * Unused
937 */
938/* static void
939 ids_to_file (char *file_name,
940 struct GNUNET_PeerIdentity *peer_ids,
941 unsigned int num_peer_ids)
942 {
943 unsigned int i;
944
945 for (i=0 ; i < num_peer_ids ; i++)
946 {
947 to_file (file_name,
948 "%u\t%s",
949 i,
950 GNUNET_i2s_full (&peer_ids[i]));
951 }
952 } */
953
954/**
955 * Test the success of a single test
956 */
957static int
958evaluate (void)
959{
960 unsigned int i;
961 int tmp_ok;
962
963 tmp_ok = 1;
964
965 for (i = 0; i < num_peers; i++)
966 {
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
968 "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
969 i,
970 GNUNET_i2s (rps_peers[i].peer_id),
971 rps_peers[i].num_recv_ids,
972 rps_peers[i].num_ids_to_request,
973 (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids));
974 tmp_ok &= (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids);
975 }
976 return tmp_ok ? 0 : 1;
977}
978
979
980/**
981 * Creates an oplist entry and adds it to the oplist DLL
982 */
983static struct OpListEntry *
984make_oplist_entry ()
985{
986 struct OpListEntry *entry;
987
988 entry = GNUNET_new (struct OpListEntry);
989 GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
990 return entry;
991}
992
993
994/**
995 * @brief Checks if given peer already received its statistics value from the
996 * statistics service.
997 *
998 * @param rps_peer the peer to check for
999 *
1000 * @return #GNUNET_YES if so
1001 * #GNUNET_NO otherwise
1002 */
1003static int
1004check_statistics_collect_completed_single_peer (
1005 const struct RPSPeer *rps_peer)
1006{
1007 if (cur_test_run.stat_collect_flags !=
1008 (cur_test_run.stat_collect_flags
1009 & rps_peer->stat_collected_flags))
1010 {
1011 return GNUNET_NO;
1012 }
1013 return GNUNET_YES;
1014}
1015
1016
1017/**
1018 * @brief Checks if all peers already received their statistics value from the
1019 * statistics service.
1020 *
1021 * @return #GNUNET_YES if so
1022 * #GNUNET_NO otherwise
1023 */
1024static int
1025check_statistics_collect_completed ()
1026{
1027 uint32_t i;
1028
1029 for (i = 0; i < num_peers; i++)
1030 {
1031 if (GNUNET_NO == check_statistics_collect_completed_single_peer (
1032 &rps_peers[i]))
1033 {
1034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1035 "At least Peer %" PRIu32
1036 " did not yet receive all statistics values\n",
1037 i);
1038 return GNUNET_NO;
1039 }
1040 }
1041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1042 "All peers received their statistics values\n");
1043 return GNUNET_YES;
1044}
1045
1046
1047static void
1048rps_disconnect_adapter (void *cls,
1049 void *op_result);
1050
1051static void
1052cancel_pending_req (struct PendingRequest *pending_req)
1053{
1054 struct RPSPeer *rps_peer;
1055
1056 rps_peer = pending_req->rps_peer;
1057 GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
1058 rps_peer->pending_req_tail,
1059 pending_req);
1060 rps_peer->num_pending_reqs--;
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1062 "Cancelling pending rps get request\n");
1063 GNUNET_SCHEDULER_cancel (pending_req->request_task);
1064 GNUNET_free (pending_req);
1065}
1066
1067
1068static void
1069cancel_request (struct PendingReply *pending_rep)
1070{
1071 struct RPSPeer *rps_peer;
1072
1073 rps_peer = pending_rep->rps_peer;
1074 GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
1075 rps_peer->pending_rep_tail,
1076 pending_rep);
1077 rps_peer->num_pending_reps--;
1078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079 "Cancelling rps get reply\n");
1080 GNUNET_assert (NULL != pending_rep->req_handle);
1081 GNUNET_RPS_request_single_info_cancel (pending_rep->req_handle);
1082 pending_rep->req_handle = NULL;
1083 GNUNET_free (pending_rep);
1084 pending_rep = NULL;
1085}
1086
1087
1088void
1089clean_peer (unsigned peer_index)
1090{
1091 struct PendingRequest *pending_req;
1092
1093 while (NULL != (pending_req = rps_peers[peer_index].pending_req_head))
1094 {
1095 cancel_pending_req (pending_req);
1096 }
1097 pending_req = rps_peers[peer_index].pending_req_head;
1098 rps_disconnect_adapter (&rps_peers[peer_index],
1099 &rps_peers[peer_index].rps_handle);
1100 for (unsigned stat_type = STAT_TYPE_ROUNDS;
1101 stat_type < STAT_TYPE_MAX;
1102 stat_type++)
1103 {
1104 if (NULL != rps_peers[peer_index].h_stat_get[stat_type])
1105 {
1106 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1107 "(%u) did not yet receive stat value for `%s'\n",
1108 rps_peers[peer_index].index,
1109 stat_type_strings[stat_type]);
1110 GNUNET_STATISTICS_get_cancel (
1111 rps_peers[peer_index].h_stat_get[stat_type]);
1112 }
1113 }
1114 if (NULL != rps_peers[peer_index].op)
1115 {
1116 GNUNET_TESTBED_operation_done (rps_peers[peer_index].op);
1117 rps_peers[peer_index].op = NULL;
1118 }
1119}
1120
1121
1122/**
1123 * Task run on timeout to shut everything down.
1124 */
1125static void
1126shutdown_op (void *cls)
1127{
1128 unsigned int i;
1129 struct OpListEntry *entry;
1130
1131 (void) cls;
1132
1133 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1134 "Shutdown task scheduled, going down.\n");
1135 in_shutdown = GNUNET_YES;
1136
1137 if (NULL != shutdown_task)
1138 {
1139 GNUNET_SCHEDULER_cancel (shutdown_task);
1140 shutdown_task = NULL;
1141 }
1142 if (NULL != post_test_task)
1143 {
1144 GNUNET_SCHEDULER_cancel (post_test_task);
1145 post_test_task = NULL;
1146 }
1147 if (NULL != churn_task)
1148 {
1149 GNUNET_SCHEDULER_cancel (churn_task);
1150 churn_task = NULL;
1151 }
1152 entry = oplist_head;
1153 while (NULL != (entry = oplist_head))
1154 {
1155 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1156 "Operation still pending on shutdown (%u)\n",
1157 entry->index);
1158 GNUNET_TESTBED_operation_done (entry->op);
1159 GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1160 GNUNET_free (entry);
1161 }
1162 for (i = 0; i < num_peers; i++)
1163 {
1164 clean_peer (i);
1165 }
1166 close_all_files ();
1167}
1168
1169
1170static void
1171trigger_shutdown (void *cls)
1172{
1173 (void) cls;
1174
1175 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1176 "Shutdown was triggered by timeout, going down.\n");
1177 shutdown_task = NULL;
1178 GNUNET_SCHEDULER_shutdown ();
1179}
1180
1181
1182/**
1183 * Task run after #duration to collect statistics and potentially shut down.
1184 */
1185static void
1186post_test_op (void *cls)
1187{
1188 unsigned int i;
1189
1190 (void) cls;
1191
1192 post_test_task = NULL;
1193 post_test = GNUNET_YES;
1194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1195 "Executing post test op.\n");
1196 if (NULL != churn_task)
1197 {
1198 GNUNET_SCHEDULER_cancel (churn_task);
1199 churn_task = NULL;
1200 }
1201 for (i = 0; i < num_peers; i++)
1202 {
1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1204 "Executing post test op. (peer %" PRIu32 ")\n",
1205 rps_peers[i].index);
1206 if (NULL != rps_peers[i].op)
1207 {
1208 GNUNET_TESTBED_operation_done (rps_peers[i].op);
1209 rps_peers[i].op = NULL;
1210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1211 "Cancelled testbed operation\n");
1212 }
1213 if (NULL != cur_test_run.post_test)
1214 {
1215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing post_test for peer %u\n",
1216 i);
1217 cur_test_run.post_test (&rps_peers[i]);
1218 }
1219 }
1220 /* If we do not collect statistics, shut down directly */
1221 if ((NO_COLLECT_STATISTICS == cur_test_run.have_collect_statistics) ||
1222 (GNUNET_YES == check_statistics_collect_completed ()) )
1223 {
1224 GNUNET_SCHEDULER_cancel (shutdown_task);
1225 shutdown_task = NULL;
1226 GNUNET_SCHEDULER_shutdown ();
1227 }
1228}
1229
1230
1231/**
1232 * Get the id of peer i.
1233 */
1234void
1235info_cb (void *cb_cls,
1236 struct GNUNET_TESTBED_Operation *op,
1237 const struct GNUNET_TESTBED_PeerInformation *pinfo,
1238 const char *emsg)
1239{
1240 struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
1241
1242 (void) op;
1243
1244 if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1245 {
1246 return;
1247 }
1248
1249 if ((NULL == pinfo) || (NULL != emsg))
1250 {
1251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
1252 GNUNET_TESTBED_operation_done (entry->op);
1253 return;
1254 }
1255
1256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1257 "Peer %u is %s\n",
1258 entry->index,
1259 GNUNET_i2s (pinfo->result.id));
1260
1261 rps_peer_ids[entry->index] = *(pinfo->result.id);
1262 rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
1263
1264 GNUNET_assert (GNUNET_OK ==
1265 GNUNET_CONTAINER_multipeermap_put (peer_map,
1266 &rps_peer_ids[entry->index],
1267 &rps_peers[entry->index],
1268 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1269 tofile ("/tmp/rps/peer_ids",
1270 "%u\t%s\n",
1271 entry->index,
1272 GNUNET_i2s_full (&rps_peer_ids[entry->index]));
1273
1274 GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1275 GNUNET_TESTBED_operation_done (entry->op);
1276 GNUNET_free (entry);
1277}
1278
1279
1280/**
1281 * Callback to be called when RPS service connect operation is completed
1282 *
1283 * @param cls the callback closure from functions generating an operation
1284 * @param op the operation that has been finished
1285 * @param ca_result the RPS service handle returned from rps_connect_adapter
1286 * @param emsg error message in case the operation has failed; will be NULL if
1287 * operation has executed successfully.
1288 */
1289static void
1290rps_connect_complete_cb (void *cls,
1291 struct GNUNET_TESTBED_Operation *op,
1292 void *ca_result,
1293 const char *emsg)
1294{
1295 struct RPSPeer *rps_peer = cls;
1296 struct GNUNET_RPS_Handle *rps = ca_result;
1297
1298 if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1299 {
1300 return;
1301 }
1302
1303 rps_peer->rps_handle = rps;
1304 rps_peer->online = GNUNET_YES;
1305 num_peers_online++;
1306
1307 GNUNET_assert (op == rps_peer->op);
1308 if (NULL != emsg)
1309 {
1310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1311 "Failed to connect to RPS service: %s\n",
1312 emsg);
1313 ok = 1;
1314 GNUNET_SCHEDULER_shutdown ();
1315 return;
1316 }
1317
1318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1319 "Started client successfully (%u)\n",
1320 rps_peer->index);
1321
1322 cur_test_run.main_test (rps_peer);
1323}
1324
1325
1326/**
1327 * Adapter function called to establish a connection to
1328 * the RPS service.
1329 *
1330 * @param cls closure
1331 * @param cfg configuration of the peer to connect to; will be available until
1332 * GNUNET_TESTBED_operation_done() is called on the operation returned
1333 * from GNUNET_TESTBED_service_connect()
1334 * @return service handle to return in 'op_result', NULL on error
1335 */
1336static void *
1337rps_connect_adapter (void *cls,
1338 const struct GNUNET_CONFIGURATION_Handle *cfg)
1339{
1340 struct GNUNET_RPS_Handle *h;
1341
1342 h = GNUNET_RPS_connect (cfg);
1343
1344 if (NULL != cur_test_run.pre_test)
1345 cur_test_run.pre_test (cls, h);
1346
1347 return h;
1348}
1349
1350
1351/**
1352 * Called to open a connection to the peer's statistics
1353 *
1354 * @param cls peer context
1355 * @param cfg configuration of the peer to connect to; will be available until
1356 * GNUNET_TESTBED_operation_done() is called on the operation returned
1357 * from GNUNET_TESTBED_service_connect()
1358 * @return service handle to return in 'op_result', NULL on error
1359 */
1360static void *
1361stat_connect_adapter (void *cls,
1362 const struct GNUNET_CONFIGURATION_Handle *cfg)
1363{
1364 struct RPSPeer *peer = cls;
1365
1366 peer->stats_h = GNUNET_STATISTICS_create ("rps-profiler", cfg);
1367 return peer->stats_h;
1368}
1369
1370
1371/**
1372 * Called to disconnect from peer's statistics service
1373 *
1374 * @param cls peer context
1375 * @param op_result service handle returned from the connect adapter
1376 */
1377static void
1378stat_disconnect_adapter (void *cls, void *op_result)
1379{
1380 struct RPSPeer *peer = cls;
1381
1382 // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
1383 // (peer->stats_h, "core", "# peers connected",
1384 // stat_iterator, peer));
1385 // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
1386 // (peer->stats_h, "nse", "# peers connected",
1387 // stat_iterator, peer));
1388 GNUNET_STATISTICS_destroy (op_result, GNUNET_NO);
1389 peer->stats_h = NULL;
1390}
1391
1392
1393/**
1394 * Called after successfully opening a connection to a peer's statistics
1395 * service; we register statistics monitoring for CORE and NSE here.
1396 *
1397 * @param cls the callback closure from functions generating an operation
1398 * @param op the operation that has been finished
1399 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
1400 * @param emsg error message in case the operation has failed; will be NULL if
1401 * operation has executed successfully.
1402 */
1403static void
1404stat_complete_cb (void *cls,
1405 struct GNUNET_TESTBED_Operation *op,
1406 void *ca_result,
1407 const char *emsg)
1408{
1409 // struct GNUNET_STATISTICS_Handle *sh = ca_result;
1410 // struct RPSPeer *peer = (struct RPSPeer *) cls;
1411 (void) cls;
1412 (void) op;
1413 (void) ca_result;
1414
1415 if (NULL != emsg)
1416 {
1417 GNUNET_break (0);
1418 return;
1419 }
1420 // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
1421 // (sh, "core", "# peers connected",
1422 // stat_iterator, peer));
1423 // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
1424 // (sh, "nse", "# peers connected",
1425 // stat_iterator, peer));
1426}
1427
1428
1429/**
1430 * Adapter function called to destroy connection to
1431 * RPS service.
1432 *
1433 * @param cls closure
1434 * @param op_result service handle returned from the connect adapter
1435 */
1436static void
1437rps_disconnect_adapter (void *cls,
1438 void *op_result)
1439{
1440 struct RPSPeer *peer = cls;
1441 struct GNUNET_RPS_Handle *h = op_result;
1442 struct PendingReply *pending_rep;
1443
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "disconnect_adapter (%u)\n",
1446 peer->index);
1447 GNUNET_assert (NULL != peer);
1448 if (NULL != peer->rps_handle)
1449 {
1450 while (NULL != (pending_rep = peer->pending_rep_head))
1451 {
1452 cancel_request (pending_rep);
1453 }
1454 GNUNET_assert (h == peer->rps_handle);
1455 if (NULL != h)
1456 {
1457 GNUNET_RPS_disconnect (h);
1458 h = NULL;
1459 }
1460 peer->rps_handle = NULL;
1461 }
1462}
1463
1464
1465/***********************************************************************
1466* Definition of tests
1467***********************************************************************/
1468
1469/**
1470 * Callback to call on receipt of a reply
1471 *
1472 * @param cls closure
1473 * @param n number of peers
1474 * @param recv_peers the received peers
1475 */
1476static void
1477default_reply_handle (void *cls,
1478 uint64_t n,
1479 const struct GNUNET_PeerIdentity *recv_peers)
1480{
1481 struct RPSPeer *rps_peer;
1482 struct PendingReply *pending_rep = (struct PendingReply *) cls;
1483 unsigned int i;
1484
1485 rps_peer = pending_rep->rps_peer;
1486 GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
1487 rps_peer->pending_rep_tail,
1488 pending_rep);
1489 rps_peer->num_pending_reps--;
1490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1491 "[%s] got %" PRIu64 " peers:\n",
1492 GNUNET_i2s (rps_peer->peer_id),
1493 n);
1494
1495 for (i = 0; i < n; i++)
1496 {
1497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1498 "%u: %s\n",
1499 i,
1500 GNUNET_i2s (&recv_peers[i]));
1501
1502 rps_peer->num_recv_ids++;
1503 }
1504
1505 if (GNUNET_YES != post_test)
1506 return;
1507 if (HAVE_QUICK_QUIT != cur_test_run.have_quick_quit)
1508 return;
1509 if (0 == evaluate ())
1510 {
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "Test succeeded before end of duration\n");
1513 if (NULL != post_test_task)
1514 GNUNET_SCHEDULER_cancel (post_test_task);
1515 post_test_task = GNUNET_SCHEDULER_add_now (&post_test_op, NULL);
1516 GNUNET_assert (NULL != post_test_task);
1517 }
1518}
1519
1520
1521static void
1522profiler_reply_handle_info (void *cls,
1523 const struct GNUNET_PeerIdentity *recv_peer,
1524 double probability,
1525 uint32_t num_observed);
1526
1527/**
1528 * Request random peers.
1529 */
1530static void
1531request_peers (void *cls)
1532{
1533 struct PendingRequest *pending_req = cls;
1534 struct RPSPeer *rps_peer;
1535 struct PendingReply *pending_rep;
1536
1537 rps_peer = pending_req->rps_peer;
1538 GNUNET_assert (1 <= rps_peer->num_pending_reqs);
1539 GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
1540 rps_peer->pending_req_tail,
1541 pending_req);
1542 rps_peer->num_pending_reqs--;
1543 if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1544 return;
1545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1546 "Requesting one peer\n");
1547 pending_rep = GNUNET_new (struct PendingReply);
1548 pending_rep->rps_peer = rps_peer;
1549 // pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
1550 // 1,
1551 // cur_test_run.reply_handle,
1552 // pending_rep);
1553 pending_rep->req_handle = GNUNET_RPS_request_peer_info (rps_peer->rps_handle,
1554 profiler_reply_handle_info,
1555 pending_rep);
1556 GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_rep_head,
1557 rps_peer->pending_rep_tail,
1558 pending_rep);
1559 rps_peer->num_pending_reps++;
1560}
1561
1562
1563/**
1564 * Schedule requests for peer @a rps_peer that have neither been scheduled, nor
1565 * issued, nor replied
1566 */
1567void
1568schedule_missing_requests (struct RPSPeer *rps_peer)
1569{
1570 unsigned int i;
1571 struct PendingRequest *pending_req;
1572
1573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1574 "Scheduling %u - %u missing requests\n",
1575 rps_peer->num_ids_to_request,
1576 rps_peer->num_pending_reqs + rps_peer->num_pending_reps);
1577 GNUNET_assert (rps_peer->num_pending_reqs + rps_peer->num_pending_reps <=
1578 rps_peer->num_ids_to_request);
1579 for (i = rps_peer->num_pending_reqs + rps_peer->num_pending_reps;
1580 i < rps_peer->num_ids_to_request; i++)
1581 {
1582 pending_req = GNUNET_new (struct PendingRequest);
1583 pending_req->rps_peer = rps_peer;
1584 pending_req->request_task = GNUNET_SCHEDULER_add_delayed (
1585 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1586 cur_test_run.request_interval * i),
1587 request_peers,
1588 pending_req);
1589 GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_req_head,
1590 rps_peer->pending_req_tail,
1591 pending_req);
1592 rps_peer->num_pending_reqs++;
1593 }
1594}
1595
1596
1597void
1598cancel_pending_req_rep (struct RPSPeer *rps_peer)
1599{
1600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1601 "Cancelling all (pending) requests.\n");
1602 while (NULL != rps_peer->pending_req_head)
1603 cancel_pending_req (rps_peer->pending_req_head);
1604 GNUNET_assert (0 == rps_peer->num_pending_reqs);
1605 while (NULL != rps_peer->pending_rep_head)
1606 cancel_request (rps_peer->pending_rep_head);
1607 GNUNET_assert (0 == rps_peer->num_pending_reps);
1608}
1609
1610
1611/***********************************
1612* MALICIOUS
1613***********************************/
1614
1615///**
1616// * Initialise only non-mal RPSPeers
1617// */
1618//static void
1619//mal_init_peer (struct RPSPeer *rps_peer)
1620//{
1621// if (rps_peer->index >= round (portion * num_peers))
1622// rps_peer->num_ids_to_request = 1;
1623//}
1624
1625
1626///**
1627// * @brief Set peers to (non-)malicious before execution
1628// *
1629// * Of signature #PreTest
1630// *
1631// * @param rps_peer the peer to set (non-) malicious
1632// * @param h the handle to the service
1633// */
1634//static void
1635//mal_pre (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
1636//{
1637// #if ENABLE_MALICIOUS
1638// uint32_t num_mal_peers;
1639//
1640// GNUNET_assert ((1 >= portion) &&
1641// (0 < portion));
1642// num_mal_peers = round (portion * num_peers);
1643//
1644// if (rps_peer->index < num_mal_peers)
1645// {
1646// GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1647// "%u. peer [%s] of %" PRIu32
1648// " malicious peers turning malicious\n",
1649// rps_peer->index,
1650// GNUNET_i2s (rps_peer->peer_id),
1651// num_mal_peers);
1652//
1653// GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers,
1654// rps_peer_ids, target_peer);
1655// }
1656// #endif /* ENABLE_MALICIOUS */
1657//}
1658
1659
1660// static void
1661// mal_cb (struct RPSPeer *rps_peer)
1662// {
1663// if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1664// {
1665// return;
1666// }
1667//
1668// #if ENABLE_MALICIOUS
1669// uint32_t num_mal_peers;
1670//
1671// GNUNET_assert ((1 >= portion) &&
1672// (0 < portion));
1673// num_mal_peers = round (portion * num_peers);
1674//
1675// if (rps_peer->index >= num_mal_peers)
1676// { /* It's useless to ask a malicious peer about a random sample -
1677// it's not sampling */
1678// GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
1679// GNUNET_TIME_UNIT_SECONDS, 2),
1680// seed_peers, rps_peer);
1681// schedule_missing_requests (rps_peer);
1682// }
1683// #endif /* ENABLE_MALICIOUS */
1684// }
1685
1686
1687/***********************************
1688* CHURN
1689***********************************/
1690
1691static void
1692churn (void *cls);
1693
1694
1695/***********************************
1696* PROFILER
1697***********************************/
1698
1699/**
1700 * Callback to be called when RPS service is started or stopped at peers
1701 *
1702 * @param cls NULL
1703 * @param op the operation handle
1704 * @param emsg NULL on success; otherwise an error description
1705 */
1706static void
1707churn_cb (void *cls,
1708 struct GNUNET_TESTBED_Operation *op,
1709 const char *emsg)
1710{
1711 // FIXME
1712 struct OpListEntry *entry = cls;
1713
1714 (void) op;
1715
1716 if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1717 {
1718 return;
1719 }
1720
1721 GNUNET_TESTBED_operation_done (entry->op);
1722 if (NULL != emsg)
1723 {
1724 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1725 "Failed to start/stop RPS at a peer\n");
1726 GNUNET_SCHEDULER_shutdown ();
1727 return;
1728 }
1729 GNUNET_assert (0 != entry->delta);
1730
1731 num_peers_online += entry->delta;
1732
1733 if (PEER_GO_OFFLINE == entry->delta)
1734 { /* Peer hopefully just went offline */
1735 if (GNUNET_YES != rps_peers[entry->index].online)
1736 {
1737 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1738 "peer %s was expected to go offline but is still marked as online\n",
1739 GNUNET_i2s (rps_peers[entry->index].peer_id));
1740 GNUNET_break (0);
1741 }
1742 else
1743 {
1744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1745 "peer %s probably went offline as expected\n",
1746 GNUNET_i2s (rps_peers[entry->index].peer_id));
1747 }
1748 rps_peers[entry->index].online = GNUNET_NO;
1749 }
1750
1751 else if (PEER_GO_ONLINE < entry->delta)
1752 { /* Peer hopefully just went online */
1753 if (GNUNET_NO != rps_peers[entry->index].online)
1754 {
1755 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1756 "peer %s was expected to go online but is still marked as offline\n",
1757 GNUNET_i2s (rps_peers[entry->index].peer_id));
1758 GNUNET_break (0);
1759 }
1760 else
1761 {
1762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1763 "peer %s probably went online as expected\n",
1764 GNUNET_i2s (rps_peers[entry->index].peer_id));
1765 if (NULL != cur_test_run.pre_test)
1766 {
1767 cur_test_run.pre_test (&rps_peers[entry->index],
1768 rps_peers[entry->index].rps_handle);
1769 schedule_missing_requests (&rps_peers[entry->index]);
1770 }
1771 }
1772 rps_peers[entry->index].online = GNUNET_YES;
1773 }
1774 else
1775 {
1776 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1777 "Invalid value for delta: %i\n", entry->delta);
1778 GNUNET_break (0);
1779 }
1780
1781 GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1782 rps_peers[entry->index].entry_op_manage = NULL;
1783 GNUNET_free (entry);
1784 // if (num_peers_in_round[current_round] == peers_running)
1785 // run_round ();
1786}
1787
1788
1789/**
1790 * @brief Set the rps-service up or down for a specific peer
1791 *
1792 * @param i index of action
1793 * @param j index of peer
1794 * @param delta (#PEER_ONLINE_DELTA) down (-1) or up (1)
1795 * @param prob_go_on_off the probability of the action
1796 */
1797static void
1798manage_service_wrapper (unsigned int i, unsigned int j,
1799 enum PEER_ONLINE_DELTA delta,
1800 double prob_go_on_off)
1801{
1802 struct OpListEntry *entry = NULL;
1803 uint32_t prob;
1804
1805 /* make sure that management operation is not already scheduled */
1806 if (NULL != rps_peers[j].entry_op_manage)
1807 {
1808 return;
1809 }
1810
1811 prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1812 UINT32_MAX);
1813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1814 "%u. selected peer (%u: %s) is %s.\n",
1815 i,
1816 j,
1817 GNUNET_i2s (rps_peers[j].peer_id),
1818 (PEER_GO_ONLINE == delta) ? "online" : "offline");
1819 if (prob < prob_go_on_off * UINT32_MAX)
1820 {
1821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1822 "%s goes %s\n",
1823 GNUNET_i2s (rps_peers[j].peer_id),
1824 (PEER_GO_OFFLINE == delta) ? "offline" : "online");
1825
1826 if (PEER_GO_OFFLINE == delta)
1827 cancel_pending_req_rep (&rps_peers[j]);
1828 entry = make_oplist_entry ();
1829 entry->delta = delta;
1830 entry->index = j;
1831 entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
1832 testbed_peers[j],
1833 "rps",
1834 &churn_cb,
1835 entry,
1836 (PEER_GO_OFFLINE == delta) ?
1837 0 : 1);
1838 rps_peers[j].entry_op_manage = entry;
1839 }
1840}
1841
1842
1843static void
1844churn (void *cls)
1845{
1846 unsigned int i;
1847 unsigned int j;
1848 double portion_online;
1849 unsigned int *permut;
1850 double prob_go_offline;
1851 double portion_go_online;
1852 double portion_go_offline;
1853
1854 (void) cls;
1855
1856 if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1857 {
1858 return;
1859 }
1860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1861 "Churn function executing\n");
1862
1863 churn_task = NULL; /* Should be invalid by now */
1864
1865 /* Compute the probability for an online peer to go offline
1866 * this round */
1867 portion_online = num_peers_online * 1.0 / num_peers;
1868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1869 "Portion online: %f\n",
1870 portion_online);
1871 portion_go_online = ((1 - portion_online) * .5 * .66);
1872 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1873 "Portion that should go online: %f\n",
1874 portion_go_online);
1875 portion_go_offline = (portion_online + portion_go_online) - .75;
1876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1877 "Portion that probably goes offline: %f\n",
1878 portion_go_offline);
1879 prob_go_offline = portion_go_offline / (portion_online * .5);
1880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1881 "Probability of a selected online peer to go offline: %f\n",
1882 prob_go_offline);
1883
1884 permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
1885 (unsigned int) num_peers);
1886
1887 /* Go over 50% randomly chosen peers */
1888 for (i = 0; i < .5 * num_peers; i++)
1889 {
1890 j = permut[i];
1891
1892 /* If online, shut down with certain probability */
1893 if (GNUNET_YES == rps_peers[j].online)
1894 {
1895 manage_service_wrapper (i, j, -1, prob_go_offline);
1896 }
1897
1898 /* If offline, restart with certain probability */
1899 else if (GNUNET_NO == rps_peers[j].online)
1900 {
1901 manage_service_wrapper (i, j, 1, 0.66);
1902 }
1903 }
1904
1905 GNUNET_free (permut);
1906
1907 churn_task = GNUNET_SCHEDULER_add_delayed (
1908 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1909 churn,
1910 NULL);
1911}
1912
1913
1914/**
1915 * Initialise given RPSPeer
1916 */
1917static void
1918profiler_init_peer (struct RPSPeer *rps_peer)
1919{
1920 rps_peer->num_ids_to_request = cur_test_run.num_requests;
1921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer shall request %i peers\n",
1922 rps_peer->num_ids_to_request);
1923}
1924
1925
1926/**
1927 * Callback to call on receipt of a reply
1928 *
1929 * @param cls closure
1930 * @param n number of peers
1931 * @param recv_peers the received peers
1932 */
1933static void
1934profiler_reply_handle (void *cls,
1935 uint64_t n,
1936 const struct GNUNET_PeerIdentity *recv_peers)
1937{
1938 struct RPSPeer *rps_peer;
1939 struct RPSPeer *rcv_rps_peer;
1940 char file_name_buf[128];
1941 char file_name_dh_buf[128];
1942 char file_name_dhr_buf[128];
1943 char file_name_dhru_buf[128];
1944 char *file_name = file_name_buf;
1945 char *file_name_dh = file_name_dh_buf;
1946 char *file_name_dhr = file_name_dhr_buf;
1947 char *file_name_dhru = file_name_dhru_buf;
1948 unsigned int i;
1949 struct PendingReply *pending_rep = (struct PendingReply *) cls;
1950
1951 pending_rep->req_handle = NULL;
1952 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "profiler_reply_handle()\n");
1953 rps_peer = pending_rep->rps_peer;
1954 (void) GNUNET_asprintf (&file_name,
1955 "/tmp/rps/received_ids-%u",
1956 rps_peer->index);
1957
1958 (void) GNUNET_asprintf (&file_name_dh,
1959 "/tmp/rps/diehard_input-%u",
1960 rps_peer->index);
1961 (void) GNUNET_asprintf (&file_name_dhr,
1962 "/tmp/rps/diehard_input_raw-%u",
1963 rps_peer->index);
1964 (void) GNUNET_asprintf (&file_name_dhru,
1965 "/tmp/rps/diehard_input_raw_aligned-%u",
1966 rps_peer->index);
1967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1968 "[%s] got %" PRIu64 " peers:\n",
1969 GNUNET_i2s (rps_peer->peer_id),
1970 n);
1971 for (i = 0; i < n; i++)
1972 {
1973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1974 "%u: %s\n",
1975 i,
1976 GNUNET_i2s (&recv_peers[i]));
1977 tofile (file_name,
1978 "%s\n",
1979 GNUNET_i2s_full (&recv_peers[i]));
1980 rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, &recv_peers[i]);
1981 GNUNET_assert (NULL != rcv_rps_peer);
1982 tofile (file_name_dh,
1983 "%" PRIu32 "\n",
1984 (uint32_t) rcv_rps_peer->index);
1985#ifdef TO_FILE
1986 to_file_raw (file_name_dhr,
1987 (char *) &rcv_rps_peer->index,
1988 sizeof(uint32_t));
1989 to_file_raw_unaligned (file_name_dhru,
1990 (char *) &rcv_rps_peer->index,
1991 sizeof(uint32_t),
1992 bits_needed);
1993#endif /* TO_FILE */
1994 }
1995 default_reply_handle (cls, n, recv_peers);
1996}
1997
1998
1999/**
2000 * Callback to call on receipt of a reply
2001 *
2002 * @param cls closure
2003 * @param n number of peers
2004 * @param recv_peers the received peers
2005 */
2006static void
2007profiler_reply_handle_info (void *cls,
2008 const struct GNUNET_PeerIdentity *recv_peer,
2009 double probability,
2010 uint32_t num_observed)
2011{
2012 struct RPSPeer *rps_peer;
2013 struct RPSPeer *rcv_rps_peer;
2014 char file_name_buf[128];
2015 char file_name_dh_buf[128];
2016 char file_name_dhr_buf[128];
2017 char file_name_dhru_buf[128];
2018 char *file_name = file_name_buf;
2019 char *file_name_dh = file_name_dh_buf;
2020 char *file_name_dhr = file_name_dhr_buf;
2021 char *file_name_dhru = file_name_dhru_buf;
2022 struct PendingReply *pending_rep = (struct PendingReply *) cls;
2023
2024 pending_rep->req_handle = NULL;
2025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "profiler_reply_handle()\n");
2026 rps_peer = pending_rep->rps_peer;
2027 (void) GNUNET_asprintf (&file_name,
2028 "/tmp/rps/received_ids-%u",
2029 rps_peer->index);
2030
2031 (void) GNUNET_asprintf (&file_name_dh,
2032 "/tmp/rps/diehard_input-%u",
2033 rps_peer->index);
2034 (void) GNUNET_asprintf (&file_name_dhr,
2035 "/tmp/rps/diehard_input_raw-%u",
2036 rps_peer->index);
2037 (void) GNUNET_asprintf (&file_name_dhru,
2038 "/tmp/rps/diehard_input_raw_aligned-%u",
2039 rps_peer->index);
2040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2041 "[%s] got peer with info:\n",
2042 GNUNET_i2s (rps_peer->peer_id));
2043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2044 " %s\n",
2045 GNUNET_i2s (recv_peer));
2046 tofile (file_name,
2047 "%s %f %" PRIu32 " \n",
2048 GNUNET_i2s_full (recv_peer),
2049 probability,
2050 num_observed);
2051 rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, recv_peer);
2052 GNUNET_assert (NULL != rcv_rps_peer);
2053 tofile (file_name_dh,
2054 "%" PRIu32 "\n",
2055 (uint32_t) rcv_rps_peer->index);
2056#ifdef TO_FILE
2057 to_file_raw (file_name_dhr,
2058 (char *) &rcv_rps_peer->index,
2059 sizeof(uint32_t));
2060 to_file_raw_unaligned (file_name_dhru,
2061 (char *) &rcv_rps_peer->index,
2062 sizeof(uint32_t),
2063 bits_needed);
2064#endif /* TO_FILE */
2065 default_reply_handle (cls, 1, recv_peer);
2066}
2067
2068
2069static void
2070profiler_cb (struct RPSPeer *rps_peer)
2071{
2072 if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
2073 {
2074 return;
2075 }
2076
2077 /* Start churn */
2078 if ((HAVE_CHURN == cur_test_run.have_churn) && (NULL == churn_task))
2079 {
2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2081 "Starting churn task\n");
2082 churn_task = GNUNET_SCHEDULER_add_delayed (
2083 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
2084 churn,
2085 NULL);
2086 }
2087 else
2088 {
2089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2090 "Not starting churn task\n");
2091 }
2092
2093 /* Only request peer ids at one peer.
2094 * (It's the before-last because last one is target of the focused attack.)
2095 */
2096 if (0 < rps_peer->num_ids_to_request)
2097 schedule_missing_requests (rps_peer);
2098}
2099
2100
2101/**
2102 * Function called from #profiler_eval with a filename.
2103 *
2104 * @param cls closure
2105 * @param filename complete filename (absolute path)
2106 * @return #GNUNET_OK to continue to iterate,
2107 * #GNUNET_NO to stop iteration with no error,
2108 * #GNUNET_SYSERR to abort iteration with error!
2109 */
2110static int
2111file_name_cb (void *cls, const char *filename)
2112{
2113 if (NULL != strstr (filename, "sampler_el"))
2114 {
2115 struct RPS_SamplerElement *s_elem;
2116 struct GNUNET_CRYPTO_AuthKey auth_key;
2117 const char *key_char;
2118 uint32_t i;
2119 (void) cls;
2120
2121 key_char = filename + 20; /* Length of "/tmp/rps/sampler_el-" */
2122 tofile (filename, "--------------------------\n");
2123
2124 auth_key = string_to_auth_key (key_char);
2125 s_elem = RPS_sampler_elem_create ();
2126 RPS_sampler_elem_set (s_elem, auth_key);
2127
2128 for (i = 0; i < num_peers; i++)
2129 {
2130 RPS_sampler_elem_next (s_elem, &rps_peer_ids[i]);
2131 }
2132 RPS_sampler_elem_destroy (s_elem);
2133 }
2134 return GNUNET_OK;
2135}
2136
2137
2138/**
2139 * This is run after the test finished.
2140 *
2141 * Compute all perfect samples.
2142 */
2143static int
2144profiler_eval (void)
2145{
2146#ifdef TO_FILE
2147 /* Compute perfect sample for each sampler element */
2148 if (-1 == GNUNET_DISK_directory_scan ("/tmp/rps/", file_name_cb, NULL))
2149 {
2150 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scan of directory failed\n");
2151 }
2152#endif /* TO_FILE */
2153
2154 return evaluate ();
2155}
2156
2157
2158/** @brief is b in view of a?
2159 *
2160 * @param a
2161 * @param b
2162 *
2163 * @return
2164 */
2165static int
2166is_in_view (uint32_t a, uint32_t b)
2167{
2168 uint32_t i;
2169
2170 for (i = 0; i < rps_peers[a].cur_view_count; i++)
2171 {
2172 if (0 == memcmp (rps_peers[b].peer_id,
2173 &rps_peers[a].cur_view[i],
2174 sizeof(struct GNUNET_PeerIdentity)))
2175 {
2176 return GNUNET_YES;
2177 }
2178 }
2179 return GNUNET_NO;
2180}
2181
2182
2183static uint32_t
2184get_idx_of_pid (const struct GNUNET_PeerIdentity *pid)
2185{
2186 uint32_t i;
2187
2188 for (i = 0; i < num_peers; i++)
2189 {
2190 if (0 == memcmp (pid,
2191 rps_peers[i].peer_id,
2192 sizeof(struct GNUNET_PeerIdentity)))
2193 {
2194 return i;
2195 }
2196 }
2197 // return 0; /* Should not happen - make compiler happy */
2198 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2199 "No known _PeerIdentity %s!\n",
2200 GNUNET_i2s_full (pid));
2201 GNUNET_assert (0);
2202}
2203
2204
2205/**
2206 * @brief Counts number of peers in view of a that have b in their view
2207 *
2208 * @param a
2209 * @param uint32_tb
2210 *
2211 * @return
2212 */
2213static uint32_t
2214count_containing_views (uint32_t a, uint32_t b)
2215{
2216 uint32_t i;
2217 uint32_t peer_idx;
2218 uint32_t count = 0;
2219
2220 for (i = 0; i < rps_peers[a].cur_view_count; i++)
2221 {
2222 peer_idx = get_idx_of_pid (&rps_peers[a].cur_view[i]);
2223 if (GNUNET_YES == is_in_view (peer_idx, b))
2224 {
2225 count++;
2226 }
2227 }
2228 return count;
2229}
2230
2231
2232/**
2233 * @brief Computes the probability for each other peer to be selected by the
2234 * sampling process based on the views of all peers
2235 *
2236 * @param peer_idx index of the peer that is about to sample
2237 */
2238static void
2239compute_probabilities (uint32_t peer_idx)
2240{
2241 // double probs[num_peers] = { 0 };
2242 double probs[num_peers];
2243 double probs_hist[num_peers]; /* Probability respecting the history */
2244 size_t probs_as_str_size = (num_peers * 10 + 2) * sizeof(char);
2245 char *probs_as_str = GNUNET_malloc (probs_as_str_size);
2246 char *probs_as_str_cpy;
2247 uint32_t i;
2248 double prob_push;
2249 double prob_pull;
2250 uint32_t view_size;
2251 uint32_t cont_views;
2252 uint32_t number_of_being_in_pull_events;
2253 int tmp;
2254 double sum_non_zero_prob = 0;
2255 double sum_non_zero_prob_hist = 0;
2256
2257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2258 "Computing probabilities for peer %" PRIu32 "\n", peer_idx);
2259 /* Firstly without knowledge of old views */
2260 for (i = 0; i < num_peers; i++)
2261 {
2262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2263 "\tfor peer %" PRIu32 ":\n", i);
2264 view_size = rps_peers[i].cur_view_count;
2265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2266 "\t\tview_size: %" PRIu32 "\n", view_size);
2267 /* For peer i the probability of being sampled is
2268 * evenly distributed among all possibly observed peers. */
2269 /* We could have observed a peer in three cases:
2270 * 1. peer sent a push
2271 * 2. peer was contained in a pull reply
2272 * 3. peer was in history (sampler) - ignored for now */
2273 /* 1. Probability of having received a push from peer i */
2274 if ((GNUNET_YES == is_in_view (i, peer_idx)) &&
2275 (1 <= (0.45 * view_size)))
2276 {
2277 if (0 == binom (view_size, 0.45 * view_size))
2278 prob_push = 0;
2279 else
2280 {
2281 prob_push = 1.0 * binom (0.45 * view_size, 1)
2282 /
2283 binom (view_size, 0.45 * view_size);
2284 }
2285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2286 "\t\t%" PRIu32 " is in %" PRIu32 "'s view, prob: %f\n",
2287 peer_idx,
2288 i,
2289 prob_push);
2290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2291 "\t\tposs choices from view: %" PRIu32 ", containing i: %"
2292 PRIu32 "\n",
2293 binom (view_size, 0.45 * view_size),
2294 binom (0.45 * view_size, 1));
2295 }
2296 else
2297 {
2298 prob_push = 0;
2299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2300 "\t\t%" PRIu32 " is not in %" PRIu32 "'s view, prob: 0\n",
2301 peer_idx,
2302 i);
2303 }
2304 /* 2. Probability of peer i being contained in pulls */
2305 view_size = rps_peers[peer_idx].cur_view_count;
2306 cont_views = count_containing_views (peer_idx, i);
2307 number_of_being_in_pull_events =
2308 (binom (view_size, 0.45 * view_size)
2309 - binom (view_size - cont_views, 0.45 * view_size));
2310 if (0 != number_of_being_in_pull_events)
2311 {
2312 prob_pull = number_of_being_in_pull_events
2313 /
2314 (1.0 * binom (view_size, 0.45 * view_size));
2315 }
2316 else
2317 {
2318 prob_pull = 0;
2319 }
2320 probs[i] = prob_push + prob_pull - (prob_push * prob_pull);
2321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2322 "\t\t%" PRIu32 " has %" PRIu32 " of %" PRIu32
2323 " peers in its view who know %" PRIu32 " prob: %f\n",
2324 peer_idx,
2325 cont_views,
2326 view_size,
2327 i,
2328 prob_pull);
2329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2330 "\t\tnumber of possible pull combinations: %" PRIu32 "\n",
2331 binom (view_size, 0.45 * view_size));
2332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2333 "\t\tnumber of possible pull combinations without %" PRIu32
2334 ": %" PRIu32 "\n",
2335 i,
2336 binom (view_size - cont_views, 0.45 * view_size));
2337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2338 "\t\tnumber of possible pull combinations with %" PRIu32
2339 ": %" PRIu32 "\n",
2340 i,
2341 number_of_being_in_pull_events);
2342
2343 probs_hist[i] = 0.9 * rps_peers[peer_idx].eval_probs_cache[i] + probs[i];
2344 rps_peers[peer_idx].eval_probs_cache[i] = probs_hist[i];
2345
2346 sum_non_zero_prob += probs[i];
2347 sum_non_zero_prob_hist += probs_hist[i];
2348 }
2349 /* normalize */
2350 if (0 != sum_non_zero_prob)
2351 {
2352 for (i = 0; i < num_peers; i++)
2353 {
2354 probs[i] = probs[i] * (1.0 / sum_non_zero_prob);
2355 }
2356 }
2357 if (0 != sum_non_zero_prob_hist)
2358 {
2359 for (i = 0; i < num_peers; i++)
2360 {
2361 probs_hist[i] = probs_hist[i] * (1.0 / sum_non_zero_prob_hist);
2362 }
2363 }
2364
2365 /* str repr */
2366 for (i = 0; i < num_peers; i++)
2367 {
2368 probs_as_str_cpy = GNUNET_strndup (probs_as_str, probs_as_str_size);
2369 tmp = GNUNET_snprintf (probs_as_str,
2370 probs_as_str_size,
2371 "%s %7.6f", probs_as_str_cpy, probs[i]);
2372 GNUNET_free (probs_as_str_cpy);
2373 GNUNET_assert (0 <= tmp);
2374 }
2375
2376 to_file_w_len (rps_peers[peer_idx].file_name_probs,
2377 probs_as_str_size,
2378 "%s",
2379 probs_as_str);
2380
2381 probs_as_str[0] = '\0';
2382 for (i = 0; i < num_peers; i++)
2383 {
2384 probs_as_str_cpy = GNUNET_strndup (probs_as_str, probs_as_str_size);
2385 tmp = GNUNET_snprintf (probs_as_str,
2386 probs_as_str_size,
2387 "%s %7.6f", probs_as_str_cpy, probs_hist[i]);
2388 GNUNET_free (probs_as_str_cpy);
2389 GNUNET_assert (0 <= tmp);
2390 }
2391
2392 to_file_w_len (rps_peers[peer_idx].file_name_probs_hist,
2393 probs_as_str_size,
2394 "%s",
2395 probs_as_str);
2396 GNUNET_free (probs_as_str);
2397}
2398
2399
2400/**
2401 * @brief This counts the number of peers in which views a given peer occurs.
2402 *
2403 * It also stores this value in the rps peer.
2404 *
2405 * @param peer_idx the index of the peer to count the representation
2406 *
2407 * @return the number of occurrences
2408 */
2409static uint32_t
2410count_peer_in_views_2 (uint32_t peer_idx)
2411{
2412 uint32_t i, j;
2413 uint32_t count = 0;
2414
2415 for (i = 0; i < num_peers; i++) /* Peer in which view is counted */
2416 {
2417 for (j = 0; j < rps_peers[i].cur_view_count; j++) /* entry in view */
2418 {
2419 if (0 == memcmp (rps_peers[peer_idx].peer_id,
2420 &rps_peers[i].cur_view[j],
2421 sizeof(struct GNUNET_PeerIdentity)))
2422 {
2423 count++;
2424 break;
2425 }
2426 }
2427 }
2428 rps_peers[peer_idx].count_in_views = count;
2429 return count;
2430}
2431
2432
2433static uint32_t
2434cumulated_view_sizes ()
2435{
2436 uint32_t i;
2437
2438 view_sizes = 0;
2439 for (i = 0; i < num_peers; i++) /* Peer in which view is counted */
2440 {
2441 view_sizes += rps_peers[i].cur_view_count;
2442 }
2443 return view_sizes;
2444}
2445
2446
2447static void
2448count_peer_in_views (uint32_t *count_peers)
2449{
2450 uint32_t i, j;
2451
2452 for (i = 0; i < num_peers; i++) /* Peer in which view is counted */
2453 {
2454 for (j = 0; j < rps_peers[i].cur_view_count; j++) /* entry in view */
2455 {
2456 if (0 == memcmp (rps_peers[i].peer_id,
2457 &rps_peers[i].cur_view[j],
2458 sizeof(struct GNUNET_PeerIdentity)))
2459 {
2460 count_peers[i]++;
2461 }
2462 }
2463 }
2464}
2465
2466
2467void
2468compute_diversity ()
2469{
2470 uint32_t i;
2471 /* ith entry represents the number of occurrences in other peer's views */
2472 uint32_t *count_peers = GNUNET_new_array (num_peers, uint32_t);
2473 uint32_t views_total_size;
2474 double expected;
2475 /* deviation from expected number of peers */
2476 double *deviation = GNUNET_new_array (num_peers, double);
2477
2478 views_total_size = 0;
2479 expected = 0;
2480
2481 /* For each peer count its representation in other peer's views*/
2482 for (i = 0; i < num_peers; i++) /* Peer to count */
2483 {
2484 views_total_size += rps_peers[i].cur_view_count;
2485 count_peer_in_views (count_peers);
2486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2487 "Counted representation of %" PRIu32 "th peer [%s]: %" PRIu32
2488 "\n",
2489 i,
2490 GNUNET_i2s (rps_peers[i].peer_id),
2491 count_peers[i]);
2492 }
2493
2494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2495 "size of all views combined: %" PRIu32 "\n",
2496 views_total_size);
2497 expected = ((double) 1 / num_peers) * views_total_size;
2498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2499 "Expected number of occurrences of each peer in all views: %f\n",
2500 expected);
2501 for (i = 0; i < num_peers; i++) /* Peer to count */
2502 {
2503 deviation[i] = expected - count_peers[i];
2504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2505 "Deviation from expectation: %f\n", deviation[i]);
2506 }
2507 GNUNET_free (count_peers);
2508 GNUNET_free (deviation);
2509}
2510
2511
2512void
2513print_view_sizes ()
2514{
2515 uint32_t i;
2516
2517 for (i = 0; i < num_peers; i++) /* Peer to count */
2518 {
2519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2520 "View size of %" PRIu32 ". [%s] is %" PRIu32 "\n",
2521 i,
2522 GNUNET_i2s (rps_peers[i].peer_id),
2523 rps_peers[i].cur_view_count);
2524 }
2525}
2526
2527
2528void
2529all_views_updated_cb ()
2530{
2531 compute_diversity ();
2532 print_view_sizes ();
2533}
2534
2535
2536void
2537view_update_cb (void *cls,
2538 uint64_t view_size,
2539 const struct GNUNET_PeerIdentity *peers)
2540{
2541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2542 "View was updated (%" PRIu64 ")\n", view_size);
2543 struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
2544 to_file ("/tmp/rps/view_sizes.txt",
2545 "%" PRIu32 " %" PRIu64 "",
2546 rps_peer->index,
2547 view_size);
2548 for (uint64_t i = 0; i < view_size; i++)
2549 {
2550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2551 "\t%s\n", GNUNET_i2s (&peers[i]));
2552 }
2553 GNUNET_array_grow (rps_peer->cur_view,
2554 rps_peer->cur_view_count,
2555 view_size);
2556 // *rps_peer->cur_view = *peers;
2557 GNUNET_memcpy (rps_peer->cur_view,
2558 peers,
2559 view_size * sizeof(struct GNUNET_PeerIdentity));
2560 to_file ("/tmp/rps/count_in_views.txt",
2561 "%" PRIu32 " %" PRIu32 "",
2562 rps_peer->index,
2563 count_peer_in_views_2 (rps_peer->index));
2564 cumulated_view_sizes ();
2565 if (0 != view_size)
2566 {
2567 to_file ("/tmp/rps/repr.txt",
2568 "%" PRIu32 /* index */
2569 " %" PRIu32 /* occurrence in views */
2570 " %" PRIu32 /* view sizes */
2571 " %f" /* fraction of repr in views */
2572 " %f" /* average view size */
2573 " %f" /* prob of occurrence in view slot */
2574 " %f" "", /* exp frac of repr in views */
2575 rps_peer->index,
2576 count_peer_in_views_2 (rps_peer->index),
2577 view_sizes,
2578 count_peer_in_views_2 (rps_peer->index) / (view_size * 1.0), /* fraction of representation in views */
2579 view_sizes / (view_size * 1.0), /* average view size */
2580 1.0 / view_size, /* prob of occurrence in view slot */
2581 (1.0 / view_size) * (view_sizes / view_size) /* expected fraction of repr in views */
2582 );
2583 }
2584 compute_probabilities (rps_peer->index);
2585 all_views_updated_cb ();
2586}
2587
2588
2589static void
2590pre_profiler (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
2591{
2592 rps_peer->file_name_probs =
2593 store_prefix_file_name (rps_peer->index, "probs");
2594 rps_peer->file_name_probs_hist =
2595 store_prefix_file_name (rps_peer->index, "probs_hist");
2596 rps_peer->eval_probs_cache = GNUNET_new_array (num_peers, double);
2597 memset (rps_peer->eval_probs_cache, 0, num_peers * sizeof (double));
2598 GNUNET_RPS_view_request (h, 0, view_update_cb, rps_peer);
2599}
2600
2601void
2602write_final_stats (void)
2603{
2604 uint64_t sums[STAT_TYPE_MAX] = { 0 };
2605
2606 for (uint32_t i = 0; i < num_peers; i++)
2607 {
2608 to_file ("/tmp/rps/final_stats.csv",
2609 "%" PRIu32 ", " /* index */
2610 "%s, %" /* id */
2611 PRIu64 ", %" /* rounds */
2612 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %"
2613 PRIu64 ", %" /* blocking */
2614 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* issued */
2615 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* sent */
2616 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %"
2617 PRIu64 ", %" /* recv */
2618 PRIu64 ", %" /* view size */
2619 PRIu64 ", %" /* known peers */
2620 PRIu64 ", %" /* valid peers */
2621 PRIu64 ", %" /* learned peers */
2622 PRIu64 ", %" /* pending online checks */
2623 PRIu64 ", %" /* unrequested pull replies */
2624 PRIu64 ", %" /* peers in push map */
2625 PRIu64 ", %" /* peers in pull map */
2626 PRIu64 ", %" /* peers in view */
2627 PRIu64 "\n" /* view size aim */,
2628 i,
2629 GNUNET_i2s (rps_peers[i].peer_id),
2630 rps_peers[i].stats[STAT_TYPE_ROUNDS],
2631 rps_peers[i].stats[STAT_TYPE_BLOCKS],
2632 rps_peers[i].stats[STAT_TYPE_BLOCKS_MANY_PUSH],
2633 rps_peers[i].stats[STAT_TYPE_BLOCKS_NO_PUSH],
2634 rps_peers[i].stats[STAT_TYPE_BLOCKS_NO_PULL],
2635 rps_peers[i].stats[STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL],
2636 rps_peers[i].stats[STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL],
2637 rps_peers[i].stats[STAT_TYPE_ISSUED_PUSH_SEND],
2638 rps_peers[i].stats[STAT_TYPE_ISSUED_PUSH_SEND_MH],
2639 rps_peers[i].stats[STAT_TYPE_ISSUED_PULL_REQ],
2640 rps_peers[i].stats[STAT_TYPE_ISSUED_PULL_REQ_MH],
2641 rps_peers[i].stats[STAT_TYPE_ISSUED_PULL_REP],
2642 rps_peers[i].stats[STAT_TYPE_SENT_PUSH_SEND],
2643 rps_peers[i].stats[STAT_TYPE_SENT_PULL_REQ],
2644 rps_peers[i].stats[STAT_TYPE_SENT_PULL_REQ_MH],
2645 rps_peers[i].stats[STAT_TYPE_SENT_PULL_REP],
2646 rps_peers[i].stats[STAT_TYPE_RECV_PUSH_SEND],
2647 rps_peers[i].stats[STAT_TYPE_RECV_PUSH_SEND_MH],
2648 rps_peers[i].stats[STAT_TYPE_RECV_PULL_REQ],
2649 rps_peers[i].stats[STAT_TYPE_RECV_PULL_REQ_MH],
2650 rps_peers[i].stats[STAT_TYPE_RECV_PULL_REP_MH],
2651 rps_peers[i].stats[STAT_TYPE_RECV_PULL_REP],
2652 rps_peers[i].stats[STAT_TYPE_VIEW_SIZE],
2653 rps_peers[i].stats[STAT_TYPE_KNOWN_PEERS],
2654 rps_peers[i].stats[STAT_TYPE_VALID_PEERS],
2655 rps_peers[i].stats[STAT_TYPE_LEARND_PEERS],
2656 rps_peers[i].stats[STAT_TYPE_PENDING_ONLINE_CHECKS],
2657 rps_peers[i].stats[STAT_TYPE_UNREQUESTED_PULL_REPLIES],
2658 rps_peers[i].stats[STAT_TYPE_PEERS_IN_PUSH_MAP],
2659 rps_peers[i].stats[STAT_TYPE_PEERS_IN_PULL_MAP],
2660 rps_peers[i].stats[STAT_TYPE_PEERS_IN_VIEW],
2661 rps_peers[i].stats[STAT_TYPE_VIEW_SIZE_AIM]);
2662 for (enum STAT_TYPE stat_type = STAT_TYPE_ROUNDS;
2663 stat_type < STAT_TYPE_MAX;
2664 stat_type++)
2665 {
2666 sums[stat_type] += rps_peers[i].stats[stat_type];
2667 }
2668 }
2669 to_file ("/tmp/rps/final_stats.dat",
2670 "SUM %"
2671 PRIu64 " %" /* rounds */
2672 PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
2673 " %" /* blocking */
2674 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* issued */
2675 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* sent */
2676 PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %"
2677 PRIu64 ", %" /* recv */
2678 PRIu64 ", %" /* view size */
2679 PRIu64 ", %" /* known peers */
2680 PRIu64 ", %" /* valid peers */
2681 PRIu64 ", %" /* learned peers */
2682 PRIu64 ", %" /* pending online checks */
2683 PRIu64 ", %" /* unrequested pull replies */
2684 PRIu64 ", %" /* peers in push map */
2685 PRIu64 ", %" /* peers in pull map */
2686 PRIu64 ", %" /* peers in view */
2687 PRIu64 "\n" /* view size aim */,
2688 sums[STAT_TYPE_ROUNDS],
2689 sums[STAT_TYPE_BLOCKS],
2690 sums[STAT_TYPE_BLOCKS_MANY_PUSH],
2691 sums[STAT_TYPE_BLOCKS_NO_PUSH],
2692 sums[STAT_TYPE_BLOCKS_NO_PULL],
2693 sums[STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL],
2694 sums[STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL],
2695 sums[STAT_TYPE_ISSUED_PUSH_SEND],
2696 sums[STAT_TYPE_ISSUED_PUSH_SEND_MH],
2697 sums[STAT_TYPE_ISSUED_PULL_REQ],
2698 sums[STAT_TYPE_ISSUED_PULL_REQ_MH],
2699 sums[STAT_TYPE_ISSUED_PULL_REP],
2700 sums[STAT_TYPE_SENT_PUSH_SEND],
2701 sums[STAT_TYPE_SENT_PULL_REQ],
2702 sums[STAT_TYPE_SENT_PULL_REQ_MH],
2703 sums[STAT_TYPE_SENT_PULL_REP],
2704 sums[STAT_TYPE_RECV_PUSH_SEND],
2705 sums[STAT_TYPE_RECV_PUSH_SEND_MH],
2706 sums[STAT_TYPE_RECV_PULL_REQ],
2707 sums[STAT_TYPE_RECV_PULL_REQ_MH],
2708 sums[STAT_TYPE_RECV_PULL_REP],
2709 sums[STAT_TYPE_RECV_PULL_REP_MH],
2710 sums[STAT_TYPE_VIEW_SIZE],
2711 sums[STAT_TYPE_KNOWN_PEERS],
2712 sums[STAT_TYPE_VALID_PEERS],
2713 sums[STAT_TYPE_LEARND_PEERS],
2714 sums[STAT_TYPE_PENDING_ONLINE_CHECKS],
2715 sums[STAT_TYPE_UNREQUESTED_PULL_REPLIES],
2716 sums[STAT_TYPE_PEERS_IN_PUSH_MAP],
2717 sums[STAT_TYPE_PEERS_IN_PULL_MAP],
2718 sums[STAT_TYPE_PEERS_IN_VIEW],
2719 sums[STAT_TYPE_VIEW_SIZE_AIM]);
2720}
2721
2722
2723/**
2724 * Continuation called by #GNUNET_STATISTICS_get() functions.
2725 *
2726 * Remembers that this specific statistics value was received for this peer.
2727 * Checks whether all peers received their statistics yet.
2728 * Issues the shutdown.
2729 *
2730 * @param cls closure
2731 * @param success #GNUNET_OK if statistics were
2732 * successfully obtained, #GNUNET_SYSERR if not.
2733 */
2734void
2735post_test_shutdown_ready_cb (void *cls,
2736 int success)
2737{
2738 struct STATcls *stat_cls = (struct STATcls *) cls;
2739 struct RPSPeer *rps_peer = stat_cls->rps_peer;
2740
2741 rps_peer->h_stat_get[stat_cls->stat_type] = NULL;
2742 if (GNUNET_OK == success)
2743 {
2744 /* set flag that we we got the value */
2745 rps_peer->stat_collected_flags |= BIT (stat_cls->stat_type);
2746 }
2747 else
2748 {
2749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2750 "Peer %u did not receive statistics value\n",
2751 rps_peer->index);
2752 GNUNET_free (stat_cls);
2753 GNUNET_break (0);
2754 return;
2755 }
2756
2757 if ((NULL != rps_peer->stat_op) &&
2758 (GNUNET_YES == check_statistics_collect_completed_single_peer (
2759 rps_peer)) )
2760 {
2761 GNUNET_TESTBED_operation_done (rps_peer->stat_op);
2762 }
2763
2764 write_final_stats ();
2765 if (GNUNET_YES == check_statistics_collect_completed ())
2766 {
2767 // write_final_stats ();
2768 GNUNET_free (stat_cls);
2769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2770 "Shutting down\n");
2771 GNUNET_SCHEDULER_shutdown ();
2772 }
2773 else
2774 {
2775 GNUNET_free (stat_cls);
2776 }
2777}
2778
2779
2780/**
2781 * Callback function to process statistic values.
2782 *
2783 * @param cls closure
2784 * @param subsystem name of subsystem that created the statistic
2785 * @param name the name of the datum
2786 * @param value the current value
2787 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
2788 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
2789 */
2790int
2791stat_iterator (void *cls,
2792 const char *subsystem,
2793 const char *name,
2794 uint64_t value,
2795 int is_persistent)
2796{
2797 const struct STATcls *stat_cls = (const struct STATcls *) cls;
2798 struct RPSPeer *rps_peer = (struct RPSPeer *) stat_cls->rps_peer;
2799 enum STAT_TYPE stat_type;
2800
2801 (void) subsystem;
2802 (void) is_persistent;
2803
2804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2805 "Got stat value: %s - %" PRIu64 " (%u)\n",
2806 name,
2807 value,
2808 rps_peer->index);
2809 to_file (rps_peer->file_name_stats,
2810 "%s: %" PRIu64 "\n",
2811 name,
2812 value);
2813 stat_type = stat_str_2_type (name);
2814 GNUNET_assert (STAT_TYPE_ROUNDS <= stat_type &&
2815 STAT_TYPE_MAX > stat_type);
2816 rps_peer->stats[stat_type] = value;
2817 return GNUNET_OK;
2818}
2819
2820
2821void
2822post_profiler (struct RPSPeer *rps_peer)
2823{
2824 if (COLLECT_STATISTICS != cur_test_run.have_collect_statistics)
2825 {
2826 return;
2827 }
2828
2829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2830 "Going to request statistic values with mask 0x%" PRIx32 "\n",
2831 cur_test_run.stat_collect_flags);
2832
2833 struct STATcls *stat_cls;
2834 uint32_t stat_type;
2835 for (stat_type = STAT_TYPE_ROUNDS;
2836 stat_type < STAT_TYPE_MAX;
2837 stat_type++)
2838 {
2839 if (BIT (stat_type) & cur_test_run.stat_collect_flags)
2840 {
2841 stat_cls = GNUNET_malloc (sizeof(struct STATcls));
2842 stat_cls->rps_peer = rps_peer;
2843 stat_cls->stat_type = stat_type;
2844 rps_peer->file_name_stats =
2845 store_prefix_file_name (rps_peer->index, "stats");
2846 rps_peer->h_stat_get[stat_type] =
2847 GNUNET_STATISTICS_get (rps_peer->stats_h,
2848 "rps",
2849 stat_type_strings [stat_type],
2850 post_test_shutdown_ready_cb,
2851 stat_iterator,
2852 (struct STATcls *) stat_cls);
2853 GNUNET_assert (NULL != rps_peer->h_stat_get);
2854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2855 "Requested statistics for %s (peer %" PRIu32 ")\n",
2856 stat_type_strings [stat_type],
2857 rps_peer->index);
2858 }
2859 }
2860 GNUNET_free (rps_peer->eval_probs_cache);
2861}
2862
2863
2864/***********************************************************************
2865* /Definition of tests
2866***********************************************************************/
2867
2868
2869/**
2870 * Actual "main" function for the testcase.
2871 *
2872 * @param cls closure
2873 * @param h the run handle
2874 * @param n_peers number of peers in 'peers'
2875 * @param peers handle to peers run in the testbed
2876 * @param links_succeeded the number of overlay link connection attempts that
2877 * succeeded
2878 * @param links_failed the number of overlay link connection attempts that
2879 * failed
2880 */
2881static void
2882test_run (void *cls,
2883 struct GNUNET_TESTBED_RunHandle *h,
2884 unsigned int n_peers,
2885 struct GNUNET_TESTBED_Peer **peers,
2886 unsigned int links_succeeded,
2887 unsigned int links_failed)
2888{
2889 unsigned int i;
2890 struct OpListEntry *entry;
2891
2892 (void) cls;
2893 (void) h;
2894 (void) links_failed;
2895
2896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RUN was called\n");
2897
2898 /* Check whether we timed out */
2899 if ((n_peers != num_peers) ||
2900 (NULL == peers) ||
2901 (0 == links_succeeded) )
2902 {
2903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2904 "Going down due to args (eg. timeout)\n");
2905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tn_peers: %u\n", n_peers);
2906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tnum_peers: %" PRIu32 "\n",
2907 num_peers);
2908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tpeers: %p\n", peers);
2909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tlinks_succeeded: %u\n",
2910 links_succeeded);
2911 ok = 1;
2912 GNUNET_SCHEDULER_shutdown ();
2913 return;
2914 }
2915
2916
2917 /* Initialize peers */
2918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "going to initialise peers\n");
2919 testbed_peers = peers;
2920 num_peers_online = 0;
2921 for (i = 0; i < num_peers; i++)
2922 {
2923 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "initialising %u\n", i);
2924 entry = make_oplist_entry ();
2925 entry->index = i;
2926 rps_peers[i].index = i;
2927 if (NULL != cur_test_run.init_peer)
2928 cur_test_run.init_peer (&rps_peers[i]);
2929 if (NO_COLLECT_VIEW == cur_test_run.have_collect_view)
2930 {
2931 rps_peers->cur_view_count = 0;
2932 rps_peers->cur_view = NULL;
2933 }
2934 entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
2935 GNUNET_TESTBED_PIT_IDENTITY,
2936 &info_cb,
2937 entry);
2938 }
2939
2940 /* Bring peers up */
2941 GNUNET_assert (num_peers == n_peers);
2942 for (i = 0; i < n_peers; i++)
2943 {
2944 rps_peers[i].index = i;
2945 rps_peers[i].op =
2946 GNUNET_TESTBED_service_connect (&rps_peers[i],
2947 peers[i],
2948 "rps",
2949 &rps_connect_complete_cb,
2950 &rps_peers[i],
2951 &rps_connect_adapter,
2952 &rps_disconnect_adapter,
2953 &rps_peers[i]);
2954 /* Connect all peers to statistics service */
2955 if (COLLECT_STATISTICS == cur_test_run.have_collect_statistics)
2956 {
2957 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2958 "Connecting to statistics service\n");
2959 rps_peers[i].stat_op =
2960 GNUNET_TESTBED_service_connect (NULL,
2961 peers[i],
2962 "statistics",
2963 stat_complete_cb,
2964 &rps_peers[i],
2965 &stat_connect_adapter,
2966 &stat_disconnect_adapter,
2967 &rps_peers[i]);
2968 }
2969 }
2970
2971 if (NULL != churn_task)
2972 GNUNET_SCHEDULER_cancel (churn_task);
2973 post_test_task = GNUNET_SCHEDULER_add_delayed (duration, &post_test_op, NULL);
2974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for shutdown is %lu\n",
2975 timeout.rel_value_us / 1000000);
2976 shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout,
2977 &trigger_shutdown,
2978 NULL);
2979 GNUNET_SCHEDULER_add_shutdown (shutdown_op, NULL);
2980}
2981
2982
2983/**
2984 * Entry point for the testcase, sets up the testbed.
2985 *
2986 * @param argc unused
2987 * @param argv unused
2988 */
2989static void
2990run (void *cls,
2991 char *const *args,
2992 const char *cfgfile,
2993 const struct GNUNET_CONFIGURATION_Handle *cfg)
2994{
2995 // int ret_value;
2996 (void) cls;
2997 (void) args;
2998 (void) cfgfile;
2999
3000 /* Defaults for tests */
3001 churn_task = NULL;
3002
3003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
3004 cur_test_run.name = "test-rps-profiler";
3005 if (0 == num_peers)
3006 num_peers = 10;
3007 mal_type = 3;
3008 cur_test_run.init_peer = profiler_init_peer;
3009 // cur_test_run.pre_test = mal_pre;
3010 cur_test_run.pre_test = pre_profiler;
3011 cur_test_run.main_test = profiler_cb;
3012 cur_test_run.reply_handle = profiler_reply_handle;
3013 cur_test_run.eval_cb = profiler_eval;
3014 cur_test_run.post_test = post_profiler;
3015 cur_test_run.request_interval = 2;
3016 if (0 == cur_test_run.num_requests)
3017 cur_test_run.num_requests = 5;
3018 // cur_test_run.have_churn = HAVE_CHURN;
3019 cur_test_run.have_churn = HAVE_NO_CHURN;
3020 cur_test_run.have_quick_quit = HAVE_QUICK_QUIT;
3021 cur_test_run.have_collect_statistics = COLLECT_STATISTICS;
3022 cur_test_run.stat_collect_flags = BIT (STAT_TYPE_ROUNDS)
3023 | BIT (STAT_TYPE_BLOCKS)
3024 | BIT (STAT_TYPE_BLOCKS_MANY_PUSH)
3025 | BIT (STAT_TYPE_BLOCKS_NO_PUSH)
3026 | BIT (STAT_TYPE_BLOCKS_NO_PULL)
3027 | BIT (STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL)
3028 | BIT (STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL)
3029 | BIT (STAT_TYPE_ISSUED_PUSH_SEND)
3030 | BIT (STAT_TYPE_ISSUED_PUSH_SEND_MH)
3031 | BIT (STAT_TYPE_ISSUED_PULL_REQ)
3032 | BIT (STAT_TYPE_ISSUED_PULL_REQ_MH)
3033 | BIT (STAT_TYPE_ISSUED_PULL_REP)
3034 | BIT (STAT_TYPE_SENT_PUSH_SEND)
3035 | BIT (STAT_TYPE_SENT_PULL_REQ)
3036 | BIT (STAT_TYPE_SENT_PULL_REQ_MH)
3037 | BIT (STAT_TYPE_SENT_PULL_REP)
3038 | BIT (STAT_TYPE_RECV_PUSH_SEND)
3039 | BIT (STAT_TYPE_RECV_PUSH_SEND_MH)
3040 | BIT (STAT_TYPE_RECV_PULL_REQ)
3041 | BIT (STAT_TYPE_RECV_PULL_REQ_MH)
3042 | BIT (STAT_TYPE_RECV_PULL_REP)
3043 | BIT (STAT_TYPE_RECV_PULL_REP_MH)
3044 | BIT (STAT_TYPE_VIEW_SIZE)
3045 | BIT (STAT_TYPE_KNOWN_PEERS)
3046 | BIT (STAT_TYPE_VALID_PEERS)
3047 | BIT (STAT_TYPE_LEARND_PEERS)
3048 | BIT (STAT_TYPE_PENDING_ONLINE_CHECKS)
3049 | BIT (STAT_TYPE_UNREQUESTED_PULL_REPLIES)
3050 | BIT (STAT_TYPE_PEERS_IN_PUSH_MAP)
3051 | BIT (STAT_TYPE_PEERS_IN_PULL_MAP)
3052 | BIT (STAT_TYPE_PEERS_IN_VIEW)
3053 | BIT (STAT_TYPE_VIEW_SIZE_AIM);
3054 cur_test_run.have_collect_view = COLLECT_VIEW;
3055
3056 /* 'Clean' directory */
3057 (void) GNUNET_DISK_directory_remove ("/tmp/rps/");
3058 GNUNET_DISK_directory_create ("/tmp/rps/");
3059 if (0 == duration.rel_value_us)
3060 {
3061 if (0 == timeout.rel_value_us)
3062 {
3063 duration = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90);
3064 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
3065 (90 * 1.2)
3066 + (0.01 * num_peers));
3067 }
3068 else
3069 {
3070 duration = GNUNET_TIME_relative_multiply (
3071 GNUNET_TIME_UNIT_SECONDS,
3072 ( (double) timeout.rel_value_us / (double) 1000000)
3073 * 0.75);
3074 }
3075 }
3076 else
3077 {
3078 if (0 == timeout.rel_value_us)
3079 {
3080 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
3081 ((duration.rel_value_us
3082 / 1000000)
3083 * 1.2) + (0.01 * num_peers));
3084 }
3085 }
3086 GNUNET_assert (duration.rel_value_us < timeout.rel_value_us);
3087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3088 "duration is %lus\n",
3089 duration.rel_value_us / 1000000);
3090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3091 "timeout is %lus\n",
3092 timeout.rel_value_us / 1000000);
3093
3094 /* Compute number of bits for representing largest peer id */
3095 for (bits_needed = 1; (uint32_t) (1 << bits_needed) < num_peers; bits_needed++)
3096 ;
3097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3098 "Need %u bits to represent %" PRIu32 " peers\n",
3099 bits_needed,
3100 num_peers);
3101
3102 rps_peers = GNUNET_new_array (num_peers, struct RPSPeer);
3103 peer_map = GNUNET_CONTAINER_multipeermap_create (num_peers, GNUNET_NO);
3104 rps_peer_ids = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
3105 if ((2 == mal_type) ||
3106 (3 == mal_type))
3107 target_peer = &rps_peer_ids[num_peers - 2];
3108
3109 ok = 1;
3110 GNUNET_TESTBED_run (NULL,
3111 cfg,
3112 num_peers,
3113 0, /* event mask */
3114 NULL,
3115 NULL,
3116 &test_run,
3117 NULL);
3118}
3119
3120
3121/**
3122 * Entry point for the testcase, sets up the testbed.
3123 *
3124 * @param argc unused
3125 * @param argv unused
3126 * @return 0 on success
3127 */
3128int
3129main (int argc, char *argv[])
3130{
3131 int ret_value;
3132 struct GNUNET_GETOPT_CommandLineOption options[] = {
3133 GNUNET_GETOPT_option_uint ('n',
3134 "num-peers",
3135 "COUNT",
3136 gettext_noop ("number of peers to start"),
3137 &num_peers),
3138 GNUNET_GETOPT_option_relative_time ('d',
3139 "duration",
3140 "DURATION",
3141 gettext_noop (
3142 "duration of the profiling"),
3143 &duration),
3144 GNUNET_GETOPT_option_relative_time ('t',
3145 "timeout",
3146 "TIMEOUT",
3147 gettext_noop (
3148 "timeout for the profiling"),
3149 &timeout),
3150 GNUNET_GETOPT_option_uint ('r',
3151 "num-requests",
3152 "COUNT",
3153 gettext_noop ("number of PeerIDs to request"),
3154 &cur_test_run.num_requests),
3155 GNUNET_GETOPT_OPTION_END
3156 };
3157
3158 unsetenv ("XDG_DATA_HOME");
3159 unsetenv ("XDG_CONFIG_HOME");
3160 // if (GNUNET_OK !=
3161 // GNUNET_STRINGS_get_utf8_args (argc, argv,
3162 // &argc, &argv))
3163 // return 2;
3164 ret_value = 0;
3165 if (GNUNET_OK !=
3166 GNUNET_PROGRAM_run (argc,
3167 argv,
3168 "gnunet-rps-profiler",
3169 gettext_noop (
3170 "Measure quality and performance of the RPS service."),
3171 options,
3172 &run,
3173 NULL))
3174 {
3175 ret_value = 1;
3176 }
3177 if (0 != ret_value)
3178 {
3179 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3180 "Test did not run successfully!\n");
3181 }
3182 else
3183 {
3184 ret_value = cur_test_run.eval_cb ();
3185 if (NO_COLLECT_VIEW == cur_test_run.have_collect_view)
3186 {
3187 GNUNET_array_grow (rps_peers->cur_view,
3188 rps_peers->cur_view_count,
3189 0);
3190 }
3191 GNUNET_free (rps_peers);
3192 GNUNET_free (rps_peer_ids);
3193 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
3194 }
3195 return ret_value;
3196}
3197
3198
3199/* end of test_rps.c */