modules/ta/ta.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- ta_findonly_l
- ta_findcreate_l
- ta_remove_l
- ta_setactivity_l
- ta_print_header
- ta_printone_l
- TA_add
- TA_delete
- TA_setactivity
- TA_setcondat
- TA_increment
- TA_tostring
- TA_trigger
1 /***************************************
2 $Revision: 1.4 $
3
4 thread accounting (ta). ta.c - functions to keep track of activities
5 of threads within the server
6
7 Status: NOT REVUED, TESTED, COMPLETE
8
9 Design and implementation by: Marek Bukowy
10
11 ******************/ /******************
12 Copyright (c) 1999 RIPE NCC
13
14 All Rights Reserved
15
16 Permission to use, copy, modify, and distribute this software and its
17 documentation for any purpose and without fee is hereby granted,
18 provided that the above copyright notice appear in all copies and that
19 both that copyright notice and this permission notice appear in
20 supporting documentation, and that the name of the author not be
21 used in advertising or publicity pertaining to distribution of the
22 software without specific, written prior permission.
23
24 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
25 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
26 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
27 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
28 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
29 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 ***************************************/
31
32 #define TA_IMPL
33 #include <ta.h>
34
35
36 static
37 ta_str_t *ta_findonly_l( GList **list, pthread_t thread_id )
/* [<][>][^][v][top][bottom][index][help] */
38 {
39 GList *item;
40
41 /* try to find first */
42 for(item = g_list_first(*list);
43 item != NULL;
44 item = g_list_next(item)) {
45 ta_str_t *tas = (ta_str_t *) (item->data);
46
47 if( tas->thread_id == thread_id ) {
48 return tas;
49 }
50 }
51 return NULL;
52 }
53
54 static
55 ta_str_t *ta_findcreate_l( GList **list, pthread_t thread_id )
/* [<][>][^][v][top][bottom][index][help] */
56 {
57 ta_str_t *newtas;
58
59 if( (newtas = ta_findonly_l(list, thread_id)) == NULL) {
60
61 /* not found => add */ /* zero everything*/
62 dieif( !NOERR( wr_calloc( (void **) &newtas, 1, sizeof( ta_str_t ))));
63 newtas->thread_id = thread_id;
64
65 *list = g_list_append( *list, newtas );
66 }
67
68 return newtas;
69 }
70
71
72 /* find and remove */
73 static
74 void ta_remove_l(GList **list, pthread_t thread_id )
/* [<][>][^][v][top][bottom][index][help] */
75 {
76 GList *item;
77
78 for(item = g_list_first(*list);
79 item != NULL;
80 item = g_list_next(item)) {
81 ta_str_t *tas = (ta_str_t *) (item->data);
82
83 if( tas->thread_id == thread_id ) {
84 *list = g_list_remove_link(*list, item);
85 wr_clear_list( &item );
86 break;
87 }
88 }
89
90 return;
91 }
92
93 /* set the activity field */
94 static
95 void ta_setactivity_l(ta_str_t *tas, char *activity)
/* [<][>][^][v][top][bottom][index][help] */
96 {
97 char *nl;
98
99 strncpy(tas->activity, activity, TA_ACT_LEN-1);
100 tas->activity[TA_ACT_LEN]=0;
101 /* convert last newline to a space, if any */
102 if( (nl=strrchr(tas->activity, '\n')) != NULL ) {
103 *nl=' ';
104 }
105 }
106
107
108 #define TA_HEADER "%-8s %15s %4s %4s %5s %5s %4s %5s %s\n"
109 #define TA_FORMAT "%-8s %15s %4d %4d %5.1f %5.1f %4d %5.2f %s\n"
110
111 static
112 void ta_print_header(char *buf, int length)
/* [<][>][^][v][top][bottom][index][help] */
113 {
114 snprintf(buf, length, TA_HEADER,
115 "type", "from", "sock", "thr", "sess", "task", "#",
116 "avg", "current"
117 );
118 }
119
120 /* fill in one entry */
121 static
122 void ta_printone_l(ta_str_t *tas, char *buf, int length,
/* [<][>][^][v][top][bottom][index][help] */
123 ut_timer_t *reftime)
124 {
125 float session, task; /* duration of the session/task */
126 char *address = SK_getpeername(tas->sock); /* allocated! */
127 /* can be NULL for example if the socket has just closed
128 or the file descriptor is not a socket */
129
130 session = UT_timediff( &tas->sessionstart, reftime );
131 task = UT_timediff( &tas->taskstart, reftime );
132
133 snprintf(buf, length, TA_FORMAT ,
134 tas->type,
135 address ? address : "",
136 tas->sock,
137 tas->thread_id,
138 session,
139 task,
140 tas->tasks,
141 (tas->tasks > 0) ? session / tas->tasks : 0,
142 tas->activity);
143
144 if (address) {
145 wr_free(address);
146 }
147 }
148
149 /* PUBLIC adding function */
150 void TA_add(int sock, char *type)
/* [<][>][^][v][top][bottom][index][help] */
151 {
152 ta_str_t *newtas;
153
154 /* lock the list */
155 pthread_mutex_lock( &ta_mutex );
156
157 /* find/create node and set peer/thread_id */
158 newtas = ta_findcreate_l( &ta_list, pthread_self());
159 newtas->sock = sock;
160 newtas->tasks = 0;
161 newtas->condat = NULL;
162 UT_timeget( &newtas->sessionstart );
163 UT_timeget( &newtas->taskstart ); /* just to get it a reasonable value */
164
165 snprintf(newtas->type, TA_TYPE_LEN, type);
166 ta_setactivity_l(newtas,"--");
167
168 /* unlock */
169 pthread_mutex_unlock( &ta_mutex );
170 }
171
172
173 /* PUBLIC deletion function */
174 void TA_delete(void)
/* [<][>][^][v][top][bottom][index][help] */
175 {
176 /* lock the list */
177 pthread_mutex_lock( &ta_mutex );
178
179 /* find & remove */
180 ta_remove_l( &ta_list, pthread_self() );
181
182 /* unlock */
183 pthread_mutex_unlock( &ta_mutex );
184 }
185
186
187 /* PUBLIC activity-setting function */
188 void TA_setactivity(char *activity)
/* [<][>][^][v][top][bottom][index][help] */
189 {
190 ta_str_t *newtas;
191
192 /* lock the list */
193 pthread_mutex_lock( &ta_mutex );
194
195 /* find */
196 newtas = ta_findcreate_l( &ta_list, pthread_self());
197
198 /* set the activity field */
199 ta_setactivity_l(newtas, activity);
200
201 /* unlock */
202 pthread_mutex_unlock( &ta_mutex );
203 }
204
205 /* PUBLIC condat-setting function */
206 void TA_setcondat(sk_conn_st *condat)
/* [<][>][^][v][top][bottom][index][help] */
207 {
208 ta_str_t *newtas;
209
210 /* lock the list */
211 pthread_mutex_lock( &ta_mutex );
212
213 /* find */
214 newtas = ta_findcreate_l( &ta_list, pthread_self());
215
216 /* set the condat field */
217 newtas->condat = condat;
218
219 /* unlock */
220 pthread_mutex_unlock( &ta_mutex );
221 }
222
223
224 void TA_increment(void)
/* [<][>][^][v][top][bottom][index][help] */
225 {
226 ta_str_t *newtas;
227
228 /* lock the list */
229 pthread_mutex_lock( &ta_mutex );
230
231 /* find */
232 newtas = ta_findcreate_l( &ta_list, pthread_self());
233 /* increment task */
234 newtas->tasks++;
235 /* set task starting time */
236 UT_timeget( &newtas->taskstart );
237
238 /* unlock */
239 pthread_mutex_unlock( &ta_mutex );
240 }
241
242 char * TA_tostring(void)
/* [<][>][^][v][top][bottom][index][help] */
243 {
244 GList *item;
245 char *bigbuf = NULL;
246 char smallbuf[TA_PRINT_LEN];
247 ut_timer_t reftime;
248
249 ta_print_header(smallbuf, TA_PRINT_LEN);
250 dieif( !NOERR(wr_malloc( (void **) &bigbuf, strlen(smallbuf)+2 )));
251 strcpy(bigbuf, smallbuf);
252 strcat(bigbuf, "\n");
253
254 /* lock the list */
255 pthread_mutex_lock( &ta_mutex );
256
257 /* get reference time */
258 UT_timeget( &reftime );
259
260 /* iterate */
261 for(item = g_list_first(ta_list);
262 item != NULL;
263 item = g_list_next(item)) {
264 ta_str_t *tas = (ta_str_t *) (item->data);
265 int smalllen;
266 int biglen = ( bigbuf == NULL ) ? 0 : strlen(bigbuf);
267
268 ta_printone_l(tas, smallbuf, TA_PRINT_LEN, &reftime);
269 smalllen = strlen(smallbuf);
270
271 dieif( !NOERR(wr_realloc( (void **) &bigbuf, biglen+smalllen+3 )));
272
273 strcat(bigbuf, smallbuf);
274 }
275 /* unlock */
276 pthread_mutex_unlock( &ta_mutex );
277
278 return bigbuf;
279 }
280
281 /*
282 find a thread of the given type, socket file descriptor and thread id
283 and execute the watchdog's triggers if it's defined.
284 */
285
286 void TA_trigger(char *type, int sock, pthread_t thread_id)
/* [<][>][^][v][top][bottom][index][help] */
287 {
288 ta_str_t *tas;
289
290 /* lock the list */
291 pthread_mutex_lock( &ta_mutex );
292
293 if( (tas = ta_findonly_l(&ta_list, thread_id)) != NULL
294 && tas->sock == sock
295 && strcmp(tas->type, type) == 0
296 && tas->condat != NULL
297 && tas->condat->sock == sock
298 ) {
299 SK_watchtrigger(tas->condat);
300 }
301
302 /* unlock */
303 pthread_mutex_unlock( &ta_mutex );
304
305 }