ats-testing-log.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010-2013 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 ats-tests/ats-testing-log.c
  18. * @brief ats benchmark: logging for performance tests
  19. * @author Christian Grothoff
  20. * @author Matthias Wachs
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "ats-testing.h"
  25. #define THROUGHPUT_TEMPLATE "#!/usr/bin/gnuplot \n" \
  26. "set datafile separator ';' \n" \
  27. "set title \"Throughput between Master and Slaves\" \n" \
  28. "set xlabel \"Time in ms\" \n" \
  29. "set ylabel \"Bytes/s\" \n" \
  30. "set grid \n"
  31. #define RTT_TEMPLATE "#!/usr/bin/gnuplot \n" \
  32. "set datafile separator ';' \n" \
  33. "set title \"Application level roundtrip time between Master and Slaves\" \n" \
  34. "set xlabel \"Time in ms\" \n" \
  35. "set ylabel \"ms\" \n" \
  36. "set grid \n"
  37. #define BW_TEMPLATE "#!/usr/bin/gnuplot \n" \
  38. "set datafile separator ';' \n" \
  39. "set title \"Bandwidth inbound and outbound between Master and Slaves\" \n" \
  40. "set xlabel \"Time in ms\" \n" \
  41. "set ylabel \"Bytes / s \" \n" \
  42. "set grid \n"
  43. #define LOG_ITEMS_TIME 2
  44. #define LOG_ITEMS_PER_PEER 17
  45. #define LOG_ITEM_BYTES_SENT 1
  46. #define LOG_ITEM_MSGS_SENT 2
  47. #define LOG_ITEM_THROUGHPUT_SENT 3
  48. #define LOG_ITEM_BYTES_RECV 4
  49. #define LOG_ITEM_MSGS_RECV 5
  50. #define LOG_ITEM_THROUGHPUT_RECV 6
  51. #define LOG_ITEM_APP_RTT 7
  52. #define LOG_ITEM_ATS_BW_IN 8
  53. #define LOG_ITEM_ATS_BW_OUT 9
  54. #define LOG_ITEM_ATS_COSTS_LAN 10
  55. #define LOG_ITEM_ATS_WAN 11
  56. #define LOG_ITEM_ATS_WLAN 12
  57. #define LOG_ITEM_ATS_DELAY 13
  58. #define LOG_ITEM_ATS_DISTANCE 14
  59. #define LOG_ITEM_ATS_NETWORKTYPE 15
  60. #define LOG_ITEM_ATS_UTIL_UP 16
  61. #define LOG_ITEM_ATS_UTIL_DOWN 17
  62. /**
  63. * A single logging time step for a partner
  64. */
  65. struct PartnerLoggingTimestep
  66. {
  67. /**
  68. * Peer
  69. */
  70. struct BenchmarkPeer *slave;
  71. /**
  72. * Total number of messages this peer has sent
  73. */
  74. unsigned int total_messages_sent;
  75. /**
  76. * Total number of bytes this peer has sent
  77. */
  78. unsigned int total_bytes_sent;
  79. /**
  80. * Total number of messages this peer has received
  81. */
  82. unsigned int total_messages_received;
  83. /**
  84. * Total number of bytes this peer has received
  85. */
  86. unsigned int total_bytes_received;
  87. /**
  88. * Total outbound throughput for master in Bytes / s
  89. */
  90. unsigned int throughput_sent;
  91. /**
  92. * Total inbound throughput for master in Bytes / s
  93. */
  94. unsigned int throughput_recv;
  95. /**
  96. * Accumulated RTT for all messages
  97. */
  98. unsigned int total_app_rtt;
  99. /**
  100. * Current application level delay
  101. */
  102. unsigned int app_rtt;
  103. /* Current ATS properties */
  104. unsigned int ats_distance;
  105. struct GNUNET_TIME_Relative ats_delay;
  106. uint32_t bandwidth_in;
  107. uint32_t bandwidth_out;
  108. uint32_t ats_utilization_out;
  109. uint32_t ats_utilization_in;
  110. enum GNUNET_NetworkType ats_network_type;
  111. double pref_bandwidth;
  112. double pref_delay;
  113. };
  114. /**
  115. * A single logging time step for a peer
  116. */
  117. struct PeerLoggingTimestep
  118. {
  119. /**
  120. * Next in DLL
  121. */
  122. struct PeerLoggingTimestep *next;
  123. /**
  124. * Prev in DLL
  125. */
  126. struct PeerLoggingTimestep *prev;
  127. /**
  128. * Logging timestamp
  129. */
  130. struct GNUNET_TIME_Absolute timestamp;
  131. /**
  132. * Total number of messages this peer has sent
  133. */
  134. unsigned int total_messages_sent;
  135. /**
  136. * Total number of bytes this peer has sent
  137. */
  138. unsigned int total_bytes_sent;
  139. /**
  140. * Total number of messages this peer has received
  141. */
  142. unsigned int total_messages_received;
  143. /**
  144. * Total number of bytes this peer has received
  145. */
  146. unsigned int total_bytes_received;
  147. /**
  148. * Total outbound throughput for master in Bytes / s
  149. */
  150. unsigned int total_throughput_send;
  151. /**
  152. * Total inbound throughput for master in Bytes / s
  153. */
  154. unsigned int total_throughput_recv;
  155. /**
  156. * Logs for slaves
  157. */
  158. struct PartnerLoggingTimestep *slaves_log;
  159. };
  160. /**
  161. * Entry for a benchmark peer
  162. */
  163. struct LoggingPeer
  164. {
  165. /**
  166. * Peer
  167. */
  168. struct BenchmarkPeer *peer;
  169. /**
  170. * Start time
  171. */
  172. struct GNUNET_TIME_Absolute start;
  173. /**
  174. * DLL for logging entries: head
  175. */
  176. struct PeerLoggingTimestep *head;
  177. /**
  178. * DLL for logging entries: tail
  179. */
  180. struct PeerLoggingTimestep *tail;
  181. };
  182. struct LoggingHandle
  183. {
  184. /**
  185. * Logging task
  186. */
  187. struct GNUNET_SCHEDULER_Task *log_task;
  188. /**
  189. * Reference to perf_ats' masters
  190. */
  191. int num_masters;
  192. int num_slaves;
  193. int running;
  194. int verbose;
  195. const char *name;
  196. struct GNUNET_TIME_Relative frequency;
  197. /**
  198. * Log structure of length num_peers
  199. */
  200. struct LoggingPeer *lp;
  201. };
  202. static void
  203. write_throughput_gnuplot_script (char * fn, struct LoggingPeer *lp, char **fs, int slaves)
  204. {
  205. struct GNUNET_DISK_FileHandle *f;
  206. char * gfn;
  207. char *data;
  208. int c_s;
  209. GNUNET_asprintf (&gfn, "gnuplot_throughput_%s",fn);
  210. fprintf (stderr, "Writing throughput plot for master %u and %u slaves to `%s'\n",
  211. lp->peer->no, slaves, gfn);
  212. f = GNUNET_DISK_file_open (gfn,
  213. GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
  214. GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ |
  215. GNUNET_DISK_PERM_USER_WRITE);
  216. if (NULL == f)
  217. {
  218. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
  219. GNUNET_free (gfn);
  220. return;
  221. }
  222. /* Write header */
  223. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, THROUGHPUT_TEMPLATE,
  224. strlen(THROUGHPUT_TEMPLATE)))
  225. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  226. "Cannot write data to plot file `%s'\n", gfn);
  227. /* Write master data */
  228. GNUNET_asprintf (&data,
  229. "plot '%s' using 2:%u with lines title 'Master %u send total', \\\n" \
  230. "'%s' using 2:%u with lines title 'Master %u receive total', \\\n",
  231. fn, LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no,
  232. fn, LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no);
  233. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
  234. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
  235. GNUNET_free (data);
  236. for (c_s = 0; c_s < slaves; c_s++)
  237. {
  238. GNUNET_asprintf (&data, "'%s' using 2:%u with lines title 'Master %u - Slave %u send', \\\n" \
  239. "'%s' using 2:%u with lines title 'Master %u - Slave %u receive'%s\n",
  240. fs[c_s],
  241. LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_SENT,
  242. lp->peer->no,
  243. lp->peer->partners[c_s].dest->no,
  244. fs[c_s],
  245. LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_RECV,
  246. lp->peer->no,
  247. lp->peer->partners[c_s].dest->no,
  248. (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1");
  249. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
  250. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
  251. GNUNET_free (data);
  252. }
  253. if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
  254. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  255. "Cannot close gnuplot file `%s'\n", gfn);
  256. else
  257. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  258. "Data successfully written to plot file `%s'\n", gfn);
  259. GNUNET_free (gfn);
  260. }
  261. static void
  262. write_rtt_gnuplot_script (char * fn, struct LoggingPeer *lp, char **fs, int slaves)
  263. {
  264. struct GNUNET_DISK_FileHandle *f;
  265. char * gfn;
  266. char *data;
  267. int c_s;
  268. GNUNET_asprintf (&gfn, "gnuplot_rtt_%s",fn);
  269. fprintf (stderr, "Writing rtt plot for master %u to `%s'\n",
  270. lp->peer->no, gfn);
  271. f = GNUNET_DISK_file_open (gfn,
  272. GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
  273. GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ |
  274. GNUNET_DISK_PERM_USER_WRITE);
  275. if (NULL == f)
  276. {
  277. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
  278. GNUNET_free (gfn);
  279. return;
  280. }
  281. /* Write header */
  282. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, RTT_TEMPLATE, strlen(RTT_TEMPLATE)))
  283. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
  284. for (c_s = 0; c_s < slaves; c_s++)
  285. {
  286. GNUNET_asprintf (&data, "%s'%s' using 2:%u with lines title 'Master %u - Slave %u '%s\n",
  287. (0 == c_s) ? "plot " :"",
  288. fs[c_s],
  289. LOG_ITEMS_TIME + LOG_ITEM_APP_RTT,
  290. lp->peer->no,
  291. lp->peer->partners[c_s].dest->no,
  292. (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1");
  293. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
  294. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
  295. GNUNET_free (data);
  296. }
  297. if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
  298. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn);
  299. else
  300. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn);
  301. GNUNET_free (gfn);
  302. }
  303. static void
  304. write_bw_gnuplot_script (char * fn, struct LoggingPeer *lp, char **fs, int slaves)
  305. {
  306. struct GNUNET_DISK_FileHandle *f;
  307. char * gfn;
  308. char *data;
  309. int c_s;
  310. GNUNET_asprintf (&gfn, "gnuplot_bw_%s",fn);
  311. fprintf (stderr, "Writing bandwidth plot for master %u to `%s'\n",
  312. lp->peer->no, gfn);
  313. f = GNUNET_DISK_file_open (gfn,
  314. GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
  315. GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ |
  316. GNUNET_DISK_PERM_USER_WRITE);
  317. if (NULL == f)
  318. {
  319. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
  320. GNUNET_free (gfn);
  321. return;
  322. }
  323. /* Write header */
  324. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, BW_TEMPLATE, strlen(BW_TEMPLATE)))
  325. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  326. "Cannot write data to plot file `%s'\n", gfn);
  327. for (c_s = 0; c_s < slaves; c_s++)
  328. {
  329. GNUNET_asprintf (&data, "%s"\
  330. "'%s' using 2:%u with lines title 'BW out master %u - Slave %u ', \\\n" \
  331. "'%s' using 2:%u with lines title 'BW in master %u - Slave %u '"\
  332. "%s\n",
  333. (0 == c_s) ? "plot " :"",
  334. fs[c_s],
  335. LOG_ITEMS_TIME + LOG_ITEM_ATS_BW_OUT,
  336. lp->peer->no, c_s,
  337. fs[c_s],
  338. LOG_ITEMS_TIME + LOG_ITEM_ATS_BW_IN,
  339. lp->peer->no, c_s,
  340. (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1");
  341. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
  342. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
  343. GNUNET_free (data);
  344. }
  345. if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
  346. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn);
  347. else
  348. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn);
  349. GNUNET_free (gfn);
  350. }
  351. void
  352. GNUNET_ATS_TEST_logging_write_to_file (struct LoggingHandle *l,
  353. const char *experiment_name,
  354. int plots)
  355. {
  356. struct GNUNET_DISK_FileHandle *f[l->num_slaves];
  357. struct GNUNET_DISK_FileHandle *f_m;
  358. const char *tmp_exp_name;
  359. char *filename_master;
  360. char *filename_slaves[l->num_slaves];
  361. char *data;
  362. struct PeerLoggingTimestep *cur_lt;
  363. struct PartnerLoggingTimestep *plt;
  364. struct GNUNET_TIME_Absolute timestamp;
  365. int c_m;
  366. int c_s;
  367. timestamp = GNUNET_TIME_absolute_get();
  368. tmp_exp_name = experiment_name;
  369. for (c_m = 0; c_m < l->num_masters; c_m++)
  370. {
  371. GNUNET_asprintf (&filename_master, "%s_%llu_master%u_%s",
  372. experiment_name, timestamp.abs_value_us, c_m, l->name);
  373. fprintf (stderr, "Writing data for master %u to file `%s'\n",
  374. c_m,filename_master);
  375. f_m = GNUNET_DISK_file_open (filename_master,
  376. GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
  377. GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
  378. if (NULL == f_m)
  379. {
  380. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n", filename_master);
  381. GNUNET_free (filename_master);
  382. return;
  383. }
  384. GNUNET_asprintf (&data, "# master %u; experiment : %s\n"
  385. "timestamp; timestamp delta; #messages sent; #bytes sent; #throughput sent; #messages received; #bytes received; #throughput received; \n" ,
  386. c_m, experiment_name);
  387. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_m, data, strlen(data)))
  388. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  389. "Cannot write data to log file `%s'\n",filename_master);
  390. GNUNET_free (data);
  391. for (c_s = 0; c_s < l->lp[c_m].peer->num_partners; c_s++)
  392. {
  393. GNUNET_asprintf (&filename_slaves[c_s], "%s_%llu_master%u_slave_%u_%s",
  394. tmp_exp_name, timestamp.abs_value_us, c_m, c_s, l->name);
  395. fprintf (stderr, "Writing data for master %u slave %u to file `%s'\n",
  396. c_m, c_s, filename_slaves[c_s]);
  397. f[c_s] = GNUNET_DISK_file_open (filename_slaves[c_s],
  398. GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
  399. GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
  400. if (NULL == f[c_s])
  401. {
  402. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n", filename_slaves[c_s]);
  403. GNUNET_free (filename_slaves[c_s]);
  404. GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close(f_m));
  405. GNUNET_free (filename_master);
  406. return;
  407. }
  408. /* Header */
  409. GNUNET_asprintf (&data, "# master %u; slave %u ; experiment : %s\n"
  410. "timestamp; timestamp delta; #messages sent; #bytes sent; #throughput sent; #messages received; #bytes received; #throughput received; " \
  411. "rtt; bw in; bw out; ats_cost_lan; ats_cost_wlan; ats_delay; ats_distance; ats_network_type; ats_utilization_up ;ats_utilization_down;" \
  412. "pref bandwidth; pref delay\n",
  413. c_m, c_s, experiment_name);
  414. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f[c_s], data, strlen(data)))
  415. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  416. "Cannot write data to log file `%s'\n",filename_slaves[c_s]);
  417. GNUNET_free (data);
  418. }
  419. for (cur_lt = l->lp[c_m].head; NULL != cur_lt; cur_lt = cur_lt->next)
  420. {
  421. if (l->verbose)
  422. fprintf (stderr,
  423. "Master [%u]: timestamp %llu %llu ; %u %u %u ; %u %u %u\n",
  424. l->lp[c_m].peer->no,
  425. (long long unsigned int) cur_lt->timestamp.abs_value_us,
  426. (long long unsigned int) GNUNET_TIME_absolute_get_difference(l->lp[c_m].start,
  427. cur_lt->timestamp).rel_value_us / 1000,
  428. cur_lt->total_messages_sent,
  429. cur_lt->total_bytes_sent,
  430. cur_lt->total_throughput_send,
  431. cur_lt->total_messages_received,
  432. cur_lt->total_bytes_received,
  433. cur_lt->total_throughput_recv);
  434. /* Assembling master string */
  435. GNUNET_asprintf (&data, "%llu;%llu;%u;%u;%u;%u;%u;%u;\n",
  436. (long long unsigned int) cur_lt->timestamp.abs_value_us,
  437. (long long unsigned int) GNUNET_TIME_absolute_get_difference(l->lp[c_m].start,
  438. cur_lt->timestamp).rel_value_us / 1000,
  439. cur_lt->total_messages_sent,
  440. cur_lt->total_bytes_sent,
  441. cur_lt->total_throughput_send,
  442. cur_lt->total_messages_received,
  443. cur_lt->total_bytes_received,
  444. cur_lt->total_throughput_recv);
  445. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_m, data, strlen(data)))
  446. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  447. "Cannot write data to master file %u\n", c_m);
  448. GNUNET_free (data);
  449. for (c_s = 0; c_s < l->lp[c_m].peer->num_partners; c_s++)
  450. {
  451. plt = &cur_lt->slaves_log[c_s];
  452. /* Log partners */
  453. /* Assembling slave string */
  454. GNUNET_asprintf(&data,
  455. "%llu;%llu;%u;%u;%u;%u;%u;%u;%.3f;%u;%u;%u;%u;%u;%u;%u;%.3f;%.3f\n",
  456. (long long unsigned int) cur_lt->timestamp.abs_value_us,
  457. (long long unsigned int) GNUNET_TIME_absolute_get_difference(l->lp[c_m].start,
  458. cur_lt->timestamp).rel_value_us / 1000,
  459. plt->total_messages_sent,
  460. plt->total_bytes_sent,
  461. plt->throughput_sent,
  462. plt->total_messages_received,
  463. plt->total_bytes_received,
  464. plt->throughput_recv,
  465. (double) plt->app_rtt / 1000,
  466. plt->bandwidth_in,
  467. plt->bandwidth_out,
  468. plt->ats_delay,
  469. plt->ats_distance,
  470. plt->ats_network_type,
  471. plt->ats_utilization_out,
  472. plt->ats_utilization_in,
  473. plt->pref_bandwidth,
  474. plt->pref_delay);
  475. if (l->verbose)
  476. fprintf (stderr,
  477. "\t Slave [%u]: %u %u %u ; %u %u %u rtt %u delay %llu bw_in %u bw_out %u \n",
  478. plt->slave->no,
  479. plt->total_messages_sent,
  480. plt->total_bytes_sent,
  481. plt->throughput_sent,
  482. plt->total_messages_received,
  483. plt->total_bytes_received,
  484. plt->throughput_recv,
  485. plt->app_rtt,
  486. (long long unsigned int) plt->ats_delay.rel_value_us,
  487. plt->bandwidth_in,
  488. plt->bandwidth_out);
  489. if (GNUNET_SYSERR == GNUNET_DISK_file_write(f[c_s], data, strlen(data)))
  490. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  491. "Cannot write data to log file `%s'\n", filename_slaves[c_s]);
  492. GNUNET_free (data);
  493. }
  494. }
  495. for (c_s = 0; c_s < l->lp[c_m].peer->num_partners; c_s++)
  496. {
  497. if (GNUNET_SYSERR == GNUNET_DISK_file_close(f[c_s]))
  498. {
  499. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  500. "Cannot close log file for master[%u] slave[%u]\n", c_m, c_s);
  501. continue;
  502. }
  503. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  504. "Data file successfully written to log file for `%s'\n",
  505. filename_slaves[c_s]);
  506. }
  507. if (GNUNET_SYSERR == GNUNET_DISK_file_close(f_m))
  508. {
  509. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  510. "close",
  511. filename_master);
  512. GNUNET_free (filename_master);
  513. return;
  514. }
  515. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  516. "Data file successfully written to log file for master `%s'\n", filename_master);
  517. if (GNUNET_YES == plots)
  518. {
  519. write_throughput_gnuplot_script (filename_master, &l->lp[c_m], filename_slaves, l->num_slaves);
  520. write_rtt_gnuplot_script (filename_master, &l->lp[c_m], filename_slaves, l->num_slaves);
  521. write_bw_gnuplot_script (filename_master, &l->lp[c_m], filename_slaves, l->num_slaves);
  522. }
  523. }
  524. GNUNET_free (filename_master);
  525. }
  526. /**
  527. * Log all data now
  528. *
  529. * @param l logging handle to use
  530. */
  531. void
  532. GNUNET_ATS_TEST_logging_now (struct LoggingHandle *l)
  533. {
  534. struct LoggingPeer *bp;
  535. struct PeerLoggingTimestep *mlt;
  536. struct PeerLoggingTimestep *prev_log_mlt;
  537. struct PartnerLoggingTimestep *slt;
  538. struct PartnerLoggingTimestep *prev_log_slt;
  539. struct BenchmarkPartner *p;
  540. struct GNUNET_TIME_Relative delta;
  541. int c_s;
  542. int c_m;
  543. unsigned int app_rtt;
  544. double mult;
  545. if (GNUNET_YES != l->running)
  546. return;
  547. for (c_m = 0; c_m < l->num_masters; c_m++)
  548. {
  549. bp = &l->lp[c_m];
  550. mlt = GNUNET_new (struct PeerLoggingTimestep);
  551. GNUNET_CONTAINER_DLL_insert_tail(l->lp[c_m].head, l->lp[c_m].tail, mlt);
  552. prev_log_mlt = mlt->prev;
  553. /* Collect data */
  554. /* Current master state */
  555. mlt->timestamp = GNUNET_TIME_absolute_get();
  556. mlt->total_bytes_sent = bp->peer->total_bytes_sent;
  557. mlt->total_messages_sent = bp->peer->total_messages_sent;
  558. mlt->total_bytes_received = bp->peer->total_bytes_received;
  559. mlt->total_messages_received = bp->peer->total_messages_received;
  560. /* Throughput */
  561. if (NULL == prev_log_mlt)
  562. {
  563. /* Get difference to start */
  564. delta = GNUNET_TIME_absolute_get_difference (l->lp[c_m].start, mlt->timestamp);
  565. }
  566. else
  567. {
  568. /* Get difference to last timestep */
  569. delta = GNUNET_TIME_absolute_get_difference (mlt->prev->timestamp, mlt->timestamp);
  570. }
  571. /* Multiplication factor for throughput calculation */
  572. mult = (double) GNUNET_TIME_UNIT_SECONDS.rel_value_us / (delta.rel_value_us);
  573. /* Total throughput */
  574. if (NULL != prev_log_mlt)
  575. {
  576. if (mlt->total_bytes_sent - mlt->prev->total_bytes_sent > 0)
  577. {
  578. mlt->total_throughput_send = mult * (mlt->total_bytes_sent - mlt->prev->total_bytes_sent);
  579. }
  580. else
  581. {
  582. mlt->total_throughput_send = 0;
  583. // mlt->total_throughput_send = prev_log_mlt->total_throughput_send; /* no msgs send */
  584. }
  585. if (mlt->total_bytes_received - mlt->prev->total_bytes_received > 0)
  586. {
  587. mlt->total_throughput_recv = mult * (mlt->total_bytes_received - mlt->prev->total_bytes_received);
  588. }
  589. else
  590. {
  591. mlt->total_throughput_recv = 0;
  592. //mlt->total_throughput_recv = prev_log_mlt->total_throughput_recv; /* no msgs received */
  593. }
  594. }
  595. else
  596. {
  597. mlt->total_throughput_send = mult * mlt->total_bytes_sent;
  598. mlt->total_throughput_recv = mult * mlt->total_bytes_received;
  599. }
  600. if (GNUNET_YES == l->verbose)
  601. {
  602. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  603. "Master[%u] delta: %llu us, bytes (sent/received): %u / %u; throughput send/recv: %u / %u\n",
  604. c_m,
  605. (unsigned long long) delta.rel_value_us,
  606. mlt->total_bytes_sent,
  607. mlt->total_bytes_received,
  608. mlt->total_throughput_send,
  609. mlt->total_throughput_recv);
  610. }
  611. mlt->slaves_log = GNUNET_malloc (bp->peer->num_partners *
  612. sizeof (struct PartnerLoggingTimestep));
  613. for (c_s = 0; c_s < bp->peer->num_partners; c_s++)
  614. {
  615. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  616. "Collect logging data master[%u] slave [%u]\n", c_m, c_s);
  617. p = &bp->peer->partners[c_s];
  618. slt = &mlt->slaves_log[c_s];
  619. slt->slave = p->dest;
  620. /* Bytes sent from master to this slave */
  621. slt->total_bytes_sent = p->bytes_sent;
  622. /* Messages sent from master to this slave */
  623. slt->total_messages_sent = p->messages_sent;
  624. /* Bytes master received from this slave */
  625. slt->total_bytes_received = p->bytes_received;
  626. /* Messages master received from this slave */
  627. slt->total_messages_received = p->messages_received;
  628. slt->total_app_rtt = p->total_app_rtt;
  629. /* ats performance information */
  630. slt->ats_delay = p->props.delay;
  631. slt->ats_distance = p->props.distance;
  632. slt->ats_network_type = p->props.scope;
  633. slt->ats_utilization_in = p->props.utilization_out;
  634. slt->ats_utilization_out = p->props.utilization_out;
  635. slt->bandwidth_in = p->bandwidth_in;
  636. slt->bandwidth_out = p->bandwidth_out;
  637. slt->pref_bandwidth = p->pref_bandwidth;
  638. slt->pref_delay = p->pref_delay;
  639. /* Total application level rtt */
  640. if (NULL == prev_log_mlt)
  641. {
  642. if (0 != slt->total_messages_sent)
  643. app_rtt = slt->total_app_rtt / slt->total_messages_sent;
  644. else
  645. app_rtt = 0;
  646. }
  647. else
  648. {
  649. prev_log_slt = &prev_log_mlt->slaves_log[c_s];
  650. if ((slt->total_messages_sent - prev_log_slt->total_messages_sent) > 0)
  651. app_rtt = (slt->total_app_rtt - prev_log_slt->total_app_rtt) /
  652. (slt->total_messages_sent - prev_log_slt->total_messages_sent);
  653. else
  654. {
  655. app_rtt = prev_log_slt->app_rtt; /* No messages were */
  656. }
  657. }
  658. slt->app_rtt = app_rtt;
  659. /* Partner throughput */
  660. if (NULL != prev_log_mlt)
  661. {
  662. prev_log_slt = &prev_log_mlt->slaves_log[c_s];
  663. if (slt->total_bytes_sent > prev_log_slt->total_bytes_sent)
  664. slt->throughput_sent = mult * (slt->total_bytes_sent - prev_log_slt->total_bytes_sent);
  665. else
  666. slt->throughput_sent = 0;
  667. if (slt->total_bytes_received > prev_log_slt->total_bytes_received)
  668. slt->throughput_recv = mult *
  669. (slt->total_bytes_received - prev_log_slt->total_bytes_received);
  670. else
  671. slt->throughput_recv = 0;
  672. }
  673. else
  674. {
  675. slt->throughput_sent = mult * slt->total_bytes_sent;
  676. slt->throughput_recv = mult * slt->total_bytes_received;
  677. }
  678. if (GNUNET_YES == l->verbose)
  679. {
  680. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  681. "Master [%u] -> Slave [%u]: delta: %llu us, bytes (sent/received): %u / %u; throughput send/recv: %u / %u\n",
  682. c_m, c_s,
  683. (unsigned long long) delta.rel_value_us,
  684. mlt->total_bytes_sent,
  685. mlt->total_bytes_received,
  686. slt->throughput_sent,
  687. slt->throughput_recv);
  688. }
  689. else
  690. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  691. "Master [%u]: slave [%u]\n",
  692. bp->peer->no, p->dest->no);
  693. }
  694. }
  695. }
  696. static void
  697. collect_log_task (void *cls)
  698. {
  699. struct LoggingHandle *l = cls;
  700. l->log_task = NULL;
  701. GNUNET_ATS_TEST_logging_now (l);
  702. l->log_task = GNUNET_SCHEDULER_add_delayed (l->frequency,
  703. &collect_log_task,
  704. l);
  705. }
  706. /**
  707. * Stop logging
  708. *
  709. * @param l the logging handle
  710. */
  711. void
  712. GNUNET_ATS_TEST_logging_stop (struct LoggingHandle *l)
  713. {
  714. if (GNUNET_YES!= l->running)
  715. return;
  716. if (NULL != l->log_task)
  717. {
  718. GNUNET_SCHEDULER_cancel (l->log_task);
  719. l->log_task = NULL;
  720. }
  721. l->running = GNUNET_NO;
  722. GNUNET_log(GNUNET_ERROR_TYPE_INFO,
  723. _("Stop logging\n"));
  724. }
  725. /**
  726. * Clean up logging data
  727. *
  728. * @param l the logging handle
  729. */
  730. void
  731. GNUNET_ATS_TEST_logging_clean_up (struct LoggingHandle *l)
  732. {
  733. int c_m;
  734. struct PeerLoggingTimestep *cur;
  735. if (GNUNET_YES == l->running)
  736. GNUNET_ATS_TEST_logging_stop (l);
  737. for (c_m = 0; c_m < l->num_masters; c_m++)
  738. {
  739. while (NULL != (cur = l->lp[c_m].head))
  740. {
  741. GNUNET_CONTAINER_DLL_remove (l->lp[c_m].head, l->lp[c_m].tail, cur);
  742. GNUNET_free (cur->slaves_log);
  743. GNUNET_free (cur);
  744. }
  745. }
  746. GNUNET_free (l->lp);
  747. GNUNET_free (l);
  748. }
  749. /**
  750. * Start logging
  751. *
  752. * @param log_frequency the logging frequency
  753. * @param testname the testname
  754. * @param masters the master peers used for benchmarking
  755. * @param num_masters the number of master peers
  756. * @param num_slaves the number of slave peers
  757. * @param verbose verbose logging
  758. * @return the logging handle or NULL on error
  759. */
  760. struct LoggingHandle *
  761. GNUNET_ATS_TEST_logging_start(struct GNUNET_TIME_Relative log_frequency,
  762. const char *testname,
  763. struct BenchmarkPeer *masters,
  764. int num_masters,
  765. int num_slaves,
  766. int verbose)
  767. {
  768. struct LoggingHandle *l;
  769. int c_m;
  770. GNUNET_log(GNUNET_ERROR_TYPE_INFO,
  771. _("Start logging `%s'\n"), testname);
  772. l = GNUNET_new (struct LoggingHandle);
  773. l->num_masters = num_masters;
  774. l->num_slaves = num_slaves;
  775. l->name = testname;
  776. l->frequency = log_frequency;
  777. l->verbose = verbose;
  778. l->lp = GNUNET_malloc (num_masters * sizeof (struct LoggingPeer));
  779. for (c_m = 0; c_m < num_masters; c_m ++)
  780. {
  781. l->lp[c_m].peer = &masters[c_m];
  782. l->lp[c_m].start = GNUNET_TIME_absolute_get();
  783. }
  784. /* Schedule logging task */
  785. l->log_task = GNUNET_SCHEDULER_add_now (&collect_log_task, l);
  786. l->running = GNUNET_YES;
  787. return l;
  788. }
  789. /* end of file ats-testing-log.c */