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