1 /*
2  * stats.c
3  * Statistics gathering and printing.
4  *
5  * Copyright (c) 2002 Christoph Pfisterer
6  *
7  * Permission is hereby granted, free of charge, to any person
8  * obtaining a copy of this software and associated documentation
9  * files (the "Software"), to deal in the Software without
10  * restriction, including without limitation the rights to use, copy,
11  * modify, merge, publish, distribute, sublicense, and/or sell copies
12  * of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #include "netstrain.h"
29 
30 /* settings */
31 #define QUANTUM (2)
32 
33 /* internal functions */
34 static void stats_hook(counter_t sendcount, counter_t recvcount);
35 static void stats_line(const char *prefix,
36 		       counter_t total_b, counter_t last_b,
37 		       counter_t total_us, counter_t last_us);
38 static void print_count(counter_t count);
39 static void print_rate(counter_t rate);
40 static counter_t timestamp(void);
41 
42 /* internal data */
43 static time_t next_time;
44 static counter_t start_stamp;
45 static counter_t last_stamp;
46 static counter_t last_sendcount = 0;
47 static counter_t last_recvcount = 0;
48 
49 
stats_init(void)50 void stats_init(void)
51 {
52   next_time = time(NULL) + QUANTUM;
53   last_stamp = start_stamp = timestamp();
54 
55   transfer_hook(stats_hook);
56 
57   printf("sent:   please wait...\nrecv'd:\n");
58 }
59 
stats_hook(counter_t sendcount,counter_t recvcount)60 static void stats_hook(counter_t sendcount, counter_t recvcount)
61 {
62   time_t now;
63   counter_t now_stamp;
64   counter_t total_b, last_b, total_us, last_us;
65 
66   now = time(NULL);
67   if (now < next_time)
68     return;
69   next_time = now + QUANTUM;
70 
71   now_stamp = timestamp();
72   total_us = now_stamp - start_stamp;
73   last_us = now_stamp - last_stamp;
74   last_stamp = now_stamp;
75 
76   printf("\033[A\033[K\033[A\033[K");
77 
78   total_b = sendcount;
79   last_b = total_b - last_sendcount;
80   last_sendcount = total_b;
81   stats_line("sent:   ", total_b, last_b, total_us, last_us);
82 
83   total_b = recvcount;
84   last_b = total_b - last_recvcount;
85   last_recvcount = total_b;
86   stats_line("recv'd: ", total_b, last_b, total_us, last_us);
87 }
88 
stats_line(const char * prefix,counter_t total_b,counter_t last_b,counter_t total_us,counter_t last_us)89 static void stats_line(const char *prefix,
90 		       counter_t total_b, counter_t last_b,
91 		       counter_t total_us, counter_t last_us)
92 {
93   counter_t total_bps, last_bps;
94 
95   total_bps = (total_b * 1000000 + (total_us >> 1)) / total_us;
96   last_bps = (last_b * 1000000 + (last_us >> 1)) / last_us;
97 
98   printf("%s", prefix);
99   print_count(total_b);
100   printf(", ");
101   print_rate(total_bps);
102   printf(" total, ");
103   print_rate(last_bps);
104   printf(" current\n");
105 }
106 
print_count(counter_t count)107 static void print_count(counter_t count)
108 {
109   int card;
110 
111   if (count < 100000) {
112     card = (int)count;
113     printf("%7dB", card);
114   } else {
115     count >>= 10;
116     if (count < 100000) {
117       card = (int)count;
118       printf("%7dK", card);
119     } else {
120       count >>= 10;
121       card = (int)count;
122       printf("%7dM", card);
123     }
124   }
125 }
126 
print_rate(counter_t rate)127 static void print_rate(counter_t rate)
128 {
129   counter_t card_c;
130   int card;
131   int frac;
132 
133   if (rate > 10240) {
134     card_c = rate >> 10;
135     if (card_c >= 10000000) {
136       printf("      \"huge\"");
137     } else {
138       card = (int)card_c;
139       frac = (int)(((rate * 10) >> 10) % 10);
140       printf("%7d.%01dK/s", card, frac);
141     }
142   } else {
143     card = (int)rate;
144     printf("%9dB/s", card);
145   }
146 }
147 
timestamp(void)148 static counter_t timestamp(void)
149 {
150   struct timeval tv;
151 
152   gettimeofday(&tv, NULL);
153   return (counter_t)tv.tv_sec * 1000000 + (counter_t)tv.tv_usec;
154 }
155