added syslog support, and use a pipe to catch logging from child processes to the...
authorAndrew Tridgell <tridge@samba.org>
Wed, 16 Jan 2008 11:03:01 +0000 (22:03 +1100)
committerAndrew Tridgell <tridge@samba.org>
Wed, 16 Jan 2008 11:03:01 +0000 (22:03 +1100)
(This used to be ctdb commit 1306b04cd01e996fd1aa1159a9521f2ff7b06165)

ctdb/Makefile.in
ctdb/include/ctdb.h
ctdb/include/ctdb_private.h
ctdb/lib/util/debug.c
ctdb/lib/util/debug.h
ctdb/server/ctdb_daemon.c
ctdb/server/ctdb_logging.c [new file with mode: 0644]
ctdb/server/ctdb_server.c
ctdb/server/ctdbd.c
ctdb/tests/events.d/00.test

index b28ab9cbabb93239501559a4ec4d52a67dc7931f..8557b9c715126f65f3b02b0f24381c4687ba119e 100644 (file)
@@ -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 \
index f8d0db3d174699df2b7c0288ed08d561f3a1adee..f734a521894f7b21853a8bdfa73a92288c7bb87a 100644 (file)
@@ -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);
index 99d9d99b180e25738f22b70d4fdedab5c92bf4f5..a7f17e6ac4ddaa22248428110d3664c9b7b6ddea 100644 (file)
@@ -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
index c1f1c9141023b1c001bf88e07fe21ce31dd225ca..341a4a1586ab6534d079abb12e1366dd48ef5be2 100644 (file)
@@ -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);
 }
+
index ce454bc668408a76ce2e8fea09ffd12182f4e0b4..ae21e7190955055122401af8a3939a947c8dec93 100644 (file)
@@ -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);
index bdd0fc86c416508c71aab919a28aee8faec2b96d..137b85eee2c2c22a4c13c143ad7b5c324d3aa658 100644 (file)
@@ -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 (file)
index 0000000..a2ff09c
--- /dev/null
@@ -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;
+}
index 2a80798dd93e6c058cd4be99e6e34f270254a0e6..1bf6e5e51522a1100e76a129c8966f8754e609d0 100644 (file)
@@ -60,32 +60,6 @@ int ctdb_set_recovery_lock_file(struct ctdb_context *ctdb, const char *file)
        return 0;
 }
 
-/*
-  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
 */
index a28d5e661b49ddfa4f1eda63d1586b3d077eb4e0..afa2c83e536227bc9b56309e1efb6ba0e0dec2d6 100644 (file)
@@ -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
index fb319bc42621570648af96dc526e1dc49f6424bb..026cf6cba77f39ea7602a3dbcb9662185f453d94 100755 (executable)
@@ -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