Source File modules/ta/ta.c

    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 )
    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 )
    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 )
    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)
    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)
    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,
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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  | }