/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include typedef struct axutil_log_impl axutil_log_impl_t; static axis2_status_t axutil_log_impl_rotate( axutil_log_t *log); static void AXIS2_CALL axutil_log_impl_write( axutil_log_t *log, const axis2_char_t *buffer, axutil_log_levels_t level, const axis2_char_t *file, const int line); AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_write_to_file( axutil_log_t *log, axutil_thread_mutex_t *mutex, axutil_log_levels_t level, const axis2_char_t *file, const int line, const axis2_char_t *value); static void AXIS2_CALL axutil_log_impl_free( axutil_allocator_t *allocator, axutil_log_t *log); struct axutil_log_impl { axutil_log_t log; void *stream; axis2_char_t *file_name; axutil_thread_mutex_t *mutex; }; #define AXUTIL_INTF_TO_IMPL(log) ((axutil_log_impl_t*)(log)) static const axutil_log_ops_t axutil_log_ops_var = { axutil_log_impl_free, axutil_log_impl_write }; static void AXIS2_CALL axutil_log_impl_free( axutil_allocator_t *allocator, axutil_log_t *log) { axutil_log_impl_t *log_impl = NULL; if(log) { log_impl = AXUTIL_INTF_TO_IMPL(log); if(log_impl->mutex) { axutil_thread_mutex_destroy(log_impl->mutex); } if(log_impl->stream) { axutil_file_handler_close(log_impl->stream); } if(log_impl->file_name) { AXIS2_FREE(allocator, log_impl->file_name); } AXIS2_FREE(allocator, log_impl); } } AXIS2_EXTERN axutil_log_t *AXIS2_CALL axutil_log_create( axutil_allocator_t *allocator, axutil_log_ops_t *ops, const axis2_char_t *stream_name) { axutil_log_impl_t *log_impl; axis2_char_t *path_home; axis2_char_t log_file_name[AXUTIL_LOG_FILE_NAME_SIZE]; axis2_char_t log_dir[AXUTIL_LOG_FILE_NAME_SIZE]; axis2_char_t tmp_filename[AXUTIL_LOG_FILE_NAME_SIZE]; if(!allocator) return NULL; log_impl = (axutil_log_impl_t *)AXIS2_MALLOC(allocator, sizeof(axutil_log_impl_t)); if(!log_impl) return NULL; log_impl->mutex = axutil_thread_mutex_create(allocator, AXIS2_THREAD_MUTEX_DEFAULT); if(!log_impl->mutex) { fprintf(stderr, "cannot create log mutex \n"); return NULL; } #ifndef WIN32 signal(SIGXFSZ, SIG_IGN); #endif /* default log file is axis2.log */ if(stream_name) AXIS2_SNPRINTF(tmp_filename, AXUTIL_LOG_FILE_NAME_SIZE, "%s", stream_name); else AXIS2_SNPRINTF(tmp_filename, AXUTIL_LOG_FILE_NAME_SIZE, "%s", "axis2.log"); /* we write all logs to AXIS2C_HOME/logs if it is set otherwise * to the working dir */ if(stream_name && !(axutil_rindex(stream_name, AXIS2_PATH_SEP_CHAR))) { path_home = AXIS2_GETENV("AXIS2C_HOME"); if(path_home) { AXIS2_SNPRINTF(log_dir, AXUTIL_LOG_FILE_NAME_SIZE, "%s%c%s", path_home, AXIS2_PATH_SEP_CHAR, "logs"); if(AXIS2_SUCCESS == axutil_file_handler_access(log_dir, AXIS2_F_OK)) { AXIS2_SNPRINTF(log_file_name, AXUTIL_LOG_FILE_NAME_SIZE, "%s%c%s", log_dir, AXIS2_PATH_SEP_CHAR, tmp_filename); } else { fprintf(stderr, "log folder %s does not exist - log file %s " "is written to . dir\n", log_dir, tmp_filename); AXIS2_SNPRINTF(log_file_name, AXUTIL_LOG_FILE_NAME_SIZE, "%s", tmp_filename); } } else { fprintf(stderr, "AXIS2C_HOME is not set - log is written to . dir\n"); AXIS2_SNPRINTF(log_file_name, AXUTIL_LOG_FILE_NAME_SIZE, "%s", tmp_filename); } } else { AXIS2_SNPRINTF(log_file_name, AXUTIL_LOG_FILE_NAME_SIZE, "%s", tmp_filename); } log_impl->file_name = AXIS2_MALLOC(allocator, AXUTIL_LOG_FILE_NAME_SIZE); log_impl->log.size = AXUTIL_LOG_FILE_SIZE; sprintf(log_impl->file_name, "%s", log_file_name); axutil_thread_mutex_lock(log_impl->mutex); log_impl->stream = axutil_file_handler_open(log_file_name, "a+"); axutil_log_impl_rotate((axutil_log_t *)log_impl); axutil_thread_mutex_unlock(log_impl->mutex); if(!log_impl->stream) log_impl->stream = stderr; /* by default, log is enabled */ log_impl->log.enabled = 1; log_impl->log.level = AXIS2_LOG_LEVEL_DEBUG; if(ops) { log_impl->log.ops = ops; } else { log_impl->log.ops = &axutil_log_ops_var; } return &(log_impl->log); } static void AXIS2_CALL axutil_log_impl_write( axutil_log_t *log, const axis2_char_t *buffer, axutil_log_levels_t level, const axis2_char_t *file, const int line) { if(log && log->enabled && buffer) { axutil_log_impl_t *l = AXUTIL_INTF_TO_IMPL(log); if(!l->mutex) fprintf(stderr, "Log mutex is not found\n"); if(!l->stream) fprintf(stderr, "Stream is not found\n"); if(level <= log->level || level == AXIS2_LOG_LEVEL_CRITICAL) { axutil_log_impl_write_to_file(log, l->mutex, level, file, line, buffer); } } #ifndef AXIS2_NO_LOG_FILE else if(buffer) fprintf(stderr, "please check your log and buffer"); #endif else fprintf(stderr, "please check your log and buffer"); } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_write_to_file( axutil_log_t *log, axutil_thread_mutex_t *mutex, axutil_log_levels_t level, const axis2_char_t *file, const int line, const axis2_char_t *value) { const char *level_str = ""; axutil_log_impl_t *log_impl = AXUTIL_INTF_TO_IMPL(log); FILE *fd = NULL; /** * print all critical and error logs irrespective of log->level setting */ switch(level) { case AXIS2_LOG_LEVEL_CRITICAL: level_str = "[critical] "; break; case AXIS2_LOG_LEVEL_ERROR: level_str = "[error] "; break; case AXIS2_LOG_LEVEL_WARNING: level_str = "[warning] "; break; case AXIS2_LOG_LEVEL_INFO: level_str = "[info] "; break; case AXIS2_LOG_LEVEL_DEBUG: level_str = "[debug] "; break; case AXIS2_LOG_LEVEL_TRACE: level_str = "[...TRACE...] "; break; case AXIS2_LOG_LEVEL_USER: break; } axutil_thread_mutex_lock(mutex); axutil_log_impl_rotate(log); fd = log_impl->stream; if(fd) { if(file) fprintf(fd, "[%s] %s%s(%d) %s\n", axutil_log_impl_get_time_str(), level_str, file, line, value); else fprintf(fd, "[%s] %s %s\n", axutil_log_impl_get_time_str(), level_str, value); fflush(fd); } axutil_thread_mutex_unlock(mutex); } static axis2_status_t axutil_log_impl_rotate( axutil_log_t *log) { long size = -1; FILE *old_log_fd = NULL; axis2_char_t old_log_file_name[AXUTIL_LOG_FILE_NAME_SIZE]; axutil_log_impl_t *log_impl = AXUTIL_INTF_TO_IMPL(log); if(log_impl->file_name) size = axutil_file_handler_size(log_impl->file_name); if(size >= log->size) { AXIS2_SNPRINTF(old_log_file_name, AXUTIL_LOG_FILE_NAME_SIZE, "%s%s", log_impl->file_name, ".old"); axutil_file_handler_close(log_impl->stream); old_log_fd = axutil_file_handler_open(old_log_file_name, "w+"); log_impl->stream = axutil_file_handler_open(log_impl->file_name, "r"); if(old_log_fd && log_impl->stream) { axutil_file_handler_copy(log_impl->stream, old_log_fd); axutil_file_handler_close(old_log_fd); axutil_file_handler_close(log_impl->stream); old_log_fd = NULL; log_impl->stream = NULL; } if(old_log_fd) { axutil_file_handler_close(old_log_fd); } if(log_impl->stream) { axutil_file_handler_close(log_impl->stream); } log_impl->stream = axutil_file_handler_open(log_impl->file_name, "w+"); } return AXIS2_SUCCESS; } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_user( axutil_log_t *log, const axis2_char_t *file, const int line, const axis2_char_t *format, ...) { if(log && log->ops && log->ops->write && format && log->enabled) { if(AXIS2_LOG_LEVEL_DEBUG <= log->level) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_USER, file, line); } } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_debug( axutil_log_t *log, const axis2_char_t *file, const int line, const axis2_char_t *format, ...) { if(log && log->ops && log->ops->write && format && log->enabled) { if(AXIS2_LOG_LEVEL_DEBUG <= log->level && log->level != AXIS2_LOG_LEVEL_USER) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_DEBUG, file, line); } } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_info( axutil_log_t *log, const axis2_char_t *format, ...) { if(log && log->ops && log->ops->write && format && log->enabled) { if(AXIS2_LOG_LEVEL_INFO <= log->level && log->level != AXIS2_LOG_LEVEL_USER) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_INFO, NULL, -1); } } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_warning( axutil_log_t *log, const axis2_char_t *file, const int line, const axis2_char_t *format, ...) { if(log && log->ops && log->ops->write && format && log->enabled) { if(AXIS2_LOG_LEVEL_WARNING <= log->level && log->level != AXIS2_LOG_LEVEL_USER) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_WARNING, file, line); } } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_error( axutil_log_t *log, const axis2_char_t *file, const int line, const axis2_char_t *format, ...) { if(log && log->ops && log->ops->write && format && log->enabled) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_ERROR, file, line); } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_critical( axutil_log_t *log, const axis2_char_t *file, const int line, const axis2_char_t *format, ...) { if(log && log->ops && log->ops->write && format && log->enabled) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_CRITICAL, file, line); } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } AXIS2_EXTERN axis2_char_t *AXIS2_CALL axutil_log_impl_get_time_str( void) { time_t tp; char *time_str; tp = time(&tp); time_str = ctime(&tp); if(!time_str) { return NULL; } if('\n' == time_str[strlen(time_str) - 1]) { time_str[strlen(time_str) - 1] = '\0'; } return time_str; } AXIS2_EXTERN axutil_log_t *AXIS2_CALL axutil_log_create_default( axutil_allocator_t *allocator) { axutil_log_impl_t *log_impl; if(!allocator) return NULL; log_impl = (axutil_log_impl_t *)AXIS2_MALLOC(allocator, sizeof(axutil_log_impl_t)); if(!log_impl) return NULL; log_impl->mutex = axutil_thread_mutex_create(allocator, AXIS2_THREAD_MUTEX_DEFAULT); if(!log_impl->mutex) { fprintf(stderr, "cannot create log mutex \n"); return NULL; } axutil_thread_mutex_lock(log_impl->mutex); log_impl->file_name = NULL; log_impl->log.size = AXUTIL_LOG_FILE_SIZE; log_impl->stream = stderr; axutil_thread_mutex_unlock(log_impl->mutex); /* by default, log is enabled */ log_impl->log.enabled = 1; log_impl->log.level = AXIS2_LOG_LEVEL_DEBUG; log_impl->log.ops = &axutil_log_ops_var; return &(log_impl->log); } #ifdef AXIS2_TRACE AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_trace( axutil_log_t *log, const axis2_char_t *file, const int line, const axis2_char_t *format, ...) { if (log && log->ops && log->ops->write && format && log->enabled) { if(AXIS2_LOG_LEVEL_TRACE <= log->level && log->level != AXIS2_LOG_LEVEL_USER) { char value[AXIS2_LEN_VALUE + 1]; va_list ap; va_start(ap, format); AXIS2_VSNPRINTF(value, AXIS2_LEN_VALUE, format, ap); va_end(ap); log->ops->write(log, value, AXIS2_LOG_LEVEL_TRACE, file, line); } } #ifndef AXIS2_NO_LOG_FILE else fprintf(stderr, "please check your log and buffer"); #endif } #else AXIS2_EXTERN void AXIS2_CALL axutil_log_impl_log_trace( axutil_log_t *log, const axis2_char_t *filename, const int linenumber, const axis2_char_t *format, ...) { } #endif AXIS2_EXTERN void AXIS2_CALL axutil_log_free( axutil_allocator_t *allocator, struct axutil_log *log) { log->ops->free(allocator, log); } AXIS2_EXTERN void AXIS2_CALL axutil_log_write( axutil_log_t *log, const axis2_char_t *buffer, axutil_log_levels_t level, const axis2_char_t *file, const int line) { log->ops->write(log, buffer, level, file, line); }