aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/testbed/gnunet-testbed-profiler.c701
-rw-r--r--src/testbed/testbed_api_testbed.c39
2 files changed, 74 insertions, 666 deletions
diff --git a/src/testbed/gnunet-testbed-profiler.c b/src/testbed/gnunet-testbed-profiler.c
index 66170c1a7..f5b9b2566 100644
--- a/src/testbed/gnunet-testbed-profiler.c
+++ b/src/testbed/gnunet-testbed-profiler.c
@@ -38,126 +38,16 @@
38 38
39 39
40/** 40/**
41 * DLL of operations
42 */
43struct DLLOperation
44{
45 /**
46 * The testbed operation handle
47 */
48 struct GNUNET_TESTBED_Operation *op;
49
50 /**
51 * Closure
52 */
53 void *cls;
54
55 /**
56 * The next pointer for DLL
57 */
58 struct DLLOperation *next;
59
60 /**
61 * The prev pointer for DLL
62 */
63 struct DLLOperation *prev;
64};
65
66
67/**
68 * Availanle states during profiling
69 */
70enum State
71{
72 /**
73 * Initial state
74 */
75 STATE_INIT = 0,
76
77 /**
78 * Starting slaves
79 */
80 STATE_SLAVES_STARTING,
81
82 /**
83 * Creating peers
84 */
85 STATE_PEERS_CREATING,
86
87 /**
88 * Starting peers
89 */
90 STATE_PEERS_STARTING,
91
92 /**
93 * Linking peers
94 */
95 STATE_PEERS_LINKING,
96
97 /**
98 * Destroying peers; we can do this as the controller takes care of stopping a
99 * peer if it is running
100 */
101 STATE_PEERS_DESTROYING
102};
103
104
105/**
106 * An array of hosts loaded from the hostkeys file
107 */
108static struct GNUNET_TESTBED_Host **hosts;
109
110/**
111 * The array of peers; we fill this as the peers are given to us by the testbed
112 */
113static struct GNUNET_TESTBED_Peer **peers;
114
115/* /\** */
116/* * Operation handle */
117/* *\/ */
118/* static struct GNUNET_TESTBED_Operation *op; */
119
120/**
121 * Host registration handle
122 */
123static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
124
125/**
126 * Handle to the master controller process
127 */
128struct GNUNET_TESTBED_ControllerProc *mc_proc;
129
130/**
131 * Handle to the master controller
132 */
133struct GNUNET_TESTBED_Controller *mc;
134
135/**
136 * Handle to global configuration 41 * Handle to global configuration
137 */ 42 */
138struct GNUNET_CONFIGURATION_Handle *cfg; 43struct GNUNET_CONFIGURATION_Handle *cfg;
139 44
140/** 45/**
141 * Head of the operations list
142 */
143struct DLLOperation *dll_op_head;
144
145/**
146 * Tail of the operations list
147 */
148struct DLLOperation *dll_op_tail;
149
150/**
151 * Peer linking - topology operation 46 * Peer linking - topology operation
152 */ 47 */
153struct GNUNET_TESTBED_Operation *topology_op; 48struct GNUNET_TESTBED_Operation *topology_op;
154 49
155/** 50/**
156 * The handle for whether a host is habitable or not
157 */
158struct GNUNET_TESTBED_HostHabitableCheckHandle **hc_handles;
159
160/**
161 * Abort task identifier 51 * Abort task identifier
162 */ 52 */
163static GNUNET_SCHEDULER_TaskIdentifier abort_task; 53static GNUNET_SCHEDULER_TaskIdentifier abort_task;
@@ -168,46 +58,16 @@ static GNUNET_SCHEDULER_TaskIdentifier abort_task;
168static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; 58static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
169 59
170/** 60/**
171 * Host registration task identifier
172 */
173static GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
174
175/**
176 * Global event mask for all testbed events 61 * Global event mask for all testbed events
177 */ 62 */
178uint64_t event_mask; 63uint64_t event_mask;
179 64
180/** 65/**
181 * The starting time of a profiling step
182 */
183struct GNUNET_TIME_Absolute prof_start_time;
184
185/**
186 * Duration profiling step has taken
187 */
188struct GNUNET_TIME_Relative prof_time;
189
190/**
191 * Current peer id
192 */
193unsigned int peer_id;
194
195/**
196 * Number of peers to be started by the profiler 66 * Number of peers to be started by the profiler
197 */ 67 */
198static unsigned int num_peers; 68static unsigned int num_peers;
199 69
200/** 70/**
201 * Number of hosts in the hosts array
202 */
203static unsigned int num_hosts;
204
205/**
206 * Number of random links to be established between peers
207 */
208static unsigned int num_links;
209
210/**
211 * Number of timeout failures to tolerate 71 * Number of timeout failures to tolerate
212 */ 72 */
213static unsigned int num_cont_fails; 73static unsigned int num_cont_fails;
@@ -232,16 +92,6 @@ static unsigned int failed_links;
232 */ 92 */
233static int result; 93static int result;
234 94
235/**
236 * current state of profiling
237 */
238enum State state;
239
240/**
241 * The topology we want to acheive
242 */
243enum GNUNET_TESTBED_TopologyOption topology;
244
245 95
246/** 96/**
247 * Shutdown nicely 97 * Shutdown nicely
@@ -252,40 +102,9 @@ enum GNUNET_TESTBED_TopologyOption topology;
252static void 102static void
253do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 103do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
254{ 104{
255 struct DLLOperation *dll_op;
256 unsigned int nhost;
257
258 shutdown_task = GNUNET_SCHEDULER_NO_TASK; 105 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
259 if (GNUNET_SCHEDULER_NO_TASK != abort_task) 106 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
260 GNUNET_SCHEDULER_cancel (abort_task); 107 GNUNET_SCHEDULER_cancel (abort_task);
261 if (NULL != hc_handles)
262 {
263 for (nhost = 0; nhost < num_hosts; nhost++)
264 if (NULL != hc_handles[nhost])
265 GNUNET_TESTBED_is_host_habitable_cancel (hc_handles[nhost]);
266 GNUNET_free (hc_handles);
267 hc_handles = NULL;
268 }
269 if (GNUNET_SCHEDULER_NO_TASK != register_hosts_task)
270 GNUNET_SCHEDULER_cancel (register_hosts_task);
271 if (NULL != reg_handle)
272 GNUNET_TESTBED_cancel_registration (reg_handle);
273 if (NULL != topology_op)
274 GNUNET_TESTBED_operation_done (topology_op);
275 for (nhost = 0; nhost < num_hosts; nhost++)
276 if (NULL != hosts[nhost])
277 GNUNET_TESTBED_host_destroy (hosts[nhost]);
278 GNUNET_free_non_null (hosts);
279 while (NULL != (dll_op = dll_op_head))
280 {
281 GNUNET_TESTBED_operation_done (dll_op->op);
282 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
283 GNUNET_free (dll_op);
284 }
285 if (NULL != mc)
286 GNUNET_TESTBED_controller_disconnect (mc);
287 if (NULL != mc_proc)
288 GNUNET_TESTBED_controller_stop (mc_proc);
289 if (NULL != cfg) 108 if (NULL != cfg)
290 GNUNET_CONFIGURATION_destroy (cfg); 109 GNUNET_CONFIGURATION_destroy (cfg);
291 GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ 110 GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */
@@ -311,129 +130,6 @@ do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
311 130
312 131
313/** 132/**
314 * Functions of this signature are called when a peer has been successfully
315 * started or stopped.
316 *
317 * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
318 * @param emsg NULL on success; otherwise an error description
319 */
320static void
321peer_churn_cb (void *cls, const char *emsg)
322{
323 struct DLLOperation *dll_op = cls;
324 struct GNUNET_TESTBED_Operation *op;
325 static unsigned int started_peers;
326
327 op = dll_op->op;
328 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
329 GNUNET_free (dll_op);
330 if (NULL != emsg)
331 {
332 LOG (GNUNET_ERROR_TYPE_WARNING,
333 _("An operation has failed while starting peers\n"));
334 GNUNET_TESTBED_operation_done (op);
335 GNUNET_SCHEDULER_cancel (abort_task);
336 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
337 return;
338 }
339 GNUNET_TESTBED_operation_done (op);
340 if (++started_peers == num_peers)
341 {
342 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
343 printf ("%u peers started successfully in %.2f seconds\n",
344 num_peers, ((double) prof_time.rel_value) / 1000.00);
345 fflush (stdout);
346 result = GNUNET_OK;
347 if ((0 == num_links) && (topology == GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI))
348 {
349 fprintf (stdout, "Testbed running, waiting for keystroke to shut down\n");
350 (void) getc (stdin);
351 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
352 return;
353 }
354 state = STATE_PEERS_LINKING;
355 /* Do overlay connect */
356 prof_start_time = GNUNET_TIME_absolute_get ();
357 switch (topology)
358 {
359 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
360 topology_op =
361 GNUNET_TESTBED_overlay_configure_topology (NULL, num_peers, peers, NULL,
362 topology,
363 num_links,
364 GNUNET_TESTBED_TOPOLOGY_DISABLE_AUTO_RETRY,
365 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
366 break;
367 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
368 topology_op =
369 GNUNET_TESTBED_overlay_configure_topology (NULL, num_peers, peers, NULL,
370 topology,
371 GNUNET_TESTBED_TOPOLOGY_DISABLE_AUTO_RETRY,
372 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
373 num_links = num_peers * (num_peers - 1);
374 break;
375 default:
376 GNUNET_assert (0);
377 }
378 }
379}
380
381
382/**
383 * Functions of this signature are called when a peer has been successfully
384 * created
385 *
386 * @param cls the closure from GNUNET_TESTBED_peer_create()
387 * @param peer the handle for the created peer; NULL on any error during
388 * creation
389 * @param emsg NULL if peer is not NULL; else MAY contain the error description
390 */
391static void
392peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
393{
394 struct DLLOperation *dll_op = cls;
395 struct GNUNET_TESTBED_Peer **peer_ptr;
396 static unsigned int created_peers;
397 unsigned int peer_cnt;
398
399 if (NULL != emsg)
400 {
401 LOG (GNUNET_ERROR_TYPE_WARNING,
402 _("Creating a peer failed. Error: %s\n"), emsg);
403 GNUNET_TESTBED_operation_done (dll_op->op);
404 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
405 GNUNET_free (dll_op);
406 GNUNET_SCHEDULER_cancel (abort_task);
407 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
408 return;
409 }
410 peer_ptr = dll_op->cls;
411 GNUNET_assert (NULL == *peer_ptr);
412 *peer_ptr = peer;
413 GNUNET_TESTBED_operation_done (dll_op->op);
414 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
415 GNUNET_free (dll_op);
416 if (++created_peers == num_peers)
417 {
418 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
419 printf ("%u peers created successfully in %.2f seconds\n",
420 num_peers, ((double) prof_time.rel_value) / 1000.00);
421 fflush (stdout);
422 /* Now peers are to be started */
423 state = STATE_PEERS_STARTING;
424 prof_start_time = GNUNET_TIME_absolute_get ();
425 for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
426 {
427 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
428 dll_op->op = GNUNET_TESTBED_peer_start (dll_op, peers[peer_cnt],
429 &peer_churn_cb, dll_op);
430 GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
431 }
432 }
433}
434
435
436/**
437 * Function to print summary about how many overlay links we have made and how 133 * Function to print summary about how many overlay links we have made and how
438 * many failed 134 * many failed
439 */ 135 */
@@ -445,42 +141,11 @@ print_overlay_links_summary ()
445 if (GNUNET_YES == printed_already) 141 if (GNUNET_YES == printed_already)
446 return; 142 return;
447 printed_already = GNUNET_YES; 143 printed_already = GNUNET_YES;
448 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
449 printf ("\n%u links established in %.2f seconds\n",
450 established_links, ((double) prof_time.rel_value) / 1000.00);
451 printf ("%u links failed due to timeouts\n", failed_links); 144 printf ("%u links failed due to timeouts\n", failed_links);
452} 145}
453 146
454 147
455/** 148/**
456 * Function to start peers
457 */
458static void
459start_peers ()
460{
461 struct DLLOperation *dll_op;
462 unsigned int peer_cnt;
463
464 state = STATE_PEERS_CREATING;
465 prof_start_time = GNUNET_TIME_absolute_get ();
466 peers = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *)
467 * num_peers);
468 for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
469 {
470 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
471 dll_op->cls = &peers[peer_cnt];
472 dll_op->op = GNUNET_TESTBED_peer_create (mc,
473 hosts
474 [peer_cnt % num_hosts],
475 cfg,
476 &peer_create_cb,
477 dll_op);
478 GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
479 }
480}
481
482
483/**
484 * Controller event callback 149 * Controller event callback
485 * 150 *
486 * @param cls NULL 151 * @param cls NULL
@@ -490,265 +155,60 @@ static void
490controller_event_cb (void *cls, 155controller_event_cb (void *cls,
491 const struct GNUNET_TESTBED_EventInformation *event) 156 const struct GNUNET_TESTBED_EventInformation *event)
492{ 157{
493 struct DLLOperation *dll_op; 158 switch (event->type)
494 struct GNUNET_TESTBED_Operation *op;
495
496 switch (state)
497 { 159 {
498 case STATE_SLAVES_STARTING: 160 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
499 switch (event->type) 161 /* Control reaches here when a peer linking operation fails */
162 if (NULL != event->details.operation_finished.emsg)
500 { 163 {
501 case GNUNET_TESTBED_ET_OPERATION_FINISHED: 164 printf ("F");
165 fflush (stdout);
166 failed_links++;
167 if (++cont_fails > num_cont_fails)
502 { 168 {
503 static unsigned int slaves_started; 169 printf ("\nAborting due to very high failure rate");
504 170 print_overlay_links_summary ();
505 dll_op = event->details.operation_finished.op_cls; 171 GNUNET_SCHEDULER_cancel (abort_task);
506 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op); 172 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
507 GNUNET_free (dll_op); 173 return;
508 op = event->details.operation_finished.operation;
509 if (NULL != event->details.operation_finished.emsg)
510 {
511 LOG (GNUNET_ERROR_TYPE_WARNING,
512 _("An operation has failed while starting slaves\n"));
513 GNUNET_TESTBED_operation_done (op);
514 GNUNET_SCHEDULER_cancel (abort_task);
515 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
516 return;
517 }
518 GNUNET_TESTBED_operation_done (op);
519 /* Proceed to start peers */
520 if (++slaves_started == num_hosts - 1)
521 {
522 printf ("%u controllers started successfully\n", num_hosts);
523 fflush (stdout);
524 start_peers ();
525 }
526 } 174 }
527 break;
528 default:
529 GNUNET_assert (0);
530 } 175 }
531 break; 176 break;
532 case STATE_PEERS_STARTING: 177 case GNUNET_TESTBED_ET_CONNECT:
533 switch (event->type)
534 {
535 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
536 /* Control reaches here when peer start fails */
537 case GNUNET_TESTBED_ET_PEER_START:
538 /* we handle peer starts in peer_churn_cb */
539 break;
540 default:
541 GNUNET_assert (0);
542 }
543 break;
544 case STATE_PEERS_LINKING:
545 switch (event->type)
546 {
547 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
548 /* Control reaches here when a peer linking operation fails */
549 if (NULL != event->details.operation_finished.emsg)
550 {
551 printf ("F");
552 fflush (stdout);
553 failed_links++;
554 if (++cont_fails > num_cont_fails)
555 {
556 printf ("\nAborting due to very high failure rate");
557 print_overlay_links_summary ();
558 GNUNET_SCHEDULER_cancel (abort_task);
559 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
560 return;
561 }
562 }
563 break;
564 case GNUNET_TESTBED_ET_CONNECT:
565 {
566 if (0 != cont_fails)
567 cont_fails--;
568 if (0 == established_links)
569 printf ("Establishing links. Please wait\n");
570 printf (".");
571 fflush (stdout);
572 established_links++;
573 }
574 break;
575 default:
576 GNUNET_assert (0);
577 }
578 if ((established_links + failed_links) == num_links)
579 { 178 {
580 print_overlay_links_summary (); 179 if (0 != cont_fails)
581 result = GNUNET_OK; 180 cont_fails--;
582 fprintf (stdout, "Testbed running, waiting for keystroke to shut down\n"); 181 if (0 == established_links)
182 printf ("Establishing links. Please wait\n");
183 printf (".");
583 fflush (stdout); 184 fflush (stdout);
584 (void) getc (stdin); 185 established_links++;
585 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 186 }
586 }
587 break; 187 break;
588 default: 188 default:
589 GNUNET_assert (0); 189 GNUNET_break (0);
590 }
591}
592
593
594/**
595 * Task to register all hosts available in the global host list
596 *
597 * @param cls NULL
598 * @param tc the scheduler task context
599 */
600static void
601register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
602
603
604/**
605 * Callback which will be called to after a host registration succeeded or failed
606 *
607 * @param cls the closure
608 * @param emsg the error message; NULL if host registration is successful
609 */
610static void
611host_registration_completion (void *cls, const char *emsg)
612{
613 reg_handle = NULL;
614 if (NULL != emsg)
615 {
616 LOG (GNUNET_ERROR_TYPE_WARNING,
617 _("Host registration failed for a host. Error: %s\n"), emsg);
618 GNUNET_SCHEDULER_cancel (abort_task);
619 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
620 return;
621 }
622 register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, NULL);
623}
624
625
626/**
627 * Task to register all hosts available in the global host list
628 *
629 * @param cls NULL
630 * @param tc the scheduler task context
631 */
632static void
633register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
634{
635 struct DLLOperation *dll_op;
636 static unsigned int reg_host;
637 unsigned int slave;
638
639 register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
640 if (reg_host == num_hosts - 1)
641 {
642 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 "All hosts successfully registered\n");
644 /* Start slaves */
645 state = STATE_SLAVES_STARTING;
646 for (slave = 1; slave < num_hosts; slave++)
647 {
648 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
649 dll_op->op = GNUNET_TESTBED_controller_link (dll_op,
650 mc,
651 hosts[slave],
652 hosts[0],
653 cfg,
654 GNUNET_YES);
655 GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
656 }
657 return;
658 }
659 reg_handle = GNUNET_TESTBED_register_host (mc, hosts[++reg_host],
660 host_registration_completion,
661 NULL);
662}
663
664
665/**
666 * Callback to signal successfull startup of the controller process
667 *
668 * @param cls the closure from GNUNET_TESTBED_controller_start()
669 * @param config the configuration with which the controller has been started;
670 * NULL if status is not GNUNET_OK
671 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
672 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
673 */
674static void
675status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int status)
676{
677 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
678 GNUNET_SCHEDULER_cancel (abort_task);
679 if (GNUNET_OK != status)
680 {
681 mc_proc = NULL;
682 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
683 return;
684 }
685 event_mask = 0;
686 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
687 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
688 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
689 event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT);
690 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
691 mc = GNUNET_TESTBED_controller_connect (config, hosts[0], event_mask,
692 &controller_event_cb, NULL);
693 if (NULL == mc)
694 {
695 LOG (GNUNET_ERROR_TYPE_WARNING,
696 _("Unable to connect to master controller -- Check config\n"));
697 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
698 return;
699 } 190 }
700 if (num_hosts > 1)
701 register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, NULL);
702 else
703 start_peers ();
704 abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
705 &do_abort, NULL);
706} 191}
707 192
708 193
709/** 194/**
710 * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to 195 * Signature of a main function for a testcase.
711 * inform whether the given host is habitable or not. The Handle returned by
712 * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
713 * 196 *
714 * @param cls NULL 197 * @param cls closure
715 * @param host the host whose status is being reported; will be NULL if the host 198 * @param num_peers number of peers in 'peers'
716 * given to GNUNET_TESTBED_is_host_habitable() is NULL 199 * @param peers handle to peers run in the testbed
717 * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
718 */ 200 */
719static void 201static void test_run (void *cls,
720host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, int status) 202 unsigned int num_peers,
203 struct GNUNET_TESTBED_Peer **peers)
721{ 204{
722 struct GNUNET_TESTBED_HostHabitableCheckHandle **hc_handle = cls; 205 result = GNUNET_OK;
723 static unsigned int hosts_checked; 206 fprintf (stdout, "\nTestbed running, waiting for keystroke to shut down\n");
724
725 *hc_handle = NULL;
726 if (GNUNET_NO == status)
727 {
728 if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host)))
729 LOG (GNUNET_ERROR_TYPE_ERROR, _("Host %s cannot start testbed\n"),
730 GNUNET_TESTBED_host_get_hostname (host));
731 else
732 LOG (GNUNET_ERROR_TYPE_ERROR, _("Testbed cannot be started on localhost\n"));
733 GNUNET_SCHEDULER_cancel (abort_task);
734 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
735 return;
736 }
737 hosts_checked++;
738 printf (_("\rChecked %u hosts"), hosts_checked);
739 fflush (stdout); 207 fflush (stdout);
740 if (hosts_checked < num_hosts) 208 (void) getc (stdin);
741 return; 209 fprintf (stdout, "Shutting down. Please wait\n");
742 printf (_("\nAll hosts can start testbed. Creating peers\n")); 210 fflush (stdout);
743 GNUNET_free (hc_handles); 211 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
744 hc_handles = NULL;
745 mc_proc =
746 GNUNET_TESTBED_controller_start (GNUNET_TESTBED_host_get_hostname
747 (hosts[0]),
748 hosts[0],
749 cfg,
750 status_cb,
751 NULL);
752} 212}
753 213
754 214
@@ -764,8 +224,6 @@ static void
764run (void *cls, char *const *args, const char *cfgfile, 224run (void *cls, char *const *args, const char *cfgfile,
765 const struct GNUNET_CONFIGURATION_Handle *config) 225 const struct GNUNET_CONFIGURATION_Handle *config)
766{ 226{
767 unsigned int nhost;
768
769 if (NULL == args[0]) 227 if (NULL == args[0])
770 { 228 {
771 fprintf (stderr, _("No hosts-file specified on command line\n")); 229 fprintf (stderr, _("No hosts-file specified on command line\n"));
@@ -776,81 +234,22 @@ run (void *cls, char *const *args, const char *cfgfile,
776 result = GNUNET_OK; 234 result = GNUNET_OK;
777 return; 235 return;
778 } 236 }
779 num_hosts = GNUNET_TESTBED_hosts_load_from_file (args[0], &hosts);
780 if (0 == num_hosts)
781 {
782 fprintf (stderr, _("No hosts loaded. Need at least one host\n"));
783 return;
784 }
785 printf (_("Checking whether given hosts can start testbed. Please wait\n"));
786 hc_handles = GNUNET_malloc (sizeof (struct
787 GNUNET_TESTBED_HostHabitableCheckHandle *)
788 * num_hosts);
789 for (nhost = 0; nhost < num_hosts; nhost++)
790 {
791 if (NULL == (hc_handles[nhost] = GNUNET_TESTBED_is_host_habitable (hosts[nhost], config,
792 &host_habitable_cb,
793 &hc_handles[nhost])))
794 {
795 GNUNET_break (0);
796 for (nhost = 0; nhost < num_hosts; nhost++)
797 if (NULL != hc_handles[nhost])
798 GNUNET_TESTBED_is_host_habitable_cancel (hc_handles[nhost]);
799 GNUNET_free (hc_handles);
800 hc_handles = NULL;
801 break;
802 }
803 }
804 if (num_hosts != nhost)
805 {
806 fprintf (stderr, _("Exiting\n"));
807 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
808 return;
809 }
810 cfg = GNUNET_CONFIGURATION_dup (config); 237 cfg = GNUNET_CONFIGURATION_dup (config);
238 event_mask = 0;
239 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
240 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
241 GNUNET_TESTBED_run (args[0], cfg,
242 num_peers, event_mask,
243 controller_event_cb, NULL,
244 &test_run, NULL);
811 abort_task = 245 abort_task =
812 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 246 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
813 (GNUNET_TIME_UNIT_SECONDS, 5), &do_abort, 247 &do_abort,
814 NULL); 248 NULL);
815} 249}
816 250
817 251
818/** 252/**
819 * Set an option of type 'char *' from the command line.
820 * A pointer to this function should be passed as part of the
821 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
822 * of this type. It should be followed by a pointer to a value of
823 * type 'char *'.
824 *
825 * @param ctx command line processing context
826 * @param scls additional closure (will point to the 'char *',
827 * which will be allocated)
828 * @param option name of the option
829 * @param value actual value of the option (a string)
830 * @return GNUNET_OK to continue procesing; GNUNET_SYSERR to signal error
831 */
832int
833set_topology (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
834 void *scls, const char *option, const char *value)
835{
836 enum GNUNET_TESTBED_TopologyOption *val = scls;
837
838 if (0 == strncasecmp ("CLIQUE", value, strlen ("CLIQUE")))
839 {
840 *val = GNUNET_TESTBED_TOPOLOGY_CLIQUE;
841 return GNUNET_OK;
842 }
843 if (0 == strncasecmp ("RANDOM", value, strlen ("RANDOM")))
844 {
845 *val = GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI;
846 return GNUNET_OK;
847 }
848 FPRINTF (stderr, "%s", _("Only `CLIQUE' and `RANDOM' are permitted.\n"));
849 return GNUNET_SYSERR;
850}
851
852
853/**
854 * Main function. 253 * Main function.
855 * 254 *
856 * @return 0 on success 255 * @return 0 on success
@@ -862,25 +261,15 @@ main (int argc, char *const *argv)
862 { 'p', "num-peers", "COUNT", 261 { 'p', "num-peers", "COUNT",
863 gettext_noop ("create COUNT number of peers"), 262 gettext_noop ("create COUNT number of peers"),
864 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers }, 263 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers },
865 { 'n', "num-links", "COUNT",
866 gettext_noop ("create COUNT number of random links"),
867 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_links },
868 { 'e', "num-errors", "COUNT", 264 { 'e', "num-errors", "COUNT",
869 gettext_noop ("tolerate COUNT number of continious timeout failures"), 265 gettext_noop ("tolerate COUNT number of continious timeout failures"),
870 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_cont_fails }, 266 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_cont_fails },
871 { 't', "topology", "TOPOLOGY",
872 gettext_noop ("Try to acheive TOPOLOGY. This options takes either CLIQUE "
873 "or RANDOM. For CLIQUE the parameter -n is ignored. The "
874 "default is to acheive a random graph topology."),
875 GNUNET_YES, &set_topology, &topology },
876 GNUNET_GETOPT_OPTION_END 267 GNUNET_GETOPT_OPTION_END
877 }; 268 };
878 int ret; 269 int ret;
879 270
880 topology = GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI;
881 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 271 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
882 return 2; 272 return 2;
883
884 result = GNUNET_SYSERR; 273 result = GNUNET_SYSERR;
885 ret = 274 ret =
886 GNUNET_PROGRAM_run (argc, argv, "gnunet-testbed-profiler [OPTIONS] hosts-file", 275 GNUNET_PROGRAM_run (argc, argv, "gnunet-testbed-profiler [OPTIONS] hosts-file",
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c
index 194d54a58..106631604 100644
--- a/src/testbed/testbed_api_testbed.c
+++ b/src/testbed/testbed_api_testbed.c
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28#include "platform.h" 28#include "platform.h"
29#include "gnunet_util_lib.h"
29#include "gnunet_testbed_service.h" 30#include "gnunet_testbed_service.h"
30#include "testbed_api_peers.h" 31#include "testbed_api_peers.h"
31#include "testbed_api_hosts.h" 32#include "testbed_api_hosts.h"
@@ -37,6 +38,11 @@
37#define LOG(kind,...) \ 38#define LOG(kind,...) \
38 GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__) 39 GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__)
39 40
41/**
42 * Debug logging shortcut
43 */
44#define DEBUG(...) \
45 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
40 46
41/** 47/**
42 * DLL of operations 48 * DLL of operations
@@ -198,6 +204,11 @@ struct RunContext
198 struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; 204 struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
199 205
200 /** 206 /**
207 * Profiling start time
208 */
209 struct GNUNET_TIME_Absolute pstart_time;
210
211 /**
201 * Host registration task 212 * Host registration task
202 */ 213 */
203 GNUNET_SCHEDULER_TaskIdentifier register_hosts_task; 214 GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
@@ -281,7 +292,8 @@ start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
281 struct DLLOperation *dll_op; 292 struct DLLOperation *dll_op;
282 unsigned int peer; 293 unsigned int peer;
283 294
284 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting Peers\n"); 295 DEBUG ("Starting Peers\n");
296 rc->pstart_time = GNUNET_TIME_absolute_get ();
285 for (peer = 0; peer < rc->num_peers; peer++) 297 for (peer = 0; peer < rc->num_peers; peer++)
286 { 298 {
287 dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); 299 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
@@ -307,6 +319,7 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
307{ 319{
308 struct DLLOperation *dll_op = cls; 320 struct DLLOperation *dll_op = cls;
309 struct RunContext *rc; 321 struct RunContext *rc;
322 struct GNUNET_TIME_Relative ptime;
310 323
311 GNUNET_assert (NULL != dll_op); 324 GNUNET_assert (NULL != dll_op);
312 rc = dll_op->rc; 325 rc = dll_op->rc;
@@ -326,7 +339,9 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
326 rc->peer_count++; 339 rc->peer_count++;
327 if (rc->peer_count < rc->num_peers) 340 if (rc->peer_count < rc->num_peers)
328 return; 341 return;
329 LOG (GNUNET_ERROR_TYPE_DEBUG, "%u peers created successfully\n", rc->num_peers); 342 ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time);
343 DEBUG ("%u peers created in %s\n", rc->num_peers,
344 GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES));
330 GNUNET_SCHEDULER_add_now (&start_peers_task, rc); 345 GNUNET_SCHEDULER_add_now (&start_peers_task, rc);
331} 346}
332 347
@@ -485,7 +500,7 @@ shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
485 rc->peer_count++; 500 rc->peer_count++;
486 continue; 501 continue;
487 } 502 }
488 LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping peer %u\n", peer); 503 DEBUG ("Stopping peer %u\n", peer);
489 dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); 504 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
490 dll_op->op = GNUNET_TESTBED_peer_stop (rc->peers[peer], NULL, NULL); 505 dll_op->op = GNUNET_TESTBED_peer_stop (rc->peers[peer], NULL, NULL);
491 dll_op->cls = rc->peers[peer]; 506 dll_op->cls = rc->peers[peer];
@@ -535,7 +550,9 @@ create_peers (struct RunContext *rc)
535{ 550{
536 struct DLLOperation *dll_op; 551 struct DLLOperation *dll_op;
537 unsigned int peer; 552 unsigned int peer;
538 553
554 DEBUG ("Creating peers\n");
555 rc->pstart_time = GNUNET_TIME_absolute_get ();
539 rc->peers = 556 rc->peers =
540 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers); 557 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers);
541 GNUNET_assert (NULL != rc->c); 558 GNUNET_assert (NULL != rc->c);
@@ -618,7 +635,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
618 GNUNET_SCHEDULER_add_continuation (&call_master, rc, 635 GNUNET_SCHEDULER_add_continuation (&call_master, rc,
619 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 636 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
620 } 637 }
621 return; 638 goto call_cc;
622 } 639 }
623 for (dll_op = rc->dll_op_head; NULL != dll_op; dll_op = dll_op->next) 640 for (dll_op = rc->dll_op_head; NULL != dll_op; dll_op = dll_op->next)
624 { 641 {
@@ -655,7 +672,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
655 rc->state = RC_PEERS_DESTROYED; 672 rc->state = RC_PEERS_DESTROYED;
656 GNUNET_free (rc->peers); 673 GNUNET_free (rc->peers);
657 rc->peers = NULL; 674 rc->peers = NULL;
658 LOG (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully destroyed\n"); 675 DEBUG ("All peers successfully destroyed\n");
659 GNUNET_SCHEDULER_add_now (&cleanup_task, rc); 676 GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
660 break; 677 break;
661 default: 678 default:
@@ -679,8 +696,11 @@ call_cc:
679 GNUNET_free (dll_op); 696 GNUNET_free (dll_op);
680 rc->peer_count++; 697 rc->peer_count++;
681 if (rc->peer_count < rc->num_peers) 698 if (rc->peer_count < rc->num_peers)
682 return; 699 return;
683 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers started successfully\n"); 700 DEBUG ("%u peers started in %s\n", rc->num_peers,
701 GNUNET_STRINGS_relative_time_to_string
702 (GNUNET_TIME_absolute_get_duration(rc->pstart_time),
703 GNUNET_YES));
684 if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology) 704 if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology)
685 { 705 {
686 if ( (GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI == rc->topology) 706 if ( (GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI == rc->topology)
@@ -777,8 +797,7 @@ register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
777 rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK; 797 rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
778 if (rc->reg_hosts == rc->num_hosts) 798 if (rc->reg_hosts == rc->num_hosts)
779 { 799 {
780 LOG (GNUNET_ERROR_TYPE_DEBUG, 800 DEBUG ("All hosts successfully registered\n");
781 "All hosts successfully registered\n");
782 /* Start slaves */ 801 /* Start slaves */
783 for (slave = 0; slave < rc->num_hosts; slave++) 802 for (slave = 0; slave < rc->num_hosts; slave++)
784 { 803 {