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