Blob Blame History Raw
From c1211c0d47fb510fbd659d9165dc584a9181ec22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
Date: Tue, 26 Apr 2016 16:44:48 +0200
Subject: [PATCH 2/6] Feature: alternative logging provider: libqb

---
 booth.spec              |  3 ++
 configure.ac            | 28 ++++++++++++++++-
 src/Makefile.am         |  8 +++++
 src/alt/logging_libqb.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/alt/logging_libqb.h | 70 +++++++++++++++++++++++++++++++++++++++++
 src/log.h               | 22 +++++++++----
 src/main.c              | 26 ++++++++++++---
 7 files changed, 229 insertions(+), 12 deletions(-)
 create mode 100644 src/alt/logging_libqb.c
 create mode 100644 src/alt/logging_libqb.h

diff --git a/booth.spec b/booth.spec
index f73d2d8..cc73af2 100644
--- a/booth.spec
+++ b/booth.spec
@@ -66,6 +66,9 @@ BuildRequires:  cluster-glue-libs-devel
 %else
 BuildRequires:  libglue-devel
 %endif
+%else
+# logging provider
+BuildRequires:  pkgconfig(libqb)
 %endif
 BuildRequires:  libxml2-devel
 BuildRequires:  zlib-devel
diff --git a/configure.ac b/configure.ac
index 1a8ed4c..32a7dd1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ AC_PREREQ([2.61])
 
 AC_INIT([booth], [1.0], [users@clusterlabs.org])
 
-AM_INIT_AUTOMAKE([-Wno-portability])
+AM_INIT_AUTOMAKE([-Wno-portability subdir-objects])
 
 AC_CONFIG_SRCDIR([src/main.c])
 AC_CONFIG_HEADER([src/b_config.h src/booth_config.h])
@@ -220,6 +220,31 @@ AC_ARG_WITH([glue],
 	[],
 	[with_glue=yes])
 
+# figure out logging provider
+logging_provider=""
+if test "x$logging_provider" = "x" && test "x$with_glue" = "xyes"; then
+	AC_CHECK_LIB([plumb], [cl_log], [logging_provider="libplumb"])
+fi
+if test "x$logging_provider" = "x" && test "x$with_glue" = "xno"; then
+	AC_CHECK_LIB([qb], [qb_log_real_], [logging_provider="libqb"])
+fi
+case "$logging_provider" in
+libplumb)
+	;;
+libqb)
+	PKG_CHECK_MODULES([LIBQB], [libqb])
+	AC_DEFINE([LOGGING_LIBQB], [], [use libqb as a logging provider])
+	PKG_CHECK_MODULES([LIBQB1], [libqb >= 1.0],
+			  [AC_DEFINE([LOGGING_LIBQB_MAJOR], [1],
+				     [libqb major version lower bound])],
+			  [AC_MSG_WARN([[syslog identifier will not get changed]])])
+	;;
+*)
+	AC_MSG_ERROR([logging provider required (libplumb, or libqb when --without-glue)])
+	;;
+esac
+AM_CONDITIONAL([LOGGING_LIBQB], [test "x$logging_provider" = "xlibqb"])
+
 # OS detection
 # THIS SECTION MUST DIE!
 CP=cp
@@ -448,6 +473,7 @@ AC_MSG_RESULT([  System init.d directory  = ${INITDDIR}])
 AC_MSG_RESULT([  booth config dir         = ${BOOTHSYSCONFDIR}])
 AC_MSG_RESULT([  SOCKETDIR                = ${SOCKETDIR}])
 AC_MSG_RESULT([  Features                 = ${PACKAGE_FEATURES}])
