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_reset_counters
- TA_tostring
- TA_trigger
1 /***************************************
2 $Revision: 1.11 $
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,2000,2001,2002 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 "rip.h"
34
35
36 /*++++++++++++++++++++++++++++++++++++++
37
38 Finds a thread by thread_id. Assumes locked list.
39
40 ta_str_t *ta_findonly_l returns a pointer to the thread's record
41
42 GList **list thread list
43
44 pthread_t thread_id thread id
45
46 ++++++++++++++++++++++++++++++++++++++*/
47 static
48 ta_str_t *ta_findonly_l( GList **list, pthread_t thread_id )
/* [<][>][^][v][top][bottom][index][help] */
49 {
50 GList *item;
51
52 /* try to find first */
53 for(item = g_list_first(*list);
54 item != NULL;
55 item = g_list_next(item)) {
56 ta_str_t *tas = (ta_str_t *) (item->data);
57
58 if( tas->thread_id == thread_id ) {
59 return tas;
60 }
61 }
62 return NULL;
63 }
64
65
66 /*++++++++++++++++++++++++++++++++++++++
67
68 Finds a thread by thread_id, or creates a new entry if there isn't one.
69 Assumes locked list.
70
71 ta_str_t *ta_findcreate_l returns a pointer to the thread's record
72
73 GList **list thread list
74
75 pthread_t thread_id thread id
76
77 ++++++++++++++++++++++++++++++++++++++*/
78 static
79 ta_str_t *ta_findcreate_l( GList **list, pthread_t thread_id )
/* [<][>][^][v][top][bottom][index][help] */
80 {
81 ta_str_t *newtas;
82
83 if( (newtas = ta_findonly_l(list, thread_id)) == NULL) {
84
85 /* not found => add */ /* zero everything*/
86 newtas = (ta_str_t *)UT_calloc(1, sizeof(ta_str_t));
87 newtas->thread_id = thread_id;
88
89 *list = g_list_append( *list, newtas );
90 }
91
92 return newtas;
93 }
94
95
96
97 /*++++++++++++++++++++++++++++++++++++++
98
99 finds and removes an entry for a thread given by thread_id.
100 Assumes locked list.
101
102 GList **list thread list
103
104 pthread_t thread_id thread id
105
106 ++++++++++++++++++++++++++++++++++++++*/
107 static
108 void ta_remove_l(GList **list, pthread_t thread_id )
/* [<][>][^][v][top][bottom][index][help] */
109 {
110 GList *item;
111
112 for(item = g_list_first(*list);
113 item != NULL;
114 item = g_list_next(item)) {
115 ta_str_t *tas = (ta_str_t *) (item->data);
116
117 if( tas->thread_id == thread_id ) {
118 *list = g_list_remove_link(*list, item);
119 wr_clear_list( &item );
120 break;
121 }
122 }
123
124 return;
125 }
126
127
128 /*++++++++++++++++++++++++++++++++++++++
129
130 sets the activity field in the given thread's record.
131 Truncates the string if too long.
132
133 ta_str_t *tas pointer to the thread's record
134
135 char *activity new value for the activity field
136 ++++++++++++++++++++++++++++++++++++++*/
137 static
138 void ta_setactivity_l(ta_str_t *tas, char *activity)
/* [<][>][^][v][top][bottom][index][help] */
139 {
140 char *nl;
141
142 strncpy(tas->activity, activity, TA_ACT_LEN-1);
143 tas->activity[TA_ACT_LEN]=0;
144 /* convert last newline to a space, if any */
145 if( (nl=strrchr(tas->activity, '\n')) != NULL ) {
146 *nl=' ';
147 }
148 }
149
150
151 #define TA_HEADER "%-8s %15s %4s %4s %5s %5s %4s %6s %s\n"
152 #define TA_FORMAT "%-8s %15s %4d %4lu %5.1f %5.1f %4d %6.3f %s\n"
153
154
155 /*++++++++++++++++++++++++++++++++++++++
156
157 prints a header for a list of threads to a specified buffer.
158 The output is truncated if the buffer is too small.
159
160 char *buf pointer to the buffer
161
162 unsigned length buffer size
163 ++++++++++++++++++++++++++++++++++++++*/
164 static
165 void ta_print_header(char *buf, unsigned length)
/* [<][>][^][v][top][bottom][index][help] */
166 {
167 snprintf(buf, length, TA_HEADER,
168 "type", "from", "sock", "thr", "sess", "task", "#",
169 "avg", "current"
170 );
171 }
172
173
174 /*++++++++++++++++++++++++++++++++++++++
175
176 Formats the data from one thread's record to an entry for a list of
177 threads. Prints to a specified buffer. Calculates the average time
178 spent per event as well as the lifetime of the thread. Checks the
179 address of the peer on the socket. The output is truncated if the
180 buffer is too small.
181
182 ta_str_t *tas pointer to the thread's record
183
184 char *buf pointer to the buffer
185
186 unsigned length buffer size
187
188 ut_timer_t *reftime current time
189
190 ++++++++++++++++++++++++++++++++++++++*/
191 static
192 void ta_printone_l(ta_str_t *tas, char *buf, unsigned length,
/* [<][>][^][v][top][bottom][index][help] */
193 ut_timer_t *reftime)
194 {
195 float session, task; /* duration of the session/task */
196 char *address = SK_getpeername(tas->sock); /* allocated! */
197 /* can be NULL for example if the socket has just closed
198 or the file descriptor is not a socket */
199
200 session = UT_timediff( &tas->sessionstart, reftime );
201 task = UT_timediff( &tas->taskstart, reftime );
202
203 snprintf(buf, length, TA_FORMAT ,
204 tas->type,
205 address ? address : "",
206 tas->sock,
207 (long unsigned)tas->thread_id,
208 session,
209 task,
210 tas->tasks,
211 (tas->tasks > 0) ? session / tas->tasks : 0,
212 tas->activity);
213
214 if (address) {
215 UT_free(address);
216 }
217 }
218
219
220 /*++++++++++++++++++++++++++++++++++++++
221
222 Public adding function - adds the current thread to the list,
223 storing the given socket and type string along.
224
225 int sock associated socket (if any, or 0 if not)
226
227 char *type type string
228
229 ++++++++++++++++++++++++++++++++++++++*/
230 void TA_add(int sock, char *type)
/* [<][>][^][v][top][bottom][index][help] */
231 {
232 ta_str_t *newtas;
233
234 /* lock the list */
235 pthread_mutex_lock( &ta_mutex );
236
237 /* find/create node and set peer/thread_id */
238 newtas = ta_findcreate_l( &ta_list, pthread_self());
239 newtas->sock = sock;
240 newtas->tasks = 0;
241 newtas->condat = NULL;
242 UT_timeget( &newtas->sessionstart );
243 UT_timeget( &newtas->taskstart ); /* just to get it a reasonable value */
244
245 snprintf(newtas->type, TA_TYPE_LEN, type);
246 ta_setactivity_l(newtas,"--");
247
248 /* unlock */
249 pthread_mutex_unlock( &ta_mutex );
250 }
251
252
253 /*++++++++++++++++++++++++++++++++++++++
254
255 Public deletion function - deletes the current thread from the list.
256
257 ++++++++++++++++++++++++++++++++++++++*/
258 void TA_delete(void)
/* [<][>][^][v][top][bottom][index][help] */
259 {
260 /* lock the list */
261 pthread_mutex_lock( &ta_mutex );
262
263 /* find & remove */
264 ta_remove_l( &ta_list, pthread_self() );
265
266 /* unlock */
267 pthread_mutex_unlock( &ta_mutex );
268 }
269
270
271 /*++++++++++++++++++++++++++++++++++++++
272
273 Public activity-setting function - sets the current activity string
274 for the current thread.
275
276 char *activity new value
277
278 ++++++++++++++++++++++++++++++++++++++*/
279 void TA_setactivity(char *activity)
/* [<][>][^][v][top][bottom][index][help] */
280 {
281 ta_str_t *newtas;
282
283 /* lock the list */
284 pthread_mutex_lock( &ta_mutex );
285
286 /* find */
287 newtas = ta_findcreate_l( &ta_list, pthread_self());
288
289 /* set the activity field */
290 ta_setactivity_l(newtas, activity);
291
292 /* unlock */
293 pthread_mutex_unlock( &ta_mutex );
294 }
295
296
297 /*++++++++++++++++++++++++++++++++++++++
298
299 Public condat-setting function - associates a connection data
300 structure with the current thread.
301
302 sk_conn_st *condat pointer to a connection data structure
303
304 ++++++++++++++++++++++++++++++++++++++*/
305 void TA_setcondat(sk_conn_st *condat)
/* [<][>][^][v][top][bottom][index][help] */
306 {
307 ta_str_t *newtas;
308
309 /* lock the list */
310 pthread_mutex_lock( &ta_mutex );
311
312 /* find */
313 newtas = ta_findcreate_l( &ta_list, pthread_self());
314
315 /* set the condat field */
316 newtas->condat = condat;
317
318 /* unlock */
319 pthread_mutex_unlock( &ta_mutex );
320 }
321
322
323 /*++++++++++++++++++++++++++++++++++++++
324
325 increments the event counter for the current thread.
326
327 ++++++++++++++++++++++++++++++++++++++*/
328 void TA_increment(void)
/* [<][>][^][v][top][bottom][index][help] */
329 {
330 ta_str_t *newtas;
331
332 /* lock the list */
333 pthread_mutex_lock( &ta_mutex );
334
335 /* find */
336 newtas = ta_findcreate_l( &ta_list, pthread_self());
337 /* increment task */
338 newtas->tasks++;
339 /* set task starting time */
340 UT_timeget( &newtas->taskstart );
341
342 /* unlock */
343 pthread_mutex_unlock( &ta_mutex );
344 }
345
346
347 /*++++++++++++++++++++++++++++++++++++++
348
349 resets the time and event counter of a specified thread.
350
351 pthread_t thread_id thread_id
352
353 ++++++++++++++++++++++++++++++++++++++*/
354 void TA_reset_counters(pthread_t thread_id)
/* [<][>][^][v][top][bottom][index][help] */
355 {
356 ta_str_t *tas;
357
358 /* lock the list */
359 pthread_mutex_lock( &ta_mutex );
360
361 if( (tas = ta_findonly_l(&ta_list, thread_id)) != NULL) {
362 UT_timeget( &tas->sessionstart );
363 UT_timeget( &tas->taskstart ); /* just to get it a reasonable value */
364 tas->tasks = 0;
365 }
366
367 pthread_mutex_unlock( &ta_mutex );
368 }
369
370
371 /*++++++++++++++++++++++++++++++++++++++
372
373 Compiles a list of the threads' data records as text.
374
375 char * TA_tostring returns an allocated text, must be freed after use.
376
377 ++++++++++++++++++++++++++++++++++++++*/
378 char * TA_tostring(void)
/* [<][>][^][v][top][bottom][index][help] */
379 {
380 GList *item;
381 char *bigbuf = NULL;
382 char smallbuf[TA_PRINT_LEN];
383 ut_timer_t reftime;
384
385 ta_print_header(smallbuf, TA_PRINT_LEN);
386 bigbuf = (char *)UT_malloc(strlen(smallbuf)+2);
387 strcpy(bigbuf, smallbuf);
388 strcat(bigbuf, "\n");
389
390 /* lock the list */
391 pthread_mutex_lock( &ta_mutex );
392
393 /* get reference time */
394 UT_timeget( &reftime );
395
396 /* iterate */
397 for(item = g_list_first(ta_list);
398 item != NULL;
399 item = g_list_next(item)) {
400 ta_str_t *tas = (ta_str_t *) (item->data);
401 unsigned smalllen;
402 unsigned biglen = ( bigbuf == NULL ) ? 0 : strlen(bigbuf);
403
404 ta_printone_l(tas, smallbuf, TA_PRINT_LEN, &reftime);
405 smalllen = strlen(smallbuf);
406
407 bigbuf = (char *)UT_realloc(bigbuf, biglen+smalllen+3);
408
409 strcat(bigbuf, smallbuf);
410 }
411 /* unlock */
412 pthread_mutex_unlock( &ta_mutex );
413
414 return bigbuf;
415 }
416
417
418
419 /*++++++++++++++++++++++++++++++++++++++
420
421 Finds a thread of the matching type, socket file descriptor and thread id
422 and executes the watchdog's triggers if it's defined.
423
424 char *type thread type string
425
426 int sock socket #
427
428 pthread_t thread_id thread id
429
430 ++++++++++++++++++++++++++++++++++++++*/
431 void TA_trigger(char *type, int sock, pthread_t thread_id)
/* [<][>][^][v][top][bottom][index][help] */
432 {
433 ta_str_t *tas;
434
435 /* lock the list */
436 pthread_mutex_lock( &ta_mutex );
437
438 if( (tas = ta_findonly_l(&ta_list, thread_id)) != NULL
439 && tas->sock == sock
440 && strcmp(tas->type, type) == 0
441 && tas->condat != NULL
442 && tas->condat->sock == sock
443 ) {
444 SK_watchtrigger(tas->condat);
445 }
446
447 /* unlock */
448 pthread_mutex_unlock( &ta_mutex );
449
450 }