Browse code

bug_fixed: statistics (they were previously updated in an unprotected way; hash entry locks were mistakenly used to protect access to global stats structures; now each process maintains its own stats, and fifo_stats sums all of them)

Jiri Kuthan authored on 25/09/2002 20:23:42
Showing 7 changed files
... ...
@@ -254,7 +254,7 @@ void free_hash_table(  )
254 254
 				free_cell( p_cell );
255 255
 			}
256 256
 		}
257
-
257
+		shm_free(tm_table);
258 258
 	}
259 259
 }
260 260
 
... ...
@@ -323,12 +323,7 @@ void insert_into_hash_table_unsafe( struct cell * p_cell )
323 323
 	/* update stats */
324 324
 	p_entry->cur_entries++;
325 325
 	p_entry->acc_entries++;
326
-	cur_stats->transactions++;
327
-	acc_stats->transactions++;
328
-	if (p_cell->local) {
329
-		cur_stats->client_transactions++;
330
-		acc_stats->client_transactions++;
331
-	}
326
+	t_stats_new(p_cell->local);
332 327
 }
333 328
 
334 329
 
... ...
@@ -369,15 +364,7 @@ void remove_from_hash_table_unsafe( struct cell * p_cell)
369 364
 	}
370 365
 #	endif
371 366
 	p_entry->cur_entries--;
372
-#	ifdef EXTRA_DEBUG
373
-	if (cur_stats->transactions==0) {
374
-		LOG(L_CRIT, "BUG: bad things happened: cur->transactions=0\n");
375
-		abort();
376
-	}
377
-#	endif
378
-	cur_stats->transactions--;
379
-	if (p_cell->local) cur_stats->client_transactions--;
380
-	cur_stats->waiting--;
367
+	t_stats_deleted(p_cell->local);
381 368
 
382 369
 	/* unlock( &(p_entry->mutex) ); */
383 370
 }
... ...
@@ -310,6 +310,7 @@ error:
310 310
 void lock_cleanup()
311 311
 {
312 312
 	/* must check if someone uses them, for now just leave them allocated*/
313
+	if (timer_group_lock) shm_free(timer_group_lock);
313 314
 }
314 315
 
315 316
 #else
... ...
@@ -354,6 +355,7 @@ void lock_cleanup()
354 355
 	wait_semaphore = 0;
355 356
 #endif
356 357
 
358
+	if (timer_group_lock) shm_free(timer_group_lock);
357 359
 
358 360
 }
359 361
 #endif /*FAST_LOCK*/
... ...
@@ -39,6 +39,7 @@
39 39
 #include "t_fwd.h"
40 40
 #include "t_lookup.h"
41 41
 #include "config.h"
42
+#include "t_stats.h"
42 43
 
43 44
 
44 45
 /* ----------------------------------------------------- */
... ...
@@ -79,6 +80,7 @@ void tm_shutdown()
79 80
 	free_timer_table();
80 81
 	DBG("DEBUG: tm_shutdown : removing semaphores\n");
81 82
 	lock_cleanup();
83
+	free_tm_stats();
82 84
 	DBG("DEBUG: tm_shutdown : done\n");
83 85
 }
84 86
 
... ...
@@ -74,20 +74,6 @@ unsigned int get_on_negative()
74 74
 	return goto_on_negative;
75 75
 }
76 76
 
77
-static void update_reply_stats( int code ) {
78
-	if (code>=600) {
79
-		acc_stats->completed_6xx++;
80
-	} else if (code>=500) {
81
-		acc_stats->completed_5xx++;
82
-	} else if (code>=400) {
83
-		acc_stats->completed_4xx++;
84
-	} else if (code>=300) {
85
-		acc_stats->completed_3xx++;
86
-	} else if (code>=200) {
87
-		acc_stats->completed_2xx++;
88
-	}
89
-}
90
-
91 77
 static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,
92 78
 	unsigned int *ret_len)
