1#include <stdio.h>
2#include <assert.h>
3#include <limits.h>
4#include "ffsb_stats.h"
5#include "util.h"
6
7char *syscall_names[] = {
8	"open",
9	"read",
10	"write",
11	"create",
12	"lseek",
13	"unlink",
14	"close",
15	"stat",
16};
17
18/* yuck, just for the parser anyway.. */
19int ffsb_stats_str2syscall(char *str, syscall_t * sys)
20{
21	int i;
22	int ret;
23	for (i = 0; i < FFSB_NUM_SYSCALLS; i++) {
24		ret = strncasecmp(syscall_names[i], str,
25				  strlen(syscall_names[i]));
26		/* printf("%s = syscall_names[%d] vs %str ret = %d\n",
27		 * syscall_names[i],i,str,ret);
28		 */
29		if (0 == ret) {
30			*sys = (syscall_t) i;	/* ewww */
31			/* printf("matched syscall %s\n",syscall_names[i]); */
32			return 1;
33		}
34	}
35	printf("warning: failed to get match for syscall %s\n", str);
36	return 0;
37}
38
39void ffsb_statsc_init(ffsb_statsc_t * fsc)
40{
41	fsc->num_buckets = 0;
42	fsc->buckets = NULL;
43	fsc->ignore_stats = 0;
44}
45
46void ffsb_statsc_addbucket(ffsb_statsc_t * fsc, uint32_t min, uint32_t max)
47{
48	struct stat_bucket *temp;
49	fsc->num_buckets++;
50
51	/* printf("ffsb_realloc(): fsc_buckets = %d\n",fsc->num_buckets); */
52	temp = ffsb_realloc(fsc->buckets, sizeof(struct stat_bucket) *
53			    fsc->num_buckets);
54
55	fsc->buckets = temp;
56
57	/* Convert to micro-secs from milli-secs */
58	fsc->buckets[fsc->num_buckets - 1].min = min;
59	fsc->buckets[fsc->num_buckets - 1].max = max;
60}
61
62void ffsb_statsc_destroy(ffsb_statsc_t * fsc)
63{
64	free(fsc->buckets);
65}
66
67void ffsb_statsc_ignore_sys(ffsb_statsc_t * fsc, syscall_t s)
68{
69	/* printf("fsis: oring 0x%x with 0x%x\n",
70	 *      fsc->ignore_stats,
71	 *      (1 << s ) );
72	 */
73	fsc->ignore_stats |= (1 << s);
74}
75
76int fsc_ignore_sys(ffsb_statsc_t * fsc, syscall_t s)
77{
78	return fsc->ignore_stats & (1 << s);
79}
80
81void ffsb_statsd_init(ffsb_statsd_t * fsd, ffsb_statsc_t * fsc)
82{
83	int i;
84	memset(fsd, 0, sizeof(*fsd));
85
86	for (i = 0; i < FFSB_NUM_SYSCALLS; i++) {
87		fsd->totals[i] = 0;
88		fsd->mins[i] = UINT_MAX;
89		fsd->maxs[i] = 0;
90		fsd->buckets[i] = ffsb_malloc(sizeof(uint32_t) *
91					      fsc->num_buckets);
92		assert(fsd->buckets[i] != NULL);
93
94		memset(fsd->buckets[i], 0, sizeof(uint32_t) * fsc->num_buckets);
95	}
96	fsd->config = fsc;
97}
98
99void ffsb_statsd_destroy(ffsb_statsd_t * fsd)
100{
101	int i;
102	for (i = 0; i < FFSB_NUM_SYSCALLS; i++)
103		free(fsd->buckets[i]);
104}
105
106void ffsb_add_data(ffsb_statsd_t * fsd, syscall_t s, uint32_t value)
107{
108	unsigned num_buckets, i;
109	struct stat_bucket *bucket_defs;
110
111	if (!fsd || fsc_ignore_sys(fsd->config, s))
112		return;
113
114	if (value < fsd->mins[s])
115		fsd->mins[s] = value;
116	if (value > fsd->maxs[s])
117		fsd->maxs[s] = value;
118
119	fsd->counts[s]++;
120	fsd->totals[s] += value;
121
122	if (fsd->config->num_buckets == 0)
123		return;
124
125	num_buckets = fsd->config->num_buckets;
126	bucket_defs = fsd->config->buckets;
127
128	for (i = 0; i < num_buckets; i++) {
129		struct stat_bucket *b = &bucket_defs[i];
130
131		if (value <= b->max && value >= b->min) {
132			fsd->buckets[s][i]++;
133			break;
134		}
135	}
136}
137
138void ffsb_statsc_copy(ffsb_statsc_t * dest, ffsb_statsc_t * src)
139{
140	memcpy(dest, src, sizeof(*src));
141}
142
143void ffsb_statsd_add(ffsb_statsd_t * dest, ffsb_statsd_t * src)
144{
145	int i, j;
146	unsigned num_buckets;
147	if (dest->config != src->config)
148		printf("ffsb_statsd_add: warning configs do not"
149		       "match for data being collected\n");
150
151	num_buckets = dest->config->num_buckets;
152
153	for (i = 0; i < FFSB_NUM_SYSCALLS; i++) {
154		dest->counts[i] += src->counts[i];
155		dest->totals[i] += src->totals[i];
156
157		if (src->mins[i] < dest->mins[i])
158			dest->mins[i] = src->mins[i];
159		if (src->maxs[i] > dest->maxs[i])
160			dest->maxs[i] = src->maxs[i];
161
162		for (j = 0; j < num_buckets; j++)
163			dest->buckets[i][j] += src->buckets[i][j];
164	}
165}
166
167static void print_buckets_helper(ffsb_statsc_t * fsc, uint32_t * buckets)
168{
169	int i;
170	if (fsc->num_buckets == 0) {
171		printf("   -\n");
172		return;
173	}
174	for (i = 0; i < fsc->num_buckets; i++) {
175		struct stat_bucket *sb = &fsc->buckets[i];
176		printf("\t\t msec_range[%d]\t%f - %f : %8u\n",
177		       i, (double)sb->min / 1000.0f, (double)sb->max / 1000.0f,
178		       buckets[i]);
179	}
180	printf("\n");
181}
182
183void ffsb_statsd_print(ffsb_statsd_t * fsd)
184{
185	int i;
186	printf("\nSystem Call Latency statistics in millisecs\n" "=====\n");
187	printf("\t\tMin\t\tAvg\t\tMax\t\tTotal Calls\n");
188	printf("\t\t========\t========\t========\t============\n");
189	for (i = 0; i < FFSB_NUM_SYSCALLS; i++)
190		if (fsd->counts[i]) {
191			printf("[%7s]\t%05f\t%05lf\t%05f\t%12u\n",
192			       syscall_names[i], (float)fsd->mins[i] / 1000.0f,
193			       (fsd->totals[i] / (1000.0f *
194						  (double)fsd->counts[i])),
195			       (float)fsd->maxs[i] / 1000.0f, fsd->counts[i]);
196			print_buckets_helper(fsd->config, fsd->buckets[i]);
197		}
198}
199
200#if 0				/* Testing */
201
202void *ffsb_malloc(size_t s)
203{
204	void *p = malloc(s);
205	assert(p != NULL);
206	return p;
207}
208
209int main(int arc, char *argv[])
210{
211	ffsb_statsc_t fsc;
212	ffsb_statsd_t fsd;
213	int i;
214
215	printf("init\n");
216
217	ffsb_statsc_init(&fsc, 10);
218	ffsb_statsc_setbucket(&fsc, 0, 0.0f, 50.0f);
219	ffsb_statsc_setbucket(&fsc, 1, 50.0f, 10000.0f);
220	ffsb_statsc_setbucket(&fsc, 2, 0.1f, 0.2f);
221	ffsb_statsc_setbucket(&fsc, 3, 0.0f, 50.0f);
222	ffsb_statsc_setbucket(&fsc, 4, 50.0f, 10000.0f);
223	ffsb_statsc_setbucket(&fsc, 5, 0.1f, 0.2f);
224	ffsb_statsc_setbucket(&fsc, 6, 0.0f, 50.0f);
225	ffsb_statsc_setbucket(&fsc, 7, 50.0f, 10000.0f);
226	ffsb_statsc_setbucket(&fsc, 8, 0.1f, 0.2f);
227	ffsb_statsc_setbucket(&fsc, 9, 50.0f, 10000.0f);
228	ffsb_statsd_init(&fsd, &fsc);
229
230	printf("test\n");
231	for (i = 0; i < 50000000; i++)
232		ffsb_add_data(&fsd, SYS_READ, (float)i);
233
234	printf("cleanup\n");
235	ffsb_statsd_destroy(&fsd);
236	ffsb_statsc_destroy(&fsc);
237	return 0;
238}
239
240#endif /* Testing */
241