diff options
| author | Andrew Tridgell <tridge@samba.org> | 2008-01-16 22:03:01 +1100 |
|---|---|---|
| committer | Andrew Tridgell <tridge@samba.org> | 2008-01-16 22:03:01 +1100 |
| commit | b62b7fcde84c503e78e65bd4ecf3abc4781af2ec (patch) | |
| tree | dc9943459a8de7a8951099ffd1eb27b666ffd8a4 | |
| parent | 9f5ce343aaf817568cfe1a3b53bc6fae1e794b0d (diff) | |
added syslog support, and use a pipe to catch logging from child processes to the ctdbd logging functions
(This used to be ctdb commit 1306b04cd01e996fd1aa1159a9521f2ff7b06165)
| -rw-r--r-- | ctdb/Makefile.in | 2 | ||||
| -rw-r--r-- | ctdb/include/ctdb.h | 2 | ||||
| -rw-r--r-- | ctdb/include/ctdb_private.h | 2 | ||||
| -rw-r--r-- | ctdb/lib/util/debug.c | 6 | ||||
| -rw-r--r-- | ctdb/lib/util/debug.h | 2 | ||||
| -rw-r--r-- | ctdb/server/ctdb_daemon.c | 2 | ||||
| -rw-r--r-- | ctdb/server/ctdb_logging.c | 174 | ||||
| -rw-r--r-- | ctdb/server/ctdb_server.c | 26 | ||||
| -rw-r--r-- | ctdb/server/ctdbd.c | 15 | ||||
| -rwxr-xr-x | ctdb/tests/events.d/00.test | 19 |
10 files changed, 201 insertions, 49 deletions
diff --git a/ctdb/Makefile.in b/ctdb/Makefile.in index b28ab9cbab..8557b9c715 100644 --- a/ctdb/Makefile.in +++ b/ctdb/Makefile.in @@ -51,7 +51,7 @@ CTDB_SERVER_OBJ = server/ctdbd.o server/ctdb_daemon.o server/ctdb_lockwait.o \ server/ctdb_control.o server/ctdb_call.o server/ctdb_ltdb_server.o \ server/ctdb_traverse.o server/eventscript.o server/ctdb_takeover.o \ server/ctdb_serverids.o server/ctdb_persistent.o \ - server/ctdb_keepalive.o \ + server/ctdb_keepalive.o server/ctdb_logging.o \ $(CTDB_CLIENT_OBJ) $(CTDB_TCP_OBJ) @INFINIBAND_WRAPPER_OBJ@ TEST_BINS=bin/ctdb_bench bin/ctdb_fetch bin/ctdb_store bin/ctdb_randrec bin/ctdb_persistent bin/rb_test \ diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index f8d0db3d17..f734a52189 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -407,7 +407,7 @@ uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode); -int ctdb_set_logfile(struct ctdb_context *ctdb, const char *logfile); +int ctdb_set_logfile(struct ctdb_context *ctdb, const char *logfile, bool use_syslog); typedef int (*ctdb_traverse_func)(struct ctdb_context *, TDB_DATA, TDB_DATA, void *); int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data); diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 99d9d99b18..a7f17e6ac4 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -369,6 +369,7 @@ struct ctdb_context { bool done_startup; const char *node_ip; struct ctdb_monitor_state *monitor; + struct ctdb_log_state *log; }; struct ctdb_db_context { @@ -1213,5 +1214,6 @@ int32_t ctdb_control_delete_record(struct ctdb_context *ctdb, TDB_DATA indata); void ctdb_block_signal(int signum); void ctdb_unblock_signal(int signum); int32_t ctdb_monitoring_mode(struct ctdb_context *ctdb); +int ctdb_set_child_logging(struct ctdb_context *ctdb); #endif diff --git a/ctdb/lib/util/debug.c b/ctdb/lib/util/debug.c index c1f1c91410..341a4a1586 100644 --- a/ctdb/lib/util/debug.c +++ b/ctdb/lib/util/debug.c @@ -22,7 +22,7 @@ #include <unistd.h> -void do_debug_v(const char *format, va_list ap) +static void _do_debug_v(const char *format, va_list ap) { struct timeval t; char *s = NULL; @@ -41,6 +41,9 @@ void do_debug_v(const char *format, va_list ap) free(s); } +/* default logging function */ +void (*do_debug_v)(const char *, va_list ap) = _do_debug_v; + void do_debug(const char *format, ...) { va_list ap; @@ -49,3 +52,4 @@ void do_debug(const char *format, ...) do_debug_v(format, ap); va_end(ap); } + diff --git a/ctdb/lib/util/debug.h b/ctdb/lib/util/debug.h index ce454bc668..ae21e71909 100644 --- a/ctdb/lib/util/debug.h +++ b/ctdb/lib/util/debug.h @@ -17,5 +17,5 @@ along with this program; if not, see <http://www.gnu.org/licenses/>. */ -void do_debug_v(const char *format, va_list ap); +void (*do_debug_v)(const char *, va_list ap); void do_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); diff --git a/ctdb/server/ctdb_daemon.c b/ctdb/server/ctdb_daemon.c index bdd0fc86c4..137b85eee2 100644 --- a/ctdb/server/ctdb_daemon.c +++ b/ctdb/server/ctdb_daemon.c @@ -656,6 +656,8 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork) ctdb->ev = event_context_init(NULL); + ctdb_set_child_logging(ctdb); + /* force initial recovery for election */ ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE; diff --git a/ctdb/server/ctdb_logging.c b/ctdb/server/ctdb_logging.c new file mode 100644 index 0000000000..a2ff09caa2 --- /dev/null +++ b/ctdb/server/ctdb_logging.c @@ -0,0 +1,174 @@ +/* + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "../include/ctdb_private.h" +#include "system/syslog.h" +#include "system/time.h" +#include "system/filesys.h" + +struct ctdb_log_state { + char *logfile; + int fd, pfd; + char buf[1024]; + uint16_t buf_used; + bool use_syslog; +}; + +/* we need this global to eep the DEBUG() syntax */ +static struct ctdb_log_state *log_state; + +/* + syslog logging function + */ +static void ctdb_syslog_log(const char *format, va_list ap) +{ + vsyslog(LOG_NOTICE, format, ap); +} + + +/* + log file logging function + */ +static void ctdb_logfile_log(const char *format, va_list ap) +{ + struct timeval t; + char *s = NULL; + struct tm *tm; + char tbuf[100]; + + vasprintf(&s, format, ap); + + t = timeval_current(); + tm = localtime(&t.tv_sec); + + strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm); + + dprintf(log_state->fd, "%s.%06u [%5u]: %s", + tbuf, (unsigned)t.tv_usec, (unsigned)getpid(), s); + free(s); +} + +/* + choose the logfile location +*/ +int ctdb_set_logfile(struct ctdb_context *ctdb, const char *logfile, bool use_syslog) +{ + ctdb->log = talloc_zero(ctdb, struct ctdb_log_state); + + log_state = ctdb->log; + + if (use_syslog) { + do_debug_v = ctdb_syslog_log; + ctdb->log->use_syslog = true; + } else if (logfile == NULL || strcmp(logfile, "-") == 0) { + do_debug_v = ctdb_logfile_log; + ctdb->log->fd = 1; + /* also catch stderr of subcommands to stdout */ + dup2(1, 2); + } else { + do_debug_v = ctdb_logfile_log; + ctdb->log->logfile = talloc_strdup(ctdb, logfile); + + ctdb->log->fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666); + if (ctdb->log->fd == -1) { + printf("Failed to open logfile %s\n", ctdb->logfile); + abort(); + } + } + + return 0; +} + + + +/* + called when log data comes in from a child process + */ +static void ctdb_log_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *private) +{ + struct ctdb_context *ctdb = talloc_get_type(private, struct ctdb_context); + ssize_t n; + char *p; + + if (!(flags & EVENT_FD_READ)) { + return; + } + + n = read(ctdb->log->pfd, &ctdb->log->buf[ctdb->log->buf_used], + sizeof(ctdb->log->buf) - ctdb->log->buf_used); + if (n > 0) { + ctdb->log->buf_used += n; + } + + if (ctdb->log->buf_used == sizeof(ctdb->log->buf)) { + do_debug("%*.*s\n", ctdb->log->buf_used, ctdb->log->buf_used, ctdb->log->buf); + ctdb->log->buf_used = 0; + return; + } + + p = memchr(ctdb->log->buf, '\n', ctdb->log->buf_used); + if (!p) { + return; + } + + n = (p - ctdb->log->buf)+1; + do_debug("%*.*s", n, n, ctdb->log->buf); + memmove(ctdb->log->buf, ctdb->log->buf+n, sizeof(ctdb->log->buf) - n); + ctdb->log->buf_used -= n; +} + + + +/* + setup for logging of child process stdout +*/ +int ctdb_set_child_logging(struct ctdb_context *ctdb) +{ + int p[2]; + + if (ctdb->log->fd == 1) { + /* not needed for stdout logging */ + return 0; + } + + /* setup a pipe to catch IO from subprocesses */ + if (pipe(p) != 0) { + DEBUG(0,(__location__ " Failed to setup for child logging pipe\n")); + return -1; + } + + event_add_fd(ctdb->ev, ctdb, p[0], EVENT_FD_READ, + ctdb_log_handler, ctdb); + set_close_on_exec(p[0]); + ctdb->log->pfd = p[0]; + + close(1); + close(2); + if (p[1] != 1) { + dup2(p[1], 1); + close(p[1]); + } + /* also catch stderr of subcommands to the log */ + dup2(1, 2); + + return 0; +} diff --git a/ctdb/server/ctdb_server.c b/ctdb/server/ctdb_server.c index 2a80798dd9..1bf6e5e515 100644 --- a/ctdb/server/ctdb_server.c +++ b/ctdb/server/ctdb_server.c @@ -61,32 +61,6 @@ int ctdb_set_recovery_lock_file(struct ctdb_context *ctdb, const char *file) } /* - choose the logfile location -*/ -int ctdb_set_logfile(struct ctdb_context *ctdb, const char *logfile) -{ - ctdb->logfile = talloc_strdup(ctdb, logfile); - if (ctdb->logfile != NULL && strcmp(logfile, "-") != 0) { - int fd; - fd = open(ctdb->logfile, O_WRONLY|O_APPEND|O_CREAT, 0666); - if (fd == -1) { - printf("Failed to open logfile %s\n", ctdb->logfile); - abort(); - } - close(1); - close(2); - if (fd != 1) { - dup2(fd, 1); - close(fd); - } - /* also catch stderr of subcommands to the log file */ - dup2(1, 2); - } - return 0; -} - - -/* set the directory for the local databases */ int ctdb_set_tdb_dir(struct ctdb_context *ctdb, const char *dir) diff --git a/ctdb/server/ctdbd.c b/ctdb/server/ctdbd.c index a28d5e661b..afa2c83e53 100644 --- a/ctdb/server/ctdbd.c +++ b/ctdb/server/ctdbd.c @@ -40,6 +40,7 @@ static struct { const char *single_public_ip; const char *node_ip; int no_setsched; + int use_syslog; } options = { .nlist = ETCDIR "/ctdb/nodes", .transport = "tcp", @@ -106,6 +107,7 @@ int main(int argc, const char *argv[]) { "dbdir-persistent", 0, POPT_ARG_STRING, &options.db_dir_persistent, 0, "directory for persistent tdb files", NULL }, { "reclock", 0, POPT_ARG_STRING, &options.recovery_lock_file, 0, "location of recovery lock file", "filename" }, { "nosetsched", 0, POPT_ARG_NONE, &options.no_setsched, 0, "disable setscheduler SCHED_FIFO call", NULL }, + { "syslog", 0, POPT_ARG_NONE, &options.use_syslog, 0, "log messages to syslog", NULL }, POPT_TABLEEND }; int opt, ret; @@ -145,9 +147,10 @@ int main(int argc, const char *argv[]) ctdb = ctdb_cmdline_init(ev); - ret = ctdb_set_logfile(ctdb, options.logfile); + ret = ctdb_set_logfile(ctdb, options.logfile, options.use_syslog); if (ret == -1) { - printf("ctdb_set_logfile to %s failed - %s\n", options.logfile, ctdb_errstr(ctdb)); + printf("ctdb_set_logfile to %s failed - %s\n", + options.use_syslog?"syslog":options.logfile, ctdb_errstr(ctdb)); exit(1); } @@ -261,14 +264,6 @@ int main(int argc, const char *argv[]) exit(1); } - /* useful default logfile */ - if (ctdb->logfile == NULL) { - char *name = talloc_asprintf(ctdb, "%s/log.ctdb.pnn%u", - VARDIR, ctdb->pnn); - ctdb_set_logfile(ctdb, name); - talloc_free(name); - } - ctdb->do_setsched = !options.no_setsched; /* setup a environment variable for the event scripts to use to find the diff --git a/ctdb/tests/events.d/00.test b/ctdb/tests/events.d/00.test index fb319bc426..026cf6cba7 100755 --- a/ctdb/tests/events.d/00.test +++ b/ctdb/tests/events.d/00.test @@ -6,11 +6,12 @@ shift case $cmd in monitor) - echo "`date` monitor event" + echo "monitor event" + echo "monitor event stderr" >&2 exit 0 ;; startup) - echo "`date` ctdb startup event" + echo "ctdb startup event" exit 0; ;; @@ -25,7 +26,7 @@ case $cmd in [ `id -u` = 0 ] && { /sbin/ip addr add $ip/$maskbits dev $iface || { - echo "`/bin/date` Failed to add $ip/$maskbits on dev $iface" + echo "Failed to add $ip/$maskbits on dev $iface" exit 1 } } @@ -37,7 +38,7 @@ case $cmd in # called when ctdbd wants to release an IP address releaseip) if [ $# != 3 ]; then - echo "`/bin/date` must supply interface, IP and maskbits" + echo "must supply interface, IP and maskbits" exit 1 fi iface=$1 @@ -45,24 +46,24 @@ case $cmd in maskbits=$3 [ `id -u` = 0 ] && { /sbin/ip addr del $ip/$maskbits dev $iface || { - echo "`/bin/date` Failed to del $ip on dev $iface" + echo "Failed to del $ip on dev $iface" exit 1 } } - echo "`date` ctdb takeip event for $1 $2 $3" + echo "ctdb takeip event for $1 $2 $3" exit 0 ;; recovered) - echo "`date` ctdb recovered event" + echo "ctdb recovered event" exit 0 ;; shutdown) - echo "`date` ctdb shutdown event" + echo "ctdb shutdown event" exit 0 ;; esac -echo "`/bin/date` Invalid command $cmd" +echo "Invalid command $cmd" exit 1 |
