-fix'
[oweals/gnunet.git] / src / regex / gnunet-regex-profiler.c
index 7812c10958c955f856e4828b5d6f49556d2dc6ab..303f1fffc784f1f54d9b45ff498d7ab0f9ce644d 100644 (file)
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file mesh/gnunet-regex-profiler.c
+ * @file regex/gnunet-regex-profiler.c
  * @brief Regex profiler for testing distributed regex use.
  * @author Bartlomiej Polot
  * @author Maximilian Szengel
 #include "gnunet_applications.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_regex_lib.h"
+#include "gnunet_arm_service.h"
 #include "gnunet_dht_service.h"
 #include "gnunet_testbed_service.h"
 
+#define FIND_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90)
+#define SEARCHES_IN_PARALLEL 2
+
 /**
  * DLL of operations
  */
@@ -149,7 +153,12 @@ struct RegexPeer
   int search_str_matched;
 
   /**
-   * Peer's dht handle.
+   * Peer's ARM handle.
+   */
+  struct GNUNET_ARM_Handle *arm_handle;
+
+  /**
+   * Peer's DHT handle.
    */
   struct GNUNET_DHT_Handle *dht_handle;
 
@@ -159,9 +168,9 @@ struct RegexPeer
    struct GNUNET_REGEX_search_handle *search_handle;
 
   /**
-   * Testbed operation handle for the dht service.
+   * Testbed operation handle for the ARM and DHT services.
    */
-  struct GNUNET_TESTBED_Operation *dht_op_handle;
+  struct GNUNET_TESTBED_Operation *op_handle;
 
   /**
    * Peers's statistics handle.
@@ -177,6 +186,11 @@ struct RegexPeer
    * The starting time of a profiling step.
    */
   struct GNUNET_TIME_Absolute prof_start_time;
+
+  /**
+   * Operation timeout
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout;
 };
 
 
@@ -287,15 +301,10 @@ static unsigned int linking_factor;
 static unsigned int num_links;
 
 /**
- * Number of times we try overlay connect operations
+ * Number of connect operations that have failed, candidates to retry
  */
 static unsigned int retry_links;
 
-/**
- * Continuous failures during overlay connect operations
- */
-static unsigned int cont_fails;
-
 /**
  * Global testing status
  */
@@ -321,6 +330,16 @@ static char **search_strings;
  */
 static int num_search_strings;
 
+/**
+ * How many searches are running in parallel
+ */
+static unsigned int parallel_searches;
+
+/**
+ * Index of peer/string search.
+ */
+static unsigned int peer_cnt;
+
 /**
  * Number of peers found with search strings.
  */
@@ -362,13 +381,6 @@ static char *data_filename;
  */
 static unsigned int max_path_compression;
 
-/**
- * If we should distribute the search evenly throught all peers (each
- * peer searches for a string) or if only one peer should search for
- * all strings.
- */
-static int no_distributed_search;
-
 /**
  * Prefix used for regex announcing. We need to prefix the search
  * strings with it, in order to find something.
@@ -380,26 +392,6 @@ static char * regex_prefix;
 /******************************  DECLARATIONS  ********************************/
 /******************************************************************************/
 
-
-/**
- * Search callback function.
- *
- * @param cls Closure provided in GNUNET_REGEX_search.
- * @param id Peer providing a regex that matches the string.
- * @param get_path Path of the get request.
- * @param get_path_length Lenght of get_path.
- * @param put_path Path of the put request.
- * @param put_path_length Length of the put_path.
- */
-static void
-regex_found_handler (void *cls,
-                     const struct GNUNET_PeerIdentity *id,
-                     const struct GNUNET_PeerIdentity *get_path,
-                     unsigned int get_path_length,
-                     const struct GNUNET_PeerIdentity *put_path,
-                     unsigned int put_path_length);
-
-
 /**
  * DHT connect callback.
  *
@@ -452,7 +444,7 @@ stats_connect_cb (void *cls,
 
 
 /**
- * Task to collect all statistics from all peers, will shutdown the
+ * Task to collect all statistics from s, will shutdown the
  * profiler, when done.
  *
  * @param cls NULL
@@ -519,8 +511,8 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
     }
 
-    if (NULL != peers[peer_cnt].dht_op_handle)
-      GNUNET_TESTBED_operation_done (peers[peer_cnt].dht_op_handle);
+    if (NULL != peers[peer_cnt].op_handle)
+      GNUNET_TESTBED_operation_done (peers[peer_cnt].op_handle);
     if (NULL != peers[peer_cnt].stats_op_handle)
       GNUNET_TESTBED_operation_done (peers[peer_cnt].stats_op_handle);
   }
@@ -778,9 +770,20 @@ do_collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
 
 /******************************************************************************/
