summaryrefslogtreecommitdiff
path: root/accel-dp/log_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-dp/log_file.c')
-rw-r--r--accel-dp/log_file.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/accel-dp/log_file.c b/accel-dp/log_file.c
new file mode 100644
index 0000000..395e24c
--- /dev/null
+++ b/accel-dp/log_file.c
@@ -0,0 +1,246 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <aio.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include "init.h"
+#include "common.h"
+#include "conf_file.h"
+
+#include "log.h"
+
+//static const char* level_name[]={" msg", "error", " warn", " info", " info", "debug"};
+static int log_fd = -1;
+static int conf_buf_size;
+
+#define THREADED_LOG_FILE
+
+#ifdef THREADED_LOG_FILE
+static LIST_HEAD(log_queue);
+static LIST_HEAD(log_buf);
+static int buf_size;
+static int buf_cnt;
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond;
+static pthread_t thr;
+static int need_reopen;
+#endif
+
+static void make_hdr(struct log_msg *msg)
+{
+ struct tm tm;
+
+ tm = *localtime(&msg->timestamp.tv_sec);
+
+ msg->hdr->len = sprintf(msg->hdr->msg, "[%i-%02i-%02i %02i:%02i:%02i]: ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec/*, (int)msg->timestamp.tv_usec/100000*/);
+}
+
+/*static void __log(struct log_msg *msg)
+{
+ struct log_chunk *chunk;
+ struct iovec iov[IOV_MAX];
+ int iov_cnt;
+ struct list_head *pos = msg->chunks->next;
+
+ make_hdr(msg);
+
+ iov[0].iov_base = msg->hdr->msg;
+ iov[0].iov_len = msg->hdr->len;
+ iov_cnt = 1;
+
+ while (pos != msg->chunks) {
+ chunk = list_entry(pos, typeof(*chunk), entry);
+ iov[iov_cnt].iov_base = chunk->msg;
+ iov[iov_cnt].iov_len = chunk->len;
+ iov_cnt++;
+ pos = pos->next;
+
+ if (iov_cnt == IOV_MAX || pos == msg->chunks) {
+ writev(log_fd, iov, iov_cnt);
+ iov_cnt = 0;
+ }
+ }
+
+ log_free_msg(msg);
+}*/
+
+static void write_buf()
+{
+ struct log_msg *msg;
+ struct log_chunk *chunk;
+ struct iovec iov[IOV_MAX];
+ int n = 0;
+
+ list_for_each_entry(msg, &log_buf, entry) {
+ iov[n].iov_base = msg->hdr->msg;
+ iov[n].iov_len = msg->hdr->len;
+ n++;
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ iov[n].iov_base = chunk->msg;
+ iov[n].iov_len = chunk->len;
+ n++;
+
+ if (n >= IOV_MAX - 2) {
+ writev(log_fd, iov, n);
+ n = 0;
+ }
+ }
+ }
+
+ if (n)
+ writev(log_fd, iov, n);
+
+ while (!list_empty(&log_buf)) {
+ msg = list_entry(log_buf.next, typeof(*msg), entry);
+ list_del(&msg->entry);
+ log_free_msg(msg);
+ }
+
+ buf_size = 0;
+ buf_cnt = 0;
+}
+
+static void do_log(struct log_msg *msg)
+{
+#ifndef THREADED_LOG_FILE
+ struct log_chunk *chunk;
+#endif
+
+ if (log_fd < 0 || msg->level == 5) {
+ log_free_msg(msg);
+ return;
+ }
+
+ make_hdr(msg);
+
+#ifdef THREADED_LOG_FILE
+ pthread_mutex_lock(&lock);
+ list_add_tail(&msg->entry, &log_queue);
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&lock);
+#else
+ buf_cnt++;
+ buf_size += msg->hdr->len;
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ buf_size += chunk->len;
+ buf_cnt++;
+ }
+
+ if (buf_cnt > IOV_MAX - 16 || buf_size >= conf_buf_size)
+ write_buf();
+#endif
+}
+
+static void __reopen(void)
+{
+ const char *fname = conf_get_opt("log", "log-file");
+
+ if (log_fd >= 0) {
+ close(log_fd);
+ log_fd = -1;
+ }
+
+ if (!fname)
+ return;
+
+ log_fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+ if (log_fd < 0) {
+ log_emerg("log_file: open '%s': %s\n", fname, strerror(errno));
+ return;
+ }
+
+ fcntl(log_fd, F_SETFD, FD_CLOEXEC);
+}
+
+static void reopen(void)
+{
+#ifdef THREADED_LOG_FILE
+ pthread_mutex_lock(&lock);
+ need_reopen = 1;
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&lock);
+#else
+ __reopen();
+#endif
+}
+
+#ifdef THREADED_LOG_FILE
+static void *log_thread(void *ignored)
+{
+ struct log_msg *msg;
+ struct log_chunk *chunk;
+
+ pthread_mutex_lock(&lock);
+ while (1) {
+ if (need_reopen) {
+ need_reopen = 0;
+ __reopen();
+ }
+ while (!list_empty(&log_queue)) {
+ msg = list_entry(log_queue.next, typeof(*msg), entry);
+ list_move_tail(&msg->entry, &log_buf);
+
+ buf_cnt++;
+ buf_size += msg->hdr->len;
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ buf_size += chunk->len;
+ buf_cnt++;
+ }
+
+ if (buf_cnt > IOV_MAX - 16 || buf_size >= conf_buf_size) {
+ pthread_mutex_unlock(&lock);
+ write_buf();
+ pthread_mutex_lock(&lock);
+ }
+ }
+ pthread_cond_wait(&cond, &lock);
+ }
+ pthread_mutex_unlock(&lock);
+
+ return NULL;
+}
+#endif
+
+static struct log_target target = {
+ .log = do_log,
+ .reopen = reopen,
+};
+
+static void load_config()
+{
+ const char *opt = conf_get_opt("log", "buffer");
+ if (opt)
+ conf_buf_size = atoi(opt);
+ else
+ conf_buf_size = 0;
+}
+
+static void init(void)
+{
+ if (!conf_get_opt("log", "log-file"))
+ return;
+
+ load_config();
+
+ log_register_target(&target);
+ reopen();
+
+#ifdef THREADED_LOG_FILE
+ pthread_cond_init(&cond, NULL);
+ pthread_create(&thr, NULL, log_thread, NULL);
+#endif
+}
+
+DEFINE_INIT(2, init);