From 739324eead1d8ece13151504c0a54ab5c82e51db Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Fri, 8 Aug 2014 20:54:54 +1000 Subject: ctdb-logging: Separate out syslog and file logging backends This makes the code cleaner and allows the syslog backend to be easily modified without affecting other code. Also do some extra clean-up, including whitespace fixups. Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs --- ctdb/server/ctdb_logging.c | 297 ++------------------------------------ ctdb/server/ctdb_logging_file.c | 98 +++++++++++++ ctdb/server/ctdb_logging_syslog.c | 267 ++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+), 285 deletions(-) create mode 100644 ctdb/server/ctdb_logging_file.c create mode 100644 ctdb/server/ctdb_logging_syslog.c (limited to 'ctdb/server') diff --git a/ctdb/server/ctdb_logging.c b/ctdb/server/ctdb_logging.c index d7e10ee415..bc47dd273f 100644 --- a/ctdb/server/ctdb_logging.c +++ b/ctdb/server/ctdb_logging.c @@ -1,4 +1,4 @@ -/* +/* ctdb logging code Copyright (C) Andrew Tridgell 2008 @@ -7,12 +7,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, see . */ @@ -25,179 +25,11 @@ #include "system/filesys.h" #include "lib/util/debug.h" -struct syslog_message { - uint32_t level; - uint32_t len; - char message[1]; -}; - - -struct ctdb_syslog_state { - int syslog_fd; - int fd[2]; -}; - -static int syslogd_is_started = 0; - -/* called when child is finished - * this is for the syslog daemon, we can not use DEBUG here - */ -static void ctdb_syslog_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *p) -{ - struct ctdb_syslog_state *state = talloc_get_type(p, struct ctdb_syslog_state); - - int count; - char str[65536]; - struct syslog_message *msg; - - if (state == NULL) { - return; - } - - count = recv(state->syslog_fd, str, sizeof(str), 0); - if (count < sizeof(struct syslog_message)) { - return; - } - msg = (struct syslog_message *)str; - if (msg->len >= (sizeof(str) - offsetof(struct syslog_message, message))) { - msg->len = (sizeof(str)-1) - offsetof(struct syslog_message, message); - } - msg->message[msg->len] = '\0'; - - syslog(msg->level, "%s", msg->message); -} - - -/* called when the pipe from the main daemon has closed - * this is for the syslog daemon, we can not use DEBUG here - */ -static void ctdb_syslog_terminate_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *p) -{ - syslog(LOG_ERR, "Shutting down SYSLOG daemon with pid:%d", (int)getpid()); - _exit(0); -} - - - -/* - * this is for the syslog daemon, we can not use DEBUG here - */ -int start_syslog_daemon(struct ctdb_context *ctdb) -{ - struct sockaddr_in syslog_sin; - struct ctdb_syslog_state *state; - struct tevent_fd *fde; - int startup_fd[2]; - int ret = -1; - - state = talloc(ctdb, struct ctdb_syslog_state); - CTDB_NO_MEMORY(ctdb, state); - - if (pipe(state->fd) != 0) { - printf("Failed to create syslog pipe\n"); - talloc_free(state); - return -1; - } - - if (pipe(startup_fd) != 0) { - printf("Failed to create syslog startup pipe\n"); - close(state->fd[0]); - close(state->fd[1]); - talloc_free(state); - return -1; - } - - ctdb->syslogd_pid = ctdb_fork(ctdb); - if (ctdb->syslogd_pid == (pid_t)-1) { - printf("Failed to create syslog child process\n"); - close(state->fd[0]); - close(state->fd[1]); - close(startup_fd[0]); - close(startup_fd[1]); - talloc_free(state); - return -1; - } - - if (ctdb->syslogd_pid != 0) { - ssize_t n; - int dummy; - - DEBUG(DEBUG_ERR,("Starting SYSLOG child process with pid:%d\n", (int)ctdb->syslogd_pid)); - - close(state->fd[1]); - set_close_on_exec(state->fd[0]); - - close(startup_fd[1]); - n = sys_read(startup_fd[0], &dummy, sizeof(dummy)); - close(startup_fd[0]); - if (n < sizeof(dummy)) { - return -1; - } - - syslogd_is_started = 1; - return 0; - } - - debug_extra = talloc_asprintf(NULL, "syslogd:"); - talloc_free(ctdb->ev); - ctdb->ev = event_context_init(NULL); - - syslog(LOG_ERR, "Starting SYSLOG daemon with pid:%d", (int)getpid()); - ctdb_set_process_name("ctdb_syslogd"); - - close(state->fd[0]); - close(startup_fd[0]); - set_close_on_exec(state->fd[1]); - set_close_on_exec(startup_fd[1]); - fde = event_add_fd(ctdb->ev, state, state->fd[1], EVENT_FD_READ, - ctdb_syslog_terminate_handler, state); - tevent_fd_set_auto_close(fde); - - state->syslog_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (state->syslog_fd == -1) { - printf("Failed to create syslog socket\n"); - close(startup_fd[1]); - return ret; - } - - set_close_on_exec(state->syslog_fd); - - syslog_sin.sin_family = AF_INET; - syslog_sin.sin_port = htons(CTDB_PORT); - syslog_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (bind(state->syslog_fd, (struct sockaddr *)&syslog_sin, - sizeof(syslog_sin)) == -1) - { - printf("syslog daemon failed to bind to socket. errno:%d(%s)\n", errno, strerror(errno)); - close(startup_fd[1]); - _exit(10); - } - - - fde = event_add_fd(ctdb->ev, state, state->syslog_fd, EVENT_FD_READ, - ctdb_syslog_handler, state); - tevent_fd_set_auto_close(fde); - - /* Tell parent that we're up */ - ret = 0; - sys_write(startup_fd[1], &ret, sizeof(ret)); - close(startup_fd[1]); - - event_loop_wait(ctdb->ev); - - /* this should not happen */ - _exit(10); -} - struct ctdb_log_state { const char *prefix; int fd, pfd; char buf[1024]; uint16_t buf_used; - bool use_syslog; void (*logfn)(const char *, uint16_t, void *); void *logfn_private; }; @@ -205,107 +37,11 @@ struct ctdb_log_state { /* we need this global to keep the DEBUG() syntax */ static struct ctdb_log_state *log_state; -/* - syslog logging function - */ -static void ctdb_syslog_log(void *private_ptr, int dbglevel, const char *s) -{ - struct syslog_message *msg; - int level = LOG_DEBUG; - int len; - int syslog_fd; - struct sockaddr_in syslog_sin; - - switch (dbglevel) { - case DEBUG_ERR: - level = LOG_ERR; - break; - case DEBUG_WARNING: - level = LOG_WARNING; - break; - case DEBUG_NOTICE: - level = LOG_NOTICE; - break; - case DEBUG_INFO: - level = LOG_INFO; - break; - default: - level = LOG_DEBUG; - break; - } - - len = offsetof(struct syslog_message, message) + strlen(debug_extra) + strlen(s) + 1; - msg = malloc(len); - if (msg == NULL) { - return; - } - msg->level = level; - msg->len = strlen(debug_extra) + strlen(s); - strcpy(msg->message, debug_extra); - strcat(msg->message, s); - - if (syslogd_is_started == 0) { - syslog(msg->level, "%s", msg->message); - } else { - syslog_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (syslog_fd == -1) { - printf("Failed to create syslog socket\n"); - free(msg); - return; - } - - syslog_sin.sin_family = AF_INET; - syslog_sin.sin_port = htons(CTDB_PORT); - syslog_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - (void) sendto(syslog_fd, msg, len, 0, - (struct sockaddr *)&syslog_sin, - sizeof(syslog_sin)); - /* no point in checking here since we cant log an error */ - - close(syslog_fd); - } - - free(msg); -} - - -/* - log file logging function - */ -static void ctdb_logfile_log(void *private_ptr, int dbglevel, const char *s) -{ - struct timeval t; - struct tm *tm; - char tbuf[100]; - char *s2 = NULL; - int ret; - - t = timeval_current(); - tm = localtime(&t.tv_sec); - - strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm); - - ret = asprintf(&s2, "%s.%06u [%s%5u]: %s\n", - tbuf, (unsigned)t.tv_usec, - debug_extra, (unsigned)getpid(), s); - if (ret == -1) { - const char *errstr = "asprintf failed\n"; - sys_write(log_state->fd, errstr, strlen(errstr)); - return; - } - if (s2) { - sys_write(log_state->fd, s2, strlen(s2)); - free(s2); - } -} - /* choose the logfile location */ int ctdb_set_logfile(TALLOC_CTX *mem_ctx, const char *logfile, bool use_syslog) { - debug_callback_fn callback; int ret; log_state = talloc_zero(mem_ctx, struct ctdb_log_state); @@ -315,29 +51,20 @@ int ctdb_set_logfile(TALLOC_CTX *mem_ctx, const char *logfile, bool use_syslog) } if (use_syslog) { - callback = ctdb_syslog_log; - log_state->use_syslog = true; - } else if (logfile == NULL || strcmp(logfile, "-") == 0) { - callback = ctdb_logfile_log; - log_state->fd = 1; - /* also catch stderr of subcommands to stdout */ - ret = dup2(1, 2); - if (ret == -1) { - printf("dup2 failed: %s\n", strerror(errno)); + ret = ctdb_log_setup_syslog(); + if (ret != 0) { + printf("Setup of syslog logging failed with \"%s\"\n", + strerror(ret)); abort(); } } else { - callback = ctdb_logfile_log; - - log_state->fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666); - if (log_state->fd == -1) { - printf("Failed to open logfile %s\n", logfile); + ret = ctdb_log_setup_file(mem_ctx, logfile); + if (ret != 0) { + printf("Setup of file logging failed with \"%s\"\n", + strerror(ret)); abort(); } } - - debug_set_callback(NULL, callback); - return 0; } @@ -584,6 +311,6 @@ int ctdb_init_tevent_logging(struct ctdb_context *ctdb) ret = tevent_set_debug(ctdb->ev, ctdb_tevent_logging, - ctdb); + ctdb); return ret; } diff --git a/ctdb/server/ctdb_logging_file.c b/ctdb/server/ctdb_logging_file.c new file mode 100644 index 0000000000..09367f3488 --- /dev/null +++ b/ctdb/server/ctdb_logging_file.c @@ -0,0 +1,98 @@ +/* + ctdb logging code + + Copyright (C) Andrew Tridgell 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include "includes.h" +#include "../include/ctdb_client.h" +#include "../include/ctdb_private.h" +#include "system/time.h" +#include "system/filesys.h" + +struct file_state { + int fd; +}; + +/* + log file logging function + */ +static void ctdb_log_to_file(void *private_ptr, int dbglevel, const char *s) +{ + struct file_state *state = talloc_get_type( + private_ptr, struct file_state); + struct timeval t; + struct tm *tm; + char tbuf[100]; + char *s2 = NULL; + int ret; + + t = timeval_current(); + tm = localtime(&t.tv_sec); + + strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm); + + ret = asprintf(&s2, "%s.%06u [%s%5u]: %s\n", + tbuf, (unsigned)t.tv_usec, + debug_extra, (unsigned)getpid(), s); + if (ret == -1) { + const char *errstr = "asprintf failed\n"; + sys_write(state->fd, errstr, strlen(errstr)); + return; + } + if (s2) { + sys_write(state->fd, s2, strlen(s2)); + free(s2); + } +} + +static int file_state_destructor(struct file_state *state) +{ + close(state->fd); + state->fd = -1; + return 0; +} + +int ctdb_log_setup_file(TALLOC_CTX *mem_ctx, const char *logfile) +{ + struct file_state *state; + + state = talloc_zero(mem_ctx, struct file_state); + if (state == NULL) { + return ENOMEM; + } + + if (logfile == NULL || strcmp(logfile, "-") == 0) { + int ret; + + state->fd = 1; + /* also catch stderr of subcommands to stdout */ + ret = dup2(1, 2); + if (ret == -1) { + return errno; + } + } else { + state->fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666); + if (state->fd == -1) { + return errno; + } + } + + talloc_set_destructor(state, file_state_destructor); + debug_set_callback(state, ctdb_log_to_file); + + return 0; +} diff --git a/ctdb/server/ctdb_logging_syslog.c b/ctdb/server/ctdb_logging_syslog.c new file mode 100644 index 0000000000..b2cb261c47 --- /dev/null +++ b/ctdb/server/ctdb_logging_syslog.c @@ -0,0 +1,267 @@ +/* + ctdb logging code - syslog backend + + Copyright (C) Andrew Tridgell 2008 + Copyright (C) Ronnie Sahlberg 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include "includes.h" +#include "../include/ctdb_client.h" +#include "../include/ctdb_private.h" +#include "system/syslog.h" + +struct syslog_message { + uint32_t level; + uint32_t len; + char message[1]; +}; + + +struct ctdb_syslog_state { + int syslog_fd; + int fd[2]; +}; + +static int syslogd_is_started = 0; + +static int ctdb_debug_to_syslog_level(int dbglevel) +{ + int level; + + switch (dbglevel) { + case DEBUG_ERR: + level = LOG_ERR; + break; + case DEBUG_WARNING: + level = LOG_WARNING; + break; + case DEBUG_NOTICE: + level = LOG_NOTICE; + break; + case DEBUG_INFO: + level = LOG_INFO; + break; + default: + level = LOG_DEBUG; + break; + } + + return level; +} + +/* called when child is finished + * this is for the syslog daemon, we can not use DEBUG here + */ +static void ctdb_syslog_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *p) +{ + struct ctdb_syslog_state *state = talloc_get_type(p, struct ctdb_syslog_state); + + int count; + char str[65536]; + struct syslog_message *msg; + + if (state == NULL) { + return; + } + + count = recv(state->syslog_fd, str, sizeof(str), 0); + if (count < sizeof(struct syslog_message)) { + return; + } + msg = (struct syslog_message *)str; + if (msg->len >= (sizeof(str) - offsetof(struct syslog_message, message))) { + msg->len = (sizeof(str)-1) - offsetof(struct syslog_message, message); + } + msg->message[msg->len] = '\0'; + + syslog(msg->level, "%s", msg->message); +} + + +/* called when the pipe from the main daemon has closed + * this is for the syslog daemon, we can not use DEBUG here + */ +static void ctdb_syslog_terminate_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *p) +{ + syslog(LOG_ERR, "Shutting down SYSLOG daemon with pid:%d", (int)getpid()); + _exit(0); +} + + + +/* + * this is for the syslog daemon, we can not use DEBUG here + */ +int start_syslog_daemon(struct ctdb_context *ctdb) +{ + struct sockaddr_in syslog_sin; + struct ctdb_syslog_state *state; + struct tevent_fd *fde; + int startup_fd[2]; + int ret = -1; + + state = talloc(ctdb, struct ctdb_syslog_state); + CTDB_NO_MEMORY(ctdb, state); + + if (pipe(state->fd) != 0) { + printf("Failed to create syslog pipe\n"); + talloc_free(state); + return -1; + } + + if (pipe(startup_fd) != 0) { + printf("Failed to create syslog startup pipe\n"); + close(state->fd[0]); + close(state->fd[1]); + talloc_free(state); + return -1; + } + + ctdb->syslogd_pid = ctdb_fork(ctdb); + if (ctdb->syslogd_pid == (pid_t)-1) { + printf("Failed to create syslog child process\n"); + close(state->fd[0]); + close(state->fd[1]); + close(startup_fd[0]); + close(startup_fd[1]); + talloc_free(state); + return -1; + } + + if (ctdb->syslogd_pid != 0) { + ssize_t n; + int dummy; + + DEBUG(DEBUG_ERR,("Starting SYSLOG child process with pid:%d\n", (int)ctdb->syslogd_pid)); + + close(state->fd[1]); + set_close_on_exec(state->fd[0]); + + close(startup_fd[1]); + n = sys_read(startup_fd[0], &dummy, sizeof(dummy)); + close(startup_fd[0]); + if (n < sizeof(dummy)) { + return -1; + } + + syslogd_is_started = 1; + return 0; + } + + debug_extra = talloc_asprintf(NULL, "syslogd:"); + talloc_free(ctdb->ev); + ctdb->ev = event_context_init(NULL); + + syslog(LOG_ERR, "Starting SYSLOG daemon with pid:%d", (int)getpid()); + ctdb_set_process_name("ctdb_syslogd"); + + close(state->fd[0]); + close(startup_fd[0]); + set_close_on_exec(state->fd[1]); + set_close_on_exec(startup_fd[1]); + fde = event_add_fd(ctdb->ev, state, state->fd[1], EVENT_FD_READ, + ctdb_syslog_terminate_handler, state); + tevent_fd_set_auto_close(fde); + + state->syslog_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (state->syslog_fd == -1) { + printf("Failed to create syslog socket\n"); + close(startup_fd[1]); + return ret; + } + + set_close_on_exec(state->syslog_fd); + + syslog_sin.sin_family = AF_INET; + syslog_sin.sin_port = htons(CTDB_PORT); + syslog_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (bind(state->syslog_fd, (struct sockaddr *)&syslog_sin, + sizeof(syslog_sin)) == -1) + { + printf("syslog daemon failed to bind to socket. errno:%d(%s)\n", errno, strerror(errno)); + close(startup_fd[1]); + _exit(10); + } + + + fde = event_add_fd(ctdb->ev, state, state->syslog_fd, EVENT_FD_READ, + ctdb_syslog_handler, state); + tevent_fd_set_auto_close(fde); + + /* Tell parent that we're up */ + ret = 0; + sys_write(startup_fd[1], &ret, sizeof(ret)); + close(startup_fd[1]); + + event_loop_wait(ctdb->ev); + + /* this should not happen */ + _exit(10); +} + +/* + syslog logging function + */ +static void ctdb_log_to_syslog(void *private_ptr, int dbglevel, const char *s) +{ + struct syslog_message *msg; + int len; + int syslog_fd; + struct sockaddr_in syslog_sin; + + len = offsetof(struct syslog_message, message) + strlen(debug_extra) + strlen(s) + 1; + msg = malloc(len); + if (msg == NULL) { + return; + } + msg->level = ctdb_debug_to_syslog_level(dbglevel); + msg->len = strlen(debug_extra) + strlen(s); + strcpy(msg->message, debug_extra); + strcat(msg->message, s); + + if (syslogd_is_started == 0) { + syslog(msg->level, "%s", msg->message); + } else { + syslog_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (syslog_fd == -1) { + printf("Failed to create syslog socket\n"); + free(msg); + return; + } + + syslog_sin.sin_family = AF_INET; + syslog_sin.sin_port = htons(CTDB_PORT); + syslog_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + (void) sendto(syslog_fd, msg, len, 0, + (struct sockaddr *)&syslog_sin, + sizeof(syslog_sin)); + /* no point in checking here since we cant log an error */ + + close(syslog_fd); + } + + free(msg); +} + +int ctdb_log_setup_syslog(void) +{ + debug_set_callback(NULL, ctdb_log_to_syslog); + return 0; +} -- cgit