+AC_MSG_RESULT([  Logging provider         = ${logging_provider}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([$PACKAGE build info:])
 AC_MSG_RESULT([  Library SONAME           = ${SONAME}])
diff --git a/src/Makefile.am b/src/Makefile.am
index e7f5aa2..49c3ac4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,5 +25,13 @@ boothd_LDFLAGS		= $(OS_DYFLAGS) -L./
 boothd_LDADD		= -lplumb -lplumbgpl -lm $(GLIB_LIBS) $(ZLIB_LIBS)
 boothd_CFLAGS		= $(GLIB_CFLAGS)
 
+if !LOGGING_LIBQB
+boothd_LDADD		+= -lplumb
+else
+boothd_LDADD		+= $(LIBQB_LIBS)
+boothd_SOURCES		+= alt/logging_libqb.c
+noinst_HEADERS		+= alt/logging_libqb.h
+endif
+
 lint:
 	-splint $(INCLUDES) $(LINT_FLAGS) $(CFLAGS) *.c
diff --git a/src/alt/logging_libqb.c b/src/alt/logging_libqb.c
new file mode 100644
index 0000000..34cf97c
--- /dev/null
+++ b/src/alt/logging_libqb.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 Jan Pokorny <jpokorny@redhat.com>
+ *
+ * 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 2.1 of the License, or (at your option) any later version.
+ *
+ * This software 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <qb/qblog.h>
+
+#include "logging_libqb.h"
+
+int debug_level = 0;
+
+/* ENV_X definitions based on glue/lib/clplumbing/cl_log.c of glue project:
+   http://hg.linux-ha.org/glue */
+#define ENV_HADEBUGVAL	"HA_debug"
+#define ENV_LOGFENV	"HA_logfile"	/* well-formed log file :-) */
+#define ENV_DEBUGFENV	"HA_debugfile"	/* Debug log file */
+#define ENV_LOGFACILITY	"HA_logfacility"/* Facility to use for logger */
+#define ENV_SYSLOGFMT	"HA_syslogmsgfmt"/* TRUE if we should use syslog message formatting */
+
+void
+alt_qb_inherit_logging_environment(void)
+{
+	char *inherit_env;
+
+	/* Don't need to free the return pointer from getenv */
+	inherit_env = getenv(ENV_HADEBUGVAL);
+	if (inherit_env != NULL && atoi(inherit_env) != 0 )
+		debug_level = atoi(inherit_env);
+
+	inherit_env = getenv(ENV_LOGFENV);
+	if (inherit_env != NULL && *inherit_env != '\0') {
+		int32_t log_fd = qb_log_file_open(inherit_env);
+		qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE);
+		/* do not log debug info even if debug_level non-zero */
+		qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD,
+				  QB_LOG_FILTER_FILE, "*", LOG_INFO);
+	}
+
+	inherit_env = getenv(ENV_DEBUGFENV);
+	if (inherit_env != NULL && *inherit_env != '\0') {
+		int32_t log_fd = qb_log_file_open(inherit_env);
+		qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE);
+	}
+
+	inherit_env = getenv(ENV_LOGFACILITY);
+	if (inherit_env != NULL && *inherit_env != '\0') {
+		int fac = qb_log_facility2int(inherit_env);
+		if (fac > 0)
+			qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, fac);
+		else
+			qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
+	}
+
+	inherit_env = getenv(ENV_SYSLOGFMT);
+	if (inherit_env != NULL && *inherit_env != '\0'
+	&&	(	!strcasecmp(inherit_env, "false")
+		||	!strcasecmp(inherit_env, "off")
+		||	!strcasecmp(inherit_env, "no")
+		||	!strcasecmp(inherit_env, "n")
+		||	!strcasecmp(inherit_env, "0"))){
+		enum qb_log_target_slot i;
+		for (i = QB_LOG_TARGET_START; i < QB_LOG_TARGET_MAX; i++) {
+			if (i == QB_LOG_SYSLOG || i == QB_LOG_BLACKBOX)
+				continue;
+			qb_log_format_set(i, NULL);
+		}
+	}
+}
diff --git a/src/alt/logging_libqb.h b/src/alt/logging_libqb.h
new file mode 100644
index 0000000..76592d4
--- /dev/null
+++ b/src/alt/logging_libqb.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 Jan Pokorny <jpokorny@redhat.com>
+ *
+ * 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 2.1 of the License, or (at your option) any later version.
+ *
+ * This software 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <qb/qblog.h>
+
+#include "b_config.h"
+
+/* qb logging compat definitions */
+#if (!defined LOGGING_LIBQB_MAJOR || (LOGGING_LIBQB_MAJOR < 1))
+enum tmp_log_target_slot {
+	TMP_LOG_SYSLOG = QB_LOG_SYSLOG,
+	TMP_LOG_STDERR = QB_LOG_STDERR,
+	TMP_LOG_BLACKBOX = QB_LOG_BLACKBOX,
+	TMP_LOG_TARGET_MAX = QB_LOG_TARGET_MAX,
+};
+
+#undef QB_LOG_SYSLOG
+#undef QB_LOG_STDERR
+#undef QB_LOG_BLACKBOX
+#undef QB_LOG_TARGET_MAX
+
+enum qb_log_target_slot {
+	QB_LOG_TARGET_START,
+	QB_LOG_SYSLOG = TMP_LOG_SYSLOG,
+	QB_LOG_STDERR = TMP_LOG_STDERR,
+	QB_LOG_BLACKBOX = TMP_LOG_BLACKBOX,
+	QB_LOG_TARGET_MAX = TMP_LOG_TARGET_MAX,
+};
+
+#define QB_LOG_CTL2_S(a)	(a)
+#define qb_log_ctl2(t, s, a)	((void) 0)
+#endif
+
+
+#ifndef HA_LOG_FACILITY
+/* based on glue/configure.ac of glue project: http://hg.linux-ha.org/glue */
+#define HA_LOG_FACILITY	LOG_DAEMON
+#endif
+
+extern int debug_level;
+#define ANYDEBUG	(debug_level)
+
+void alt_qb_inherit_logging_environment(void);
+
+#define cl_log_set_entity(ent) \
+	(void) qb_log_ctl2(QB_LOG_SYSLOG, QB_LOG_CONF_IDENT, QB_LOG_CTL2_S(ent))
+
+#define cl_log_enable_stderr(b) \
+	(void) qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, b ? QB_TRUE : QB_FALSE)
+
+#define cl_log_set_facility(f) \
+	(void) qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, f)
+
+#define cl_inherit_logging_environment(logqueuemax) \
+	alt_qb_inherit_logging_environment()
diff --git a/src/log.h b/src/log.h
index 0be4066..e570a8d 100644
--- a/src/log.h
+++ b/src/log.h
@@ -21,26 +21,36 @@
 #ifndef _LOG_H
 #define _LOG_H
 
