free in proper place
[oweals/gnunet.git] / src / testing / testing_group.c
index b4420115dbb3d64a87ebf58766bee50b9a58c77a..f9b3cc3fc51eeb8c6dfac8da260999525c387d3e 100644 (file)
@@ -44,7 +44,7 @@
  * enough to not conflict with client-ports (typically starting around
  * 32k).
  */
-#define LOW_PORT 10000
+#define LOW_PORT 12000
 
 /**
  * Highest port used for GNUnet testing.  Should be low enough to not
@@ -363,6 +363,23 @@ struct ChurnRestartContext
   struct GNUNET_TIME_Relative timeout;
 };
 
+struct OutstandingSSH
+{
+  struct OutstandingSSH *next;
+
+  struct OutstandingSSH *prev;
+
+  /**
+   * Number of current ssh connections.
+   */
+  uint32_t outstanding;
+
+  /**
+   * The hostname of this peer.
+   */
+  const char *hostname;
+};
+
 /**
  * Data we keep per peer.
  */
@@ -673,6 +690,18 @@ struct GNUNET_TESTING_PeerGroup
    * Hostkeys loaded from a file.
    */
   char *hostkey_data;
+
+  /**
+   * Head of DLL to keep track of the number of outstanding
+   * ssh connections per peer.
+   */
+  struct OutstandingSSH *ssh_head;
+
+  /**
+   * Tail of DLL to keep track of the number of outstanding
+   * ssh connections per peer.
+   */
+  struct OutstandingSSH *ssh_tail;
 };
 
 struct UpdateContext
@@ -2510,11 +2539,15 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
   struct GNUNET_OS_Process **procarr;
   char *arg;
   char *mytemp;
+#if NOT_STUPID
   enum GNUNET_OS_ProcessStatusType type;
   unsigned long return_code;
   int count;
-  int ret;
   int max_wait = 10;
+#endif
+  int ret;
+
+  ret = GNUNET_OK;
 #if OLD
   struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
   struct PeerConnection *conn_iter;
@@ -2586,6 +2619,11 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
             GNUNET_OS_start_process (NULL, NULL, "scp", "scp", mytemp, arg,
                                      NULL);
 
+          ret = GNUNET_OS_process_wait(procarr[pg_iter]); /* FIXME: schedule this, throttle! */
+          GNUNET_OS_process_close (procarr[pg_iter]);
+          if (ret != GNUNET_OK)
+            return ret;
+          procarr[pg_iter] = NULL;
 #if VERBOSE_TESTING
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       _("Copying file with command scp %s %s\n"), mytemp,
@@ -2597,6 +2635,7 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
       GNUNET_free (mytemp);
     }
 
+#if NOT_STUPID
   count = 0;
   ret = GNUNET_SYSERR;
   while ((count < max_wait) && (ret != GNUNET_OK))
@@ -2642,6 +2681,7 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
 #if VERBOSE_TESTING
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _("Finished copying all friend files!\n"));
+#endif
 #endif
   GNUNET_free (procarr);
   return ret;
@@ -2777,6 +2817,8 @@ create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg,
             GNUNET_OS_start_process (NULL, NULL, "scp", "scp", mytemp, arg,
                                      NULL);
 
+          GNUNET_OS_process_wait(procarr[pg_iter]); /* FIXME: add scheduled blacklist file copy that parallelizes file copying! */
+
 #if VERBOSE_TESTING
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       _("Copying file with command scp %s %s\n"), mytemp,
@@ -4564,6 +4606,63 @@ GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
   return connect_topology (pg, connect_timeout, connect_attempts, notify_callback, notify_cls);
 }
 
