Simple utilities sink - stuff that doesn't fit anywhere else / objects in plain C Snapshot
|
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