summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2008-01-16 22:03:01 +1100
committerAndrew Tridgell <tridge@samba.org>2008-01-16 22:03:01 +1100
commitb62b7fcde84c503e78e65bd4ecf3abc4781af2ec (patch)
treedc9943459a8de7a8951099ffd1eb27b666ffd8a4
parent9f5ce343aaf817568cfe1a3b53bc6fae1e794b0d (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.in2
-rw-r--r--ctdb/include/ctdb.h2
-rw-r--r--ctdb/include/ctdb_private.h2
-rw-r--r--ctdb/lib/util/debug.c6
-rw-r--r--ctdb/lib/util/debug.h2
-rw-r--r--ctdb/server/ctdb_daemon.c2
-rw-r--r--ctdb/server/ctdb_logging.c174
-rw-r--r--ctdb/server/ctdb_server.c26
-rw-r--r--ctdb/server/ctdbd.c15
-rwxr-xr-xctdb/tests/events.d/00.test19
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