GNUnet  0.10.x
gnunet-regex-profiler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2011 - 2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
29 #include <string.h>
30 
31 #include "platform.h"
32 #include "gnunet_applications.h"
33 #include "gnunet_util_lib.h"
34 #include "regex_internal_lib.h"
35 #include "gnunet_arm_service.h"
36 #include "gnunet_dht_service.h"
37 #include "gnunet_testbed_service.h"
38 
39 #define FIND_TIMEOUT \
40  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90)
41 
46 {
51 
55  void *cls;
56 
60  struct DLLOperation *next;
61 
65  struct DLLOperation *prev;
66 };
67 
68 
72 enum State
73 {
78 
83 
88 
93 
98 
103 
109 };
110 
111 
115 struct RegexPeer
116 {
120  unsigned int id;
121 
126 
131 
135  const char *search_str;
136 
144 
149 
154 
159 
164 
169 
174 
179 };
180 
184 static int in_shutdown;
185 
189 static struct RegexPeer *peers;
190 
195 
200 
205 
210 
215 
220 
224 static uint64_t event_mask;
225 
230 
235 
239 static unsigned int num_peers;
240 
244 static int result;
245 
250 
254 static char * policy_dir;
255 
259 static char *hosts_file;
260 
264 static char *strings_file;
265 
269 static char **search_strings;
270 
274 static long long unsigned int init_parallel_searches;
275 
279 static unsigned int parallel_searches;
280 
284 static unsigned int strings_found;
285 
289 static unsigned int next_search;
290 
295 
299 static struct GNUNET_TIME_Relative search_timeout_time = { 60000 };
300 
305 
309 static char *data_filename;
310 
315 static char * regex_prefix;
316 
321 
322 
323 /******************************************************************************/
324 /****************************** DECLARATIONS ********************************/
325 /******************************************************************************/
326 
335 static void
337  void *ca_result, const char *emsg);
338 
347 static void *
348 dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg);
349 
350 
358 static void
359 dht_da (void *cls, void *op_result);
360 
361 
371 static void
372 stats_connect_cb (void *cls,
374  void *ca_result,
375  const char *emsg);
376 
377 
383 static void
384 announce_next_regex (void *cls);
385 
386 
387 /******************************************************************************/
388 /******************************** SHUTDOWN **********************************/
389 /******************************************************************************/
390 
391 
397 static void
399 {
400  struct RegexPeer *peer;
401  unsigned int peer_cnt;
402  unsigned int search_str_cnt;
403  char output_buffer[512];
404  size_t size;
405 
406  if (NULL != abort_task)
407  {
408  GNUNET_SCHEDULER_cancel (abort_task);
409  abort_task = NULL;
410  }
411  if (NULL != register_hosts_task)
412  {
413  GNUNET_SCHEDULER_cancel (register_hosts_task);
414  register_hosts_task = NULL;
415  }
416  for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
417  {
418  peer = &peers[peer_cnt];
419 
420  if (GNUNET_YES != peer->search_str_matched && NULL != data_file)
421  {
423  size =
424  GNUNET_snprintf (output_buffer,
425  sizeof (output_buffer),
426  "%p Search string not found: %s (%d)\n"
427  "%p On peer: %u (%p)\n"
428  "%p After: %s\n",
429  peer, peer->search_str, peer->search_str_matched,
430  peer, peer->id, peer,
431  peer,
433  GNUNET_NO));
434  if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
435  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
436  }
437 
438  if (NULL != peers[peer_cnt].op_handle)
439  GNUNET_TESTBED_operation_done (peers[peer_cnt].op_handle);
440  }
441 
442  if (NULL != data_file)
443  {
444  GNUNET_DISK_file_close (data_file);
445  data_file = NULL;
446  }
447  for (search_str_cnt = 0;
448  search_str_cnt < num_peers && NULL != search_strings;
449  search_str_cnt++)
450  {
451  GNUNET_free_non_null (search_strings[search_str_cnt]);
452  }
454  search_strings = NULL;
455 
456  if (NULL != reg_handle)
457  {
459  reg_handle = NULL;
460  }
461  if (NULL != mc)
462  {
464  mc = NULL;
465  }
466  if (NULL != mc_proc)
467  {
469  mc_proc = NULL;
470  }
471  if (NULL != cfg)
472  {
474  cfg = NULL;
475  }
476 }
477 
478 
484 static void
485 do_abort (void *cls)
486 {
487  unsigned long i = (unsigned long) cls;
488 
490  "Aborting from line %lu...\n", i);
491  abort_task = NULL;
494 }
495 
496 
497 /******************************************************************************/
498 /********************* STATISTICS SERVICE CONNECTIONS ***********************/
499 /******************************************************************************/
500 
511 static void *
512 stats_ca (void *cls,
513  const struct GNUNET_CONFIGURATION_Handle *cfg)
514 {
515  return GNUNET_STATISTICS_create ("<driver>", cfg);
516 }
517 
518 
526 static void
527 stats_da (void *cls, void *op_result)
528 {
529  struct RegexPeer *peer = cls;
530 
531  GNUNET_assert (op_result == peer->stats_handle);
532 
534  peer->stats_handle = NULL;
535 }
536 
537 
548 static int
550  const char *subsystem,
551  const char *name,
552  uint64_t value, int is_persistent)
553 {
554  struct RegexPeer *peer = cls;
555  char output_buffer[512];
556  size_t size;
557 
558  if (NULL == data_file)
559  {
561  "%p -> %s [%s]: %llu\n",
562  peer,
563  subsystem,
564  name,
565  (unsigned long long) value);
566  return GNUNET_OK;
567  }
568  size =
569  GNUNET_snprintf (output_buffer,
570  sizeof (output_buffer),
571  "%p [%s] %llu %s\n",
572  peer,
573  subsystem, value, name);
574  if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
576  "Unable to write to file!\n");
577 
578  return GNUNET_OK;
579 }
580 
581 
590 static void
591 stats_cb (void *cls,
592  int success)
593 {
594  static unsigned int peer_cnt;
595  struct RegexPeer *peer = cls;
596 
597  if (GNUNET_OK != success)
598  {
600  "Getting statistics for peer %u failed!\n",
601  peer->id);
602  return;
603  }
604 
605  GNUNET_assert (NULL != peer->op_handle);
606 
608  peer->op_handle = NULL;
609 
610  peer_cnt++;
611  peer = &peers[peer_cnt];
612 
613  fprintf (stderr, "s");
614  if (peer_cnt == num_peers)
615  {
617  "\nCollecting stats finished. Shutting down.\n");
619  result = GNUNET_OK;
620  }
621  else
622  {
623  peer->op_handle =
625  peer->peer_handle,
626  "statistics",
628  peer,
629  &stats_ca,
630  &stats_da,
631  peer);
632  }
633 }
634 
635 
645 static void
648  void *ca_result,
649  const char *emsg)
650 {
651  struct RegexPeer *peer = cls;
652 
653  if (NULL == ca_result || NULL != emsg)
654  {
656  "Failed to connect to statistics service on peer %u: %s\n",
657  peer->id, emsg);
658 
659  peer->stats_handle = NULL;
660  return;
661  }
662 
663  peer->stats_handle = ca_result;
664 
665  if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, NULL, NULL,
666  &stats_cb,
667  &stats_iterator, peer))
668  {
670  "Could not get statistics of peer %u!\n", peer->id);
671  }
672 }
673 
674 
681 static void
683 {
684  struct RegexPeer *peer = &peers[0];
685 
686  GNUNET_assert (NULL != peer->peer_handle);
687 
688  peer->op_handle =
690  peer->peer_handle,
691  "statistics",
693  peer,
694  &stats_ca,
695  &stats_da,
696  peer);
697 }
698 
699 
700 /******************************************************************************/
701 /************************ REGEX FIND CONNECTIONS **************************/
702 /******************************************************************************/
703 
704 
710 static void
711 find_string (void *cls);
712 
713 
725 static void
727  const struct GNUNET_PeerIdentity *id,
728  const struct GNUNET_PeerIdentity *get_path,
729  unsigned int get_path_length,
730  const struct GNUNET_PeerIdentity *put_path,
731  unsigned int put_path_length)
732 {
733  struct RegexPeer *peer = cls;
734  char output_buffer[512];
735  size_t size;
736 
737  if (GNUNET_YES == peer->search_str_matched)
738  {
740  "String %s on peer %u already matched!\n",
741  peer->search_str, peer->id);
742  return;
743  }
744 
745  strings_found++;
747 
748  if (NULL != peer->timeout)
749  {
751  peer->timeout = NULL;
752  if (GNUNET_NO == in_shutdown)
754  }
755 
756  if (NULL == id)
757  {
758  // FIXME not possible right now
760  "String matching timed out for string %s on peer %u (%i/%i)\n",
761  peer->search_str, peer->id, strings_found, num_peers);
763  }
764  else
765  {
767 
769  "String %s found on peer %u after %s (%i/%i) (%u||)\n",
770  peer->search_str, peer->id,
773 
775 
776  if (NULL != data_file)
777  {
778  size =
779  GNUNET_snprintf (output_buffer,
780  sizeof (output_buffer),
781  "%p Peer: %u\n"
782  "%p Search string: %s\n"
783  "%p Search duration: %s\n\n",
784  peer, peer->id,
785  peer, peer->search_str,
786  peer,
788  GNUNET_NO));
789 
790  if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
791  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
792  }
793  }
794 
796  peer->op_handle = NULL;
797 
798  if (strings_found == num_peers)
799  {
802  "All strings successfully matched in %s\n",
804 
805  if (NULL != search_timeout_task)
806  {
807  GNUNET_SCHEDULER_cancel (search_timeout_task);
808  search_timeout_task = NULL;
809  }
810 
811  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Collecting stats.\n");
813  }
814 }
815 
816 
823 static void
825 {
826  unsigned int i;
827 
829  "Finding matches to all strings did not succeed after %s.\n",
830  GNUNET_STRINGS_relative_time_to_string (search_timeout_time,
831  GNUNET_NO));
833  "Found %i of %i strings\n", strings_found, num_peers);
834 
836  "Search timed out after %s."
837  "Collecting stats and shutting down.\n",
838  GNUNET_STRINGS_relative_time_to_string (search_timeout_time,
839  GNUNET_NO));
840 
842  for (i = 0; i < num_peers; i++)
843  {
844  if (NULL != peers[i].op_handle)
845  {
846  GNUNET_TESTBED_operation_done (peers[i].op_handle);
847  peers[i].op_handle = NULL;
848  }
849  }
851 }
852 
853 
860 static void
862 {
863  struct RegexPeer *p = cls;
864 
865  p->timeout = NULL;
867  "Searching for string \"%s\" on peer %d timed out.\n",
868  p->search_str,
869  p->id);
870  if (GNUNET_NO == in_shutdown)
872 }
873 
874 
880 static void
882 {
883  unsigned int search_peer = (unsigned int) (long) cls;
884 
885  if ( (search_peer >= num_peers) ||
886  (GNUNET_YES == in_shutdown) )
887  return;
888 
890  "Searching for string \"%s\" on peer %d (%u||)\n",
891  peers[search_peer].search_str,
892  search_peer,
894 
895  peers[search_peer].op_handle =
897  peers[search_peer].peer_handle,
898  "dht",
900  &peers[search_peer],
901  &dht_ca,
902  &dht_da,
903  &peers[search_peer]);
904  GNUNET_assert (NULL != peers[search_peer].op_handle);
905  peers[search_peer].timeout
908  &peers[search_peer]);
909 }
910 
911 
919 static void
922  const char *emsg)
923 {
924  struct RegexPeer *peer = (struct RegexPeer *) cls;
925  unsigned long search_peer;
926  unsigned int i;
927 
929  peer->daemon_op = NULL;
930  if (NULL != emsg)
931  {
933  "Failed to start/stop daemon at peer %u: %s\n", peer->id, emsg);
934  GNUNET_assert (0);
935  }
936  else
937  {
939  "Deamon %u started successfully\n", peer->id);
940  }
941 
942  /* Find a peer to look for a string matching the regex announced */
944  num_peers);
945  for (i = 0; peers[search_peer].search_str != NULL; i++)
946  {
947  search_peer = (search_peer + 1) % num_peers;
948  if (i > num_peers)
949  GNUNET_assert (0); /* we ran out of peers, must be a bug */
950  }
951  peers[search_peer].search_str = search_strings[peer->id];
952  peers[search_peer].search_str_matched = GNUNET_NO;
955  2),
956  &find_string,
957  (void *) search_peer);
958 }
959 
960 
968 static void
970 {
971  unsigned int i;
972 
973  if (GNUNET_YES == in_shutdown)
974  return;
976  "Starting announce.\n");
977  for (i = 0; i < init_parallel_searches; i++)
978  {
980  " scheduling announce %u\n",
981  i);
983  }
984 }
985 
986 
992 static void
994 {
995  struct RegexPeer *peer;
996 
997  if (GNUNET_YES == in_shutdown)
998  return;
999  if (next_search >= num_peers)
1000  {
1001  if (strings_found != num_peers)
1002  {
1003  struct GNUNET_TIME_Relative new_delay;
1004  if (NULL != search_timeout_task)
1005  GNUNET_SCHEDULER_cancel (search_timeout_task);
1007  search_timeout_task = GNUNET_SCHEDULER_add_delayed (new_delay,
1009  NULL);
1010  }
1011  return;
1012  }
1013 
1014  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting daemon %u\n", next_search);
1015  peer = &peers[next_search];
1016  peer->daemon_op =
1018  peer->peer_handle,
1019  "regexprofiler",
1020  &daemon_started,
1021  peer,
1022  1);
1023  next_search++;
1025 }
1026 
1027 
1038 static void
1040  struct GNUNET_TESTBED_Operation *op,
1041  void *ca_result,
1042  const char *emsg)
1043 {
1044  struct RegexPeer *peer = (struct RegexPeer *) cls;
1045 
1046  if (NULL != emsg || NULL == op || NULL == ca_result)
1047  {
1048  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "DHT connect failed: %s\n", emsg);
1049  GNUNET_assert (0);
1050  }
1051 
1052  GNUNET_assert (NULL != peer->dht_handle);
1053  GNUNET_assert (peer->op_handle == op);
1054  GNUNET_assert (peer->dht_handle == ca_result);
1055 
1056  peer->search_str_matched = GNUNET_NO;
1058  peer->search_str,
1059  &regex_found_handler, peer,
1060  NULL);
1062 }
1063 
1064 
1073 static void *
1074 dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
1075 {
1076  struct RegexPeer *peer = cls;
1077 
1078  peer->dht_handle = GNUNET_DHT_connect (cfg, 32);
1079 
1080  return peer->dht_handle;
1081 }
1082 
1083 
1090 static void
1091 dht_da (void *cls, void *op_result)
1092 {
1093  struct RegexPeer *peer = (struct RegexPeer *) cls;
1094 
1095  GNUNET_assert (peer->dht_handle == op_result);
1096 
1097  if (NULL != peer->search_handle)
1098  {
1100  peer->search_handle = NULL;
1101  }
1102 
1103  if (NULL != peer->dht_handle)
1104  {
1106  peer->dht_handle = NULL;
1107  }
1108 }
1109 
1110 
1124 static void
1126  struct GNUNET_TESTBED_RunHandle *h,
1127  unsigned int num_peers_,
1129  unsigned int links_succeeded,
1130  unsigned int links_failed)
1131 {
1132  unsigned int i;
1133 
1134  GNUNET_assert (num_peers_ == num_peers);
1135 
1138  "Testbed started in %s\n",
1140 
1141  if (NULL != abort_task)
1142  {
1143  GNUNET_SCHEDULER_cancel (abort_task);
1144  abort_task = NULL;
1145  }
1146 
1147  for (i = 0; i < num_peers; i++)
1148  {
1149  peers[i].peer_handle = testbed_peers[i];
1150  }
1151  if (GNUNET_NO ==
1152  GNUNET_CONFIGURATION_get_value_yesno (cfg, "DHT", "DISABLE_TRY_CONNECT"))
1153  {
1154  struct GNUNET_TIME_Relative settle_time;
1155 
1156  settle_time =
1158  10 * num_peers);
1160  "Waiting for DHT for %s to settle new connections.\n\n",
1162  GNUNET_SCHEDULER_add_delayed (settle_time, &do_announce, NULL);
1163  }
1164  else
1165  {
1167  }
1168  search_timeout_task =
1169  GNUNET_SCHEDULER_add_delayed (search_timeout_time, &search_timed_out, NULL);
1170 }
1171 
1178 static void
1180  const struct GNUNET_TESTBED_EventInformation *event)
1181 {
1182  switch (event->type)
1183  {
1185  printf(".");
1186  break;
1188  printf("#");
1189  break;
1190  default:
1191  break;
1192  }
1193  fflush(stdout);
1194 }
1195 
1196 
1197 /******************************************************************************/
1198 /*************************** TESTBED PEER SETUP *****************************/
1199 /******************************************************************************/
1200 
1211 static int
1213  uint64_t data_size,
1214  unsigned int str_max)
1215 {
1216  char *buf; // Keep track of last string to skip blank lines
1217  unsigned int offset;
1218  unsigned int str_cnt;
1219 
1220  buf = data;
1221  offset = 0;
1222  str_cnt = 0;
1223  while ( (offset < (data_size - 1)) && (str_cnt < str_max) )
1224  {
1225  offset++;
1226  if ( ((data[offset] == '\n')) &&
1227  (buf != &data[offset]) )
1228  {
1229  data[offset] = '\0';
1230  str_cnt++;
1231  buf = &data[offset + 1];
1232  }
1233  else if ( (data[offset] == '\n') ||
1234  (data[offset] == '\0') )
1235  buf = &data[offset + 1];
1236  }
1237  return str_cnt;
1238 }
1239 
1240 
1254 static int
1256  char ***strings, unsigned int str_cnt)
1257 {
1258  uint64_t offset;
1259  uint64_t len;
1260  unsigned int i;
1261 
1262  *strings = GNUNET_malloc (sizeof (char *) * str_cnt);
1263  offset = 0;
1264  for (i = 0; i < str_cnt; i++)
1265  {
1266  len = strlen (&data[offset]);
1267  if (offset + len >= data_size)
1268  {
1269  GNUNET_free (*strings);
1270  *strings = NULL;
1271  return GNUNET_SYSERR;
1272  }
1273  if (0 == len) // empty line
1274  {
1275  offset++;
1276  i--;
1277  continue;
1278  }
1279 
1280  GNUNET_asprintf (&(*strings)[i],
1281  "%s%s",
1282  regex_prefix,
1283  &data[offset]);
1284  offset += len + 1;
1285  }
1286  return GNUNET_OK;
1287 }
1288 
1289 
1299 static int
1301  char ***strings,
1302  unsigned int limit)
1303 {
1304  char *data;
1305  uint64_t filesize;
1306  int str_cnt;
1307 
1308  /* Sanity checks */
1309  if (NULL == filename)
1310  {
1311  return GNUNET_SYSERR;
1312  }
1313  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1314  {
1316  "Could not find search strings file %s\n", filename);
1317  return GNUNET_SYSERR;
1318  }
1319  if (GNUNET_OK !=
1320  GNUNET_DISK_file_size (filename,
1321  &filesize,
1322  GNUNET_YES,
1323  GNUNET_YES))
1324  {
1326  "Search strings file %s cannot be read.\n",
1327  filename);
1328  return GNUNET_SYSERR;
1329  }
1330  if (0 == filesize)
1331  {
1333  "Search strings file %s is empty.\n",
1334  filename);
1335  return GNUNET_SYSERR;
1336  }
1337 
1338  /* Read data into memory */
1339  data = GNUNET_malloc (filesize + 1);
1340  if (filesize != GNUNET_DISK_fn_read (filename,
1341  data,
1342  filesize))
1343  {
1344  GNUNET_free (data);
1346  "Could not read search strings file %s.\n",
1347  filename);
1348  return GNUNET_SYSERR;
1349  }
1350 
1351  /* Process buffer and build array */
1352  str_cnt = count_and_separate_strings (data, filesize, limit);
1353  if (GNUNET_OK != create_string_array (data, filesize, strings, str_cnt))
1354  {
1355  str_cnt = GNUNET_SYSERR;
1356  }
1357  GNUNET_free (data);
1358  return str_cnt;
1359 }
1360 
1361 
1370 static void
1371 run (void *cls,
1372  char *const *args,
1373  const char *cfgfile,
1374  const struct GNUNET_CONFIGURATION_Handle *config)
1375 {
1376  unsigned int nsearchstrs;
1377  unsigned int i;
1378  struct GNUNET_TIME_Relative abort_time;
1379 
1381 
1382  /* Check config */
1383  if (NULL == config)
1384  {
1386  _("No configuration file given. Exiting\n"));
1388  return;
1389  }
1390  cfg = GNUNET_CONFIGURATION_dup (config);
1391  if (GNUNET_OK !=
1392  GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER",
1393  "REGEX_PREFIX",
1394  &regex_prefix))
1395  {
1397  "regexprofiler",
1398  "regex_prefix");
1400  return;
1401  }
1402  if (GNUNET_OK !=
1403  GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER",
1404  "PARALLEL_SEARCHES",
1406  {
1408  "Configuration option \"PARALLEL_SEARCHES\" missing."
1409  " Using default (%d)\n", 10);
1411  }
1412  if (GNUNET_OK !=
1413  GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER",
1414  "REANNOUNCE_PERIOD_MAX",
1416  {
1418  "reannounce_period_max not given. Using 10 minutes.\n");
1421  }
1422 
1423  /* Check arguments */
1424  if (NULL == policy_dir)
1425  {
1427  _("No policy directory specified on command line. Exiting.\n"));
1428  return;
1429  }
1431  {
1433  _("Specified policies directory does not exist. Exiting.\n"));
1435  return;
1436  }
1437  if (0 >= (int) (num_peers = GNUNET_DISK_directory_scan (policy_dir, NULL, NULL)))
1438  {
1440  _("No files found in `%s'\n"),
1441  policy_dir);
1442  return;
1443  }
1444  GNUNET_CONFIGURATION_set_value_string (cfg, "REGEXPROFILER",
1445  "POLICY_DIR", policy_dir);
1447  {
1449  _("No search strings file given. Exiting.\n"));
1451  return;
1452  }
1453  nsearchstrs = load_search_strings (strings_file,
1454  &search_strings,
1455  num_peers);
1456  if (num_peers != nsearchstrs)
1457  {
1459  "Error loading search strings.\n");
1461  "File (%s) does not contain enough strings (%u/%u).\n",
1462  strings_file, nsearchstrs, num_peers);
1464  return;
1465  }
1466  if ( (0 == num_peers) || (NULL == search_strings))
1467  {
1469  _("Error loading search strings. Exiting.\n"));
1471  return;
1472  }
1473  for (i = 0; i < num_peers; i++)
1475  "search string: %s\n",
1476  search_strings[i]);
1477 
1478  /* Check logfile */
1479  if ( (NULL != data_filename) &&
1480  (NULL == (data_file =
1487  {
1489  "open",
1490  data_filename);
1491  return;
1492  }
1493 
1494  /* Initialize peers */
1495  peers = GNUNET_malloc (sizeof (struct RegexPeer) * num_peers);
1496  for (i = 0; i < num_peers; i++)
1497  peers[i].id = i;
1498 
1500  "TESTBED", "OVERLAY_RANDOM_LINKS",
1501  num_peers * 20);
1503  "DHT", "FORCE_NSE",
1504  (long long unsigned)
1505  (log (num_peers) / log (2.0)));
1506  event_mask = 0LL;
1507 /* For feedback about the start process activate these and pass master_cb */
1509 // event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
1511 // event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT);
1514  cfg,
1515  num_peers,
1516  event_mask,
1518  NULL, /* master_controller_cb cls */
1519  &test_master,
1520  NULL); /* test_master cls */
1521  if (GNUNET_OK !=
1522  GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
1523  "SETUP_TIMEOUT",
1524  &abort_time))
1525  {
1527  "SETUP_TIMEOUT not given. Using 15 minutes.\n");
1528  abort_time =
1530  }
1531  abort_time = GNUNET_TIME_relative_add (abort_time, GNUNET_TIME_UNIT_MINUTES);
1532  abort_task =
1533  GNUNET_SCHEDULER_add_delayed (abort_time,
1534  &do_abort,
1535  (void*) __LINE__);
1537  "setup_timeout: %s\n",
1539 }
1540 
1541 
1549 int
1550 main (int argc, char *const *argv)
1551 {
1552  struct GNUNET_GETOPT_CommandLineOption options[] = {
1553 
1555  "output-file",
1556  "FILENAME",
1557  gettext_noop ("name of the file for writing statistics"),
1558  &data_filename),
1559 
1561  "matching-timeout",
1562  "TIMEOUT",
1563  gettext_noop ("wait TIMEOUT before ending the experiment"),
1564  &search_timeout_time),
1565 
1567  "policy-dir",
1568  "DIRECTORY",
1569  gettext_noop ("directory with policy files"),
1570  &policy_dir),
1571 
1572 
1574  "strings-file",
1575  "FILENAME",
1576  gettext_noop ("name of file with input strings"),
1577  &strings_file),
1578 
1580  "hosts-file",
1581  "FILENAME",
1582  gettext_noop ("name of file with hosts' names"),
1583  &hosts_file),
1584 
1586  };
1587  int ret;
1588 
1589  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1590  return 2;
1592  ret =
1593  GNUNET_PROGRAM_run (argc, argv,
1594  "gnunet-regex-profiler",
1595  _("Profiler for regex"),
1596  options, &run, NULL);
1597  if (GNUNET_OK != ret)
1598  return ret;
1599  if (GNUNET_OK != result)
1600  return 1;
1601  return 0;
1602 }
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_relative_time(char shortName, const char *name, const char *argumentHelp, const char *description, struct GNUNET_TIME_Relative *val)
Allow user to specify a struct GNUNET_TIME_Relative (using human-readable "fancy" time)...
static char * regex_prefix
Prefix used for regex announcing.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:669
void GNUNET_TESTBED_cancel_registration(struct GNUNET_TESTBED_HostRegistrationHandle *handle)
Cancel the pending registration.
struct GNUNET_STATISTICS_Handle * stats_handle
Peers&#39;s statistics handle.
Create file if it doesn&#39;t exist.
unsigned int id
Peer id.
static char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
void GNUNET_TESTBED_controller_disconnect(struct GNUNET_TESTBED_Controller *c)
Stop the given controller (also will terminate all peers and controllers dependent on this controller...
Definition: testbed_api.c:1723
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config)
Main function that will be run by the scheduler.
struct GNUNET_CONFIGURATION_Handle * cfg
Peer configuration handle.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1817
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
static char * strings_file
File with the strings to look for.
static int in_shutdown
Set when shutting down to avoid making more queries.
Handle to interact with a GNUnet testbed controller.
Definition: testbed_api.h:194
static int count_and_separate_strings(char *data, uint64_t data_size, unsigned int str_max)
Process the text buffer counting the non-empty lines and separating them with NULL characters...
static struct GNUNET_SCHEDULER_Task * register_hosts_task
Host registration task identifier.
static void find_timed_out(void *cls)
Search timed out.
static void stats_connect_cb(void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg)
Function called by testbed once we are connected to stats service.
Destroying peers; we can do this as the controller takes care of stopping a peer if it is running...
static char * data_filename
Filename to log statistics to.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GNUNET_DHT_Handle * dht_handle
Peer&#39;s DHT handle.
#define FIND_TIMEOUT
Matching strings against announced regexes.
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static struct GNUNET_SCHEDULER_Task * abort_task
Abort task identifier.
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
void * cls
Closure.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
struct GNUNET_TESTBED_Operation * op_handle
Testbed operation handle for DHT.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Peer handles.
static int op_result(struct GNUNET_OP_Handle *h, uint64_t op_id, int64_t result_code, const void *data, uint16_t data_size, void **ctx, uint8_t cancel)
Remove an operation, and call its result callback (unless it was cancelled).
Definition: op.c:244
struct GNUNET_TESTBED_Operation * daemon_op
Deamon start.
void GNUNET_TESTBED_controller_stop(struct GNUNET_TESTBED_ControllerProc *cproc)
Stop the controller process (also will terminate all peers and controllers dependent on this controll...
static void dht_connect_cb(void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg)
DHT connect callback.
static void dht_da(void *cls, void *op_result)
Adapter function called to destroy a connection to the DHT service.
static void * dht_ca(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
DHT connect adapter.
int GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:628
Argument to GNUNET_TESTBED_ControllerCallback with details about the event.
struct GNUNET_TIME_Absolute prof_start_time
The starting time of a profiling step.
void GNUNET_CONFIGURATION_set_value_number(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number)
Set a configuration value that should be a number.
struct GNUNET_SCHEDULER_Task * timeout
Operation timeout.
static void test_master(void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers_, struct GNUNET_TESTBED_Peer **testbed_peers, unsigned int links_succeeded, unsigned int links_failed)
Signature of a main function for a testcase.
#define GNUNET_NO
Definition: gnunet_common.h:81
struct GNUNET_TESTBED_Operation * op
The testbed operation handle.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
enum GNUNET_TESTBED_EventType type
Type of the event.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Definition of a command line option.
static void stats_da(void *cls, void *op_result)
Adapter function called to destroy a connection to statistics service.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:1233
int main(int argc, char *const *argv)
Main function.
static struct GNUNET_CONFIGURATION_Handle * cfg
Handle to global configuration.
static int create_string_array(char *data, uint64_t data_size, char ***strings, unsigned int str_cnt)
Allocate a string array and fill it with the prefixed strings from a pre-processed, NULL-separated memory region.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
Handle for controller process.
struct DLLOperation * prev
The prev pointer for DLL.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
Connection to the DHT service.
Definition: dht_api.c:205
Opaque handle to an abstract operation to be executed by the testing framework.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static char * hosts_file
File with hostnames where to execute the test.
static void do_abort(void *cls)
abort task to run on test timed out
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_filename(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a filename (automatically path expanded).
static struct GNUNET_TESTBED_ControllerProc * mc_proc
Handle to the master controller process.
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_service_connect(void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_ServiceConnectCompletionCallback cb, void *cb_cls, GNUNET_TESTBED_ConnectAdapter ca, GNUNET_TESTBED_DisconnectAdapter da, void *cada_cls)
Connect to a service offered by the given peer.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
static void * stats_ca(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Adapter function called to establish a connection to statistics service.
enum State state
current state of profiling
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
library to parse regular expressions into dfa
struct GNUNET_TESTBED_Peer * peer_handle
The actual testbed peer handle.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static void do_announce(void *cls)
Task to start the daemons on each peer so that the regexes are announced into the DHT...
Truncate file if it exists.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:1049
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1273
static struct GNUNET_TIME_Relative reannounce_period_max
What&#39;s the maximum regex reannounce period.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:727
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static struct GNUNET_TESTBED_HostRegistrationHandle * reg_handle
Host registration handle.
static char buf[2048]
static char * filename
static const struct GNUNET_CONFIGURATION_Handle * config
static int result
Global testing status.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:439
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)
Method called when we&#39;ve found a peer that announced a regex that matches our search string...
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
static void master_controller_cb(void *cls, const struct GNUNET_TESTBED_EventInformation *event)
Function that will be called whenever something in the testbed changes.
static void daemon_started(void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
Callback called when testbed has started the daemon we asked for.
void REGEX_INTERNAL_search_cancel(struct REGEX_INTERNAL_Search *h)
Cancel an ongoing regex search in the DHT and free all resources.
static void find_string(void *cls)
Start searching for the next string in the DHT.
void GNUNET_TESTBED_operation_done(struct GNUNET_TESTBED_Operation *operation)
This function is used to signal that the event information (struct GNUNET_TESTBED_EventInformation) f...
Definition: testbed_api.c:2046
void GNUNET_TESTBED_run(const char *host_filename, const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls)
Convenience method for running a testbed with a single call.
const char * search_str
Peer&#39;s search string.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static struct GNUNET_TESTBED_Controller * mc
Handle to the master controller.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static void do_collect_stats(void *cls)
Task to collect all statistics from all peers, will shutdown the profiler, when done.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static struct GNUNET_DISK_FileHandle * data_file
File to log statistics to.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
static struct GNUNET_TESTBED_Peer ** testbed_peers
Handles to all of the running peers.
struct REGEX_INTERNAL_Search * REGEX_INTERNAL_search(struct GNUNET_DHT_Handle *dht, const char *string, REGEX_INTERNAL_Found callback, void *callback_cls, struct GNUNET_STATISTICS_Handle *stats)
Search for a peer offering a regex matching certain string in the DHT.
static void announce_next_regex(void *cls)
Start announcing the next regex in the DHT.
struct GNUNET_DHT_Handle * GNUNET_DHT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len)
Initialize the connection with the DHT service.
Definition: dht_api.c:895
static void stats_cb(void *cls, int success)
Stats callback.
const char * name
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:923
static unsigned int parallel_searches
How many searches are running in parallel.
static char * policy_dir
Folder where policy files are stored.
State
Available states during profiling.
static long long unsigned int init_parallel_searches
How many searches are we going to start in parallel.
static void search_timed_out(void *cls)
Connect by string timeout task.
A connection between two peers was established.
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:289
Struct to keep information of searches of services described by a regex using a user-provided string ...
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
static void do_shutdown(void *cls)
Shutdown nicely.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:576
The identity of the host (wraps the signing key of the peer).
static struct GNUNET_TIME_Relative prof_time
Duration profiling step has taken.
DLL of operations.
static struct RegexPeer * peers
The array of peers; we fill this as the peers are given to us by the testbed.
static char ** search_strings
Search strings (num_peers of them).
static unsigned int next_search
Index of peer to start next announce/search.
struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls)
Get statistic from the peer.
static uint64_t event_mask
Global event mask for all testbed events.
configuration data
Definition: configuration.c:85
static struct GNUNET_TIME_Absolute prof_start_time
The starting time of a profiling step.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
struct DLLOperation * next
The next pointer for DLL.
Open the file for both reading and writing.
static int stats_iterator(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
Process statistic values.
Initial state.
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:361
handle for host registration
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
static int load_search_strings(const char *filename, char ***strings, unsigned int limit)
Load search strings from given filename.
static unsigned int num_peers
Number of peers to be started by the profiler.
A peer controlled by the testing framework.
static struct GNUNET_TIME_Relative search_timeout_time
Search timeout in seconds.
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_manage_service(void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, unsigned int start)
Start or stop given service at a peer.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
struct REGEX_INTERNAL_Search * search_handle
Handle to a running regex search.
uint32_t data
The data value.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1673
static size_t data_size
Number of bytes in data.
Handle used to access files (and pipes).
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:499
static unsigned int strings_found
Number of strings found in the published regexes.
int search_str_matched
Set to GNUNET_YES if the peer successfully matched the above search string.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
static struct GNUNET_SCHEDULER_Task * search_timeout_task
Search timeout task identifier.
#define GNUNET_malloc(size)
Wrapper around malloc.
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:1019
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965