Browse code

- New stats code

ric authored on 28/08/2002 18:59:38
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,836 @@
0
+#ifdef STATS
1
+#include "stats.h"
2
+#include <stdio.h>
3
+#include <stdlib.h>
4
+#include <string.h>
5
+#include <time.h>
6
+#include <sys/types.h>
7
+#include <unistd.h>
8
+#include "dprint.h"
9
+#include "mem/shm_mem.h"
10
+#include "sr_module.h"
11
+
12
+/* SNMP includes */
13
+#include "modules/snmp/snmp_handler.h"
14
+#include "modules/snmp/sipCommonStatsMethod.h"
15
+#include "modules/snmp/sipCommonStatusCode.h"
16
+
17
+struct stats_s *stats;		/* per process stats structure */ 
18
+char *stat_file = NULL;		/* set by the parser */
19
+
20
+/* private variables */
21
+static struct stats_s *global_stats=NULL;
22
+static int stats_segments=-1;	/*used also to determine if we've been init'ed*/
23
+
24
+/* adds up global statistics and puts them into passed struct.
25
+ * -1 returned on failure */
26
+static int collect_stats(struct stats_s *s);
27
+
28
+/***********************8 SNMP Stuff **************************/
29
+/* a small structure we use to pass around the functions needed by
30
+ * all the registration functions */
31
+struct stats_funcs {
32
+	int (*reg_func)(const char *, struct sip_snmp_handler*);
33
+	struct sip_snmp_handler* (*new_func)(size_t);
34
+	void (*free_func)(struct sip_snmp_handler*);
35
+};
36
+
37
+/* SNMP Handler registration functions */
38
+static int sipSummaryStatsTable_register(const struct stats_funcs *f);
39
+static int sipMethodStatsTable_register(const struct stats_funcs *f);
40
+static int sipStatusCodesTable_register(const struct stats_funcs *f);
41
+
42
+/* the handlers */
43
+static int collect_InReqs(struct sip_snmp_obj *, enum handler_op);
44
+static int collect_OutReqs(struct sip_snmp_obj *, enum handler_op);
45
+static int collect_InResp(struct sip_snmp_obj *, enum handler_op);
46
+static int collect_OutResp(struct sip_snmp_obj *, enum handler_op);
47
+static int sipStatsMethod_handler(struct sip_snmp_obj *o, enum handler_op op);
48
+static int sipStatusCodes_handler(struct sip_snmp_obj *o, enum handler_op op);
49
+
50
+int init_stats(int nr_of_processes)
51
+{
52
+	LOG(L_DBG,"init_stats(): initializing stats for %d processes\n", 
53
+		nr_of_processes);
54
+
55
+	if(!stat_file) {
56
+		LOG(L_ERR, "Invalid stats file\n");
57
+		return -1;
58
+	}
59
+
60
+
61
+	global_stats = shm_malloc(nr_of_processes*sizeof(struct stats_s));
62
+	if(!global_stats) {
63
+		LOG(L_ERR, "Out of memory\n");
64
+		return -1;
65
+	}
66
+	stats_segments = nr_of_processes;
67
+
68
+	if(stats_register() == -1)
69
+		LOG(L_WARN, "init_stats(): Couldn't register stats with snmp module\n");
70
+
71
+
72
+	return 0;
73
+}
74
+
75
+/* sets the stats pointer for the passed process */
76
+void setstats(int child_index)
77
+{
78
+	if(stats_segments == -1 || !global_stats) {
79
+		LOG(L_ERR, "Stats not initialized. Cannot set them\n");
80
+		stats = NULL;
81
+		return;
82
+	}
83
+	if(child_index < 0 || child_index >= stats_segments) {
84
+		stats = NULL;
85
+		LOG(L_ERR, "Invalid index %d while setting statistics. Only have "
86
+			"space for %d processes\n", child_index, stats_segments);
87
+		return;
88
+	}
89
+	stats = global_stats+child_index;
90
+	stats->process_index = child_index;
91
+	/* can't use pids[] because we may be called before the corresponding
92
+	 * slot in pids[] is initialized (chk main_loop()) */
93
+	stats->pid = getpid();
94
+	stats->start_time = time(NULL);
95
+}
96
+
97
+/* printheader is used to print pid, date and index */
98
+int dump_statistic(FILE *fp, struct stats_s *istats, int printheader)
99
+{
100
+	struct tm res;
101
+	char t[256];
102
+	if(stats_segments == -1 || !global_stats) {
103
+		LOG(L_ERR, "Stats \"engine\" not initialized\n");
104
+		return -1;
105
+	}
106
+
107
+	if(printheader) {
108
+		localtime_r(&istats->start_time, &res);
109
+		strftime(t, 255, "%c", &res);
110
+		
111
+		fprintf(fp, "stats for process %d (pid %d) started at %s\n", 
112
+				istats->process_index, istats->pid, t);
113
+	}
114
+
115
+	fprintf(fp, "received requests:\ninv: %ld\tack: %ld\tcnc: %ld\t"
116
+		"bye: %ld\tother: %ld\n",
117
+		istats->received_requests_inv,
118
+		istats->received_requests_ack,
119
+		istats->received_requests_cnc,
120
+		istats->received_requests_bye,
121
+		istats->received_requests_other);
122
+	fprintf(fp, "sent requests:\n"
123
+		"inv: %ld\tack: %ld\tcnc: %ld\tbye: %ld\tother: %ld\n",
124
+		istats->sent_requests_inv,
125
+		istats->sent_requests_ack,
126
+		istats->sent_requests_cnc,
127
+		istats->sent_requests_bye,
128
+		istats->sent_requests_other);
129
+	fprintf(fp, "received responses:\n"
130
+		"1: %ld\t2: %ld\t3: %ld\t4: %ld\t5: %ld\t6: %ld\tother: %ld\t"
131
+		"drops: %ld\n",
132
+		istats->received_responses_1,
133
+		istats->received_responses_2,
134
+		istats->received_responses_3,
135
+		istats->received_responses_4,
136
+		istats->received_responses_5,
137
+		istats->received_responses_6,
138
+		istats->received_responses_other,
139
+		istats->received_drops);
140
+	fprintf(fp, "sent responses:\n"
141
+		"1: %ld\t2: %ld\t3: %ld\t4: %ld\t5: %ld\t6: %ld\n",
142
+		istats->sent_responses_1,
143
+		istats->sent_responses_2,
144
+		istats->sent_responses_3,
145
+		istats->sent_responses_4,
146
+		istats->sent_responses_5,
147
+		istats->sent_responses_6);
148
+	fprintf(fp, "processed requests: %ld\t\tprocessed responses: %ld\n"
149
+		"acc req time: %ld\t\t\tacc res time: %ld\nfailed on send: %ld\n\n",
150
+		istats->processed_requests,
151
+		istats->processed_responses,
152
+		istats->acc_req_time,
153
+		istats->acc_res_time,
154
+		istats->failed_on_send);
155
+	return 0;
156
+}
157
+
158
+int dump_all_statistic()
159
+{
160
+	register int i;
161
+	register struct stats_s *c;
162
+	static struct stats_s *g = NULL;
163
+	struct tm res;
164
+	char t[256];
165
+	time_t ts;
166
+	FILE *stat_fp = NULL;
167
+
168
+	if(stats_segments == -1 || !global_stats) {
169
+		LOG(L_ERR, "%s: Can't dump statistics, not initialized!\n", __func__);
170
+		return -1;
171
+	}
172
+
173
+	if(!stat_file) {
174
+		LOG(L_ERR, "%s: Can't dump statistics, invalid stats file\n", __func__);
175
+		return -1;
176
+	}
177
+
178
+	stat_fp = fopen(stat_file, "a");
179
+	if(!stat_fp) {
180
+		LOG(L_ERR, "%s: Couldn't open stats file %s: %s\n", __func__, stat_file,
181
+				strerror(errno));
182
+		return -1;
183
+	}
184
+
185
+	/* time stamp them since we're appending to the file */
186
+	ts = time(NULL);
187
+	localtime_r(&ts, &res);
188
+	strftime(t, 255, "%c", &res);
189
+	fprintf(stat_fp, "#### stats @ %s #####\n", t); 
190
+
191
+	c = global_stats;
192
+	for(i=0; i<stats_segments; i++) {
193
+		if(dump_statistic(stat_fp, c, 1) == -1) {
194
+			LOG(L_ERR, "Error dumping statistics for process %d\n", i);
195
+			goto end;
196
+		}
197
+		c++;
198
+	}
199
+
200
+	fprintf(stat_fp, "## Global Stats ##\n");
201
+	if(!g)
202
+		g = calloc(1, sizeof(struct stats_s));
203
+	if(!g) {
204
+		LOG(L_ERR, "Couldn't dump global stats: %s\n", strerror(errno));
205
+		goto end;
206
+	}
207
+	
208
+	if(collect_stats(g) == -1) {
209
+		LOG(L_ERR, "%s: Couldn't dump global stats\n", __func__);
210
+		goto end;
211
+	}
212
+	if(dump_statistic(stat_fp, g, 0) == -1) {
213
+		LOG(L_ERR, "Couldn't dump global stats\n");
214
+		goto end;
215
+	}
216
+end:
217
+	fprintf(stat_fp, "\n");
218
+	fclose(stat_fp);
219
+
220
+	return 0;
221
+}
222
+
223
+static int collect_stats(struct stats_s *s)
224
+{
225
+	register int i;
226
+	register struct stats_s *c;
227
+	if(!s) {
228
+		LOG(L_ERR, "collect_stats(): Invalid stats pointer passed\n");
229
+		return -1;
230
+	}
231
+	if(!global_stats || stats_segments == -1) {
232
+		LOG(L_ERR, "Can't collect statistics, not initalized!!\n");
233
+		return -1;
234
+	}
235
+
236
+	c = global_stats;
237
+	memset(s, '\0', sizeof(struct stats_s));
238
+	for(i=0; i<stats_segments; i++) {
239
+		s->received_requests_inv += c->received_requests_inv;
240
+		s->received_requests_ack += c->received_requests_ack;
241
+		s->received_requests_cnc += c->received_requests_cnc;
242
+		s->received_requests_bye += c->received_requests_bye;
243
+		s->received_requests_other += c->received_requests_other;
244
+		s->received_responses_1 += c->received_responses_1;
245
+		s->received_responses_2 += c->received_responses_2;
246
+		s->received_responses_3 += c->received_responses_3;
247
+		s->received_responses_4 += c->received_responses_4;
248
+		s->received_responses_5 += c->received_responses_5;
249
+		s->received_responses_6 += c->received_responses_6;
250
+		s->received_responses_other += c->received_responses_other;
251
+		s->received_drops += c->received_drops;
252
+		s->sent_requests_inv += c->sent_requests_inv;
253
+		s->sent_requests_ack += c->sent_requests_ack;
254
+		s->sent_requests_cnc += c->sent_requests_cnc;
255
+		s->sent_requests_bye += c->sent_requests_bye;
256
+		s->sent_requests_other += c->sent_requests_other;
257
+		s->sent_responses_1 += c->sent_responses_1;
258
+		s->sent_responses_2 += c->sent_responses_2;
259
+		s->sent_responses_3 += c->sent_responses_3;
260
+		s->sent_responses_4 += c->sent_responses_4;
261
+		s->sent_responses_5 += c->sent_responses_5;
262
+		s->sent_responses_6 += c->sent_responses_6;
263
+		s->processed_requests += c->processed_requests;
264
+		s->processed_responses += c->processed_responses;
265
+		s->acc_req_time += c->acc_req_time;
266
+		s->acc_res_time += c->acc_res_time;
267
+		s->failed_on_send += c->failed_on_send;
268
+
269
+		c++; /* next, please... */
270
+	}
271
+
272
+	return 0;
273
+}
274
+
275
+/*************************** SNMP Stuff ***********************/
276
+
277
+/* ##### Registration Functions ####### */
278
+
279
+/* Registers the handlers for:
280
+ * - sipSummaryStatsTable
281
+ * - sipMethodStatsTable
282
+ * - sipStatusCodesTable
283
+ * - sipCommonStatusCodeTable
284
+ *
285
+ * Returns 0 if snmp module not present, -1 on error, 1 on successful
286
+ * registration
287
+ */
288
+
289
+#define reg(t) \
290
+	if(t##_register(&f) == -1) {	\
291
+		LOG(L_ERR, "%s: Failed registering SNMP handlers\n", func);	\
292
+		return -1;	\
293
+	}
294
+
295
+int stats_register()
296
+{
297
+	const char *func = __FUNCTION__;
298
+	struct stats_funcs f;
299
+
300
+	f.reg_func = (void*) find_export("snmp_register_handler", 2);
301
+	f.new_func = (void*) find_export("snmp_new_handler", 1);
302
+	f.free_func = (void*) find_export("snmp_free_handler", 1);
303
+	if(!f.reg_func || !f.new_func || !f.free_func) {
304
+		LOG(L_WARN, "%s: Couldn't find necessary SNMP functions. Is the "
305
+			"module loaded?\n", func);
306
+		return 0;
307
+	}
308
+
309
+	reg(sipSummaryStatsTable);
310
+	reg(sipMethodStatsTable);
311
+	reg(sipStatusCodesTable);
312
+
313
+	return 0;
314
+}
315
+
316
+/* Receives the function used to register SNMP handlers. Returns 0
317
+ * on success, -1 on error */
318
+/* Registers:
319
+ * - sipSummaryInRequests
320
+ * - sipSummaryOutRequests
321
+ * - sipSummaryInResponses
322
+ * - sipSummaryOutResponses
323
+ * => sipSummaryTotalTransactions is handled by the tm module */
324
+static int sipSummaryStatsTable_register(const struct stats_funcs *f)
325
+{
326
+	register struct sip_snmp_handler *h;
327
+	register struct sip_snmp_obj *o;
328
+	const char *func = __FUNCTION__;
329
+
330
+	h = f->new_func(sizeof(unsigned long));
331
+	if(!h) {
332
+		LOG(L_ERR, "%s: Error creating handler\n", func);
333
+		return -1;
334
+	}
335
+	o = h->sip_obj;
336
+
337
+	/* this is the same for all of our objects */
338
+	o->type = SER_COUNTER;
339
+	*o->value.integer = 0;	/* default value. The real one is computed on
340
+							   request */
341
+	o->val_len = sizeof(unsigned long);
342
+
343
+	/* sipSummaryInRequests */
344
+	h->on_get = collect_InReqs;
345
+	h->on_set = h->on_end = NULL;
346
+	if(f->reg_func("sipSummaryInRequests", h) == -1) {
347
+		LOG(L_ERR, "%s: Error registering sipSummaryInRequests\n", func);
348
+		f->free_func(h);
349
+		return -1;
350
+	}
351
+
352
+	/* sipSummaryOutRequests */
353
+	h->on_get = collect_OutReqs;
354
+	if(f->reg_func("sipSummaryOutRequests", h) == -1) {
355
+		LOG(L_ERR, "%s: Error registering sipSummaryOutRequests\n", func);
356
+		f->free_func(h);
357
+		return -1;
358
+	}
359
+
360
+	/* sipSummaryInResponses */
361
+	h->on_get = collect_InResp;
362
+	if(f->reg_func("sipSummaryInResponses", h) == -1) {
363
+		LOG(L_ERR, "%s: Error registering sipSummaryInResponses\n", func);
364
+		f->free_func(h);
365
+		return -1;
366
+	}
367
+	
368
+	/* sipSummaryOutResponses */
369
+	h->on_get = collect_OutResp;
370
+	if(f->reg_func("sipSummaryOutResponses", h) == -1) {
371
+		LOG(L_ERR, "%s: Error registering sipSummaryOutResponses\n", func);
372
+		f->free_func(h);
373
+		return -1;
374
+	}
375
+
376
+	f->free_func(h);
377
+
378
+	return 0;
379
+}
380
+
381
+static int sipMethodStatsTable_register(const struct stats_funcs *f)
382
+{
383
+	const char* objs[] = {
384
+		"sipStatsInviteIns",
385
+		"sipStatsInviteOuts",
386
+		"sipStatsAckIns",
387
+		"sipStatsAckOuts",
388
+		"sipStatsByeIns",
389
+		"sipStatsByeOuts",
390
+		"sipStatsCancelIns",
391
+		"sipStatsCancelOuts"
392
+#if 0	/* we don't know about these */
393
+		"sipStatsOptionsIns",
394
+		"sipStatsOptionsOuts",
395
+		"sipStatsRegisterIns",
396
+		"sipStatsRegisterOuts",
397
+		"sipStatsInfoIns",
398
+		"sipStatsInfoOuts"
399
+#endif
400
+	};
401
+	int i, num = 8;
402
+	const char *func = __FUNCTION__;
403
+	register struct sip_snmp_handler *h;
404
+	register struct sip_snmp_obj *o;
405
+
406
+	h = f->new_func(sizeof(unsigned long));
407
+	if(!h) {
408
+		LOG(L_ERR, "%s: Error creating handler\n", func);
409
+		return -1;
410
+	}
411
+	o = h->sip_obj;
412
+	o->type = SER_COUNTER;
413
+	*o->value.integer = 0;
414
+	o->val_len = sizeof(unsigned long);
415
+
416
+	h->on_get = sipStatsMethod_handler;
417
+	h->on_set = h->on_end = NULL;
418
+
419
+	for(i=0; i<num; i++) {
420
+		if(f->reg_func(objs[i], h) == -1) {
421
+			LOG(L_ERR, "%s: Error registering %s\n", func, objs[i]);
422
+			f->free_func(h);
423
+			return -1;
424
+		}
425
+	}
426
+
427
+	f->free_func(h);
428
+
429
+	return 0;
430
+}
431
+
432
+static int sipStatusCodesTable_register(const struct stats_funcs *f)
433
+{
434
+	const char *objs[] = {
435
+		"sipStatsInfoClassIns",
436
+		"sipStatsInfoClassOuts",
437
+		"sipStatsSuccessClassIns",
438
+		"sipStatsSuccessClassOuts",
439
+		"sipStatsRedirClassIns",
440
+		"sipStatsRedirClassOuts",
441
+		"sipStatsReqFailClassIns",
442
+		"sipStatsReqFailClassOuts",
443
+		"sipStatsServerFailClassIns",
444
+		"sipStatsServerFailClassOuts",
445
+		"sipStatsGlobalFailClassIns",
446
+		"sipStatsGlobalFailClassOuts",
447
+		"sipStatsOtherClassesIns",
448
+		"sipStatsOtherClassesOuts"
449
+	};
450
+	int i, num = 14;
451
+	const char *func = __FUNCTION__;
452
+	register struct sip_snmp_handler *h;
453
+	register struct sip_snmp_obj *o;
454
+
455
+	h = f->new_func(sizeof(unsigned long));
456
+	if(!h) {
457
+		LOG(L_ERR, "%s: Error creating handler\n", func);
458
+		return -1;
459
+	}
460
+	o = h->sip_obj;
461
+	o->type = SER_COUNTER;
462
+	*o->value.integer = 0;
463
+	o->val_len = sizeof(unsigned long);
464
+
465
+	h->on_get = sipStatusCodes_handler;
466
+	h->on_set = h->on_end = NULL;
467
+
468
+	for(i=0; i<num; i++) {
469
+		if(f->reg_func(objs[i], h) == -1) {
470
+			LOG(L_ERR, "%s: Error registering %s\n", func, objs[i]);
471
+			f->free_func(h);
472
+			return -1;
473
+		}
474
+	}
475
+
476
+	f->free_func(h);
477
+
478
+	return 0;}
479
+
480
+/* ########################## SNMP Handlers ######################### */
481
+
482
+/*** Handlers for sipSummaryStatsTable */
483
+static int collect_InReqs(struct sip_snmp_obj *o, enum handler_op op)
484
+{
485
+	register int i;
486
+	register struct stats_s *c;
487
+	register unsigned long t1, t2, t3, t4, t5;
488
+	const char *func = __FUNCTION__;
489
+
490
+	if(!global_stats || stats_segments == -1) {
491
+		LOG(L_ERR, "%s: Can't collect stats, they have not been initialized."
492
+			"Did you call init_stats()?\n", func);
493
+		return -1;
494
+	}
495
+
496
+	if(op != SER_GET) {
497
+		LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
498
+		return -1;
499
+	}
500
+
501
+	if(!o->value.integer) {
502
+		o->value.integer = calloc(1, sizeof(unsigned long));
503
+		if(!o->value.integer) {
504
+			LOG(L_ERR, "%s: %s\n", func, strerror(errno));
505
+			return -1;
506
+		}
507
+	}
508
+
509
+	c = global_stats;
510
+	t1 = t2 = t3 = t4 = t5 = 0;
511
+	for(i=0; i<stats_segments; i++, c++) {
512
+		t1 += c->received_requests_inv;
513
+		t2 += c->received_requests_ack;
514
+		t3 += c->received_requests_cnc;
515
+		t4 += c->received_requests_bye;
516
+		t5 += c->received_requests_other;
517
+	}
518
+
519
+	*o->value.integer = t1 + t2 + t3 + t4 + t5; 
520
+	o->val_len = sizeof(unsigned long);
521
+	o->type = SER_COUNTER;
522
+	
523
+	return 0;
524
+}
525
+
526
+static int collect_OutReqs(struct sip_snmp_obj *o, enum handler_op op)
527
+{
528
+	register int i;
529
+	register struct stats_s *c;
530
+	register unsigned long t1, t2, t3, t4, t5;
531
+	const char *func = __FUNCTION__;
532
+
533
+	if(!global_stats || stats_segments == -1) {
534
+		LOG(L_ERR, "%s: Can't collect stats, they have not been initialized."
535
+			"Did you call init_stats()?\n", func);
536
+		return -1;
537
+	}
538
+
539
+	if(op != SER_GET) {
540
+		LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
541
+		return -1;
542
+	}
543
+
544
+	if(!o->value.integer) {
545
+		o->value.integer = calloc(1, sizeof(unsigned long));
546
+		if(!o->value.integer) {
547
+			LOG(L_ERR, "%s: %s\n", func, strerror(errno));
548
+			return -1;
549
+		}
550
+	}
551
+
552
+	c = global_stats;
553
+	t1 = t2 = t3 = t4 = t5 = 0;
554
+	for(i=0; i<stats_segments; i++, c++) {
555
+		t1 += c->sent_requests_inv;
556
+		t2 += c->sent_requests_ack;
557
+		t3 += c->sent_requests_cnc;
558
+		t4 += c->sent_requests_bye;
559
+		t5 += c->sent_requests_other;
560
+	}
561
+
562
+	*o->value.integer = t1 + t2 + t3 + t4 + t5; 
563
+	o->val_len = sizeof(unsigned long);
564
+	o->type = SER_COUNTER;
565
+	
566
+	return 0;
567
+}
568
+
569
+static int collect_InResp(struct sip_snmp_obj *o, enum handler_op op)
570
+{
571
+	register int i;
572
+	register struct stats_s *c;
573
+	register unsigned long t1, t2, t3, t4, t5, t6, t7;
574
+	const char *func = __FUNCTION__;
575
+
576
+	if(!global_stats || stats_segments == -1) {
577
+		LOG(L_ERR, "%s: Can't collect stats, they have not been initialized."
578
+			"Did you call init_stats()?\n", func);
579
+		return -1;
580
+	}
581
+
582
+	if(op != SER_GET) {
583
+		LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
584
+		return -1;
585
+	}
586
+
587
+	if(!o->value.integer) {
588
+		o->value.integer = calloc(1, sizeof(unsigned long));
589
+		if(!o->value.integer) {
590
+			LOG(L_ERR, "%s: %s\n", func, strerror(errno));
591
+			return -1;
592
+		}
593
+	}
594
+
595
+	c = global_stats;
596
+	t1 = t2 = t3 = t4 = t5 = t6 = t7 = 0;
597
+	for(i=0; i<stats_segments; i++, c++) {
598
+		t1 += c->received_responses_1;
599
+		t2 += c->received_responses_2;
600
+		t3 += c->received_responses_3;
601
+		t4 += c->received_responses_4;
602
+		t5 += c->received_responses_5;
603
+		t6 += c->received_responses_6;
604
+		t7 += c->received_responses_other;
605
+	}
606
+
607
+	*o->value.integer = t1 + t2 + t3 + t4 + t5 + t6 + t7; 
608
+	o->val_len = sizeof(unsigned long);
609
+	o->type = SER_COUNTER;
610
+	
611
+	return 0;
612
+}
613
+
614
+static int collect_OutResp(struct sip_snmp_obj *o, enum handler_op op)
615
+{
616
+	register int i;
617
+	register struct stats_s *c;
618
+	register unsigned long t1, t2, t3, t4, t5, t6, t7;
619
+	const char *func = __FUNCTION__;
620
+
621
+	if(!global_stats || stats_segments == -1) {
622
+		LOG(L_ERR, "%s: Can't collect stats, they have not been initialized\n",
623
+			func);
624
+		return -1;
625
+	}
626
+
627
+	if(op != SER_GET) {
628
+		LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
629
+		return -1;
630
+	}
631
+
632
+	if(!o->value.integer) {
633
+		o->value.integer = calloc(1, sizeof(unsigned long));
634
+		if(!o->value.integer) {
635
+			LOG(L_ERR, "%s: %s\n", func, strerror(errno));
636
+			return -1;
637
+		}
638
+	}
639
+
640
+	c = global_stats;
641
+	t1 = t2 = t3 = t4 = t5 = t6 = t7 = 0;
642
+	for(i=0; i<stats_segments; i++, c++) {
643
+		t1 += c->sent_responses_1;
644
+		t2 += c->sent_responses_2;
645
+		t3 += c->sent_responses_3;
646
+		t4 += c->sent_responses_4;
647
+		t5 += c->sent_responses_5;
648
+		t6 += c->sent_responses_6;
649
+		/* XXX: Not in stats struct 
650
+		t7 += c->sent_responses_other;
651
+		*/
652
+	}
653
+
654
+	*o->value.integer = t1 + t2 + t3 + t4 + t5 + t6 + t7; 
655
+	o->val_len = sizeof(unsigned long);
656
+	o->type = SER_COUNTER;
657
+	
658
+	return 0;
659
+}
660
+
661
+/***** Handlers for sipMethodStatsTable ******/
662
+/* Collects the specified stat and puts the result in total. s defines
663
+ * the starting point in the stats array, normally global_stats */
664
+#define collect_this_stat(stat, total, s) \
665
+	for(i=0; i<stats_segments; i++)	\
666
+		total += s++->stat;
667
+
668
+static int sipStatsMethod_handler(struct sip_snmp_obj *o, enum handler_op op)
669
+{
670
+	register struct stats_s *c;
671
+	register unsigned long total;
672
+	register int i;
673
+	const char *func = __FUNCTION__;
674
+
675
+	if(!o) {
676
+		LOG(L_ERR, "%s: Invalid sip SNMP object passed\n", func);
677
+		return -1;
678
+	}
679
+
680
+	if(!global_stats || stats_segments == -1) {
681
+		LOG(L_ERR, "%s: Can't collect stats, they have not been initialized\n",
682
+			func);
683
+		return -1;
684
+	}
685
+
686
+	if(op != SER_GET) {
687
+		LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
688
+		return -1;
689
+	}
690
+
691
+	if(!o->value.integer) {
692
+		o->value.integer = calloc(1, sizeof(unsigned long));
693
+		if(!o->value.integer) {
694
+			LOG(L_ERR, "%s: %s\n", func, strerror(errno));
695
+			return -1;
696
+		}
697
+	}
698
+
699
+	c = global_stats;
700
+	total = 0;
701
+	switch(o->col) {
702
+		/* these definitions are taken from sipMethodStatsHandler */
703
+		case COLUMN_SIPSTATSINVITEINS: 
704
+			collect_this_stat(received_requests_inv, total, c);
705
+			break;
706
+		case COLUMN_SIPSTATSINVITEOUTS: 
707
+			collect_this_stat(sent_requests_inv, total, c);
708
+			break;
709
+		case COLUMN_SIPSTATSACKINS: 
710
+			collect_this_stat(received_requests_ack, total, c);
711
+			break;
712
+		case COLUMN_SIPSTATSACKOUTS: 
713
+			collect_this_stat(sent_requests_ack, total, c);
714
+			break;
715
+		case COLUMN_SIPSTATSBYEINS: 
716
+			collect_this_stat(received_requests_bye, total, c);
717
+			break;
718
+		case COLUMN_SIPSTATSBYEOUTS: 
719
+			collect_this_stat(sent_requests_bye, total, c);
720
+			break;
721
+		case COLUMN_SIPSTATSCANCELINS: 
722
+			collect_this_stat(received_requests_cnc, total, c);
723
+			break;
724
+		case COLUMN_SIPSTATSCANCELOUTS: 
725
+			collect_this_stat(sent_requests_cnc, total, c);
726
+			break;
727
+		/* ser doesn't have notion for these. We don't
728
+		 * register them with snmp. Here just as remainder */
729
+#if 0
730
+		case COLUMN_SIPSTATSOPTIONSINS:
731
+		case COLUMN_SIPSTATSOPTIONSOUTS:
732
+		case COLUMN_SIPSTATSREGISTERINS:
733
+		case COLUMN_SIPSTATSREGISTEROUTS:
734
+		case COLUMN_SIPSTATSINFOINS:
735
+		case COLUMN_SIPSTATSINFOOUTS:
736
+			break;
737
+#endif
738
+	}
739
+
740
+	*o->value.integer = total;
741
+	o->val_len = sizeof(unsigned long);
742
+	o->type = SER_COUNTER;
743
+
744
+	return 0;
745
+}
746
+
747
+static int sipStatusCodes_handler(struct sip_snmp_obj *o, enum handler_op op)
748
+{
749
+	register struct stats_s *c;
750
+	register unsigned long total;
751
+	register int i;
752
+	const char *func = __FUNCTION__;
753
+
754
+	if(!o) {
755
+		LOG(L_ERR, "%s: Invalid sip SNMP object passed\n", func);
756
+		return -1;
757
+	}
758
+
759
+	if(!global_stats || stats_segments == -1) {
760
+		LOG(L_ERR, "%s: Can't collect stats, they have not been initialized\n",
761
+			func);
762
+		return -1;
763
+	}
764
+
765
+	if(op != SER_GET) {
766
+		LOG(L_ERR, "%s: Invalid handler operation passed\n", func);
767
+		return -1;
768
+	}
769
+
770
+	if(!o->value.integer) {
771
+		o->value.integer = calloc(1, sizeof(unsigned long));
772
+		if(!o->value.integer) {
773
+			LOG(L_ERR, "%s: %s\n", func, strerror(errno));
774
+			return -1;
775
+		}
776
+	}
777
+
778
+	c = global_stats;
779
+	total = 0;
780
+	switch(o->col) {
781
+		case COLUMN_SIPSTATSINFOCLASSINS:
782
+			collect_this_stat(received_responses_1, total, c);
783
+			break;
784
+		case COLUMN_SIPSTATSINFOCLASSOUTS:
785
+			collect_this_stat(sent_responses_1, total, c);
786
+			break;
787
+		case COLUMN_SIPSTATSSUCCESSCLASSINS:
788
+			collect_this_stat(received_responses_2, total, c);
789
+			break;
790
+		case COLUMN_SIPSTATSSUCCESSCLASSOUTS:
791
+			collect_this_stat(sent_responses_2, total, c);
792
+			break;
793
+		case COLUMN_SIPSTATSREDIRCLASSINS:
794
+			collect_this_stat(received_responses_3, total, c);
795
+			break;
796
+		case COLUMN_SIPSTATSREDIRCLASSOUTS:
797
+			collect_this_stat(sent_responses_3, total, c);
798
+			break;
799
+		case COLUMN_SIPSTATSREQFAILCLASSINS:
800
+			collect_this_stat(received_responses_4, total, c);
801
+			break;
802
+		case COLUMN_SIPSTATSREQFAILCLASSOUTS:
803
+			collect_this_stat(sent_responses_4, total, c);
804
+			break;
805
+		case COLUMN_SIPSTATSSERVERFAILCLASSINS:
806
+			collect_this_stat(received_responses_5, total, c);
807
+			break;
808
+		case COLUMN_SIPSTATSSERVERFAILCLASSOUTS:
809
+			collect_this_stat(sent_responses_5, total, c);
810
+			break;
811
+		case COLUMN_SIPSTATSGLOBALFAILCLASSINS:
812
+			collect_this_stat(received_responses_6, total, c);
813
+			break;
814
+		case COLUMN_SIPSTATSGLOBALFAILCLASSOUTS:
815
+			collect_this_stat(sent_responses_6, total, c);
816
+			break;
817
+		case COLUMN_SIPSTATSOTHERCLASSESINS:
818
+			collect_this_stat(received_responses_other, total, c);
819
+			break;
820
+		case COLUMN_SIPSTATSOTHERCLASSESOUTS:
821
+			/* FIXME: For some reason this is not defined in
822
+			 * struct stats_s... */
823
+			/* collect_this_stat(sent_responses_other, total, c); */
824
+			total = 0;
825
+			break;
826
+	}
827
+
828
+	*o->value.integer = total;
829
+	o->val_len = sizeof(unsigned long);
830
+	o->type = SER_COUNTER;
831
+
832
+	return 0;
833
+}
834
+
835
+#endif
... ...
@@ -36,6 +36,7 @@
36 36
 
