replacing test_regex_big with gnunet-regex-profiler
[oweals/gnunet.git] / src / regex / gnunet-regex-profiler.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file regex/gnunet-regex-profiler.c
23  * @brief Regex profiler for testing distributed regex use.
24  * @author Bart Polot
25  * @author Max Szengel
26  */
27
28 #include <string.h>
29
30 #include "platform.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_mesh_service.h"
33 #include "gnunet_stream_lib.h"
34 #include "gnunet_testbed_service.h"
35
36
37 #define NUM_HOSTS 2
38
39 #define PEER_PER_HOST 1
40
41 #define TOTAL_PEERS (NUM_HOSTS * PEER_PER_HOST)
42
43 /**
44  * Shorthand for Relative time in seconds
45  */
46 #define TIME_REL_SECS(sec) \
47   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
48
49 /**
50  * Structure for holding peer's sockets and IO Handles
51  */
52 struct PeerData
53 {
54   /**
55    * Handle to testbed peer
56    */
57   struct GNUNET_TESTBED_Peer *peer;
58
59   /**
60    * The service connect operation to stream
61    */
62   struct GNUNET_TESTBED_Operation *op;
63
64   /**
65    * Our Peer id
66    */
67   struct GNUNET_PeerIdentity our_id;
68 };
69
70
71 /**
72  * Different states in test setup
73  */
74 enum SetupState
75 {
76   /**
77    * The initial state
78    */
79   INIT,
80
81   /**
82    * Connecting to slave controller
83    */
84   LINKING,
85
86   LINKING_SLAVES,
87
88   LINKING_SLAVES_SUCCESS,
89
90   CONNECTING_PEERS,
91
92   CREATING_PEER,
93
94   STARTING_PEER
95 };
96
97
98 /**
99  * Event Mask for operation callbacks
100  */
101 uint64_t event_mask;
102
103 /**
104  * Testbed operation handle
105  */
106 static struct GNUNET_TESTBED_Operation *op[NUM_HOSTS];
107
108 static enum SetupState state[NUM_HOSTS];
109
110 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
111
112 /**
113  * Global test result
114  */
115 static int result;
116
117 /**
118  * Hosts successfully registered
119  */
120 static unsigned int host_registered;
121
122 /**
123  * Peers successfully started
124  */
125 static unsigned int peers_started;
126
127 /**
128  * The master controller host
129  */
130 struct GNUNET_TESTBED_Host *master_host;
131
132 /**
133  * The master controller process
134  */
135 static struct GNUNET_TESTBED_ControllerProc *master_proc;
136
137 /**
138  * Handle to master controller
139  */
140 static struct GNUNET_TESTBED_Controller *master_ctrl;
141
142 /**
143  * Slave host IP addresses
144  */
145
146 static char *slave_ips[NUM_HOSTS] = { "192.168.1.33", "192.168.1.34" };
147
148 /**
149  * The slave hosts
150  */
151 struct GNUNET_TESTBED_Host *slave_hosts[NUM_HOSTS];
152
153 /**
154  * Slave host registration handles
155  */
156 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
157
158 /**
159  * The peers
160  */
161 struct GNUNET_TESTBED_Peer *peers[TOTAL_PEERS];
162
163 /**
164  * Handle to global configuration
165  */
166 static struct GNUNET_CONFIGURATION_Handle *cfg;
167
168
169 /**
170  * Completion callback for shutdown
171  *
172  * @param cls the closure from GNUNET_STREAM_shutdown call
173  * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
174  *          SHUT_RDWR)
175  */
176 // static void
177 // shutdown_completion (void *cls,
178 //                      int operation)
179 // {
180 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STREAM shutdown successful\n");
181 //   GNUNET_SCHEDULER_add_now (&do_close, cls);
182 // }
183
184
185
186 /**
187  * Shutdown sockets gracefully
188  */
189 // static void
190 // do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
191 // {
192 //   result = GNUNET_OK;
193 //   peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket, SHUT_RDWR,
194 //                                                   &shutdown_completion, cls);
195 // }
196
197
198 /**
199  * Something went wrong and timed out. Kill everything and set error flag
200  */
201 static void
202 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
203 {
204   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
205   result = GNUNET_SYSERR;
206   abort_task = 0;
207 }
208
209
210 /**
211  * Adapter function called to destroy a connection to
212  * a service.
213  *
214  * @param cls closure
215  * @param op_result service handle returned from the connect adapter
216  */
217 // static void
218 // stream_da (void *cls, void *op_result)
219 // {
220 //   struct GNUNET_STREAM_ListenSocket *lsocket;
221 //   struct GNUNET_STREAM_Socket *socket;
222 //
223 //   if (&peer1 == cls)
224 //   {
225 //     lsocket = op_result;
226 //     GNUNET_STREAM_listen_close (lsocket);
227 //     GNUNET_TESTBED_operation_done (peer2.op);
228 //     return;
229 //   }
230 //   if (&peer2 == cls)
231 //   {
232 //     socket = op_result;
233 //     GNUNET_STREAM_close (socket);
234 //     GNUNET_SCHEDULER_shutdown (); /* Exit point of the test */
235 //     return;
236 //   }
237 //   GNUNET_assert (0);
238 // }
239
240
241 /**
242  * Adapter function called to establish a connection to
243  * a service.
244  *
245  * @param cls closure
246  * @param cfg configuration of the peer to connect to; will be available until
247  *          GNUNET_TESTBED_operation_done() is called on the operation returned
248  *          from GNUNET_TESTBED_service_connect()
249  * @return service handle to return in 'op_result', NULL on error
250  */
251 // static void *
252 // stream_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
253 // {
254 //   struct GNUNET_STREAM_ListenSocket *lsocket;
255 //
256 //   switch (setup_state)
257 //   {
258 //   case PEER1_STREAM_CONNECT:
259 //     lsocket = GNUNET_STREAM_listen (cfg, 10, &stream_listen_cb, NULL,
260 //                                     GNUNET_STREAM_OPTION_SIGNAL_LISTEN_SUCCESS,
261 //                                     &stream_connect, GNUNET_STREAM_OPTION_END);
262 //     return lsocket;
263 //   case PEER2_STREAM_CONNECT:
264 //     peer2.socket = GNUNET_STREAM_open (cfg, &peer1.our_id, 10, &stream_open_cb,
265 //                                        &peer2, GNUNET_STREAM_OPTION_END);
266 //     return peer2.socket;
267 //   default:
268 //     GNUNET_assert (0);
269 //   }
270 // }
271
272
273 /**
274  * Listen success callback; connects a peer to stream as client
275  */
276 // static void
277 // stream_connect (void)
278 // {
279 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stream listen open successful\n");
280 //   peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "stream",
281 //                                              NULL, NULL,
282 //                                              stream_ca, stream_da, &peer2);
283 //   setup_state = PEER2_STREAM_CONNECT;
284 // }
285
286
287 /**
288  * Callback to be called when the requested peer information is available
289  *
290  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
291  * @param op the operation this callback corresponds to
292  * @param pinfo the result; will be NULL if the operation has failed
293  * @param emsg error message if the operation has failed; will be NULL if the
294  *          operation is successfull
295  */
296 // static void
297 // peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
298 //              const struct GNUNET_TESTBED_PeerInformation *pinfo,
299 //              const char *emsg)
300 // {
301 //   GNUNET_assert (NULL == emsg);
302 //   GNUNET_assert (op == op_);
303 //   switch (setup_state)
304 //     {
305 //     case PEER1_GET_IDENTITY:
306 //       memcpy (&peer1.our_id, pinfo->result.id,
307 //               sizeof (struct GNUNET_PeerIdentity));
308 //       GNUNET_TESTBED_operation_done (op);
309 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s
310 //                   (&peer1.our_id));
311 //       op = GNUNET_TESTBED_peer_get_information (peer2.peer,
312 //                                                 GNUNET_TESTBED_PIT_IDENTITY,
313 //                                                 &peerinfo_cb, NULL);
314 //       setup_state = PEER2_GET_IDENTITY;
315 //       break;
316 //     case PEER2_GET_IDENTITY:
317 //       memcpy (&peer2.our_id, pinfo->result.id,
318 //               sizeof (struct GNUNET_PeerIdentity));
319 //       GNUNET_TESTBED_operation_done (op);
320 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s
321 //                   (&peer2.our_id));
322 //       peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "stream",
323 //                                                  NULL, NULL, stream_ca,
324 //                                                  stream_da, &peer1);
325 //       setup_state = PEER1_STREAM_CONNECT;
326 //       break;
327 //     default:
328 //       GNUNET_assert (0);
329 //     }
330 // }
331
332
333 /**
334  * Signature of a main function for a testcase.
335  *
336  * @param cls closure
337  * @param num_peers number of peers in 'peers'
338  * @param peers handle to peers run in the testbed
339  */
340 // static void
341 // test_master (void *cls, unsigned int num_peers,
342 //              struct GNUNET_TESTBED_Peer **peers)
343 // {
344 //   GNUNET_assert (NULL != peers);
345 //   GNUNET_assert (NULL != peers[0]);
346 //   GNUNET_assert (NULL != peers[1]);
347 //   peer1.peer = peers[0];
348 //   peer2.peer = peers[1];
349 //   op = GNUNET_TESTBED_overlay_connect (NULL, NULL, NULL, peer2.peer, peer1.peer);
350 //   setup_state = INIT;
351 //   abort_task =
352 //     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
353 //                                   (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort,
354 //                                   NULL);
355 // }
356
357 void
358 mesh_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
359                  void *ca_result, const char *emsg)
360 {
361   long i = (long) cls;
362
363   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh connect callback for peer %i\n",
364               i);
365 }
366
367
368 void *
369 mesh_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
370 {
371   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh connect adapter\n");
372
373   return NULL;
374 }
375
376
377 void
378 mesh_da (void *cls, void *op_result)
379 {
380   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh disconnect adapter\n");
381 }
382
383
384 /**
385  * Functions of this signature are called when a peer has been successfully
386  * started or stopped.
387  *
388  * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
389  * @param emsg NULL on success; otherwise an error description
390  */
391 static void
392 peer_start_cb (void *cls, const char *emsg)
393 {
394   unsigned int cnt;
395   long i = (long) cls;
396
397   GNUNET_TESTBED_operation_done (op[i]);
398   peers_started++;
399   // FIXME create and start rest of PEERS_PER_HOST
400   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u peer(s) started\n", peers_started);
401
402   if (TOTAL_PEERS == peers_started)
403   {
404     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started.\n");
405     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Linking slave controllers\n");
406
407     for (cnt = 0; cnt < NUM_HOSTS - 1; cnt++)
408     {
409       state[cnt] = LINKING_SLAVES;
410       op[cnt] =
411           GNUNET_TESTBED_get_slave_config ((void *) (long) cnt, master_ctrl,
412                                            slave_hosts[cnt + 1]);
413     }
414   }
415 }
416
417
418 /**
419  * Functions of this signature are called when a peer has been successfully
420  * created
421  *
422  * @param cls the closure from GNUNET_TESTBED_peer_create()
423  * @param peer the handle for the created peer; NULL on any error during
424  *          creation
425  * @param emsg NULL if peer is not NULL; else MAY contain the error description
426  */
427 static void
428 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
429 {
430   long i = (long) cls;
431   long peer_id;
432
433 //   GNUNET_TESTBED_operation_done(op[i]);
434   peer_id = i;                  // FIXME  A * i + B
435   peers[peer_id] = peer;
436   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer %i created\n", peer_id);
437   op[i] = GNUNET_TESTBED_peer_start (NULL, peer, peer_start_cb, (void *) i);
438 }
439
440
441 /**
442  * Signature of the event handler function called by the
443  * respective event controller.
444  *
445  * @param cls closure
446  * @param event information about the event
447  */
448 static void
449 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
450 {
451   long i;
452
453   switch (event->type)
454   {
455   case GNUNET_TESTBED_ET_PEER_START:
456     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer started\n");
457     /* event->details.peer_start.peer; */
458     /* event->details.peer_start.host; */
459
460     break;
461   case GNUNET_TESTBED_ET_PEER_STOP:
462     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer stopped\n");
463     break;
464   case GNUNET_TESTBED_ET_CONNECT:
465     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Overlay Connected\n");
466     for (i = 0; i < TOTAL_PEERS; i++)
467     {
468       GNUNET_TESTBED_service_connect (NULL, peers[i], "mesh", &mesh_connect_cb,
469                                       (void *) i, &mesh_ca, &mesh_da, NULL);
470     }
471     break;
472   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
473     if (NULL != event->details.operation_finished.emsg)
474     {
475       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testbed error: %s\n",
476                   event->details.operation_finished.emsg);
477       GNUNET_assert (0);
478     }
479
480     i = (long) event->details.operation_finished.op_cls;
481     switch (state[i])
482     {
483     case INIT:
484       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Init: %u\n", i);
485       GNUNET_TESTBED_operation_done (event->details.
486                                      operation_finished.operation);
487       op[i] = NULL;
488       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
489       break;
490     case LINKING:
491       GNUNET_TESTBED_operation_done (event->details.
492                                      operation_finished.operation);
493       op[i] = NULL;
494       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
495       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Linked host %i\n", i);
496       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Creating peer...\n");
497
498       state[i] = CREATING_PEER;
499       op[i] =
500           GNUNET_TESTBED_peer_create (master_ctrl, slave_hosts[i], cfg,
501                                       peer_create_cb, (void *) i);
502       break;
503     case CREATING_PEER:
504       GNUNET_TESTBED_operation_done (event->details.
505                                      operation_finished.operation);
506       op[i] = NULL;
507       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
508       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Peer create\n");
509       break;
510     case LINKING_SLAVES:
511     {
512       struct GNUNET_CONFIGURATION_Handle *slave_cfg;
513
514       GNUNET_assert (NULL != event->details.operation_finished.generic);
515       slave_cfg =
516           GNUNET_CONFIGURATION_dup ((struct GNUNET_CONFIGURATION_Handle *)
517                                     event->details.operation_finished.generic);
518       GNUNET_TESTBED_operation_done (event->details.
519                                      operation_finished.operation);
520       op[i] = NULL;
521       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
522       state[i] = LINKING_SLAVES_SUCCESS;
523       op[i] =
524           GNUNET_TESTBED_controller_link ((void *) (long) i, master_ctrl,
525                                           slave_hosts[i + 1], slave_hosts[i],
526                                           slave_cfg, GNUNET_NO);
527       GNUNET_CONFIGURATION_destroy (slave_cfg);
528       break;
529     }
530     case LINKING_SLAVES_SUCCESS:
531       GNUNET_TESTBED_operation_done (event->details.
532                                      operation_finished.operation);
533       op[i] = NULL;
534       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
535       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Linking slave %i succeeded\n", i);
536       state[0] = CONNECTING_PEERS;
537       op[0] =
538           GNUNET_TESTBED_overlay_configure_topology (NULL, TOTAL_PEERS, peers,
539                                                      GNUNET_TESTBED_TOPOLOGY_LINE);
540       GNUNET_assert (NULL != op[0]);
541       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peers...\n");
542       break;
543     case CONNECTING_PEERS:
544       GNUNET_TESTBED_operation_done (event->details.
545                                      operation_finished.operation);
546       op[i] = NULL;
547       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
548       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n");
549       break;
550     default:
551       GNUNET_break (0);
552     }
553     break;
554   default:
555     GNUNET_break (0);
556   }
557 }
558
559 /**
560  * Callback which will be called to after a host registration succeeded or failed
561  *
562  * @param cls the host which has been registered
563  * @param emsg the error message; NULL if host registration is successful
564  */
565 static void
566 registration_cont (void *cls, const char *emsg)
567 {
568   if (NULL != emsg)
569   {
570     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
571     GNUNET_assert (0);
572   }
573   state[host_registered] = LINKING;
574   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Linking host %u\n", host_registered);
575   op[host_registered] =
576       GNUNET_TESTBED_controller_link ((void *) (long) host_registered,
577                                       master_ctrl, slave_hosts[host_registered],
578                                       NULL, cfg, GNUNET_YES);
579   host_registered++;
580   if (NUM_HOSTS != host_registered)
581   {
582     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
583                 host_registered);
584     rh = GNUNET_TESTBED_register_host (master_ctrl,
585                                        slave_hosts[host_registered],
586                                        &registration_cont, NULL);
587     return;
588   }
589 }
590
591 /**
592  * Callback to signal successfull startup of the controller process
593  *
594  * @param cls the closure from GNUNET_TESTBED_controller_start()
595  * @param cfg the configuration with which the controller has been started;
596  *          NULL if status is not GNUNET_OK
597  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
598  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
599  */
600 static void
601 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
602            int status)
603 {
604   unsigned int i;
605
606   if (NULL == config || GNUNET_OK != status)
607     return;
608
609   event_mask = 0;
610   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
611   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
612   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
613   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
614   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to master controller\n");
615   master_ctrl =
616       GNUNET_TESTBED_controller_connect (config, master_host, event_mask,
617                                          &controller_cb, NULL);
618   GNUNET_assert (NULL != master_ctrl);
619
620   for (i = 0; i < NUM_HOSTS; i++)
621   {
622     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating host %u\n", i);
623     slave_hosts[i] = GNUNET_TESTBED_host_create (slave_ips[i], NULL, 0);
624     GNUNET_assert (NULL != slave_hosts[i]);
625   }
626   host_registered = 0;
627   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
628               host_registered);
629   rh = GNUNET_TESTBED_register_host (master_ctrl, slave_hosts[0],
630                                      &registration_cont, NULL);
631   GNUNET_assert (NULL != rh);
632 }
633
634
635 /**
636  * Main run function.
637  *
638  * @param cls NULL
639  * @param args arguments passed to GNUNET_PROGRAM_run
640  * @param cfgfile the path to configuration file
641  * @param cfg the configuration file handle
642  */
643 static void
644 run (void *cls, char *const *args, const char *cfgfile,
645      const struct GNUNET_CONFIGURATION_Handle *config)
646 {
647   master_host = GNUNET_TESTBED_host_create ("192.168.1.33", NULL, 0);
648   GNUNET_assert (NULL != master_host);
649   cfg = GNUNET_CONFIGURATION_dup (config);
650   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting master controller\n");
651   master_proc =
652       GNUNET_TESTBED_controller_start ("192.168.1.33", master_host, cfg,
653                                        status_cb, NULL);
654   abort_task =
655       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
656                                     (GNUNET_TIME_UNIT_MINUTES, 60), &do_abort,
657                                     NULL);
658 }
659
660 /**
661  * Main function
662  */
663 int
664 main (int argc, char **argv)
665 {
666   int ret;
667   int test_hosts;
668   unsigned int i;
669
670   struct GNUNET_GETOPT_CommandLineOption options[] = {
671     GNUNET_GETOPT_OPTION_END
672   };
673   char *const argv2[] = { "gnunet-regex-profiler",
674     "-c", "regex_profiler_test.conf",
675     NULL
676   };
677
678   test_hosts = GNUNET_OK;
679   for (i = 0; i < NUM_HOSTS; i++)
680   {
681     char *const remote_args[] = {
682       "ssh", "-o", "BatchMode=yes", slave_ips[i],
683       "gnunet-helper-testbed --help > /dev/null", NULL
684     };
685     struct GNUNET_OS_Process *auxp;
686     enum GNUNET_OS_ProcessStatusType type;
687     unsigned long code;
688
689     fprintf (stderr, "Testing host %i\n", i);
690     auxp =
691         GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
692                                      NULL, "ssh", remote_args);
693     GNUNET_assert (NULL != auxp);
694     do
695     {
696       ret = GNUNET_OS_process_status (auxp, &type, &code);
697       GNUNET_assert (GNUNET_SYSERR != ret);
698       (void) usleep (300);
699     }
700     while (GNUNET_NO == ret);
701     (void) GNUNET_OS_process_wait (auxp);
702     GNUNET_OS_process_destroy (auxp);
703     if (0 != code)
704     {
705       fprintf (stderr,
706                "Unable to run the test as this system is not configured "
707                "to use password less SSH logins to host %s.\n", slave_ips[i]);
708       test_hosts = GNUNET_SYSERR;
709     }
710   }
711   if (test_hosts != GNUNET_OK)
712   {
713     fprintf (stderr, "Some hosts have failed the ssh check. Exiting.\n");
714     return 1;
715   }
716   fprintf (stderr, "START.\n");
717
718   result = GNUNET_SYSERR;
719
720   ret =
721       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
722                           "gnunet-regex-profiler", "nohelp", options, &run, NULL);
723
724   fprintf (stderr, "END.\n");
725
726   if (GNUNET_SYSERR == result || GNUNET_OK != ret)
727     return 1;
728   return 0;
729 }