From 673b8dadbe8cbc17d2c1391d16f15a0d7626b4fd Mon Sep 17 00:00:00 2001 From: "Nathan S. Evans" Date: Tue, 11 May 2010 07:35:38 +0000 Subject: [PATCH] more testing changes --- src/testing/testing.c | 69 ++++++++++++++++--- src/testing/testing_group.c | 130 +++++++++++++++++++++++++++++++++++- 2 files changed, 188 insertions(+), 11 deletions(-) diff --git a/src/testing/testing.c b/src/testing/testing.c index b05c02278..1bf3e40cd 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -126,7 +126,7 @@ testing_init (void *cls, { d->server = NULL; if (GNUNET_YES == d->dead) - GNUNET_TESTING_daemon_stop (d, GNUNET_TIME_absolute_get_remaining(d->max_timeout), d->dead_cb, d->dead_cb_cls, GNUNET_YES); + GNUNET_TESTING_daemon_stop (d, GNUNET_TIME_absolute_get_remaining(d->max_timeout), d->dead_cb, d->dead_cb_cls, GNUNET_YES, GNUNET_NO); else if (NULL != cb) cb (d->cb_cls, NULL, d->cfg, d, _("Failed to connect to core service\n")); @@ -141,7 +141,7 @@ testing_init (void *cls, d->server = server; d->running = GNUNET_YES; if (GNUNET_YES == d->dead) - GNUNET_TESTING_daemon_stop (d, GNUNET_TIME_absolute_get_remaining(d->max_timeout), d->dead_cb, d->dead_cb_cls, GNUNET_YES); + GNUNET_TESTING_daemon_stop (d, GNUNET_TIME_absolute_get_remaining(d->max_timeout), d->dead_cb, d->dead_cb_cls, GNUNET_YES, GNUNET_NO); else if (NULL != cb) cb (d->cb_cls, my_identity, d->cfg, d, NULL); #if DEBUG_TESTING @@ -155,7 +155,7 @@ testing_init (void *cls, if (d->th == NULL) { if (GNUNET_YES == d->dead) - GNUNET_TESTING_daemon_stop (d, GNUNET_TIME_absolute_get_remaining(d->max_timeout), d->dead_cb, d->dead_cb_cls, GNUNET_YES); + GNUNET_TESTING_daemon_stop (d, GNUNET_TIME_absolute_get_remaining(d->max_timeout), d->dead_cb, d->dead_cb_cls, GNUNET_YES, GNUNET_NO); else if (NULL != d->cb) d->cb (d->cb_cls, &d->id, d->cfg, d, _("Failed to connect to transport service!\n")); @@ -580,14 +580,19 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) d->th = NULL; } /* state clean up and notifications */ - GNUNET_CONFIGURATION_destroy (d->cfg); - GNUNET_free (d->cfgfile); + if (d->churn == GNUNET_NO) + { + GNUNET_CONFIGURATION_destroy (d->cfg); + GNUNET_free (d->cfgfile); + GNUNET_free_non_null (d->hostname); + GNUNET_free_non_null (d->username); + } + GNUNET_free_non_null(d->hello); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); GNUNET_free_non_null (d->shortname); if (NULL != d->dead_cb) d->dead_cb (d->dead_cb_cls, NULL); + GNUNET_free (d); break; case SP_CONFIG_UPDATE: @@ -643,6 +648,39 @@ GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon) daemon->phase = SP_TOPOLOGY_SETUP; } + +/** + * Start a peer that has previously been stopped using the daemon_stop + * call (and files weren't deleted and the allow restart flag) + * + * @param daemon the daemon to start (has been previously stopped) + * @param timeout how long to wait for restart + * @param cb the callback for notification when the peer is running + * @param cb_cls closure for the callback + */ +void +GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyDaemonRunning cb, + void *cb_cls) +{ + if (daemon->running == GNUNET_YES) + { + cb(cb_cls, &daemon->id, daemon->cfg, daemon, "Daemon already running, can't restart!"); + return; + } + + daemon->cb = cb; + daemon->cb_cls = cb_cls; + daemon->phase = SP_TOPOLOGY_SETUP; + daemon->max_timeout = GNUNET_TIME_relative_to_absolute(timeout); + + GNUNET_SCHEDULER_add_continuation (daemon->sched, + &start_fsm, + daemon, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); +} + /** * Starts a GNUnet daemon. GNUnet must be installed on the target * system and available in the PATH. The machine must furthermore be @@ -879,14 +917,15 @@ GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d, * @param cb function called once the daemon was stopped * @param cb_cls closure for cb * @param delete_files GNUNET_YES to remove files, GNUNET_NO - * to leave them (i.e. for restarting at a later time, - * or logfile inspection once finished) + * to leave them + * @param allow_restart GNUNET_YES to restart peer later (using this API) + * GNUNET_NO to kill off and clean up for good */ void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyCompletion cb, void *cb_cls, - int delete_files) + int delete_files, int allow_restart) { char *arg; char *del_arg; @@ -926,6 +965,16 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, #endif d->phase = SP_SHUTDOWN_START; + d->running = GNUNET_NO; + + if (allow_restart == GNUNET_YES) + d->churn = GNUNET_YES; + if (d->th != NULL) + { + GNUNET_TRANSPORT_get_hello_cancel(d->th, &process_hello, d); + GNUNET_TRANSPORT_disconnect(d->th); + d->th = NULL; + } /* Check if this is a local or remote process */ if (NULL != d->hostname) { diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 269df5c21..835b1d979 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c @@ -2606,6 +2606,134 @@ void restart_callback (void *cls, } +void +churn_stop_callback (void *cls, const char *emsg) +{ + +} + +void +churn_start_callback (void *cls, + const struct GNUNET_PeerIdentity *id, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Daemon *d, + const char *emsg) +{ + +} + +/** + * Context for handling churning a peer group + */ +struct ChurnContext +{ + +}; + +/** + * Simulate churn by stopping some peers (and possibly + * re-starting others if churn is called multiple times). This + * function can only be used to create leave-join churn (peers "never" + * leave for good). First "voff" random peers that are currently + * online will be taken offline; then "von" random peers that are then + * offline will be put back online. No notifications will be + * generated for any of these operations except for the callback upon + * completion. Note that the implementation is at liberty to keep + * the ARM service itself (but none of the other services or daemons) + * running even though the "peer" is being varied offline. + * + * @param pg handle for the peer group + * @param voff number of peers that should go offline + * @param von number of peers that should come back online; + * must be zero on first call (since "testbed_start" + * always starts all of the peers) + * @param timeout how long to wait for operations to finish before + * giving up + * @param cb function to call at the end + * @param cb_cls closure for cb + */ +void +GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg, + unsigned int voff, + unsigned int von, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyCompletion cb, + void *cb_cls) +{ + struct ChurnContext *churn_ctx; + unsigned int running; + unsigned int stopped; + unsigned int i; + unsigned int *running_arr; + unsigned int *stopped_arr; + unsigned int *running_permute; + unsigned int *stopped_permute; + + running = 0; + stopped = 0; + + for (i = 0; i < pg->total; i++) + { + if (pg->peers[i].daemon->running == GNUNET_YES) + { + running++; + } + else + { + stopped++; + } + } + + if (voff > running) + { + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Trying to stop more peers than are currently running!\n"); + cb(cb_cls, "Trying to stop more peers than are currently running!"); + return; + } + + if (von > stopped) + { + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Trying to start more peers than are currently stopped!\n"); + cb(cb_cls, "Trying to start more peers than are currently stopped!"); + return; + } + + churn_ctx = GNUNET_malloc(sizeof(struct ChurnContext)); + running_arr = GNUNET_malloc(running * sizeof(unsigned int)); + stopped_arr = GNUNET_malloc(stopped * sizeof(unsigned int)); + running_permute = GNUNET_CRYPTO_random_permute(GNUNET_CRYPTO_QUALITY_WEAK, running); + stopped_permute = GNUNET_CRYPTO_random_permute(GNUNET_CRYPTO_QUALITY_WEAK, stopped); + + running = 0; + stopped = 0; + + for (i = 0; i < pg->total; i++) + { + if (pg->peers[i].daemon->running == GNUNET_YES) + { + running_arr[running] = i; + running++; + } + else + { + stopped_arr[stopped] = i; + stopped++; + } + } + + for (i = 0; i < voff; i++) + { + GNUNET_TESTING_daemon_stop(pg->peers[running_arr[running_permute[i]]].daemon, timeout, &churn_stop_callback, churn_ctx, GNUNET_NO, GNUNET_YES); + } + + for (i = 0; i < von; i++) + { + GNUNET_TESTING_daemon_start_stopped(pg->peers[stopped_arr[stopped_permute[i]]].daemon, timeout, &churn_start_callback, churn_ctx); + } + +} + + /** * Restart all peers in the given group. * @@ -2655,7 +2783,7 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, struct GNUNET_ as well... */ if (NULL != pg->peers[off].daemon) - GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, timeout, NULL, NULL, GNUNET_YES); + GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, timeout, NULL, NULL, GNUNET_YES, GNUNET_NO); if (NULL != pg->peers[off].cfg) GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); -- 2.25.1