summaryrefslogtreecommitdiffstats
path: root/util/src/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/src/log.c')
-rw-r--r--util/src/log.c576
1 files changed, 576 insertions, 0 deletions
diff --git a/util/src/log.c b/util/src/log.c
new file mode 100644
index 0000000..72a2508
--- /dev/null
+++ b/util/src/log.c
@@ -0,0 +1,576 @@
+/*
+ * 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_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_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);
+}
+