gnunet-daemon-fsprofiler.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2012 Christian Grothoff
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. 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. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file fs/gnunet-daemon-fsprofiler.c
  19. * @brief daemon that publishes and downloads (random) files
  20. * @author Christian Grothoff
  21. *
  22. * TODO:
  23. * - how to signal driver that we're done?
  24. */
  25. #include "platform.h"
  26. #include "gnunet_fs_service.h"
  27. #include "gnunet_statistics_service.h"
  28. /**
  29. * We use 'patterns' of the form (x,y,t) to specify desired download/publish
  30. * activities of a peer. They are stored in a DLL.
  31. */
  32. struct Pattern
  33. {
  34. /**
  35. * Kept in a DLL.
  36. */
  37. struct Pattern *next;
  38. /**
  39. * Kept in a DLL.
  40. */
  41. struct Pattern *prev;
  42. /**
  43. * Execution context for the pattern (FS-handle to the operation).
  44. */
  45. void *ctx;
  46. /**
  47. * Secondary execution context for the pattern (FS-handle to the operation).
  48. */
  49. void *sctx;
  50. /**
  51. * When did the operation start?
  52. */
  53. struct GNUNET_TIME_Absolute start_time;
  54. /**
  55. * With how much delay should this operation be started?
  56. */
  57. struct GNUNET_TIME_Relative delay;
  58. /**
  59. * Task to run the operation.
  60. */
  61. GNUNET_SCHEDULER_TaskIdentifier task;
  62. /**
  63. * Secondary task to run the operation.
  64. */
  65. GNUNET_SCHEDULER_TaskIdentifier stask;
  66. /**
  67. * X-value.
  68. */
  69. unsigned long long x;
  70. /**
  71. * Y-value.
  72. */
  73. unsigned long long y;
  74. };
  75. /**
  76. * Return value from 'main'.
  77. */
  78. static int global_ret;
  79. /**
  80. * Configuration we use.
  81. */
  82. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  83. /**
  84. * Handle to the statistics service.
  85. */
  86. static struct GNUNET_STATISTICS_Handle *stats_handle;
  87. /**
  88. * Peer's FS handle.
  89. */
  90. static struct GNUNET_FS_Handle *fs_handle;
  91. /**
  92. * Unique number for this peer in the testbed.
  93. */
  94. static unsigned long long my_peerid;
  95. /**
  96. * Desired anonymity level.
  97. */
  98. static unsigned long long anonymity_level;
  99. /**
  100. * Desired replication level.
  101. */
  102. static unsigned long long replication_level;
  103. /**
  104. * String describing which publishing operations this peer should
  105. * perform. The format is "(SIZE,SEED,TIME)*", for example:
  106. * "(1,5,0)(7,3,13)" means to publish a file with 1 byte and
  107. * seed/keyword 5 immediately and another file with 7 bytes and
  108. * seed/keyword 3 after 13 ms.
  109. */
  110. static char *publish_pattern;
  111. /**
  112. * Head of the DLL of publish patterns.
  113. */
  114. static struct Pattern *publish_head;
  115. /**
  116. * Tail of the DLL of publish patterns.
  117. */
  118. static struct Pattern *publish_tail;
  119. /**
  120. * String describing which download operations this peer should
  121. * perform. The format is "(KEYWORD,SIZE,DELAY)*"; for example,
  122. * "(1,7,3)(3,8,8)" means to download one file of 7 bytes under
  123. * keyword "1" starting the search after 3 ms; and another one of 8
  124. * bytes under keyword '3' starting after 8 ms. The file size is
  125. * used to determine which search result(s) should be used or ignored.
  126. */
  127. static char *download_pattern;
  128. /**
  129. * Head of the DLL of publish patterns.
  130. */
  131. static struct Pattern *download_head;
  132. /**
  133. * Tail of the DLL of publish patterns.
  134. */
  135. static struct Pattern *download_tail;
  136. /**
  137. * Parse a pattern string and store the corresponding
  138. * 'struct Pattern' in the given head/tail.
  139. *
  140. * @param head where to store the head
  141. * @param tail where to store the tail
  142. * @param pattern pattern to parse
  143. * @return GNUNET_OK on success
  144. */
  145. static int
  146. parse_pattern (struct Pattern **head,
  147. struct Pattern **tail,
  148. const char *pattern)
  149. {
  150. struct Pattern *p;
  151. unsigned long long x;
  152. unsigned long long y;
  153. unsigned long long t;
  154. while (3 == sscanf (pattern,
  155. "(%llu,%llu,%llu)",
  156. &x, &y, &t))
  157. {
  158. p = GNUNET_new (struct Pattern);
  159. p->x = x;
  160. p->y = y;
  161. p->delay.rel_value_us = (uint64_t) t;
  162. GNUNET_CONTAINER_DLL_insert (*head, *tail, p);
  163. pattern = strstr (pattern, ")");
  164. GNUNET_assert (NULL != pattern);
  165. pattern++;
  166. }
  167. return (0 == strlen (pattern)) ? GNUNET_OK : GNUNET_SYSERR;
  168. }
  169. /**
  170. * Create a KSK URI from a number.
  171. *
  172. * @param kval the number
  173. * @return corresponding KSK URI
  174. */
  175. static struct GNUNET_FS_Uri *
  176. make_keywords (uint64_t kval)
  177. {
  178. char kw[128];
  179. GNUNET_snprintf (kw, sizeof (kw),
  180. "%llu", (unsigned long long) kval);
  181. return GNUNET_FS_uri_ksk_create (kw, NULL);
  182. }
  183. /**
  184. * Create a file of the given length with a deterministic amount
  185. * of data to be published under keyword 'kval'.
  186. *
  187. * @param length number of bytes in the file
  188. * @param kval keyword value and seed for the data of the file
  189. * @param ctx context to pass to 'fi'
  190. * @return file information handle for the file
  191. */
  192. static struct GNUNET_FS_FileInformation *
  193. make_file (uint64_t length,
  194. uint64_t kval,
  195. void *ctx)
  196. {
  197. struct GNUNET_FS_FileInformation *fi;
  198. struct GNUNET_FS_BlockOptions bo;
  199. char *data;
  200. struct GNUNET_FS_Uri *keywords;
  201. unsigned long long i;
  202. uint64_t xor;
  203. data = NULL; /* to make compilers happy */
  204. if ( (0 != length) &&
  205. (NULL == (data = GNUNET_malloc_large ((size_t) length))) )
  206. return NULL;
  207. /* initialize data with 'unique' data only depending on 'kval' and 'size',
  208. making sure that blocks do not repeat */
  209. for (i=0;i<length; i+=8)
  210. {
  211. xor = length ^ kval ^ (uint64_t) (i / 32 / 1024);
  212. memcpy (&data[i], &xor, GNUNET_MIN (length - i, sizeof (uint64_t)));
  213. }
  214. bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
  215. bo.anonymity_level = (uint32_t) anonymity_level;
  216. bo.content_priority = 128;
  217. bo.replication_level = (uint32_t) replication_level;
  218. keywords = make_keywords (kval);
  219. fi = GNUNET_FS_file_information_create_from_data (fs_handle,
  220. ctx,
  221. length,
  222. data, keywords,
  223. NULL, GNUNET_NO, &bo);
  224. GNUNET_FS_uri_destroy (keywords);
  225. return fi;
  226. }
  227. /**
  228. * Task run during shutdown.
  229. *
  230. * @param cls unused
  231. * @param tc unused
  232. */
  233. static void
  234. shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  235. {
  236. struct Pattern *p;
  237. while (NULL != (p = publish_head))
  238. {
  239. if (GNUNET_SCHEDULER_NO_TASK != p->task)
  240. GNUNET_SCHEDULER_cancel (p->task);
  241. if (NULL != p->ctx)
  242. GNUNET_FS_publish_stop (p->ctx);
  243. GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p);
  244. GNUNET_free (p);
  245. }
  246. while (NULL != (p = download_head))
  247. {
  248. if (GNUNET_SCHEDULER_NO_TASK != p->task)
  249. GNUNET_SCHEDULER_cancel (p->task);
  250. if (GNUNET_SCHEDULER_NO_TASK != p->stask)
  251. GNUNET_SCHEDULER_cancel (p->stask);
  252. if (NULL != p->ctx)
  253. GNUNET_FS_download_stop (p->ctx, GNUNET_YES);
  254. if (NULL != p->sctx)
  255. GNUNET_FS_search_stop (p->sctx);
  256. GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p);
  257. GNUNET_free (p);
  258. }
  259. if (NULL != fs_handle)
  260. {
  261. GNUNET_FS_stop (fs_handle);
  262. fs_handle = NULL;
  263. }
  264. if (NULL != stats_handle)
  265. {
  266. GNUNET_STATISTICS_destroy (stats_handle, GNUNET_YES);
  267. stats_handle = NULL;
  268. }
  269. }
  270. /**
  271. * Task run when a publish operation should be stopped.
  272. *
  273. * @param cls the 'struct Pattern' of the publish operation to stop
  274. * @param tc unused
  275. */
  276. static void
  277. publish_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  278. {
  279. struct Pattern *p = cls;
  280. p->task = GNUNET_SCHEDULER_NO_TASK;
  281. GNUNET_FS_publish_stop (p->ctx);
  282. }
  283. /**
  284. * Task run when a download operation should be stopped.
  285. *
  286. * @param cls the 'struct Pattern' of the download operation to stop
  287. * @param tc unused
  288. */
  289. static void
  290. download_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  291. {
  292. struct Pattern *p = cls;
  293. p->task = GNUNET_SCHEDULER_NO_TASK;
  294. GNUNET_FS_download_stop (p->ctx, GNUNET_YES);
  295. }
  296. /**
  297. * Task run when a download operation should be stopped.
  298. *
  299. * @param cls the 'struct Pattern' of the download operation to stop
  300. * @param tc unused
  301. */
  302. static void
  303. search_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  304. {
  305. struct Pattern *p = cls;
  306. p->stask = GNUNET_SCHEDULER_NO_TASK;
  307. GNUNET_FS_search_stop (p->sctx);
  308. }
  309. /**
  310. * Notification of FS to a client about the progress of an
  311. * operation. Callbacks of this type will be used for uploads,
  312. * downloads and searches. Some of the arguments depend a bit
  313. * in their meaning on the context in which the callback is used.
  314. *
  315. * @param cls closure
  316. * @param info details about the event, specifying the event type
  317. * and various bits about the event
  318. * @return client-context (for the next progress call
  319. * for this operation; should be set to NULL for
  320. * SUSPEND and STOPPED events). The value returned
  321. * will be passed to future callbacks in the respective
  322. * field in the GNUNET_FS_ProgressInfo struct.
  323. */
  324. static void *
  325. progress_cb (void *cls,
  326. const struct GNUNET_FS_ProgressInfo *info)
  327. {
  328. struct Pattern *p;
  329. const struct GNUNET_FS_Uri *uri;
  330. switch (info->status)
  331. {
  332. case GNUNET_FS_STATUS_PUBLISH_START:
  333. case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
  334. p = info->value.publish.cctx;
  335. return p;
  336. case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY:
  337. p = info->value.publish.cctx;
  338. return p;
  339. case GNUNET_FS_STATUS_PUBLISH_ERROR:
  340. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  341. "Publishing failed\n");
  342. GNUNET_STATISTICS_update (stats_handle,
  343. "# failed publish operations", 1, GNUNET_NO);
  344. p = info->value.publish.cctx;
  345. p->task = GNUNET_SCHEDULER_add_now (&publish_stop_task, p);
  346. return p;
  347. case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
  348. p = info->value.publish.cctx;
  349. GNUNET_STATISTICS_update (stats_handle,
  350. "# publishing time (ms)",
  351. (long long) GNUNET_TIME_absolute_get_duration (p->start_time).rel_value_us / 1000LL,
  352. GNUNET_NO);
  353. p->task = GNUNET_SCHEDULER_add_now (&publish_stop_task, p);
  354. return p;
  355. case GNUNET_FS_STATUS_PUBLISH_STOPPED:
  356. p = info->value.publish.cctx;
  357. p->ctx = NULL;
  358. GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p);
  359. GNUNET_free (p);
  360. return NULL;
  361. case GNUNET_FS_STATUS_DOWNLOAD_START:
  362. case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
  363. case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
  364. case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
  365. p = info->value.download.cctx;
  366. return p;
  367. case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
  368. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  369. "Download failed\n");
  370. GNUNET_STATISTICS_update (stats_handle,
  371. "# failed downloads", 1, GNUNET_NO);
  372. p = info->value.download.cctx;
  373. p->task = GNUNET_SCHEDULER_add_now (&download_stop_task, p);
  374. return p;
  375. case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
  376. p = info->value.download.cctx;
  377. GNUNET_STATISTICS_update (stats_handle,
  378. "# download time (ms)",
  379. (long long) GNUNET_TIME_absolute_get_duration (p->start_time).rel_value_us / 1000LL,
  380. GNUNET_NO);
  381. p->task = GNUNET_SCHEDULER_add_now (&download_stop_task, p);
  382. return p;
  383. case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
  384. p = info->value.download.cctx;
  385. p->ctx = NULL;
  386. if (NULL == p->sctx)
  387. {
  388. GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p);
  389. GNUNET_free (p);
  390. }
  391. return NULL;
  392. case GNUNET_FS_STATUS_SEARCH_START:
  393. case GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE:
  394. p = info->value.search.cctx;
  395. return p;
  396. case GNUNET_FS_STATUS_SEARCH_RESULT:
  397. p = info->value.search.cctx;
  398. uri = info->value.search.specifics.result.uri;
  399. if (GNUNET_YES != GNUNET_FS_uri_test_chk (uri))
  400. return NULL; /* not what we want */
  401. if (p->y != GNUNET_FS_uri_chk_get_file_size (uri))
  402. return NULL; /* not what we want */
  403. GNUNET_STATISTICS_update (stats_handle,
  404. "# search time (ms)",
  405. (long long) GNUNET_TIME_absolute_get_duration (p->start_time).rel_value_us / 1000LL,
  406. GNUNET_NO);
  407. p->start_time = GNUNET_TIME_absolute_get ();
  408. p->ctx = GNUNET_FS_download_start (fs_handle, uri,
  409. NULL, NULL, NULL,
  410. 0, GNUNET_FS_uri_chk_get_file_size (uri),
  411. anonymity_level,
  412. GNUNET_FS_DOWNLOAD_NO_TEMPORARIES,
  413. p,
  414. NULL);
  415. p->stask = GNUNET_SCHEDULER_add_now (&search_stop_task, p);
  416. return NULL;
  417. case GNUNET_FS_STATUS_SEARCH_UPDATE:
  418. case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
  419. return NULL; /* don't care */
  420. case GNUNET_FS_STATUS_SEARCH_ERROR:
  421. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  422. "Search failed\n");
  423. GNUNET_STATISTICS_update (stats_handle,
  424. "# failed searches", 1, GNUNET_NO);
  425. p = info->value.search.cctx;
  426. p->stask = GNUNET_SCHEDULER_add_now (&search_stop_task, p);
  427. return p;
  428. case GNUNET_FS_STATUS_SEARCH_STOPPED:
  429. p = info->value.search.cctx;
  430. p->sctx = NULL;
  431. if (NULL == p->ctx)
  432. {
  433. GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p);
  434. GNUNET_free (p);
  435. }
  436. return NULL;
  437. default:
  438. /* unexpected event during profiling */
  439. GNUNET_break (0);
  440. return NULL;
  441. }
  442. }
  443. /**
  444. * Start publish operation.
  445. *
  446. * @param cls the 'struct Pattern' specifying the operation to perform
  447. * @param tc scheduler context
  448. */
  449. static void
  450. start_publish (void *cls,
  451. const struct GNUNET_SCHEDULER_TaskContext *tc)
  452. {
  453. struct Pattern *p = cls;
  454. struct GNUNET_FS_FileInformation *fi;
  455. p->task = GNUNET_SCHEDULER_NO_TASK;
  456. if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  457. return;
  458. fi = make_file (p->x, p->y, p);
  459. p->start_time = GNUNET_TIME_absolute_get ();
  460. p->ctx = GNUNET_FS_publish_start (fs_handle,
  461. fi,
  462. NULL, NULL, NULL,
  463. GNUNET_FS_PUBLISH_OPTION_NONE);
  464. }
  465. /**
  466. * Start download operation.
  467. *
  468. * @param cls the 'struct Pattern' specifying the operation to perform
  469. * @param tc scheduler context
  470. */
  471. static void
  472. start_download (void *cls,
  473. const struct GNUNET_SCHEDULER_TaskContext *tc)
  474. {
  475. struct Pattern *p = cls;
  476. struct GNUNET_FS_Uri *keywords;
  477. p->task = GNUNET_SCHEDULER_NO_TASK;
  478. if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  479. return;
  480. keywords = make_keywords (p->x);
  481. p->start_time = GNUNET_TIME_absolute_get ();
  482. p->sctx = GNUNET_FS_search_start (fs_handle, keywords,
  483. anonymity_level,
  484. GNUNET_FS_SEARCH_OPTION_NONE,
  485. p);
  486. }
  487. /**
  488. * @brief Main function that will be run by the scheduler.
  489. *
  490. * @param cls closure
  491. * @param args remaining command-line arguments
  492. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  493. * @param cfg_ configuration
  494. */
  495. static void
  496. run (void *cls, char *const *args GNUNET_UNUSED,
  497. const char *cfgfile GNUNET_UNUSED,
  498. const struct GNUNET_CONFIGURATION_Handle *cfg_)
  499. {
  500. char myoptname[128];
  501. struct Pattern *p;
  502. cfg = cfg_;
  503. /* Scheduled the task to clean up when shutdown is called */
  504. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
  505. NULL);
  506. if (GNUNET_OK !=
  507. GNUNET_CONFIGURATION_get_value_number (cfg,
  508. "TESTBED", "PEERID",
  509. &my_peerid))
  510. {
  511. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  512. "TESTBED", "PEERID");
  513. global_ret = GNUNET_SYSERR;
  514. GNUNET_SCHEDULER_shutdown ();
  515. return;
  516. }
  517. if (GNUNET_OK !=
  518. GNUNET_CONFIGURATION_get_value_number (cfg,
  519. "FSPROFILER", "ANONYMITY_LEVEL",
  520. &anonymity_level))
  521. anonymity_level = 1;
  522. if (GNUNET_OK !=
  523. GNUNET_CONFIGURATION_get_value_number (cfg,
  524. "FSPROFILER", "REPLICATION_LEVEL",
  525. &replication_level))
  526. replication_level = 1;
  527. GNUNET_snprintf (myoptname, sizeof (myoptname),
  528. "DOWNLOAD-PATTERN-%u", my_peerid);
  529. if (GNUNET_OK !=
  530. GNUNET_CONFIGURATION_get_value_string (cfg,
  531. "FSPROFILER", myoptname,
  532. &download_pattern))
  533. download_pattern = GNUNET_strdup ("");
  534. GNUNET_snprintf (myoptname, sizeof (myoptname),
  535. "PUBLISH-PATTERN-%u", my_peerid);
  536. if (GNUNET_OK !=
  537. GNUNET_CONFIGURATION_get_value_string (cfg,
  538. "FSPROFILER", myoptname,
  539. &publish_pattern))
  540. publish_pattern = GNUNET_strdup ("");
  541. if ( (GNUNET_OK !=
  542. parse_pattern (&download_head,
  543. &download_tail,
  544. download_pattern)) ||
  545. (GNUNET_OK !=
  546. parse_pattern (&publish_head,
  547. &publish_tail,
  548. publish_pattern)) )
  549. {
  550. GNUNET_SCHEDULER_shutdown ();
  551. return;
  552. }
  553. stats_handle = GNUNET_STATISTICS_create ("fsprofiler", cfg);
  554. fs_handle =
  555. GNUNET_FS_start (cfg,
  556. "fsprofiler",
  557. &progress_cb, NULL,
  558. GNUNET_FS_FLAGS_NONE,
  559. GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, 1,
  560. GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, 1,
  561. GNUNET_FS_OPTIONS_END);
  562. if (NULL == fs_handle)
  563. {
  564. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not acquire FS handle. Exiting.\n");
  565. global_ret = GNUNET_SYSERR;
  566. GNUNET_SCHEDULER_shutdown ();
  567. return;
  568. }
  569. for (p = publish_head; NULL != p; p = p->next)
  570. p->task = GNUNET_SCHEDULER_add_delayed (p->delay,
  571. &start_publish, p);
  572. for (p = download_head; NULL != p; p = p->next)
  573. p->task = GNUNET_SCHEDULER_add_delayed (p->delay,
  574. &start_download, p);
  575. }
  576. /**
  577. * Program that performs various "random" FS activities.
  578. *
  579. * @param argc number of arguments from the command line
  580. * @param argv command line arguments
  581. * @return 0 ok, 1 on error
  582. */
  583. int
  584. main (int argc, char *const *argv)
  585. {
  586. static const struct GNUNET_GETOPT_CommandLineOption options[] = {
  587. GNUNET_GETOPT_OPTION_END
  588. };
  589. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  590. return 2;
  591. return (GNUNET_OK ==
  592. GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-fsprofiler",
  593. gettext_noop
  594. ("Daemon to use file-sharing to measure its performance."),
  595. options, &run, NULL)) ? global_ret : 1;
  596. }
  597. /* end of gnunet-daemon-fsprofiler.c */