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 
45 struct DLLOperation {
50 
54  void *cls;
55 
59  struct DLLOperation *next;
60 
64  struct DLLOperation *prev;
65 };
66 
67 
71 enum State {
76 
81 
86 
91 
96 
101 
107 };
108 
109 
113 struct RegexPeer {
117  unsigned int id;
118 
123 
128 
132  const char *search_str;
133 
141 
146 
151 
156 
161 
166 
171 
176 };
177 
181 static int in_shutdown;
182 
186 static struct RegexPeer *peers;
187 
192 
197 
202 
207 
212 
217 
221 static uint64_t event_mask;
222 
227 
232 
236 static unsigned int num_peers;
237 
241 static int result;
242 
247 
251 static char * policy_dir;
252 
256 static char *hosts_file;
257 
261 static char *strings_file;
262 
266 static char **search_strings;
267 
271 static long long unsigned int init_parallel_searches;
272 
276 static unsigned int parallel_searches;
277 
281 static unsigned int strings_found;
282 
286 static unsigned int next_search;
287 
292 
296 static struct GNUNET_TIME_Relative search_timeout_time = { 60000 };
297 
302 
306 static char *data_filename;
307 
312 static char * regex_prefix;
313 
318 
319 
320 /******************************************************************************/
321 /****************************** DECLARATIONS ********************************/
322 /******************************************************************************/
323 
332 static void
334  void *ca_result, const char *emsg);
335 
344 static void *
345 dht_ca(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg);
346 
347 
355 static void
356 dht_da(void *cls, void *op_result);
357 
358 
368 static void
369 stats_connect_cb(void *cls,
371  void *ca_result,
372  const char *emsg);
373 
374 
380 static void
381 announce_next_regex(void *cls);
382 
383 
384 /******************************************************************************/
385 /******************************** SHUTDOWN **********************************/
386 /******************************************************************************/
387 
388 
394 static void
396 {
397  struct RegexPeer *peer;
398  unsigned int peer_cnt;
399  unsigned int search_str_cnt;
400  char output_buffer[512];
401  size_t size;
402 
403  if (NULL != abort_task)
404  {
405  GNUNET_SCHEDULER_cancel(abort_task);
406  abort_task = NULL;
407  }
408  if (NULL != register_hosts_task)
409  {
410  GNUNET_SCHEDULER_cancel(register_hosts_task);
411  register_hosts_task = NULL;
412  }
413  for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
414  {
415  peer = &peers[peer_cnt];
416 
417  if (GNUNET_YES != peer->search_str_matched && NULL != data_file)
418  {
420  size =
421  GNUNET_snprintf(output_buffer,
422  sizeof(output_buffer),
423  "%p Search string not found: %s (%d)\n"
424  "%p On peer: %u (%p)\n"
425  "%p After: %s\n",
426  peer, peer->search_str, peer->search_str_matched,
427  peer, peer->id, peer,
428  peer,
430  GNUNET_NO));
431  if (size != GNUNET_DISK_file_write(data_file, output_buffer, size))
432  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
433  }
434 
435  if (NULL != peers[peer_cnt].op_handle)
436  GNUNET_TESTBED_operation_done(peers[peer_cnt].op_handle);
437  }
438 
439  if (NULL != data_file)
440  {
441  GNUNET_DISK_file_close(data_file);
442  data_file = NULL;
443  }
444  for (search_str_cnt = 0;
445  search_str_cnt < num_peers && NULL != search_strings;
446  search_str_cnt++)
447  {
448  GNUNET_free_non_null(search_strings[search_str_cnt]);
449  }
451  search_strings = NULL;
452 
453  if (NULL != reg_handle)
454  {
456  reg_handle = NULL;
457  }
458  if (NULL != mc)
459  {
461  mc = NULL;
462  }
463  if (NULL != mc_proc)
464  {
466  mc_proc = NULL;
467  }
468  if (NULL != cfg)
469  {
471  cfg = NULL;
472  }
473 }
474 
475 
481 static void
482 do_abort(void *cls)
483 {
484  unsigned long i = (unsigned long)cls;
485 
487  "Aborting from line %lu...\n", i);
488  abort_task = NULL;
491 }
492 
493 
494 /******************************************************************************/
495 /********************* STATISTICS SERVICE CONNECTIONS ***********************/
496 /******************************************************************************/
497 
508 static void *
509 stats_ca(void *cls,
510  const struct GNUNET_CONFIGURATION_Handle *cfg)
511 {
512  return GNUNET_STATISTICS_create("<driver>", cfg);
513 }
514 
515 
523 static void
524 stats_da(void *cls, void *op_result)
525 {
526  struct RegexPeer *peer = cls;
527 
528  GNUNET_assert(op_result == peer->stats_handle);
529 
531  peer->stats_handle = NULL;
532 }
533 
534 
545 static int
547  const char *subsystem,
548  const char *name,
549  uint64_t value, int is_persistent)
550 {
551  struct RegexPeer *peer = cls;
552  char output_buffer[512];
553  size_t size;
554 
555  if (NULL == data_file)
556  {
558  "%p -> %s [%s]: %llu\n",
559  peer,
560  subsystem,
561  name,
562  (unsigned long long)value);
563  return GNUNET_OK;
564  }
565  size =
566  GNUNET_snprintf(output_buffer,
567  sizeof(output_buffer),
568  "%p [%s] %llu %s\n",
569  peer,
570  subsystem, value, name);
571  if (size != GNUNET_DISK_file_write(data_file, output_buffer, size))
573  "Unable to write to file!\n");
574 
575  return GNUNET_OK;
576 }
577 
578 
587 static void
588 stats_cb(void *cls,
589  int success)
590 {
591  static unsigned int peer_cnt;
592  struct RegexPeer *peer = cls;
593 
594  if (GNUNET_OK != success)
595  {
597  "Getting statistics for peer %u failed!\n",
598  peer->id);
599  return;
600  }
601 
602  GNUNET_assert(NULL != peer->op_handle);
603 
605  peer->op_handle = NULL;
606 
607  peer_cnt++;
608  peer = &peers[peer_cnt];
609 
610  fprintf(stderr, "s");
611  if (peer_cnt == num_peers)
612  {
614  "\nCollecting stats finished. Shutting down.\n");
616  result = GNUNET_OK;
617  }
618  else
619  {
620  peer->op_handle =
622  peer->peer_handle,
623  "statistics",
625  peer,
626  &stats_ca,
627  &stats_da,
628  peer);
629  }
630 }
631 
632 
642 static void
645  void *ca_result,
646  const char *emsg)
647 {
648  struct RegexPeer *peer = cls;
649 
650  if (NULL == ca_result || NULL != emsg)
651  {
653  "Failed to connect to statistics service on peer %u: %s\n",
654  peer->id, emsg);
655 
656  peer->stats_handle = NULL;
657  return;
658  }
659 
660  peer->stats_handle = ca_result;
661 
662  if (NULL == GNUNET_STATISTICS_get(peer->stats_handle, NULL, NULL,
663  &stats_cb,
664  &stats_iterator, peer))
665  {
667  "Could not get statistics of peer %u!\n", peer->id);
668  }
669 }
670 
671 
678 static void
680 {
681  struct RegexPeer *peer = &peers[0];
682 
683  GNUNET_assert(NULL != peer->peer_handle);
684 
685  peer->op_handle =
687  peer->peer_handle,
688  "statistics",
690  peer,
691  &stats_ca,
692  &stats_da,
693  peer);
694 }
695 
696 
697 /******************************************************************************/
698 /************************ REGEX FIND CONNECTIONS **************************/
699 /******************************************************************************/
700 
701 
707 static void
708 find_string(void *cls);
709 
710 
722 static void
724  const struct GNUNET_PeerIdentity *id,
725  const struct GNUNET_PeerIdentity *get_path,
726  unsigned int get_path_length,
727  const struct GNUNET_PeerIdentity *put_path,
728  unsigned int put_path_length)
729 {
730  struct RegexPeer *peer = cls;
731  char output_buffer[512];
732  size_t size;
733 
734  if (GNUNET_YES == peer->search_str_matched)
735  {
737  "String %s on peer %u already matched!\n",
738  peer->search_str, peer->id);
739  return;
740  }
741 
742  strings_found++;
744 
745  if (NULL != peer->timeout)
746  {
748  peer->timeout = NULL;
749  if (GNUNET_NO == in_shutdown)
751  }
752 
753  if (NULL == id)
754  {
755  // FIXME not possible right now
757  "String matching timed out for string %s on peer %u (%i/%i)\n",
758  peer->search_str, peer->id, strings_found, num_peers);
760  }
761  else
762  {
764 
766  "String %s found on peer %u after %s (%i/%i) (%u||)\n",
767  peer->search_str, peer->id,
770 
772 
773  if (NULL != data_file)
774  {
775  size =
776  GNUNET_snprintf(output_buffer,
777  sizeof(output_buffer),
778  "%p Peer: %u\n"
779  "%p Search string: %s\n"
780  "%p Search duration: %s\n\n",
781  peer, peer->id,
782  peer, peer->search_str,
783  peer,
785  GNUNET_NO));
786 
787  if (size != GNUNET_DISK_file_write(data_file, output_buffer, size))
788  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
789  }
790  }
791 
793  peer->op_handle = NULL;
794 
795  if (strings_found == num_peers)
796  {
799  "All strings successfully matched in %s\n",
801 
802  if (NULL != search_timeout_task)
803  {
804  GNUNET_SCHEDULER_cancel(search_timeout_task);
805  search_timeout_task = NULL;
806  }
807 
808  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Collecting stats.\n");
810  }
811 }
812 
813 
820 static void
822 {
823  unsigned int i;
824 
826  "Finding matches to all strings did not succeed after %s.\n",
827  GNUNET_STRINGS_relative_time_to_string(search_timeout_time,
828  GNUNET_NO));
830  "Found %i of %i strings\n", strings_found, num_peers);
831 
833  "Search timed out after %s."
834  "Collecting stats and shutting down.\n",
835  GNUNET_STRINGS_relative_time_to_string(search_timeout_time,
836  GNUNET_NO));
837 
839  for (i = 0; i < num_peers; i++)
840  {
841  if (NULL != peers[i].op_handle)
842  {
843  GNUNET_TESTBED_operation_done(peers[i].op_handle);
844  peers[i].op_handle = NULL;
845  }
846  }
848 }
849 
850 
857 static void
859 {
860  struct RegexPeer *p = cls;
861 
862  p->timeout = NULL;
864  "Searching for string \"%s\" on peer %d timed out.\n",
865  p->search_str,
866  p->id);
867  if (GNUNET_NO == in_shutdown)
869 }
870 
871 
877 static void
879 {
880  unsigned int search_peer = (unsigned int)(long)cls;
881 
882  if ((search_peer >= num_peers) ||
883  (GNUNET_YES == in_shutdown))
884  return;
885 
887  "Searching for string \"%s\" on peer %d (%u||)\n",
888  peers[search_peer].search_str,
889  search_peer,
891 
892  peers[search_peer].op_handle =
894  peers[search_peer].peer_handle,
895  "dht",
897  &peers[search_peer],
898  &dht_ca,
899  &dht_da,
900  &peers[search_peer]);
901  GNUNET_assert(NULL != peers[search_peer].op_handle);
902  peers[search_peer].timeout
905  &peers[search_peer]);
906 }
907 
908 
916 static void
919  const char *emsg)
920 {
921  struct RegexPeer *peer = (struct RegexPeer *)cls;
922  unsigned long search_peer;
923  unsigned int i;
924 
926  peer->daemon_op = NULL;
927  if (NULL != emsg)
928  {
930  "Failed to start/stop daemon at peer %u: %s\n", peer->id, emsg);
931  GNUNET_assert(0);
932  }
933  else
934  {
936  "Deamon %u started successfully\n", peer->id);
937  }
938 
939  /* Find a peer to look for a string matching the regex announced */
941  num_peers);
942  for (i = 0; peers[search_peer].search_str != NULL; i++)
943  {
944  search_peer = (search_peer + 1) % num_peers;
945  if (i > num_peers)
946  GNUNET_assert(0); /* we ran out of peers, must be a bug */
947  }
948  peers[search_peer].search_str = search_strings[peer->id];
949  peers[search_peer].search_str_matched = GNUNET_NO;
952  2),
953  &find_string,
954  (void *)search_peer);
955 }
956 
957 
965 static void
967 {
968  unsigned int i;
969 
970  if (GNUNET_YES == in_shutdown)
971  return;
973  "Starting announce.\n");
974  for (i = 0; i < init_parallel_searches; i++)
975  {
977  " scheduling announce %u\n",
978  i);
980  }
981 }
982 
983 
989 static void
991 {
992  struct RegexPeer *peer;
993 
994  if (GNUNET_YES == in_shutdown)
995  return;
996  if (next_search >= num_peers)
997  {
998  if (strings_found != num_peers)
999  {
1000  struct GNUNET_TIME_Relative new_delay;
1001  if (NULL != search_timeout_task)
1002  GNUNET_SCHEDULER_cancel(search_timeout_task);
1004  search_timeout_task = GNUNET_SCHEDULER_add_delayed(new_delay,
1006  NULL);
1007  }
1008  return;
1009  }
1010 
1011  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Starting daemon %u\n", next_search);
1012  peer = &peers[next_search];
1013  peer->daemon_op =
1015  peer->peer_handle,
1016  "regexprofiler",
1017  &daemon_started,
1018  peer,
1019  1);
1020  next_search++;
1022 }
1023 
1024 
1035 static void
1037  struct GNUNET_TESTBED_Operation *op,
1038  void *ca_result,
1039  const char *emsg)
1040 {
1041  struct RegexPeer *peer = (struct RegexPeer *)cls;
1042 
1043  if (NULL != emsg || NULL == op || NULL == ca_result)
1044  {
1045  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "DHT connect failed: %s\n", emsg);
1046  GNUNET_assert(0);
1047  }
1048 
1049  GNUNET_assert(NULL != peer->dht_handle);
1050  GNUNET_assert(peer->op_handle == op);
1051  GNUNET_assert(peer->dht_handle == ca_result);
1052 
1053  peer->search_str_matched = GNUNET_NO;
1055  peer->search_str,
1056  &regex_found_handler, peer,
1057  NULL);
1059 }
1060 
1061 
1070 static void *
1071 dht_ca(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
1072 {
1073  struct RegexPeer *peer = cls;
1074 
1075  peer->dht_handle = GNUNET_DHT_connect(cfg, 32);
1076 
1077  return peer->dht_handle;
1078 }
1079 
1080 
1087 static void
1088 dht_da(void *cls, void *op_result)
1089 {
1090  struct RegexPeer *peer = (struct RegexPeer *)cls;
1091 
1092  GNUNET_assert(peer->dht_handle == op_result);
1093 
1094  if (NULL != peer->search_handle)
1095  {
1097  peer->search_handle = NULL;
1098  }
1099 
1100  if (NULL != peer->dht_handle)
1101  {
1103  peer->dht_handle = NULL;
1104  }
1105 }
1106 
1107 
1121 static void
1123  struct GNUNET_TESTBED_RunHandle *h,
1124  unsigned int num_peers_,
1126  unsigned int links_succeeded,
1127  unsigned int links_failed)
1128 {
1129  unsigned int i;
1130 
1131  GNUNET_assert(num_peers_ == num_peers);
1132 
1135  "Testbed started in %s\n",
1137 
1138  if (NULL != abort_task)
1139  {
1140  GNUNET_SCHEDULER_cancel(abort_task);
1141  abort_task = NULL;
1142  }
1143 
1144  for (i = 0; i < num_peers; i++)
1145  {
1146  peers[i].peer_handle = testbed_peers[i];
1147  }
1148  if (GNUNET_NO ==
1149  GNUNET_CONFIGURATION_get_value_yesno(cfg, "DHT", "DISABLE_TRY_CONNECT"))
1150  {
1151  struct GNUNET_TIME_Relative settle_time;
1152 
1153  settle_time =
1155  10 * num_peers);
1157  "Waiting for DHT for %s to settle new connections.\n\n",
1159  GNUNET_SCHEDULER_add_delayed(settle_time, &do_announce, NULL);
1160  }
1161  else
1162  {
1164  }
1165  search_timeout_task =
1166  GNUNET_SCHEDULER_add_delayed(search_timeout_time, &search_timed_out, NULL);
1167 }
1168 
1175 static void
1177  const struct GNUNET_TESTBED_EventInformation *event)
1178 {
1179  switch (event->type)
1180  {
1182  printf(".");
1183  break;
1184 
1186  printf("#");
1187  break;
1188 
1189  default:
1190  break;
1191  }
1192  fflush(stdout);
1193 }
1194 
1195 
1196 /******************************************************************************/
1197 /*************************** TESTBED PEER SETUP *****************************/
1198 /******************************************************************************/
1199 
1210 static int
1212  uint64_t data_size,
1213  unsigned int str_max)
1214 {
1215  char *buf; // Keep track of last string to skip blank lines
1216  unsigned int offset;
1217  unsigned int str_cnt;
1218 
1219  buf = data;
1220  offset = 0;
1221  str_cnt = 0;
1222  while ((offset < (data_size - 1)) && (str_cnt < str_max))
1223  {
1224  offset++;
1225  if (((data[offset] == '\n')) &&
1226  (buf != &data[offset]))
1227  {
1228  data[offset] = '\0';
1229  str_cnt++;
1230  buf = &data[offset + 1];
1231  }
1232  else if ((data[offset] == '\n') ||
1233  (data[offset] == '\0'))
1234  buf = &data[offset + 1];
1235  }
1236  return str_cnt;
1237 }
1238 
1239 
1253 static int
1255  char ***strings, unsigned int str_cnt)
1256 {
1257  uint64_t offset;
1258  uint64_t len;
1259  unsigned int i;
1260 
1261  *strings = GNUNET_malloc(sizeof(char *) * str_cnt);
1262  offset = 0;
1263  for (i = 0; i < str_cnt; i++)
1264  {
1265  len = strlen(&data[offset]);
1266  if (offset + len >= data_size)
1267  {
1268  GNUNET_free(*strings);
1269  *strings = NULL;
1270  return GNUNET_SYSERR;
1271  }
1272  if (0 == len) // empty line
1273  {
1274  offset++;
1275  i--;
1276  continue;
1277  }
1278 
1279  GNUNET_asprintf(&(*strings)[i],
1280  "%s%s",
1281  regex_prefix,
1282  &data[offset]);
1283  offset += len + 1;
1284  }
1285  return GNUNET_OK;
1286 }
1287 
1288 
1298 static int
1300  char ***strings,
1301  unsigned int limit)
1302 {
1303  char *data;
1304  uint64_t filesize;
1305  int str_cnt;
1306 
1307  /* Sanity checks */
1308  if (NULL == filename)
1309  {
1310  return GNUNET_SYSERR;
1311  }
1312  if (GNUNET_YES != GNUNET_DISK_file_test(filename))
1313  {
1315  "Could not find search strings file %s\n", filename);
1316  return GNUNET_SYSERR;
1317  }
1318  if (GNUNET_OK !=
1319  GNUNET_DISK_file_size(filename,
1320  &filesize,
1321  GNUNET_YES,
1322  GNUNET_YES))
1323  {
1325  "Search strings file %s cannot be read.\n",
1326  filename);
1327  return GNUNET_SYSERR;
1328  }
1329  if (0 == filesize)
1330  {
1332  "Search strings file %s is empty.\n",
1333  filename);
1334  return GNUNET_SYSERR;
1335  }
1336 
1337  /* Read data into memory */
1338  data = GNUNET_malloc(filesize + 1);
1339  if (filesize != GNUNET_DISK_fn_read(filename,
1340  data,
1341  filesize))
1342  {
1343  GNUNET_free(data);
1345  "Could not read search strings file %s.\n",
1346  filename);
1347  return GNUNET_SYSERR;
1348  }
1349 
1350  /* Process buffer and build array */
1351  str_cnt = count_and_separate_strings(data, filesize, limit);
1352  if (GNUNET_OK != create_string_array(data, filesize, strings, str_cnt))
1353  {
1354  str_cnt = GNUNET_SYSERR;
1355  }
1356  GNUNET_free(data);
1357  return str_cnt;
1358 }
1359 
1360 
1369 static void
1370 run(void *cls,
1371  char *const *args,
1372  const char *cfgfile,
1373  const struct GNUNET_CONFIGURATION_Handle *config)
1374 {
1375  unsigned int nsearchstrs;
1376  unsigned int i;
1377  struct GNUNET_TIME_Relative abort_time;
1378 
1380 
1381  /* Check config */
1382  if (NULL == config)
1383  {
1385  _("No configuration file given. Exiting\n"));
1387  return;
1388  }
1389  cfg = GNUNET_CONFIGURATION_dup(config);
1390  if (GNUNET_OK !=
1391  GNUNET_CONFIGURATION_get_value_string(cfg, "REGEXPROFILER",
1392  "REGEX_PREFIX",
1393  &regex_prefix))
1394  {
1396  "regexprofiler",
1397  "regex_prefix");
1399  return;
1400  }
1401  if (GNUNET_OK !=
1402  GNUNET_CONFIGURATION_get_value_number(cfg, "REGEXPROFILER",
1403  "PARALLEL_SEARCHES",
1405  {
1407  "Configuration option \"PARALLEL_SEARCHES\" missing."
1408  " Using default (%d)\n", 10);
1410  }
1411  if (GNUNET_OK !=
1412  GNUNET_CONFIGURATION_get_value_time(cfg, "REGEXPROFILER",
1413  "REANNOUNCE_PERIOD_MAX",
1415  {
1417  "reannounce_period_max not given. Using 10 minutes.\n");
1420  }
1421 
1422  /* Check arguments */
1423  if (NULL == policy_dir)
1424  {
1426  _("No policy directory specified on command line. Exiting.\n"));
1427  return;
1428  }
1430  {
1432  _("Specified policies directory does not exist. Exiting.\n"));
1434  return;
1435  }
1436  if (0 >= (int)(num_peers = GNUNET_DISK_directory_scan(policy_dir, NULL, NULL)))
1437  {
1439  _("No files found in `%s'\n"),
1440  policy_dir);
1441  return;
1442  }
1443  GNUNET_CONFIGURATION_set_value_string(cfg, "REGEXPROFILER",
1444  "POLICY_DIR", policy_dir);
1446  {
1448  _("No search strings file given. Exiting.\n"));
1450  return;
1451  }
1452  nsearchstrs = load_search_strings(strings_file,
1453  &search_strings,
1454  num_peers);
1455  if (num_peers != nsearchstrs)
1456  {
1458  "Error loading search strings.\n");
1460  "File (%s) does not contain enough strings (%u/%u).\n",
1461  strings_file, nsearchstrs, num_peers);
1463  return;
1464  }
1465  if ((0 == num_peers) || (NULL == search_strings))
1466  {
1468  _("Error loading search strings. Exiting.\n"));
1470  return;
1471  }
1472  for (i = 0; i < num_peers; i++)
1474  "search string: %s\n",
1475  search_strings[i]);
1476 
1477  /* Check logfile */
1478  if ((NULL != data_filename) &&
1479  (NULL == (data_file =
1486  {
1488  "open",
1489  data_filename);
1490  return;
1491  }
1492 
1493  /* Initialize peers */
1494  peers = GNUNET_malloc(sizeof(struct RegexPeer) * num_peers);
1495  for (i = 0; i < num_peers; i++)
1496  peers[i].id = i;
1497 
1499  "TESTBED", "OVERLAY_RANDOM_LINKS",
1500  num_peers * 20);
1502  "DHT", "FORCE_NSE",
1503  (long long unsigned)
1504  (log(num_peers) / log(2.0)));
1505  event_mask = 0LL;
1506 /* For feedback about the start process activate these and pass master_cb */
1508 // event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
1510 // event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT);
1513  cfg,
1514  num_peers,
1515  event_mask,
1517  NULL, /* master_controller_cb cls */
1518  &test_master,
1519  NULL); /* test_master cls */
1520  if (GNUNET_OK !=
1521  GNUNET_CONFIGURATION_get_value_time(cfg, "TESTBED",
1522  "SETUP_TIMEOUT",
1523  &abort_time))
1524  {
1526  "SETUP_TIMEOUT not given. Using 15 minutes.\n");
1527  abort_time =
1529  }
1530  abort_time = GNUNET_TIME_relative_add(abort_time, GNUNET_TIME_UNIT_MINUTES);
1531  abort_task =
1532  GNUNET_SCHEDULER_add_delayed(abort_time,
1533  &do_abort,
1534  (void*)__LINE__);
1536  "setup_timeout: %s\n",
1538 }
1539 
1540 
1548 int
1549 main(int argc, char *const *argv)
1550 {
1551  struct GNUNET_GETOPT_CommandLineOption options[] = {
1553  "output-file",
1554  "FILENAME",
1555  gettext_noop("name of the file for writing statistics"),
1556  &data_filename),
1557 
1559  "matching-timeout",
1560  "TIMEOUT",
1561  gettext_noop("wait TIMEOUT before ending the experiment"),
1562  &search_timeout_time),
1563 
1565  "policy-dir",
1566  "DIRECTORY",
1567  gettext_noop("directory with policy files"),
1568  &policy_dir),
1569 
1570 
1572  "strings-file",
1573  "FILENAME",
1574  gettext_noop("name of file with input strings"),
1575  &strings_file),
1576 
1578  "hosts-file",
1579  "FILENAME",
1580  gettext_noop("name of file with hosts' names"),
1581  &hosts_file),
1582 
1584  };
1585  int ret;
1586 
1587  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
1588  return 2;
1590  ret =
1591  GNUNET_PROGRAM_run(argc, argv,
1592  "gnunet-regex-profiler",
1593  _("Profiler for regex"),
1594  options, &run, NULL);
1595  if (GNUNET_OK != ret)
1596  return ret;
1597  if (GNUNET_OK != result)
1598  return 1;
1599  return 0;
1600 }
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:541
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:1713
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:1339
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:191
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:1439
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:243
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:500
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:78
struct GNUNET_TESTBED_Operation * op
The testbed operation handle.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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:909
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:517
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:198
Opaque handle to an abstract operation to be executed by the testing framework.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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:1237
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:817
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:1264
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:686
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:440
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:2037
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:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
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:885
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:913
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:254
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:577
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:83
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:131
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:367
handle for host registration
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:1262
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:791
#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:956