From 86259aa395555aaf7b2fae7326caa2ea62961092 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 4 Jun 2010 20:27:03 +0930 Subject: [PATCH] libctdb: add logging infrastructure This is based on Ronnie's work, merged with mine. That means errors are all my fault. Differences from Ronnie's: 1) use syslog's LOG_ levels directly. 2) typesafe arg to log function, and use it (eg stderr) in helper function. 3) store fn in ctdb context, and expose ctdb_log_level directly thru API. Signed-off-by: Rusty Russell --- Makefile.in | 3 ++- include/ctdb.h | 24 ++++++++++++++++- libctdb/ctdb.c | 6 ++++- libctdb/libctdb_private.h | 17 ++++++++++++ libctdb/logging.c | 56 +++++++++++++++++++++++++++++++++++++++ libctdb/tst.c | 3 ++- 6 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 libctdb/logging.c diff --git a/Makefile.in b/Makefile.in index dd7864ea..d2e0dea9 100755 --- a/Makefile.in +++ b/Makefile.in @@ -47,7 +47,8 @@ CTDB_COMMON_OBJ = common/ctdb_io.o common/ctdb_util.o \ common/ctdb_logging.c CTDB_LIB_OBJ = libctdb/ctdb.o libctdb/io_elem.o libctdb/local_tdb.o \ - libctdb/messages.o libctdb/sync.o libctdb/control.o + libctdb/messages.o libctdb/sync.o libctdb/control.o \ + libctdb/logging.o CTDB_TCP_OBJ = tcp/tcp_connect.o tcp/tcp_io.o tcp/tcp_init.o diff --git a/include/ctdb.h b/include/ctdb.h index 5ad8736a..1d0a0861 100644 --- a/include/ctdb.h +++ b/include/ctdb.h @@ -23,8 +23,15 @@ #include #include #include +#include +#include #include +/* The type of the first arg should match the arg given to ctdb_connect() */ +typedef void (*ctdb_log_fn_t)(void *log_priv, + int severity, const char *format, va_list ap); + + /* All *_send() functions are guaranteed to be non-blocking and fully * asynchronous. The non-_send variants are synchronous. */ @@ -34,7 +41,8 @@ * Returns a ctdb context if successful or NULL. * */ -struct ctdb_connection *ctdb_connect(const char *addr); +struct ctdb_connection *ctdb_connect(const char *addr, + ctdb_log_fn_t log_fn, void *log_priv); int ctdb_get_fd(struct ctdb_connection *ctdb); @@ -212,12 +220,26 @@ int ctdb_getrecmaster(struct ctdb_connection *ctdb, int ctdb_cancel(struct ctdb_connection *ctdb, struct ctdb_request *req); +/* + * functions for logging errors + */ +extern int ctdb_log_level; /* LOG_WARNING and above by default. */ +void ctdb_log_file(FILE *, int severity, const char *format, va_list ap); + + /* These ugly macro wrappers make the callbacks typesafe. */ #include #define ctdb_sendcb(cb, cbdata) \ typesafe_cb_preargs(void, (cb), (cbdata), \ struct ctdb_connection *, struct ctdb_request *) +#define ctdb_connect(addr, log, logpriv) \ + ctdb_connect((addr), \ + typesafe_cb_postargs(void, (log), (logpriv), \ + int, const char *, va_list), \ + (logpriv)) + + #define ctdb_attachdb_send(ctdb, name, persistent, tdb_flags, cb, cbdata) \ ctdb_attachdb_send((ctdb), (name), (persistent), (tdb_flags), \ ctdb_sendcb((cb), (cbdata)), (cbdata)) diff --git a/libctdb/ctdb.c b/libctdb/ctdb.c index 771afec6..b6ea121c 100644 --- a/libctdb/ctdb.c +++ b/libctdb/ctdb.c @@ -34,6 +34,7 @@ /* Remove type-safety macros. */ #undef ctdb_attachdb_send #undef ctdb_readrecordlock_async +#undef ctdb_connect /* FIXME: Could be in shared util code with rest of ctdb */ static void close_noerr(int fd) @@ -78,7 +79,8 @@ static void set_pnn(struct ctdb_connection *ctdb, ctdb_request_free(ctdb, req); } -struct ctdb_connection *ctdb_connect(const char *addr) +struct ctdb_connection *ctdb_connect(const char *addr, + ctdb_log_fn_t log_fn, void *log_priv) { struct ctdb_connection *ctdb; struct sockaddr_un sun; @@ -92,6 +94,8 @@ struct ctdb_connection *ctdb_connect(const char *addr) ctdb->message_handlers = NULL; ctdb->next_id = 0; ctdb->broken = false; + ctdb->log = log_fn; + ctdb->log_priv = log_priv; memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_UNIX; diff --git a/libctdb/libctdb_private.h b/libctdb/libctdb_private.h index b3486d20..9e8783e5 100644 --- a/libctdb/libctdb_private.h +++ b/libctdb/libctdb_private.h @@ -6,11 +6,25 @@ #include #include #include +#include #ifndef offsetof #define offsetof(t,f) ((unsigned int)&((t *)0)->f) #endif +#ifndef COLD_ATTRIBUTE +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#define COLD_ATTRIBUTE __attribute__((cold)) +#else +#define COLD_ATTRIBUTE +#endif +#endif /* COLD_ATTRIBUTE */ + +#define DEBUG(ctdb, lvl, format, args...) do { if (lvl <= ctdb_log_level) { ctdb_do_debug(ctdb, lvl, format , ## args ); }} while(0) + +void ctdb_do_debug(struct ctdb_connection *, int, const char *format, ...) + PRINTF_ATTRIBUTE(3, 4) COLD_ATTRIBUTE; + struct message_handler_info; struct ctdb_reply_call; @@ -55,6 +69,9 @@ struct ctdb_connection { struct message_handler_info *message_handlers; /* PNN of this ctdb: valid by the time we do our first db connection. */ uint32_t pnn; + /* Extra logging. */ + ctdb_log_fn_t log; + void *log_priv; }; /* ctdb.c */ diff --git a/libctdb/logging.c b/libctdb/logging.c new file mode 100644 index 00000000..05aaa035 --- /dev/null +++ b/libctdb/logging.c @@ -0,0 +1,56 @@ +/* + logging wrapper for libctdb + + Copyright (C) Ronnie Sahlberg 2010 + + 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 +#include +#include +#include +#include "libctdb_private.h" + +int ctdb_log_level = LOG_WARNING; + +void ctdb_do_debug(struct ctdb_connection *ctdb, + int severity, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + ctdb->log(ctdb->log_priv, severity, format, ap); + va_end(ap); +} + +/* Convenient log helper. */ +void ctdb_log_file(FILE *outf, int priority, const char *format, va_list ap) +{ + fprintf(outf, "%s:", + priority == LOG_EMERG ? "EMERG" : + priority == LOG_ALERT ? "ALERT" : + priority == LOG_CRIT ? "CRIT" : + priority == LOG_ERR ? "ERR" : + priority == LOG_WARNING ? "WARNING" : + priority == LOG_NOTICE ? "NOTICE" : + priority == LOG_INFO ? "INFO" : + priority == LOG_DEBUG ? "DEBUG" : + "Unknown Error Level"); + + vfprintf(outf, format, ap); + if (priority == LOG_ERR) { + fprintf(outf, " (%s)", strerror(errno)); + } + fprintf(outf, "\n"); +} diff --git a/libctdb/tst.c b/libctdb/tst.c index 461c8136..530125c7 100644 --- a/libctdb/tst.c +++ b/libctdb/tst.c @@ -137,7 +137,8 @@ int main(int argc, char *argv[]) bool rrl_cb_called = false; - ctdb_connection = ctdb_connect("/tmp/ctdb.socket"); + ctdb_connection = ctdb_connect("/tmp/ctdb.socket", + ctdb_log_file, stderr); if (!ctdb_connection) err(1, "Connecting to /tmp/ctdb.socket"); -- 2.34.1