X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftestbed%2Ftestbed_api_testbed.c;h=2be565e63c182a5fe3292eb709bd8f402b516580;hb=8a2d1e6aedbf1bc95052e63ac67093b89385b0a1;hp=98b8eaad1a95a183657cadf0fe91c573c4833e52;hpb=11f22e574f38ecb8698f6b457f39d84632aedf6d;p=oweals%2Fgnunet.git diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c index 98b8eaad1..2be565e63 100644 --- a/src/testbed/testbed_api_testbed.c +++ b/src/testbed/testbed_api_testbed.c @@ -28,6 +28,7 @@ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" +#include "testbed_api.h" #include "testbed_api_peers.h" #include "testbed_api_hosts.h" #include "testbed_api_topology.h" @@ -49,10 +50,23 @@ */ #define DEFAULT_SETUP_TIMEOUT 300 + /** - * Testbed Run Handle + * Configuration section for testbed + */ +#define TESTBED_CONFIG_SECTION "testbed" + +/** + * Option string for the maximum number of edges a peer is permitted to have + * while generating scale free topology + */ +#define SCALE_FREE_CAP "SCALE_FREE_TOPOLOGY_CAP" + +/** + * Option string for the number of edges to be established when adding a new + * node to the scale free network */ -struct RunContext; +#define SCALE_FREE_M "SCALE_FREE_TOPOLOGY_M" /** * Context information for the operation we start @@ -67,7 +81,7 @@ struct RunContextOperation /** * Context information for GNUNET_TESTBED_run() */ - struct RunContext *rc; + struct GNUNET_TESTBED_RunHandle *rc; /** * Closure @@ -87,13 +101,6 @@ enum State */ RC_INIT = 0, -#if ENABLE_LL - /** - * Island level controllers are started and linked - */ - RC_ISLANDS_LINKED, -#endif - /** * Controllers on given hosts started and linked */ @@ -136,7 +143,7 @@ struct CompatibilityCheckContext /** * The run context */ - struct RunContext *rc; + struct GNUNET_TESTBED_RunHandle *rc; /** * Handle for the compability check @@ -149,28 +156,11 @@ struct CompatibilityCheckContext unsigned int index; }; -#if ENABLE_LL -/** - * Structure to represent an island of SuperMUC's nodes - */ -struct Island -{ - /** - * Array of nodes in this island - */ - struct GNUNET_TESTBED_Host **hosts; - - /** - * Number of nodes in the above array - */ - unsigned int nhosts; -}; -#endif /** * Testbed Run Handle */ -struct RunContext +struct GNUNET_TESTBED_RunHandle { /** * The controller handle @@ -229,13 +219,6 @@ struct RunContext */ struct GNUNET_TESTBED_Host **hosts; -#if ENABLE_LL - /** - * Array of SuperMUC islands - */ - struct Island **islands; -#endif - /** * Array of compatibility check contexts */ @@ -253,8 +236,7 @@ struct RunContext struct GNUNET_TESTBED_Operation *topology_operation; /** - * The file containing topology data. Only used if the topology is set to - * 'FROM_FILE' + * The file containing topology data. Only used if the topology is set to 'FROM_FILE' */ char *topo_file; @@ -273,11 +255,6 @@ struct RunContext */ GNUNET_SCHEDULER_TaskIdentifier register_hosts_task; - /** - * Task to be run while shutting down - */ - GNUNET_SCHEDULER_TaskIdentifier shutdown_run_task; - /** * Task to be run of a timeout */ @@ -350,12 +327,6 @@ struct RunContext */ unsigned int links_failed; -#if ENABLE_LL - /** - * Number of SuperMUC islands we are running on - */ - unsigned int nislands; -#endif }; @@ -367,7 +338,7 @@ struct RunContext */ static uint32_t rcop_key (void *rcop) -{ +{ return * ((uint32_t *) &rcop); } @@ -423,13 +394,13 @@ search_iterator (void *cls, uint32_t key, void *value) * @return the matching RunContextOperation if found; NULL if not */ static struct RunContextOperation * -search_rcop (struct RunContext *rc, struct GNUNET_TESTBED_Operation *op) +search_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct GNUNET_TESTBED_Operation *op) { struct SearchContext sc; - + sc.query = op; sc.result = NULL; - if (GNUNET_SYSERR == + if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap32_get_multiple (rc->rcop_map, rcop_key (op), &search_iterator, @@ -449,7 +420,7 @@ search_rcop (struct RunContext *rc, struct GNUNET_TESTBED_Operation *op) * @param rcop the RunContextOperation to insert */ static void -insert_rcop (struct RunContext *rc, struct RunContextOperation *rcop) +insert_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct RunContextOperation *rcop) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (rc->rcop_map, @@ -466,7 +437,7 @@ insert_rcop (struct RunContext *rc, struct RunContextOperation *rcop) * @param rcop the RunContextOperation */ static void -remove_rcop (struct RunContext *rc, struct RunContextOperation *rcop) +remove_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct RunContextOperation *rcop) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (rc->rcop_map, @@ -474,36 +445,15 @@ remove_rcop (struct RunContext *rc, struct RunContextOperation *rcop) rcop)); } -#if ENABLE_LL -static void -cleanup_islands (struct RunContext *rc) -{ - struct Island *island; - unsigned int cnt; - - GNUNET_assert (NULL != rc->islands); - for (cnt = 0; cnt < rc->nislands; cnt++) - { - island = rc->islands[cnt]; - GNUNET_free (island->hosts); - GNUNET_free (island); - } - GNUNET_free (rc->islands); - rc->islands = NULL; -} -#endif - /** * Assuming all peers have been destroyed cleanup run handle * - * @param cls the run handle - * @param tc the task context from scheduler + * @param rc the run context */ static void -cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +cleanup (struct GNUNET_TESTBED_RunHandle *rc) { - struct RunContext *rc = cls; - unsigned int cnt; + unsigned int hid; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rc->register_hosts_task); GNUNET_assert (NULL == rc->reg_handle); @@ -518,12 +468,8 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_TESTBED_controller_stop (rc->cproc); if (NULL != rc->h) GNUNET_TESTBED_host_destroy (rc->h); -#if ENABLE_LL - if (NULL != rc->islands) - cleanup_islands (rc); -#endif - for (cnt = 0; cnt < rc->num_hosts; cnt++) - GNUNET_TESTBED_host_destroy (rc->hosts[cnt]); + for (hid = 0; hid < rc->num_hosts; hid++) + GNUNET_TESTBED_host_destroy (rc->hosts[hid]); GNUNET_free_non_null (rc->hosts); if (NULL != rc->cfg) GNUNET_CONFIGURATION_destroy (rc->cfg); @@ -534,7 +480,7 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Iterator for cleaning up elements from rcop_map + * Iterator for cleaning up elements from rcop_map * * @param cls the RunContext * @param key the 32-bit key @@ -544,7 +490,7 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static int rcop_cleanup_iterator (void *cls, uint32_t key, void *value) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop = value; GNUNET_assert (rc == rcop->rc); @@ -556,13 +502,12 @@ rcop_cleanup_iterator (void *cls, uint32_t key, void *value) /** - * Frees memory, closes pending operations, cancels actives tasks of the given - * RunContext + * Cancels operations and tasks which are assigned to the given run context * * @param rc the RunContext */ static void -cleanup (struct RunContext *rc) +rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc) { struct CompatibilityCheckContext *hc; unsigned int nhost; @@ -589,11 +534,6 @@ cleanup (struct RunContext *rc) GNUNET_SCHEDULER_cancel (rc->timeout_task); rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; } - if (GNUNET_SCHEDULER_NO_TASK != rc->interrupt_task) - { - GNUNET_SCHEDULER_cancel (rc->interrupt_task); - rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; - } if (NULL != rc->reg_handle) { GNUNET_TESTBED_cancel_registration (rc->reg_handle); @@ -605,7 +545,7 @@ cleanup (struct RunContext *rc) rc->topology_operation = NULL; } /* cancel any exiting operations */ - GNUNET_assert (GNUNET_SYSERR != + GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map, &rcop_cleanup_iterator, rc)); @@ -613,61 +553,62 @@ cleanup (struct RunContext *rc) /** - * Stops the testbed run and releases any used resources + * Cancels the scheduled interrupt task * - * @param cls the tesbed run handle - * @param tc the task context from scheduler + * @param rc the run context */ static void -shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc) { - struct RunContext *rc = cls; - struct RunContextOperation *rcop; - - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task); - rc->shutdown_run_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_assert (GNUNET_NO == rc->shutdown); - rc->shutdown = GNUNET_YES; - cleanup (rc); - if (NULL != rc->c) - { - if (NULL != rc->peers) - { - rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); - rcop->rc = rc; - rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL); - GNUNET_assert (NULL != rcop->op); - DEBUG ("Shutting down peers\n"); - rc->pstart_time = GNUNET_TIME_absolute_get (); - insert_rcop (rc, rcop); - return; - } - } - rc->state = RC_PEERS_SHUTDOWN; /* No peers are present so we consider the - * state where all peers are SHUTDOWN */ - GNUNET_SCHEDULER_add_now (&cleanup_task, rc); + GNUNET_SCHEDULER_cancel (rc->interrupt_task); + rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; } /** - * Function to shutdown now + * This callback will be called when all the operations are completed + * (done/cancelled) * - * @param rc the RunContext + * @param cls run context */ static void -shutdown_now (struct RunContext *rc) +wait_op_completion (void *cls) { - if (GNUNET_YES == rc->shutdown) - return; - if (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task) - GNUNET_SCHEDULER_cancel (rc->shutdown_run_task); - GNUNET_SCHEDULER_shutdown (); /* Trigger shutdown in programs using this API */ - rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc); + struct GNUNET_TESTBED_RunHandle *rc = cls; + struct RunContextOperation *rcop; + + if ( (NULL == rc->cproc) + || (NULL == rc->c) + || (GNUNET_YES == rc->shutdown) ) + { + if (NULL != rc->peers) + { + GNUNET_free (rc->peers); + rc->peers = NULL; + } + goto cleanup_; + } + if (NULL == rc->peers) + goto cleanup_; + rc->shutdown = GNUNET_YES; + rcop = GNUNET_new (struct RunContextOperation); + rcop->rc = rc; + rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL); + GNUNET_assert (NULL != rcop->op); + DEBUG ("Shutting down peers\n"); + rc->pstart_time = GNUNET_TIME_absolute_get (); + insert_rcop (rc, rcop); + return; + + cleanup_: + rc->state = RC_PEERS_SHUTDOWN; + cancel_interrupt_task (rc); + cleanup (rc); } /** - * Task run upon any interrupt. Common ones are SIGINT & SIGTERM. + * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown. * * @param cls the RunContext which has to be acted upon * @param tc the scheduler task context @@ -675,10 +616,25 @@ shutdown_now (struct RunContext *rc) static void interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct RunContext *rc = cls; - - rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; - shutdown_now (rc); + struct GNUNET_TESTBED_RunHandle *rc = cls; + struct GNUNET_TESTBED_Controller *c = rc->c; + unsigned int size; + + /* reschedule */ + rc->interrupt_task = GNUNET_SCHEDULER_add_delayed + (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt, rc); + rc_cleanup_operations (rc); + if ( (GNUNET_NO == rc->shutdown) + && (NULL != c) + && (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map)))) + { + LOG (GNUNET_ERROR_TYPE_WARNING, "Shutdown postponed as there are " + "%u operations currently active\n", size); + c->opcq_empty_cb = &wait_op_completion; + c->opcq_empty_cls = rc; + return; + } + wait_op_completion (rc); } @@ -690,7 +646,7 @@ interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @return the representation string; this is NOT reentrant */ static const char * -prof_time (struct RunContext *rc) +prof_time (struct GNUNET_TESTBED_RunHandle *rc) { struct GNUNET_TIME_Relative ptime; @@ -708,7 +664,7 @@ prof_time (struct RunContext *rc) static void start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; unsigned int peer; @@ -716,7 +672,7 @@ start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) rc->pstart_time = GNUNET_TIME_absolute_get (); for (peer = 0; peer < rc->num_peers; peer++) { - rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); + rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL); GNUNET_assert (NULL != rcop->op); @@ -740,7 +696,7 @@ static void peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) { struct RunContextOperation *rcop = cls; - struct RunContext *rc; + struct GNUNET_TESTBED_RunHandle *rc; GNUNET_assert (NULL != rcop); GNUNET_assert (NULL != (rc = rcop->rc)); @@ -752,7 +708,7 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) if (NULL != emsg) LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n", emsg); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } rc->peers[rc->peer_count] = peer; @@ -771,12 +727,12 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) * @param rc the RunContext */ static void -call_master (struct RunContext *rc) +call_master (struct GNUNET_TESTBED_RunHandle *rc) { GNUNET_SCHEDULER_cancel (rc->timeout_task); rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != rc->test_master) - rc->test_master (rc->test_master_cls, rc->num_peers, rc->peers, + rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers, rc->links_succeeded, rc->links_failed); } @@ -794,7 +750,7 @@ static void topology_completion_callback (void *cls, unsigned int nsuccess, unsigned int nfailures) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; DEBUG ("Overlay topology generated in %s\n", prof_time (rc)); GNUNET_TESTBED_operation_done (rc->topology_operation); @@ -812,20 +768,11 @@ topology_completion_callback (void *cls, unsigned int nsuccess, * @param rc the RunContext */ static void -create_peers (struct RunContext *rc) +create_peers (struct GNUNET_TESTBED_RunHandle *rc) { struct RunContextOperation *rcop; - struct GNUNET_TESTBED_Host *host; unsigned int peer; -#if ENABLE_LL - struct Island *island; - unsigned int icnt; - unsigned int hcnt; - - island = NULL; - icnt = 0; - hcnt = 0; -#endif + DEBUG ("Creating peers\n"); rc->pstart_time = GNUNET_TIME_absolute_get (); rc->peers = @@ -834,35 +781,14 @@ create_peers (struct RunContext *rc) rc->peer_count = 0; for (peer = 0; peer < rc->num_peers; peer++) { - rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); + rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; -#if ENABLE_LL - if (0 != rc->nislands) - { - island = rc->islands[icnt]; - if (hcnt == island->nhosts) - { - icnt++; - if (icnt == rc->nislands) - icnt = 0; - island = rc->islands[icnt]; - hcnt = 0; - } - if ( (0 == hcnt) && (1 < island->nhosts) ) - hcnt = 1; - GNUNET_assert (icnt < rc->nislands); - GNUNET_assert (hcnt < island->nhosts); - GNUNET_assert (NULL != island->hosts[hcnt]); - host = island->hosts[hcnt]; - hcnt++; - } - else - host = rc->h; -#else - host = (0 == rc->num_hosts) ? rc->h : rc->hosts[peer % rc->num_hosts]; -#endif - rcop->op = GNUNET_TESTBED_peer_create (rc->c, host, rc->cfg, - &peer_create_cb, rcop); + rcop->op = + GNUNET_TESTBED_peer_create (rc->c, + (0 == + rc->num_hosts) ? rc->h : rc->hosts[peer % + rc->num_hosts], + rc->cfg, &peer_create_cb, rcop); GNUNET_assert (NULL != rcop->op); insert_rcop (rc, rcop); } @@ -879,7 +805,7 @@ create_peers (struct RunContext *rc) static void event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; if (RC_INIT == rc->state) @@ -891,7 +817,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) if (NULL != event->details.operation_finished.emsg) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Linking controllers failed. Exiting")); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); } else rc->reg_hosts++; @@ -899,79 +825,18 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) remove_rcop (rc, rcop); GNUNET_TESTBED_operation_done (rcop->op); GNUNET_free (rcop); -#if !ENABLE_LL - if (rc->reg_hosts != rc->num_hosts) - return; - rc->state = RC_LINKED; - create_peers (rc); -#else - if (rc->reg_hosts != rc->nislands) - return; - struct Island *island; - struct GNUNET_TESTBED_Host *host; - unsigned int cnt; - unsigned int cnt2; - rc->state = RC_ISLANDS_LINKED; - rc->reg_hosts = 0; - for (cnt = 0; cnt < rc->nislands; cnt++) - { - island = rc->islands[cnt]; - for (cnt2 = 1; cnt2 < island->nhosts; cnt2++) - { - host = island->hosts[cnt2]; - rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); - rcop->rc = rc; - rcop->op = - GNUNET_TESTBED_controller_link (rcop, rc->c, host, - island->hosts[0], GNUNET_YES); - GNUNET_assert (NULL != rcop->op); - insert_rcop (rc, rcop); - rc->reg_hosts++; - } - } - if (0 != rc->reg_hosts) - return; - rc->state = RC_LINKED; - create_peers (rc); -#endif - return; - default: - GNUNET_break (0); - shutdown_now (rc); - return; - } - } -#if ENABLE_LL - if (RC_ISLANDS_LINKED == rc->state) - { - switch (event->type) - { - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - rcop = event->op_cls; - if (NULL != event->details.operation_finished.emsg) + if (rc->reg_hosts == rc->num_hosts) { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Linking 2nd level controllers failed. Exiting"); - shutdown_now (rc); + rc->state = RC_LINKED; + create_peers (rc); } - else - rc->reg_hosts--; - GNUNET_assert (event->op == rcop->op); - remove_rcop (rc, rcop); - GNUNET_TESTBED_operation_done (rcop->op); - GNUNET_free (rcop); - if (0 != rc->reg_hosts) - return; - rc->state = RC_LINKED; - create_peers (rc); return; default: GNUNET_break (0); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } } -#endif if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) goto call_cc; if (NULL == (rcop = search_rcop (rc, event->op))) @@ -984,7 +849,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n", event->details.operation_finished.emsg); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } GNUNET_assert (GNUNET_YES == rc->shutdown); @@ -997,7 +862,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) GNUNET_free_non_null (rc->peers); rc->peers = NULL; DEBUG ("Peers shut down in %s\n", prof_time (rc)); - GNUNET_SCHEDULER_add_now (&cleanup_task, rc); + GNUNET_SCHEDULER_shutdown (); break; default: GNUNET_assert (0); @@ -1020,10 +885,13 @@ call_cc: DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc)); if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology) { - if ((GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI == rc->topology) || - (GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING == rc->topology) || - (GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD == rc->topology)) + switch (rc->topology) { + case GNUNET_TESTBED_TOPOLOGY_NONE: + GNUNET_assert (0); + case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: + case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: + case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, rc->peers, &rc->num_oc, @@ -1032,9 +900,8 @@ call_cc: rc->topology, rc->random_links, GNUNET_TESTBED_TOPOLOGY_OPTION_END); - } - else if (GNUNET_TESTBED_TOPOLOGY_FROM_FILE == rc->topology) - { + break; + case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: GNUNET_assert (NULL != rc->topo_file); rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, @@ -1044,8 +911,32 @@ call_cc: rc->topology, rc->topo_file, GNUNET_TESTBED_TOPOLOGY_OPTION_END); - } - else + break; + case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: + { + unsigned long long number; + unsigned int cap; + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, + SCALE_FREE_CAP, + &number)); + cap = (unsigned int) number; + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, + SCALE_FREE_M, + &number)); + rc->topology_operation = + GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, + rc->peers, &rc->num_oc, + &topology_completion_callback, + rc, + rc->topology, + cap, /* uint16_t */ + (unsigned int) number, /* uint8_t */ + GNUNET_TESTBED_TOPOLOGY_OPTION_END); + } + break; + default: rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, rc->peers, &rc->num_oc, @@ -1053,9 +944,10 @@ call_cc: rc, rc->topology, GNUNET_TESTBED_TOPOLOGY_OPTION_END); + } if (NULL == rc->topology_operation) LOG (GNUNET_ERROR_TYPE_WARNING, - "Not generating topology. Check number of peers\n"); + "Not generating a topology. Check number of peers\n"); else { DEBUG ("Creating overlay topology\n"); @@ -1087,14 +979,14 @@ register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void host_registration_completion (void *cls, const char *emsg) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; rc->reg_handle = NULL; if (NULL != emsg) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Host registration failed for a host. Error: %s\n"), emsg); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } rc->register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, rc); @@ -1110,41 +1002,25 @@ host_registration_completion (void *cls, const char *emsg) static void register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; - unsigned int cnt; + unsigned int slave; rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK; if (rc->reg_hosts == rc->num_hosts) { DEBUG ("All hosts successfully registered\n"); - /* Start cnts */ -#if !ENABLE_LL - for (cnt = 0; cnt < rc->num_hosts; cnt++) + /* Start slaves */ + for (slave = 0; slave < rc->num_hosts; slave++) { - rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); + rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; rcop->op = - GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[cnt], + GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave], rc->h, GNUNET_YES); GNUNET_assert (NULL != rcop->op); insert_rcop (rc, rcop); } -#else - struct Island *island; - for (cnt = 0; cnt < rc->nislands; cnt++) - { - island = rc->islands[cnt]; - GNUNET_assert (0 < island->nhosts); - rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); - rcop->rc = rc; - rcop->op = - GNUNET_TESTBED_controller_link (rcop, rc->c, island->hosts[0], - rc->h, GNUNET_YES); - GNUNET_assert (NULL != rcop->op); - insert_rcop (rc, rcop); - } -#endif rc->reg_hosts = 0; return; } @@ -1168,27 +1044,15 @@ static void controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; uint64_t event_mask; if (status != GNUNET_OK) { + rc->cproc = NULL; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Controller crash detected. Shutting down.\n")); - rc->cproc = NULL; - cleanup (rc); - if (NULL != rc->peers) - { - GNUNET_free (rc->peers); - rc->peers = NULL; - } - if (GNUNET_YES == rc->shutdown) - { - rc->state = RC_PEERS_SHUTDOWN; - GNUNET_SCHEDULER_add_now (&cleanup_task, rc); - } - else - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } GNUNET_CONFIGURATION_destroy (rc->cfg); @@ -1211,49 +1075,6 @@ controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, } -#if ENABLE_LL -#define ISLANDNAME_SIZE 4 -static void -parse_islands (struct RunContext *rc) -{ - char island_id[ISLANDNAME_SIZE]; - struct GNUNET_TESTBED_Host *host; - struct Island *island; - const char *hostname; - unsigned int nhost; - - DEBUG ("Parsing for islands\n"); - memset (island_id, 0, ISLANDNAME_SIZE); - island = NULL; - for (nhost = 0; nhost < rc->num_hosts; nhost++) - { - host = rc->hosts[nhost]; - hostname = GNUNET_TESTBED_host_get_hostname (host); - GNUNET_assert (NULL != hostname); - if (NULL == island) - { - strncpy (island_id, hostname, ISLANDNAME_SIZE - 1); - island = GNUNET_malloc (sizeof (struct Island)); - } - if (0 == strncmp (island_id, hostname, ISLANDNAME_SIZE - 1)) - { - GNUNET_array_append (island->hosts, island->nhosts, host); - continue; - } - DEBUG ("Adding island `%s' with %u hosts\n", island_id, island->nhosts); - GNUNET_array_append (rc->islands, rc->nislands, island); - island = NULL; - } - if (NULL != island) - { - DEBUG ("Adding island `%s' with %u hosts\n", island_id, island->nhosts); - GNUNET_array_append (rc->islands, rc->nislands, island); - } - DEBUG ("Total islands parsed: %u\n", rc->nislands); -} -#endif - - /** * Callback function invoked for each interface found. * @@ -1271,7 +1092,7 @@ netint_proc (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { - struct RunContext *rc = cls; + struct GNUNET_TESTBED_RunHandle *rc = cls; char hostip[NI_MAXHOST]; char *buf; @@ -1307,7 +1128,7 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, int status) { struct CompatibilityCheckContext *hc = cls; - struct RunContext *rc; + struct GNUNET_TESTBED_RunHandle *rc; struct GNUNET_TESTBED_Host **old_hosts; unsigned int nhost; @@ -1324,7 +1145,7 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, else LOG (GNUNET_ERROR_TYPE_ERROR, _("Testbed cannot be started on localhost\n")); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } rc->reg_hosts++; @@ -1348,9 +1169,6 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, GNUNET_free (rc->hosts); rc->hosts = NULL; } -#if ENABLE_LL - parse_islands (rc); -#endif GNUNET_TESTBED_host_resolve_ (rc->h); for (nhost = 0; nhost < rc->num_hosts; nhost++) GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]); @@ -1365,7 +1183,7 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, if (NULL == rc->cproc) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller")); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); } } @@ -1379,13 +1197,13 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, static void timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct RunContext *rc = cls; - + struct GNUNET_TESTBED_RunHandle *rc = cls; + rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_ERROR, _("Shutting down testbed due to timeout while setup.\n")); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); if (NULL != rc->test_master) - rc->test_master (rc->test_master_cls, 0, NULL, 0, 0); + rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0); rc->test_master = NULL; } @@ -1425,18 +1243,18 @@ GNUNET_TESTBED_run (const char *host_filename, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls) { - struct RunContext *rc; + struct GNUNET_TESTBED_RunHandle *rc; char *topology; - struct CompatibilityCheckContext *hc; + struct CompatibilityCheckContext *hc; struct GNUNET_TIME_Relative timeout; - unsigned long long random_links; + unsigned long long number; unsigned int hid; unsigned int nhost; GNUNET_assert (num_peers > 0); - rc = GNUNET_malloc (sizeof (struct RunContext)); + rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle); rc->cfg = GNUNET_CONFIGURATION_dup (cfg); -#if ENABLE_LL +#if ENABLE_SUPERMUC rc->num_hosts = GNUNET_TESTBED_hosts_load_from_loadleveler (rc->cfg, &rc->hosts); if (0 == rc->num_hosts) @@ -1470,12 +1288,12 @@ GNUNET_TESTBED_run (const char *host_filename, rc->state = RC_INIT; rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE; if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (rc->cfg, "testbed", + GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_TOPOLOGY", &topology)) { if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology)) { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "testbed", + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, "OVERLAY_TOPLOGY", _ ("Specified topology must be supported by testbed")); @@ -1488,37 +1306,73 @@ GNUNET_TESTBED_run (const char *host_filename, case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (rc->cfg, "testbed", + GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_RANDOM_LINKS", - &random_links)) + &number)) { /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS * option to be set to the number of random links to be established */ - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "testbed", + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, "OVERLAY_RANDOM_LINKS"); goto error_cleanup; } - if (random_links > UINT32_MAX) + if (number > UINT32_MAX) { GNUNET_break (0); /* Too big number */ goto error_cleanup; } - rc->random_links = (unsigned int) random_links; + rc->random_links = (unsigned int) number; break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (rc->cfg, "testbed", + GNUNET_CONFIGURATION_get_value_filename (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_TOPOLOGY_FILE", &rc->topo_file)) { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "testbed", + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, "OVERLAY_TOPOLOGY_FILE"); goto error_cleanup; } + goto warn_ignore; + case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, + SCALE_FREE_CAP, &number)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, + SCALE_FREE_CAP); + goto error_cleanup; + } + if (UINT16_MAX < number) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Maximum number of edges a peer can have in a scale free topology" + " cannot be more than %u. Given `%s = %llu'"), UINT16_MAX, + SCALE_FREE_CAP, number); + goto error_cleanup; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, + SCALE_FREE_M, &number)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, + SCALE_FREE_M); + goto error_cleanup; + } + if (UINT8_MAX < number) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("The number of edges that can established when adding a new node" + " to scale free topology cannot be more than %u. Given `%s = %llu'"), + UINT8_MAX, SCALE_FREE_M, number); + goto error_cleanup; + } + goto warn_ignore; default: + warn_ignore: /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */ if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (rc->cfg, "testbed", + GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_RANDOM_LINKS")) LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n"); @@ -1554,7 +1408,7 @@ GNUNET_TESTBED_run (const char *host_filename, rc->cproc = GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, &controller_status_cb, rc); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED", + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, TESTBED_CONFIG_SECTION, "SETUP_TIMEOUT", &timeout)) { @@ -1585,4 +1439,18 @@ error_cleanup: } +/** + * Obtain handle to the master controller from a testbed run. The handle + * returned should not be disconnected. + * + * @param h the testbed run handle + * @return handle to the master controller + */ +struct GNUNET_TESTBED_Controller * +GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h) +{ + return h->c; +} + + /* end of testbed_api_testbed.c */