@cryptotaxi247 / netdata-1 / commits / 2a824f13c

now it works internally in microseconds and automatically adjusts sleep time to loop exactly the seconds given on the command line. Even if for some reason it exceeds the time given, it calculates correctly bandwidths per second.

now it works internally in microseconds and automatically adjusts sleep time to loop exactly the seconds given on the command line. Even if for some reason it exceeds the time given, it calculates correctly bandwidths per second.

box@home root committed Jun 20, 2013 at 23:18 UTC 2a824f13cac2e2d98a8226abdc8bf7ce37cc2fc5
1 file changed +98 -54
netdata.c
+98 -54
@@ -4,12 +4,15 @@
4 #include <time.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 +#include <sys/time.h>
8
9 // internal defaults
10 #define UPDATE_EVERY 1
11 #define HISTORY 3600
12 #define SAVE_PATH "/tmp"
13
14 +#define DEBUG 0
15 +
16 // configuration
17 #define MAX_LINE 4096
18 #define MAX_IFACE_NAME 1024
@@ -19,6 +22,8 @@ int save_history = 60;
22
23 struct iface_history {
24 time_t time;
25 + unsigned long long usec;
26 +
27 unsigned long long rbytes;
28 unsigned long long tbytes;
29 };
@@ -32,7 +37,7 @@ struct iface_stats {
37 struct iface_stats *next;
38 } *interfaces = NULL;
39
35 -void update_iface_history(char *name, unsigned long long rbytes, unsigned long long tbytes) {
40 +void update_iface_history(unsigned long long usec, char *name, unsigned long long rbytes, unsigned long long tbytes) {
41 struct iface_stats *iface = NULL;
42
43 for(iface = interfaces; iface != NULL; iface = iface->next)
@@ -41,7 +46,7 @@ void update_iface_history(char *name, unsigned long long rbytes, unsigned long l
46 if(!iface) {
47 int i;
48
44 - // printf("Creating new interface for %s\n", name);
49 + if(DEBUG) printf("Creating new interface for %s\n", name);
50
51 iface = malloc(sizeof(struct iface_stats));
52 if(!iface) return;
@@ -56,21 +61,23 @@ void update_iface_history(char *name, unsigned long long rbytes, unsigned long l
61 iface->history[i].time = time(NULL) - HISTORY + (i * update_every);
62 iface->history[i].rbytes = rbytes;
63 iface->history[i].tbytes = tbytes;
64 + iface->history[i].usec = usec;
65 }
66 }
67
68 iface->last_history_id++;
69 if(iface->last_history_id >= HISTORY) iface->last_history_id = 0;
70
65 - // printf("Updating values for interface %s at position %d, rbytes = %llu, tbytes = %llu\n", iface->name, iface->last_history_id, rbytes, tbytes);
71 + if(DEBUG) printf("Updating values for interface %s at position %d, rbytes = %llu, tbytes = %llu\n", iface->name, iface->last_history_id, rbytes, tbytes);
72
73 strcpy(iface->name, name);
74 iface->history[iface->last_history_id].time = time(NULL);
75 iface->history[iface->last_history_id].rbytes = rbytes;
76 iface->history[iface->last_history_id].tbytes = tbytes;
77 + iface->history[iface->last_history_id].usec = usec;
78 }
79
73 -void save_stats() {
80 +void save_proc_net_dev() {
81 struct iface_stats *iface = NULL;
82 int r;
83
@@ -107,8 +114,10 @@ void save_stats() {
114
115 dt = iface->history[ld].time - iface->history[d].time;
116 if(dt == 0) dt = 1;
110 - rb = (iface->history[ld].rbytes - iface->history[d].rbytes) * 8 / dt / 1024;
111 - tb = (iface->history[ld].tbytes - iface->history[d].tbytes) * 8 / dt / 1024;
117 + //rb = (iface->history[ld].rbytes - iface->history[d].rbytes) * 8 / dt / 1024;
118 + //tb = (iface->history[ld].tbytes - iface->history[d].tbytes) * 8 / dt / 1024;
119 + rb = (iface->history[ld].rbytes - iface->history[d].rbytes) * 1000000 * 8 / iface->history[ld].usec / 1024;
120 + tb = (iface->history[ld].tbytes - iface->history[d].tbytes) * 1000000 * 8 / iface->history[ld].usec / 1024;
121
122 s = time(NULL) - iface->history[ld].time;
123
@@ -135,11 +144,62 @@ void save_stats() {
144 }
145 }
146
138 -int main(int argc, char **argv) {
147 +int do_proc_net_dev(unsigned long long usec) {
148 char buffer[MAX_LINE+1] = "";
149 char iface[MAX_IFACE_NAME + 1] = "";
150 unsigned long long rbytes, rpackets, rerrors, rdrops, rfifo, rframe, rcompressed, rmulticast;
151 unsigned long long tbytes, tpackets, terrors, tdrops, tfifo, tcollisions, tcarrier, tcompressed;
152 +
153 + int r;
154 + char *p;
155 +
156 + FILE *fp = fopen("/proc/net/dev", "r");
157 + if(!fp) {
158 + perror("/proc/net/dev");
159 + return 1;
160 + }
161 +
162 + // skip the first two lines
163 + p = fgets(buffer, MAX_LINE, fp);
164 + p = fgets(buffer, MAX_LINE, fp);
165 +
166 + // read the rest of the lines
167 + for(;1;) {
168 + char *c;
169 + p = fgets(buffer, MAX_LINE, fp);
170 + if(!p) break;
171 +
172 + c = strchr(buffer, ':');
173 + if(c) *c = '\t';
174 +
175 + // if(DEBUG) printf("%s\n", buffer);
176 + r = sscanf(buffer, "%s\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\n",
177 + iface,
178 + &rbytes, &rpackets, &rerrors, &rdrops, &rfifo, &rframe, &rcompressed, &rmulticast,
179 + &tbytes, &tpackets, &terrors, &tdrops, &tfifo, &tcollisions, &tcarrier, &tcompressed);
180 + if(r == EOF) break;
181 + if(r != 17) fprintf(stderr, "Cannot read line. Expected 17 params, read %d\n", r);
182 + else {
183 + // update our data
184 + update_iface_history(usec, iface, rbytes, tbytes);
185 + }
186 + }
187 +
188 + // done reading, close it
189 + fclose(fp);
190 +
191 + // save statistics
192 + save_proc_net_dev();
193 +
194 + return 0;
195 +}
196 +
197 +unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
198 + return ((((now->tv_sec * 1000000) + now->tv_usec) - ((last->tv_sec * 1000000) + last->tv_usec)));
199 +}
200 +
201 +int main(int argc, char **argv) {
202 + struct timeval last, now, tmp;
203 int i;
204 int daemon = 0;
205
@@ -200,54 +260,38 @@ int main(int argc, char **argv) {
260 close(2);
261 }
262
263 + // main loop
264 + gettimeofday(&last, NULL);
265 + last.tv_sec -= update_every;
266 +
267 for(;1;) {
204 - FILE *fp = fopen("/proc/net/dev", "r");
205 - int r;
206 - char *p;
207 -
208 - if(!fp) {
209 - perror("/proc/net/dev");
210 - sleep(1);
211 - continue;
212 - }
213 -
214 - // skip the first two lines
215 - p = fgets(buffer, MAX_LINE, fp);
216 - p = fgets(buffer, MAX_LINE, fp);
268 + unsigned long long usec, susec;
269 + gettimeofday(&now, NULL);
270
218 - printf("ok\n");
219 - // read the rest of the lines
220 - for(;1;) {
221 - char *c;
222 - p = fgets(buffer, MAX_LINE, fp);
223 - if(!p) break;
224 -
225 - c = strchr(buffer, ':');
226 - if(c) *c = '\t';
227 -
228 - printf("%s\n", buffer);
229 - r = sscanf(buffer, "%s\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\n",
230 - iface,
231 - &rbytes, &rpackets, &rerrors, &rdrops, &rfifo, &rframe, &rcompressed, &rmulticast,
232 - &tbytes, &tpackets, &terrors, &tdrops, &tfifo, &tcollisions, &tcarrier, &tcompressed);
233 - if(r == EOF) break;
234 - if(r != 17) printf("Cannot read line. Expected 17 params, read %d\n", r);
235 - else {
236 - // printf("Read %d items\n", r);
237 -
238 - // update our data
239 - update_iface_history(iface, rbytes, tbytes);
240 - }
241 - }
242 -
243 - // done reading, close it
244 - fclose(fp);
245 -
246 - // save statistics
247 - save_stats();
248 -
249 - // printf("Received bytes = %llu, Transmit bytes = %llu\n", rbytes, tbytes);
250 - sleep(update_every);
271 + // calculate the time it took for a full loop
272 + usec = usecdiff(&now, &last);
273 + if(DEBUG) printf("Last loop took %llu usec\n", usec);
274 +
275 + do_proc_net_dev(usec);
276 +
277 + // find the time to sleep in order to wait exactly update_every seconds
278 + gettimeofday(&tmp, NULL);
279 + usec = usecdiff(&tmp, &now);
280 + if(DEBUG) printf("This loop took %llu usec\n", usec);
281 +
282 + if(usec < (update_every * 1000000)) susec = (update_every * 1000000) - usec;
283 + else susec = 0;
284 +
285 + // make sure we will wait at least 100ms
286 + if(susec < 100000) susec = 100000;
287 +
288 + if(DEBUG) printf("Sleeping for %llu usec\n", susec);
289 + usleep(susec);
290 +
291 + // copy now to last
292 + last.tv_sec = now.tv_sec;
293 + last.tv_usec = now.tv_usec;
294 +
295 + //exit(1);
296 }
297 }
253 -