-/************************  MESH SERVICE CONNECTIONS  **************************/
+/************************   REGEX FIND CONNECTIONS   **************************/
 /******************************************************************************/
 
+
+/**
+ * Start searching for the next string in the DHT.
+ *
+ * @param cls Index of the next peer in the peers array.
+ * @param tc TaskContext.
+ */
+static void
+find_next_string (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
 /**
  * Method called when we've found a peer that announced a regex
  * that matches our search string. Now get the statistics.
@@ -813,6 +816,14 @@ regex_found_handler (void *cls,
   }
 
   peers_found++;
+  parallel_searches--;
+
+  if (GNUNET_SCHEDULER_NO_TASK != peer->timeout)
+  {
+    GNUNET_SCHEDULER_cancel (peer->timeout);
+    peer->timeout = GNUNET_SCHEDULER_NO_TASK;
+    GNUNET_SCHEDULER_add_now (&find_next_string, NULL);
+  }
 
   if (NULL == id)
   {
@@ -820,24 +831,17 @@ regex_found_handler (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "String matching timed out for string %s on peer %u (%i/%i)\n",
                 peer->search_str, peer->id, peers_found, num_search_strings);
-
-    printf ("String matching timed out for string %s on peer %u (%i/%i)\n",
-            peer->search_str, peer->id, peers_found, num_search_strings);
-
     peer->search_str_matched = GNUNET_SYSERR;
   }
   else
   {
     prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "String %s successfully matched on peer %u after %s (%i/%i)\n",
-                peer->search_str, peer->id, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
-                peers_found, num_search_strings);
 
-    printf ("String %s successfully matched on peer %u after %s (%i/%i)\n",
-            peer->search_str, peer->id, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
-            peers_found, num_search_strings);
-    fflush (stdout);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "String %s found on peer %u after %s (%i/%i) (%u||)\n",
+                peer->search_str, peer->id,
+                GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
+                peers_found, num_search_strings, parallel_searches);
 
     peer->search_str_matched = GNUNET_YES;
 
@@ -862,8 +866,8 @@ regex_found_handler (void *cls,
     }
   }
 
-  GNUNET_TESTBED_operation_done (peer->dht_op_handle);
-  peer->dht_op_handle = NULL;
+  GNUNET_TESTBED_operation_done (peer->op_handle);
+  peer->op_handle = NULL;
 
   if (peers_found == num_search_strings)
   {
@@ -871,13 +875,11 @@ regex_found_handler (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "All strings successfully matched in %s\n",
                 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
-    printf ("All strings successfully matched.\n");
-    fflush (stdout);
 
     if (GNUNET_SCHEDULER_NO_TASK != search_timeout_task)
       GNUNET_SCHEDULER_cancel (search_timeout_task);
 
-    printf ("Collecting stats and shutting down.\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Collecting stats and shutting down.\n");
     GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL);
   }
 }
@@ -920,33 +922,266 @@ static void
 do_connect_by_string (void *cls,
                       const struct GNUNET_SCHEDULER_TaskContext * tc)
 {
+  unsigned int i;
+
   printf ("Starting string search.\n");
   fflush (stdout);
 
-  peers[0].search_str = search_strings[0];
-  peers[0].search_str_matched = GNUNET_NO;
+  search_timeout_task = GNUNET_SCHEDULER_add_delayed (search_timeout,
+                                                      &do_connect_by_string_timeout, NULL);
+  for (i = 0; i < SEARCHES_IN_PARALLEL; i++)
+    GNUNET_SCHEDULER_add_now (&find_next_string, NULL);
+}
+
+
+/**
+ * Search timed out. It might still complete in the future,
+ * but we should start another one.
+ *
+ * @param cls Index of the next peer in the peers array.
+ * @param tc TaskContext.
+ */
+static void
+find_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct RegexPeer *p = cls;
+
+  p->timeout = GNUNET_SCHEDULER_NO_TASK;
+
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Searching for string \"%s\" on peer %d timed out. Starting new search.\n",
+              p->search_str,
+              p->id);
+  GNUNET_SCHEDULER_add_now (&find_next_string, NULL);
+}
 