+/**
+ * Lookup and return the number of SSH connections to a host.
+ *
+ * @param hostname the hostname to lookup in the list
+ * @param pg the peergroup that the host belongs to
+ *
+ * @return the number of current ssh connections to the host
+ */
+static unsigned int
+count_outstanding_at_host(const char *hostname, struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct OutstandingSSH *pos;
+  pos = pg->ssh_head;
+  while ((pos != NULL) && (strcmp(pos->hostname, hostname) != 0))
+    pos = pos->next;
+  GNUNET_assert(pos != NULL);
+  return pos->outstanding;
+}
+
+
+/**
+ * Increment the number of SSH connections to a host by one.
+ *
+ * @param hostname the hostname to lookup in the list
+ * @param pg the peergroup that the host belongs to
+ *
+ */
+static void
+increment_outstanding_at_host(const char *hostname, struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct OutstandingSSH *pos;
+  pos = pg->ssh_head;
+  while ((pos != NULL) && (strcmp(pos->hostname, hostname) != 0))
+    pos = pos->next;
+  GNUNET_assert(pos != NULL);
+  pos->outstanding++;
+}
+
+/**
+ * Decrement the number of SSH connections to a host by one.
+ *
+ * @param hostname the hostname to lookup in the list
+ * @param pg the peergroup that the host belongs to
+ *
+ */
+static void
+decrement_outstanding_at_host(const char *hostname, struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct OutstandingSSH *pos;
+  pos = pg->ssh_head;
+  while ((pos != NULL) && (strcmp(pos->hostname, hostname) != 0))
+    pos = pos->next;
+  GNUNET_assert(pos != NULL);
+  pos->outstanding--;
+}
+
+
 /**
  * Callback that is called whenever a hostkey is generated
  * for a peer.  Call the real callback and decrement the
@@ -4582,6 +4681,8 @@ internal_hostkey_callback (void *cls,
   struct InternalStartContext *internal_context = cls;
   internal_context->peer->pg->starting--;
   internal_context->peer->pg->started++;
+  if (internal_context->hostname != NULL)
+    decrement_outstanding_at_host(internal_context->hostname, internal_context->peer->pg);
   if (internal_context->hostkey_callback != NULL)
     internal_context->hostkey_callback (internal_context->hostkey_cls, id, d,
                                         emsg);
@@ -4612,6 +4713,8 @@ internal_startup_callback (void *cls,
 {
   struct InternalStartContext *internal_context = cls;
   internal_context->peer->pg->starting--;
+  if (internal_context->hostname != NULL)
+    decrement_outstanding_at_host(internal_context->hostname, internal_context->peer->pg);
   if (internal_context->start_cb != NULL)
     internal_context->start_cb (internal_context->start_cb_cls, id, cfg, d,
                                 emsg);
@@ -4628,8 +4731,12 @@ internal_continue_startup (void *cls,
       return;
     }
 
-  if (internal_context->peer->pg->starting < internal_context->peer->pg->max_concurrent_ssh)
+  if ((internal_context->peer->pg->starting < internal_context->peer->pg->max_concurrent_ssh) ||
+      ((internal_context->hostname != NULL) &&
+       (count_outstanding_at_host(internal_context->hostname, internal_context->peer->pg) < internal_context->peer->pg->max_concurrent_ssh)))
     {
+      if (internal_context->hostname != NULL)
+        increment_outstanding_at_host(internal_context->hostname, internal_context->peer->pg);
       internal_context->peer->pg->starting++;
       GNUNET_TESTING_daemon_continue_startup (internal_context->peer->daemon);
     }
@@ -4725,6 +4832,8 @@ schedule_churn_restart (void *cls,
     }
 }
 
+
+
 static void
 internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
@@ -4735,8 +4844,12 @@ internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       return;
     }
 
-  if (internal_context->peer->pg->starting < internal_context->peer->pg->max_concurrent_ssh)
+  if ((internal_context->peer->pg->starting < internal_context->peer->pg->max_concurrent_ssh) ||
+      ((internal_context->hostname != NULL) &&
+       (count_outstanding_at_host(internal_context->hostname, internal_context->peer->pg) < internal_context->peer->pg->max_concurrent_ssh)))
     {
+      if (internal_context->hostname != NULL)
+        increment_outstanding_at_host(internal_context->hostname, internal_context->peer->pg);
       internal_context->peer->pg->starting++;
       internal_context->peer->daemon =
         GNUNET_TESTING_daemon_start (internal_context->peer->cfg,
@@ -4953,6 +5066,10 @@ GNUNET_TESTING_daemons_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
                                                                     &baseservicehome));
   for (i = 0; i < pg->num_hosts; i++)
     {
+      struct OutstandingSSH *ssh_entry;
+      ssh_entry = GNUNET_malloc(sizeof(struct OutstandingSSH));
+      ssh_entry->hostname = pg->hosts[i].hostname; /* Don't free! */
+      GNUNET_CONTAINER_DLL_insert(pg->ssh_head, pg->ssh_tail, ssh_entry);
       if (NULL != pg->hosts[i].username)
         GNUNET_asprintf (&arg, "%s@%s", pg->hosts[i].username, pg->hosts[i].hostname);
       else
@@ -5577,6 +5694,7 @@ void
 internal_shutdown_callback (void *cls, const char *emsg)
 {
   struct ShutdownContext *shutdown_ctx = cls;
+  unsigned int off;
 
   shutdown_ctx->outstanding--;
   if (emsg == NULL)
@@ -5597,6 +5715,17 @@ internal_shutdown_callback (void *cls, const char *emsg)
                           "Not all peers successfully shut down!");
       else
         shutdown_ctx->cb (shutdown_ctx->cb_cls, NULL);
+
+      GNUNET_free (shutdown_ctx->pg->peers);
+      GNUNET_free_non_null(shutdown_ctx->pg->hostkey_data);
+      for (off = 0; off < shutdown_ctx->pg->num_hosts; off++)
+        {
+          GNUNET_free (shutdown_ctx->pg->hosts[off].hostname);
+          GNUNET_free_non_null (shutdown_ctx->pg->hosts[off].username);
+        }
+      GNUNET_free_non_null (shutdown_ctx->pg->hosts);
+      GNUNET_free (shutdown_ctx->pg);
+
       GNUNET_free (shutdown_ctx);
     }
 }
@@ -5718,15 +5847,7 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg,
                                                peers[off].blacklisted_peers);
 #endif
     }
-  GNUNET_free (pg->peers);
-  GNUNET_free_non_null(pg->hostkey_data);
-  for (off = 0; off < pg->num_hosts; off++)
-    {
-      GNUNET_free (pg->hosts[off].hostname);
-      GNUNET_free_non_null (pg->hosts[off].username);
-    }
-  GNUNET_free_non_null (pg->hosts);
-  GNUNET_free (pg);
+
 }