add now instead of add delayed
[oweals/gnunet.git] / src / testing / testing.c
index 65441c1882ab337402221c0c4b5180a3eeb9237e..6d75be6a5a635a5c9a6ee8184d8af22bb60a472d 100644 (file)
@@ -37,8 +37,8 @@
 #include "gnunet_transport_service.h"
 #include "gnunet_hello_lib.h"
 
-#define DEBUG_TESTING GNUNET_YES
-#define DEBUG_TESTING_RECONNECT GNUNET_YES
+#define DEBUG_TESTING GNUNET_NO
+#define DEBUG_TESTING_RECONNECT GNUNET_NO
 
 /**
  * How long do we wait after starting gnunet-service-arm
@@ -126,7 +126,7 @@ testing_init (void *cls,
     {
       d->server = NULL;
       if (GNUNET_YES == d->dead)
-        GNUNET_TESTING_daemon_stop (d, 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, 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, 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"));
@@ -196,15 +196,14 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       /* confirm copying complete */
       if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
         {
-          d->wait_runs++;
-          if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
+          if (GNUNET_TIME_absolute_get_remaining(d->max_timeout).value == 0)
             {
               cb = d->cb;
               d->cb = NULL;
               if (NULL != cb)
                 cb (d->cb_cls,
                     NULL,
-                    d->cfg, d, _("`scp' does not seem to terminate.\n"));
+                    d->cfg, d, _("`scp' does not seem to terminate (timeout copying config).\n"));
               return;
             }
           /* wait some more */
@@ -305,7 +304,6 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                   "gnunet-peerinfo");
 #endif
       d->phase = SP_HOSTKEY_CREATE;
-      d->wait_runs = 0;
       d->task
         = GNUNET_SCHEDULER_add_delayed (d->sched,
                                         GNUNET_CONSTANTS_EXEC_WAIT,
@@ -336,8 +334,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
       if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
         {
-          d->wait_runs++;
-          if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
+          if (GNUNET_TIME_absolute_get_remaining(d->max_timeout).value == 0)
             {
               cb = d->cb;
               d->cb = NULL;
@@ -391,8 +388,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       /* Fall through */
     case SP_HOSTKEY_CREATED:
       /* wait for topology finished */
-      d->wait_runs++;
-      if ((GNUNET_YES == d->dead) || (d->wait_runs > MAX_EXEC_WAIT_RUNS))
+      if ((GNUNET_YES == d->dead) || (GNUNET_TIME_absolute_get_remaining(d->max_timeout).value == 0))
         {
           cb = d->cb;
           d->cb = NULL;
@@ -475,7 +471,6 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                   "gnunet-arm", "gnunet-service-core");
 #endif
       d->phase = SP_START_ARMING;
-      d->wait_runs = 0;
       d->task
         = GNUNET_SCHEDULER_add_delayed (d->sched,
                                         GNUNET_CONSTANTS_EXEC_WAIT,
@@ -484,8 +479,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     case SP_START_ARMING:
       if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
         {
-          d->wait_runs++;
-          if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
+          if (GNUNET_TIME_absolute_get_remaining(d->max_timeout).value == 0)
             {
               cb = d->cb;
               d->cb = NULL;
@@ -530,8 +524,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       /* confirm copying complete */
       if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
         {
-          d->wait_runs++;
-          if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
+          if (GNUNET_TIME_absolute_get_remaining(d->max_timeout).value == 0)
             {
               d->dead_cb (d->dead_cb_cls,
                           _("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
@@ -551,6 +544,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
               return;
             }
           /* wait some more */
+          fprintf(stderr, "scheduling in shutdown_start\n");
           d->task
             = GNUNET_SCHEDULER_add_delayed (d->sched,
                                             GNUNET_CONSTANTS_EXEC_WAIT,
@@ -587,22 +581,30 @@ 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);
+      d->hello = NULL;
       GNUNET_free_non_null (d->shortname);
+      d->shortname = NULL;
       if (NULL != d->dead_cb)
         d->dead_cb (d->dead_cb_cls, NULL);
-      GNUNET_free (d);
+
+      if (d->churn == GNUNET_NO)
+        GNUNET_free (d);
+
       break;
     case SP_CONFIG_UPDATE:
       /* confirm copying complete */
       if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
         {
-          d->wait_runs++;
-          if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
+          if (GNUNET_TIME_absolute_get_remaining(d->max_timeout).value == 0) /* FIXME: config update should take timeout parameter! */
             {
               cb = d->cb;
               d->cb = NULL;
@@ -651,6 +653,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
@@ -659,6 +694,7 @@ GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon)
  *
  * @param sched scheduler to use
  * @param cfg configuration to use
+ * @param timeout how long to wait starting up peers
  * @param hostname name of the machine where to run GNUnet
  *        (use NULL for localhost).
  * @param hostkey_callback function to call once the hostkey has been
@@ -672,6 +708,7 @@ GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon)
 struct GNUNET_TESTING_Daemon *
 GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
                              const struct GNUNET_CONFIGURATION_Handle *cfg,
+                             struct GNUNET_TIME_Relative timeout,
                              const char *hostname,
                              GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
                              void *hostkey_cls,
@@ -701,6 +738,7 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
   ret->hostkey_cls = hostkey_cls;
   ret->cb = cb;
   ret->cb_cls = cb_cls;
+  ret->max_timeout = GNUNET_TIME_relative_to_absolute(timeout);
   ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
   GNUNET_CONFIGURATION_set_value_string (ret->cfg,
                                          "PATHS",
@@ -868,7 +906,6 @@ GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
     }
 
     GNUNET_free_non_null(del_arg);
-    d->wait_runs = 0;
     d->task
       = GNUNET_SCHEDULER_add_delayed (d->sched,
                                       GNUNET_CONSTANTS_EXEC_WAIT,
@@ -881,16 +918,19 @@ GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
  * Stops a GNUnet daemon.
  *
  * @param d the daemon that should be stopped
+ * @param timeout how long to wait for process for shutdown to complete
  * @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;
@@ -929,8 +969,18 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
               _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id));
 #endif
 
-   d->phase = SP_SHUTDOWN_START;
+  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)
     {
@@ -969,11 +1019,11 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
     }
 
   GNUNET_free_non_null(del_arg);
-  d->wait_runs = 0;
+  d->max_timeout = GNUNET_TIME_relative_to_absolute(timeout);
+  fprintf(stderr, "scheduling shutdown fsm phase\n");
   d->task
-    = GNUNET_SCHEDULER_add_delayed (d->sched,
-                                    GNUNET_CONSTANTS_EXEC_WAIT,
-                                    &start_fsm, d);
+    = GNUNET_SCHEDULER_add_now (d->sched,
+                                &start_fsm, d);
 }
 
 
@@ -1363,7 +1413,7 @@ reattempt_daemons_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext
       return;
     }
 #if DEBUG_TESTING_RECONNECT
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "re-attempting connect of peer %s to peer %s\n",
+  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "re-attempting connect of peer %s to peer %s\n",
               ctx->d1->shortname, ctx->d2->shortname);
 #endif