+
+/**
+ * Start searching for the next string in the DHT.
+ *
+ * @param cls Index of the next peer in the peers array.
+ * @param tc TaskContext.
+ */
+static void
+find_next_string (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) ||
+      peer_cnt >= num_search_strings)
+    return;
+
+  parallel_searches++;
+  peers[peer_cnt].search_str = search_strings[peer_cnt];
+  peers[peer_cnt].search_str_matched = GNUNET_NO;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             "Searching for string \"%s\" on peer %d with file %s\n",
-             peers[0].search_str, 0, peers[0].policy_file);
+              "Searching for string \"%s\" on peer %d with file %s (%u||)\n",
+              peers[peer_cnt].search_str,
+              peer_cnt,
+              peers[peer_cnt].policy_file,
+              parallel_searches);
+
+  peers[peer_cnt].op_handle =
+    GNUNET_TESTBED_service_connect (NULL,
+                                    peers[peer_cnt].peer_handle,
+                                    "dht",
+                                    &dht_connect_cb,
+                                    &peers[peer_cnt],
+                                    &dht_ca,
+                                    &dht_da,
+                                    &peers[peer_cnt]);
+  peers[peer_cnt].timeout = GNUNET_SCHEDULER_add_delayed (FIND_TIMEOUT,
+                                                          &find_timeout,
+                                                          &peers[peer_cnt]);
+  peer_cnt++;
+}
+
+
+
+/**
+ * Start announcing the next regex in the DHT.
+ *
+ * @param cls Index of the next peer in the peers array.
+ * @param tc TaskContext.
+ */
+void
+announce_next_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * ARM connect adapter. Opens a connection to the ARM service.
+ *
+ * @param cls Closure (peer).
+ * @param cfg Configuration handle.
+ *
+ * @return
+ */
+static void *
+arm_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct RegexPeer *peer = cls;
+
+  peer->arm_handle = GNUNET_ARM_alloc (cfg);
+  GNUNET_ARM_connect (peer->arm_handle, NULL, NULL);
+
+  return peer->arm_handle;
+}
+
+
+/**
+ * Adapter function called to destroy a connection to the ARM service.
+ *
+ * @param cls Closure (peer).
+ * @param op_result Service handle returned from the connect adapter.
+ */
+static void
+arm_da (void *cls, void *op_result)
+{
+  struct RegexPeer *peer = (struct RegexPeer *) cls;
+
+  GNUNET_assert (peer->arm_handle == op_result);
+
+  if (NULL != peer->arm_handle)
+  {
+    GNUNET_ARM_disconnect (peer->arm_handle);
+    peer->arm_handle = NULL;
+  }
+}
+
+static void
+regexprofiler_start_cb (void *cls, struct GNUNET_ARM_Handle *arm,
+    enum GNUNET_ARM_RequestStatus rs, const char *service,
+    enum GNUNET_ARM_Result result)
+{
+  struct RegexPeer *peer = (struct RegexPeer *) cls;
+  unsigned int next_p;
+
+  if (rs != GNUNET_ARM_REQUEST_SENT_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ARM request was not sent: %u\n", rs);
+    GNUNET_abort ();
+  }
+  else if (result != GNUNET_ARM_RESULT_STARTING)
+  {
+    /* FIXME: maybe check for other acceptable results (already starting,
+     * already started)?
+     */
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ARM failed to start regexprofiler: %u\n", result);
+    GNUNET_abort ();
+  }
+  GNUNET_TESTBED_operation_done (peer->op_handle);
+  peer->op_handle = NULL;
+
+  if (peer_cnt < (num_peers - 1))
+  {
+    next_p = (++peer_cnt % num_peers);
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
+                                    GNUNET_TIME_UNIT_MILLISECONDS,
+                                    400),
+                                  &announce_next_regex,
+                                  (void *) (long) next_p);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "All daemons started."
+                " Waiting %s to start string searches\n",
+                GNUNET_STRINGS_relative_time_to_string (search_delay,
+                                                        GNUNET_NO));
+    GNUNET_SCHEDULER_add_delayed (search_delay,
+                                  do_connect_by_string, 
+                                  NULL);
+  }
+}
+
+/**
+ * ARM connect callback. Called when we are connected to the arm service for
+ * the peer in 'cls'. If successfull we start the regex deamon to start
+ * announcing the regex of this peer.
+ *
+ * @param cls internal peer id.
+ * @param op operation handle.
+ * @param ca_result connect adapter result.
+ * @param emsg error message.
+ */
+static void
+arm_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
+                void *ca_result, const char *emsg)
+{
+  struct RegexPeer *peer = (struct RegexPeer *) cls;
+
+  if (NULL != emsg || NULL == op || NULL == ca_result)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ARM connect failed: %s\n", emsg);
+    GNUNET_abort ();
+  }
+
+  GNUNET_assert (NULL != peer->arm_handle);
+  GNUNET_assert (peer->op_handle == op);
+  GNUNET_assert (peer->arm_handle == ca_result);
+
+  GNUNET_ARM_request_service_start (ca_result, "regexprofiler",
+      GNUNET_OS_INHERIT_STD_NONE,
+      GNUNET_TIME_UNIT_FOREVER_REL,
+      regexprofiler_start_cb, cls);
+}
+
 
