]> mj.ucw.cz Git - netgrind.git/blob - netgrind/histogram.c
Add histograms and recovery after SIGINT.
[netgrind.git] / netgrind / histogram.c
1 /*
2  *      Netgrind -- Histograms
3  *
4  *      (c) 2003 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "netgrind/pkt.h"
12 #include "netgrind/netgrind.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 static FILE *hist_file;
19 static list hist_list;
20 static uns hist_bucket_start, hist_threshold;
21 static uns hist_bucket_size = 60;
22
23 struct hist_entry {
24   node n;
25   byte *name;
26   enum {
27     HE_STATS,
28     HE_INT
29   } type;
30   union {
31     struct {
32       struct pkt_stats *var;
33       struct pkt_stats last_state;
34     } st;
35     struct {
36       int *var;
37       int last_state;
38     } in;
39   } u;
40 };
41
42 void histogram_init(byte *name)
43 {
44   hist_file = fopen(name, "w");
45   if (!hist_file)
46     die("Unable to open %s: %m", name);
47   list_init(&hist_list);
48 }
49
50 void histogram_add_stat(byte *name, struct pkt_stats *stat)
51 {
52   struct hist_entry *e = xmalloc_zero(sizeof(*e));
53   list_add_tail(&hist_list, &e->n);
54   e->name = name;
55   e->type = HE_STATS;
56   e->u.st.var = stat;
57 }
58
59 void histogram_add_int(byte *name, int *var)
60 {
61   struct hist_entry *e = xmalloc_zero(sizeof(*e));
62   list_add_tail(&hist_list, &e->n);
63   e->name = name;
64   e->type = HE_INT;
65   e->u.in.var = var;
66 }
67
68 static void hist_header(void)
69 {
70   struct hist_entry *e;
71   fprintf(hist_file, "# time");
72   WALK_LIST(e, hist_list)
73     fprintf(hist_file, "\t%s", e->name);
74   fputc('\n', hist_file);
75 }
76
77 static void hist_print(void)
78 {
79   struct hist_entry *e;
80   fprintf(hist_file, "%d", hist_bucket_start);
81   WALK_LIST(e, hist_list)
82     switch (e->type)
83       {
84       case HE_STATS:
85         fprintf(hist_file, "\t%Ld(%Ld)",
86                 e->u.st.var->packets - e->u.st.last_state.packets,
87                 e->u.st.var->bytes - e->u.st.last_state.bytes);
88         break;
89       case HE_INT:
90         fprintf(hist_file, "\t%d", *e->u.in.var - e->u.in.last_state);
91         break;
92       default:
93         ASSERT(0);
94       }
95   fputc('\n', hist_file);
96 }
97
98 void histogram_step(uns time)
99 {
100   if (!hist_file || time < hist_threshold)
101     return;
102   if (!hist_bucket_start)
103     hist_header();
104   else
105     hist_print();
106   hist_bucket_start = time - (time % hist_bucket_size);
107   hist_threshold = hist_bucket_start + hist_bucket_size;
108
109   struct hist_entry *e;
110   WALK_LIST(e, hist_list)
111     switch (e->type)
112       {
113       case HE_STATS:
114         e->u.st.last_state = *e->u.st.var;
115         break;
116       case HE_INT:
117         e->u.in.last_state = *e->u.in.var;
118         break;
119       default:
120         ASSERT(0);
121       }
122 }
123
124 void histogram_cleanup(void)
125 {
126   if (hist_file)
127     {
128       if (hist_threshold)
129         hist_print();
130       fclose(hist_file);
131     }
132 }