2
0

gnunet-regex-profiler.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613
  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. * Daemon 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,
  481. (unsigned long long) value,
  482. name);
  483. if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
  484. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  485. "Unable to write to file!\n");
  486. return GNUNET_OK;
  487. }
  488. /**
  489. * Stats callback. Finish the stats testbed operation and when all stats have
  490. * been iterated, shutdown the profiler.
  491. *
  492. * @param cls closure
  493. * @param success GNUNET_OK if statistics were
  494. * successfully obtained, GNUNET_SYSERR if not.
  495. */
  496. static void
  497. stats_cb (void *cls,
  498. int success)
  499. {
  500. static unsigned int peer_cnt;
  501. struct RegexPeer *peer = cls;
  502. if (GNUNET_OK != success)
  503. {
  504. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  505. "Getting statistics for peer %u failed!\n",
  506. peer->id);
  507. return;
  508. }
  509. GNUNET_assert (NULL != peer->op_handle);
  510. GNUNET_TESTBED_operation_done (peer->op_handle);
  511. peer->op_handle = NULL;
  512. peer_cnt++;
  513. peer = &peers[peer_cnt];
  514. fprintf (stderr, "s");
  515. if (peer_cnt == num_peers)
  516. {
  517. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  518. "\nCollecting stats finished. Shutting down.\n");
  519. GNUNET_SCHEDULER_shutdown ();
  520. result = GNUNET_OK;
  521. }
  522. else
  523. {
  524. peer->op_handle =
  525. GNUNET_TESTBED_service_connect (NULL,
  526. peer->peer_handle,
  527. "statistics",
  528. &stats_connect_cb,
  529. peer,
  530. &stats_ca,
  531. &stats_da,
  532. peer);
  533. }
  534. }
  535. /**
  536. * Function called by testbed once we are connected to stats
  537. * service. Get the statistics for the services of interest.
  538. *
  539. * @param cls the 'struct RegexPeer' for which we connected to stats
  540. * @param op connect operation handle
  541. * @param ca_result handle to stats service
  542. * @param emsg error message on failure
  543. */
  544. static void
  545. stats_connect_cb (void *cls,
  546. struct GNUNET_TESTBED_Operation *op,
  547. void *ca_result,
  548. const char *emsg)
  549. {
  550. struct RegexPeer *peer = cls;
  551. if ((NULL == ca_result) || (NULL != emsg))
  552. {
  553. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  554. "Failed to connect to statistics service on peer %u: %s\n",
  555. peer->id, emsg);
  556. peer->stats_handle = NULL;
  557. return;
  558. }
  559. peer->stats_handle = ca_result;
  560. if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, NULL, NULL,
  561. &stats_cb,
  562. &stats_iterator, peer))
  563. {
  564. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  565. "Could not get statistics of peer %u!\n", peer->id);
  566. }
  567. }
  568. /**
  569. * Task to collect all statistics from all peers, will shutdown the
  570. * profiler, when done.
  571. *
  572. * @param cls NULL
  573. */
  574. static void
  575. do_collect_stats (void *cls)
  576. {
  577. struct RegexPeer *peer = &peers[0];
  578. GNUNET_assert (NULL != peer->peer_handle);
  579. peer->op_handle =
  580. GNUNET_TESTBED_service_connect (NULL,
  581. peer->peer_handle,
  582. "statistics",
  583. &stats_connect_cb,
  584. peer,
  585. &stats_ca,
  586. &stats_da,
  587. peer);
  588. }
  589. /******************************************************************************/
  590. /************************ REGEX FIND CONNECTIONS **************************/
  591. /******************************************************************************/
  592. /**
  593. * Start searching for the next string in the DHT.
  594. *
  595. * @param cls Index of the next peer in the peers array.
  596. */
  597. static void
  598. find_string (void *cls);
  599. /**
  600. * Method called when we've found a peer that announced a regex
  601. * that matches our search string. Now get the statistics.
  602. *
  603. * @param cls Closure provided in REGEX_INTERNAL_search.
  604. * @param id Peer providing a regex that matches the string.
  605. * @param get_path Path of the get request.
  606. * @param get_path_length Length of get_path.
  607. * @param put_path Path of the put request.
  608. * @param put_path_length Length of the put_path.
  609. */
  610. static void
  611. regex_found_handler (void *cls,
  612. const struct GNUNET_PeerIdentity *id,
  613. const struct GNUNET_PeerIdentity *get_path,
  614. unsigned int get_path_length,
  615. const struct GNUNET_PeerIdentity *put_path,
  616. unsigned int put_path_length)
  617. {
  618. struct RegexPeer *peer = cls;
  619. char output_buffer[512];
  620. size_t size;
  621. if (GNUNET_YES == peer->search_str_matched)
  622. {
  623. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  624. "String %s on peer %u already matched!\n",
  625. peer->search_str, peer->id);
  626. return;
  627. }
  628. strings_found++;
  629. parallel_searches--;
  630. if (NULL != peer->timeout)
  631. {
  632. GNUNET_SCHEDULER_cancel (peer->timeout);
  633. peer->timeout = NULL;
  634. if (GNUNET_NO == in_shutdown)
  635. GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
  636. }
  637. if (NULL == id)
  638. {
  639. // FIXME not possible right now
  640. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  641. "String matching timed out for string %s on peer %u (%i/%i)\n",
  642. peer->search_str, peer->id, strings_found, num_peers);
  643. peer->search_str_matched = GNUNET_SYSERR;
  644. }
  645. else
  646. {
  647. prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time);
  648. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  649. "String %s found on peer %u after %s (%i/%i) (%u||)\n",
  650. peer->search_str, peer->id,
  651. GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO),
  652. strings_found, num_peers, parallel_searches);
  653. peer->search_str_matched = GNUNET_YES;
  654. if (NULL != data_file)
  655. {
  656. size =
  657. GNUNET_snprintf (output_buffer,
  658. sizeof(output_buffer),
  659. "%p Peer: %u\n"
  660. "%p Search string: %s\n"
  661. "%p Search duration: %s\n\n",
  662. peer, peer->id,
  663. peer, peer->search_str,
  664. peer,
  665. GNUNET_STRINGS_relative_time_to_string (prof_time,
  666. GNUNET_NO));
  667. if (size != GNUNET_DISK_file_write (data_file, output_buffer, size))
  668. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
  669. }
  670. }
  671. GNUNET_TESTBED_operation_done (peer->op_handle);
  672. peer->op_handle = NULL;
  673. if (strings_found == num_peers)
  674. {
  675. prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
  676. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  677. "All strings successfully matched in %s\n",
  678. GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
  679. if (NULL != search_timeout_task)
  680. {
  681. GNUNET_SCHEDULER_cancel (search_timeout_task);
  682. search_timeout_task = NULL;
  683. }
  684. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Collecting stats.\n");
  685. GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL);
  686. }
  687. }
  688. /**
  689. * Connect by string timeout task. This will cancel the profiler after the
  690. * specified timeout 'search_timeout'.
  691. *
  692. * @param cls NULL
  693. */
  694. static void
  695. search_timed_out (void *cls)
  696. {
  697. unsigned int i;
  698. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  699. "Finding matches to all strings did not succeed after %s.\n",
  700. GNUNET_STRINGS_relative_time_to_string (search_timeout_time,
  701. GNUNET_NO));
  702. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  703. "Found %i of %i strings\n", strings_found, num_peers);
  704. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  705. "Search timed out after %s."
  706. "Collecting stats and shutting down.\n",
  707. GNUNET_STRINGS_relative_time_to_string (search_timeout_time,
  708. GNUNET_NO));
  709. in_shutdown = GNUNET_YES;
  710. for (i = 0; i < num_peers; i++)
  711. {
  712. if (NULL != peers[i].op_handle)
  713. {
  714. GNUNET_TESTBED_operation_done (peers[i].op_handle);
  715. peers[i].op_handle = NULL;
  716. }
  717. }
  718. GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL);
  719. }
  720. /**
  721. * Search timed out. It might still complete in the future,
  722. * but we should start another one.
  723. *
  724. * @param cls Index of the next peer in the peers array.
  725. */
  726. static void
  727. find_timed_out (void *cls)
  728. {
  729. struct RegexPeer *p = cls;
  730. p->timeout = NULL;
  731. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  732. "Searching for string \"%s\" on peer %d timed out.\n",
  733. p->search_str,
  734. p->id);
  735. if (GNUNET_NO == in_shutdown)
  736. GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
  737. }
  738. /**
  739. * Start searching for a string in the DHT.
  740. *
  741. * @param cls Index of the next peer in the peers array.
  742. */
  743. static void
  744. find_string (void *cls)
  745. {
  746. unsigned int search_peer = (unsigned int) (long) cls;
  747. if ((search_peer >= num_peers) ||
  748. (GNUNET_YES == in_shutdown))
  749. return;
  750. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  751. "Searching for string \"%s\" on peer %d (%u||)\n",
  752. peers[search_peer].search_str,
  753. search_peer,
  754. parallel_searches);
  755. peers[search_peer].op_handle =
  756. GNUNET_TESTBED_service_connect (NULL,
  757. peers[search_peer].peer_handle,
  758. "dht",
  759. &dht_connect_cb,
  760. &peers[search_peer],
  761. &dht_ca,
  762. &dht_da,
  763. &peers[search_peer]);
  764. GNUNET_assert (NULL != peers[search_peer].op_handle);
  765. peers[search_peer].timeout
  766. = GNUNET_SCHEDULER_add_delayed (FIND_TIMEOUT,
  767. &find_timed_out,
  768. &peers[search_peer]);
  769. }
  770. /**
  771. * Callback called when testbed has started the daemon we asked for.
  772. *
  773. * @param cls NULL
  774. * @param op the operation handle
  775. * @param emsg NULL on success; otherwise an error description
  776. */
  777. static void
  778. daemon_started (void *cls,
  779. struct GNUNET_TESTBED_Operation *op,
  780. const char *emsg)
  781. {
  782. struct RegexPeer *peer = (struct RegexPeer *) cls;
  783. unsigned long search_peer;
  784. unsigned int i;
  785. GNUNET_TESTBED_operation_done (peer->daemon_op);
  786. peer->daemon_op = NULL;
  787. if (NULL != emsg)
  788. {
  789. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  790. "Failed to start/stop daemon at peer %u: %s\n", peer->id, emsg);
  791. GNUNET_assert (0);
  792. }
  793. else
  794. {
  795. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  796. "Daemon %u started successfully\n", peer->id);
  797. }
  798. /* Find a peer to look for a string matching the regex announced */
  799. search_peer = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
  800. num_peers);
  801. for (i = 0; peers[search_peer].search_str != NULL; i++)
  802. {
  803. search_peer = (search_peer + 1) % num_peers;
  804. if (i > num_peers)
  805. GNUNET_assert (0); /* we ran out of peers, must be a bug */
  806. }
  807. peers[search_peer].search_str = search_strings[peer->id];
  808. peers[search_peer].search_str_matched = GNUNET_NO;
  809. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_saturating_multiply (
  810. reannounce_period_max,
  811. 2),
  812. &find_string,
  813. (void *) search_peer);
  814. }
  815. /**
  816. * Task to start the daemons on each peer so that the regexes are announced
  817. * into the DHT.
  818. *
  819. * @param cls NULL
  820. * @param tc the task context
  821. */
  822. static void
  823. do_announce (void *cls)
  824. {
  825. unsigned int i;
  826. if (GNUNET_YES == in_shutdown)
  827. return;
  828. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  829. "Starting announce.\n");
  830. for (i = 0; i < init_parallel_searches; i++)
  831. {
  832. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  833. " scheduling announce %u\n",
  834. i);
  835. (void) GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL);
  836. }
  837. }
  838. /**
  839. * Start announcing the next regex in the DHT.
  840. *
  841. * @param cls Closure (unused).
  842. */
  843. static void
  844. announce_next_regex (void *cls)
  845. {
  846. struct RegexPeer *peer;
  847. if (GNUNET_YES == in_shutdown)
  848. return;
  849. if (next_search >= num_peers)
  850. {
  851. if (strings_found != num_peers)
  852. {
  853. struct GNUNET_TIME_Relative new_delay;
  854. if (NULL != search_timeout_task)
  855. GNUNET_SCHEDULER_cancel (search_timeout_task);
  856. new_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15);
  857. search_timeout_task = GNUNET_SCHEDULER_add_delayed (new_delay,
  858. &search_timed_out,
  859. NULL);
  860. }
  861. return;
  862. }
  863. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting daemon %u\n", next_search);
  864. peer = &peers[next_search];
  865. peer->daemon_op =
  866. GNUNET_TESTBED_peer_manage_service (NULL,
  867. peer->peer_handle,
  868. "regexprofiler",
  869. &daemon_started,
  870. peer,
  871. 1);
  872. next_search++;
  873. parallel_searches++;
  874. }
  875. /**
  876. * DHT connect callback. Called when we are connected to the dht service for
  877. * the peer in 'cls'. If successful we connect to the stats service of this
  878. * peer and then try to match the search string of this peer.
  879. *
  880. * @param cls internal peer id.
  881. * @param op operation handle.
  882. * @param ca_result connect adapter result.
  883. * @param emsg error message.
  884. */
  885. static void
  886. dht_connect_cb (void *cls,
  887. struct GNUNET_TESTBED_Operation *op,
  888. void *ca_result,
  889. const char *emsg)
  890. {
  891. struct RegexPeer *peer = (struct RegexPeer *) cls;
  892. if ((NULL != emsg) || (NULL == op) || (NULL == ca_result))
  893. {
  894. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "DHT connect failed: %s\n", emsg);
  895. GNUNET_assert (0);
  896. }
  897. GNUNET_assert (NULL != peer->dht_handle);
  898. GNUNET_assert (peer->op_handle == op);
  899. GNUNET_assert (peer->dht_handle == ca_result);
  900. peer->search_str_matched = GNUNET_NO;
  901. peer->search_handle = REGEX_INTERNAL_search (peer->dht_handle,
  902. peer->search_str,
  903. &regex_found_handler, peer,
  904. NULL);
  905. peer->prof_start_time = GNUNET_TIME_absolute_get ();
  906. }
  907. /**
  908. * DHT connect adapter. Opens a connection to the dht service.
  909. *
  910. * @param cls Closure (peer).
  911. * @param cfg Configuration handle.
  912. *
  913. * @return
  914. */
  915. static void *
  916. dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
  917. {
  918. struct RegexPeer *peer = cls;
  919. peer->dht_handle = GNUNET_DHT_connect (cfg, 32);
  920. return peer->dht_handle;
  921. }
  922. /**
  923. * Adapter function called to destroy a connection to the dht service.
  924. *
  925. * @param cls Closure (peer).
  926. * @param op_result Service handle returned from the connect adapter.
  927. */
  928. static void
  929. dht_da (void *cls, void *op_result)
  930. {
  931. struct RegexPeer *peer = (struct RegexPeer *) cls;
  932. GNUNET_assert (peer->dht_handle == op_result);
  933. if (NULL != peer->search_handle)
  934. {
  935. REGEX_INTERNAL_search_cancel (peer->search_handle);
  936. peer->search_handle = NULL;
  937. }
  938. if (NULL != peer->dht_handle)
  939. {
  940. GNUNET_DHT_disconnect (peer->dht_handle);
  941. peer->dht_handle = NULL;
  942. }
  943. }
  944. /**
  945. * Signature of a main function for a testcase.
  946. *
  947. * @param cls NULL
  948. * @param h the run handle
  949. * @param num_peers_ number of peers in 'peers'
  950. * @param testbed_peers handle to peers run in the testbed. NULL upon timeout (see
  951. * GNUNET_TESTBED_test_run()).
  952. * @param links_succeeded the number of overlay link connection attempts that
  953. * succeeded
  954. * @param links_failed the number of overlay link connection attempts that
  955. * failed
  956. */
  957. static void
  958. test_master (void *cls,
  959. struct GNUNET_TESTBED_RunHandle *h,
  960. unsigned int num_peers_,
  961. struct GNUNET_TESTBED_Peer **testbed_peers,
  962. unsigned int links_succeeded,
  963. unsigned int links_failed)
  964. {
  965. unsigned int i;
  966. GNUNET_assert (num_peers_ == num_peers);
  967. prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time);
  968. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  969. "Testbed started in %s\n",
  970. GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO));
  971. if (NULL != abort_task)
  972. {
  973. GNUNET_SCHEDULER_cancel (abort_task);
  974. abort_task = NULL;
  975. }
  976. for (i = 0; i < num_peers; i++)
  977. {
  978. peers[i].peer_handle = testbed_peers[i];
  979. }
  980. if (GNUNET_NO ==
  981. GNUNET_CONFIGURATION_get_value_yesno (cfg, "DHT", "DISABLE_TRY_CONNECT"))
  982. {
  983. struct GNUNET_TIME_Relative settle_time;
  984. settle_time =
  985. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
  986. 10 * num_peers);
  987. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  988. "Waiting for DHT for %s to settle new connections.\n\n",
  989. GNUNET_STRINGS_relative_time_to_string (settle_time,
  990. GNUNET_NO));
  991. GNUNET_SCHEDULER_add_delayed (settle_time, &do_announce, NULL);
  992. }
  993. else
  994. {
  995. GNUNET_SCHEDULER_add_now (&do_announce, NULL);
  996. }
  997. search_timeout_task =
  998. GNUNET_SCHEDULER_add_delayed (search_timeout_time, &search_timed_out, NULL);
  999. }
  1000. /**
  1001. * Function that will be called whenever something in the testbed changes.
  1002. *
  1003. * @param cls closure, NULL
  1004. * @param event information on what is happening
  1005. */
  1006. static void
  1007. master_controller_cb (void *cls,
  1008. const struct GNUNET_TESTBED_EventInformation *event)
  1009. {
  1010. switch (event->type)
  1011. {
  1012. case GNUNET_TESTBED_ET_CONNECT:
  1013. printf (".");
  1014. break;
  1015. case GNUNET_TESTBED_ET_PEER_START:
  1016. printf ("#");
  1017. break;
  1018. default:
  1019. break;
  1020. }
  1021. fflush (stdout);
  1022. }
  1023. /******************************************************************************/
  1024. /*************************** TESTBED PEER SETUP *****************************/
  1025. /******************************************************************************/
  1026. /**
  1027. * Process the text buffer counting the non-empty lines and separating them
  1028. * with NULL characters, for later ease of copy using (as)printf.
  1029. *
  1030. * @param data Memory buffer with strings.
  1031. * @param data_size Size of the @a data buffer in bytes.
  1032. * @param str_max Maximum number of strings to return.
  1033. * @return Positive number of lines found in the buffer,
  1034. * #GNUNET_SYSERR otherwise.
  1035. */
  1036. static int
  1037. count_and_separate_strings (char *data,
  1038. uint64_t data_size,
  1039. unsigned int str_max)
  1040. {
  1041. char *buf; // Keep track of last string to skip blank lines
  1042. unsigned int offset;
  1043. unsigned int str_cnt;
  1044. buf = data;
  1045. offset = 0;
  1046. str_cnt = 0;
  1047. while ((offset < (data_size - 1)) && (str_cnt < str_max))
  1048. {
  1049. offset++;
  1050. if (((data[offset] == '\n')) &&
  1051. (buf != &data[offset]))
  1052. {
  1053. data[offset] = '\0';
  1054. str_cnt++;
  1055. buf = &data[offset + 1];
  1056. }
  1057. else if ((data[offset] == '\n') ||
  1058. (data[offset] == '\0'))
  1059. buf = &data[offset + 1];
  1060. }
  1061. return str_cnt;
  1062. }
  1063. /**
  1064. * Allocate a string array and fill it with the prefixed strings
  1065. * from a pre-processed, NULL-separated memory region.
  1066. *
  1067. * @param data Preprocessed memory with strings
  1068. * @param data_size Size of the @a data buffer in bytes.
  1069. * @param strings Address of the string array to be created.
  1070. * Must be freed by caller if function end in success.
  1071. * @param str_cnt String count. The @a data buffer should contain
  1072. * at least this many NULL-separated strings.
  1073. * @return #GNUNET_OK in ase of success, #GNUNET_SYSERR otherwise.
  1074. * In case of error @a strings must not be freed.
  1075. */
  1076. static int
  1077. create_string_array (char *data, uint64_t data_size,
  1078. char ***strings, unsigned int str_cnt)
  1079. {
  1080. uint64_t offset;
  1081. uint64_t len;
  1082. unsigned int i;
  1083. *strings = GNUNET_malloc (sizeof(char *) * str_cnt);
  1084. offset = 0;
  1085. for (i = 0; i < str_cnt; i++)
  1086. {
  1087. len = strlen (&data[offset]);
  1088. if (offset + len >= data_size)
  1089. {
  1090. GNUNET_free (*strings);
  1091. *strings = NULL;
  1092. return GNUNET_SYSERR;
  1093. }
  1094. if (0 == len) // empty line
  1095. {
  1096. offset++;
  1097. i--;
  1098. continue;
  1099. }
  1100. GNUNET_asprintf (&(*strings)[i],
  1101. "%s%s",
  1102. regex_prefix,
  1103. &data[offset]);
  1104. offset += len + 1;
  1105. }
  1106. return GNUNET_OK;
  1107. }
  1108. /**
  1109. * Load search strings from given filename. One search string per line.
  1110. *
  1111. * @param filename filename of the file containing the search strings.
  1112. * @param strings set of strings loaded from file. Caller needs to free this
  1113. * if number returned is greater than zero.
  1114. * @param limit upper limit on the number of strings read from the file
  1115. * @return number of strings found in the file. #GNUNET_SYSERR on error.
  1116. */
  1117. static int
  1118. load_search_strings (const char *filename,
  1119. char ***strings,
  1120. unsigned int limit)
  1121. {
  1122. char *data;
  1123. uint64_t filesize;
  1124. int str_cnt;
  1125. /* Sanity checks */
  1126. if (NULL == filename)
  1127. {
  1128. return GNUNET_SYSERR;
  1129. }
  1130. if (GNUNET_YES != GNUNET_DISK_file_test (filename))
  1131. {
  1132. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1133. "Could not find search strings file %s\n", filename);
  1134. return GNUNET_SYSERR;
  1135. }
  1136. if (GNUNET_OK !=
  1137. GNUNET_DISK_file_size (filename,
  1138. &filesize,
  1139. GNUNET_YES,
  1140. GNUNET_YES))
  1141. {
  1142. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1143. "Search strings file %s cannot be read.\n",
  1144. filename);
  1145. return GNUNET_SYSERR;
  1146. }
  1147. if (0 == filesize)
  1148. {
  1149. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1150. "Search strings file %s is empty.\n",
  1151. filename);
  1152. return GNUNET_SYSERR;
  1153. }
  1154. /* Read data into memory */
  1155. data = GNUNET_malloc (filesize + 1);
  1156. if (filesize != GNUNET_DISK_fn_read (filename,
  1157. data,
  1158. filesize))
  1159. {
  1160. GNUNET_free (data);
  1161. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1162. "Could not read search strings file %s.\n",
  1163. filename);
  1164. return GNUNET_SYSERR;
  1165. }
  1166. /* Process buffer and build array */
  1167. str_cnt = count_and_separate_strings (data, filesize, limit);
  1168. if (GNUNET_OK != create_string_array (data, filesize, strings, str_cnt))
  1169. {
  1170. str_cnt = GNUNET_SYSERR;
  1171. }
  1172. GNUNET_free (data);
  1173. return str_cnt;
  1174. }
  1175. /**
  1176. * Main function that will be run by the scheduler.
  1177. *
  1178. * @param cls closure
  1179. * @param args remaining command-line arguments
  1180. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  1181. * @param config configuration
  1182. */
  1183. static void
  1184. run (void *cls,
  1185. char *const *args,
  1186. const char *cfgfile,
  1187. const struct GNUNET_CONFIGURATION_Handle *config)
  1188. {
  1189. unsigned int nsearchstrs;
  1190. unsigned int i;
  1191. struct GNUNET_TIME_Relative abort_time;
  1192. in_shutdown = GNUNET_NO;
  1193. /* Check config */
  1194. if (NULL == config)
  1195. {
  1196. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1197. _ ("No configuration file given. Exiting\n"));
  1198. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1199. return;
  1200. }
  1201. cfg = GNUNET_CONFIGURATION_dup (config);
  1202. if (GNUNET_OK !=
  1203. GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER",
  1204. "REGEX_PREFIX",
  1205. &regex_prefix))
  1206. {
  1207. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  1208. "regexprofiler",
  1209. "regex_prefix");
  1210. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1211. return;
  1212. }
  1213. if (GNUNET_OK !=
  1214. GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER",
  1215. "PARALLEL_SEARCHES",
  1216. &init_parallel_searches))
  1217. {
  1218. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1219. "Configuration option \"PARALLEL_SEARCHES\" missing."
  1220. " Using default (%d)\n", 10);
  1221. init_parallel_searches = 10;
  1222. }
  1223. if (GNUNET_OK !=
  1224. GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER",
  1225. "REANNOUNCE_PERIOD_MAX",
  1226. &reannounce_period_max))
  1227. {
  1228. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1229. "reannounce_period_max not given. Using 10 minutes.\n");
  1230. reannounce_period_max =
  1231. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10);
  1232. }
  1233. /* Check arguments */
  1234. if (NULL == policy_dir)
  1235. {
  1236. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1237. _ (
  1238. "No policy directory specified on command line. Exiting.\n"));
  1239. return;
  1240. }
  1241. if (GNUNET_YES != GNUNET_DISK_directory_test (policy_dir, GNUNET_YES))
  1242. {
  1243. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1244. _ ("Specified policies directory does not exist. Exiting.\n"));
  1245. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1246. return;
  1247. }
  1248. if (0 >= (int) (num_peers = GNUNET_DISK_directory_scan (policy_dir, NULL,
  1249. NULL)))
  1250. {
  1251. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1252. _ ("No files found in `%s'\n"),
  1253. policy_dir);
  1254. return;
  1255. }
  1256. GNUNET_CONFIGURATION_set_value_string (cfg, "REGEXPROFILER",
  1257. "POLICY_DIR", policy_dir);
  1258. if (GNUNET_YES != GNUNET_DISK_file_test (strings_file))
  1259. {
  1260. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1261. _ ("No search strings file given. Exiting.\n"));
  1262. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1263. return;
  1264. }
  1265. nsearchstrs = load_search_strings (strings_file,
  1266. &search_strings,
  1267. num_peers);
  1268. if (num_peers != nsearchstrs)
  1269. {
  1270. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1271. "Error loading search strings.\n");
  1272. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1273. "File (%s) does not contain enough strings (%u/%u).\n",
  1274. strings_file, nsearchstrs, num_peers);
  1275. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1276. return;
  1277. }
  1278. if ((0 == num_peers) || (NULL == search_strings))
  1279. {
  1280. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1281. _ ("Error loading search strings. Exiting.\n"));
  1282. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  1283. return;
  1284. }
  1285. for (i = 0; i < num_peers; i++)
  1286. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1287. "search string: %s\n",
  1288. search_strings[i]);
  1289. /* Check logfile */
  1290. if ((NULL != data_filename) &&
  1291. (NULL == (data_file =
  1292. GNUNET_DISK_file_open (data_filename,
  1293. GNUNET_DISK_OPEN_READWRITE
  1294. | GNUNET_DISK_OPEN_TRUNCATE
  1295. | GNUNET_DISK_OPEN_CREATE,
  1296. GNUNET_DISK_PERM_USER_READ
  1297. | GNUNET_DISK_PERM_USER_WRITE))))
  1298. {
  1299. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  1300. "open",
  1301. data_filename);
  1302. return;
  1303. }
  1304. /* Initialize peers */
  1305. peers = GNUNET_malloc (sizeof(struct RegexPeer) * num_peers);
  1306. for (i = 0; i < num_peers; i++)
  1307. peers[i].id = i;
  1308. GNUNET_CONFIGURATION_set_value_number (cfg,
  1309. "TESTBED", "OVERLAY_RANDOM_LINKS",
  1310. num_peers * 20);
  1311. GNUNET_CONFIGURATION_set_value_number (cfg,
  1312. "DHT", "FORCE_NSE",
  1313. (long long unsigned)
  1314. (log (num_peers) / log (2.0)));
  1315. event_mask = 0LL;
  1316. /* For feedback about the start process activate these and pass master_cb */
  1317. event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
  1318. // event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
  1319. event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
  1320. // event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT);
  1321. prof_start_time = GNUNET_TIME_absolute_get ();
  1322. GNUNET_TESTBED_run (hosts_file,
  1323. cfg,
  1324. num_peers,
  1325. event_mask,
  1326. &master_controller_cb,
  1327. NULL, /* master_controller_cb cls */
  1328. &test_master,
  1329. NULL); /* test_master cls */
  1330. if (GNUNET_OK !=
  1331. GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
  1332. "SETUP_TIMEOUT",
  1333. &abort_time))
  1334. {
  1335. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1336. "SETUP_TIMEOUT not given. Using 15 minutes.\n");
  1337. abort_time =
  1338. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15);
  1339. }
  1340. abort_time = GNUNET_TIME_relative_add (abort_time, GNUNET_TIME_UNIT_MINUTES);
  1341. abort_task =
  1342. GNUNET_SCHEDULER_add_delayed (abort_time,
  1343. &do_abort,
  1344. (void *) __LINE__);
  1345. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1346. "setup_timeout: %s\n",
  1347. GNUNET_STRINGS_relative_time_to_string (abort_time, GNUNET_YES));
  1348. }
  1349. /**
  1350. * Main function.
  1351. *
  1352. * @param argc argument count
  1353. * @param argv argument values
  1354. * @return 0 on success
  1355. */
  1356. int
  1357. main (int argc, char *const *argv)
  1358. {
  1359. struct GNUNET_GETOPT_CommandLineOption options[] = {
  1360. GNUNET_GETOPT_option_filename ('o',
  1361. "output-file",
  1362. "FILENAME",
  1363. gettext_noop (
  1364. "name of the file for writing statistics"),
  1365. &data_filename),
  1366. GNUNET_GETOPT_option_relative_time ('t',
  1367. "matching-timeout",
  1368. "TIMEOUT",
  1369. gettext_noop (
  1370. "wait TIMEOUT before ending the experiment"),
  1371. &search_timeout_time),
  1372. GNUNET_GETOPT_option_filename ('p',
  1373. "policy-dir",
  1374. "DIRECTORY",
  1375. gettext_noop ("directory with policy files"),
  1376. &policy_dir),
  1377. GNUNET_GETOPT_option_filename ('s',
  1378. "strings-file",
  1379. "FILENAME",
  1380. gettext_noop (
  1381. "name of file with input strings"),
  1382. &strings_file),
  1383. GNUNET_GETOPT_option_filename ('H',
  1384. "hosts-file",
  1385. "FILENAME",
  1386. gettext_noop (
  1387. "name of file with hosts' names"),
  1388. &hosts_file),
  1389. GNUNET_GETOPT_OPTION_END
  1390. };
  1391. int ret;
  1392. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  1393. return 2;
  1394. result = GNUNET_SYSERR;
  1395. ret =
  1396. GNUNET_PROGRAM_run (argc, argv,
  1397. "gnunet-regex-profiler",
  1398. _ ("Profiler for regex"),
  1399. options, &run, NULL);
  1400. if (GNUNET_OK != ret)
  1401. return ret;
  1402. if (GNUNET_OK != result)
  1403. return 1;
  1404. return 0;
  1405. }