93 79
 {
... ...
@@ -390,7 +376,7 @@ static int _reply( struct cell *trans, struct sip_msg* p_msg,
390 376
 	   on current transactions status */
391 377
 	/* t_update_timers_after_sending_reply( rb ); */
392 378
 	update_reply_stats( code );
393
-	acc_stats->replied_localy++;
379
+	tm_stats->replied_localy++;
394 380
 	if (lock) UNLOCK_REPLIES( trans );
395 381
 	
396 382
 	/* do UAC cleanup procedures in case we generated
... ...
@@ -544,6 +530,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
544 530
 	       or a stored message */
545 531
 		relayed_msg = branch==relay ? p_msg :  t->uac[relay].reply;
546 532
 		if (relayed_msg ==FAKED_REPLY) {
533
+			tm_stats->replied_localy++;
547 534
 			relayed_code = branch==relay
548 535
 				? msg_status : t->uac[relay].last_received;
549 536
 			buf = build_res_buf_from_sip_req( relayed_code,
... ...
@@ -674,6 +661,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch,
674 661
 		winning_msg= branch==local_winner 
675 662
 			? p_msg :  t->uac[local_winner].reply;
676 663
 		if (winning_msg==FAKED_REPLY) {
664
+			tm_stats->replied_localy++;
677 665
 			winning_code = branch==local_winner
678 666
 				? msg_status : t->uac[local_winner].last_received;
679 667
 		} else {
... ...
@@ -35,8 +35,9 @@
35 35
 #include "../../dprint.h"
36 36
 #include "../../config.h"
37 37
 #include "../../fifo_server.h"
38
+#include "../../pt.h"
38 39
 
39
-struct t_stats *cur_stats, *acc_stats;
40
+struct t_stats *tm_stats;
40 41
 
41 42
 
42 43
 /* we don't worry about locking data during reads (unlike
... ...
@@ -44,34 +45,37 @@ struct t_stats *cur_stats, *acc_stats;
44 45
   
45 46
 int print_stats(  FILE *f )
46 47
 {
47
-	fprintf(f, "Current:\n");
48
-	fprintf(f, "# of transactions: %10lu, ", 
49
-		cur_stats->transactions );
50
-	fprintf(f, "local: %10lu, ",
51
-		cur_stats->client_transactions );
52
-	fprintf(f, "waiting: %10lu" CLEANUP_EOL ,
53
-		cur_stats->waiting );
54
-
55
-	fprintf(f, "Total:\n");
56
-	fprintf(f, "# of transactions: %10lu,",
57
-		acc_stats->transactions );
58
-	fprintf(f, " local: %10lu,",
59
-		acc_stats->client_transactions );
60
-	fprintf(f, " waiting: %10lu" CLEANUP_EOL ,
61
-		acc_stats->waiting );
62
-
63
-	fprintf(f, "Replied localy: %10lu" CLEANUP_EOL ,
64
-		acc_stats->replied_localy );
65
-	fprintf(f, "Completion status 6xx: %10lu,",
66
-		acc_stats->completed_6xx );
67
-	fprintf(f, " 5xx: %10lu,",
68
-		acc_stats->completed_5xx );
69
-	fprintf(f, " 4xx: %10lu,",
70
-		acc_stats->completed_4xx );
71
-	fprintf(f, " 3xx: %10lu,",
72
-		acc_stats->completed_3xx );
73
-	fprintf(f, "2xx: %10lu" CLEANUP_EOL ,
74
-		acc_stats->completed_2xx );
48
+	unsigned long total, current, waiting, total_local;
49
+	int i;
50
+	int pno;
51
+
52
+	pno=process_count();
53
+	for(i=0, total=0, waiting=0, total_local=0; i<pno;i++) {
54
+		total+=tm_stats->s_transactions[i];
55
+		waiting+=tm_stats->s_waiting[i];
56
+		total_local+=tm_stats->s_client_transactions[i];
57
+	}
58
+	current=total-tm_stats->deleted;
59
+	waiting-=tm_stats->deleted;
60
+
61
+	
62
+
63
+	fprintf(f, "Current: %lu (%lu waiting) "
64
+		"Total: %lu (%lu local) " CLEANUP_EOL,
65
+		current, waiting, total, total_local);
66
+
67
+	fprintf(f, "Replied localy: %lu" CLEANUP_EOL ,
68
+		tm_stats->replied_localy );
69
+	fprintf(f, "Completion status 6xx: %lu,",
70
+		tm_stats->completed_6xx );
71
+	fprintf(f, " 5xx: %lu,",
72
+		tm_stats->completed_5xx );
73
+	fprintf(f, " 4xx: %lu,",
74
+		tm_stats->completed_4xx );
75
+	fprintf(f, " 3xx: %lu,",
76
+		tm_stats->completed_3xx );
77
+	fprintf(f, "2xx: %lu" CLEANUP_EOL ,
78
+		tm_stats->completed_2xx );
75 79
 	
76 80
 	return 1;
77 81
 }
... ...
@@ -101,24 +105,60 @@ int static fifo_stats( FILE *pipe, char *response_file )
101 105
 
102 106
 int init_tm_stats(void)
103 107
 {
104
-	cur_stats=shm_malloc(sizeof(struct t_stats));
105
-	if (cur_stats==0) {
108
+	int size;
109
+
110
+	tm_stats=shm_malloc(sizeof(struct t_stats));
111
+	if (tm_stats==0) {
106 112
 		LOG(L_ERR, "ERROR: init_stats: no mem for stats\n");
107
-		return -1;
113
+		goto error0;
108 114
 	}
109
-	acc_stats=shm_malloc(sizeof(struct t_stats));
110
-	if (acc_stats==0) {
115
+	memset(tm_stats, 0, sizeof(struct t_stats) );
116
+
117
+	size=sizeof(int)*process_count();
118
+	tm_stats->s_waiting=shm_malloc(size);
119
+	if (tm_stats->s_waiting==0) {
111 120
 		LOG(L_ERR, "ERROR: init_stats: no mem for stats\n");
112
-		shm_free(cur_stats);
113
-		return -1;
121
+		goto error1;
114 122
 	}
123
+	memset(tm_stats->s_waiting, 0, size );
115 124
 
125
+	tm_stats->s_transactions=shm_malloc(size);
126
+	if (tm_stats->s_transactions==0) {
127
+		LOG(L_ERR, "ERROR: init_stats: no mem for stats\n");
128
+		goto error2;
129
+	}
130
+	memset(tm_stats->s_transactions, 0, size );
131
+
132
+	tm_stats->s_client_transactions=shm_malloc(size);
133
+	if (tm_stats->s_client_transactions==0) {
134
+		LOG(L_ERR, "ERROR: init_stats: no mem for stats\n");
135
+		goto error3;
136
+	}
137
+	memset(tm_stats->s_client_transactions, 0, size );
138
+		 
116 139
 	if (register_fifo_cmd(fifo_stats, "t_stats", 0)<0) {
117 140
 		LOG(L_CRIT, "cannot register fifo stats\n");
118
-		return -1;
141
+		goto error4;
119 142
 	}
120 143
 
121
-	memset(cur_stats, 0, sizeof(struct t_stats) );
122
-	memset(acc_stats, 0, sizeof(struct t_stats) );
123 144
 	return 1;
145
+
146
+error4:
147
+	shm_free(tm_stats->s_client_transactions);
148
+error3:
149
+	shm_free(tm_stats->s_transactions);
150
+error2:
151
+	shm_free(tm_stats->s_waiting);
152
+error1:
153
+	shm_free(tm_stats);
154
+error0:
155
+	return -1;
156
+}
157
+
158
+void free_tm_stats()
159
+{
160
+	shm_free(tm_stats->s_client_transactions);
161
+	shm_free(tm_stats->s_transactions);
162
+	shm_free(tm_stats->s_waiting);
163
+	shm_free(tm_stats);
124 164
 }
... ...
@@ -31,22 +31,60 @@
31 31
 #ifndef _T_STATS_H
32 32
 #define _T_STATS_H
33 33
 
34
+#include "../../pt.h"
34 35
 
35
-extern struct t_stats *cur_stats, *acc_stats;
36
+
37
+extern struct t_stats *tm_stats;
36 38
 
37 39
 struct t_stats {
40
+	/* number of transactions in wait state */
41
+	unsigned long *s_waiting;
38 42
 	/* number of server transactions */
39
-	unsigned long transactions;
43
+	unsigned long *s_transactions;
40 44
 	/* number of UAC transactions (part of transactions) */
41
-	unsigned long client_transactions;
42
-	/* number of transactions in wait state */
43
-	unsigned long waiting;
45
+	unsigned long *s_client_transactions;
44 46
 	/* number of transactions which completed with this status */
45 47
 	unsigned long completed_3xx, completed_4xx, completed_5xx, 
46 48
 		completed_6xx, completed_2xx;
47 49
 	unsigned long replied_localy;
50
+	unsigned long deleted;
48 51
 };
49 52
 
53
+inline void static t_stats_new(int local)
54
+{
55
+	/* keep it in process's piece of shmem */
56
+	tm_stats->s_transactions[process_no]++;
57
+	if(local) tm_stats->s_client_transactions[process_no]++;
58
+}
59
+
60
+inline void static t_stats_wait()
61
+{
62
+	/* keep it in process's piece of shmem */
63
+	tm_stats->s_waiting[process_no]++;
64
+}
65
+
66
+inline void static t_stats_deleted( int local )
67
+{
68
+	/* no locking needed here -- only timer process deletes */
69
+	tm_stats->deleted++;
70
+}
71
+
72
+static void update_reply_stats( int code ) {
73
+	if (code>=600) {
74
+		tm_stats->completed_6xx++;
75
+	} else if (code>=500) {
76
+		tm_stats->completed_5xx++;
77
+	} else if (code>=400) {
78
+		tm_stats->completed_4xx++;
79
+	} else if (code>=300) {
80
+		tm_stats->completed_3xx++;
81
+	} else if (code>=200) {
82
+		tm_stats->completed_2xx++;
83
+	}
84
+}
85
+
86
+
50 87
 int init_tm_stats(void);
88
+void free_tm_stats();
51 89
 
52 90
 #endif
... ...
@@ -746,9 +746,9 @@ void set_1timer( struct timer_link *new_tl, enum lists list_id )
746 746
 		   afford updating wait statistics; I admit its not nice
747 747
 		   but it greatly utilizes existing lock 
748 748
 		*/
749
-		cur_stats->waiting++;acc_stats->waiting++;
750 749
 	}
751 750
 	unlock(list->mutex);
751
+	t_stats_wait();
752 752
 }
753 753
 
754 754