## modules/ta/ta.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. ta_findonly_l
2. ta_findcreate_l
3. ta_remove_l
4. ta_setactivity_l
5. ta_print_header
6. ta_printone_l
7. TA_add
8. TA_delete
9. TA_setactivity
10. TA_setcondat
11. TA_increment
12. TA_reset_counters
13. TA_tostring
14. TA_trigger

       1 /***************************************
       2   $Revision: 1.8 $
       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 /*++++++++++++++++++++++++++++++++++++++
      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     dieif( !NOERR( wr_calloc( (void **) &newtas, 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 %4d %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            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     wr_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   dieif( !NOERR(wr_malloc( (void **) &bigbuf, 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     dieif( !NOERR(wr_realloc( (void **) &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 }

/* [<][>][^][v][top][bottom][index][help] */