2 This file is part of GNUnet
3 (C) 2008-2011 Christian Grothoff (and other contributing authors)
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.
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.
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testing/testing_peergroup.c
23 * @brief API implementation for easy peer group creation
24 * @author Nathan Evans
25 * @author Christian Grothoff
29 #include "gnunet_constants.h"
30 #include "gnunet_arm_service.h"
31 #include "gnunet_testing_lib.h"
32 #include "gnunet_core_service.h"
33 #include "gnunet_disk_lib.h"
36 #define DEFAULT_CONNECT_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
38 #define DEFAULT_CONNECT_ATTEMPTS 2
40 /** Struct definitions **/
42 struct PeerGroupStartupContext
44 struct GNUNET_TESTING_PeerGroup *pg;
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
47 unsigned int peers_left;
48 unsigned long long max_concurrent_connections;
49 unsigned long long connect_attempts;
50 unsigned long long max_concurrent_ssh;
51 struct GNUNET_TIME_Absolute timeout;
52 GNUNET_TESTING_NotifyConnection connect_cb;
53 GNUNET_TESTING_NotifyCompletion peergroup_cb;
56 * Closure for all peergroup callbacks.
60 const struct GNUNET_TESTING_Host *hostnames;
61 enum GNUNET_TESTING_Topology topology;
63 float topology_percentage;
65 float topology_probability;
67 enum GNUNET_TESTING_Topology restrict_topology;
68 char *restrict_transports;
69 enum GNUNET_TESTING_Topology connect_topology;
70 enum GNUNET_TESTING_TopologyOption connect_topology_option;
71 double connect_topology_option_modifier;
74 struct ProgressMeter *hostkey_meter;
75 struct ProgressMeter *peer_start_meter;
76 struct ProgressMeter *connect_meter;
79 * Task used to kill the peergroup.
81 GNUNET_SCHEDULER_TaskIdentifier die_task;
86 * Variable used to store the number of connections we should wait for.
88 unsigned int expected_connections;
91 * Time when the connecting peers was started.
93 struct GNUNET_TIME_Absolute connect_start_time;
96 * The total number of connections that have been created so far.
98 unsigned int total_connections;
101 * The total number of connections that have failed so far.
103 unsigned int failed_connections;
106 * File handle to write out topology in dot format.
108 struct GNUNET_DISK_FileHandle *topology_output_file;
111 struct TopologyOutputContext
113 struct GNUNET_DISK_FileHandle *file;
114 GNUNET_TESTING_NotifyCompletion notify_cb;
119 * Simple struct to keep track of progress, and print a
120 * percentage meter for long running tasks.
125 * Total number of tasks to complete.
130 * Print percentage done after modnum tasks.
135 * Print a . each dotnum tasks.
140 * Total number completed thus far.
142 unsigned int completed;
145 * Whether or not to print.
150 * Startup string for progress meter.
152 char *startup_string;
156 /** Utility functions **/
159 * Create a meter to keep track of the progress of some task.
161 * @param total the total number of items to complete
162 * @param start_string a string to prefix the meter with (if printing)
163 * @param print GNUNET_YES to print the meter, GNUNET_NO to count
166 * @return the progress meter
168 static struct ProgressMeter *
169 create_meter(unsigned int total, char * start_string, int print)
171 struct ProgressMeter *ret;
172 ret = GNUNET_malloc(sizeof(struct ProgressMeter));
175 ret->modnum = total / 4;
176 ret->dotnum = (total / 50) + 1;
177 if (start_string != NULL)
178 ret->startup_string = GNUNET_strdup(start_string);
180 ret->startup_string = GNUNET_strdup("");
186 * Update progress meter (increment by one).
188 * @param meter the meter to update and print info for
190 * @return GNUNET_YES if called the total requested,
191 * GNUNET_NO if more items expected
194 update_meter(struct ProgressMeter *meter)
196 if (meter->print == GNUNET_YES)
198 if (meter->completed % meter->modnum == 0)
200 if (meter->completed == 0)
202 fprintf (stdout, "%sProgress: [0%%", meter->startup_string);
205 fprintf (stdout, "%d%%", (int) (((float) meter->completed
206 / meter->total) * 100));
208 else if (meter->completed % meter->dotnum == 0)
209 fprintf (stdout, ".");
211 if (meter->completed + 1 == meter->total)
212 fprintf (stdout, "%d%%]\n", 100);
217 if (meter->completed == meter->total)
223 * Reset progress meter.
225 * @param meter the meter to reset
227 * @return GNUNET_YES if meter reset,
228 * GNUNET_SYSERR on error
231 reset_meter(struct ProgressMeter *meter)
234 return GNUNET_SYSERR;
236 meter->completed = 0;
241 * Release resources for meter
243 * @param meter the meter to free
246 free_meter(struct ProgressMeter *meter)
248 GNUNET_free_non_null (meter->startup_string);
253 /** Functions for creating, starting and connecting the peergroup **/
256 * Check whether peers successfully shut down.
259 internal_shutdown_callback(void *cls, const char *emsg)
261 struct PeerGroupStartupContext *pg_start_ctx = cls;
263 pg_start_ctx->peergroup_cb(pg_start_ctx->cls, emsg);
265 pg_start_ctx->peergroup_cb(pg_start_ctx->cls, pg_start_ctx->fail_reason);
269 * Check if the get_handle is being used, if so stop the request. Either
270 * way, schedule the end_badly_cont function which actually shuts down the
274 end_badly(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
276 struct PeerGroupStartupContext *pg_start_ctx = cls;
277 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failing peer group startup with error: `%s'!\n",
278 pg_start_ctx->fail_reason);
280 GNUNET_TESTING_daemons_stop (pg_start_ctx->pg, GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout), &internal_shutdown_callback, pg_start_ctx);
282 if (pg_start_ctx->hostkey_meter != NULL)
283 free_meter (pg_start_ctx->hostkey_meter);
284 if (pg_start_ctx->peer_start_meter != NULL)
285 free_meter (pg_start_ctx->peer_start_meter);
286 if (pg_start_ctx->connect_meter != NULL)
287 free_meter (pg_start_ctx->connect_meter);
291 * This function is called whenever a connection attempt is finished between two of
292 * the started peers (started with GNUNET_TESTING_daemons_start). The total
293 * number of times this function is called should equal the number returned
294 * from the GNUNET_TESTING_connect_topology call.
296 * The emsg variable is NULL on success (peers connected), and non-NULL on
297 * failure (peers failed to connect).
300 internal_topology_callback(
302 const struct GNUNET_PeerIdentity *first,
303 const struct GNUNET_PeerIdentity *second,
305 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
306 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
307 struct GNUNET_TESTING_Daemon *first_daemon,
308 struct GNUNET_TESTING_Daemon *second_daemon,
311 struct PeerGroupStartupContext *pg_start_ctx = cls;
316 unsigned long long duration;
317 unsigned long long total_duration;
318 unsigned int new_connections;
319 unsigned int new_failed_connections;
320 double conns_per_sec_recent;
321 double conns_per_sec_total;
322 double failed_conns_per_sec_recent;
323 double failed_conns_per_sec_total;
327 if (GNUNET_TIME_absolute_get_difference (connect_last_time,
328 GNUNET_TIME_absolute_get ()).rel_value
329 > GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
330 CONN_UPDATE_DURATION).rel_value)
332 /* Get number of new connections */
333 new_connections = total_connections - previous_connections;
335 /* Get number of new FAILED connections */
336 new_failed_connections = failed_connections - previous_failed_connections;
338 /* Get duration in seconds */
340 = GNUNET_TIME_absolute_get_difference (connect_last_time,
341 GNUNET_TIME_absolute_get ()).rel_value
344 = GNUNET_TIME_absolute_get_difference (connect_start_time,
345 GNUNET_TIME_absolute_get ()).rel_value
348 failed_conns_per_sec_recent = (double) new_failed_connections / duration;
349 failed_conns_per_sec_total = (double) failed_connections / total_duration;
350 conns_per_sec_recent = (double) new_connections / duration;
351 conns_per_sec_total = (double) total_connections / total_duration;
353 GNUNET_ERROR_TYPE_WARNING,
354 "Recent: %.2f/s, Total: %.2f/s, Recent failed: %.2f/s, total failed %.2f/s\n",
355 conns_per_sec_recent, CONN_UPDATE_DURATION,
356 conns_per_sec_total, failed_conns_per_sec_recent,
357 failed_conns_per_sec_total);
358 connect_last_time = GNUNET_TIME_absolute_get ();
359 previous_connections = total_connections;
360 previous_failed_connections = failed_connections;
361 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
362 "have %u total_connections, %u failed\n", total_connections,
370 pg_start_ctx->total_connections++;
372 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s, distance %u\n",
373 first_daemon->shortname,
374 second_daemon->shortname,
377 if (pg_start_ctx->topology_output_file != NULL)
379 second_str = GNUNET_strdup(GNUNET_i2s(second));
380 temp = GNUNET_asprintf(&temp_str, "\t\"%s\" -- \"%s\"\n", GNUNET_i2s(first), second_str);
381 GNUNET_free(second_str);
383 GNUNET_DISK_file_write(pg_start_ctx->topology_output_file, temp_str, temp);
384 GNUNET_free(temp_str);
389 pg_start_ctx->failed_connections++;
391 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to connect peer %s to peer %s with error :\n%s\n",
392 first_daemon->shortname,
393 second_daemon->shortname, emsg);
395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error :\n%s\n",
396 first_daemon->shortname,
397 second_daemon->shortname, emsg);
401 GNUNET_assert(pg_start_ctx->connect_meter != NULL);
402 if (pg_start_ctx->connect_cb != NULL)
403 pg_start_ctx->connect_cb(pg_start_ctx->cls, first,
411 if (GNUNET_YES == update_meter (pg_start_ctx->connect_meter))
414 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
415 "Created %d total connections, which is our target number! Starting next phase of testing.\n",
421 = GNUNET_TIME_absolute_get_difference (connect_start_time,
422 GNUNET_TIME_absolute_get ()).rel_value
424 failed_conns_per_sec_total = (double) failed_connections / total_duration;
425 conns_per_sec_total = (double) total_connections / total_duration;
426 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
427 "Overall connection info --- Total: %u, Total Failed %u/s\n",
428 total_connections, failed_connections);
430 GNUNET_ERROR_TYPE_WARNING,
431 "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n",
432 conns_per_sec_total, failed_conns_per_sec_total);
435 GNUNET_assert(pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
436 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
438 /* Call final callback, signifying that the peer group has been started and connected */
439 if (pg_start_ctx->peergroup_cb != NULL)
440 pg_start_ctx->peergroup_cb(pg_start_ctx->cls, NULL);
442 if (pg_start_ctx->topology_output_file != NULL)
444 temp = GNUNET_asprintf(&temp_str, "}\n");
446 GNUNET_DISK_file_write(pg_start_ctx->topology_output_file, temp_str, temp);
447 GNUNET_free(temp_str);
448 GNUNET_DISK_file_close(pg_start_ctx->topology_output_file);
454 internal_peers_started_callback(void *cls, const struct GNUNET_PeerIdentity *id,
455 const struct GNUNET_CONFIGURATION_Handle *cfg,
456 struct GNUNET_TESTING_Daemon *d, const char *emsg)
458 struct PeerGroupStartupContext *pg_start_ctx = cls;
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462 "Failed to start daemon with error: `%s'\n", emsg);
465 GNUNET_assert (id != NULL);
468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
469 (num_peers - peers_left) + 1, num_peers);
472 pg_start_ctx->peers_left--;
474 if (GNUNET_YES == update_meter (pg_start_ctx->peer_start_meter))
477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
478 "All %d daemons started, now connecting peers!\n",
481 GNUNET_assert(pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
482 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
484 pg_start_ctx->expected_connections = UINT_MAX;
485 if ((pg_start_ctx->pg != NULL) && (pg_start_ctx->peers_left == 0))
487 pg_start_ctx->connect_start_time = GNUNET_TIME_absolute_get ();
488 pg_start_ctx->expected_connections
489 = GNUNET_TESTING_connect_topology (
491 pg_start_ctx->connect_topology,
492 pg_start_ctx->connect_topology_option,
493 pg_start_ctx->connect_topology_option_modifier,
494 DEFAULT_CONNECT_TIMEOUT,
495 pg_start_ctx->connect_attempts,
498 pg_start_ctx->connect_meter
499 = create_meter (pg_start_ctx->expected_connections,
500 "Peer connection ", pg_start_ctx->verbose);
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502 "Have %d expected connections\n",
503 pg_start_ctx->expected_connections);
506 if (pg_start_ctx->expected_connections == 0)
508 GNUNET_free_non_null(pg_start_ctx->fail_reason);
509 pg_start_ctx->fail_reason = GNUNET_strdup("from connect topology (bad return)");
510 pg_start_ctx->die_task
511 = GNUNET_SCHEDULER_add_now (&end_badly,
515 GNUNET_free_non_null(pg_start_ctx->fail_reason);
516 pg_start_ctx->fail_reason = GNUNET_strdup("from connect topology (timeout)");
517 pg_start_ctx->die_task
518 = GNUNET_SCHEDULER_add_delayed (
519 GNUNET_TIME_absolute_get_remaining (pg_start_ctx->timeout),
526 * Callback indicating that the hostkey was created for a peer.
529 * @param id the peer identity
530 * @param d the daemon handle (pretty useless at this point, remove?)
531 * @param emsg non-null on failure
534 internal_hostkey_callback(void *cls, const struct GNUNET_PeerIdentity *id,
535 struct GNUNET_TESTING_Daemon *d, const char *emsg)
537 struct PeerGroupStartupContext *pg_start_ctx = cls;
538 unsigned int create_expected_connections;
542 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
543 "Hostkey callback received error: %s\n", emsg);
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Hostkey (%d/%d) created for peer `%s'\n",
549 num_peers - peers_left, num_peers, GNUNET_i2s(id));
552 pg_start_ctx->peers_left--;
553 if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter))
555 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
556 /* Set up task in case topology creation doesn't finish
557 * within a reasonable amount of time */
558 pg_start_ctx->die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
560 "from create_topology");
561 pg_start_ctx->peers_left = pg_start_ctx->total; /* Reset counter */
562 create_expected_connections = GNUNET_TESTING_create_topology (pg_start_ctx->pg, pg_start_ctx->topology, pg_start_ctx->restrict_topology,
563 pg_start_ctx->restrict_transports);
564 if (create_expected_connections > 0)
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
567 "Topology set up, have %u expected connections, now starting peers!\n", create_expected_connections);
568 GNUNET_TESTING_daemons_continue_startup (pg_start_ctx->pg);
572 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
573 pg_start_ctx->die_task = GNUNET_SCHEDULER_add_now (&end_badly,
574 "from create topology (bad return)");
577 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
578 pg_start_ctx->die_task
579 = GNUNET_SCHEDULER_add_delayed (
580 GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
582 "from continue startup (timeout)");
588 * Prototype of a callback function indicating that two peers
589 * are currently connected.
592 * @param first peer id for first daemon
593 * @param second peer id for the second daemon
594 * @param distance distance between the connected peers
595 * @param emsg error message (NULL on success)
598 write_topology_cb (void *cls,
599 const struct GNUNET_PeerIdentity *first,
600 const struct GNUNET_PeerIdentity *second,
603 struct TopologyOutputContext *topo_ctx;
608 topo_ctx = (struct TopologyOutputContext *)cls;
609 GNUNET_assert(topo_ctx->file != NULL);
610 if ((emsg == NULL) && (first != NULL) && (second != NULL))
612 GNUNET_assert(first != NULL);
613 GNUNET_assert(second != NULL);
614 temp_pid2 = GNUNET_strdup(GNUNET_i2s(second));
615 temp = GNUNET_asprintf(&temp_str, "\t\"%s\" -- \"%s\"\n", GNUNET_i2s(first), temp_pid2);
616 GNUNET_free(temp_pid2);
617 GNUNET_DISK_file_write(topo_ctx->file, temp_str, temp);
619 else if ((emsg == NULL) && (first == NULL) && (second == NULL))
621 temp = GNUNET_asprintf(&temp_str, "}\n");
622 GNUNET_DISK_file_write(topo_ctx->file, temp_str, temp);
623 GNUNET_DISK_file_close(topo_ctx->file);
624 topo_ctx->notify_cb(topo_ctx->notify_cb_cls, NULL);
625 GNUNET_free(topo_ctx);
629 temp = GNUNET_asprintf(&temp_str, "}\n");
630 GNUNET_DISK_file_write(topo_ctx->file, temp_str, temp);
631 GNUNET_DISK_file_close(topo_ctx->file);
632 topo_ctx->notify_cb(topo_ctx->notify_cb_cls, emsg);
633 GNUNET_free(topo_ctx);
638 * Print current topology to a graphviz readable file.
640 * @param pg a currently running peergroup to print to file
641 * @param output_filename the file to write the topology to
642 * @param notify_cb callback to call upon completion or failure
643 * @param notify_cb_cls closure for notify_cb
647 GNUNET_TESTING_peergroup_topology_to_file(struct GNUNET_TESTING_PeerGroup *pg,
648 const char *output_filename,
649 GNUNET_TESTING_NotifyCompletion notify_cb,
652 struct TopologyOutputContext *topo_ctx;
655 topo_ctx = GNUNET_malloc(sizeof(struct TopologyOutputContext));
657 topo_ctx->notify_cb = notify_cb;
658 topo_ctx->notify_cb_cls = notify_cb_cls;
659 topo_ctx->file = GNUNET_DISK_file_open (output_filename, GNUNET_DISK_OPEN_READWRITE
660 | GNUNET_DISK_OPEN_CREATE,
661 GNUNET_DISK_PERM_USER_READ |
662 GNUNET_DISK_PERM_USER_WRITE);
663 if (topo_ctx->file == NULL)
665 notify_cb (notify_cb_cls, "Failed to open output file!");
666 GNUNET_free (topo_ctx);
670 temp = GNUNET_asprintf(&temp_str, "strict graph G {\n");
672 GNUNET_DISK_file_write(topo_ctx->file, temp_str, temp);
673 GNUNET_free_non_null(temp_str);
674 GNUNET_TESTING_get_topology(pg, &write_topology_cb, topo_ctx);
678 * Start a peer group with a given number of peers. Notify
679 * on completion of peer startup and connection based on given
680 * topological constraints. Optionally notify on each
681 * established connection.
683 * @param cfg configuration template to use
684 * @param total number of daemons to start
685 * @param timeout total time allowed for peers to start
686 * @param connect_cb function to call each time two daemons are connected
687 * @param peergroup_cb function to call once all peers are up and connected
688 * @param peergroup_cls closure for peergroup callbacks
689 * @param hostnames linked list of host structs to use to start peers on
690 * (NULL to run on localhost only)
692 * @return NULL on error, otherwise handle to control peer group
694 struct GNUNET_TESTING_PeerGroup *
695 GNUNET_TESTING_peergroup_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
697 struct GNUNET_TIME_Relative timeout,
698 GNUNET_TESTING_NotifyConnection connect_cb,
699 GNUNET_TESTING_NotifyCompletion peergroup_cb,
701 const struct GNUNET_TESTING_Host *hostnames)
703 struct PeerGroupStartupContext *pg_start_ctx;
704 unsigned long long temp_config_number;
707 GNUNET_assert(total > 0);
708 GNUNET_assert(cfg != NULL);
710 pg_start_ctx = GNUNET_malloc(sizeof(struct PeerGroupStartupContext));
712 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
714 &pg_start_ctx->connect_attempts))
716 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
717 "testing", "connect_attempts");
718 GNUNET_free(pg_start_ctx);
723 != GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
724 "max_outstanding_connections",
725 &pg_start_ctx->max_concurrent_connections))
727 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
728 "testing", "max_outstanding_connections");
729 GNUNET_free(pg_start_ctx);
733 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
734 "max_concurrent_ssh",
735 &pg_start_ctx->max_concurrent_ssh))
737 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
738 "testing", "max_concurrent_ssh");
739 GNUNET_free(pg_start_ctx);
743 if (GNUNET_SYSERR == (pg_start_ctx->verbose = GNUNET_CONFIGURATION_get_value_yesno (cfg, "testing",
744 "use_progressbars")))
746 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
747 "testing", "use_progressbars");
748 GNUNET_free(pg_start_ctx);
752 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
754 &temp_config_number))
755 pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute(GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
756 temp_config_number));
759 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
760 "testing", "peergroup_timeout");
761 GNUNET_free(pg_start_ctx);
766 /* Read topology related options from the configuration file */
768 if ((GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
771 && (GNUNET_NO == GNUNET_TESTING_topology_get (&pg_start_ctx->topology, temp_str)))
773 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
774 "Invalid topology `%s' given for section %s option %s\n",
775 temp_str, "TESTING", "TOPOLOGY");
776 pg_start_ctx->topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */
778 GNUNET_free_non_null(temp_str);
780 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(cfg, "testing", "topology_output_file", &temp_str))
782 pg_start_ctx->topology_output_file = GNUNET_DISK_file_open (temp_str, GNUNET_DISK_OPEN_READWRITE
783 | GNUNET_DISK_OPEN_CREATE,
784 GNUNET_DISK_PERM_USER_READ |
785 GNUNET_DISK_PERM_USER_WRITE);
786 if (pg_start_ctx->topology_output_file != NULL)
788 GNUNET_free(temp_str);
789 temp = GNUNET_asprintf(&temp_str, "strict graph G {\n");
791 GNUNET_DISK_file_write(pg_start_ctx->topology_output_file, temp_str, temp);
793 GNUNET_free(temp_str);
797 != GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "percentage",
799 pg_start_ctx->topology_percentage = 0.5;
802 pg_start_ctx->topology_percentage = atof (temp_str);
803 GNUNET_free(temp_str);
807 != GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "probability",
809 pg_start_ctx->topology_probability = 0.5;
812 pg_start_ctx->topology_probability = atof (temp_str);
813 GNUNET_free(temp_str);
817 == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
820 && (GNUNET_NO == GNUNET_TESTING_topology_get (&pg_start_ctx->connect_topology,
824 GNUNET_ERROR_TYPE_WARNING,
825 "Invalid connect topology `%s' given for section %s option %s\n",
826 temp_str, "TESTING", "CONNECT_TOPOLOGY");
828 GNUNET_free_non_null(temp_str);
831 == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
832 "connect_topology_option",
835 == GNUNET_TESTING_topology_option_get (&pg_start_ctx->connect_topology_option,
839 GNUNET_ERROR_TYPE_WARNING,
840 "Invalid connect topology option `%s' given for section %s option %s\n",
842 "CONNECT_TOPOLOGY_OPTION");
843 pg_start_ctx->connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */
845 GNUNET_free_non_null(temp_str);
848 == GNUNET_CONFIGURATION_get_value_string (cfg,
850 "connect_topology_option_modifier",
853 if (sscanf (temp_str, "%lf",
854 &pg_start_ctx->connect_topology_option_modifier) != 1)
857 GNUNET_ERROR_TYPE_WARNING,
858 _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
860 "connect_topology_option_modifier", "TESTING");
861 GNUNET_free (temp_str);
862 GNUNET_free(pg_start_ctx);
865 GNUNET_free (temp_str);
869 != GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
870 "blacklist_transports",
871 &pg_start_ctx->restrict_transports))
872 pg_start_ctx->restrict_transports = NULL;
874 pg_start_ctx->restrict_topology = GNUNET_TESTING_TOPOLOGY_NONE;
876 == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
877 "blacklist_topology",
879 && (GNUNET_NO == GNUNET_TESTING_topology_get (&pg_start_ctx->restrict_topology,
882 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
883 "Invalid topology `%s' given for section %s option %s\n",
884 temp_str, "TESTING", "BLACKLIST_TOPOLOGY");
887 GNUNET_free_non_null(temp_str);
889 pg_start_ctx->cfg = cfg;
890 pg_start_ctx->total = total;
891 pg_start_ctx->peers_left = total;
892 pg_start_ctx->connect_cb = connect_cb;
893 pg_start_ctx->peergroup_cb = peergroup_cb;
894 pg_start_ctx->cls = peergroup_cls;
895 pg_start_ctx->hostnames = hostnames;
896 pg_start_ctx->hostkey_meter = create_meter (pg_start_ctx->peers_left, "Hostkeys created ", pg_start_ctx->verbose);
897 pg_start_ctx->peer_start_meter = create_meter (pg_start_ctx->peers_left, "Peers started ", pg_start_ctx->verbose);
898 /* Make compilers happy */
899 reset_meter(pg_start_ctx->peer_start_meter);
900 pg_start_ctx->die_task
901 = GNUNET_SCHEDULER_add_delayed (
902 GNUNET_TIME_absolute_get_remaining (
903 pg_start_ctx->timeout),
905 "didn't generate all hostkeys within allowed startup time!");
908 = GNUNET_TESTING_daemons_start (
910 pg_start_ctx->peers_left,
911 pg_start_ctx->max_concurrent_connections,
912 pg_start_ctx->max_concurrent_ssh,
913 GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
914 &internal_hostkey_callback, pg_start_ctx,
915 &internal_peers_started_callback,
917 &internal_topology_callback,
918 pg_start_ctx, pg_start_ctx->hostnames);
920 return pg_start_ctx->pg;
923 /* end of testing_peergroup.c */