-fix (C) notices
[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
6  it under the terms of the GNU General Public License as published
7  by the Free Software Foundation; either version 3, or (at your
8  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  General Public License for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with GNUnet; see the file COPYING.  If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
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 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
260   if (NULL == f)
261   {
262     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
263     GNUNET_free (gfn);
264     return;
265   }
266
267   /* Write header */
268
269   if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, THROUGHPUT_TEMPLATE, strlen(THROUGHPUT_TEMPLATE)))
270     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
271
272   /* Write master data */
273   peer_index = LOG_ITEMS_TIME;
274   GNUNET_asprintf (&data, "plot '%s' using 2:%u with lines title 'Master %u send total', \\\n" \
275                            "'%s' using 2:%u with lines title 'Master %u receive total', \\\n",
276                            fn, peer_index + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no,
277                            fn, peer_index + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no);
278   if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
279     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
280   GNUNET_free (data);
281
282   peer_index = LOG_ITEMS_TIME + LOG_ITEMS_PER_PEER ;
283   for (c_s = 0; c_s < lp->peer->num_partners; c_s++)
284   {
285     GNUNET_asprintf (&data, "'%s' using 2:%u with lines title 'Master %u - Slave %u send', \\\n" \
286                             "'%s' using 2:%u with lines title 'Master %u - Slave %u receive'%s\n",
287                             fn, peer_index + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no, lp->peer->partners[c_s].dest->no,
288                             fn, peer_index + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no, lp->peer->partners[c_s].dest->no,
289                             (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1");
290     if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
291         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
292     GNUNET_free (data);
293     peer_index += LOG_ITEMS_PER_PEER;
294   }
295
296   if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
297     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn);
298   else
299     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn);
300
301   GNUNET_free (gfn);
302 }
303
304
305 static void
306 write_rtt_gnuplot_script (char * fn, struct LoggingPeer *lp)
307 {
308   struct GNUNET_DISK_FileHandle *f;
309   char * gfn;
310   char *data;
311   int c_s;
312   int index;
313
314   GNUNET_asprintf (&gfn, "gnuplot_rtt_%s",fn);
315   f = GNUNET_DISK_file_open (gfn,
316       GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
317       GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
318   if (NULL == f)
319   {
320     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
321     GNUNET_free (gfn);
322     return;
323   }
324
325   /* Write header */
326
327   if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, RTT_TEMPLATE, strlen(RTT_TEMPLATE)))
328     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
329
330   index = LOG_ITEMS_TIME + LOG_ITEMS_PER_PEER;
331   for (c_s = 0; c_s < lp->peer->num_partners; c_s++)
332   {
333     GNUNET_asprintf (&data, "%s'%s' using 2:%u with lines title 'Master %u - Slave %u '%s\n",
334         (0 == c_s) ? "plot " :"",
335         fn, index + LOG_ITEM_APP_RTT, lp->peer->no, lp->peer->partners[c_s].dest->no,
336         (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1");
337     if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
338         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
339     GNUNET_free (data);
340     index += LOG_ITEMS_PER_PEER;
341   }
342
343   if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
344     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn);
345   else
346     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn);
347   GNUNET_free (gfn);
348 }
349
350 static void
351 write_bw_gnuplot_script (char * fn, struct LoggingPeer *lp)
352 {
353   struct GNUNET_DISK_FileHandle *f;
354   char * gfn;
355   char *data;
356   int c_s;
357   int index;
358
359   GNUNET_asprintf (&gfn, "gnuplot_bw_%s",fn);
360   f = GNUNET_DISK_file_open (gfn,
361       GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
362       GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
363   if (NULL == f)
364   {
365     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
366     GNUNET_free (gfn);
367     return;
368   }
369
370   /* Write header */
371
372   if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, BW_TEMPLATE, strlen(BW_TEMPLATE)))
373     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
374
375   index = LOG_ITEMS_TIME + LOG_ITEMS_PER_PEER;
376   for (c_s = 0; c_s < lp->peer->num_partners; c_s++)
377   {
378     GNUNET_asprintf (&data, "%s"\
379         "'%s' using 2:%u with lines title 'BW out master %u - Slave %u ', \\\n" \
380         "'%s' using 2:%u with lines title 'BW in master %u - Slave %u '"\
381         "%s\n",
382         (0 == c_s) ? "plot " :"",
383         fn, index + LOG_ITEM_ATS_BW_OUT, lp->peer->no, lp->peer->partners[c_s].dest->no,
384         fn, index + LOG_ITEM_ATS_BW_IN, lp->peer->no, lp->peer->partners[c_s].dest->no,
385         (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1");
386     if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
387         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
388     GNUNET_free (data);
389     index += LOG_ITEMS_PER_PEER;
390   }
391
392   if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
393     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn);
394   else
395     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn);
396   GNUNET_free (gfn);
397 }
398
399
400 static void
401 write_to_file ()
402 {
403   struct GNUNET_DISK_FileHandle *f;
404
405   char * filename;
406   char *data;
407   char *slave_string;
408   char *slave_string_tmp;
409   struct PeerLoggingTimestep *cur_lt;
410   struct PartnerLoggingTimestep *plt;
411   int c_m;
412   int c_s;
413
414   for (c_m = 0; c_m < num_peers; c_m++)
415   {
416     GNUNET_asprintf (&filename, "%llu_master_%u_%s_%s.data", GNUNET_TIME_absolute_get().abs_value_us,
417         lp[c_m].peer->no, GNUNET_i2s(&lp[c_m].peer->id), name);
418
419     f = GNUNET_DISK_file_open (filename,
420         GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
421         GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
422     if (NULL == f)
423     {
424       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n", filename);
425       GNUNET_free (filename);
426       return;
427     }
428
429     for (cur_lt = lp[c_m].head; NULL != cur_lt; cur_lt = cur_lt->next)
430     {
431        GNUNET_log(GNUNET_ERROR_TYPE_INFO,
432           "Master [%u]: timestamp %llu %llu ; %u %u %u ; %u %u %u\n", lp[c_m].peer->no,
433           cur_lt->timestamp, GNUNET_TIME_absolute_get_difference(lp[c_m].start,cur_lt->timestamp).rel_value_us / 1000,
434           cur_lt->total_messages_sent, cur_lt->total_bytes_sent, cur_lt->total_throughput_send,
435           cur_lt->total_messages_received, cur_lt->total_bytes_received, cur_lt->total_throughput_recv);
436
437       slave_string = GNUNET_strdup (";");
438       for (c_s = 0; c_s < lp[c_m].peer->num_partners; c_s++)
439       {
440         plt = &cur_lt->slaves_log[c_s];
441         /* Log partners */
442
443         /* Assembling slave string */
444         GNUNET_log(GNUNET_ERROR_TYPE_INFO,
445             "\t Slave [%u]: %u %u %u ; %u %u %u rtt %u delay %u bw_in %u bw_out %u \n", plt->slave->no,
446             plt->total_messages_sent, plt->total_bytes_sent, plt->throughput_sent,
447             plt->total_messages_received, plt->total_bytes_received, plt->throughput_recv,
448             plt->app_rtt, plt->ats_delay,
449             plt->bandwidth_in, plt->bandwidth_out);
450
451         GNUNET_asprintf(&slave_string_tmp, "%s%u;%u;%u;%u;%u;%u;%.3f;%u;%u;%u;%u;%u;%u;%u;%u;%u;%u;",slave_string,
452             plt->total_messages_sent, plt->total_bytes_sent,  plt->throughput_sent,
453             plt->total_messages_received, plt->total_bytes_received,  plt->throughput_sent,
454             (double) plt->app_rtt / 1000,
455             plt->bandwidth_in,plt->bandwidth_out,
456             plt->ats_cost_lan, plt->ats_cost_wan, plt->ats_cost_wlan,
457             plt->ats_delay, plt->ats_distance, plt->ats_network_type,
458             plt->ats_utilization_up, plt->ats_utilization_down);
459         GNUNET_free (slave_string);
460         slave_string = slave_string_tmp;
461       }
462       /* Assembling master string */
463
464
465
466       GNUNET_asprintf (&data, "%llu;%llu;%u;%u;%u;%u;%u;%u;;;;;;;;;;;%s\n",
467           cur_lt->timestamp,
468           GNUNET_TIME_absolute_get_difference(lp[c_m].start,cur_lt->timestamp).rel_value_us / 1000,
469           cur_lt->total_messages_sent, cur_lt->total_bytes_sent,  cur_lt->total_throughput_send,
470           cur_lt->total_messages_received, cur_lt->total_bytes_received, cur_lt->total_throughput_recv,
471           slave_string);
472       GNUNET_free (slave_string);
473
474       if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
475         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", filename);
476       GNUNET_free (data);
477     }
478     if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
479     {
480       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", filename);
481       GNUNET_free (filename);
482       return;
483     }
484
485     write_throughput_gnuplot_script (filename, lp);
486     write_rtt_gnuplot_script (filename, lp);
487     write_bw_gnuplot_script (filename, lp);
488
489     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data file successfully written to log file `%s'\n", filename);
490     GNUNET_free (filename);
491   }
492 }
493
494
495 void
496 collect_log_now (void)
497 {
498   struct LoggingPeer *bp;
499   struct PeerLoggingTimestep *mlt;
500   struct PeerLoggingTimestep *prev_log_mlt;
501   struct PartnerLoggingTimestep *slt;
502   struct PartnerLoggingTimestep *prev_log_slt;
503   struct BenchmarkPartner *p;
504   struct GNUNET_TIME_Relative delta;
505   int c_s;
506   int c_m;
507   unsigned int app_rtt;
508   double mult;
509
510   if (GNUNET_YES != running)
511     return;
512
513   for (c_m = 0; c_m < num_peers; c_m++)
514   {
515     bp = &lp[c_m];
516     mlt = GNUNET_new (struct PeerLoggingTimestep);
517     GNUNET_CONTAINER_DLL_insert_tail(bp->head, bp->tail, mlt);
518     prev_log_mlt = mlt->prev;
519
520     /* Collect data */
521
522     /* Current master state */
523     mlt->timestamp = GNUNET_TIME_absolute_get();
524     mlt->total_bytes_sent = bp->peer->total_bytes_sent;
525     mlt->total_messages_sent = bp->peer->total_messages_sent;
526     mlt->total_bytes_received = bp->peer->total_bytes_received;
527     mlt->total_messages_received = bp->peer->total_messages_received;
528
529     /* Throughput */
530     if (NULL == prev_log_mlt)
531      {
532        /* Get difference to start */
533        delta = GNUNET_TIME_absolute_get_difference (lp[c_m].start, mlt->timestamp);
534      }
535      else
536      {
537        /* Get difference to last timestep */
538        delta = GNUNET_TIME_absolute_get_difference (mlt->prev->timestamp, mlt->timestamp);
539      }
540
541      /* Multiplication factor for throughput calculation */
542      mult = (1.0 * 1000 * 1000) / (delta.rel_value_us);
543
544      /* Total throughput */
545      if (NULL != prev_log_mlt)
546      {
547        if (mlt->total_bytes_sent - mlt->prev->total_bytes_sent > 0)
548          mlt->total_throughput_send = mult * (mlt->total_bytes_sent - mlt->prev->total_bytes_sent);
549        else
550          mlt->total_throughput_send = prev_log_mlt->total_throughput_send; /* no msgs send */
551
552        if (mlt->total_bytes_received - mlt->prev->total_bytes_received > 0)
553          mlt->total_throughput_recv = mult * (mlt->total_bytes_received - mlt->prev->total_bytes_received);
554        else
555          mlt->total_throughput_recv = prev_log_mlt->total_throughput_recv; /* no msgs received */
556      }
557      else
558      {
559        mlt->total_throughput_send = mult * mlt->total_bytes_sent;
560        mlt->total_throughput_send = mult * mlt->total_bytes_received;
561      }
562
563     mlt->slaves_log = GNUNET_malloc (bp->peer->num_partners *
564         sizeof (struct PartnerLoggingTimestep));
565
566     for (c_s = 0; c_s < bp->peer->num_partners; c_s++)
567     {
568       p = &bp->peer->partners[c_s];
569       slt = &mlt->slaves_log[c_s];
570
571       slt->slave = p->dest;
572       /* Bytes sent from master to this slave */
573       slt->total_bytes_sent = p->bytes_sent;
574       /* Messages sent from master to this slave */
575       slt->total_messages_sent = p->messages_sent;
576       /* Bytes master received from this slave */
577       slt->total_bytes_received = p->bytes_received;
578       /* Messages master received from this slave */
579       slt->total_messages_received = p->messages_received;
580       slt->total_app_rtt = p->total_app_rtt;
581       /* ats performance information */
582       slt->ats_cost_lan = p->ats_cost_lan;
583       slt->ats_cost_wan = p->ats_cost_wan;
584       slt->ats_cost_wlan = p->ats_cost_wlan;
585       slt->ats_delay = p->ats_delay;
586       slt->ats_distance = p->ats_distance;
587       slt->ats_network_type = p->ats_network_type;
588       slt->ats_utilization_down = p->ats_utilization_down;
589       slt->ats_utilization_up = p->ats_utilization_up;
590       slt->bandwidth_in = p->bandwidth_in;
591       slt->bandwidth_out = p->bandwidth_out;
592
593       /* Total application level rtt  */
594       if (NULL == prev_log_mlt)
595       {
596         if (0 != slt->total_messages_sent)
597           app_rtt = slt->total_app_rtt / slt->total_messages_sent;
598         else
599           app_rtt = 0;
600       }
601       else
602       {
603         prev_log_slt =  &prev_log_mlt->slaves_log[c_s];
604         if ((slt->total_messages_sent - prev_log_slt->total_messages_sent) > 0)
605           app_rtt = (slt->total_app_rtt - prev_log_slt->total_app_rtt) /
606                   (slt->total_messages_sent - prev_log_slt->total_messages_sent);
607         else
608           app_rtt = prev_log_slt->app_rtt; /* No messages were */
609       }
610       slt->app_rtt = app_rtt;
611
612       /* Partner throughput */
613       if (NULL != prev_log_mlt)
614       {
615         prev_log_slt =  &prev_log_mlt->slaves_log[c_s];
616         if (slt->total_bytes_sent - prev_log_slt->total_bytes_sent > 0)
617           slt->throughput_sent = mult * (slt->total_bytes_sent - prev_log_slt->total_bytes_sent);
618         else
619           slt->throughput_sent = prev_log_slt->throughput_sent; /* no msgs send */
620
621         if (slt->total_bytes_received - prev_log_slt->total_bytes_received > 0)
622           slt->throughput_recv = mult * (slt->total_bytes_received - prev_log_slt->total_bytes_received);
623         else
624           slt->throughput_recv = prev_log_slt->throughput_recv; /* no msgs received */
625       }
626       else
627       {
628         slt->throughput_sent = mult * slt->total_bytes_sent;
629         slt->throughput_sent = mult * slt->total_bytes_received;
630       }
631
632       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
633           "Master [%u]: slave [%u]\n",
634           bp->peer->no, p->dest->no);
635     }
636   }
637 }
638
639 static void
640 collect_log_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
641 {
642   log_task = NULL;
643
644   collect_log_now();
645
646   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
647     return;
648
649   log_task = GNUNET_SCHEDULER_add_delayed (frequency,
650       &collect_log_task, NULL);
651 }
652
653
654 void
655 perf_logging_stop ()
656 {
657   int c_m;
658   struct GNUNET_SCHEDULER_TaskContext tc;
659   struct PeerLoggingTimestep *cur;
660
661   if (GNUNET_YES!= running)
662     return;
663
664   if (NULL != log_task)
665     GNUNET_SCHEDULER_cancel (log_task);
666   log_task = NULL;
667   tc.reason = GNUNET_SCHEDULER_REASON_SHUTDOWN;
668   collect_log_task (NULL, &tc);
669
670   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
671       _("Stop logging\n"));
672
673   write_to_file ();
674
675   for (c_m = 0; c_m < num_peers; c_m++)
676   {
677     while (NULL != (cur = lp[c_m].head))
678     {
679       GNUNET_CONTAINER_DLL_remove (lp[c_m].head, lp[c_m].tail, cur);
680       GNUNET_free (cur->slaves_log);
681       GNUNET_free (cur);
682     }
683   }
684
685   GNUNET_free (lp);
686 }
687
688 void
689 perf_logging_start (struct GNUNET_TIME_Relative log_frequency,
690     char * testname, struct BenchmarkPeer *masters, int num_masters)
691 {
692   int c_m;
693   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
694       _("Start logging `%s'\n"), testname);
695
696   num_peers = num_masters;
697   name = testname;
698   frequency = log_frequency;
699
700   lp = GNUNET_malloc (num_masters * sizeof (struct LoggingPeer));
701
702   for (c_m = 0; c_m < num_masters; c_m ++)
703   {
704     lp[c_m].peer = &masters[c_m];
705     lp[c_m].start = GNUNET_TIME_absolute_get();
706   }
707
708   /* Schedule logging task */
709   log_task = GNUNET_SCHEDULER_add_now (&collect_log_task, NULL);
710   running = GNUNET_YES;
711 }
712 /* end of file perf_ats_logging.c */
713