-    /* First connect to mesh service, then search for string. Next
-       connect will be in mesh_connect_cb */
-    peers[0].dht_op_handle =
+/**
+ * Task to start the daemons on each peer so that the regexes are announced
+ * into the DHT.
+ *
+ * @param cls NULL
+ * @param tc the task context
+ */
+static void
+do_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  printf ("Starting announce.\n");
+  fflush (stdout);
+
+    /* First connect to arm service, then announce. Next
+       announce will be in arm_connect_cb */
+    peers[0].op_handle =
       GNUNET_TESTBED_service_connect (NULL,
                                       peers[0].peer_handle,
-                                      "dht",
-                                      &dht_connect_cb,
+                                      "arm",
+                                      &arm_connect_cb,
                                       &peers[0],
-                                      &dht_ca,
-                                      &dht_da,
+                                      &arm_ca,
+                                      &arm_da,
                                       &peers[0]);
 
-  search_timeout_task = GNUNET_SCHEDULER_add_delayed (search_timeout,
-                                                      &do_connect_by_string_timeout, NULL);
 }
 
 
+/**
+ * Start announcing the next regex in the DHT.
+ *
+ * @param cls Index of the next peer in the peers array.
+ * @param tc TaskContext.
+ */
+void
+announce_next_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  long next_p = (long) cls;
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting daemon %ld\n", next_p);
+
+  peers[next_p].op_handle =
+    GNUNET_TESTBED_service_connect (NULL,
+                                    peers[next_p].peer_handle,
+                                    "arm",
+                                    &arm_connect_cb,
+                                    &peers[next_p],
+                                    &arm_ca,
+                                    &arm_da,
+                                    &peers[next_p]);
+}
+
 /**
  * DHT connect callback. Called when we are connected to the dht service for
  * the peer in 'cls'. If successfull we connect to the stats service of this
@@ -962,8 +1197,6 @@ dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
                 void *ca_result, const char *emsg)
 {
   struct RegexPeer *peer = (struct RegexPeer *) cls;
-  static unsigned int peer_cnt;
-  unsigned int next_p;
 
   if (NULL != emsg || NULL == op || NULL == ca_result)
   {
@@ -972,7 +1205,7 @@ dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
   }
 
   GNUNET_assert (NULL != peer->dht_handle);
-  GNUNET_assert (peer->dht_op_handle == op);
+  GNUNET_assert (peer->op_handle == op);
   GNUNET_assert (peer->dht_handle == ca_result);
 
   peer->search_str_matched = GNUNET_NO;
@@ -981,35 +1214,6 @@ dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
                                              &regex_found_handler, peer,
                                              NULL);
   peer->prof_start_time = GNUNET_TIME_absolute_get ();
-
-  if (peer_cnt < (num_search_strings - 1))
-  {
-    if (GNUNET_YES == no_distributed_search)
-      next_p = 0;
-    else
-      next_p = (++peer_cnt % num_peers);
-
-    peers[next_p].search_str = search_strings[next_p];
-    peers[next_p].search_str_matched = GNUNET_NO;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Searching for string \"%s\" on peer %d with file %s\n",
-                peers[next_p].search_str, next_p, peers[next_p].policy_file);
-
-    /* FIXME
-     * dont connect to a new dht for each peer, we might want to seach for n
-     * strings on m peers where n > m
-     */
-    peers[next_p].dht_op_handle =
-      GNUNET_TESTBED_service_connect (NULL,
-                                      peers[next_p].peer_handle,
-                                      "dht",
-                                      &dht_connect_cb,
-                                      &peers[next_p],
-                                      &dht_ca,
-                                      &dht_da,
-                                      &peers[next_p]);
-  }
 }
 
 
