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