diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-05 09:49:58 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-05 09:49:58 +0000 |
commit | 96884ee94297035e20e29eed83d15e38e9e7797b (patch) | |
tree | 4ca00d5688e998cce07f7149473bc767869f5a53 /src/testbed/testbed_api_testbed.c | |
parent | 49f7d44deb51f4cd7f8027d5a1fac9d7ddef1f27 (diff) |
- warn and wait for all operations to be completed
Diffstat (limited to 'src/testbed/testbed_api_testbed.c')
-rw-r--r-- | src/testbed/testbed_api_testbed.c | 182 |
1 files changed, 73 insertions, 109 deletions
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c index 064e43b9f7..dae364699a 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" @@ -242,11 +243,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 */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; @@ -257,11 +253,6 @@ struct RunContext GNUNET_SCHEDULER_TaskIdentifier interrupt_task; /** - * Task for cleaning up the run context and various resources it uses - */ - GNUNET_SCHEDULER_TaskIdentifier cleanup_task; - - /** * The event mask for the controller */ uint64_t event_mask; @@ -448,7 +439,7 @@ remove_rcop (struct RunContext *rc, struct RunContextOperation *rcop) * @param tc the task context from scheduler */ static void -cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +cleanup (void *cls) { struct RunContext *rc = cls; unsigned int hid; @@ -478,20 +469,6 @@ cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Perform the cleanup task now - * - * @param rc the run context to be cleaned up - */ -static void -cleanup_now (struct RunContext *rc) -{ - if (GNUNET_SCHEDULER_NO_TASK != rc->cleanup_task) - GNUNET_SCHEDULER_cancel (rc->cleanup_task); - rc->cleanup_task = GNUNET_SCHEDULER_add_now (&cleanup, rc); -} - - -/** * Iterator for cleaning up elements from rcop_map * * @param cls the RunContext @@ -514,21 +491,6 @@ rcop_cleanup_iterator (void *cls, uint32_t key, void *value) /** - * Cleanup existing operation in given run context - * - * @param rc the run context - */ -static void -cleanup_operations (struct RunContext *rc) -{ - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map, - &rcop_cleanup_iterator, - rc)); -} - - -/** * Cancels operations and tasks which are assigned to the given run context * * @param rc the RunContext @@ -561,11 +523,6 @@ rc_cleanup_operations (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); @@ -577,66 +534,71 @@ rc_cleanup_operations (struct RunContext *rc) rc->topology_operation = NULL; } /* cancel any exiting operations */ - cleanup_operations (rc); + GNUNET_assert (GNUNET_SYSERR != + GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map, + &rcop_cleanup_iterator, + 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 RunContext *rc) +{ + GNUNET_SCHEDULER_cancel (rc->interrupt_task); + rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; +} + + +/** + * This callback will be called when all the operations are completed + * (done/cancelled) + * + * @param cls run context + * @param tc scheduler task context + */ +static void +wait_op_completion (void *cls) { 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; - rc_cleanup_operations (rc); - if (NULL != rc->c) + if ( (NULL == rc->cproc) + || (NULL == rc->c) + || (GNUNET_YES == rc->shutdown) ) { 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; + GNUNET_free (rc->peers); + rc->peers = NULL; } + goto cleanup_; } - rc->state = RC_PEERS_SHUTDOWN; /* No peers are present so we consider the - * state where all peers are SHUTDOWN */ - cleanup_now (rc); -} - + if (NULL == rc->peers) + goto cleanup_; + rc->shutdown = GNUNET_YES; + 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; -/** - * Function to shutdown now - * - * @param rc the RunContext - */ -static void -shutdown_now (struct RunContext *rc) -{ - 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); + 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 @@ -645,9 +607,24 @@ static void interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RunContext *rc = cls; + struct GNUNET_TESTBED_Controller *c = rc->c; + unsigned int size; - rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; - shutdown_now (rc); + /* 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); } @@ -721,7 +698,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; @@ -830,7 +807,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++; @@ -846,7 +823,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) return; default: GNUNET_break (0); - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } } @@ -862,7 +839,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); @@ -875,7 +852,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)); - cleanup_now (rc); + GNUNET_SCHEDULER_shutdown (); break; default: GNUNET_assert (0); @@ -972,7 +949,7 @@ host_registration_completion (void *cls, const char *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); @@ -1037,20 +1014,7 @@ controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Controller crash detected. Shutting down.\n")); - rc->cproc = NULL; - rc_cleanup_operations (rc); - if (NULL != rc->peers) - { - GNUNET_free (rc->peers); - rc->peers = NULL; - } - if (GNUNET_YES == rc->shutdown) - { - rc->state = RC_PEERS_SHUTDOWN; - cleanup_now (rc); - } - else - shutdown_now (rc); + GNUNET_SCHEDULER_shutdown (); return; } GNUNET_CONFIGURATION_destroy (rc->cfg); @@ -1143,7 +1107,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++; @@ -1181,7 +1145,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 (); } } @@ -1199,7 +1163,7 @@ timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 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 = NULL; |