@@ -1086,10 +1290,13 @@ do_configure_topology (void *cls,
   prof_start_time = GNUNET_TIME_absolute_get ();
   topology_op =
     GNUNET_TESTBED_overlay_configure_topology (NULL, num_peers, peer_handles,
+                                               NULL,
+                                               NULL,
                                                NULL,
                                                GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI,
                                                num_links,
-                                               GNUNET_TESTBED_TOPOLOGY_DISABLE_AUTO_RETRY,
+                                               GNUNET_TESTBED_TOPOLOGY_RETRY_CNT,
+                                               (unsigned int) 0,
                                                GNUNET_TESTBED_TOPOLOGY_OPTION_END);
   if (NULL == topology_op)
   {
@@ -1121,7 +1328,7 @@ peer_churn_cb (void *cls, const char *emsg)
   if (NULL != emsg)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-         _("An operation has failed while starting peers\n"));
+         _("An operation has failed while starting peers: %s\n"), emsg);
     GNUNET_TESTBED_operation_done (op);
     if (GNUNET_SCHEDULER_NO_TASK != abort_task)
       GNUNET_SCHEDULER_cancel (abort_task);
@@ -1132,7 +1339,7 @@ peer_churn_cb (void *cls, const char *emsg)
   if (++started_peers == num_peers)
   {
     prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
                 "All peers started successfully in %s\n",
                 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
     result = GNUNET_OK;
@@ -1202,7 +1409,8 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
     for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
     {
       dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
-      dll_op->op = GNUNET_TESTBED_peer_start (dll_op, peers[peer_cnt].peer_handle,
+      dll_op->op = GNUNET_TESTBED_peer_start (dll_op,
+                                              peers[peer_cnt].peer_handle,
                                               &peer_churn_cb, dll_op);
       GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
     }
@@ -1370,34 +1578,39 @@ controller_event_cb (void *cls,
      /* Control reaches here when a peer linking operation fails */
      if (NULL != event->details.operation_finished.emsg)
      {
-       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    _("An operation has failed while linking\n"));
-       printf ("F");
-       fflush (stdout);
+       printf ("F%u/%u(%s)",
+               retry_links + 1, established_links + 1, 
+               event->details.operation_finished.emsg);
        retry_links++;
      }
      /* We do no retries, consider this link as established */
      /* break; */
    case GNUNET_TESTBED_ET_CONNECT:
    {
-     char output_buffer[512];
+     char output_buffer[1024];
      size_t size;
 
      if (0 == established_links)
-       printf ("Establishing links .");
+       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Establishing links .");
      else
      {
        printf (".");
-       fflush (stdout);
      }
      if (++established_links == num_links)
      {
-       fflush (stdout);
        prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                   "%u links established in %s\n",
+                   "\n%u links established in %s\n",
                    num_links,
-                   GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
+                   GNUNET_STRINGS_relative_time_to_string (prof_time,
+                                                           GNUNET_NO));
+       prof_time = GNUNET_TIME_relative_divide(prof_time, num_links);
+       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                   "Average of %s per connection\n",
+                   GNUNET_STRINGS_relative_time_to_string (prof_time,
+                                                           GNUNET_NO));
        result = GNUNET_OK;
        GNUNET_free (peer_handles);
 
@@ -1407,12 +1620,15 @@ controller_event_cb (void *cls,
            GNUNET_snprintf (output_buffer,
                             sizeof (output_buffer),
                             "# of peers: %u\n# of links established: %u\n"
-                            "Time to establish links: %s\nLinking failures: %u\n"
-                            "path compression length: %u\n# of search strings: %u\n",
+                            "Time to establish links: %s\n"
+                            "Linking failures: %u\n"
+                            "path compression length: %u\n"
+                            "# of search strings: %u\n",
                             num_peers,
-                            (established_links - cont_fails),
-                            GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
-                            cont_fails,
+                            (established_links - retry_links),
+                            GNUNET_STRINGS_relative_time_to_string (prof_time,
+                                                                    GNUNET_NO),
+                            retry_links,
                             max_path_compression,
                             num_search_strings);
 
@@ -1420,18 +1636,13 @@ controller_event_cb (void *cls,
            GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
        }
 
-       printf ("\nWaiting %s before starting to search.\n",
-               GNUNET_STRINGS_relative_time_to_string (search_delay, GNUNET_YES));
-       fflush (stdout);
-
        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                   "Waiting %s before starting to search.\n",
-                   GNUNET_STRINGS_relative_time_to_string (search_delay, GNUNET_NO));
-
+                   "\nWaiting %s before starting to announce.\n",
+                   GNUNET_STRINGS_relative_time_to_string (search_delay,
+                                                           GNUNET_NO));
        state = STATE_SEARCH_REGEX;
-
        search_task = GNUNET_SCHEDULER_add_delayed (search_delay,
-                                                   &do_connect_by_string, NULL);
+                                                   &do_announce, NULL);
      }
    }
    break;
