+ &peers[search_peer]);
+ GNUNET_assert (NULL != peers[search_peer].op_handle);
+ peers[search_peer].timeout = GNUNET_SCHEDULER_add_delayed (FIND_TIMEOUT,
+ &find_timed_out,
+ &peers[search_peer]);
+}
+
+
+
+
+/**
+ * Callback called when testbed has started the daemon we asked for.
+ *
+ * @param cls NULL
+ * @param op the operation handle
+ * @param emsg NULL on success; otherwise an error description
+ */
+static void
+daemon_started (void *cls, struct GNUNET_TESTBED_Operation *op,
+ const char *emsg)
+{
+ struct RegexPeer *peer = (struct RegexPeer *) cls;
+ unsigned long search_peer;
+ unsigned int i;
+
+ GNUNET_TESTBED_operation_done (peer->daemon_op);
+ peer->daemon_op = NULL;
+ if (NULL != emsg)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to start/stop daemon at peer %u: %s\n", peer->id, emsg);
+ GNUNET_abort ();
+ }
+
+ /* Find a peer to look for a string matching the regex announced */
+ search_peer = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ num_peers);
+ for (i = 0; peers[search_peer].search_str != NULL; i++)
+ {
+ search_peer = (search_peer + 1) % num_peers;
+ if (i > num_peers)
+ GNUNET_abort (); /* we ran out of peers, must be a bug */
+ }
+ peers[search_peer].search_str = search_strings[peer->id];
+ peers[search_peer].search_str_matched = GNUNET_NO;
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
+ reannounce_period_max,
+ 2),
+ &find_string,
+ (void *) search_peer);
+}
+
+
+/**
+ * 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)
+{
+ unsigned int i;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting announce.\n");
+
+ for (i = 0; i < init_parallel_searches; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ " scheduling announce %u\n",
+ i);
+ (void) GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
+ }
+}
+
+
+/**
+ * Start announcing the next regex in the DHT.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext.
+ */
+static void
+announce_next_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct RegexPeer *peer;
+
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ if (next_search >= num_peers)
+ {
+ if (strings_found != num_peers)
+ {
+ struct GNUNET_TIME_Relative new_delay;
+ if (GNUNET_SCHEDULER_NO_TASK != search_timeout_task)
+ GNUNET_SCHEDULER_cancel (search_timeout_task);
+ new_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15);
+ search_timeout_task = GNUNET_SCHEDULER_add_delayed (new_delay,
+ &search_timed_out,
+ NULL);
+ }
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting daemon %u\n", next_search);
+ peer = &peers[next_search];
+ peer->daemon_op =
+ GNUNET_TESTBED_peer_manage_service (NULL,
+ peer->peer_handle,
+ "regexprofiler",
+ &daemon_started,
+ peer,
+ 1);
+ next_search++;
+ parallel_searches++;