2 This file is part of GNUnet.
3 (C) 2011, 2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file mesh/gnunet-regex-profiler.c
23 * @brief Regex profiler for testing distributed regex use.
32 #include "gnunet_applications.h"
33 #include "gnunet_util_lib.h"
34 #include "gnunet_mesh_service.h"
35 #include "gnunet_stream_lib.h"
36 #include "gnunet_testbed_service.h"
44 * The testbed operation handle
46 struct GNUNET_TESTBED_Operation *op;
54 * The next pointer for DLL
56 struct DLLOperation *next;
59 * The prev pointer for DLL
61 struct DLLOperation *prev;
66 * Available states during profiling
78 STATE_SLAVES_STARTING,
101 * Matching strings against announced regexes
106 * Destroying peers; we can do this as the controller takes care of stopping a
107 * peer if it is running
109 STATE_PEERS_DESTROYING
124 * The actual testbed peer handle.
126 struct GNUNET_TESTBED_Peer *peer_handle;
129 * Host on which the peer is running.
131 struct GNUNET_TESTBED_Host *host_handle;
134 * Filename of the peer's policy file.
139 * Peers search string.
141 const char *search_str;
144 * Set to GNUNET_YES if the peer successfully matched the above
145 * search string. GNUNET_NO if the string could not be matched
146 * during the profiler run. GNUNET_SYSERR if the string matching
147 * timed out. Undefined if search_str is NULL
149 int search_str_matched;
152 * Peer's mesh handle.
154 struct GNUNET_MESH_Handle *mesh_handle;
157 * Peer's mesh tunnel handle.
159 struct GNUNET_MESH_Tunnel *mesh_tunnel_handle;
162 * Testbed operation handle for the mesh service.
164 struct GNUNET_TESTBED_Operation *mesh_op_handle;
167 * Peers's statistics handle.
169 struct GNUNET_STATISTICS_Handle *stats_handle;
172 * Testbed operation handle for the statistics service.
174 struct GNUNET_TESTBED_Operation *stats_op_handle;
177 * The starting time of a profiling step.
179 struct GNUNET_TIME_Absolute prof_start_time;
184 * An array of hosts loaded from the hostkeys file
186 static struct GNUNET_TESTBED_Host **hosts;
189 * Array of peer handles used to pass to
190 * GNUNET_TESTBED_overlay_configure_topology
192 static struct GNUNET_TESTBED_Peer **peer_handles;
195 * The array of peers; we fill this as the peers are given to us by the testbed
197 static struct RegexPeer *peers;
200 * Host registration handle
202 static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
205 * Handle to the master controller process
207 static struct GNUNET_TESTBED_ControllerProc *mc_proc;
210 * Handle to the master controller
212 static struct GNUNET_TESTBED_Controller *mc;
215 * Handle to global configuration
217 static struct GNUNET_CONFIGURATION_Handle *cfg;
220 * Head of the operations list
222 static struct DLLOperation *dll_op_head;
225 * Tail of the operations list
227 static struct DLLOperation *dll_op_tail;
230 * Peer linking - topology operation
232 static struct GNUNET_TESTBED_Operation *topology_op;
235 * Abort task identifier
237 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
240 * Host registration task identifier
242 static GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
245 * Global event mask for all testbed events
247 static uint64_t event_mask;
250 * The starting time of a profiling step
252 static struct GNUNET_TIME_Absolute prof_start_time;
255 * Duration profiling step has taken
257 static struct GNUNET_TIME_Relative prof_time;
262 static unsigned int peer_id;
265 * Number of peers to be started by the profiler
267 static unsigned int num_peers;
270 * Number of hosts in the hosts array
272 static unsigned int num_hosts;
275 * Factor of number of links. num_links = num_peers * linking_factor.
277 static unsigned int linking_factor;
280 * Number of random links to be established between peers
282 static unsigned int num_links;
285 * Number of times we try overlay connect operations
287 static unsigned int retry_links;
290 * Continuous failures during overlay connect operations
292 static unsigned int cont_fails;
295 * Global testing status
300 * current state of profiling
305 * Folder where policy files are stored.
307 static char * policy_dir;
312 static char **search_strings;
315 * Number of search strings.
317 static int num_search_strings;
320 * Number of peers found with search strings.
322 static unsigned int peers_found;
325 * Search task identifier
327 static GNUNET_SCHEDULER_TaskIdentifier search_task;
330 * Search timeout task identifier.
332 static GNUNET_SCHEDULER_TaskIdentifier search_timeout_task;
335 * Search timeout in seconds.
337 static struct GNUNET_TIME_Relative search_timeout = { 60000 };
340 * How long do we wait before starting the search?
343 static struct GNUNET_TIME_Relative search_delay = { 60000 };
346 * Delay before setting mesh service op as done.
348 static struct GNUNET_TIME_Relative mesh_done_delay = { 1000 };
351 * Delay to wait before starting to configure the overlay topology
353 static struct GNUNET_TIME_Relative conf_topo_delay = { 10000 };
356 * File to log statistics to.
358 static struct GNUNET_DISK_FileHandle *data_file;
361 * Filename to log statistics to.
363 static char *data_filename;
366 * Maximal path compression length.
368 static unsigned int max_path_compression;
370 /******************************************************************************/
371 /****************************** DECLARATIONS ********************************/
372 /******************************************************************************/
376 * Method called whenever a peer has connected to the tunnel.
379 * @param peer_id peer identity the tunnel was created to, NULL on timeout
380 * @param atsi performance data for the connection
384 mesh_peer_connect_handler (void *cls,
385 const struct GNUNET_PeerIdentity* peer_id,
386 const struct GNUNET_ATS_Information * atsi);
390 * Method called whenever a peer has disconnected from the tunnel.
391 * Implementations of this callback must NOT call
392 * GNUNET_MESH_tunnel_destroy immediately, but instead schedule those
393 * to run in some other task later. However, calling
394 * "GNUNET_MESH_notify_transmit_ready_cancel" is allowed.
397 * @param peer_id peer identity the tunnel stopped working with
400 mesh_peer_disconnect_handler (void *cls,
401 const struct GNUNET_PeerIdentity * peer_id);
404 * Mesh connect callback.
406 * @param cls internal peer id.
407 * @param op operation handle.
408 * @param ca_result connect adapter result.
409 * @param emsg error message.
412 mesh_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
413 void *ca_result, const char *emsg);
416 * Mesh connect adapter.
418 * @param cls not used.
419 * @param cfg configuration handle.
424 mesh_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg);
428 * Adapter function called to destroy a connection to
432 * @param op_result service handle returned from the connect adapter
435 mesh_da (void *cls, void *op_result);
438 /******************************************************************************/
439 /******************************** SHUTDOWN **********************************/
440 /******************************************************************************/
447 * @param tc the task context
450 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
452 struct DLLOperation *dll_op;
453 struct RegexPeer *peer;
455 unsigned int peer_cnt;
456 unsigned int search_str_cnt;
457 char output_buffer[512];
460 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
461 GNUNET_SCHEDULER_cancel (abort_task);
462 if (GNUNET_SCHEDULER_NO_TASK != register_hosts_task)
463 GNUNET_SCHEDULER_cancel (register_hosts_task);
465 for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
467 peer = &peers[peer_cnt];
469 if (GNUNET_YES != peer->search_str_matched && NULL != data_file)
471 prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time);
473 GNUNET_snprintf (output_buffer,
474 sizeof (output_buffer),
475 "Search string not found: %s (%d)\nOn peer: %u (%p)\nWith policy file: %s\nAfter: %s\n",
477 peer->search_str_matched,
481 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
482 if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
483 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
486 if (NULL != peers[peer_cnt].mesh_op_handle)
487 GNUNET_TESTBED_operation_done (peers[peer_cnt].mesh_op_handle);
488 if (NULL != peers[peer_cnt].stats_op_handle)
489 GNUNET_TESTBED_operation_done (peers[peer_cnt].stats_op_handle);
492 if (NULL != data_file)
493 GNUNET_DISK_file_close (data_file);
495 for (search_str_cnt = 0;
496 search_str_cnt < num_search_strings && NULL != search_strings;
499 GNUNET_free_non_null (search_strings[search_str_cnt]);
501 GNUNET_free_non_null (search_strings);
503 if (NULL != reg_handle)
504 GNUNET_TESTBED_cancel_registration (reg_handle);
505 if (NULL != topology_op)
506 GNUNET_TESTBED_operation_done (topology_op);
507 for (nhost = 0; nhost < num_hosts; nhost++)
508 if (NULL != hosts[nhost])
509 GNUNET_TESTBED_host_destroy (hosts[nhost]);
510 GNUNET_free_non_null (hosts);
512 while (NULL != (dll_op = dll_op_head))
514 GNUNET_TESTBED_operation_done (dll_op->op);
515 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
516 GNUNET_free (dll_op);
519 GNUNET_TESTBED_controller_disconnect (mc);
521 GNUNET_TESTBED_controller_stop (mc_proc);
523 GNUNET_CONFIGURATION_destroy (cfg);
525 GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */
530 * abort task to run on test timed out
533 * @param tc the task context
536 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
538 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Aborting\n");
539 abort_task = GNUNET_SCHEDULER_NO_TASK;
540 result = GNUNET_SYSERR;
541 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
545 /******************************************************************************/
546 /********************* STATISTICS SERVICE CONNECTIONS ***********************/
547 /******************************************************************************/
550 * Adapter function called to establish a connection to
551 * statistics service.
554 * @param cfg configuration of the peer to connect to; will be available until
555 * GNUNET_TESTBED_operation_done() is called on the operation returned
556 * from GNUNET_TESTBED_service_connect()
557 * @return service handle to return in 'op_result', NULL on error
560 stats_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
562 return GNUNET_STATISTICS_create ("<driver>", cfg);
567 * Adapter function called to destroy a connection to
568 * statistics service.
571 * @param op_result service handle returned from the connect adapter
574 stats_da (void *cls, void *op_result)
576 struct RegexPeer *peer = cls;
578 GNUNET_assert (op_result == peer->stats_handle);
580 GNUNET_STATISTICS_destroy (peer->stats_handle, GNUNET_NO);
581 peer->stats_handle = NULL;
586 * Process statistic values.
589 * @param subsystem name of subsystem that created the statistic
590 * @param name the name of the datum
591 * @param value the current value
592 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
593 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
596 stats_iterator (void *cls, const char *subsystem, const char *name,
597 uint64_t value, int is_persistent)
599 struct RegexPeer *peer = cls;
600 char output_buffer[512];
603 if (NULL == data_file)
605 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
606 "%p -> %s [%s]: %llu\n",
607 peer, subsystem, name, value);
611 GNUNET_snprintf (output_buffer,
612 sizeof (output_buffer),
615 subsystem, value, name);
616 if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
617 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
627 * @param success GNUNET_OK if statistics were
628 * successfully obtained, GNUNET_SYSERR if not.
634 static unsigned int peer_cnt;
635 struct RegexPeer *peer = cls;
637 if (GNUNET_OK != success)
639 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
640 "Getting statistics for peer %u failed!\n",
645 GNUNET_TESTBED_operation_done (peer->stats_op_handle);
646 peer->stats_op_handle = NULL;
648 if (++peer_cnt == num_search_strings)
650 struct GNUNET_TIME_Relative delay = { 100 };
651 GNUNET_SCHEDULER_add_delayed (delay, &do_shutdown, NULL);
657 * Function called by testbed once we are connected to stats service.
659 * @param cls the 'struct RegexPeer' for which we connected to stats
660 * @param op connect operation handle
661 * @param ca_result handle to stats service
662 * @param emsg error message on failure
665 stats_connect_cb (void *cls,
666 struct GNUNET_TESTBED_Operation *op,
670 struct RegexPeer *peer = cls;
672 if (NULL == ca_result || NULL != emsg)
674 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
675 "Failed to connect to statistics service on peer %u: %s\n",
678 peer->stats_handle = NULL;
682 GNUNET_assert (NULL != peer->mesh_handle);
684 peer->stats_handle = ca_result;
686 peer->mesh_tunnel_handle = GNUNET_MESH_tunnel_create (peer->mesh_handle,
688 &mesh_peer_connect_handler,
689 &mesh_peer_disconnect_handler,
692 peer->prof_start_time = GNUNET_TIME_absolute_get ();
694 peer->search_str_matched = GNUNET_NO;
695 GNUNET_MESH_peer_request_connect_by_string (peer->mesh_tunnel_handle,
700 /******************************************************************************/
701 /************************ MESH SERVICE CONNECTIONS **************************/
702 /******************************************************************************/
705 * Method called whenever another peer has added us to a tunnel
706 * the other peer initiated.
707 * Only called (once) upon reception of data with a message type which was
708 * subscribed to in GNUNET_MESH_connect. A call to GNUNET_MESH_tunnel_destroy
709 * causes te tunnel to be ignored and no further notifications are sent about
713 * @param tunnel new handle to the tunnel
714 * @param initiator peer that started the tunnel
715 * @param atsi performance information for the tunnel
716 * @return initial tunnel context for the tunnel
717 * (can be NULL -- that's not an error)
720 mesh_inbound_tunnel_handler (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
721 const struct GNUNET_PeerIdentity *initiator,
722 const struct GNUNET_ATS_Information *atsi)
724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh inbound tunnel handler.\n");
731 * Function called whenever an inbound tunnel is destroyed. Should clean up
732 * any associated state. This function is NOT called if the client has
733 * explicitly asked for the tunnel to be destroyed using
734 * GNUNET_MESH_tunnel_destroy. It must NOT call GNUNET_MESH_tunnel_destroy on
737 * @param cls closure (set from GNUNET_MESH_connect)
738 * @param tunnel connection to the other end (henceforth invalid)
739 * @param tunnel_ctx place where local state associated
740 * with the tunnel is stored
743 mesh_tunnel_end_handler (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
746 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh tunnel end handler.\n");
751 * Method called whenever a peer has disconnected from the tunnel.
752 * Implementations of this callback must NOT call
753 * GNUNET_MESH_tunnel_destroy immediately, but instead schedule those
754 * to run in some other task later. However, calling
755 * "GNUNET_MESH_notify_transmit_ready_cancel" is allowed.
758 * @param peer_id peer identity the tunnel stopped working with
761 mesh_peer_disconnect_handler (void *cls,
762 const struct GNUNET_PeerIdentity * peer_id)
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh peer disconnect handler.\n");
769 * Method called whenever a peer has connected to the tunnel.
772 * @param peer_id peer identity the tunnel was created to, NULL on timeout
773 * @param atsi performance data for the connection
777 mesh_peer_connect_handler (void *cls,
778 const struct GNUNET_PeerIdentity* peer_id,
779 const struct GNUNET_ATS_Information * atsi)
781 struct RegexPeer *peer = cls;
782 char output_buffer[512];
789 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
790 "String matching timed out for string %s on peer %u (%i/%i)\n",
791 peer->search_str, peer->id, peers_found, num_search_strings);
793 printf ("String matching timed out for string %s on peer %u (%i/%i)\n",
794 peer->search_str, peer->id, peers_found, num_search_strings);
796 peer->search_str_matched = GNUNET_SYSERR;
800 prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time);
801 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
802 "String %s successfully matched on peer %u after %s (%i/%i)\n",
803 peer->search_str, peer->id, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
804 peers_found, num_search_strings);
806 printf ("String %s successfully matched on peer %u after %s (%i/%i)\n",
807 peer->search_str, peer->id, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
808 peers_found, num_search_strings);
811 peer->search_str_matched = GNUNET_YES;
813 if (NULL != data_file)
816 GNUNET_snprintf (output_buffer,
817 sizeof (output_buffer),
818 "Peer: %u (%p)\nHost: %s\nPolicy file: %s\nSearch string: %s\nSearch duration: %s\n\n",
821 GNUNET_TESTBED_host_get_hostname (peer->host_handle),
824 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
826 if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
827 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
830 if (NULL == peer->stats_handle)
832 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
833 "Cannot get statistics for peer %u, stats handle is NULL!\n");
837 if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, "mesh", NULL,
838 GNUNET_TIME_UNIT_FOREVER_REL,
840 &stats_iterator, peer))
842 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
843 "Could not get mesh statistics of peer %u!\n", peer->id);
845 if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, "transport", NULL,
846 GNUNET_TIME_UNIT_FOREVER_REL,
848 &stats_iterator, peer))
850 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
851 "Could not get transport statistics of peer %u!\n", peer->id);
853 if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, "dht", NULL,
854 GNUNET_TIME_UNIT_FOREVER_REL,
856 &stats_iterator, peer))
858 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
859 "Could not get dht statistics of peer %u!\n", peer->id);
863 if (peers_found == num_search_strings)
865 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
866 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
867 "All strings successfully matched in %s\n",
868 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
869 printf ("All strings successfully matched. Shutting down.\n");
872 if (GNUNET_SCHEDULER_NO_TASK != search_timeout_task)
873 GNUNET_SCHEDULER_cancel (search_timeout_task);
879 * Connect by string timeout task
882 * @param tc the task context
885 do_connect_by_string_timeout (void *cls,
886 const struct GNUNET_SCHEDULER_TaskContext * tc)
888 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
889 "Finding matches to all strings did not succeed after %s.\n",
890 GNUNET_STRINGS_relative_time_to_string (search_timeout, GNUNET_NO));
891 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
892 "Found %i of %i strings\n", peers_found, num_search_strings);
894 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
899 * Connect by string task that is run to search for a string in the NFA
902 * @param tc the task context
905 do_connect_by_string (void *cls,
906 const struct GNUNET_SCHEDULER_TaskContext * tc)
908 unsigned int search_cnt;
909 struct RegexPeer *peer;
911 printf ("Starting string search.\n");
914 for (search_cnt = 0; search_cnt < num_search_strings; search_cnt++)
916 peer = &peers[search_cnt % num_peers];
917 peer->search_str = search_strings[search_cnt];
918 peer->search_str_matched = GNUNET_NO;
920 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
921 "Searching for string \"%s\" on peer %d with file %s\n",
922 peer->search_str, (search_cnt % num_peers), peer->policy_file);
924 /* First connect to mesh service, then connect to stats service
925 and then try connecting by string in stats_connect_cb */
926 peer->mesh_op_handle =
927 GNUNET_TESTBED_service_connect (NULL,
937 search_timeout_task = GNUNET_SCHEDULER_add_delayed (search_timeout,
938 &do_connect_by_string_timeout, NULL);
943 * Delayed operation done for mesh service disconnects.
946 * @param tc the task context
949 do_mesh_op_done (void *cls,
950 const struct GNUNET_SCHEDULER_TaskContext * tc)
952 struct RegexPeer *peer = cls;
953 static unsigned int peer_cnt;
954 GNUNET_TESTBED_operation_done (peer->mesh_op_handle);
955 peer->mesh_op_handle = NULL;
957 if (++peer_cnt < num_peers)
959 peers[peer_cnt].mesh_op_handle =
960 GNUNET_TESTBED_service_connect (NULL,
961 peers[peer_cnt].peer_handle,
973 * Mesh connect callback.
975 * @param cls internal peer id.
976 * @param op operation handle.
977 * @param ca_result connect adapter result.
978 * @param emsg error message.
981 mesh_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
982 void *ca_result, const char *emsg)
984 struct RegexPeer *peer = (struct RegexPeer *) cls;
991 if (NULL != emsg || NULL == op || NULL == ca_result)
993 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Mesh connect failed: %s\n", emsg);
997 GNUNET_assert (peer->mesh_handle != NULL);
998 GNUNET_assert (peer->mesh_op_handle == op);
999 GNUNET_assert (peer->mesh_handle == ca_result);
1000 GNUNET_assert (NULL != peer->policy_file);
1004 case STATE_ANNOUNCE_REGEX:
1006 static unsigned int num_files_announced;
1008 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1009 "Announcing regexes for peer %u with file %s\n",
1010 peer->id, peer->policy_file);
1012 if (GNUNET_YES != GNUNET_DISK_file_test (peer->policy_file))
1014 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1015 "Could not find policy file %s\n", peer->policy_file);
1018 if (GNUNET_OK != GNUNET_DISK_file_size (peer->policy_file, &filesize, GNUNET_YES, GNUNET_YES))
1022 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Policy file %s is empty.\n", peer->policy_file);
1025 data = GNUNET_malloc (filesize);
1026 if (filesize != GNUNET_DISK_fn_read (peer->policy_file, data, filesize))
1029 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not read policy file %s.\n",
1036 while (offset < (filesize - 1))
1039 if (((data[offset] == '\n')) && (buf != &data[offset]))
1041 data[offset] = '\0';
1043 GNUNET_assert (NULL != regex);
1044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Announcing regex: %s on peer %u \n",
1046 GNUNET_MESH_announce_regex (peer->mesh_handle, regex, max_path_compression);
1047 buf = &data[offset + 1];
1049 else if ((data[offset] == '\n') || (data[offset] == '\0'))
1050 buf = &data[offset + 1];
1054 GNUNET_SCHEDULER_add_delayed (mesh_done_delay, &do_mesh_op_done, peer);
1056 if (++num_files_announced == num_peers)
1058 state = STATE_SEARCH_REGEX;
1060 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
1062 printf ("All files announced in %s.\n",
1063 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
1064 printf ("Waiting %s before starting to search.\n",
1065 GNUNET_STRINGS_relative_time_to_string (search_delay, GNUNET_YES));
1068 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1069 "All regexes announced in %s. Waiting %s before starting to search.\n",
1070 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
1071 GNUNET_STRINGS_relative_time_to_string (search_delay, GNUNET_NO));
1073 search_task = GNUNET_SCHEDULER_add_delayed (search_delay,
1074 &do_connect_by_string, NULL);
1078 case STATE_SEARCH_REGEX:
1080 /* First connect to the stats service, then start to search */
1081 peer->stats_op_handle =
1082 GNUNET_TESTBED_service_connect (NULL,
1099 * Mesh connect adapter.
1101 * @param cls not used.
1102 * @param cfg configuration handle.
1107 mesh_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
1109 GNUNET_MESH_ApplicationType app;
1110 struct RegexPeer *peer = cls;
1112 static struct GNUNET_MESH_MessageHandler handlers[] = {
1116 app = (GNUNET_MESH_ApplicationType)0;
1119 GNUNET_MESH_connect (cfg, cls, NULL, NULL, handlers, &app);
1121 return peer->mesh_handle;
1126 * Adapter function called to destroy a connection to
1129 * @param cls closure
1130 * @param op_result service handle returned from the connect adapter
1133 mesh_da (void *cls, void *op_result)
1135 struct RegexPeer *peer = (struct RegexPeer *) cls;
1137 GNUNET_assert (peer->mesh_handle == op_result);
1139 if (NULL != peer->mesh_tunnel_handle)
1141 GNUNET_MESH_tunnel_destroy (peer->mesh_tunnel_handle);
1142 peer->mesh_tunnel_handle = NULL;
1145 if (NULL != peer->mesh_handle)
1147 GNUNET_MESH_disconnect (peer->mesh_handle);
1148 peer->mesh_handle = NULL;
1153 /******************************************************************************/
1154 /*************************** TESTBED PEER SETUP *****************************/
1155 /******************************************************************************/
1159 * Configure the peer overlay topology.
1162 * @param tc the task context
1165 do_configure_topology (void *cls,
1166 const struct GNUNET_SCHEDULER_TaskContext * tc)
1169 if (0 == linking_factor)
1171 num_links = linking_factor * num_peers;
1173 /* num_links = num_peers - 1; */
1174 num_links = linking_factor;
1176 /* Do overlay connect */
1177 prof_start_time = GNUNET_TIME_absolute_get ();
1179 GNUNET_TESTBED_overlay_configure_topology (NULL, num_peers, peer_handles,
1180 GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI,
1182 GNUNET_TESTBED_TOPOLOGY_DISABLE_AUTO_RETRY,
1183 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1184 if (NULL == topology_op)
1186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1187 "Cannot create topology, op handle was NULL\n");
1194 * Functions of this signature are called when a peer has been successfully
1195 * started or stopped.
1197 * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
1198 * @param emsg NULL on success; otherwise an error description
1201 peer_churn_cb (void *cls, const char *emsg)
1203 struct DLLOperation *dll_op = cls;
1204 struct GNUNET_TESTBED_Operation *op;
1205 static unsigned int started_peers;
1206 unsigned int peer_cnt;
1209 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
1210 GNUNET_free (dll_op);
1213 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1214 _("An operation has failed while starting peers\n"));
1215 GNUNET_TESTBED_operation_done (op);
1216 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
1217 GNUNET_SCHEDULER_cancel (abort_task);
1218 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
1221 GNUNET_TESTBED_operation_done (op);
1222 if (++started_peers == num_peers)
1224 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
1225 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1226 "All peers started successfully in %s\n",
1227 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
1230 peer_handles = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * num_peers);
1231 for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
1232 peer_handles[peer_cnt] = peers[peer_cnt].peer_handle;
1234 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1235 "Waiting %s before starting to link peers\n",
1236 GNUNET_STRINGS_relative_time_to_string (conf_topo_delay, GNUNET_YES));
1238 printf ("Waiting %s before starting to link peers\n",
1239 GNUNET_STRINGS_relative_time_to_string (conf_topo_delay, GNUNET_YES));
1242 state = STATE_PEERS_LINKING;
1243 GNUNET_SCHEDULER_add_delayed (conf_topo_delay, &do_configure_topology, NULL);
1249 * Functions of this signature are called when a peer has been successfully
1252 * @param cls the closure from GNUNET_TESTBED_peer_create()
1253 * @param peer the handle for the created peer; NULL on any error during
1255 * @param emsg NULL if peer is not NULL; else MAY contain the error description
1258 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
1260 struct DLLOperation *dll_op = cls;
1261 struct RegexPeer *peer_ptr;
1262 static unsigned int created_peers;
1263 unsigned int peer_cnt;
1267 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1268 _("Creating a peer failed. Error: %s\n"), emsg);
1269 GNUNET_TESTBED_operation_done (dll_op->op);
1270 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
1271 GNUNET_free (dll_op);
1272 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
1273 GNUNET_SCHEDULER_cancel (abort_task);
1274 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
1278 peer_ptr = dll_op->cls;
1279 GNUNET_assert (NULL == peer_ptr->peer_handle);
1280 peer_ptr->peer_handle = peer;
1281 GNUNET_TESTBED_operation_done (dll_op->op);
1282 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
1283 GNUNET_free (dll_op);
1285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %i created on host %s\n",
1287 GNUNET_TESTBED_host_get_hostname (peer_ptr->host_handle));
1289 if (++created_peers == num_peers)
1291 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
1292 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1293 "All peers created successfully in %s\n",
1294 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
1295 /* Now peers are to be started */
1296 state = STATE_PEERS_STARTING;
1297 prof_start_time = GNUNET_TIME_absolute_get ();
1298 for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
1300 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
1301 dll_op->op = GNUNET_TESTBED_peer_start (dll_op, peers[peer_cnt].peer_handle,
1302 &peer_churn_cb, dll_op);
1303 GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
1310 * Function called with a filename.
1312 * @param cls closure
1313 * @param filename complete filename (absolute path)
1314 * @return GNUNET_OK to continue to iterate,
1315 * GNUNET_SYSERR to abort iteration with error!
1318 policy_filename_cb (void *cls, const char *filename)
1320 static unsigned int peer_cnt;
1321 struct DLLOperation *dll_op;
1322 struct RegexPeer *peer = &peers[peer_cnt];
1324 GNUNET_assert (NULL != peer);
1326 peer->policy_file = GNUNET_strdup (filename);
1328 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Creating peer %i on host %s for policy file %s\n",
1330 GNUNET_TESTBED_host_get_hostname (peer->host_handle),
1333 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
1334 dll_op->cls = &peers[peer_cnt];
1335 dll_op->op = GNUNET_TESTBED_peer_create (mc,
1340 GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
1348 * Controller event callback.
1351 * @param event the controller event
1354 controller_event_cb (void *cls,
1355 const struct GNUNET_TESTBED_EventInformation *event)
1357 struct DLLOperation *dll_op;
1358 struct GNUNET_TESTBED_Operation *op;
1363 case STATE_SLAVES_STARTING:
1364 switch (event->type)
1366 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
1368 static unsigned int slaves_started;
1369 unsigned int peer_cnt;
1371 dll_op = event->details.operation_finished.op_cls;
1372 GNUNET_CONTAINER_DLL_remove (dll_op_head, dll_op_tail, dll_op);
1373 GNUNET_free (dll_op);
1374 op = event->details.operation_finished.operation;
1375 if (NULL != event->details.operation_finished.emsg)
1377 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1378 _("An operation has failed while starting slaves\n"));
1379 GNUNET_TESTBED_operation_done (op);
1380 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
1381 GNUNET_SCHEDULER_cancel (abort_task);
1382 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
1385 GNUNET_TESTBED_operation_done (op);
1386 /* Proceed to start peers */
1387 if (++slaves_started == num_hosts - 1)
1389 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1390 "All slaves started successfully\n");
1392 state = STATE_PEERS_CREATING;
1393 prof_start_time = GNUNET_TIME_absolute_get ();
1395 if (-1 == (ret = GNUNET_DISK_directory_scan (policy_dir,
1399 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1400 _("No files found in `%s'\n"),
1402 GNUNET_SCHEDULER_shutdown ();
1405 num_peers = (unsigned int) ret;
1406 peers = GNUNET_malloc (sizeof (struct RegexPeer) * num_peers);
1408 /* Initialize peers */
1409 for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
1411 struct RegexPeer *peer = &peers[peer_cnt];
1412 peer->id = peer_cnt;
1413 peer->policy_file = NULL;
1414 /* Do not start peers on hosts[0] (master controller) */
1415 peer->host_handle = hosts[1 + (peer_cnt % (num_hosts -1))];
1416 peer->mesh_handle = NULL;
1417 peer->mesh_tunnel_handle = NULL;
1418 peer->stats_handle = NULL;
1419 peer->stats_op_handle = NULL;
1420 peer->search_str = NULL;
1421 peer->search_str_matched = GNUNET_NO;
1424 GNUNET_DISK_directory_scan (policy_dir,
1425 &policy_filename_cb,
1434 case STATE_PEERS_STARTING:
1435 switch (event->type)
1437 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
1438 /* Control reaches here when peer start fails */
1439 case GNUNET_TESTBED_ET_PEER_START:
1440 /* we handle peer starts in peer_churn_cb */
1446 case STATE_PEERS_LINKING:
1447 switch (event->type)
1449 static unsigned int established_links;
1450 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
1451 /* Control reaches here when a peer linking operation fails */
1452 if (NULL != event->details.operation_finished.emsg)
1454 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1455 _("An operation has failed while linking\n"));
1460 /* We do no retries, consider this link as established */
1462 case GNUNET_TESTBED_ET_CONNECT:
1464 char output_buffer[512];
1467 if (0 == established_links)
1468 printf ("Establishing links .");
1474 if (++established_links == num_links)
1477 prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
1478 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1479 "%u links established in %s\n",
1481 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
1483 GNUNET_free (peer_handles);
1485 if (NULL != data_file)
1488 GNUNET_snprintf (output_buffer,
1489 sizeof (output_buffer),
1490 "# of peers: %u\n# of links established: %u\n"
1491 "Time to establish links: %s\nLinking failures: %u\n"
1492 "path compression length: %u\n# of search strings: %u\n",
1494 (established_links - cont_fails),
1495 GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
1497 max_path_compression,
1498 num_search_strings);
1500 if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
1501 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
1504 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1505 "Connecting to mesh service and start announcing regex...\n");
1506 printf ("\nStarting to connect to mesh services and announce regex\n");
1509 prof_start_time = GNUNET_TIME_absolute_get ();
1510 peers[0].mesh_op_handle =
1511 GNUNET_TESTBED_service_connect (NULL,
1512 peers[0].peer_handle,
1519 state = STATE_ANNOUNCE_REGEX;
1527 case STATE_ANNOUNCE_REGEX:
1529 /* Handled in service connect callback */
1532 case STATE_SEARCH_REGEX:
1534 /* Handled in service connect callback */
1540 case STATE_PEERS_CREATING:
1541 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create peer\n");
1544 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1545 "Unexpected controller_cb with state %i!\n", state);
1553 * Task to register all hosts available in the global host list
1556 * @param tc the scheduler task context
1559 register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1563 * Callback which will be called to after a host registration succeeded or failed
1565 * @param cls the closure
1566 * @param emsg the error message; NULL if host registration is successful
1569 host_registration_completion (void *cls, const char *emsg)
1574 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1575 _("Host registration failed for a host. Error: %s\n"), emsg);
1576 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
1577 GNUNET_SCHEDULER_cancel (abort_task);
1578 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
1581 register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, NULL);
1586 * Task to register all hosts available in the global host list
1589 * @param tc the scheduler task context
1592 register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1594 struct DLLOperation *dll_op;
1595 static unsigned int reg_host;
1598 register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
1599 if (reg_host == num_hosts - 1)
1601 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1602 "All hosts successfully registered\n");
1604 state = STATE_SLAVES_STARTING;
1605 for (slave = 1; slave < num_hosts; slave++)
1607 dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
1608 dll_op->op = GNUNET_TESTBED_controller_link (dll_op,
1614 GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
1618 reg_handle = GNUNET_TESTBED_register_host (mc, hosts[++reg_host],
1619 host_registration_completion,
1625 * Callback to signal successfull startup of the controller process
1627 * @param cls the closure from GNUNET_TESTBED_controller_start()
1628 * @param config the configuration with which the controller has been started;
1629 * NULL if status is not GNUNET_OK
1630 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
1631 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1634 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int status)
1636 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
1637 GNUNET_SCHEDULER_cancel (abort_task);
1638 if (GNUNET_OK != status)
1641 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
1645 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
1646 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
1647 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1648 event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT);
1649 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1650 mc = GNUNET_TESTBED_controller_connect (config, hosts[0], event_mask,
1651 &controller_event_cb, NULL);
1654 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1655 _("Unable to connect to master controller -- Check config\n"));
1656 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
1659 register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, NULL);
1660 abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1666 * Load search strings from given filename. One search string per line.
1668 * @param filename filename of the file containing the search strings.
1669 * @param strings set of strings loaded from file. Caller needs to free this
1670 * if number returned is greater than zero.
1671 * @param limit upper limit on the number of strings read from the file
1672 * @return number of strings found in the file. GNUNET_SYSERR on error.
1675 load_search_strings (const char *filename, char ***strings, unsigned int limit)
1680 unsigned int offset;
1684 if (NULL == filename)
1686 return GNUNET_SYSERR;
1689 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1691 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1692 "Could not find search strings file %s\n", filename);
1693 return GNUNET_SYSERR;
1695 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &filesize, GNUNET_YES, GNUNET_YES))
1699 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Search strings file %s is empty.\n", filename);
1700 return GNUNET_SYSERR;
1702 data = GNUNET_malloc (filesize);
1703 if (filesize != GNUNET_DISK_fn_read (filename, data, filesize))
1706 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not read search strings file %s.\n",
1708 return GNUNET_SYSERR;
1713 while (offset < (filesize - 1) && str_cnt < limit)
1716 if (((data[offset] == '\n')) && (buf != &data[offset]))
1718 data[offset] = '\0';
1720 buf = &data[offset + 1];
1722 else if ((data[offset] == '\n') || (data[offset] == '\0'))
1723 buf = &data[offset + 1];
1725 *strings = GNUNET_malloc (sizeof (char *) * str_cnt);
1727 for (i = 0; i < str_cnt; i++)
1729 (*strings)[i] = GNUNET_strdup (&data[offset]);
1730 offset += strlen ((*strings)[i]) + 1;
1738 * Main function that will be run by the scheduler.
1740 * @param cls closure
1741 * @param args remaining command-line arguments
1742 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1743 * @param config configuration
1746 run (void *cls, char *const *args, const char *cfgfile,
1747 const struct GNUNET_CONFIGURATION_Handle *config)
1750 unsigned int nsearchstrs;
1752 if (NULL == args[0])
1754 fprintf (stderr, _("No hosts-file specified on command line. Exiting.\n"));
1757 if (NULL == args[1])
1759 fprintf (stderr, _("No policy directory specified on command line. Exiting.\n"));
1762 num_hosts = GNUNET_TESTBED_hosts_load_from_file (args[0], &hosts);
1765 fprintf (stderr, _("No hosts loaded. Need at least one host\n"));
1768 for (nhost = 0; nhost < num_hosts; nhost++)
1770 if (GNUNET_YES != GNUNET_TESTBED_is_host_habitable (hosts[nhost], config))
1772 fprintf (stderr, _("Host %s cannot start testbed\n"),
1773 GNUNET_TESTBED_host_get_hostname (hosts[nhost]));
1777 if (num_hosts != nhost)
1779 fprintf (stderr, _("Exiting\n"));
1780 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1785 fprintf (stderr, _("No configuration file given. Exiting\n"));
1786 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1789 if ( (NULL != data_filename) &&
1790 (NULL == (data_file =
1791 GNUNET_DISK_file_open (data_filename,
1792 GNUNET_DISK_OPEN_READWRITE |
1793 GNUNET_DISK_OPEN_TRUNCATE |
1794 GNUNET_DISK_OPEN_CREATE,
1795 GNUNET_DISK_PERM_USER_READ |
1796 GNUNET_DISK_PERM_USER_WRITE))) )
1797 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1800 if (GNUNET_YES != GNUNET_DISK_directory_test (args[1]))
1802 fprintf (stderr, _("Specified policies directory does not exist. Exiting.\n"));
1803 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1806 policy_dir = args[1];
1807 if (GNUNET_YES != GNUNET_DISK_file_test (args[2]))
1809 fprintf (stderr, _("No search strings file given. Exiting.\n"));
1810 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1813 nsearchstrs = load_search_strings (args[2], &search_strings, num_search_strings);
1814 if (num_search_strings != nsearchstrs)
1816 num_search_strings = nsearchstrs;
1817 fprintf (stderr, _("Error loading search strings. Given file does not contain enough strings. Exiting.\n"));
1818 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1821 if (0 >= num_search_strings || NULL == search_strings)
1823 fprintf (stderr, _("Error loading search strings. Exiting.\n"));
1824 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1828 for (i = 0; i < num_search_strings; i++)
1829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "search string: %s\n", search_strings[i]);
1830 cfg = GNUNET_CONFIGURATION_dup (config);
1832 GNUNET_TESTBED_controller_start (GNUNET_TESTBED_host_get_hostname
1839 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1840 (GNUNET_TIME_UNIT_SECONDS, 5), &do_abort,
1848 * @param argc argument count
1849 * @param argv argument values
1850 * @return 0 on success
1853 main (int argc, char *const *argv)
1855 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1856 {'d', "details", "FILENAME",
1857 gettext_noop ("name of the file for writing statistics"),
1858 1, &GNUNET_GETOPT_set_string, &data_filename},
1859 {'n', "num-links", "COUNT",
1860 gettext_noop ("create COUNT number of random links between peers"),
1861 GNUNET_YES, &GNUNET_GETOPT_set_uint, &linking_factor },
1862 {'t', "matching-timeout", "TIMEOUT",
1863 gettext_noop ("wait TIMEOUT before considering a string match as failed"),
1864 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &search_timeout },
1865 {'s', "search-delay", "DELAY",
1866 gettext_noop ("wait DELAY before starting string search"),
1867 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &search_delay },
1868 {'a', "num-search-strings", "COUNT",
1869 gettext_noop ("number of search strings to read from search strings file"),
1870 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_search_strings },
1871 {'p', "max-path-compression", "MAX_PATH_COMPRESSION",
1872 gettext_noop ("maximum path compression length"),
1873 1, &GNUNET_GETOPT_set_uint, &max_path_compression},
1874 GNUNET_GETOPT_OPTION_END
1878 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1881 result = GNUNET_SYSERR;
1883 GNUNET_PROGRAM_run (argc, argv, "gnunet-regex-profiler [OPTIONS] hosts-file policy-dir search-strings-file",
1884 _("Profiler for regex/mesh"),
1885 options, &run, NULL);
1886 GNUNET_free ((void*) argv);
1887 if (GNUNET_OK != ret)
1889 if (GNUNET_OK != result)