aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-09-16 14:16:15 +0000
committerNathan S. Evans <evans@in.tum.de>2010-09-16 14:16:15 +0000
commita2b46552b7f2cf112bc0f65f0c2e2f1936df98be (patch)
tree1bda0273491ca71b957a691c9e6f7b5dc75c071d /src
parent6d15bc3f382bddb55c6678e839d25728e1512af4 (diff)
downloadgnunet-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.c269
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 */
182struct 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 */
198struct 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
179struct CreateTopologyContext 212struct CreateTopologyContext
180{ 213{
181 214
@@ -256,6 +289,24 @@ struct InternalStartContext
256 289
257}; 290};
258 291
292struct 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 */
3385void
3386churn_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
3434static 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
3322static void 3451static void
3323internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) 3452internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
3324{ 3453{
@@ -3684,11 +3813,14 @@ void restart_callback (void *cls,
3684void 3813void
3685churn_stop_callback (void *cls, const char *emsg) 3814churn_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 */
3736void
3737churn_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 */
3888static void
3889schedule_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 */
4071struct 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 *