+#include "b_config.h"
+
+#ifndef LOGGING_LIBQB
 #include <heartbeat/glue_config.h>
 #include <clplumbing/cl_log.h>
+#define priv_log(prio, ...)		cl_log(prio, __VA_ARGS__)
+#else
+#include "alt/logging_libqb.h"
+#define priv_log(prio, ...)		qb_log(prio, __VA_ARGS__)
+#endif
+
 #include "inline-fn.h"
 
+
 #define log_debug(fmt, args...)		do { \
-	if (ANYDEBUG) cl_log(LOG_DEBUG, fmt, ##args); } \
+	if (ANYDEBUG) priv_log(LOG_DEBUG, fmt, ##args); } \
 	while (0)
-#define log_info(fmt, args...)		cl_log(LOG_INFO, fmt, ##args)
-#define log_warn(fmt, args...)		cl_log(LOG_WARNING, fmt, ##args)
-#define log_error(fmt, args...)		cl_log(LOG_ERR, fmt, ##args)
+#define log_info(fmt, args...)		priv_log(LOG_INFO, fmt, ##args)
+#define log_warn(fmt, args...)		priv_log(LOG_WARNING, fmt, ##args)
+#define log_error(fmt, args...)		priv_log(LOG_ERR, fmt, ##args)
 
 /* all tk_* macros prepend "%(tk->name): " (the caller needs to
  * have the ticket named tk!)
  */
 #define tk_cl_log(sev, fmt, args...) \
-	cl_log(sev, "%s (%s/%d/%d): " fmt, \
+	priv_log(sev, "%s (%s/%d/%d): " fmt, \
 	tk->name, state_to_string(tk->state), tk->current_term, term_time_left(tk), \
 	##args)
 #define tk_cl_log_src(sev, fmt, args...) \
-	cl_log(sev, "%s:%d: %s (%s/%d/%d): " fmt, \
+	priv_log(sev, "%s:%d: %s (%s/%d/%d): " fmt, \
 	__FUNCTION__, __LINE__, \
 	tk->name, state_to_string(tk->state), tk->current_term, term_time_left(tk), \
 	##args)
diff --git a/src/main.c b/src/main.c
index c377392..498718b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1536,6 +1536,9 @@ int main(int argc, char *argv[], char *envp[])
 {
 	int rv;
 	const char *cp;
+#ifdef LOGGING_LIBQB
+	enum qb_log_target_slot i;
+#endif
 
 	init_set_proc_title(argc, argv, envp);
 	get_time(&start_time);
@@ -1546,15 +1549,25 @@ int main(int argc, char *argv[], char *envp[])
 	cl.lockfile[0] = 0;
 	debug_level = 0;
 
-	cl_log_set_entity(
-		(cp = strstr(argv[0], ATTR_PROG)) && !strcmp(cp, ATTR_PROG)
+
+	cp = ((cp = strstr(argv[0], ATTR_PROG)) && !strcmp(cp, ATTR_PROG)
 		? ATTR_PROG
-		: "booth"
-		);
+		: "booth");
+#ifndef LOGGING_LIBQB
+	cl_log_set_entity(cp);
+#else
+	qb_log_init(cp, LOG_USER, LOG_DEBUG);  /* prio driven by debug_level */
+	for (i = QB_LOG_TARGET_START; i < QB_LOG_TARGET_MAX; i++) {
+		if (i == QB_LOG_SYSLOG || i == QB_LOG_BLACKBOX)
+			continue;
+		qb_log_format_set(i, "%t %H %N: [%P]: %p: %b");
+	}
+	(void) qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
+	                         QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
+#endif
 	cl_log_enable_stderr(TRUE);
 	cl_log_set_facility(0);
 
-
 	rv = read_arguments(argc, argv);
 	if (rv < 0)
 		goto out;
@@ -1581,6 +1594,9 @@ int main(int argc, char *argv[], char *envp[])
 	}
 
 out:
+#ifdef LOGGING_LIBQB
+	qb_log_fini();
+#endif
 	/* Normalize values. 0x100 would be seen as "OK" by waitpid(). */
 	return (rv >= 0 && rv < 0x70) ? rv : 1;
 }
-- 
2.4.11