37 37
 #define         _statusline(class, dir )       case class: stats->dir##_responses_##class++; break;
38 38
 
39
+/* FIXME: Don't have case for _other (see received_responses_other) */
39 40
 #define _update_response( statusclass, dir )		\
40 41
         { if (stat_file!=NULL)                          \
41 42
                 switch( statusclass ) {                 \
... ...
@@ -84,7 +85,7 @@ struct stats_s {
84 84
 	received_requests_bye,
85 85
 	received_requests_other,
86 86
 
87
-	received_responses_1, 		/* received_requests */
87
+	received_responses_1, 		/* received_responses */
88 88
 	received_responses_2,
89 89
 	received_responses_3,
90 90
 	received_responses_4,
... ...
@@ -92,7 +93,7 @@ struct stats_s {
92 92
 	received_responses_6,
93 93
 	received_responses_other,
94 94
 
95
-	received_drops, 		/* all messages we received and did not process
95
+	received_drops,	/* all messages we received and did not process
96 96
 					   successfully; reasons include SIP sanity checks 
97 97
 					   (missing Vias, neither request nor response, 
98 98
 					   failed parsing), ser errors (malloc, action
... ...
@@ -115,6 +116,7 @@ struct stats_s {
115 115
 	sent_responses_4,
116 116
 	sent_responses_5,
117 117
 	sent_responses_6,
118
+	/* FIXME: Don't want sent_responses_other?? */
118 119
 
119 120
 	processed_requests,
120 121
 	processed_responses,
... ...
@@ -122,18 +124,17 @@ struct stats_s {
122 122
 	acc_res_time,
123 123
 
124 124
 	failed_on_send;			
125
-			  
126 125
 };
127 126
 
128
-
129 127
 extern struct stats_s *stats;
128
+extern char *stat_file;
130 129
 
130
+int init_stats( int nr_of_processes );
131 131
 void setstats( int child_index );
132
-void dump_statistic( FILE *fp, struct stats_s *istats );
133 132
 int dump_all_statistic();
134
-int init_stats( int nr_of_processes );
135
-
136
-
133
+int dump_statistic(FILE *fp, struct stats_s *istats, int printheader);
134
+/* Registers handlers with SNMP module */
135
+int stats_register(); 
137 136
 
138 137
 #endif
139 138
 #endif