diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-09-16 14:16:15 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-09-16 14:16:15 +0000 |
commit | a2b46552b7f2cf112bc0f65f0c2e2f1936df98be (patch) | |
tree | 1bda0273491ca71b957a691c9e6f7b5dc75c071d /src | |
parent | 6d15bc3f382bddb55c6678e839d25728e1512af4 (diff) | |
download | gnunet-a2b46552b7f2cf112bc0f65f0c2e2f1936df98be.tar.gz gnunet-a2b46552b7f2cf112bc0f65f0c2e2f1936df98be.zip |
mostly untested testing code, throttling churning of peers in the same manner as normal peer startup and shutdown is
Diffstat (limited to 'src')
-rw-r--r-- | src/testing/testing_group.c | 269 |
1 files changed, 195 insertions, 74 deletions
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 1c9f1c4bb..6f100cbdd 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c | |||
@@ -176,6 +176,39 @@ struct ShutdownContext | |||
176 | void *cb_cls; | 176 | void *cb_cls; |
177 | }; | 177 | }; |
178 | 178 | ||
179 | /** | ||
180 | * Individual shutdown context for a particular peer. | ||
181 | */ | ||
182 | struct PeerShutdownContext | ||
183 | { | ||
184 | /** | ||
185 | * Pointer to the high level shutdown context. | ||
186 | */ | ||
187 | struct ShutdownContext *shutdown_ctx; | ||
188 | |||
189 | /** | ||
190 | * The daemon handle for the peer to shut down. | ||
191 | */ | ||
192 | struct GNUNET_TESTING_Daemon *daemon; | ||
193 | }; | ||
194 | |||
195 | /** | ||
196 | * Individual shutdown context for a particular peer. | ||
197 | */ | ||
198 | struct PeerRestartContext | ||
199 | { | ||
200 | /** | ||
201 | * Pointer to the high level restart context. | ||
202 | */ | ||
203 | struct ChurnRestartContext *churn_restart_ctx; | ||
204 | |||
205 | /** | ||
206 | * The daemon handle for the peer to shut down. | ||
207 | */ | ||
208 | struct GNUNET_TESTING_Daemon *daemon; | ||
209 | }; | ||
210 | |||
211 | |||
179 | struct CreateTopologyContext | 212 | struct CreateTopologyContext |
180 | { | 213 | { |
181 | 214 | ||
@@ -256,6 +289,24 @@ struct InternalStartContext | |||
256 | 289 | ||
257 | }; | 290 | }; |
258 | 291 | ||
292 | struct ChurnRestartContext | ||
293 | { | ||
294 | /** | ||
295 | * Number of restarts currently in flight. | ||
296 | */ | ||
297 | unsigned int outstanding; | ||
298 | |||
299 | /** | ||
300 | * Handle to the underlying churn context. | ||
301 | */ | ||
302 | struct ChurnContext *churn_ctx; | ||
303 | |||
304 | /** | ||
305 | * How long to allow the operation to take. | ||
306 | */ | ||
307 | struct GNUNET_TIME_Relative timeout; | ||
308 | }; | ||
309 | |||
259 | /** | 310 | /** |
260 | * Data we keep per peer. | 311 | * Data we keep per peer. |
261 | */ | 312 | */ |
@@ -3319,6 +3370,84 @@ internal_continue_startup (void *cls, const struct GNUNET_SCHEDULER_TaskContext | |||
3319 | } | 3370 | } |
3320 | } | 3371 | } |
3321 | 3372 | ||
3373 | |||
3374 | /** | ||
3375 | * Callback for informing us about a successful | ||
3376 | * or unsuccessful churn start call. | ||
3377 | * | ||
3378 | * @param cls a ChurnContext | ||
3379 | * @param id the peer identity of the started peer | ||
3380 | * @param cfg the handle to the configuration of the peer | ||
3381 | * @param d handle to the daemon for the peer | ||
3382 | * @param emsg NULL on success, non-NULL on failure | ||
3383 | * | ||
3384 | */ | ||
3385 | void | ||
3386 | churn_start_callback (void *cls, | ||
3387 | const struct GNUNET_PeerIdentity *id, | ||
3388 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
3389 | struct GNUNET_TESTING_Daemon *d, | ||
3390 | const char *emsg) | ||
3391 | { | ||
3392 | struct ChurnRestartContext *startup_ctx = cls; | ||
3393 | struct ChurnContext *churn_ctx = startup_ctx->churn_ctx; | ||
3394 | |||
3395 | unsigned int total_left; | ||
3396 | char *error_message; | ||
3397 | |||
3398 | error_message = NULL; | ||
3399 | if (emsg != NULL) | ||
3400 | { | ||
3401 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
3402 | "Churn stop callback failed with error `%s'\n", | ||
3403 | emsg); | ||
3404 | churn_ctx->num_failed_start++; | ||
3405 | } | ||
3406 | else | ||
3407 | { | ||
3408 | churn_ctx->num_to_start--; | ||
3409 | } | ||
3410 | |||
3411 | #if DEBUG_CHURN | ||
3412 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | ||
3413 | "Started peer, %d left.\n", | ||
3414 | churn_ctx->num_to_start); | ||
3415 | #endif | ||
3416 | |||
3417 | total_left = (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + (churn_ctx->num_to_start - churn_ctx->num_failed_start); | ||
3418 | |||
3419 | if (total_left == 0) | ||
3420 | { | ||
3421 | if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0)) | ||
3422 | GNUNET_asprintf(&error_message, | ||
3423 | "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", | ||
3424 | churn_ctx->num_failed_start, | ||
3425 | churn_ctx->num_failed_stop); | ||
3426 | churn_ctx->cb(churn_ctx->cb_cls, error_message); | ||
3427 | GNUNET_free_non_null(error_message); | ||
3428 | GNUNET_free(churn_ctx); | ||
3429 | GNUNET_free(startup_ctx); | ||
3430 | } | ||
3431 | } | ||
3432 | |||
3433 | |||
3434 | static void schedule_churn_restart(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
3435 | { | ||
3436 | struct PeerRestartContext *peer_restart_ctx = cls; | ||
3437 | struct ChurnRestartContext *startup_ctx = peer_restart_ctx->churn_restart_ctx; | ||
3438 | |||
3439 | if (startup_ctx->outstanding > MAX_CONCURRENT_STARTING) | ||
3440 | GNUNET_SCHEDULER_add_delayed(peer_restart_ctx->daemon->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100), &schedule_churn_restart, peer_restart_ctx); | ||
3441 | else | ||
3442 | { | ||
3443 | GNUNET_TESTING_daemon_start_stopped(peer_restart_ctx->daemon, | ||
3444 | startup_ctx->timeout, | ||
3445 | &churn_start_callback, | ||
3446 | startup_ctx); | ||
3447 | GNUNET_free(peer_restart_ctx); | ||
3448 | } | ||
3449 | } | ||
3450 | |||
3322 | static void | 3451 | static void |
3323 | internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | 3452 | internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) |
3324 | { | 3453 | { |
@@ -3684,11 +3813,14 @@ void restart_callback (void *cls, | |||
3684 | void | 3813 | void |
3685 | churn_stop_callback (void *cls, const char *emsg) | 3814 | churn_stop_callback (void *cls, const char *emsg) |
3686 | { | 3815 | { |
3687 | struct ChurnContext *churn_ctx = cls; | 3816 | struct ShutdownContext *shutdown_ctx = cls; |
3817 | struct ChurnContext *churn_ctx = shutdown_ctx->cb_cls; | ||
3688 | unsigned int total_left; | 3818 | unsigned int total_left; |
3689 | char *error_message; | 3819 | char *error_message; |
3690 | 3820 | ||
3691 | error_message = NULL; | 3821 | error_message = NULL; |
3822 | shutdown_ctx->outstanding--; | ||
3823 | |||
3692 | if (emsg != NULL) | 3824 | if (emsg != NULL) |
3693 | { | 3825 | { |
3694 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | 3826 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, |
@@ -3719,62 +3851,7 @@ churn_stop_callback (void *cls, const char *emsg) | |||
3719 | churn_ctx->cb(churn_ctx->cb_cls, error_message); | 3851 | churn_ctx->cb(churn_ctx->cb_cls, error_message); |
3720 | GNUNET_free_non_null(error_message); | 3852 | GNUNET_free_non_null(error_message); |
3721 | GNUNET_free(churn_ctx); | 3853 | GNUNET_free(churn_ctx); |
3722 | } | 3854 | GNUNET_free(shutdown_ctx); |
3723 | } | ||
3724 | |||
3725 | /** | ||
3726 | * Callback for informing us about a successful | ||
3727 | * or unsuccessful churn start call. | ||
3728 | * | ||
3729 | * @param cls a ChurnContext | ||
3730 | * @param id the peer identity of the started peer | ||
3731 | * @param cfg the handle to the configuration of the peer | ||
3732 | * @param d handle to the daemon for the peer | ||
3733 | * @param emsg NULL on success, non-NULL on failure | ||
3734 | * | ||
3735 | */ | ||
3736 | void | ||
3737 | churn_start_callback (void *cls, | ||
3738 | const struct GNUNET_PeerIdentity *id, | ||
3739 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
3740 | struct GNUNET_TESTING_Daemon *d, | ||
3741 | const char *emsg) | ||
3742 | { | ||
3743 | struct ChurnContext *churn_ctx = cls; | ||
3744 | unsigned int total_left; | ||
3745 | char *error_message; | ||
3746 | |||
3747 | error_message = NULL; | ||
3748 | if (emsg != NULL) | ||
3749 | { | ||
3750 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
3751 | "Churn stop callback failed with error `%s'\n", | ||
3752 | emsg); | ||
3753 | churn_ctx->num_failed_start++; | ||
3754 | } | ||
3755 | else | ||
3756 | { | ||
3757 | churn_ctx->num_to_start--; | ||
3758 | } | ||
3759 | |||
3760 | #if DEBUG_CHURN | ||
3761 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | ||
3762 | "Started peer, %d left.\n", | ||
3763 | churn_ctx->num_to_start); | ||
3764 | #endif | ||
3765 | |||
3766 | total_left = (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + (churn_ctx->num_to_start - churn_ctx->num_failed_start); | ||
3767 | |||
3768 | if (total_left == 0) | ||
3769 | { | ||
3770 | if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0)) | ||
3771 | GNUNET_asprintf(&error_message, | ||
3772 | "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", | ||
3773 | churn_ctx->num_failed_start, | ||
3774 | churn_ctx->num_failed_stop); | ||
3775 | churn_ctx->cb(churn_ctx->cb_cls, error_message); | ||
3776 | GNUNET_free_non_null(error_message); | ||
3777 | GNUNET_free(churn_ctx); | ||
3778 | } | 3855 | } |
3779 | } | 3856 | } |
3780 | 3857 | ||
@@ -3802,6 +3879,33 @@ GNUNET_TESTING_daemons_running (struct GNUNET_TESTING_PeerGroup *pg) | |||
3802 | } | 3879 | } |
3803 | 3880 | ||
3804 | /** | 3881 | /** |
3882 | * Task to rate limit the number of outstanding peer shutdown | ||
3883 | * requests. This is necessary for making sure we don't do | ||
3884 | * too many ssh connections at once, but is generally nicer | ||
3885 | * to any system as well (graduated task starts, as opposed | ||
3886 | * to calling gnunet-arm N times all at once). | ||
3887 | */ | ||
3888 | static void | ||
3889 | schedule_churn_shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
3890 | { | ||
3891 | struct PeerShutdownContext *peer_shutdown_ctx = cls; | ||
3892 | struct ShutdownContext *shutdown_ctx; | ||
3893 | |||
3894 | GNUNET_assert(peer_shutdown_ctx != NULL); | ||
3895 | shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; | ||
3896 | GNUNET_assert(shutdown_ctx != NULL); | ||
3897 | |||
3898 | if (shutdown_ctx->outstanding > MAX_CONCURRENT_SHUTDOWN) | ||
3899 | GNUNET_SCHEDULER_add_delayed(peer_shutdown_ctx->daemon->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100), &schedule_churn_shutdown_task, peer_shutdown_ctx); | ||
3900 | else | ||
3901 | { | ||
3902 | shutdown_ctx->outstanding++; | ||
3903 | GNUNET_TESTING_daemon_stop (peer_shutdown_ctx->daemon, shutdown_ctx->timeout, shutdown_ctx->cb, shutdown_ctx, GNUNET_NO, GNUNET_YES); | ||
3904 | GNUNET_free(peer_shutdown_ctx); | ||
3905 | } | ||
3906 | } | ||
3907 | |||
3908 | /** | ||
3805 | * Simulate churn by stopping some peers (and possibly | 3909 | * Simulate churn by stopping some peers (and possibly |
3806 | * re-starting others if churn is called multiple times). This | 3910 | * re-starting others if churn is called multiple times). This |
3807 | * function can only be used to create leave-join churn (peers "never" | 3911 | * function can only be used to create leave-join churn (peers "never" |
@@ -3830,6 +3934,11 @@ GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg, | |||
3830 | void *cb_cls) | 3934 | void *cb_cls) |
3831 | { | 3935 | { |
3832 | struct ChurnContext *churn_ctx; | 3936 | struct ChurnContext *churn_ctx; |
3937 | struct ShutdownContext *shutdown_ctx; | ||
3938 | struct PeerShutdownContext *peer_shutdown_ctx; | ||
3939 | struct PeerRestartContext *peer_restart_ctx; | ||
3940 | struct ChurnRestartContext *churn_startup_ctx; | ||
3941 | |||
3833 | unsigned int running; | 3942 | unsigned int running; |
3834 | unsigned int stopped; | 3943 | unsigned int stopped; |
3835 | unsigned int total_running; | 3944 | unsigned int total_running; |
@@ -3922,27 +4031,53 @@ GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg, | |||
3922 | } | 4031 | } |
3923 | 4032 | ||
3924 | GNUNET_assert(running >= voff); | 4033 | GNUNET_assert(running >= voff); |
4034 | if (voff > 0) | ||
4035 | { | ||
4036 | shutdown_ctx = GNUNET_malloc(sizeof(struct ShutdownContext)); | ||
4037 | shutdown_ctx->cb = &churn_stop_callback; | ||
4038 | shutdown_ctx->cb_cls = churn_ctx; | ||
4039 | shutdown_ctx->total_peers = voff; | ||
4040 | shutdown_ctx->timeout = timeout; | ||
4041 | } | ||
4042 | |||
3925 | for (i = 0; i < voff; i++) | 4043 | for (i = 0; i < voff; i++) |
3926 | { | 4044 | { |
3927 | #if DEBUG_CHURN | 4045 | #if DEBUG_CHURN |
3928 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Stopping peer %d!\n", running_permute[i]); | 4046 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Stopping peer %d!\n", running_permute[i]); |
3929 | #endif | 4047 | #endif |
3930 | GNUNET_assert(running_arr != NULL); | 4048 | GNUNET_assert(running_arr != NULL); |
4049 | peer_shutdown_ctx = GNUNET_malloc(sizeof(struct PeerShutdownContext)); | ||
4050 | peer_shutdown_ctx->daemon = pg->peers[running_arr[running_permute[i]]].daemon; | ||
4051 | peer_shutdown_ctx->shutdown_ctx = shutdown_ctx; | ||
4052 | GNUNET_SCHEDULER_add_now(peer_shutdown_ctx->daemon->sched, &schedule_churn_shutdown_task, peer_shutdown_ctx); | ||
4053 | |||
4054 | /* | ||
3931 | GNUNET_TESTING_daemon_stop (pg->peers[running_arr[running_permute[i]]].daemon, | 4055 | GNUNET_TESTING_daemon_stop (pg->peers[running_arr[running_permute[i]]].daemon, |
3932 | timeout, | 4056 | timeout, |
3933 | &churn_stop_callback, churn_ctx, | 4057 | &churn_stop_callback, churn_ctx, |
3934 | GNUNET_NO, GNUNET_YES); | 4058 | GNUNET_NO, GNUNET_YES); */ |
3935 | } | 4059 | } |
3936 | 4060 | ||
3937 | GNUNET_assert(stopped >= von); | 4061 | GNUNET_assert(stopped >= von); |
4062 | if (von > 0) | ||
4063 | { | ||
4064 | churn_startup_ctx = GNUNET_malloc(sizeof(struct ChurnRestartContext)); | ||
4065 | churn_startup_ctx->churn_ctx = churn_ctx; | ||
4066 | churn_startup_ctx->timeout = timeout; | ||
4067 | } | ||
3938 | for (i = 0; i < von; i++) | 4068 | for (i = 0; i < von; i++) |
3939 | { | 4069 | { |
3940 | #if DEBUG_CHURN | 4070 | #if DEBUG_CHURN |
3941 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Starting up peer %d!\n", stopped_permute[i]); | 4071 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Starting up peer %d!\n", stopped_permute[i]); |
3942 | #endif | 4072 | #endif |
3943 | GNUNET_assert(stopped_arr != NULL); | 4073 | GNUNET_assert(stopped_arr != NULL); |
4074 | peer_restart_ctx = GNUNET_malloc(sizeof(struct PeerRestartContext)); | ||
4075 | peer_restart_ctx->churn_restart_ctx = churn_startup_ctx; | ||
4076 | peer_restart_ctx->daemon = pg->peers[stopped_arr[stopped_permute[i]]].daemon; | ||
4077 | GNUNET_SCHEDULER_add_now(peer_restart_ctx->daemon->sched, &schedule_churn_restart, peer_restart_ctx); | ||
4078 | /* | ||
3944 | GNUNET_TESTING_daemon_start_stopped(pg->peers[stopped_arr[stopped_permute[i]]].daemon, | 4079 | GNUNET_TESTING_daemon_start_stopped(pg->peers[stopped_arr[stopped_permute[i]]].daemon, |
3945 | timeout, &churn_start_callback, churn_ctx); | 4080 | timeout, &churn_start_callback, churn_ctx);*/ |
3946 | } | 4081 | } |
3947 | 4082 | ||
3948 | GNUNET_free_non_null(running_arr); | 4083 | GNUNET_free_non_null(running_arr); |
@@ -4065,21 +4200,6 @@ void internal_shutdown_callback (void *cls, | |||
4065 | } | 4200 | } |
4066 | } | 4201 | } |
4067 | 4202 | ||
4068 | /** | ||
4069 | * Individual shutdown context for a particular peer. | ||
4070 | */ | ||
4071 | struct PeerShutdownContext | ||
4072 | { | ||
4073 | /** | ||
4074 | * Pointer to the high level shutdown context. | ||
4075 | */ | ||
4076 | struct ShutdownContext *shutdown_ctx; | ||
4077 | |||
4078 | /** | ||
4079 | * The daemon handle for the peer to shut down. | ||
4080 | */ | ||
4081 | struct GNUNET_TESTING_Daemon *daemon; | ||
4082 | }; | ||
4083 | 4203 | ||
4084 | /** | 4204 | /** |
4085 | * Task to rate limit the number of outstanding peer shutdown | 4205 | * Task to rate limit the number of outstanding peer shutdown |
@@ -4107,6 +4227,7 @@ schedule_shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext * t | |||
4107 | GNUNET_free(peer_shutdown_ctx); | 4227 | GNUNET_free(peer_shutdown_ctx); |
4108 | } | 4228 | } |
4109 | } | 4229 | } |
4230 | |||
4110 | /** | 4231 | /** |
4111 | * Shutdown all peers started in the given group. | 4232 | * Shutdown all peers started in the given group. |
4112 | * | 4233 | * |