aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2012-12-02 12:02:38 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2012-12-02 12:02:38 +0000
commit020a5d9860368e63c997fb5dd82b2498b85f0584 (patch)
treed9e6c4aa7635aba4ac59dcf5f96438ea168cc32f /src/testbed
parent3d6db893ead2345c2d2b6ccce27c25baa4266970 (diff)
downloadgnunet-020a5d9860368e63c997fb5dd82b2498b85f0584.tar.gz
gnunet-020a5d9860368e63c997fb5dd82b2498b85f0584.zip
hosts file support in GNUNET_TESTBED_run() - fixes 2667
Diffstat (limited to 'src/testbed')
-rw-r--r--src/testbed/testbed_api_testbed.c398
1 files changed, 310 insertions, 88 deletions
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c
index f253cf799..61dc5e741 100644
--- a/src/testbed/testbed_api_testbed.c
+++ b/src/testbed/testbed_api_testbed.c
@@ -102,6 +102,11 @@ enum State
102 RC_INIT = 0, 102 RC_INIT = 0,
103 103
104 /** 104 /**
105 * Controllers on given hosts started and linked
106 */
107 RC_LINKED,
108
109 /**
105 * The testbed run is ready and the master callback can be called now. At this 110 * The testbed run is ready and the master callback can be called now. At this
106 * time the peers are all started and if a topology is provided in the 111 * time the peers are all started and if a topology is provided in the
107 * configuration the topology would have been attempted 112 * configuration the topology would have been attempted
@@ -131,6 +136,13 @@ struct RunContext
131 struct GNUNET_TESTBED_Controller *c; 136 struct GNUNET_TESTBED_Controller *c;
132 137
133 /** 138 /**
139 * The configuration of the controller. This is based on the cfg given to the
140 * function GNUNET_TESTBED_run(). We also use this config as a template while
141 * for peers
142 */
143 struct GNUNET_CONFIGURATION_Handle *cfg;
144
145 /**
134 * Handle to the host on which the controller runs 146 * Handle to the host on which the controller runs
135 */ 147 */
136 struct GNUNET_TESTBED_Host *h; 148 struct GNUNET_TESTBED_Host *h;
@@ -171,6 +183,11 @@ struct RunContext
171 struct DLLOperation *dll_op_tail; 183 struct DLLOperation *dll_op_tail;
172 184
173 /** 185 /**
186 * An array of hosts loaded from the hostkeys file
187 */
188 struct GNUNET_TESTBED_Host **hosts;
189
190 /**
174 * Array of peers which we create 191 * Array of peers which we create
175 */ 192 */
176 struct GNUNET_TESTBED_Peer **peers; 193 struct GNUNET_TESTBED_Peer **peers;
@@ -187,6 +204,21 @@ struct RunContext
187 char *topo_file; 204 char *topo_file;
188 205
189 /** 206 /**
207 * Host registration handle
208 */
209 struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
210
211 /**
212 * Host registration task
213 */
214 GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
215
216 /**
217 * Task to be run while shutting down
218 */
219 GNUNET_SCHEDULER_TaskIdentifier shutdown_run_task;
220
221 /**
190 * The event mask for the controller 222 * The event mask for the controller
191 */ 223 */
192 uint64_t event_mask; 224 uint64_t event_mask;
@@ -202,6 +234,16 @@ struct RunContext
202 enum GNUNET_TESTBED_TopologyOption topology; 234 enum GNUNET_TESTBED_TopologyOption topology;
203 235
204 /** 236 /**
237 * Number of hosts in the given host file
238 */
239 unsigned int num_hosts;
240
241 /**
242 * Number of registered hosts
243 */
244 unsigned int reg_hosts;
245
246 /**
205 * Current peer count for an operation; Set this to 0 and increment for each 247 * Current peer count for an operation; Set this to 0 and increment for each
206 * successful operation on a peer 248 * successful operation on a peer
207 */ 249 */
@@ -305,7 +347,10 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
305{ 347{
306 struct RunContext *rc = cls; 348 struct RunContext *rc = cls;
307 struct DLLOperation *dll_op; 349 struct DLLOperation *dll_op;
350 unsigned int hid;
308 351
352 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rc->register_hosts_task);
353 GNUNET_assert (NULL == rc->reg_handle);
309 GNUNET_assert (NULL == rc->peers); 354 GNUNET_assert (NULL == rc->peers);
310 GNUNET_assert (RC_PEERS_DESTROYED == rc->state); 355 GNUNET_assert (RC_PEERS_DESTROYED == rc->state);
311 if (NULL != rc->c) 356 if (NULL != rc->c)
@@ -314,6 +359,9 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
314 GNUNET_TESTBED_controller_stop (rc->cproc); 359 GNUNET_TESTBED_controller_stop (rc->cproc);
315 if (NULL != rc->h) 360 if (NULL != rc->h)
316 GNUNET_TESTBED_host_destroy (rc->h); 361 GNUNET_TESTBED_host_destroy (rc->h);
362 for (hid = 0; hid < rc->num_hosts; hid++)
363 GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
364 GNUNET_free_non_null (rc->hosts);
317 if (NULL != rc->dll_op_head) 365 if (NULL != rc->dll_op_head)
318 { 366 {
319 LOG (GNUNET_ERROR_TYPE_WARNING, 367 LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -325,12 +373,95 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
325 GNUNET_free (dll_op); 373 GNUNET_free (dll_op);
326 } 374 }
327 } 375 }
376 if (NULL != rc->cfg)
377 GNUNET_CONFIGURATION_destroy (rc->cfg);
328 GNUNET_free_non_null (rc->topo_file); 378 GNUNET_free_non_null (rc->topo_file);
329 GNUNET_free (rc); 379 GNUNET_free (rc);
330} 380}
331 381
332 382
333/** 383/**
384 * Stops the testbed run and releases any used resources
385 *
386 * @param cls the tesbed run handle
387 * @param tc the task context from scheduler
388 */
389static void
390shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
391{
392 struct RunContext *rc = cls;
393 struct DLLOperation *dll_op;
394 unsigned int peer;
395
396 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task);
397 rc->shutdown_run_task = GNUNET_SCHEDULER_NO_TASK;
398 /* Stop register hosts task if it is running */
399 if (GNUNET_SCHEDULER_NO_TASK != rc->register_hosts_task)
400 {
401 GNUNET_SCHEDULER_cancel (rc->register_hosts_task);
402 rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
403 }
404 if (NULL != rc->reg_handle)
405 {
406 GNUNET_TESTBED_cancel_registration (rc->reg_handle);
407 rc->reg_handle = NULL;
408 }
409 if (NULL != rc->c)
410 {
411 if (NULL != rc->peers)
412 {
413 if (NULL != rc->topology_operation)
414 {
415 GNUNET_TESTBED_operation_done (rc->topology_operation);
416 rc->topology_operation = NULL;
417 }
418 if (RC_INIT == rc->state)
419 rc->state = RC_READY; /* Even though we haven't called the master callback */
420 rc->peer_count = 0;
421 /* Check if some peers are stopped */
422 for (peer = 0; peer < rc->num_peers; peer++)
423 {
424 if (PS_STOPPED != rc->peers[peer]->state)
425 break;
426 }
427 if (peer == rc->num_peers)
428 {
429 /* All peers are stopped */
430 rc->state = RC_PEERS_STOPPED;
431 for (peer = 0; peer < rc->num_peers; peer++)
432 {
433 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
434 dll_op->op = GNUNET_TESTBED_peer_destroy (rc->peers[peer]);
435 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
436 dll_op);
437 }
438 return;
439 }
440 /* Some peers are stopped */
441 for (peer = 0; peer < rc->num_peers; peer++)
442 {
443 if (PS_STARTED != rc->peers[peer]->state)
444 {
445 rc->peer_count++;
446 continue;
447 }
448 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
449 dll_op->op = GNUNET_TESTBED_peer_stop (rc->peers[peer], NULL, NULL);
450 dll_op->cls = rc->peers[peer];
451 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
452 dll_op);
453 }
454 if (rc->peer_count != rc->num_peers)
455 return;
456 }
457 }
458 rc->state = RC_PEERS_DESTROYED; /* No peers are present so we consider the
459 * state where all peers are destroyed */
460 GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
461}
462
463
464/**
334 * Task to call master task 465 * Task to call master task
335 * 466 *
336 * @param cls the run context 467 * @param cls the run context
@@ -353,6 +484,36 @@ call_master (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
353 484
354 485
355/** 486/**
487 * Function to create peers
488 *
489 * @param rc the RunContext
490 */
491static void
492create_peers (struct RunContext *rc)
493{
494 struct DLLOperation *dll_op;
495 unsigned int peer;
496
497 rc->peers =
498 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers);
499 GNUNET_assert (NULL != rc->c);
500 rc->peer_count = 0;
501 for (peer = 0; peer < rc->num_peers; peer++)
502 {
503 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
504 dll_op->rc = rc;
505 dll_op->op =
506 GNUNET_TESTBED_peer_create (rc->c,
507 (0 == rc->num_hosts)
508 ? rc->h : rc->hosts[peer % rc->num_hosts],
509 rc->cfg,
510 peer_create_cb, dll_op);
511 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);
512 }
513}
514
515
516/**
356 * Signature of the event handler function called by the 517 * Signature of the event handler function called by the
357 * respective event controller. 518 * respective event controller.
358 * 519 *
@@ -366,6 +527,38 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
366 struct DLLOperation *dll_op; 527 struct DLLOperation *dll_op;
367 unsigned int peer_id; 528 unsigned int peer_id;
368 529
530 if (RC_INIT == rc->state)
531 {
532 switch (event->type)
533 {
534 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
535 dll_op = event->details.operation_finished.op_cls;
536 if (NULL != event->details.operation_finished.emsg)
537 {
538 LOG (GNUNET_ERROR_TYPE_ERROR,
539 _("Linking controllers failed. Exiting"));
540 GNUNET_SCHEDULER_cancel (rc->shutdown_run_task);
541 rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc);
542 }
543 else
544 rc->reg_hosts++;
545 GNUNET_assert (event->details.operation_finished.operation == dll_op->op);
546 GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
547 GNUNET_TESTBED_operation_done (dll_op->op);
548 GNUNET_free (dll_op);
549 if (rc->reg_hosts == rc->num_hosts)
550 {
551 rc->state = RC_LINKED;
552 create_peers (rc);
553 }
554 return;
555 default:
556 GNUNET_assert (0);
557 GNUNET_SCHEDULER_cancel (rc->shutdown_run_task);
558 rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc);
559 return;
560 }
561 }
369 if (NULL != rc->topology_operation) 562 if (NULL != rc->topology_operation)
370 { 563 {
371 switch (event->type) 564 switch (event->type)
@@ -376,6 +569,9 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
376 break; 569 break;
377 default: 570 default:
378 GNUNET_assert (0); 571 GNUNET_assert (0);
572 GNUNET_SCHEDULER_cancel (rc->shutdown_run_task);
573 rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc);
574 return;
379 } 575 }
380 if (rc->oc_count == rc->num_oc) 576 if (rc->oc_count == rc->num_oc)
381 { 577 {
@@ -385,7 +581,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
385 } 581 }
386 return; 582 return;
387 } 583 }
388 if ((RC_INIT != rc->state) && 584 if ((RC_LINKED < rc->state) &&
389 ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) || 585 ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) ||
390 (GNUNET_TESTBED_ET_PEER_STOP == event->type))) 586 (GNUNET_TESTBED_ET_PEER_STOP == event->type)))
391 { 587 {
@@ -496,6 +692,80 @@ call_cc:
496} 692}
497 693
498 694
695/**
696 * Task to register all hosts available in the global host list
697 *
698 * @param cls the RunContext
699 * @param tc the scheduler task context
700 */
701static void
702register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
703
704
705/**
706 * Callback which will be called to after a host registration succeeded or failed
707 *
708 * @param cls the closure
709 * @param emsg the error message; NULL if host registration is successful
710 */
711static void
712host_registration_completion (void *cls, const char *emsg)
713{
714 struct RunContext *rc = cls;
715
716 rc->reg_handle = NULL;
717 if (NULL != emsg)
718 {
719 LOG (GNUNET_ERROR_TYPE_WARNING,
720 _("Host registration failed for a host. Error: %s\n"), emsg);
721 GNUNET_SCHEDULER_cancel (rc->shutdown_run_task);
722 rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc);
723 return;
724 }
725 rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
726}
727
728
729/**
730 * Task to register all hosts available in the global host list
731 *
732 * @param cls RunContext
733 * @param tc the scheduler task context
734 */
735static void
736register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
737{
738 struct RunContext *rc = cls;
739 struct DLLOperation *dll_op;
740 unsigned int slave;
741
742 rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
743 if (rc->reg_hosts == rc->num_hosts)
744 {
745 LOG (GNUNET_ERROR_TYPE_DEBUG,
746 "All hosts successfully registered\n");
747 /* Start slaves */
748 for (slave = 0; slave < rc->num_hosts; slave++)
749 {
750 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
751 dll_op->rc = rc;
752 dll_op->op = GNUNET_TESTBED_controller_link (dll_op,
753 rc->c,
754 rc->hosts[slave],
755 rc->h,
756 rc->cfg,
757 GNUNET_YES);
758 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);
759 }
760 rc->reg_hosts = 0;
761 return;
762 }
763 rc->reg_handle = GNUNET_TESTBED_register_host (rc->c,
764 rc->hosts[rc->reg_hosts++],
765 host_registration_completion,
766 rc);
767}
768
499 769
500/** 770/**
501 * Callback to signal successfull startup of the controller process 771 * Callback to signal successfull startup of the controller process
@@ -511,102 +781,28 @@ controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
511 int status) 781 int status)
512{ 782{
513 struct RunContext *rc = cls; 783 struct RunContext *rc = cls;
514 struct DLLOperation *dll_op;
515 uint64_t event_mask; 784 uint64_t event_mask;
516 unsigned int peer;
517 785
518 if (status != GNUNET_OK) 786 if (status != GNUNET_OK)
519 { 787 {
520 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed startup failed\n"); 788 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed startup failed\n");
521 return; 789 return;
522 } 790 }
791 rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
523 event_mask = rc->event_mask; 792 event_mask = rc->event_mask;
524 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); 793 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
525 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); 794 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
526 if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE) 795 if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE)
527 event_mask |= GNUNET_TESTBED_ET_CONNECT; 796 event_mask |= GNUNET_TESTBED_ET_CONNECT;
528 rc->c = 797 rc->c =
529 GNUNET_TESTBED_controller_connect (cfg, rc->h, event_mask, &event_cb, rc); 798 GNUNET_TESTBED_controller_connect (rc->cfg, rc->h, event_mask, &event_cb, rc);
530 rc->peers = 799 if (0 < rc->num_hosts)
531 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers);
532 GNUNET_assert (NULL != rc->c);
533 rc->peer_count = 0;
534 for (peer = 0; peer < rc->num_peers; peer++)
535 { 800 {
536 dll_op = GNUNET_malloc (sizeof (struct DLLOperation)); 801 rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
537 dll_op->rc = rc; 802 return;
538 dll_op->op =
539 GNUNET_TESTBED_peer_create (rc->c, rc->h, cfg, peer_create_cb, dll_op);
540 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);
541 }
542}
543
544
545/**
546 * Stops the testbed run and releases any used resources
547 *
548 * @param cls the tesbed run handle
549 * @param tc the task context from scheduler
550 */
551static void
552shutdown_run_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
553{
554 struct RunContext *rc = cls;
555 struct DLLOperation *dll_op;
556 unsigned int peer;
557
558 if (NULL != rc->c)
559 {
560 if (NULL != rc->peers)
561 {
562 if (NULL != rc->topology_operation)
563 {
564 GNUNET_TESTBED_operation_done (rc->topology_operation);
565 rc->topology_operation = NULL;
566 }
567 if (RC_INIT == rc->state)
568 rc->state = RC_READY; /* Even though we haven't called the master callback */
569 rc->peer_count = 0;
570 /* Check if some peers are stopped */
571 for (peer = 0; peer < rc->num_peers; peer++)
572 {
573 if (PS_STOPPED != rc->peers[peer]->state)
574 break;
575 }
576 if (peer == rc->num_peers)
577 {
578 /* All peers are stopped */
579 rc->state = RC_PEERS_STOPPED;
580 for (peer = 0; peer < rc->num_peers; peer++)
581 {
582 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
583 dll_op->op = GNUNET_TESTBED_peer_destroy (rc->peers[peer]);
584 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
585 dll_op);
586 }
587 return;
588 }
589 /* Some peers are stopped */
590 for (peer = 0; peer < rc->num_peers; peer++)
591 {
592 if (PS_STARTED != rc->peers[peer]->state)
593 {
594 rc->peer_count++;
595 continue;
596 }
597 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
598 dll_op->op = GNUNET_TESTBED_peer_stop (rc->peers[peer], NULL, NULL);
599 dll_op->cls = rc->peers[peer];
600 GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
601 dll_op);
602 }
603 if (rc->peer_count != rc->num_peers)
604 return;
605 }
606 } 803 }
607 rc->state = RC_PEERS_DESTROYED; /* No peers are present so we consider the 804 rc->state = RC_LINKED;
608 * state where all peers are destroyed */ 805 create_peers (rc);
609 GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
610} 806}
611 807
612 808
@@ -647,15 +843,32 @@ GNUNET_TESTBED_run (const char *host_filename,
647 struct RunContext *rc; 843 struct RunContext *rc;
648 char *topology; 844 char *topology;
649 unsigned long long random_links; 845 unsigned long long random_links;
650 846 unsigned int hid;
651 GNUNET_break (NULL == host_filename); /* Currently we do not support host 847
652 * files */
653 GNUNET_assert (NULL != cc); 848 GNUNET_assert (NULL != cc);
654 GNUNET_assert (num_peers > 0); 849 GNUNET_assert (num_peers > 0);
655 host_filename = NULL; 850 host_filename = NULL;
656 rc = GNUNET_malloc (sizeof (struct RunContext)); 851 rc = GNUNET_malloc (sizeof (struct RunContext));
657 rc->h = GNUNET_TESTBED_host_create (NULL, NULL, 0); 852 if (NULL != host_filename)
853 {
854 rc->num_hosts =
855 GNUNET_TESTBED_hosts_load_from_file (host_filename, &rc->hosts);
856 if (0 == rc->num_hosts)
857 {
858 LOG (GNUNET_ERROR_TYPE_WARNING,
859 _("No hosts loaded. Need at least one host\n"));
860 return;
861 }
862 rc->h = rc->hosts[0];
863 rc->num_hosts--;
864 if (0 < rc->num_hosts)
865 rc->hosts = &rc->hosts[1];
866 }
867 else
868 rc->h = GNUNET_TESTBED_host_create (NULL, NULL, 0);
658 GNUNET_assert (NULL != rc->h); 869 GNUNET_assert (NULL != rc->h);
870 /* FIXME: If we are starting controller on different host 127.0.0.1 may not ab
871 correct */
659 rc->cproc = 872 rc->cproc =
660 GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, cfg, 873 GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, cfg,
661 &controller_status_cb, rc); 874 &controller_status_cb, rc);
@@ -698,6 +911,10 @@ GNUNET_TESTBED_run (const char *host_filename,
698 if (random_links > UINT32_MAX) 911 if (random_links > UINT32_MAX)
699 { 912 {
700 GNUNET_break (0); /* Too big number */ 913 GNUNET_break (0); /* Too big number */
914 GNUNET_TESTBED_host_destroy (rc->h);
915 for (hid = 0; hid < rc->num_hosts; hid++)
916 GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
917 GNUNET_free_non_null (rc->hosts);
701 GNUNET_free (rc); 918 GNUNET_free (rc);
702 return; 919 return;
703 } 920 }
@@ -711,12 +928,17 @@ GNUNET_TESTBED_run (const char *host_filename,
711 { 928 {
712 /* You need to set TOPOLOGY_FILE option to a topolog file */ 929 /* You need to set TOPOLOGY_FILE option to a topolog file */
713 GNUNET_break (0); 930 GNUNET_break (0);
931 GNUNET_TESTBED_host_destroy (rc->h);
932 for (hid = 0; hid < rc->num_hosts; hid++)
933 GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
934 GNUNET_free_non_null (rc->hosts);
714 GNUNET_free (rc); 935 GNUNET_free (rc);
715 return; 936 return;
716 } 937 }
717 } 938 }
718 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 939 rc->shutdown_run_task =
719 &shutdown_run_task, rc); 940 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
941 &shutdown_run, rc);
720} 942}
721 943
722 944