aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api_testbed.c
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-09-05 09:49:58 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-09-05 09:49:58 +0000
commit96884ee94297035e20e29eed83d15e38e9e7797b (patch)
tree4ca00d5688e998cce07f7149473bc767869f5a53 /src/testbed/testbed_api_testbed.c
parent49f7d44deb51f4cd7f8027d5a1fac9d7ddef1f27 (diff)
downloadgnunet-96884ee94297035e20e29eed83d15e38e9e7797b.tar.gz
gnunet-96884ee94297035e20e29eed83d15e38e9e7797b.zip
- 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.c182
1 files changed, 73 insertions, 109 deletions
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c
index 064e43b9f..dae364699 100644
--- a/src/testbed/testbed_api_testbed.c
+++ b/src/testbed/testbed_api_testbed.c
@@ -28,6 +28,7 @@
28#include "platform.h" 28#include "platform.h"
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_testbed_service.h" 30#include "gnunet_testbed_service.h"
31#include "testbed_api.h"
31#include "testbed_api_peers.h" 32#include "testbed_api_peers.h"
32#include "testbed_api_hosts.h" 33#include "testbed_api_hosts.h"
33#include "testbed_api_topology.h" 34#include "testbed_api_topology.h"
@@ -242,11 +243,6 @@ struct RunContext
242 GNUNET_SCHEDULER_TaskIdentifier register_hosts_task; 243 GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
243 244
244 /** 245 /**
245 * Task to be run while shutting down
246 */
247 GNUNET_SCHEDULER_TaskIdentifier shutdown_run_task;
248
249 /**
250 * Task to be run of a timeout 246 * Task to be run of a timeout
251 */ 247 */
252 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 248 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
@@ -257,11 +253,6 @@ struct RunContext
257 GNUNET_SCHEDULER_TaskIdentifier interrupt_task; 253 GNUNET_SCHEDULER_TaskIdentifier interrupt_task;
258 254
259 /** 255 /**
260 * Task for cleaning up the run context and various resources it uses
261 */
262 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
263
264 /**
265 * The event mask for the controller 256 * The event mask for the controller
266 */ 257 */
267 uint64_t event_mask; 258 uint64_t event_mask;
@@ -448,7 +439,7 @@ remove_rcop (struct RunContext *rc, struct RunContextOperation *rcop)
448 * @param tc the task context from scheduler 439 * @param tc the task context from scheduler
449 */ 440 */
450static void 441static void
451cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 442cleanup (void *cls)
452{ 443{
453 struct RunContext *rc = cls; 444 struct RunContext *rc = cls;
454 unsigned int hid; 445 unsigned int hid;
@@ -478,20 +469,6 @@ cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
478 469
479 470
480/** 471/**
481 * Perform the cleanup task now
482 *
483 * @param rc the run context to be cleaned up
484 */
485static void
486cleanup_now (struct RunContext *rc)
487{
488 if (GNUNET_SCHEDULER_NO_TASK != rc->cleanup_task)
489 GNUNET_SCHEDULER_cancel (rc->cleanup_task);
490 rc->cleanup_task = GNUNET_SCHEDULER_add_now (&cleanup, rc);
491}
492
493
494/**
495 * Iterator for cleaning up elements from rcop_map 472 * Iterator for cleaning up elements from rcop_map
496 * 473 *
497 * @param cls the RunContext 474 * @param cls the RunContext
@@ -514,21 +491,6 @@ rcop_cleanup_iterator (void *cls, uint32_t key, void *value)
514 491
515 492
516/** 493/**
517 * Cleanup existing operation in given run context
518 *
519 * @param rc the run context
520 */
521static void
522cleanup_operations (struct RunContext *rc)
523{
524 GNUNET_assert (GNUNET_SYSERR !=
525 GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map,
526 &rcop_cleanup_iterator,
527 rc));
528}
529
530
531/**
532 * Cancels operations and tasks which are assigned to the given run context 494 * Cancels operations and tasks which are assigned to the given run context
533 * 495 *
534 * @param rc the RunContext 496 * @param rc the RunContext
@@ -561,11 +523,6 @@ rc_cleanup_operations (struct RunContext *rc)
561 GNUNET_SCHEDULER_cancel (rc->timeout_task); 523 GNUNET_SCHEDULER_cancel (rc->timeout_task);
562 rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; 524 rc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
563 } 525 }
564 if (GNUNET_SCHEDULER_NO_TASK != rc->interrupt_task)
565 {
566 GNUNET_SCHEDULER_cancel (rc->interrupt_task);
567 rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK;
568 }
569 if (NULL != rc->reg_handle) 526 if (NULL != rc->reg_handle)
570 { 527 {
571 GNUNET_TESTBED_cancel_registration (rc->reg_handle); 528 GNUNET_TESTBED_cancel_registration (rc->reg_handle);
@@ -577,66 +534,71 @@ rc_cleanup_operations (struct RunContext *rc)
577 rc->topology_operation = NULL; 534 rc->topology_operation = NULL;
578 } 535 }
579 /* cancel any exiting operations */ 536 /* cancel any exiting operations */
580 cleanup_operations (rc); 537 GNUNET_assert (GNUNET_SYSERR !=
538 GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map,
539 &rcop_cleanup_iterator,
540 rc));
581} 541}
582 542
583 543
584/** 544/**
585 * Stops the testbed run and releases any used resources 545 * Cancels the scheduled interrupt task
586 * 546 *
587 * @param cls the tesbed run handle 547 * @param rc the run context
588 * @param tc the task context from scheduler
589 */ 548 */
590static void 549static void
591shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 550cancel_interrupt_task (struct RunContext *rc)
551{
552 GNUNET_SCHEDULER_cancel (rc->interrupt_task);
553 rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK;
554}
555
556
557/**
558 * This callback will be called when all the operations are completed
559 * (done/cancelled)
560 *
561 * @param cls run context
562 * @param tc scheduler task context
563 */
564static void
565wait_op_completion (void *cls)
592{ 566{
593 struct RunContext *rc = cls; 567 struct RunContext *rc = cls;
594 struct RunContextOperation *rcop; 568 struct RunContextOperation *rcop;
595 569
596 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task); 570 if ( (NULL == rc->cproc)
597 rc->shutdown_run_task = GNUNET_SCHEDULER_NO_TASK; 571 || (NULL == rc->c)
598 GNUNET_assert (GNUNET_NO == rc->shutdown); 572 || (GNUNET_YES == rc->shutdown) )
599 rc->shutdown = GNUNET_YES;
600 rc_cleanup_operations (rc);
601 if (NULL != rc->c)
602 { 573 {
603 if (NULL != rc->peers) 574 if (NULL != rc->peers)
604 { 575 {
605 rcop = GNUNET_malloc (sizeof (struct RunContextOperation)); 576 GNUNET_free (rc->peers);
606 rcop->rc = rc; 577 rc->peers = NULL;
607 rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL);
608 GNUNET_assert (NULL != rcop->op);
609 DEBUG ("Shutting down peers\n");
610 rc->pstart_time = GNUNET_TIME_absolute_get ();
611 insert_rcop (rc, rcop);
612 return;
613 } 578 }
579 goto cleanup_;
614 } 580 }
615 rc->state = RC_PEERS_SHUTDOWN; /* No peers are present so we consider the 581 if (NULL == rc->peers)
616 * state where all peers are SHUTDOWN */ 582 goto cleanup_;
617 cleanup_now (rc); 583 rc->shutdown = GNUNET_YES;
618} 584 rcop = GNUNET_malloc (sizeof (struct RunContextOperation));
619 585 rcop->rc = rc;
586 rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL);
587 GNUNET_assert (NULL != rcop->op);
588 DEBUG ("Shutting down peers\n");
589 rc->pstart_time = GNUNET_TIME_absolute_get ();
590 insert_rcop (rc, rcop);
591 return;
620 592
621/** 593 cleanup_:
622 * Function to shutdown now 594 rc->state = RC_PEERS_SHUTDOWN;
623 * 595 cancel_interrupt_task (rc);
624 * @param rc the RunContext 596 cleanup (rc);
625 */
626static void
627shutdown_now (struct RunContext *rc)
628{
629 if (GNUNET_YES == rc->shutdown)
630 return;
631 if (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task)
632 GNUNET_SCHEDULER_cancel (rc->shutdown_run_task);
633 GNUNET_SCHEDULER_shutdown (); /* Trigger shutdown in programs using this API */
634 rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc);
635} 597}
636 598
637 599
638/** 600/**
639 * Task run upon any interrupt. Common ones are SIGINT & SIGTERM. 601 * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown.
640 * 602 *
641 * @param cls the RunContext which has to be acted upon 603 * @param cls the RunContext which has to be acted upon
642 * @param tc the scheduler task context 604 * @param tc the scheduler task context
@@ -645,9 +607,24 @@ static void
645interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 607interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
646{ 608{
647 struct RunContext *rc = cls; 609 struct RunContext *rc = cls;
610 struct GNUNET_TESTBED_Controller *c = rc->c;
611 unsigned int size;
648 612
649 rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; 613 /* reschedule */
650 shutdown_now (rc); 614 rc->interrupt_task = GNUNET_SCHEDULER_add_delayed
615 (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt, rc);
616 rc_cleanup_operations (rc);
617 if ( (GNUNET_NO == rc->shutdown)
618 && (NULL != c)
619 && (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map))))
620 {
621 LOG (GNUNET_ERROR_TYPE_WARNING, "Shutdown postponed as there are "
622 "%u operations currently active\n", size);
623 c->opcq_empty_cb = &wait_op_completion;
624 c->opcq_empty_cls = rc;
625 return;
626 }
627 wait_op_completion (rc);
651} 628}
652 629
653 630
@@ -721,7 +698,7 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
721 if (NULL != emsg) 698 if (NULL != emsg)
722 LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n", 699 LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n",
723 emsg); 700 emsg);
724 shutdown_now (rc); 701 GNUNET_SCHEDULER_shutdown ();
725 return; 702 return;
726 } 703 }
727 rc->peers[rc->peer_count] = peer; 704 rc->peers[rc->peer_count] = peer;
@@ -830,7 +807,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
830 if (NULL != event->details.operation_finished.emsg) 807 if (NULL != event->details.operation_finished.emsg)
831 { 808 {
832 LOG (GNUNET_ERROR_TYPE_ERROR, _("Linking controllers failed. Exiting")); 809 LOG (GNUNET_ERROR_TYPE_ERROR, _("Linking controllers failed. Exiting"));
833 shutdown_now (rc); 810 GNUNET_SCHEDULER_shutdown ();
834 } 811 }
835 else 812 else
836 rc->reg_hosts++; 813 rc->reg_hosts++;
@@ -846,7 +823,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
846 return; 823 return;
847 default: 824 default:
848 GNUNET_break (0); 825 GNUNET_break (0);
849 shutdown_now (rc); 826 GNUNET_SCHEDULER_shutdown ();
850 return; 827 return;
851 } 828 }
852 } 829 }
@@ -862,7 +839,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
862 { 839 {
863 LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n", 840 LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n",
864 event->details.operation_finished.emsg); 841 event->details.operation_finished.emsg);
865 shutdown_now (rc); 842 GNUNET_SCHEDULER_shutdown ();
866 return; 843 return;
867 } 844 }
868 GNUNET_assert (GNUNET_YES == rc->shutdown); 845 GNUNET_assert (GNUNET_YES == rc->shutdown);
@@ -875,7 +852,7 @@ event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
875 GNUNET_free_non_null (rc->peers); 852 GNUNET_free_non_null (rc->peers);
876 rc->peers = NULL; 853 rc->peers = NULL;
877 DEBUG ("Peers shut down in %s\n", prof_time (rc)); 854 DEBUG ("Peers shut down in %s\n", prof_time (rc));
878 cleanup_now (rc); 855 GNUNET_SCHEDULER_shutdown ();
879 break; 856 break;
880 default: 857 default:
881 GNUNET_assert (0); 858 GNUNET_assert (0);
@@ -972,7 +949,7 @@ host_registration_completion (void *cls, const char *emsg)
972 { 949 {
973 LOG (GNUNET_ERROR_TYPE_WARNING, 950 LOG (GNUNET_ERROR_TYPE_WARNING,
974 _("Host registration failed for a host. Error: %s\n"), emsg); 951 _("Host registration failed for a host. Error: %s\n"), emsg);
975 shutdown_now (rc); 952 GNUNET_SCHEDULER_shutdown ();
976 return; 953 return;
977 } 954 }
978 rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc); 955 rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
@@ -1037,20 +1014,7 @@ controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1037 { 1014 {
1038 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1015 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1039 _("Controller crash detected. Shutting down.\n")); 1016 _("Controller crash detected. Shutting down.\n"));
1040 rc->cproc = NULL; 1017 GNUNET_SCHEDULER_shutdown ();
1041 rc_cleanup_operations (rc);
1042 if (NULL != rc->peers)
1043 {
1044 GNUNET_free (rc->peers);
1045 rc->peers = NULL;
1046 }
1047 if (GNUNET_YES == rc->shutdown)
1048 {
1049 rc->state = RC_PEERS_SHUTDOWN;
1050 cleanup_now (rc);
1051 }
1052 else
1053 shutdown_now (rc);
1054 return; 1018 return;
1055 } 1019 }
1056 GNUNET_CONFIGURATION_destroy (rc->cfg); 1020 GNUNET_CONFIGURATION_destroy (rc->cfg);
@@ -1143,7 +1107,7 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host,
1143 else 1107 else
1144 LOG (GNUNET_ERROR_TYPE_ERROR, 1108 LOG (GNUNET_ERROR_TYPE_ERROR,
1145 _("Testbed cannot be started on localhost\n")); 1109 _("Testbed cannot be started on localhost\n"));
1146 shutdown_now (rc); 1110 GNUNET_SCHEDULER_shutdown ();
1147 return; 1111 return;
1148 } 1112 }
1149 rc->reg_hosts++; 1113 rc->reg_hosts++;
@@ -1181,7 +1145,7 @@ host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host,
1181 if (NULL == rc->cproc) 1145 if (NULL == rc->cproc)
1182 { 1146 {
1183 LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller")); 1147 LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller"));
1184 shutdown_now (rc); 1148 GNUNET_SCHEDULER_shutdown ();
1185 } 1149 }
1186} 1150}
1187 1151
@@ -1199,7 +1163,7 @@ timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1199 1163
1200 rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; 1164 rc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1201 LOG (GNUNET_ERROR_TYPE_ERROR, _("Shutting down testbed due to timeout while setup.\n")); 1165 LOG (GNUNET_ERROR_TYPE_ERROR, _("Shutting down testbed due to timeout while setup.\n"));
1202 shutdown_now (rc); 1166 GNUNET_SCHEDULER_shutdown ();
1203 if (NULL != rc->test_master) 1167 if (NULL != rc->test_master)
1204 rc->test_master (rc->test_master_cls, 0, NULL, 0, 0); 1168 rc->test_master (rc->test_master_cls, 0, NULL, 0, 0);
1205 rc->test_master = NULL; 1169 rc->test_master = NULL;