diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-05-18 02:04:21 +0000 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-05-18 02:15:30 +0000 |
commit | 6147e4dcef23570b025813f1afe481c34ce07ccc (patch) | |
tree | 81e13c3cb8536dda7e0e864a8d79d49d859c22d4 /accel-pppd | |
parent | a833b45f18f8213bc88ff6d1c72154ec9c13ad4d (diff) | |
download | accel-ppp-6147e4dcef23570b025813f1afe481c34ce07ccc.tar.gz accel-ppp-6147e4dcef23570b025813f1afe481c34ce07ccc.zip |
log_file: rewrited file write procedure
Use separated thread to write messages to file instead of async io.
On mips platform async io does not work properly by some reason and may stuck logging
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/logs/log_file.c | 272 |
1 files changed, 99 insertions, 173 deletions
diff --git a/accel-pppd/logs/log_file.c b/accel-pppd/logs/log_file.c index 3a618237..cc8c1bc4 100644 --- a/accel-pppd/logs/log_file.c +++ b/accel-pppd/logs/log_file.c @@ -9,6 +9,7 @@ #include <signal.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/uio.h> #include "log.h" #include "events.h" @@ -26,8 +27,7 @@ #define BLUE_COLOR "\033[1;34m" #define NORMAL_COLOR "\033[0;39m" -struct log_file_t -{ +struct log_file_t { struct list_head entry; struct list_head msgs; spinlock_t lock; @@ -37,30 +37,26 @@ struct log_file_t int fd; int new_fd; - off_t offset; - unsigned long magic; }; -struct log_file_pd_t -{ +struct log_file_pd_t { struct ap_private pd; struct log_file_t lf; unsigned long tmp; }; -struct fail_log_pd_t -{ +struct fail_log_pd_t { struct ap_private pd; struct list_head msgs; }; - static int conf_color; static int conf_per_session; static char *conf_per_user_dir; static char *conf_per_session_dir; static int conf_copy; static int conf_fail_log; +static pthread_t log_thr; static const char* level_name[]={" msg", "error", " warn", " info", " info", "debug"}; static const char* level_color[]={NORMAL_COLOR, RED_COLOR, YELLOW_COLOR, GREEN_COLOR, GREEN_COLOR, BLUE_COLOR}; @@ -74,23 +70,13 @@ static struct log_file_t *fail_log_file; static mempool_t lpd_pool; static mempool_t fpd_pool; -static char *log_buf; - -static struct aiocb aiocb = { - .aio_lio_opcode = LIO_WRITE, - .aio_sigevent.sigev_notify = SIGEV_SIGNAL, - .aio_sigevent.sigev_signo = SIGIO, -}; static LIST_HEAD(lf_queue); -static spinlock_t lf_queue_lock = SPINLOCK_INITIALIZER; -static int lf_queue_sleeping = 1; +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static unsigned long temp_seq; -static void send_next_chunk(); - - static void log_file_init(struct log_file_t *lf) { spinlock_init(&lf->lock); @@ -101,147 +87,84 @@ static void log_file_init(struct log_file_t *lf) static int log_file_open(struct log_file_t *lf, const char *fname) { - lf->fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + lf->fd = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, S_IRUSR | S_IWUSR); if (lf->fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return -1; } - fcntl(lf->fd, F_SETFD, fcntl(lf->fd, F_GETFD) | FD_CLOEXEC); - - lf->offset = lseek(lf->fd, 0, SEEK_END); - return 0; } -static void sigio(int num, siginfo_t *si, void *uc) +static void *log_thread(void *unused) { struct log_file_t *lf; - int n; - - if (si->si_signo != SIGIO) - return; - - if (si->si_code != SI_ASYNCIO) { - if (aio_write(&aiocb)) - log_emerg("log_file: aio_write: %s\n", strerror(errno)); - return; - } - - lf = (struct log_file_t *)si->si_ptr; - - n = aio_return(&aiocb); - if (n < 0) - log_emerg("log_file: %s\n", strerror(aio_error(&aiocb))); - else if (n != aiocb.aio_nbytes) - log_emerg("log_file: short write %p %i %lu\n", lf, n, aiocb.aio_nbytes); - - spin_lock(&lf->lock); - lf->offset += n; - if (list_empty(&lf->msgs)) { - if (lf->need_free) { - spin_unlock(&lf->lock); - close(lf->fd); - mempool_free(lf->lpd); - } else { - lf->queued = 0; - spin_unlock(&lf->lock); - } - } else { - spin_unlock(&lf->lock); - - spin_lock(&lf_queue_lock); - list_add_tail(&lf->entry, &lf_queue); - spin_unlock(&lf_queue_lock); - } - - send_next_chunk(); -} - -static int dequeue_log(struct log_file_t *lf) -{ - int n, pos = 0; - struct log_msg_t *msg; + struct iovec iov[IOV_MAX]; struct log_chunk_t *chunk; + struct log_msg_t *msg; + int iov_cnt = 0; while (1) { - spin_lock(&lf->lock); - if (list_empty(&lf->msgs)) { + pthread_mutex_lock(&lock); + if (list_empty(&lf_queue)) + pthread_cond_wait(&cond, &lock); + lf = list_first_entry(&lf_queue, typeof(*lf), entry); + list_del(&lf->entry); + pthread_mutex_unlock(&lock); + + iov_cnt = 0; + + while (1) { + spin_lock(&lf->lock); + if (list_empty(&lf->msgs)) { + lf->queued = 0; + if (lf->need_free) { + spin_unlock(&lf->lock); + close(lf->fd); + if (lf->new_fd != -1) + close(lf->new_fd); + mempool_free(lf->lpd); + } else { + spin_unlock(&lf->lock); + + if (iov_cnt) + writev(lf->fd, iov, iov_cnt); + + if (lf->new_fd != -1) { + close(lf->fd); + lf->fd = lf->new_fd; + lf->new_fd = -1; + } + } + break; + } + + msg = list_first_entry(&lf->msgs, typeof(*msg), entry); + list_del(&msg->entry); spin_unlock(&lf->lock); - return pos; - } - msg = list_entry(lf->msgs.next, typeof(*msg), entry); - list_del(&msg->entry); - spin_unlock(&lf->lock); - - if (pos + msg->hdr->len > LOG_BUF_SIZE) - goto overrun; - memcpy(log_buf + pos, msg->hdr->msg, msg->hdr->len); - n = msg->hdr->len; - - list_for_each_entry(chunk, msg->chunks, entry) { - if (pos + n + chunk->len > LOG_BUF_SIZE) - goto overrun; - memcpy(log_buf + pos + n, chunk->msg, chunk->len); - n += chunk->len; - } - - log_free_msg(msg); - pos += n; - } - -overrun: - spin_lock(&lf->lock); - list_add(&msg->entry, &lf->msgs); - spin_unlock(&lf->lock); - - return pos; -} - -static void send_next_chunk(void) -{ - struct log_file_t *lf; - spin_lock(&lf_queue_lock); - if (list_empty(&lf_queue)) { - lf_queue_sleeping = 1; - spin_unlock(&lf_queue_lock); - return; - } - lf = list_entry(lf_queue.next, typeof(*lf), entry); - - list_del(&lf->entry); - - spin_unlock(&lf_queue_lock); - - if (lf->new_fd != -1) { - close(lf->fd); - lf->fd = lf->new_fd; - lf->new_fd = -1; - lf->offset = 0; + list_for_each_entry(chunk, msg->chunks, entry) { + iov[iov_cnt].iov_base = chunk->msg; + iov[iov_cnt].iov_len = chunk->len; + if (++iov_cnt == IOV_MAX) { + writev(lf->fd, iov, iov_cnt); + iov_cnt = 0; + } + } + + log_free_msg(msg); + } } - aiocb.aio_fildes = lf->fd; - aiocb.aio_offset = lf->offset; - aiocb.aio_sigevent.sigev_value.sival_ptr = lf; - aiocb.aio_nbytes = dequeue_log(lf); - - if (aio_write(&aiocb)) - log_emerg("log_file: aio_write: %s\n", strerror(errno)); + return NULL; } static void queue_lf(struct log_file_t *lf) { - int r; - - spin_lock(&lf_queue_lock); + pthread_mutex_lock(&lock); list_add_tail(&lf->entry, &lf_queue); - r = lf_queue_sleeping; - lf_queue_sleeping = 0; - spin_unlock(&lf_queue_lock); - - if (r) - send_next_chunk(); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&lock); } static void queue_log(struct log_file_t *lf, struct log_msg_t *msg) @@ -264,14 +187,9 @@ static void queue_log(struct log_file_t *lf, struct log_msg_t *msg) static void queue_log_list(struct log_file_t *lf, struct list_head *l) { int r; - struct log_msg_t *msg; spin_lock(&lf->lock); - while (!list_empty(l)) { - msg = list_entry(l->next, typeof(*msg), entry); - list_del(&msg->entry); - list_add_tail(&msg->entry, &lf->msgs); - } + list_splice_init(l, &lf->msgs); if (lf->fd != -1) { r = lf->queued; lf->queued = 1; @@ -407,27 +325,48 @@ static void fail_log(struct log_target_t *t, struct log_msg_t *msg, struct ap_se static void fail_reopen(void) { - char *fname = conf_get_opt("log", "log-fail-file"); - int fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + const char *fname = conf_get_opt("log", "log-fail-file"); + int old_fd = -1; + int fd = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return; } - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - fail_log_file->new_fd = fd; -} + + spin_lock(&fail_log_file->lock); + if (fail_log_file->queued) + fail_log_file->new_fd = fd; + else { + old_fd = fail_log_file->fd; + fail_log_file->fd = fd; + } + spin_unlock(&fail_log_file->lock); + if (old_fd != -1) + close(old_fd); +} static void general_reopen(void) { - char *fname = conf_get_opt("log", "log-file"); - int fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + const char *fname = conf_get_opt("log", "log-file"); + int old_fd = -1; + int fd = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return; } - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - log_file->new_fd = fd; + + spin_lock(&log_file->lock); + if (log_file->queued) + log_file->new_fd = fd; + else { + old_fd = log_file->fd; + log_file->fd = fd; + } + spin_unlock(&log_file->lock); + + if (old_fd != -1) + close(old_fd); } static void free_lpd(struct log_file_pd_t *lpd) @@ -447,6 +386,8 @@ static void free_lpd(struct log_file_pd_t *lpd) } if (lpd->lf.fd != -1) close(lpd->lf.fd); + if (lpd->lf.new_fd != -1) + close(lpd->lf.fd); spin_unlock(&lpd->lf.lock); mempool_free(lpd); } @@ -682,27 +623,12 @@ static struct log_target_t fail_log_target = static void init(void) { - char *opt; - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGIO); - - struct sigaction sa = { - .sa_sigaction = sigio, - .sa_flags = SA_SIGINFO, - .sa_mask = set, - }; + const char *opt; + pthread_create(&log_thr, NULL, log_thread, NULL); + lpd_pool = mempool_create(sizeof(struct log_file_pd_t)); fpd_pool = mempool_create(sizeof(struct fail_log_pd_t)); - log_buf = malloc(LOG_BUF_SIZE); - aiocb.aio_buf = log_buf; - - if (sigaction(SIGIO, &sa, NULL)) { - log_emerg("log_file: sigaction: %s\n", strerror(errno)); - return; - } opt = conf_get_opt("log", "log-file"); if (opt) { |