| /* |
| * 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 <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <platforms/axutil_platform_auto_sense.h> |
| #include <axutil_log_default.h> |
| #include <axutil_file_handler.h> |
| #include <axutil_thread.h> |
| #include <signal.h> |
| |
| 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); |
| } |
| |