Simple utilities sink - stuff that doesn't fit anywhere else / objects in plain C Snapshot
logg.c
Go to the documentation of this file.
00001 #include <pthread.h>
00002 #include <unistd.h>
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/time.h>
00006 #include <fcntl.h>
00007 #include <syslog.h>
00008 #include <stdarg.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <butils/errorp.h>
00012 #include <butils/logg.h>
00013 
00014 MLOG_LEVEL m_current_log_level = MLOG_LEVEL_ERROR;
00015 
00016 static MLOG_ACTION log_action;
00017 static MLOG_ALLOC alloc_strategy = MLOG_ALLOC_TLS_HEAP;
00018 static MLOG_LEVEL stack_dump_level = MLOG_LEVEL_ERROR;
00019 static size_t alloc_size = 1024;
00020 static pthread_key_t log_tls_entry;
00021 static int log_fd;
00022 static int log_prefix_level = MLOG_PREFIX_LOG_LEVEL | MLOG_PREFIX_SOURCE_FILE | MLOG_PREFIX_TIME;
00023 
00024 static char * log_level_names[] = {
00025   "TURN_OFF_LOGGING",
00026   "ERROR",
00027   "WARN",
00028   "INFO",
00029   "DEBUG",
00030   "TRACE",
00031 };
00032 
00033 void error_dump_string( const char *msg, char *buff, size_t buff_size);
00034 
00035 
00036 static void tls_free(void *val)
00037 {
00038   if (val) {
00039     free(val);
00040   }
00041 }
00042 
00043 int  MLOG_init( MLOG_LEVEL current, MLOG_ACTION action, void *arg)
00044 {
00045   m_current_log_level = current;
00046  
00047   log_action |= action;
00048 
00049   if (action & MLOG_ACTION_TO_FILE) {
00050     log_fd = open( (const char *) arg , O_CREAT | O_RDWR, S_IWUSR  | S_IRUSR );
00051     return log_fd == -1;
00052   }
00053   return 0;
00054 }
00055 
00056 
00057 int  MLOG_alloc_option( MLOG_ALLOC option, size_t size)
00058 {
00059   alloc_strategy = option;
00060   alloc_size = size;
00061 
00062 
00063   if (alloc_strategy == MLOG_ALLOC_TLS_HEAP) {
00064     if (log_tls_entry == 0) {
00065       if (pthread_key_create( &log_tls_entry, tls_free )) {
00066         return -1;
00067       }
00068       pthread_setspecific( log_tls_entry, 0 );
00069     }
00070   }
00071   return 0;
00072 }
00073 
00074 void MLOG_dump_stack_level( MLOG_LEVEL level )
00075 {
00076   stack_dump_level = level;
00077 }
00078 
00079 
00080 int MLOG_printf( MLOG_LEVEL current,  const char *file, int line, const char *format , ... )
00081 {
00082   char *sbuf,*pos;
00083   size_t buf_size, msg_len;
00084   va_list vlist;
00085   struct timeval now_time_val;
00086   struct tm now_time;
00087   int rt;
00088 
00089   switch(alloc_strategy) {
00090     case MLOG_ALLOC_STACK:
00091       sbuf = alloca( alloc_size );
00092       break;
00093     case MLOG_ALLOC_HEAP:
00094       sbuf = (char *) malloc( alloc_size );
00095       if (!sbuf) {
00096         return -1;
00097       }
00098       break;
00099     case MLOG_ALLOC_TLS_HEAP:
00100       sbuf = pthread_getspecific( log_tls_entry );
00101       if (!sbuf) {
00102         sbuf = malloc( alloc_size );
00103         if (!sbuf) {
00104           return -1;
00105         }
00106         pthread_setspecific( log_tls_entry, sbuf );
00107       }
00108       break;
00109   }
00110   
00111   buf_size = alloc_size - 2;
00112   pos = sbuf;
00113 
00114   if (log_prefix_level & MLOG_PREFIX_LOG_LEVEL && buf_size > 0) {
00115     rt = snprintf( pos, buf_size, "%s : ", log_level_names[ current ] );
00116     if (rt < 0) {
00117       return -1;
00118     }
00119     pos += rt;
00120     buf_size -= rt;
00121   }
00122   
00123   if (log_prefix_level & MLOG_PREFIX_SOURCE_FILE && buf_size > 0) {
00124     rt = snprintf( pos, buf_size, "[%s:%d] ", file, line  );
00125     if (rt < 0) {
00126       return -1;
00127     }
00128     pos += rt;
00129     buf_size -= rt;
00130    }
00131   
00132   if (log_prefix_level & MLOG_PREFIX_TIME && buf_size > 0) {
00133     gettimeofday( &now_time_val, 0 );
00134     localtime_r(  &now_time_val.tv_sec, &now_time);
00135           
00136     rt = snprintf( pos, buf_size, "%02d:%02d:%02d:%06ld ",
00137                                         (int)  now_time.tm_hour,
00138                                         (int)  now_time.tm_min,
00139                                         (int)  now_time.tm_sec,
00140                                         now_time_val.tv_usec );
00141     if (rt < 0) {
00142       return -1;
00143     }
00144     pos += rt;
00145     buf_size -= rt;
00146   }
00147 
00148   if (buf_size > 0) {
00149     va_start( vlist, format );
00150     rt = vsnprintf( pos, buf_size, format, vlist );
00151     va_end( vlist );
00152     if (rt < 0) {
00153       return -1;
00154     }
00155     pos += rt;
00156     buf_size -= rt;
00157   }
00158   
00159   strcpy( pos, "\n");
00160   msg_len = alloc_size - buf_size - 1;
00161   
00162   if (log_action & MLOG_ACTION_CONSOLE) {
00163     write( 2, sbuf, msg_len );
00164   } 
00165 
00166 
00167   if (log_action & MLOG_ACTION_TO_FILE) {
00168     write( log_fd, sbuf, msg_len );
00169   }
00170 
00171   if (log_action & MLOG_ACTION_SYSLOG_TRACE) {
00172     syslog( LOG_USER, "%s", sbuf );
00173   }
00174   
00175   if (current <= stack_dump_level) {
00176     if (!errorp_is_file_open()) {
00177        errorp_open_file( "err.log" );
00178     }
00179     error_dump_string( sbuf, sbuf, alloc_size );
00180   }
00181 
00182   switch(alloc_strategy) {
00183     case MLOG_ALLOC_TLS_HEAP:
00184     case MLOG_ALLOC_STACK:
00185       break;
00186     case MLOG_ALLOC_HEAP:
00187       free(sbuf);
00188       break;
00189   }
00190   return 0;
00191 } 
00192 
00193