Source File modules/ta/ta.c

    1    | /***************************************
    2    |   $Revision: 1.2 $
    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   | static
    36   | ta_str_t *ta_findcreate_l( GList **list, pthread_t thread_id )
    37   | {
    38   |   GList *item;
    39   |   ta_str_t *newtas;
    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   |
    52   |   /* not found => add */  /* zero everything*/
    53   |   dieif( !NOERR( wr_calloc( (void **) &newtas, 1, sizeof( ta_str_t ))));
    54   |   newtas->thread_id = thread_id;
    55   |
    56   |   *list = g_list_append( *list, newtas );
    57   |
    58   |   return newtas;
    59   | }
    60   |
    61   |
    62   | /* find and remove */
    63   | static
    64   | void ta_remove_l(GList **list, pthread_t thread_id )
    65   | {
    66   |  GList *item;
    67   |
    68   |  for(item = g_list_first(*list);
    69   |      item != NULL;
    70   |      item = g_list_next(item)) {
    71   |    ta_str_t *tas = (ta_str_t *) (item->data);
    72   |
    73   |    if( tas->thread_id == thread_id ) {
    74   |      *list = g_list_remove_link(*list, item);
    75   |      wr_clear_list( &item );
    76   |      break;
    77   |    }
    78   |  }
    79   |
    80   |  return;
    81   | }
    82   |
    83   | /* set the activity field */
    84   | static
    85   | void ta_setactivity_l(ta_str_t *tas, char *activity)
    86   | {
    87   |   char *nl;
    88   |
    89   |   strncpy(tas->activity, activity, TA_ACT_LEN-1);
    90   |   tas->activity[TA_ACT_LEN]=0;
    91   |   /* convert last newline to a space, if any */
    92   |   if( (nl=strrchr(tas->activity, '\n')) != NULL ) {
    93   |     *nl=' ';
    94   |   }
    95   | }
    96   |
    97   |
    98   | #define TA_HEADER "%-8s %15s %4s %4s %5s %5s %4s %5s %s\n"
    99   | #define TA_FORMAT "%-8s %15s %4d %4d %5.1f %5.1f %4d %5.2f %s\n"
    100  |
    101  | static
    102  | void ta_print_header(char *buf, int length)
    103  | {
    104  |   snprintf(buf, length, TA_HEADER,
    105  | 	   "type", "from", "sock", "thr", "sess", "task", "#",
    106  | 	   "avg", "current"
    107  | 	   );
    108  | }
    109  |
    110  | /* fill in one entry */
    111  | static
    112  | void ta_printone_l(ta_str_t *tas, char *buf, int length,
    113  | 		   ut_timer_t *reftime)
    114  | {
    115  |   float session, task;  /* duration of the session/task */
    116  |   char *address = SK_getpeername(tas->sock); /* allocated! */
    117  |   /* can be NULL for example if the socket has just closed
    118  |      or the file descriptor is not a socket */
    119  |
    120  |   session = UT_timediff( &tas->sessionstart, reftime );
    121  |   task    = UT_timediff( &tas->taskstart, reftime );
    122  |
    123  |   snprintf(buf, length, TA_FORMAT ,
    124  | 	   tas->type,
    125  | 	   address ? address : "",
    126  | 	   tas->sock,
    127  | 	   tas->thread_id,
    128  | 	   session,
    129  | 	   task,
    130  | 	   tas->tasks,
    131  | 	   (tas->tasks > 0) ? session / tas->tasks : 0,
    132  | 	   tas->activity);
    133  |
    134  |   if (address) {
    135  |     wr_free(address);
    136  |   }
    137  | }
    138  |
    139  | /* PUBLIC adding function */
    140  | void TA_add(int sock, char *type)
    141  | {
    142  |   ta_str_t *newtas;
    143  |
    144  |   /* lock the list */
    145  |   pthread_mutex_lock( &ta_mutex );
    146  |
    147  |   /* find/create node and set peer/thread_id */
    148  |   newtas = ta_findcreate_l( &ta_list, pthread_self());
    149  |   newtas->sock = sock;
    150  |   newtas->tasks = 0;
    151  |   UT_timeget( &newtas->sessionstart );
    152  |   UT_timeget( &newtas->taskstart ); /* just to get it a reasonable value */
    153  |
    154  |   snprintf(newtas->type, TA_TYPE_LEN, type);
    155  |   ta_setactivity_l(newtas,"--");
    156  |
    157  |   /* unlock */
    158  |   pthread_mutex_unlock( &ta_mutex );
    159  | }
    160  |
    161  |
    162  | /* PUBLIC deletion function */
    163  | void TA_delete(void)
    164  | {
    165  |   /* lock the list */
    166  |   pthread_mutex_lock( &ta_mutex );
    167  |
    168  |   /* find & remove */
    169  |   ta_remove_l( &ta_list, pthread_self() );
    170  |
    171  |   /* unlock */
    172  |   pthread_mutex_unlock( &ta_mutex );
    173  | }
    174  |
    175  |
    176  | /* PUBLIC activity-setting function */
    177  | void TA_setactivity(char *activity)
    178  | {
    179  |   ta_str_t *newtas;
    180  |
    181  |   /* lock the list */
    182  |   pthread_mutex_lock( &ta_mutex );
    183  |
    184  |   /* find */
    185  |   newtas = ta_findcreate_l( &ta_list, pthread_self());
    186  |
    187  |   /* set the activity field */
    188  |   ta_setactivity_l(newtas, activity);
    189  |
    190  |   /* unlock */
    191  |   pthread_mutex_unlock( &ta_mutex );
    192  | }
    193  |
    194  | void TA_increment(void)
    195  | {
    196  |   ta_str_t *newtas;
    197  |
    198  |   /* lock the list */
    199  |   pthread_mutex_lock( &ta_mutex );
    200  |
    201  |   /* find */
    202  |   newtas = ta_findcreate_l( &ta_list, pthread_self());
    203  |   /* increment task */
    204  |   newtas->tasks++;
    205  |   /* set task starting time */
    206  |   UT_timeget( &newtas->taskstart );
    207  |
    208  |   /* unlock */
    209  |   pthread_mutex_unlock( &ta_mutex );
    210  | }
    211  |
    212  | char * TA_tostring(void)
    213  | {
    214  |   GList *item;
    215  |   char *bigbuf = NULL;
    216  |   char smallbuf[TA_PRINT_LEN];
    217  |   ut_timer_t reftime;
    218  |
    219  |   ta_print_header(smallbuf, TA_PRINT_LEN);
    220  |   dieif( !NOERR(wr_realloc( (void **) &bigbuf, strlen(smallbuf)+2 )));
    221  |   strcat(bigbuf, smallbuf);
    222  |   strcat(bigbuf, "\n");
    223  |
    224  |   /* lock the list */
    225  |   pthread_mutex_lock( &ta_mutex );
    226  |
    227  |   /* get reference time */
    228  |   UT_timeget( &reftime );
    229  |
    230  |   /* iterate */
    231  |   for(item = g_list_first(ta_list);
    232  |       item != NULL;
    233  |       item = g_list_next(item)) {
    234  |     ta_str_t *tas = (ta_str_t *) (item->data);
    235  |     int smalllen;
    236  |     int biglen = ( bigbuf == NULL ) ? 0 : strlen(bigbuf);
    237  |
    238  |     ta_printone_l(tas, smallbuf, TA_PRINT_LEN, &reftime);
    239  |     smalllen = strlen(smallbuf);
    240  |
    241  |     dieif( !NOERR(wr_realloc( (void **) &bigbuf, biglen+smalllen+3 )));
    242  |
    243  |     strcat(bigbuf, smallbuf);
    244  |   }
    245  |   /* unlock */
    246  |   pthread_mutex_unlock( &ta_mutex );
    247  |
    248  |   return bigbuf;
    249  | }