gnunet-regex-profiler.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011 - 2017 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file regex/gnunet-regex-profiler.c
  18. * @brief Regex profiler for testing distributed regex use.
  19. * @author Bartlomiej Polot
  20. * @author Maximilian Szengel
  21. *
  22. */
  23. #include <string.h>
  24. #include "platform.h"
  25. #include "gnunet_applications.h"
  26. #include "gnunet_util_lib.h"
  27. #include "regex_internal_lib.h"
  28. #include "gnunet_arm_service.h"
  29. #include "gnunet_dht_service.h"
  30. #include "gnunet_testbed_service.h"
  31. #define FIND_TIMEOUT \
  32. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90)
  33. /**
  34. * DLL of operations
  35. */
  36. struct DLLOperation
  37. {
  38. /**
  39. * The testbed operation handle
  40. */
  41. struct GNUNET_TESTBED_Operation *op;
  42. /**
  43. * Closure
  44. */
  45. void *cls;
  46. /**
  47. * The next pointer for DLL
  48. */
  49. struct DLLOperation *next;
  50. /**
  51. * The prev pointer for DLL
  52. */
  53. struct DLLOperation *prev;
  54. };
  55. /**
  56. * Available states during profiling
  57. */
  58. enum State
  59. {
  60. /**
  61. * Initial state
  62. */
  63. STATE_INIT = 0,
  64. /**
  65. * Starting slaves
  66. */
  67. STATE_SLAVES_STARTING,
  68. /**
  69. * Creating peers
  70. */
  71. STATE_PEERS_CREATING,
  72. /**
  73. * Starting peers
  74. */
  75. STATE_PEERS_STARTING,
  76. /**
  77. * Linking peers
  78. */
  79. STATE_PEERS_LINKING,
  80. /**
  81. * Matching strings against announced regexes
  82. */
  83. STATE_SEARCH_REGEX,
  84. /**
  85. * Destroying peers; we can do this as the controller takes care of stopping a
  86. * peer if it is running
  87. */
  88. STATE_PEERS_DESTROYING
  89. };
  90. /**
  91. * Peer handles.
  92. */
  93. struct RegexPeer
  94. {
  95. /**
  96. * Peer id.
  97. */
  98. unsigned int id;
  99. /**
  100. * Peer configuration handle.
  101. */
  102. struct GNUNET_CONFIGURATION_Handle *cfg;
  103. /**
  104. * The actual testbed peer handle.
  105. */
  106. struct GNUNET_TESTBED_Peer *peer_handle;
  107. /**
  108. * Peer's search string.
  109. */
  110. const char *search_str;
  111. /**
  112. * Set to GNUNET_YES if the peer successfully matched the above
  113. * search string. GNUNET_NO if the string could not be matched
  114. * during the profiler run. GNUNET_SYSERR if the string matching
  115. * timed out. Undefined if search_str is NULL
  116. */
  117. int search_str_matched;
  118. /**
  119. * Peer's DHT handle.
  120. */
  121. struct GNUNET_DHT_Handle *dht_handle;
  122. /**
  123. * Handle to a running regex search.
  124. */
  125. struct REGEX_INTERNAL_Search *search_handle;
  126. /**
  127. * Testbed operation handle for DHT.
  128. */
  129. struct GNUNET_TESTBED_Operation *op_handle;
  130. /**
  131. * Peers's statistics handle.
  132. */
  133. struct GNUNET_STATISTICS_Handle *stats_handle;
  134. /**
  135. * The starting time of a profiling step.
  136. */
  137. struct GNUNET_TIME_Absolute prof_start_time;
  138. /**
  139. * Operation timeout
  140. */
  141. struct GNUNET_SCHEDULER_Task *timeout;
  142. /**
  143. * Deamon start
  144. */
  145. struct GNUNET_TESTBED_Operation *daemon_op;
  146. };
  147. /**
  148. * Set when shutting down to avoid making more queries.
  149. */
  150. static int in_shutdown;
  151. /**
  152. * The array of peers; we fill this as the peers are given to us by the testbed
  153. */
  154. static struct RegexPeer *peers;
  155. /**
  156. * Host registration handle
  157. */
  158. static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
  159. /**
  160. * Handle to the master controller process
  161. */
  162. static struct GNUNET_TESTBED_ControllerProc *mc_proc;
  163. /**
  164. * Handle to the master controller
  165. */
  166. static struct GNUNET_TESTBED_Controller *mc;
  167. /**
  168. * Handle to global configuration
  169. */
  170. static struct GNUNET_CONFIGURATION_Handle *cfg;
  171. /**
  172. * Abort task identifier
  173. */
  174. static struct GNUNET_SCHEDULER_Task *abort_task;
  175. /**
  176. * Host registration task identifier
  177. */
  178. static struct GNUNET_SCHEDULER_Task *register_hosts_task;
  179. /**
  180. * Global event mask for all testbed events
  181. */
  182. static uint64_t event_mask;
  183. /**
  184. * The starting time of a profiling step
  185. */
  186. static struct GNUNET_TIME_Absolute prof_start_time;
  187. /**
  188. * Duration profiling step has taken
  189. */
  190. static struct GNUNET_TIME_Relative prof_time;
  191. /**
  192. * Number of peers to be started by the profiler
  193. */
  194. static unsigned int num_peers;
  195. /**
  196. * Global testing status
  197. */
  198. static int result;
  199. /**
  200. * current state of profiling
  201. */
  202. enum State state;
  203. /**
  204. * Folder where policy files are stored.
  205. */
  206. static char *policy_dir;
  207. /**
  208. * File with hostnames where to execute the test.
  209. */
  210. static char *hosts_file;
  211. /**
  212. * File with the strings to look for.
  213. */
  214. static char *strings_file;
  215. /**
  216. * Search strings (num_peers of them).
  217. */
  218. static char **search_strings;
  219. /**
  220. * How many searches are we going to start in parallel
  221. */
  222. static long long unsigned int init_parallel_searches;
  223. /**
  224. * How many searches are running in parallel
  225. */
  226. static unsigned int parallel_searches;
  227. /**
  228. * Number of strings found in the published regexes.
  229. */
  230. static unsigned int strings_found;
  231. /**
  232. * Index of peer to start next announce/search.
  233. */
  234. static unsigned int next_search;
  235. /**
  236. * Search timeout task identifier.
  237. */
  238. static struct GNUNET_SCHEDULER_Task *search_timeout_task;
  239. /**
  240. * Search timeout in seconds.
  241. */
  242. static struct GNUNET_TIME_Relative search_timeout_time = { 60000 };
  243. /**
  244. * File to log statistics to.
  245. */
  246. static struct GNUNET_DISK_FileHandle *data_file;
  247. /**
  248. * Filename to log statistics to.
  249. */
  250. static char *data_filename;
  251. /**
  252. * Prefix used for regex announcing. We need to prefix the search
  253. * strings with it, in order to find something.
  254. */
  255. static char *regex_prefix;
  256. /**
  257. * What's the maximum regex reannounce period.
  258. */
  259. static struct GNUNET_TIME_Relative reannounce_period_max;
  260. /******************************************************************************/
  261. /****************************** DECLARATIONS ********************************/
  262. /******************************************************************************/
  263. /**
  264. * DHT connect callback.
  265. *
  266. * @param cls internal peer id.
  267. * @param op operation handle.
  268. * @param ca_result connect adapter result.
  269. * @param emsg error message.
  270. */
  271. static void
  272. dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
  273. void *ca_result, const char *emsg);
  274. /**
  275. * DHT connect adapter.
  276. *
  277. * @param cls not used.
  278. * @param cfg configuration handle.
  279. *
  280. * @return
  281. */
  282. static void *
  283. dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg);
  284. /**
  285. * Adapter function called to destroy a connection to
  286. * the DHT service
  287. *
  288. * @param cls closure
  289. * @param op_result service handle returned from the connect adapter
  290. */
  291. static void
  292. dht_da (void *cls, void *op_result);
  293. /**
  294. * Function called by testbed once we are connected to stats
  295. * service. Get the statistics for the services of interest.
  296. *
  297. * @param cls the 'struct RegexPeer' for which we connected to stats
  298. * @param op connect operation handle
  299. * @param ca_result handle to stats service
  300. * @param emsg error message on failure
  301. */
  302. static void
  303. stats_connect_cb (void *cls,
  304. struct GNUNET_TESTBED_Operation *op,
  305. void *ca_result,
  306. const char *emsg);
  307. /**
  308. * Start announcing the next regex in the DHT.
  309. *
  310. * @param cls Index of the next peer in the peers array.
  311. */
  312. static void
  313. announce_next_regex (void *cls);
  314. /******************************************************************************/
  315. /******************************** SHUTDOWN **********************************/
  316. /******************************************************************************/
  317. /**
  318. * Shutdown nicely
  319. *
  320. * @param cls NULL
  321. */
  322. static void
  323. do_shutdown (void *cls)
  324. {
  325. struct RegexPeer *peer;
  326. unsigned int peer_cnt;
  327. unsigned int search_str_cnt;
  328. char output_buffer[512];
  329. size_t size;
  330. if (NULL != abort_task)
  331. {
  332. GNUNET_SCHEDULER_cancel (abort_task);
  333. abort_task = NULL;
  334. }
  335. if (NULL != register_hosts_task)
  336. {
  337. GNUNET_SCHEDULER_cancel (register_hosts_task);
  338. register_hosts_task = NULL;
  339. }
  340. for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++)
  341. {
  342. peer = &peers[peer_cnt];
  343. if ((GNUNET_YES != peer->search_str_matched) && (NULL != data_file) )
  344. {
  345. prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time);
  346. size =
  347. GNUNET_snprintf (output_buffer,
  348. sizeof(output_buffer),
  349. "%p Search string not found: %s (%d)\n"
  350. "%p On peer: %u (%p)\n"
  351. "%p After: %s\n",
  352. peer, peer->search_str, peer->search_str_matched,
  353. peer, peer->id, peer,
  354. peer,
  355. GNUNET_STRINGS_relative_time_to_string (prof_time,
  356. GNUNET_NO));
  357. if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
  358. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
  359. }
  360. if (NULL != peers[peer_cnt].op_handle)
  361. GNUNET_TESTBED_operation_done (peers[peer_cnt].op_handle);
  362. }
  363. if (NULL != data_file)
  364. {
  365. GNUNET_DISK_file_close (data_file);
  366. data_file = NULL;
  367. }
  368. for (search_str_cnt = 0;
  369. search_str_cnt < num_peers && NULL != search_strings;
  370. search_str_cnt++)
  371. {
  372. GNUNET_free (search_strings[search_str_cnt]);
  373. }
  374. GNUNET_free (search_strings);
  375. search_strings = NULL;
  376. if (NULL != reg_handle)
  377. {
  378. GNUNET_TESTBED_cancel_registration (reg_handle);
  379. reg_handle = NULL;
  380. }
  381. if (NULL != mc)
  382. {
  383. GNUNET_TESTBED_controller_disconnect (mc);
  384. mc = NULL;
  385. }
  386. if (NULL != mc_proc)
  387. {
  388. GNUNET_TESTBED_controller_stop (mc_proc);
  389. mc_proc = NULL;
  390. }
  391. if (NULL != cfg)
  392. {
  393. GNUNET_CONFIGURATION_destroy (cfg);
  394. cfg = NULL;
  395. }
  396. }
  397. /**
  398. * abort task to run on test timed out
  399. *
  400. * @param cls NULL
  401. */
  402. static void
  403. do_abort (void *cls)
  404. {
  405. unsigned long i = (unsigned long) cls;
  406. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  407. "Aborting from line %lu...\n", i);
  408. abort_task = NULL;
  409. result = GNUNET_SYSERR;
  410. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  411. }
  412. /******************************************************************************/
  413. /********************* STATISTICS SERVICE CONNECTIONS ***********************/
  414. /******************************************************************************/
  415. /**
  416. * Adapter function called to establish a connection to
  417. * statistics service.
  418. *
  419. * @param cls closure
  420. * @param cfg configuration of the peer to connect to; will be available until
  421. * GNUNET_TESTBED_operation_done() is called on the operation returned
  422. * from GNUNET_TESTBED_service_connect()
  423. * @return service handle to return in 'op_result', NULL on error
  424. */
  425. static void *
  426. stats_ca (void *cls,
  427. const struct GNUNET_CONFIGURATION_Handle *cfg)
  428. {
  429. return GNUNET_STATISTICS_create ("<driver>", cfg);
  430. }
  431. /**
  432. * Adapter function called to destroy a connection to
  433. * statistics service.
  434. *
  435. * @param cls closure
  436. * @param op_result service handle returned from the connect adapter
  437. */
  438. static void
  439. stats_da (void *cls, void *op_result)
  440. {
  441. struct RegexPeer *peer = cls;
  442. GNUNET_assert (op_result == peer->stats_handle);
  443. GNUNET_STATISTICS_destroy (peer->stats_handle, GNUNET_NO);
  444. peer->stats_handle = NULL;
  445. }
  446. /**
  447. * Process statistic values. Write all values to global 'data_file', if present.
  448. *
  449. * @param cls closure
  450. * @param subsystem name of subsystem that created the statistic
  451. * @param name the name of the datum
  452. * @param value the current value
  453. * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
  454. * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  455. */
  456. static int
  457. stats_iterator (void *cls,
  458. const char *subsystem,
  459. const char *name,
  460. uint64_t value, int is_persistent)
  461. {
  462. struct RegexPeer *peer = cls;
  463. char output_buffer[512];
  464. size_t size;
  465. if (NULL == data_file)
  466. {
  467. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  468. "%p -> %s [%s]: %llu\n",
  469. peer,
  470. subsystem,
  471. name,
  472. (unsigned long long) value);
  473. return GNUNET_OK;
  474. }
  475. size =
  476. GNUNET_snprintf (output_buffer,
  477. sizeof(output_buffer),
  478. "%p [%s] %llu %s\n",
  479. peer,
  480. subsystem, value, name);
  481. if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
  482. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  483. "Unable to write to file!\n");
  484. return GNUNET_OK;
  485. }
  486. /**
  487. * Stats callback. Finish the stats testbed operation and when all stats have
  488. * been iterated, shutdown the profiler.
  489. *
  490. * @param cls closure
  491. * @param success GNUNET_OK if statistics were
  492. * successfully obtained, GNUNET_SYSERR if not.
  493. */
  494. static void
  495. stats_cb (void *cls,
  496. int success)
  497. {
  498. static unsigned int peer_cnt;
  499. struct RegexPeer *peer = cls;
  500. if (GNUNET_OK != success)
  501. {
  502. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  503. "Getting statistics for peer %u failed!\n",
  504. peer->id);
  505. return;
  506. }
  507. GNUNET_assert (NULL != peer->op_handle);
  508. GNUNET_TESTBED_operation_done (peer->op_handle);
  509. peer->op_handle = NULL;
  510. peer_cnt++;
  511. peer = &peers[peer_cnt];
  512. fprintf (stderr, "s");
  513. if (peer_cnt == num_peers)
  514. {
  515. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  516. "\nCollecting stats finished. Shutting down.\n");
  517. GNUNET_SCHEDULER_shutdown ();
  518. result = GNUNET_OK;
  519. }
  520. else
  521. {
  522. peer->op_handle =
  523. GNUNET_TESTBED_service_connect (NULL,
  524. peer->peer_handle,
  525. "statistics",
  526. &stats_connect_cb,
  527. peer,
  528. &stats_ca,
  529. &stats_da,
  530. peer);
  531. }
  532. }
  533. /**
  534. * Function called by testbed once we are connected to stats
  535. * service. Get the statistics for the services of interest.
  536. *
  537. * @param cls the 'struct RegexPeer' for which we connected to stats
  538. * @param op connect operation handle
  539. * @param ca_result handle to stats service
  540. * @param emsg error message on failure
  541. */
  542. static void
  543. stats_connect_cb (void *cls,
  544. struct GNUNET_TESTBED_Operation *op,
  545. void *ca_result,
  546. const char *emsg)
  547. {
  548. struct RegexPeer *peer = cls;
  549. if ((NULL == ca_result) || (NULL != emsg))
  550. {
  551. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  552. "Failed to connect to statistics service on peer %u: %s\n",
  553. peer->id, emsg);
  554. peer->stats_handle = NULL;
  555. return;
  556. }
  557. peer->stats_handle = ca_result;
  558. if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, NULL, NULL,
  559. &stats_cb,
  560. &stats_iterator, peer))
  561. {
  562. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  563. "Could not get statistics of peer %u!\n", peer->id);
  564. }
  565. }
  566. /**
  567. * Task to collect all statistics from all peers, will shutdown the
  568. * profiler, when done.
  569. *
  570. * @param cls NULL
  571. */
  572. static void
  573. do_collect_stats (void *cls)
  574. {
  575. struct RegexPeer *peer = &peers[0];
  576. GNUNET_assert (NULL != peer->peer_handle);
  577. peer->op_handle =
  578. GNUNET_TESTBED_service_connect (NULL,
  579. peer->peer_handle,
  580. "statistics",
  581. &stats_connect_cb,
  582. peer,
  583. &stats_ca,
  584. &stats_da,
  585. peer);
  586. }
  587. /******************************************************************************/
  588. /************************ REGEX FIND CONNECTIONS **************************/
  589. /******************************************************************************/
  590. /**
  591. * Start searching for the next string in the DHT.
  592. *
  593. * @param cls Index of the next peer in the peers array.
  594. */
  595. static void
  596. find_string (void *cls);
  597. /**
  598. * Method called when we've found a peer that announced a regex
  599. * that matches our search string. Now get the statistics.
  600. *
  601. * @param cls Closure provided in REGEX_INTERNAL_search.
  602. * @param id Peer providing a regex that matches the string.
  603. * @param get_path Path of the get request.
  604. * @param get_path_length Lenght of get_path.
  605. * @param put_path Path of the put request.
  606. * @param put_path_length Length of the put_path.
  607. */
  608. static void
  609. regex_found_handler (void *cls,
  610. const struct GNUNET_PeerIdentity *id,
  611. const struct GNUNET_PeerIdentity *get_path,
  612. unsigned int get_path_length,
  613. const struct GNUNET_PeerIdentity *put_path,
  614. unsigned int put_path_length)
  615. {
  616. struct RegexPeer *peer = cls;
  617. char output_buffer[512];
  618. size_t size;
  619. if (GNUNET_YES == peer->search_str_matched)
  620. {
  621. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  622. "String %s on peer %u already matched!\n",
  623. peer->search_str, peer->id);
  624. return;
  625. }
  626. strings_found++;
  627. parallel_searches--;
  628. if (NULL != peer->timeout)
  629. {
  630. GNUNET_SCHEDULER_cancel (peer->timeout);
  631. peer->timeout = NULL;
  632. if (GNUNET_NO == in_shutdown)
  633. GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
  634. }
  635. if (NULL == id)
  636. {
  637. // FIXME not possible right now
  638. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  639. "String matching timed out for string %s on peer %u (%i/%i)\n",
  640. peer->search_str, peer->id, strings_found, num_peers);
  641. peer->search_str_matched = GNUNET_SYSERR;
  642. }
  643. else
  644. {
  645. prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time);
  646. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  647. "String %s found on peer %u after %s (%i/%i) (%u||)\n",
  648. peer->search_str, peer->id,
  649. GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
  650. strings_found, num_peers, parallel_searches);
  651. peer->search_str_matched = GNUNET_YES;
  652. if (NULL != data_file)
  653. {
  654. size =
  655. GNUNET_snprintf (output_buffer,
  656. sizeof(output_buffer),
  657. "%p Peer: %u\n"
  658. "%p Search string: %s\n"
  659. "%p Search duration: %s\n\n",
  660. peer, peer->id,
  661. peer, peer->search_str,
  662. peer,
  663. GNUNET_STRINGS_relative_time_to_string (prof_time,
  664. GNUNET_NO));
  665. if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
  666. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
  667. }
  668. }
  669. GNUNET_TESTBED_operation_done (peer->op_handle);
  670. peer->op_handle = NULL;
  671. if (strings_found == num_peers)
  672. {
  673. prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
  674. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  675. "All strings successfully matched in %s\n",
  676. GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
  677. if (NULL != search_timeout_task)
  678. {
  679. GNUNET_SCHEDULER_cancel (search_timeout_task);
  680. search_timeout_task = NULL;
  681. }
  682. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Collecting stats.\n");
  683. GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL);
  684. }
  685. }
  686. /**
  687. * Connect by string timeout task. This will cancel the profiler after the
  688. * specified timeout 'search_timeout'.
  689. *
  690. * @param cls NULL
  691. */
  692. static void
  693. search_timed_out (void *cls)
  694. {
  695. unsigned int i;
  696. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  697. "Finding matches to all strings did not succeed after %s.\n",
  698. GNUNET_STRINGS_relative_time_to_string (search_timeout_time,
  699. GNUNET_NO));
  700. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  701. "Found %i of %i strings\n", strings_found, num_peers);
  702. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  703. "Search timed out after %s."
  704. "Collecting stats and shutting down.\n",
  705. GNUNET_STRINGS_relative_time_to_string (search_timeout_time,
  706. GNUNET_NO));
  707. in_shutdown = GNUNET_YES;
  708. for (i = 0; i < num_peers; i++)
  709. {
  710. if (NULL != peers[i].op_handle)
  711. {
  712. GNUNET_TESTBED_operation_done (peers[i].op_handle);
  713. peers[i].op_handle = NULL;
  714. }
  715. }
  716. GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL);
  717. }
  718. /**
  719. * Search timed out. It might still complete in the future,
  720. * but we should start another one.
  721. *
  722. * @param cls Index of the next peer in the peers array.
  723. */
  724. static void
  725. find_timed_out (void *cls)
  726. {
  727. struct RegexPeer *p = cls;
  728. p->timeout = NULL;
  729. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  730. "Searching for string \"%s\" on peer %d timed out.\n",
  731. p->search_str,
  732. p->id);
  733. if (GNUNET_NO == in_shutdown)
  734. GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
  735. }
  736. /**
  737. * Start searching for a string in the DHT.
  738. *
  739. * @param cls Index of the next peer in the peers array.
  740. */
  741. static void
  742. find_string (void *cls)
  743. {
  744. unsigned int search_peer = (unsigned int) (long) cls;
  745. if ((search_peer >= num_peers) ||
  746. (GNUNET_YES == in_shutdown))
  747. return;
  748. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  749. "Searching for string \"%s\" on peer %d (%u||)\n",
  750. peers[search_peer].search_str,
  751. search_peer,
  752. parallel_searches);
  753. peers[search_peer].op_handle =
  754. GNUNET_TESTBED_service_connect (NULL,
  755. peers[search_peer].peer_handle,
  756. "dht",
  757. &dht_connect_cb,
  758. &peers[search_peer],
  759. &dht_ca,
  760. &dht_da,
  761. &peers[search_peer]);
  762. GNUNET_assert (NULL != peers[search_peer].op_handle);
  763. peers[search_peer].timeout
  764. = GNUNET_SCHEDULER_add_delayed (FIND_TIMEOUT,
  765. &find_timed_out,
  766. &peers[search_peer]);
  767. }
  768. /**
  769. * Callback called when testbed has started the daemon we asked for.
  770. *
  771. * @param cls NULL
  772. * @param op the operation handle
  773. * @param emsg NULL on success; otherwise an error description
  774. */
  775. static void
  776. daemon_started (void *cls,
  777. struct GNUNET_TESTBED_Operation *op,
  778. const char *emsg)
  779. {
  780. struct RegexPeer *peer = (struct RegexPeer *) cls;
  781. unsigned long search_peer;
  782. unsigned int i;
  783. GNUNET_TESTBED_operation_done (peer->daemon_op);
  784. peer->daemon_op = NULL;
  785. if (NULL != emsg)
  786. {
  787. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  788. "Failed to start/stop daemon at peer %u: %s\n", peer->id, emsg);
  789. GNUNET_assert (0);
  790. }
  791. else
  792. {
  793. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  794. "Deamon %u started successfully\n", peer->id);
  795. }
  796. /* Find a peer to look for a string matching the regex announced */
  797. search_peer = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
  798. num_peers);
  799. for (i = 0; peers[search_peer].search_str != NULL; i++)
  800. {
  801. search_peer = (search_peer + 1) % num_peers;
  802. if (i > num_peers)
  803. GNUNET_assert (0); /* we ran out of peers, must be a bug */
  804. }
  805. peers[search_peer].search_str = search_strings[peer->id];
  806. peers[search_peer].search_str_matched = GNUNET_NO;
  807. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_saturating_multiply (
  808. reannounce_period_max,
  809. 2),
  810. &find_string,
  811. (void *) search_peer);
  812. }
  813. /**
  814. * Task to start the daemons on each peer so that the regexes are announced
  815. * into the DHT.
  816. *
  817. * @param cls NULL
  818. * @param tc the task context
  819. */
  820. static void
  821. do_announce (void *cls)
  822. {
  823. unsigned int i;
  824. if (GNUNET_YES == in_shutdown)
  825. return;
  826. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  827. "Starting announce.\n");
  828. for (i = 0; i < init_parallel_searches; i++)
  829. {
  830. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  831. " scheduling announce %u\n",
  832. i);
  833. (void) GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
  834. }
  835. }
  836. /**
  837. * Start announcing the next regex in the DHT.
  838. *
  839. * @param cls Closure (unused).
  840. */
  841. static void
  842. announce_next_regex (void *cls)
  843. {
  844. struct RegexPeer *peer;
  845. if (GNUNET_YES == in_shutdown)
  846. return;
  847. if (next_search >= num_peers)
  848. {
  849. if (strings_found != num_peers)
  850. {
  851. struct GNUNET_TIME_Relative new_delay;
  852. if (NULL != search_timeout_task)
  853. GNUNET_SCHEDULER_cancel (search_timeout_task);
  854. new_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15);
  855. search_timeout_task = GNUNET_SCHEDULER_add_delayed (new_delay,
  856. &search_timed_out,
  857. NULL);
  858. }
  859. return;
  860. }
  861. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting daemon %u\n", next_search);
  862. peer = &peers[next_search];
  863. peer->daemon_op =
  864. GNUNET_TESTBED_peer_manage_service (NULL,
  865. peer->peer_handle,
  866. "regexprofiler",
  867. &daemon_started,
  868. peer,
  869. 1);
  870. next_search++;
  871. parallel_searches++;
  872. }
  873. /**
  874. * DHT connect callback. Called when we are connected to the dht service for
  875. * the peer in 'cls'. If successfull we connect to the stats service of this
  876. * peer and then try to match the search string of this peer.
  877. *
  878. * @param cls internal peer id.
  879. * @param op operation handle.
  880. * @param ca_result connect adapter result.
  881. * @param emsg error message.
  882. */
  883. static void
  884. dht_connect_cb (void *cls,
  885. struct GNUNET_TESTBED_Operation *op,
  886. void *ca_result,
  887. const char *emsg)
  888. {
  889. struct RegexPeer *peer = (struct RegexPeer *) cls;
  890. if ((NULL != emsg) || (NULL == op) || (NULL == ca_result))
  891. {
  892. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "DHT connect failed: %s\n", emsg);
  893. GNUNET_assert (0);
  894. }
  895. GNUNET_assert (NULL != peer->dht_handle);
  896. GNUNET_assert (peer->op_handle == op);
  897. GNUNET_assert (peer->dht_handle == ca_result);
  898. peer->search_str_matched = GNUNET_NO;
  899. peer->search_handle = REGEX_INTERNAL_search (peer->dht_handle,
  900. peer->search_str,
  901. &regex_found_handler, peer,
  902. NULL);
  903. peer->prof_start_time = GNUNET_TIME_absolute_get ();
  904. }
  905. /**
  906. * DHT connect adapter. Opens a connection to the dht service.
  907. *
  908. * @param cls Closure (peer).
  909. * @param cfg Configuration handle.
  910. *
  911. * @return
  912. */
  913. static void *
  914. dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
  915. {
  916. struct RegexPeer *peer = cls;
  917. peer->dht_handle = GNUNET_DHT_connect (cfg, 32);
  918. return peer->dht_handle;
  919. }
  920. /**
  921. * Adapter function called to destroy a connection to the dht service.
  922. *
  923. * @param cls Closure (peer).
  924. * @param op_result Service handle returned from the connect adapter.
  925. */
  926. static void
  927. dht_da (void *cls, void *op_result)
  928. {
  929. struct RegexPeer *peer = (struct RegexPeer *) cls;
  930. GNUNET_assert (peer->dht_handle == op_result);
  931. if (NULL != peer->search_handle)
  932. {
  933. REGEX_INTERNAL_search_cancel (peer->search_handle);
  934. peer->search_handle = NULL;
  935. }
  936. if (NULL != peer->dht_handle)
  937. {
  938. GNUNET_DHT_disconnect (peer->dht_handle);
  939. peer->dht_handle = NULL;
  940. }
  941. }
  942. /**
  943. * Signature of a main function for a testcase.
  944. *
  945. * @param cls NULL
  946. * @param h the run handle
  947. * @param num_peers_ number of peers in 'peers'
  948. * @param testbed_peers handle to peers run in the testbed. NULL upon timeout (see
  949. * GNUNET_TESTBED_test_run()).
  950. * @param links_succeeded the number of overlay link connection attempts that
  951. * succeeded
  952. * @param links_failed the number of overlay link connection attempts that
  953. * failed
  954. */
  955. static void
  956. test_master (void *cls,
  957. struct GNUNET_TESTBED_RunHandle *h,
  958. unsigned int num_peers_,
  959. struct GNUNET_TESTBED_Peer **testbed_peers,
  960. unsigned int links_succeeded,
  961. unsigned int links_failed)
  962. {
  963. unsigned int i;
  964. GNUNET_assert (num_peers_ == num_peers);
  965. prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
  966. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  967. "Testbed started in %s\n",
  968. GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
  969. if (NULL != abort_task)
  970. {
  971. GNUNET_SCHEDULER_cancel (abort_task);
  972. abort_task = NULL;
  973. }
  974. for (i = 0; i < num_peers; i++)
  975. {
  976. peers[i].peer_handle = testbed_peers[i];
  977. }
  978. if (GNUNET_NO ==
  979. GNUNET_CONFIGURATION_get_value_yesno (cfg, "DHT", "DISABLE_TRY_CONNECT"))
  980. {
  981. struct GNUNET_TIME_Relative settle_time;
  982. settle_time =
  983. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
  984. 10 * num_peers);
  985. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  986. "Waiting for DHT for %s to settle new connections.\n\n",
  987. GNUNET_STRINGS_relative_time_to_string (settle_time,
  988. GNUNET_NO));
  989. GNUNET_SCHEDULER_add_delayed (settle_time, &do_announce, NULL);
  990. }
  991. else
  992. {
  993. GNUNET_SCHEDULER_add_now (&do_announce, NULL);
  994. }
  995. search_timeout_task =
  996. GNUNET_SCHEDULER_add_delayed (search_timeout_time, &search_timed_out, NULL);
  997. }
  998. /**
  999. * Function that will be called whenever something in the testbed changes.
  1000. *
  1001. * @param cls closure, NULL
  1002. * @param event information on what is happening
  1003. */
  1004. static void
  1005. master_controller_cb (void *cls,
  1006. const struct GNUNET_TESTBED_EventInformation *event)
  1007. {
  1008. switch (event->type)
  1009. {
  1010. case GNUNET_TESTBED_ET_CONNECT:
  1011. printf (".");
  1012. break;
  1013. case GNUNET_TESTBED_ET_PEER_START:
  1014. printf ("#");
  1015. break;
  1016. default:
  1017. break;
  1018. }
  1019. fflush (stdout);
  1020. }
  1021. /******************************************************************************/
  1022. /*************************** TESTBED PEER SETUP *****************************/
  1023. /******************************************************************************/
  1024. /**
  1025. * Process the text buffer counting the non-empty lines and separating them
  1026. * with NULL characters, for later ease of copy using (as)printf.
  1027. *
  1028. * @param data Memory buffer with strings.
  1029. * @param data_size Size of the @a data buffer in bytes.
  1030. * @param str_max Maximum number of strings to return.
  1031. * @return Positive number of lines found in the buffer,
  1032. * #GNUNET_SYSERR otherwise.
  1033. */
  1034. static int
  1035. count_and_separate_strings (char *data,
  1036. uint64_t data_size,
  1037. unsigned int str_max)
  1038. {
  1039. char *buf; // Keep track of last string to skip blank lines
  1040. unsigned int offset;
  1041. unsigned int str_cnt;
  1042. buf = data;
  1043. offset = 0;
  1044. str_cnt = 0;
  1045. while ((offset < (data_size - 1)) && (str_cnt < str_max))
  1046. {
  1047. offset++;
  1048. if (((data[offset] == '\n')) &&
  1049. (buf != &data[offset]))
  1050. {
  1051. data[offset] = '\0';
  1052. str_cnt++;
  1053. buf = &data[offset + 1];
  1054. }
  1055. else if ((data[offset] == '\n') ||
  1056. (data[offset] == '\0'))
  1057. buf = &data[offset + 1];
  1058. }
  1059. return str_cnt;
  1060. }
  1061. /**
  1062. * Allocate a string array and fill it with the prefixed strings
  1063. * from a pre-processed, NULL-separated memory region.
  1064. *
  1065. * @param data Preprocessed memory with strings
  1066. * @param data_size Size of the @a data buffer in bytes.
  1067. * @param strings Address of the string array to be created.
  1068. * Must be freed by caller if function end in success.
  1069. * @param str_cnt String count. The @a data buffer should contain
  1070. * at least this many NULL-separated strings.
  1071. * @return #GNUNET_OK in ase of success, #GNUNET_SYSERR otherwise.
  1072. * In case of error @a strings must not be freed.
  1073. */
  1074. static int
  1075. create_string_array (char *data, uint64_t data_size,
  1076. char ***strings, unsigned int str_cnt)
  1077. {
  1078. uint64_t offset;
  1079. uint64_t len;
  1080. unsigned int i;
  1081. *strings = GNUNET_malloc (sizeof(char *) * str_cnt);
  1082. offset = 0;
  1083. for (i = 0; i < str_cnt; i++)
  1084. {
  1085. len = strlen (&data[offset]);
  1086. if (offset + len >= data_size)
  1087. {
  1088. GNUNET_free (*strings);
  1089. *strings = NULL;
  1090. return GNUNET_SYSERR;
  1091. }
  1092. if (0 == len) // empty line
  1093. {
  1094. offset++;
  1095. i--;
  1096. continue;
  1097. }
  1098. GNUNET_asprintf (&(*strings)[i],
  1099. "%s%s",
  1100. regex_prefix,
  1101. &data[offset]);
  1102. offset += len + 1;
  1103. }
  1104. return GNUNET_OK;
  1105. }
  1106. /**
  1107. * Load search strings from given filename. One search string per line.
  1108. *
  1109. * @param filename filename of the file containing the search strings.
  1110. * @param strings set of strings loaded from file. Caller needs to free this
  1111. * if number returned is greater than zero.
  1112. * @param limit upper limit on the number of strings read from the file
  1113. * @return number of strings found in the file. #GNUNET_SYSERR on error.
  1114. */
  1115. static int
  1116. load_search_strings (const char *filename,
  1117. char ***strings,
  1118. unsigned int limit)
  1119. {
  1120. char *data;
  1121. uint64_t filesize;
  1122. int str_cnt;
  1123. /* Sanity checks */
  1124. if (NULL == filename)
  1125. {
  1126. return GNUNET_SYSERR;
  1127. }
  1128. if (GNUNET_YES != GNUNET_DISK_file_test (filename))
  1129. {
  1130. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1131. "Could not find search strings file %s\n", filename);
  1132. return GNUNET_SYSERR;
  1133. }
  1134. if (GNUNET_OK !=
  1135. GNUNET_DISK_file_size (filename,
  1136. &filesize,
  1137. GNUNET_YES,
  1138. GNUNET_YES))
  1139. {
  1140. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1141. "Search strings file %s cannot be read.\n",
  1142. filename);
  1143. return GNUNET_SYSERR;
  1144. }
  1145. if (0 == filesize)
  1146. {
  1147. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1148. "Search strings file %s is empty.\n",
  1149. filename);
  1150. return GNUNET_SYSERR;
  1151. }
  1152. /* Read data into memory */
  1153. data = GNUNET_malloc (filesize + 1);
  1154. if (filesize != GNUNET_DISK_fn_read (filename,
  1155. data,
  1156. filesize))
  1157. {
  1158. GNUNET_free (data);
  1159. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1160. "Could not read search strings file %s.\n",
  1161. filename);
  1162. return GNUNET_SYSERR;
  1163. }
  1164. /* Process buffer and build array */
  1165. str_cnt = count_and_separate_strings (data, filesize, limit);
  1166. if (GNUNET_OK != create_string_array (data, filesize, strings, str_cnt))
  1167. {
  1168. str_cnt = GNUNET_SYSERR;
  1169. }
  1170. GNUNET_free (data);
  1171. return str_cnt;
  1172. }
  1173. /**
  1174. * Main function that will be run by the scheduler.
  1175. *
  1176. * @param cls closure
  1177. * @param args remaining command-line arguments
  1178. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  1179. * @param config configuration
  1180. */
  1181. static void
  1182. run (void *cls,
  1183. char *const *args,
  1184. const char *cfgfile,
  1185. const struct GNUNET_CONFIGURATION_Handle *config)
  1186. {
  1187. unsigned int nsearchstrs;
  1188. unsigned int i;
  1189. struct GNUNET_TIME_Relative abort_time;
  1190. in_shutdown = GNUNET_NO;
  1191. /* Check config */
  1192. if (NULL == config)
  1193. {
  1194. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1195. _ ("No configuration file given. Exiting\n"));
  1196. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1197. return;
  1198. }
  1199. cfg = GNUNET_CONFIGURATION_dup (config);
  1200. if (GNUNET_OK !=
  1201. GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER",
  1202. "REGEX_PREFIX",
  1203. &regex_prefix))
  1204. {
  1205. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  1206. "regexprofiler",
  1207. "regex_prefix");
  1208. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1209. return;
  1210. }
  1211. if (GNUNET_OK !=
  1212. GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER",
  1213. "PARALLEL_SEARCHES",
  1214. &init_parallel_searches))
  1215. {
  1216. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1217. "Configuration option \"PARALLEL_SEARCHES\" missing."
  1218. " Using default (%d)\n", 10);
  1219. init_parallel_searches = 10;
  1220. }
  1221. if (GNUNET_OK !=
  1222. GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER",
  1223. "REANNOUNCE_PERIOD_MAX",
  1224. &reannounce_period_max))
  1225. {
  1226. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1227. "reannounce_period_max not given. Using 10 minutes.\n");
  1228. reannounce_period_max =
  1229. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10);
  1230. }
  1231. /* Check arguments */
  1232. if (NULL == policy_dir)
  1233. {
  1234. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1235. _ (
  1236. "No policy directory specified on command line. Exiting.\n"));
  1237. return;
  1238. }
  1239. if (GNUNET_YES != GNUNET_DISK_directory_test (policy_dir, GNUNET_YES))
  1240. {
  1241. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1242. _ ("Specified policies directory does not exist. Exiting.\n"));
  1243. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1244. return;
  1245. }
  1246. if (0 >= (int) (num_peers = GNUNET_DISK_directory_scan (policy_dir, NULL,
  1247. NULL)))
  1248. {
  1249. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1250. _ ("No files found in `%s'\n"),
  1251. policy_dir);
  1252. return;
  1253. }
  1254. GNUNET_CONFIGURATION_set_value_string (cfg, "REGEXPROFILER",
  1255. "POLICY_DIR", policy_dir);
  1256. if (GNUNET_YES != GNUNET_DISK_file_test (strings_file))
  1257. {
  1258. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1259. _ ("No search strings file given. Exiting.\n"));
  1260. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1261. return;
  1262. }
  1263. nsearchstrs = load_search_strings (strings_file,
  1264. &search_strings,
  1265. num_peers);
  1266. if (num_peers != nsearchstrs)
  1267. {
  1268. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1269. "Error loading search strings.\n");
  1270. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1271. "File (%s) does not contain enough strings (%u/%u).\n",
  1272. strings_file, nsearchstrs, num_peers);
  1273. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1274. return;
  1275. }
  1276. if ((0 == num_peers) || (NULL == search_strings))
  1277. {
  1278. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1279. _ ("Error loading search strings. Exiting.\n"));
  1280. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1281. return;
  1282. }
  1283. for (i = 0; i < num_peers; i++)
  1284. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1285. "search string: %s\n",
  1286. search_strings[i]);
  1287. /* Check logfile */
  1288. if ((NULL != data_filename) &&
  1289. (NULL == (data_file =
  1290. GNUNET_DISK_file_open (data_filename,
  1291. GNUNET_DISK_OPEN_READWRITE
  1292. | GNUNET_DISK_OPEN_TRUNCATE
  1293. | GNUNET_DISK_OPEN_CREATE,
  1294. GNUNET_DISK_PERM_USER_READ
  1295. | GNUNET_DISK_PERM_USER_WRITE))))
  1296. {
  1297. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  1298. "open",
  1299. data_filename);
  1300. return;
  1301. }
  1302. /* Initialize peers */
  1303. peers = GNUNET_malloc (sizeof(struct RegexPeer) * num_peers);
  1304. for (i = 0; i < num_peers; i++)
  1305. peers[i].id = i;
  1306. GNUNET_CONFIGURATION_set_value_number (cfg,
  1307. "TESTBED", "OVERLAY_RANDOM_LINKS",
  1308. num_peers * 20);
  1309. GNUNET_CONFIGURATION_set_value_number (cfg,
  1310. "DHT", "FORCE_NSE",
  1311. (long long unsigned)
  1312. (log (num_peers) / log (2.0)));
  1313. event_mask = 0LL;
  1314. /* For feedback about the start process activate these and pass master_cb */
  1315. event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
  1316. // event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
  1317. event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
  1318. // event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT);
  1319. prof_start_time = GNUNET_TIME_absolute_get ();
  1320. GNUNET_TESTBED_run (hosts_file,
  1321. cfg,
  1322. num_peers,
  1323. event_mask,
  1324. &master_controller_cb,
  1325. NULL, /* master_controller_cb cls */
  1326. &test_master,
  1327. NULL); /* test_master cls */
  1328. if (GNUNET_OK !=
  1329. GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
  1330. "SETUP_TIMEOUT",
  1331. &abort_time))
  1332. {
  1333. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1334. "SETUP_TIMEOUT not given. Using 15 minutes.\n");
  1335. abort_time =
  1336. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15);
  1337. }
  1338. abort_time = GNUNET_TIME_relative_add (abort_time, GNUNET_TIME_UNIT_MINUTES);
  1339. abort_task =
  1340. GNUNET_SCHEDULER_add_delayed (abort_time,
  1341. &do_abort,
  1342. (void *) __LINE__);
  1343. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1344. "setup_timeout: %s\n",
  1345. GNUNET_STRINGS_relative_time_to_string (abort_time, GNUNET_YES));
  1346. }
  1347. /**
  1348. * Main function.
  1349. *
  1350. * @param argc argument count
  1351. * @param argv argument values
  1352. * @return 0 on success
  1353. */
  1354. int
  1355. main (int argc, char *const *argv)
  1356. {
  1357. struct GNUNET_GETOPT_CommandLineOption options[] = {
  1358. GNUNET_GETOPT_option_filename ('o',
  1359. "output-file",
  1360. "FILENAME",
  1361. gettext_noop (
  1362. "name of the file for writing statistics"),
  1363. &data_filename),
  1364. GNUNET_GETOPT_option_relative_time ('t',
  1365. "matching-timeout",
  1366. "TIMEOUT",
  1367. gettext_noop (
  1368. "wait TIMEOUT before ending the experiment"),
  1369. &search_timeout_time),
  1370. GNUNET_GETOPT_option_filename ('p',
  1371. "policy-dir",
  1372. "DIRECTORY",
  1373. gettext_noop ("directory with policy files"),
  1374. &policy_dir),
  1375. GNUNET_GETOPT_option_filename ('s',
  1376. "strings-file",
  1377. "FILENAME",
  1378. gettext_noop (
  1379. "name of file with input strings"),
  1380. &strings_file),
  1381. GNUNET_GETOPT_option_filename ('H',
  1382. "hosts-file",
  1383. "FILENAME",
  1384. gettext_noop (
  1385. "name of file with hosts' names"),
  1386. &hosts_file),
  1387. GNUNET_GETOPT_OPTION_END
  1388. };
  1389. int ret;
  1390. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  1391. return 2;
  1392. result = GNUNET_SYSERR;
  1393. ret =
  1394. GNUNET_PROGRAM_run (argc, argv,
  1395. "gnunet-regex-profiler",
  1396. _ ("Profiler for regex"),
  1397. options, &run, NULL);
  1398. if (GNUNET_OK != ret)
  1399. return ret;
  1400. if (GNUNET_OK != result)
  1401. return 1;
  1402. return 0;
  1403. }