@@ -1548,7 +1759,7 @@ status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int stat
   if (GNUNET_OK != status)
   {
     mc_proc = NULL;
-    printf("CRAPPP\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Oh, dear!\n");
     abort_task = GNUNET_SCHEDULER_add_now (&do_abort, (void*) __LINE__);
     return;
   }
@@ -1708,34 +1919,42 @@ run (void *cls, char *const *args, const char *cfgfile,
 
   if (NULL == args[0])
   {
-    fprintf (stderr, _("No hosts-file specified on command line. Exiting.\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("No hosts-file specified on command line. Exiting.\n"));
     return;
   }
   if (NULL == args[1])
   {
-    fprintf (stderr, _("No policy directory specified on command line. Exiting.\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("No policy directory specified on command line. Exiting.\n"));
     return;
   }
-  num_hosts = GNUNET_TESTBED_hosts_load_from_file (args[0], &hosts);
+  num_hosts = GNUNET_TESTBED_hosts_load_from_file (args[0], config, &hosts);
   if (0 == num_hosts)
   {
-    fprintf (stderr, _("No hosts loaded. Need at least one host\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("No hosts loaded. Need at least one host\n"));
     return;
   }
-  printf (_("Checking whether given hosts can start testbed. Please wait\n"));
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
+              _("Checking whether given hosts can start testbed."
+                "Please wait\n"));
   hc_handles = GNUNET_malloc (sizeof (struct
                                       GNUNET_TESTBED_HostHabitableCheckHandle *) 
                               * num_hosts);
   for (nhost = 0; nhost < num_hosts; nhost++)
-  {    
-    if (NULL == (hc_handles[nhost] = GNUNET_TESTBED_is_host_habitable (hosts[nhost], config,
-                                                                       &host_habitable_cb,
-                                                                       &hc_handles[nhost])))
+  {
+    hc_handles[nhost] = GNUNET_TESTBED_is_host_habitable (hosts[nhost], config,
+                                                          &host_habitable_cb,
+                                                          &hc_handles[nhost]);
+    if (NULL == hc_handles[nhost])
     {
+      int i;
+
       GNUNET_break (0);
-      for (nhost = 0; nhost < num_hosts; nhost++)
-        if (NULL != hc_handles[nhost])
-          GNUNET_TESTBED_is_host_habitable_cancel (hc_handles[nhost]);
+      for (i = 0; i <= nhost; i++)
+        if (NULL != hc_handles[i])
+          GNUNET_TESTBED_is_host_habitable_cancel (hc_handles[i]);
       GNUNET_free (hc_handles);
       hc_handles = NULL;
       break;
@@ -1743,13 +1962,14 @@ run (void *cls, char *const *args, const char *cfgfile,
   }
   if (num_hosts != nhost)
   {
-    fprintf (stderr, _("Exiting\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Exiting\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
   if (NULL == config)
   {
-    fprintf (stderr, _("No configuration file given. Exiting\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("No configuration file given. Exiting\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
@@ -1758,7 +1978,8 @@ run (void *cls, char *const *args, const char *cfgfile,
       GNUNET_CONFIGURATION_get_value_string (config, "REGEXPROFILER", "REGEX_PREFIX",
                                             &regex_prefix))
   {
-    fprintf (stderr, _("Configuration option (regex_prefix) missing. Exiting\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Configuration option \"regex_prefix\" missing. Exiting\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
@@ -1776,14 +1997,16 @@ run (void *cls, char *const *args, const char *cfgfile,
                               data_filename);
   if (GNUNET_YES != GNUNET_DISK_directory_test (args[1], GNUNET_YES))
   {
-    fprintf (stderr, _("Specified policies directory does not exist. Exiting.\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Specified policies directory does not exist. Exiting.\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
   policy_dir = args[1];
   if (GNUNET_YES != GNUNET_DISK_file_test (args[2]))
   {
-    fprintf (stderr, _("No search strings file given. Exiting.\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("No search strings file given. Exiting.\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
@@ -1791,13 +2014,16 @@ run (void *cls, char *const *args, const char *cfgfile,
   if (num_search_strings != nsearchstrs)
   {
     num_search_strings = nsearchstrs;
-    fprintf (stderr, _("Error loading search strings. Given file does not contain enough strings. Exiting.\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Error loading search strings."
+                  "Given file does not contain enough strings. Exiting.\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
   if (0 >= num_search_strings || NULL == search_strings)
   {
-    fprintf (stderr, _("Error loading search strings. Exiting.\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Error loading search strings. Exiting.\n"));
     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
     return;
   }
@@ -1841,9 +2067,6 @@ main (int argc, char *const *argv)
     {'p', "max-path-compression", "MAX_PATH_COMPRESSION",
      gettext_noop ("maximum path compression length"),
      1, &GNUNET_GETOPT_set_uint, &max_path_compression},
-    {'i', "no-distributed-search", "",
-     gettext_noop ("if this option is set, only one peer is responsible for searching all strings"),
-     0, &GNUNET_GETOPT_set_one, &no_distributed_search},
     GNUNET_GETOPT_OPTION_END
   };
   int ret;
@@ -1853,8 +2076,9 @@ main (int argc, char *const *argv)
 
   result = GNUNET_SYSERR;
   ret =
-      GNUNET_PROGRAM_run (argc, argv, "gnunet-regex-profiler [OPTIONS] hosts-file policy-dir search-strings-file",
-                          _("Profiler for regex/mesh"),
+      GNUNET_PROGRAM_run (argc, argv,
+                          "gnunet-regex-profiler [OPTIONS] hosts-file policy-dir search-strings-file",
+                          _("Profiler for regex"),
                           options, &run, NULL);
 
   if (GNUNET_OK != ret)