diff options
Diffstat (limited to 'src/lib/log')
94 files changed, 17140 insertions, 0 deletions
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am new file mode 100644 index 0000000..b7150e3 --- /dev/null +++ b/src/lib/log/Makefile.am @@ -0,0 +1,119 @@ +SUBDIRS = interprocess . compiler tests + +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) +AM_CPPFLAGS += -DTOP_BUILDDIR=\"$(abs_top_builddir)\" + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +CLEANFILES = *.gcno *.gcda + +lib_LTLIBRARIES = libkea-log.la +libkea_log_la_SOURCES = +libkea_log_la_SOURCES += logimpl_messages.cc logimpl_messages.h +libkea_log_la_SOURCES += log_dbglevels.cc log_dbglevels.h +libkea_log_la_SOURCES += log_formatter.h log_formatter.cc +libkea_log_la_SOURCES += logger.cc logger.h +libkea_log_la_SOURCES += logger_impl.cc logger_impl.h +libkea_log_la_SOURCES += logger_level.cc logger_level.h +libkea_log_la_SOURCES += logger_level_impl.cc logger_level_impl.h +libkea_log_la_SOURCES += logger_manager.cc logger_manager.h +libkea_log_la_SOURCES += logger_manager_impl.cc logger_manager_impl.h +libkea_log_la_SOURCES += logger_name.cc logger_name.h +libkea_log_la_SOURCES += logger_specification.h +libkea_log_la_SOURCES += logger_support.cc logger_support.h +libkea_log_la_SOURCES += logger_unittest_support.cc logger_unittest_support.h +libkea_log_la_SOURCES += log_messages.cc log_messages.h +libkea_log_la_SOURCES += macros.h +libkea_log_la_SOURCES += message_dictionary.cc message_dictionary.h +libkea_log_la_SOURCES += message_exception.h +libkea_log_la_SOURCES += message_initializer.cc message_initializer.h +libkea_log_la_SOURCES += message_reader.cc message_reader.h +libkea_log_la_SOURCES += message_types.h +libkea_log_la_SOURCES += output_option.cc output_option.h +libkea_log_la_SOURCES += buffer_appender_impl.cc buffer_appender_impl.h + +EXTRA_DIST = logging.dox +EXTRA_DIST += logimpl_messages.mes +EXTRA_DIST += log_messages.mes + +# Note: the ordering matters: -Wno-... must follow -Wextra (defined in +# KEA_CXXFLAGS) +libkea_log_la_CXXFLAGS = $(AM_CXXFLAGS) +if USE_GXX +libkea_log_la_CXXFLAGS += -Wno-unused-parameter -Wno-deprecated-declarations +endif +libkea_log_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES) +libkea_log_la_LIBADD = $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la +libkea_log_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la +libkea_log_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +libkea_log_la_LIBADD += $(LOG4CPLUS_LIBS) +libkea_log_la_LDFLAGS = -no-undefined -version-info 48:0:0 + +# Specify the headers for copying into the installation directory tree. +libkea_log_includedir = $(pkgincludedir)/log +libkea_log_include_HEADERS = \ + buffer_appender_impl.h \ + log_dbglevels.h \ + log_formatter.h \ + log_messages.h \ + logger.h \ + logger_impl.h \ + logger_level.h \ + logger_level_impl.h \ + logger_manager.h \ + logger_manager_impl.h \ + logger_name.h \ + logger_specification.h \ + logger_support.h \ + logger_unittest_support.h \ + logimpl_messages.h \ + macros.h \ + message_dictionary.h \ + message_exception.h \ + message_initializer.h \ + message_reader.h \ + message_types.h \ + output_option.h + +libkea_log_interprocess_includedir = $(pkgincludedir)/log/interprocess +libkea_log_interprocess_include_HEADERS = \ + interprocess/interprocess_sync.h \ + interprocess/interprocess_sync_file.h \ + interprocess/interprocess_sync_null.h + +# If we want to get rid of all generated messages files, we need to use +# make maintainer-clean. The proper way to introduce custom commands for +# that operation is to define maintainer-clean-local target. However, +# make maintainer-clean also removes Makefile, so running configure script +# is required. To make it easy to rebuild messages without going through +# reconfigure, a new target messages-clean has been added. +maintainer-clean-local: + rm -f log_messages.cc log_messages.h logimpl_messages.cc logimpl_messages.h + +# To regenerate messages files, one can do: +# +# make messages-clean +# make messages +# +# This is needed only when a .mes file is modified. +messages-clean: maintainer-clean-local + +if GENERATE_MESSAGES + +# Define rule to build logging source files from message file. +messages: log_messages.cc log_messages.h logimpl_messages.cc logimpl_messages.h + @echo Message files regenerated + +log_messages.cc log_messages.h: log_messages.mes + $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/log/log_messages.mes + +logimpl_messages.cc logimpl_messages.h: logimpl_messages.mes + $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/log/logimpl_messages.mes + +else + +messages log_messages.cc log_messages.h logimpl_messages.cc logimpl_messages.h: + @echo Messages generation disabled. Configure with --enable-generate-messages to enable it. + +endif diff --git a/src/lib/log/Makefile.in b/src/lib/log/Makefile.in new file mode 100644 index 0000000..1cce016 --- /dev/null +++ b/src/lib/log/Makefile.in @@ -0,0 +1,1258 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@USE_GXX_TRUE@am__append_1 = -Wno-unused-parameter -Wno-deprecated-declarations +subdir = src/lib/log +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \ + $(top_srcdir)/m4macros/ax_cpp11.m4 \ + $(top_srcdir)/m4macros/ax_cpp20.m4 \ + $(top_srcdir)/m4macros/ax_crypto.m4 \ + $(top_srcdir)/m4macros/ax_find_library.m4 \ + $(top_srcdir)/m4macros/ax_gssapi.m4 \ + $(top_srcdir)/m4macros/ax_gtest.m4 \ + $(top_srcdir)/m4macros/ax_isc_rpath.m4 \ + $(top_srcdir)/m4macros/ax_netconf.m4 \ + $(top_srcdir)/m4macros/libtool.m4 \ + $(top_srcdir)/m4macros/ltoptions.m4 \ + $(top_srcdir)/m4macros/ltsugar.m4 \ + $(top_srcdir)/m4macros/ltversion.m4 \ + $(top_srcdir)/m4macros/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(libkea_log_include_HEADERS) \ + $(libkea_log_interprocess_include_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(libkea_log_includedir)" \ + "$(DESTDIR)$(libkea_log_interprocess_includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libkea_log_la_DEPENDENCIES = $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la \ + $(top_builddir)/src/lib/util/libkea-util.la \ + $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ + $(am__DEPENDENCIES_1) +am_libkea_log_la_OBJECTS = libkea_log_la-logimpl_messages.lo \ + libkea_log_la-log_dbglevels.lo libkea_log_la-log_formatter.lo \ + libkea_log_la-logger.lo libkea_log_la-logger_impl.lo \ + libkea_log_la-logger_level.lo \ + libkea_log_la-logger_level_impl.lo \ + libkea_log_la-logger_manager.lo \ + libkea_log_la-logger_manager_impl.lo \ + libkea_log_la-logger_name.lo libkea_log_la-logger_support.lo \ + libkea_log_la-logger_unittest_support.lo \ + libkea_log_la-log_messages.lo \ + libkea_log_la-message_dictionary.lo \ + libkea_log_la-message_initializer.lo \ + libkea_log_la-message_reader.lo libkea_log_la-output_option.lo \ + libkea_log_la-buffer_appender_impl.lo +libkea_log_la_OBJECTS = $(am_libkea_log_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libkea_log_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) $(libkea_log_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + ./$(DEPDIR)/libkea_log_la-buffer_appender_impl.Plo \ + ./$(DEPDIR)/libkea_log_la-log_dbglevels.Plo \ + ./$(DEPDIR)/libkea_log_la-log_formatter.Plo \ + ./$(DEPDIR)/libkea_log_la-log_messages.Plo \ + ./$(DEPDIR)/libkea_log_la-logger.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_impl.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_level.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_level_impl.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_manager.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_manager_impl.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_name.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_support.Plo \ + ./$(DEPDIR)/libkea_log_la-logger_unittest_support.Plo \ + ./$(DEPDIR)/libkea_log_la-logimpl_messages.Plo \ + ./$(DEPDIR)/libkea_log_la-message_dictionary.Plo \ + ./$(DEPDIR)/libkea_log_la-message_initializer.Plo \ + ./$(DEPDIR)/libkea_log_la-message_reader.Plo \ + ./$(DEPDIR)/libkea_log_la-output_option.Plo +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libkea_log_la_SOURCES) +DIST_SOURCES = $(libkea_log_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(libkea_log_include_HEADERS) \ + $(libkea_log_interprocess_include_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_INCLUDES = @BOOST_INCLUDES@ +BOOST_LIBS = @BOOST_LIBS@ +BOTAN_TOOL = @BOTAN_TOOL@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONTRIB_DIR = @CONTRIB_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ +CRYPTO_INCLUDES = @CRYPTO_INCLUDES@ +CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPTO_PACKAGE = @CRYPTO_PACKAGE@ +CRYPTO_RPATH = @CRYPTO_RPATH@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@ +DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@ +DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@ +DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@ +DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@ +DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@ +DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@ +DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@ +DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@ +DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@ +DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@ +DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@ +DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@ +DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@ +DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_INCLUDES = @GTEST_INCLUDES@ +GTEST_LDADD = @GTEST_LDADD@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_SOURCE = @GTEST_SOURCE@ +HAVE_NETCONF = @HAVE_NETCONF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KEA_CXXFLAGS = @KEA_CXXFLAGS@ +KEA_SRCID = @KEA_SRCID@ +KRB5_CONFIG = @KRB5_CONFIG@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@ +LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@ +LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@ +LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@ +LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@ +LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@ +LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@ +LIBYANG_LIBS = @LIBYANG_LIBS@ +LIBYANG_PREFIX = @LIBYANG_PREFIX@ +LIBYANG_VERSION = @LIBYANG_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@ +LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +PERL = @PERL@ +PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PKGPYTHONDIR = @PKGPYTHONDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PLANTUML = @PLANTUML@ +PREMIUM_DIR = @PREMIUM_DIR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SEP = @SEP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINXBUILD = @SPHINXBUILD@ +SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@ +SR_PLUGINS_PATH = @SR_PLUGINS_PATH@ +SR_REPO_PATH = @SR_REPO_PATH@ +STRIP = @STRIP@ +SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@ +SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@ +SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@ +SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@ +SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@ +SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@ +SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@ +SYSREPO_LIBS = @SYSREPO_LIBS@ +SYSREPO_PREFIX = @SYSREPO_PREFIX@ +SYSREPO_VERSION = @SYSREPO_VERSION@ +USE_LCOV = @USE_LCOV@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = interprocess . compiler tests +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib \ + $(BOOST_INCLUDES) -DTOP_BUILDDIR=\"$(abs_top_builddir)\" +AM_CXXFLAGS = $(KEA_CXXFLAGS) +CLEANFILES = *.gcno *.gcda +lib_LTLIBRARIES = libkea-log.la +libkea_log_la_SOURCES = logimpl_messages.cc logimpl_messages.h \ + log_dbglevels.cc log_dbglevels.h log_formatter.h \ + log_formatter.cc logger.cc logger.h logger_impl.cc \ + logger_impl.h logger_level.cc logger_level.h \ + logger_level_impl.cc logger_level_impl.h logger_manager.cc \ + logger_manager.h logger_manager_impl.cc logger_manager_impl.h \ + logger_name.cc logger_name.h logger_specification.h \ + logger_support.cc logger_support.h logger_unittest_support.cc \ + logger_unittest_support.h log_messages.cc log_messages.h \ + macros.h message_dictionary.cc message_dictionary.h \ + message_exception.h message_initializer.cc \ + message_initializer.h message_reader.cc message_reader.h \ + message_types.h output_option.cc output_option.h \ + buffer_appender_impl.cc buffer_appender_impl.h +EXTRA_DIST = logging.dox logimpl_messages.mes log_messages.mes + +# Note: the ordering matters: -Wno-... must follow -Wextra (defined in +# KEA_CXXFLAGS) +libkea_log_la_CXXFLAGS = $(AM_CXXFLAGS) $(am__append_1) +libkea_log_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES) +libkea_log_la_LIBADD = $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la \ + $(top_builddir)/src/lib/util/libkea-util.la \ + $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ + $(LOG4CPLUS_LIBS) +libkea_log_la_LDFLAGS = -no-undefined -version-info 48:0:0 + +# Specify the headers for copying into the installation directory tree. +libkea_log_includedir = $(pkgincludedir)/log +libkea_log_include_HEADERS = \ + buffer_appender_impl.h \ + log_dbglevels.h \ + log_formatter.h \ + log_messages.h \ + logger.h \ + logger_impl.h \ + logger_level.h \ + logger_level_impl.h \ + logger_manager.h \ + logger_manager_impl.h \ + logger_name.h \ + logger_specification.h \ + logger_support.h \ + logger_unittest_support.h \ + logimpl_messages.h \ + macros.h \ + message_dictionary.h \ + message_exception.h \ + message_initializer.h \ + message_reader.h \ + message_types.h \ + output_option.h + +libkea_log_interprocess_includedir = $(pkgincludedir)/log/interprocess +libkea_log_interprocess_include_HEADERS = \ + interprocess/interprocess_sync.h \ + interprocess/interprocess_sync_file.h \ + interprocess/interprocess_sync_null.h + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/log/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/log/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libkea-log.la: $(libkea_log_la_OBJECTS) $(libkea_log_la_DEPENDENCIES) $(EXTRA_libkea_log_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libkea_log_la_LINK) -rpath $(libdir) $(libkea_log_la_OBJECTS) $(libkea_log_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-buffer_appender_impl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-log_dbglevels.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-log_formatter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-log_messages.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_impl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_level.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_level_impl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_manager.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_manager_impl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_name.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_support.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logger_unittest_support.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-logimpl_messages.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-message_dictionary.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-message_initializer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-message_reader.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkea_log_la-output_option.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +libkea_log_la-logimpl_messages.lo: logimpl_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logimpl_messages.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logimpl_messages.Tpo -c -o libkea_log_la-logimpl_messages.lo `test -f 'logimpl_messages.cc' || echo '$(srcdir)/'`logimpl_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logimpl_messages.Tpo $(DEPDIR)/libkea_log_la-logimpl_messages.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logimpl_messages.cc' object='libkea_log_la-logimpl_messages.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logimpl_messages.lo `test -f 'logimpl_messages.cc' || echo '$(srcdir)/'`logimpl_messages.cc + +libkea_log_la-log_dbglevels.lo: log_dbglevels.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-log_dbglevels.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-log_dbglevels.Tpo -c -o libkea_log_la-log_dbglevels.lo `test -f 'log_dbglevels.cc' || echo '$(srcdir)/'`log_dbglevels.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-log_dbglevels.Tpo $(DEPDIR)/libkea_log_la-log_dbglevels.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_dbglevels.cc' object='libkea_log_la-log_dbglevels.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-log_dbglevels.lo `test -f 'log_dbglevels.cc' || echo '$(srcdir)/'`log_dbglevels.cc + +libkea_log_la-log_formatter.lo: log_formatter.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-log_formatter.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-log_formatter.Tpo -c -o libkea_log_la-log_formatter.lo `test -f 'log_formatter.cc' || echo '$(srcdir)/'`log_formatter.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-log_formatter.Tpo $(DEPDIR)/libkea_log_la-log_formatter.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_formatter.cc' object='libkea_log_la-log_formatter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-log_formatter.lo `test -f 'log_formatter.cc' || echo '$(srcdir)/'`log_formatter.cc + +libkea_log_la-logger.lo: logger.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger.Tpo -c -o libkea_log_la-logger.lo `test -f 'logger.cc' || echo '$(srcdir)/'`logger.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger.Tpo $(DEPDIR)/libkea_log_la-logger.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger.cc' object='libkea_log_la-logger.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger.lo `test -f 'logger.cc' || echo '$(srcdir)/'`logger.cc + +libkea_log_la-logger_impl.lo: logger_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_impl.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_impl.Tpo -c -o libkea_log_la-logger_impl.lo `test -f 'logger_impl.cc' || echo '$(srcdir)/'`logger_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_impl.Tpo $(DEPDIR)/libkea_log_la-logger_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_impl.cc' object='libkea_log_la-logger_impl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_impl.lo `test -f 'logger_impl.cc' || echo '$(srcdir)/'`logger_impl.cc + +libkea_log_la-logger_level.lo: logger_level.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_level.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_level.Tpo -c -o libkea_log_la-logger_level.lo `test -f 'logger_level.cc' || echo '$(srcdir)/'`logger_level.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_level.Tpo $(DEPDIR)/libkea_log_la-logger_level.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_level.cc' object='libkea_log_la-logger_level.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_level.lo `test -f 'logger_level.cc' || echo '$(srcdir)/'`logger_level.cc + +libkea_log_la-logger_level_impl.lo: logger_level_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_level_impl.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_level_impl.Tpo -c -o libkea_log_la-logger_level_impl.lo `test -f 'logger_level_impl.cc' || echo '$(srcdir)/'`logger_level_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_level_impl.Tpo $(DEPDIR)/libkea_log_la-logger_level_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_level_impl.cc' object='libkea_log_la-logger_level_impl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_level_impl.lo `test -f 'logger_level_impl.cc' || echo '$(srcdir)/'`logger_level_impl.cc + +libkea_log_la-logger_manager.lo: logger_manager.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_manager.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_manager.Tpo -c -o libkea_log_la-logger_manager.lo `test -f 'logger_manager.cc' || echo '$(srcdir)/'`logger_manager.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_manager.Tpo $(DEPDIR)/libkea_log_la-logger_manager.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_manager.cc' object='libkea_log_la-logger_manager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_manager.lo `test -f 'logger_manager.cc' || echo '$(srcdir)/'`logger_manager.cc + +libkea_log_la-logger_manager_impl.lo: logger_manager_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_manager_impl.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_manager_impl.Tpo -c -o libkea_log_la-logger_manager_impl.lo `test -f 'logger_manager_impl.cc' || echo '$(srcdir)/'`logger_manager_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_manager_impl.Tpo $(DEPDIR)/libkea_log_la-logger_manager_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_manager_impl.cc' object='libkea_log_la-logger_manager_impl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_manager_impl.lo `test -f 'logger_manager_impl.cc' || echo '$(srcdir)/'`logger_manager_impl.cc + +libkea_log_la-logger_name.lo: logger_name.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_name.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_name.Tpo -c -o libkea_log_la-logger_name.lo `test -f 'logger_name.cc' || echo '$(srcdir)/'`logger_name.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_name.Tpo $(DEPDIR)/libkea_log_la-logger_name.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_name.cc' object='libkea_log_la-logger_name.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_name.lo `test -f 'logger_name.cc' || echo '$(srcdir)/'`logger_name.cc + +libkea_log_la-logger_support.lo: logger_support.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_support.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_support.Tpo -c -o libkea_log_la-logger_support.lo `test -f 'logger_support.cc' || echo '$(srcdir)/'`logger_support.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_support.Tpo $(DEPDIR)/libkea_log_la-logger_support.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_support.cc' object='libkea_log_la-logger_support.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_support.lo `test -f 'logger_support.cc' || echo '$(srcdir)/'`logger_support.cc + +libkea_log_la-logger_unittest_support.lo: logger_unittest_support.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-logger_unittest_support.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-logger_unittest_support.Tpo -c -o libkea_log_la-logger_unittest_support.lo `test -f 'logger_unittest_support.cc' || echo '$(srcdir)/'`logger_unittest_support.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-logger_unittest_support.Tpo $(DEPDIR)/libkea_log_la-logger_unittest_support.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_unittest_support.cc' object='libkea_log_la-logger_unittest_support.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-logger_unittest_support.lo `test -f 'logger_unittest_support.cc' || echo '$(srcdir)/'`logger_unittest_support.cc + +libkea_log_la-log_messages.lo: log_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-log_messages.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-log_messages.Tpo -c -o libkea_log_la-log_messages.lo `test -f 'log_messages.cc' || echo '$(srcdir)/'`log_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-log_messages.Tpo $(DEPDIR)/libkea_log_la-log_messages.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_messages.cc' object='libkea_log_la-log_messages.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-log_messages.lo `test -f 'log_messages.cc' || echo '$(srcdir)/'`log_messages.cc + +libkea_log_la-message_dictionary.lo: message_dictionary.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-message_dictionary.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-message_dictionary.Tpo -c -o libkea_log_la-message_dictionary.lo `test -f 'message_dictionary.cc' || echo '$(srcdir)/'`message_dictionary.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-message_dictionary.Tpo $(DEPDIR)/libkea_log_la-message_dictionary.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_dictionary.cc' object='libkea_log_la-message_dictionary.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-message_dictionary.lo `test -f 'message_dictionary.cc' || echo '$(srcdir)/'`message_dictionary.cc + +libkea_log_la-message_initializer.lo: message_initializer.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-message_initializer.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-message_initializer.Tpo -c -o libkea_log_la-message_initializer.lo `test -f 'message_initializer.cc' || echo '$(srcdir)/'`message_initializer.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-message_initializer.Tpo $(DEPDIR)/libkea_log_la-message_initializer.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_initializer.cc' object='libkea_log_la-message_initializer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-message_initializer.lo `test -f 'message_initializer.cc' || echo '$(srcdir)/'`message_initializer.cc + +libkea_log_la-message_reader.lo: message_reader.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-message_reader.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-message_reader.Tpo -c -o libkea_log_la-message_reader.lo `test -f 'message_reader.cc' || echo '$(srcdir)/'`message_reader.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-message_reader.Tpo $(DEPDIR)/libkea_log_la-message_reader.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_reader.cc' object='libkea_log_la-message_reader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-message_reader.lo `test -f 'message_reader.cc' || echo '$(srcdir)/'`message_reader.cc + +libkea_log_la-output_option.lo: output_option.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-output_option.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-output_option.Tpo -c -o libkea_log_la-output_option.lo `test -f 'output_option.cc' || echo '$(srcdir)/'`output_option.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-output_option.Tpo $(DEPDIR)/libkea_log_la-output_option.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='output_option.cc' object='libkea_log_la-output_option.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-output_option.lo `test -f 'output_option.cc' || echo '$(srcdir)/'`output_option.cc + +libkea_log_la-buffer_appender_impl.lo: buffer_appender_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -MT libkea_log_la-buffer_appender_impl.lo -MD -MP -MF $(DEPDIR)/libkea_log_la-buffer_appender_impl.Tpo -c -o libkea_log_la-buffer_appender_impl.lo `test -f 'buffer_appender_impl.cc' || echo '$(srcdir)/'`buffer_appender_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkea_log_la-buffer_appender_impl.Tpo $(DEPDIR)/libkea_log_la-buffer_appender_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_appender_impl.cc' object='libkea_log_la-buffer_appender_impl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkea_log_la_CPPFLAGS) $(CPPFLAGS) $(libkea_log_la_CXXFLAGS) $(CXXFLAGS) -c -o libkea_log_la-buffer_appender_impl.lo `test -f 'buffer_appender_impl.cc' || echo '$(srcdir)/'`buffer_appender_impl.cc + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-libkea_log_includeHEADERS: $(libkea_log_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libkea_log_include_HEADERS)'; test -n "$(libkea_log_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libkea_log_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libkea_log_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libkea_log_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libkea_log_includedir)" || exit $$?; \ + done + +uninstall-libkea_log_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libkea_log_include_HEADERS)'; test -n "$(libkea_log_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libkea_log_includedir)'; $(am__uninstall_files_from_dir) +install-libkea_log_interprocess_includeHEADERS: $(libkea_log_interprocess_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libkea_log_interprocess_include_HEADERS)'; test -n "$(libkea_log_interprocess_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libkea_log_interprocess_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libkea_log_interprocess_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libkea_log_interprocess_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libkea_log_interprocess_includedir)" || exit $$?; \ + done + +uninstall-libkea_log_interprocess_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libkea_log_interprocess_include_HEADERS)'; test -n "$(libkea_log_interprocess_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libkea_log_interprocess_includedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libkea_log_includedir)" "$(DESTDIR)$(libkea_log_interprocess_includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/libkea_log_la-buffer_appender_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-log_dbglevels.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-log_formatter.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-log_messages.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_level.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_level_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_manager.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_manager_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_name.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_support.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_unittest_support.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logimpl_messages.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-message_dictionary.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-message_initializer.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-message_reader.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-output_option.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-libkea_log_includeHEADERS \ + install-libkea_log_interprocess_includeHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/libkea_log_la-buffer_appender_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-log_dbglevels.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-log_formatter.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-log_messages.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_level.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_level_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_manager.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_manager_impl.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_name.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_support.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logger_unittest_support.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-logimpl_messages.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-message_dictionary.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-message_initializer.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-message_reader.Plo + -rm -f ./$(DEPDIR)/libkea_log_la-output_option.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES \ + uninstall-libkea_log_includeHEADERS \ + uninstall-libkea_log_interprocess_includeHEADERS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES \ + install-libkea_log_includeHEADERS \ + install-libkea_log_interprocess_includeHEADERS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \ + uninstall-libkea_log_includeHEADERS \ + uninstall-libkea_log_interprocess_includeHEADERS + +.PRECIOUS: Makefile + + +# If we want to get rid of all generated messages files, we need to use +# make maintainer-clean. The proper way to introduce custom commands for +# that operation is to define maintainer-clean-local target. However, +# make maintainer-clean also removes Makefile, so running configure script +# is required. To make it easy to rebuild messages without going through +# reconfigure, a new target messages-clean has been added. +maintainer-clean-local: + rm -f log_messages.cc log_messages.h logimpl_messages.cc logimpl_messages.h + +# To regenerate messages files, one can do: +# +# make messages-clean +# make messages +# +# This is needed only when a .mes file is modified. +messages-clean: maintainer-clean-local + +# Define rule to build logging source files from message file. +@GENERATE_MESSAGES_TRUE@messages: log_messages.cc log_messages.h logimpl_messages.cc logimpl_messages.h +@GENERATE_MESSAGES_TRUE@ @echo Message files regenerated + +@GENERATE_MESSAGES_TRUE@log_messages.cc log_messages.h: log_messages.mes +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/log/log_messages.mes + +@GENERATE_MESSAGES_TRUE@logimpl_messages.cc logimpl_messages.h: logimpl_messages.mes +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/log/logimpl_messages.mes + +@GENERATE_MESSAGES_FALSE@messages log_messages.cc log_messages.h logimpl_messages.cc logimpl_messages.h: +@GENERATE_MESSAGES_FALSE@ @echo Messages generation disabled. Configure with --enable-generate-messages to enable it. + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib/log/buffer_appender_impl.cc b/src/lib/log/buffer_appender_impl.cc new file mode 100644 index 0000000..6ce8d40 --- /dev/null +++ b/src/lib/log/buffer_appender_impl.cc @@ -0,0 +1,96 @@ +// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/buffer_appender_impl.h> + +#include <log4cplus/loglevel.h> +#include <log4cplus/version.h> +#include <boost/scoped_ptr.hpp> +#include <cstdio> + +namespace isc { +namespace log { +namespace internal { + +BufferAppender::~BufferAppender() { + // If there is anything left in the buffer, + // it means no reconfig has been done, and + // we can assume the logging system was either + // never setup, or broke while doing so. + // So dump all that is left to stdout + try { + flushStdout(); + destructorImpl(); + } catch (...) { + // Ok if we can't even seem to dump to stdout, never mind. + } +} + +void +BufferAppender::flushStdout() { + // This does not show a bit of information normal log messages + // do, so perhaps we should try and setup a new logger here + // However, as this is called from a destructor, it may not + // be a good idea; as we can't reliably know whether in what + // state the logger instance is now (or what the specific logger's + // settings were). + LogEventList::const_iterator it; + for (it = stored_.begin(); it != stored_.end(); ++it) { + const std::string level(it->first); + LogEventPtr event(it->second); + std::printf("%s [%s]: %s\n", level.c_str(), + event->getLoggerName().c_str(), + event->getMessage().c_str()); + } + stored_.clear(); +} + +void +BufferAppender::flush() { + LogEventList stored_copy; + stored_.swap(stored_copy); + + LogEventList::const_iterator it; + for (it = stored_copy.begin(); it != stored_copy.end(); ++it) { + LogEventPtr event(it->second); + log4cplus::Logger logger = + log4cplus::Logger::getInstance(event->getLoggerName()); + + logger.log(event->getLogLevel(), event->getMessage()); + } + flushed_ = true; +} + +size_t +BufferAppender::getBufferSize() const { + return (stored_.size()); +} + +void +BufferAppender::append(const log4cplus::spi::InternalLoggingEvent& event) { + if (flushed_) { + isc_throw(LogBufferAddAfterFlush, + "Internal log buffer has been flushed already"); + } + // get a clone, and put the pointer in a shared_ptr in the list +#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0) + std::auto_ptr<log4cplus::spi::InternalLoggingEvent> +#else + std::unique_ptr<log4cplus::spi::InternalLoggingEvent> +#endif + event_aptr = event.clone(); + // Also store the string representation of the log level, to be + // used in flushStdout if necessary + stored_.push_back(LevelAndEvent( + log4cplus::LogLevelManager().toString(event.getLogLevel()), + LogEventPtr(event_aptr.release()))); +} + +} // end namespace internal +} // end namespace log +} // end namespace isc diff --git a/src/lib/log/buffer_appender_impl.h b/src/lib/log/buffer_appender_impl.h new file mode 100644 index 0000000..10290b5 --- /dev/null +++ b/src/lib/log/buffer_appender_impl.h @@ -0,0 +1,110 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOG_BUFFER_H +#define LOG_BUFFER_H + +#include <exceptions/exceptions.h> + +#include <log4cplus/logger.h> +#include <log4cplus/spi/loggingevent.h> +#include <boost/shared_ptr.hpp> + +namespace isc { +namespace log { +namespace internal { + +/// \brief Buffer add after flush +/// +/// This exception is thrown if the log buffer's add() method +/// is called after the log buffer has been flushed; the buffer +/// is only supposed to be used once (until the first time a +/// logger specification is processed) +class LogBufferAddAfterFlush : public isc::Exception { +public: + LogBufferAddAfterFlush(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + +/// Convenience typedef for a pointer to a log event +typedef boost::shared_ptr<log4cplus::spi::InternalLoggingEvent> LogEventPtr; + +/// Convenience typedef for a pair string/logeventptr, the string representing +/// the logger level, as returned by LogLevelManager::toString() at the +/// time of initial logging +typedef std::pair<std::string, LogEventPtr> LevelAndEvent; + +/// Convenience typedef for a vector of LevelAndEvent instances +typedef std::vector<LevelAndEvent> LogEventList; + +/// \brief Buffering Logger Appender +/// +/// This class can be set as an Appender for log4cplus loggers, +/// and is used to store logging events; it simply keeps any +/// event that is passed to \c append(), and will replay them to the +/// logger that they were originally created for when \c flush() is +/// called. +/// +/// The idea is that initially, a program may want to do some logging, +/// but does not know where to yet (for instance because it has yet to +/// read and parse its configuration). Any log messages before this time +/// would normally go to some default (say, stdout), and be lost in the +/// real logging destination. By buffering them (and flushing them once +/// the logger has been configured), these log messages are kept in a +/// consistent place, and are not lost. +/// +/// Given this goal, this class has an extra check; it will raise +/// an exception if \c append() is called after flush(). +/// +/// If the BufferAppender instance is destroyed before being flushed, +/// it will dump any event it has left to stdout. +class BufferAppender : public log4cplus::Appender { +public: + /// \brief Constructor + /// + /// Constructs a BufferAppender that buffers log evens + BufferAppender() : flushed_(false) {} + + /// \brief Destructor + /// + /// Any remaining events are flushed to stdout (there should + /// only be any events remaining if flush() was never called) + virtual ~BufferAppender(); + + /// \brief Close the appender + /// + /// This class has no specialized handling for this method + virtual void close() {} + + /// \brief Flush the internal buffer + /// + /// Events that have been stored (after calls to \c append() + /// are replayed to the logger. Should only be called after + /// new appenders have been set to the logger. + void flush(); + + /// \brief Returns the number of stored logging events + /// + /// Mainly useful for testing + size_t getBufferSize() const; + +protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); +private: + /// \brief Helper for the destructor, flush events to stdout + void flushStdout(); + + LogEventList stored_; + bool flushed_; +}; + +} // end namespace internal +} // end namespace log +} // end namespace isc + +#endif // LOG_BUFFER_H + diff --git a/src/lib/log/compiler/Makefile.am b/src/lib/log/compiler/Makefile.am new file mode 100644 index 0000000..ff414b8 --- /dev/null +++ b/src/lib/log/compiler/Makefile.am @@ -0,0 +1,24 @@ +SUBDIRS = . + +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +if USE_STATIC_LINK +AM_LDFLAGS = -static +endif + +CLEANFILES = *.gcno *.gcda + +if GENERATE_MESSAGES + +bin_PROGRAMS = kea-msg-compiler + +kea_msg_compiler_SOURCES = message.cc +kea_msg_compiler_LDADD = $(top_builddir)/src/lib/log/libkea-log.la +kea_msg_compiler_LDADD += $(top_builddir)/src/lib/util/libkea-util.la +kea_msg_compiler_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +kea_msg_compiler_LDADD += $(LOG4CPLUS_LIBS) + +endif diff --git a/src/lib/log/compiler/Makefile.in b/src/lib/log/compiler/Makefile.in new file mode 100644 index 0000000..38c37b0 --- /dev/null +++ b/src/lib/log/compiler/Makefile.in @@ -0,0 +1,878 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@GENERATE_MESSAGES_TRUE@bin_PROGRAMS = kea-msg-compiler$(EXEEXT) +subdir = src/lib/log/compiler +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \ + $(top_srcdir)/m4macros/ax_cpp11.m4 \ + $(top_srcdir)/m4macros/ax_cpp20.m4 \ + $(top_srcdir)/m4macros/ax_crypto.m4 \ + $(top_srcdir)/m4macros/ax_find_library.m4 \ + $(top_srcdir)/m4macros/ax_gssapi.m4 \ + $(top_srcdir)/m4macros/ax_gtest.m4 \ + $(top_srcdir)/m4macros/ax_isc_rpath.m4 \ + $(top_srcdir)/m4macros/ax_netconf.m4 \ + $(top_srcdir)/m4macros/libtool.m4 \ + $(top_srcdir)/m4macros/ltoptions.m4 \ + $(top_srcdir)/m4macros/ltsugar.m4 \ + $(top_srcdir)/m4macros/ltversion.m4 \ + $(top_srcdir)/m4macros/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__kea_msg_compiler_SOURCES_DIST = message.cc +@GENERATE_MESSAGES_TRUE@am_kea_msg_compiler_OBJECTS = \ +@GENERATE_MESSAGES_TRUE@ message.$(OBJEXT) +kea_msg_compiler_OBJECTS = $(am_kea_msg_compiler_OBJECTS) +am__DEPENDENCIES_1 = +@GENERATE_MESSAGES_TRUE@kea_msg_compiler_DEPENDENCIES = $(top_builddir)/src/lib/log/libkea-log.la \ +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \ +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ +@GENERATE_MESSAGES_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/message.Po +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(kea_msg_compiler_SOURCES) +DIST_SOURCES = $(am__kea_msg_compiler_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_INCLUDES = @BOOST_INCLUDES@ +BOOST_LIBS = @BOOST_LIBS@ +BOTAN_TOOL = @BOTAN_TOOL@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONTRIB_DIR = @CONTRIB_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ +CRYPTO_INCLUDES = @CRYPTO_INCLUDES@ +CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPTO_PACKAGE = @CRYPTO_PACKAGE@ +CRYPTO_RPATH = @CRYPTO_RPATH@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@ +DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@ +DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@ +DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@ +DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@ +DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@ +DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@ +DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@ +DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@ +DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@ +DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@ +DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@ +DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@ +DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@ +DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_INCLUDES = @GTEST_INCLUDES@ +GTEST_LDADD = @GTEST_LDADD@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_SOURCE = @GTEST_SOURCE@ +HAVE_NETCONF = @HAVE_NETCONF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KEA_CXXFLAGS = @KEA_CXXFLAGS@ +KEA_SRCID = @KEA_SRCID@ +KRB5_CONFIG = @KRB5_CONFIG@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@ +LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@ +LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@ +LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@ +LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@ +LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@ +LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@ +LIBYANG_LIBS = @LIBYANG_LIBS@ +LIBYANG_PREFIX = @LIBYANG_PREFIX@ +LIBYANG_VERSION = @LIBYANG_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@ +LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +PERL = @PERL@ +PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PKGPYTHONDIR = @PKGPYTHONDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PLANTUML = @PLANTUML@ +PREMIUM_DIR = @PREMIUM_DIR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SEP = @SEP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINXBUILD = @SPHINXBUILD@ +SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@ +SR_PLUGINS_PATH = @SR_PLUGINS_PATH@ +SR_REPO_PATH = @SR_REPO_PATH@ +STRIP = @STRIP@ +SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@ +SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@ +SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@ +SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@ +SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@ +SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@ +SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@ +SYSREPO_LIBS = @SYSREPO_LIBS@ +SYSREPO_PREFIX = @SYSREPO_PREFIX@ +SYSREPO_VERSION = @SYSREPO_VERSION@ +USE_LCOV = @USE_LCOV@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib \ + $(BOOST_INCLUDES) +AM_CXXFLAGS = $(KEA_CXXFLAGS) +@USE_STATIC_LINK_TRUE@AM_LDFLAGS = -static +CLEANFILES = *.gcno *.gcda +@GENERATE_MESSAGES_TRUE@kea_msg_compiler_SOURCES = message.cc +@GENERATE_MESSAGES_TRUE@kea_msg_compiler_LDADD = $(top_builddir)/src/lib/log/libkea-log.la \ +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \ +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ +@GENERATE_MESSAGES_TRUE@ $(LOG4CPLUS_LIBS) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/log/compiler/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/log/compiler/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +kea-msg-compiler$(EXEEXT): $(kea_msg_compiler_OBJECTS) $(kea_msg_compiler_DEPENDENCIES) $(EXTRA_kea_msg_compiler_DEPENDENCIES) + @rm -f kea-msg-compiler$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(kea_msg_compiler_OBJECTS) $(kea_msg_compiler_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/message.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/message.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib/log/compiler/message.cc b/src/lib/log/compiler/message.cc new file mode 100644 index 0000000..8f19c5a --- /dev/null +++ b/src/lib/log/compiler/message.cc @@ -0,0 +1,543 @@ +// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <cctype> +#include <cstddef> +#include <fstream> +#include <iostream> +#include <string> +#include <vector> + +#include <errno.h> +#include <getopt.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <exceptions/exceptions.h> + +#include <util/filename.h> +#include <util/strutil.h> + +#include <log/log_messages.h> +#include <log/message_dictionary.h> +#include <log/message_exception.h> +#include <log/message_reader.h> + +#include <log/logger.h> + +#include <boost/foreach.hpp> + +using namespace std; +using namespace isc::log; +using namespace isc::util; + +/// \file log/compiler/message.cc +/// \brief Message Compiler +/// +/// \b Overview<BR> +/// This is the program that takes as input a message file and produces: +/// +/// \li A .h file containing message definition +/// \li A .cc file containing code that adds the messages to the program's +/// message dictionary at start-up time. +/// +/// \b Invocation<BR> +/// The program is invoked with the command: +/// +/// <tt>kea-msg-compiler [-v | -h | -d <dir> | <message-file>]</tt> +/// +/// It reads the message file and writes out two files of the same +/// name in the current working directory (unless -d is used) but +/// with extensions of .h and .cc. +/// +/// -v causes it to print the version number and exit. -h prints a +/// help message (and exits). -d <dir> will make it write the +/// output file(s) to dir instead of current working directory + +/// \brief Print Version +/// +/// Prints the program's version number. + +void +version() { + cout << VERSION << "\n"; +} + +/// \brief Print Usage +/// +/// Prints program usage to stdout. + +void +usage() { + cout << + "Usage: kea-msg-compiler [-h] [-v] [-d dir] <message-file>\n" << + "\n" << + "-h Print this message and exit\n" << + "-v Print the program version and exit\n" << + "-d <dir> Place output files in given directory\n" << + "\n" << + "<message-file> is the name of the input message file.\n"; +} + +/// \brief Create Header Sentinel +/// +/// Given the name of a file, create an \#ifdef sentinel name. The name is +/// <name>_<ext>, where <name> is the name of the file, and <ext> +/// is the extension less the leading period. The sentinel will be upper-case. +/// +/// \param file Filename object representing the file. +/// +/// \return Sentinel name + +string +sentinel(Filename& file) { + + string name = file.name(); + string ext = file.extension(); + string sentinel_text = name + "_" + ext.substr(1); + isc::util::str::uppercase(sentinel_text); + return (sentinel_text); +} + +/// \brief Quote String +/// +/// Inserts an escape character (a backslash) prior to any double quote +/// characters. This is used to handle the fact that the input file does not +/// contain quotes, yet the string will be included in a C++ literal string. + +string +quoteString(const string& instring) { + + // Create the output string and reserve the space needed to hold the input + // string. (Most input strings will not contain quotes, so this single + // reservation should be all that is needed.) + string outstring; + outstring.reserve(instring.size()); + + // Iterate through the input string, preceding quotes with a slash. + for (size_t i = 0; i < instring.size(); ++i) { + if (instring[i] == '"') { + outstring += '\\'; + } + outstring += instring[i]; + } + + return (outstring); +} + +/// \brief Sorted Identifiers +/// +/// Given a dictionary, return a vector holding the message IDs in sorted +/// order. +/// +/// \param dictionary Dictionary to examine +/// +/// \return Sorted list of message IDs + +vector<string> +sortedIdentifiers(MessageDictionary& dictionary) { + vector<string> ident; + + for (MessageDictionary::const_iterator i = dictionary.begin(); + i != dictionary.end(); ++i) { + ident.push_back(i->first); + } + sort(ident.begin(), ident.end()); + + return (ident); +} + +/// \brief Split Namespace +/// +/// The $NAMESPACE directive may well specify a namespace in the form a::b. +/// Unfortunately, the C++ "namespace" statement can only accept a single +/// string - to set up the namespace of "a::b" requires two statements, one +/// for "namespace a" and the other for "namespace b". +/// +/// This function returns the set of namespace components as a vector of +/// strings. A vector of one element, containing the empty string, is returned +/// if the anonymous namespace is specified. +/// +/// \param ns Argument to $NAMESPACE (passed by value, as we will be modifying +/// it.) + +vector<string> +splitNamespace(string ns) { + + // Namespaces components are separated by double colon characters - + // convert to single colons. + size_t dcolon; + while ((dcolon = ns.find("::")) != string::npos) { + ns.replace(dcolon, 2, ":"); + } + + // ... and return the vector of namespace components split on the single + // colon. + return (isc::util::str::tokens(ns, ":")); +} + +/// \brief Write Opening Namespace(s) +/// +/// Writes the lines listing the namespaces in use. +void +writeOpeningNamespace(ostream& output, const vector<string>& ns) { + if (!ns.empty()) { + + // Output namespaces in correct order + for (vector<string>::size_type i = 0; i < ns.size(); ++i) { + output << "namespace " << ns[i] << " {\n"; + } + output << "\n"; + } +} + +/// \brief Write Closing Namespace(s) +/// +/// Writes the lines listing the namespaces in use. +void +writeClosingNamespace(ostream& output, const vector<string>& ns) { + if (!ns.empty()) { + for (int i = ns.size() - 1; i >= 0; --i) { + output << "} // namespace " << ns[i] << "\n"; + } + output << "\n"; + } +} + +/// \brief Write Header File +/// +/// Writes the C++ header file containing the symbol definitions. These are +/// "extern" references to definitions in the .cc file. As such, they should +/// take up no space in the module in which they are included, and redundant +/// references should be removed by the compiler. +/// +/// \param file Name of the message file. The header file is written to a +/// file of the same name but with a .h suffix. +/// \param ns_components Namespace in which the definitions are to be placed. +/// An empty string indicates no namespace. +/// \param dictionary Dictionary holding the message definitions. +/// \param output_directory if not null NULL, output files are written +/// to the given directory. If NULL, they are written to the current +/// working directory. +void +writeHeaderFile(const string& file, + const vector<string>& ns_components, + MessageDictionary& dictionary, + const char* output_directory) { + Filename message_file(file); + Filename header_file(Filename(message_file.name()).useAsDefault(".h")); + if (output_directory != NULL) { + header_file.setDirectory(output_directory); + } + + // Text to use as the sentinels. + string sentinel_text = sentinel(header_file); + + // zero out the errno to be safe + errno = 0; + + // Open the output file for writing + ofstream hfile(header_file.fullName().c_str()); + + if (hfile.fail()) { + isc_throw_4(MessageException, "Failed to open output file", + LOG_OPEN_OUTPUT_FAIL, header_file.fullName(), + strerror(errno), 0); + } + + // Write the header preamble. If there is an error, we'll pick it up + // after the last write. + + hfile << + "// File created from " << message_file.fullName() << "\n" << + "\n" << + "#ifndef " << sentinel_text << "\n" << + "#define " << sentinel_text << "\n" << + "\n" << + "#include <log/message_types.h>\n" << + "\n"; + + // Write the message identifiers, bounded by a namespace declaration + writeOpeningNamespace(hfile, ns_components); + + vector<string> idents = sortedIdentifiers(dictionary); + for (vector<string>::const_iterator j = idents.begin(); + j != idents.end(); ++j) { + hfile << "extern const isc::log::MessageID " << *j << ";\n"; + } + hfile << "\n"; + + writeClosingNamespace(hfile, ns_components); + + // ... and finally the postamble + hfile << "#endif // " << sentinel_text << "\n"; + + // Report errors (if any) and exit + if (hfile.fail()) { + isc_throw_4(MessageException, "Error writing to output file", + LOG_WRITE_ERROR, header_file.fullName(), strerror(errno), + 0); + } + + hfile.close(); +} + +/// \brief Convert Non Alpha-Numeric Characters to Underscores +/// +/// Simple function for use in a call to transform +char +replaceNonAlphaNum(char c) { + return (isalnum(c) ? c : '_'); +} + +/// \brief Write Program File +/// +/// Writes the C++ source code file. This defines the text of the message +/// symbols, as well as the initializer object that sets the entries in the +/// global dictionary. +/// +/// The construction of the initializer object loads the dictionary with the +/// message text. However, nothing actually references it. If the initializer +/// were in a file by itself, the lack of things referencing it would cause the +/// linker to ignore it when pulling modules out of the logging library in a +/// static link. By including it in the file with the symbol definitions, the +/// module will get included in the link process to resolve the symbol +/// definitions, and so the initializer object will be included in the final +/// image. (Note that there are no such problems when the logging library is +/// built as a dynamically-linked library: the whole library - including the +/// initializer module - gets mapped into address space when the library is +/// loaded, after which all the initializing code (including the constructors +/// of objects declared outside functions) gets run.) +/// +/// There _may_ be a problem when we come to port this to Windows. Microsoft +/// Visual Studio contains a "Whole Program Optimization" option, where the +/// optimization is done at link-time, not compiler-time. In this it _may_ +/// decide to remove the initializer object because of a lack of references +/// to it. But until BIND-10 is ported to Windows, we won't know. +/// +/// \param file Name of the message file. The header file is written to a +/// file of the same name but with a .h suffix. +/// \param ns_components Namespace in which the definitions are to be placed. +/// An empty string indicates no namespace. +/// \param dictionary Dictionary holding the message definitions. +/// \param output_directory if not null NULL, output files are written +/// to the given directory. If NULL, they are written to the current +/// working directory. +void +writeProgramFile(const string& file, + const vector<string>& ns_components, + MessageDictionary& dictionary, + const char* output_directory) { + Filename message_file(file); + Filename program_file(Filename(message_file.name()).useAsDefault(".cc")); + if (output_directory) { + program_file.setDirectory(output_directory); + } + + // zero out the errno to be safe + errno = 0; + + // Open the output file for writing + ofstream ccfile(program_file.fullName().c_str()); + + if (ccfile.fail()) { + isc_throw_4(MessageException, "Error opening output file", + LOG_OPEN_OUTPUT_FAIL, program_file.fullName(), + strerror(errno), 0); + } + + // Write the preamble. If there is an error, we'll pick it up after + // the last write. + + ccfile << + "// File created from " << message_file.fullName() << "\n" << + "\n" << + "#include <cstddef>\n" << + "#include <log/message_types.h>\n" << + "#include <log/message_initializer.h>\n" << + "\n"; + + // Declare the message symbols themselves. + + writeOpeningNamespace(ccfile, ns_components); + + vector<string> idents = sortedIdentifiers(dictionary); + for (vector<string>::const_iterator j = idents.begin(); + j != idents.end(); ++j) { + ccfile << "extern const isc::log::MessageID " << *j << + " = \"" << *j << "\";\n"; + } + ccfile << "\n"; + + writeClosingNamespace(ccfile, ns_components); + + // Now the code for the message initialization. + + ccfile << + "namespace {\n" << + "\n" << + "const char* values[] = {\n"; + + // Output the identifiers and the associated text. + idents = sortedIdentifiers(dictionary); + for (vector<string>::const_iterator i = idents.begin(); + i != idents.end(); ++i) { + ccfile << " \"" << *i << "\", \"" << + quoteString(dictionary.getText(*i)) << "\",\n"; + } + + // ... and the postamble + ccfile << + " NULL\n" << + "};\n" << + "\n" << + "const isc::log::MessageInitializer initializer(values);\n" << + "\n" << + "} // Anonymous namespace\n" << + "\n"; + + // Report errors (if any) and exit + if (ccfile.fail()) { + isc_throw_4(MessageException, "Error writing to output file", + LOG_WRITE_ERROR, program_file.fullName(), strerror(errno), + 0); + } + + ccfile.close(); +} + +/// \brief Error and exit if there are duplicate entries +/// +/// If the input file contained duplicate message IDs, we print an +/// error for each of them, then exit the program with a non-0 value. +/// +/// \param reader Message Reader used to read the file +void +errorDuplicates(MessageReader& reader) { + + // Get the duplicates (the overflow) and, if present, sort them into some + // order and remove those which occur more than once (which mean that they + // occur more than twice in the input file). + MessageReader::MessageIDCollection duplicates = reader.getNotAdded(); + if (!duplicates.empty()) { + cout << "Error: the following duplicate IDs were found:\n"; + + sort(duplicates.begin(), duplicates.end()); + MessageReader::MessageIDCollection::iterator new_end = + unique(duplicates.begin(), duplicates.end()); + for (MessageReader::MessageIDCollection::iterator i = duplicates.begin(); + i != new_end; ++i) { + cout << " " << *i << "\n"; + } + exit(1); + } +} + +/// \brief Main Program +/// +/// Parses the options then dispatches to the appropriate function. See the +/// main file header for the invocation. +int +main(int argc, char* argv[]) { + + const char* soptions = "hvpd:"; // Short options + + optind = 1; // Ensure we start a new scan + int opt; // Value of the option + + const char *output_directory = NULL; + + while ((opt = getopt(argc, argv, soptions)) != -1) { + switch (opt) { + case 'd': + output_directory = optarg; + break; + + case 'h': + usage(); + return (0); + + case 'v': + version(); + return (0); + + default: + // A message will have already been output about the error. + return (1); + } + } + + // Do we have the message file? + if (optind < (argc - 1)) { + cout << "Error: excess arguments in command line\n"; + usage(); + return (1); + } else if (optind >= argc) { + cout << "Error: missing message file\n"; + usage(); + return (1); + } + string message_file = argv[optind]; + + try { + // Have identified the file, so process it. First create a local + // dictionary into which the data will be put. + MessageDictionary dictionary; + + // Read the data into it. + MessageReader reader(&dictionary); + reader.readFile(message_file); + + // Error (and quit) if there are of any duplicates encountered. + errorDuplicates(reader); + + // Get the namespace into which the message definitions will be put and + // split it into components. + vector<string> ns_components = + splitNamespace(reader.getNamespace()); + + // Write the header file. + writeHeaderFile(message_file, ns_components, dictionary, + output_directory); + + // Write the file that defines the message symbols and text + writeProgramFile(message_file, ns_components, dictionary, + output_directory); + + } catch (const MessageException& e) { + // Create an error message from the ID and the text + const MessageDictionaryPtr& global = MessageDictionary::globalDictionary(); + string text = e.id(); + text += ", "; + text += global->getText(e.id()); + // Format with arguments + vector<string> args(e.arguments()); + for (size_t i(0); i < args.size(); ++ i) { + try { + replacePlaceholder(text, args[i], i + 1); + } catch (...) { + // Error in error handling: nothing right to do... + } + } + + cerr << text << "\n"; + + return (1); + } catch (const std::exception& ex) { + cerr << "Fatal error: " << ex.what() << "\n"; + + return (1); + } catch (...) { + cerr << "Fatal error\n"; + + return (1); + } + + return (0); +} diff --git a/src/lib/log/interprocess/Makefile.am b/src/lib/log/interprocess/Makefile.am new file mode 100644 index 0000000..676af42 --- /dev/null +++ b/src/lib/log/interprocess/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = . tests + +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib +AM_CPPFLAGS += -DLOCKFILE_DIR=\"$(localstatedir)/run/$(PACKAGE_NAME)\" +AM_CPPFLAGS += $(BOOST_INCLUDES) + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +CLEANFILES = *.gcno *.gcda + +noinst_LTLIBRARIES = libkea-log_interprocess.la + +libkea_log_interprocess_la_SOURCES = interprocess_sync.h +libkea_log_interprocess_la_SOURCES += interprocess_sync_file.h +libkea_log_interprocess_la_SOURCES += interprocess_sync_file.cc +libkea_log_interprocess_la_SOURCES += interprocess_sync_null.h +libkea_log_interprocess_la_SOURCES += interprocess_sync_null.cc + +libkea_log_interprocess_la_LIBADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la + +EXTRA_DIST = README diff --git a/src/lib/log/interprocess/Makefile.in b/src/lib/log/interprocess/Makefile.in new file mode 100644 index 0000000..95c3b6e --- /dev/null +++ b/src/lib/log/interprocess/Makefile.in @@ -0,0 +1,854 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib/log/interprocess +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \ + $(top_srcdir)/m4macros/ax_cpp11.m4 \ + $(top_srcdir)/m4macros/ax_cpp20.m4 \ + $(top_srcdir)/m4macros/ax_crypto.m4 \ + $(top_srcdir)/m4macros/ax_find_library.m4 \ + $(top_srcdir)/m4macros/ax_gssapi.m4 \ + $(top_srcdir)/m4macros/ax_gtest.m4 \ + $(top_srcdir)/m4macros/ax_isc_rpath.m4 \ + $(top_srcdir)/m4macros/ax_netconf.m4 \ + $(top_srcdir)/m4macros/libtool.m4 \ + $(top_srcdir)/m4macros/ltoptions.m4 \ + $(top_srcdir)/m4macros/ltsugar.m4 \ + $(top_srcdir)/m4macros/ltversion.m4 \ + $(top_srcdir)/m4macros/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libkea_log_interprocess_la_DEPENDENCIES = \ + $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +am_libkea_log_interprocess_la_OBJECTS = interprocess_sync_file.lo \ + interprocess_sync_null.lo +libkea_log_interprocess_la_OBJECTS = \ + $(am_libkea_log_interprocess_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/interprocess_sync_file.Plo \ + ./$(DEPDIR)/interprocess_sync_null.Plo +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libkea_log_interprocess_la_SOURCES) +DIST_SOURCES = $(libkea_log_interprocess_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_INCLUDES = @BOOST_INCLUDES@ +BOOST_LIBS = @BOOST_LIBS@ +BOTAN_TOOL = @BOTAN_TOOL@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONTRIB_DIR = @CONTRIB_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ +CRYPTO_INCLUDES = @CRYPTO_INCLUDES@ +CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPTO_PACKAGE = @CRYPTO_PACKAGE@ +CRYPTO_RPATH = @CRYPTO_RPATH@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@ +DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@ +DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@ +DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@ +DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@ +DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@ +DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@ +DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@ +DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@ +DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@ +DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@ +DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@ +DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@ +DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@ +DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_INCLUDES = @GTEST_INCLUDES@ +GTEST_LDADD = @GTEST_LDADD@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_SOURCE = @GTEST_SOURCE@ +HAVE_NETCONF = @HAVE_NETCONF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KEA_CXXFLAGS = @KEA_CXXFLAGS@ +KEA_SRCID = @KEA_SRCID@ +KRB5_CONFIG = @KRB5_CONFIG@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@ +LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@ +LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@ +LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@ +LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@ +LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@ +LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@ +LIBYANG_LIBS = @LIBYANG_LIBS@ +LIBYANG_PREFIX = @LIBYANG_PREFIX@ +LIBYANG_VERSION = @LIBYANG_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@ +LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +PERL = @PERL@ +PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PKGPYTHONDIR = @PKGPYTHONDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PLANTUML = @PLANTUML@ +PREMIUM_DIR = @PREMIUM_DIR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SEP = @SEP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINXBUILD = @SPHINXBUILD@ +SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@ +SR_PLUGINS_PATH = @SR_PLUGINS_PATH@ +SR_REPO_PATH = @SR_REPO_PATH@ +STRIP = @STRIP@ +SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@ +SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@ +SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@ +SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@ +SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@ +SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@ +SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@ +SYSREPO_LIBS = @SYSREPO_LIBS@ +SYSREPO_PREFIX = @SYSREPO_PREFIX@ +SYSREPO_VERSION = @SYSREPO_VERSION@ +USE_LCOV = @USE_LCOV@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . tests +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib \ + -DLOCKFILE_DIR=\"$(localstatedir)/run/$(PACKAGE_NAME)\" \ + $(BOOST_INCLUDES) +AM_CXXFLAGS = $(KEA_CXXFLAGS) +CLEANFILES = *.gcno *.gcda +noinst_LTLIBRARIES = libkea-log_interprocess.la +libkea_log_interprocess_la_SOURCES = interprocess_sync.h \ + interprocess_sync_file.h interprocess_sync_file.cc \ + interprocess_sync_null.h interprocess_sync_null.cc +libkea_log_interprocess_la_LIBADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +EXTRA_DIST = README +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/log/interprocess/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/log/interprocess/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libkea-log_interprocess.la: $(libkea_log_interprocess_la_OBJECTS) $(libkea_log_interprocess_la_DEPENDENCIES) $(EXTRA_libkea_log_interprocess_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(libkea_log_interprocess_la_OBJECTS) $(libkea_log_interprocess_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interprocess_sync_file.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interprocess_sync_null.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/interprocess_sync_file.Plo + -rm -f ./$(DEPDIR)/interprocess_sync_null.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/interprocess_sync_file.Plo + -rm -f ./$(DEPDIR)/interprocess_sync_null.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib/log/interprocess/README b/src/lib/log/interprocess/README new file mode 100644 index 0000000..6f48dc6 --- /dev/null +++ b/src/lib/log/interprocess/README @@ -0,0 +1,13 @@ +The files in this directory implement a helper sub-library of the +inter process locking for the log library. We use our own locks +because such locks are only available in relatively recent versions of +log4cplus. Also (against our usual practice) we somehow re-invented +an in-house version of such a general purpose library rather than +existing proven tools such as boost::interprocess. While we decided +to go with the in-house version for the log library at least until we +completely switch to log4cplus's native lock support, no other BIND 10 +module should use this; they should use existing external +tools/libraries. + +This sub-library is therefore "hidden" here. As such, none of these +files should be installed. diff --git a/src/lib/log/interprocess/interprocess_sync.h b/src/lib/log/interprocess/interprocess_sync.h new file mode 100644 index 0000000..0692ee1 --- /dev/null +++ b/src/lib/log/interprocess/interprocess_sync.h @@ -0,0 +1,143 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef INTERPROCESS_SYNC_H +#define INTERPROCESS_SYNC_H + +#include <string> + +namespace isc { +namespace log { +namespace interprocess { + +class InterprocessSyncLocker; // forward declaration + +/// \brief Interprocess Sync Class +/// +/// This class specifies an interface for mutual exclusion among +/// co-operating processes. This is an abstract class and a real +/// implementation such as InterprocessSyncFile should be used +/// in code. Usage is as follows: +/// +/// 1. Client instantiates a sync object of an implementation (such as +/// InterprocessSyncFile). +/// 2. Client then creates an automatic (stack) object of +/// InterprocessSyncLocker around the sync object. Such an object +/// destroys itself and releases any acquired lock when it goes out of extent. +/// 3. Client calls lock() method on the InterprocessSyncLocker. +/// 4. Client performs task that needs mutual exclusion. +/// 5. Client frees lock with unlock(), or simply returns from the basic +/// block which forms the scope for the InterprocessSyncLocker. +/// +/// NOTE: All implementations of InterprocessSync should keep the +/// is_locked_ member variable updated whenever their +/// lock()/tryLock()/unlock() implementations are called. +class InterprocessSync { + // InterprocessSyncLocker is the only code outside this class that + // should be allowed to call the lock(), tryLock() and unlock() + // methods. + friend class InterprocessSyncLocker; + +public: + /// \brief Constructor + /// + /// Creates an interprocess synchronization object + /// + /// \param task_name Name of the synchronization task. This has to be + /// identical among the various processes that need to be + /// synchronized for the same task. + InterprocessSync(const std::string& task_name) : + task_name_(task_name), is_locked_(false) + {} + + /// \brief Destructor + virtual ~InterprocessSync() {} + +protected: + /// \brief Acquire the lock (blocks if something else has acquired a + /// lock on the same task name) + /// + /// \return Returns true if the lock was acquired, false otherwise. + virtual bool lock() = 0; + + /// \brief Try to acquire a lock (doesn't block) + /// + /// \return Returns true if the lock was acquired, false otherwise. + virtual bool tryLock() = 0; + + /// \brief Release the lock + /// + /// \return Returns true if the lock was released, false otherwise. + virtual bool unlock() = 0; + + const std::string task_name_; ///< The task name + bool is_locked_; ///< Is the lock taken? +}; + +/// \brief Interprocess Sync Locker Class +/// +/// This class is used for making automatic stack objects to manage +/// locks that are released automatically when the block is exited +/// (RAII). It is meant to be used along with InterprocessSync objects. See +/// the description of InterprocessSync. +class InterprocessSyncLocker { +public: + /// \brief Constructor + /// + /// Creates a lock manager around a interprocess synchronization object + /// + /// \param sync The sync object which has to be locked/unlocked by + /// this locker object. + InterprocessSyncLocker(InterprocessSync& sync) : + sync_(sync) + {} + + /// \brief Destructor + ~InterprocessSyncLocker() { + if (isLocked()) + unlock(); + } + + /// \brief Acquire the lock (blocks if something else has acquired a + /// lock on the same task name) + /// + /// \return Returns true if the lock was acquired, false otherwise. + bool lock() { + return (sync_.lock()); + } + + /// \brief Try to acquire a lock (doesn't block) + /// + /// \return Returns true if a new lock could be acquired, false + /// otherwise. + bool tryLock() { + return (sync_.tryLock()); + } + + /// \brief Check if the lock is taken + /// + /// \return Returns true if a lock is currently acquired, false + /// otherwise. + bool isLocked() const { + return (sync_.is_locked_); + } + + /// \brief Release the lock + /// + /// \return Returns true if the lock was released, false otherwise. + bool unlock() { + return (sync_.unlock()); + } + +protected: + InterprocessSync& sync_; ///< Ref to underlying sync object +}; + +} // namespace interprocess +} // namespace log +} // namespace isc + +#endif // INTERPROCESS_SYNC_H diff --git a/src/lib/log/interprocess/interprocess_sync_file.cc b/src/lib/log/interprocess/interprocess_sync_file.cc new file mode 100644 index 0000000..ed6a5b7 --- /dev/null +++ b/src/lib/log/interprocess/interprocess_sync_file.cc @@ -0,0 +1,132 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// This file requires LOCKFILE_DIR to be defined. It points to the default +// directory where lockfile will be created. + +#include <config.h> + +#include <log/interprocess/interprocess_sync_file.h> + +#include <string> +#include <cerrno> +#include <cstring> +#include <sstream> +#include <iostream> + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +namespace isc { +namespace log { +namespace interprocess { + +InterprocessSyncFile::~InterprocessSyncFile() { + if (fd_ != -1) { + // This will also release any applied locks. + close(fd_); + // The lockfile will continue to exist, and we must not delete + // it. + } +} + +bool +InterprocessSyncFile::do_lock(int cmd, short l_type) { + // Open lock file only when necessary (i.e., here). This is so that + // if a default InterprocessSync object is replaced with another + // implementation, it doesn't attempt any opens. + if (fd_ == -1) { + std::string lockfile_path = LOCKFILE_DIR; + + const char* const env = getenv("KEA_LOCKFILE_DIR"); + if (env != NULL) { + lockfile_path = env; + } + + lockfile_path += "/" + task_name_ + "_lockfile"; + + // Open the lockfile in the constructor so it doesn't do the access + // checks every time a message is logged. + const mode_t mode = umask(S_IXUSR | S_IXGRP | S_IXOTH); // 0111 + fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); // 0660 + umask(mode); + + if (fd_ == -1) { + std::stringstream tmp; + + // We failed to create a lockfile. This means that the logging + // system is unusable. We need to report the issue using plain + // print to stderr. + tmp << "Unable to use interprocess sync lockfile (" + << std::strerror(errno) << "): " << lockfile_path; + std::cerr << tmp.str() << std::endl; + + // And then throw exception as usual. + isc_throw(InterprocessSyncFileError, tmp.str()); + } + } + + struct flock lock; + + memset(&lock, 0, sizeof (lock)); + lock.l_type = l_type; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + + return (fcntl(fd_, cmd, &lock) == 0); +} + +bool +InterprocessSyncFile::lock() { + if (is_locked_) { + return (true); + } + + if (do_lock(F_SETLKW, F_WRLCK)) { + is_locked_ = true; + return (true); + } + + return (false); +} + +bool +InterprocessSyncFile::tryLock() { + if (is_locked_) { + return (true); + } + + if (do_lock(F_SETLK, F_WRLCK)) { + is_locked_ = true; + return (true); + } + + return (false); +} + +bool +InterprocessSyncFile::unlock() { + if (!is_locked_) { + return (true); + } + + if (do_lock(F_SETLKW, F_UNLCK)) { + is_locked_ = false; + return (true); + } + + return (false); +} + +} // namespace interprocess +} // namespace log +} // namespace isc diff --git a/src/lib/log/interprocess/interprocess_sync_file.h b/src/lib/log/interprocess/interprocess_sync_file.h new file mode 100644 index 0000000..9613e7f --- /dev/null +++ b/src/lib/log/interprocess/interprocess_sync_file.h @@ -0,0 +1,85 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef INTERPROCESS_SYNC_FILE_H +#define INTERPROCESS_SYNC_FILE_H + +#include <log/interprocess/interprocess_sync.h> +#include <exceptions/exceptions.h> + +namespace isc { +namespace log { +namespace interprocess { + +/// \brief InterprocessSyncFileError +/// +/// Exception that is thrown if it's not possible to open the +/// lock file. +class InterprocessSyncFileError : public Exception { +public: + InterprocessSyncFileError(const char* file, size_t line, + const char* what) : + isc::Exception(file, line, what) {} +}; + +/// \brief File-based Interprocess Sync Class +/// +/// This class specifies a concrete implementation for a file-based +/// interprocess synchronization mechanism. Please see the +/// InterprocessSync class documentation for usage. +/// +/// An InterprocessSyncFileError exception may be thrown if there is an +/// issue opening the lock file. +/// +/// Lock files are created typically in the local state directory +/// (var). They are typically named like "<task_name>_lockfile". +/// This implementation opens lock files lazily (only when +/// necessary). It also leaves the lock files lying around as multiple +/// processes may have locks on them. +class InterprocessSyncFile : public InterprocessSync { +public: + /// \brief Constructor + /// + /// Creates a file-based interprocess synchronization object + /// + /// \param task_name Name of the synchronization task. This has to be + /// identical among the various processes that need to be + /// synchronized for the same task. + InterprocessSyncFile(const std::string& task_name) : + InterprocessSync(task_name), fd_(-1) + {} + + /// \brief Destructor + virtual ~InterprocessSyncFile(); + +protected: + /// \brief Acquire the lock (blocks if something else has acquired a + /// lock on the same task name) + /// + /// \return Returns true if the lock was acquired, false otherwise. + bool lock(); + + /// \brief Try to acquire a lock (doesn't block) + /// + /// \return Returns true if the lock was acquired, false otherwise. + bool tryLock(); + + /// \brief Release the lock + /// + /// \return Returns true if the lock was released, false otherwise. + bool unlock(); + +private: + bool do_lock(int cmd, short l_type); + + int fd_; ///< The descriptor for the open file +}; + +} // namespace interprocess +} // namespace log +} // namespace isc + +#endif // INTERPROCESS_SYNC_FILE_H diff --git a/src/lib/log/interprocess/interprocess_sync_null.cc b/src/lib/log/interprocess/interprocess_sync_null.cc new file mode 100644 index 0000000..ccd9e32 --- /dev/null +++ b/src/lib/log/interprocess/interprocess_sync_null.cc @@ -0,0 +1,38 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/interprocess/interprocess_sync_null.h> + +namespace isc { +namespace log { +namespace interprocess { + +InterprocessSyncNull::~InterprocessSyncNull() { +} + +bool +InterprocessSyncNull::lock() { + is_locked_ = true; + return (true); +} + +bool +InterprocessSyncNull::tryLock() { + is_locked_ = true; + return (true); +} + +bool +InterprocessSyncNull::unlock() { + is_locked_ = false; + return (true); +} + +} // namespace interprocess +} // namespace log +} // namespace isc diff --git a/src/lib/log/interprocess/interprocess_sync_null.h b/src/lib/log/interprocess/interprocess_sync_null.h new file mode 100644 index 0000000..8b0c57b --- /dev/null +++ b/src/lib/log/interprocess/interprocess_sync_null.h @@ -0,0 +1,58 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef INTERPROCESS_SYNC_NULL_H +#define INTERPROCESS_SYNC_NULL_H + +#include <log/interprocess/interprocess_sync.h> + +namespace isc { +namespace log { +namespace interprocess { + +/// \brief Null Interprocess Sync Class +/// +/// This class specifies a concrete implementation for a null (no effect) +/// interprocess synchronization mechanism. Please see the +/// InterprocessSync class documentation for usage. +class InterprocessSyncNull : public InterprocessSync { +public: + /// \brief Constructor + /// + /// Creates a null interprocess synchronization object + /// + /// \param task_name Name of the synchronization task. This has to be + /// identical among the various processes that need to be + /// synchronized for the same task. + InterprocessSyncNull(const std::string& task_name) : + InterprocessSync(task_name) + {} + + /// \brief Destructor + virtual ~InterprocessSyncNull(); + +protected: + /// \brief Acquire the lock (never blocks) + /// + /// \return Always returns true + bool lock(); + + /// \brief Try to acquire a lock (doesn't block) + /// + /// \return Always returns true + bool tryLock(); + + /// \brief Release the lock + /// + /// \return Always returns true + bool unlock(); +}; + +} // namespace interprocess +} // namespace log +} // namespace isc + +#endif // INTERPROCESS_SYNC_NULL_H diff --git a/src/lib/log/interprocess/tests/Makefile.am b/src/lib/log/interprocess/tests/Makefile.am new file mode 100644 index 0000000..a51a4b3 --- /dev/null +++ b/src/lib/log/interprocess/tests/Makefile.am @@ -0,0 +1,36 @@ +SUBDIRS = . + +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) +# XXX: we'll pollute the top builddir for creating a temporary test file +# used to bind a UNIX domain socket so we can minimize the risk of exceeding +# the limit of file name path size. +AM_CPPFLAGS += -DTEST_DATA_TOPBUILDDIR=\"$(abs_top_builddir)\" +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +if USE_STATIC_LINK +AM_LDFLAGS = -static +endif + +CLEANFILES = *.gcno *.gcda + +TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) + +TESTS = +if HAVE_GTEST +TESTS += run_unittests +run_unittests_SOURCES = run_unittests.cc +run_unittests_SOURCES += interprocess_sync_file_unittest.cc +run_unittests_SOURCES += interprocess_sync_null_unittest.cc + +run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) + +run_unittests_LDADD = $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la +run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la +run_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la +run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +run_unittests_LDADD += $(GTEST_LDADD) +endif + +noinst_PROGRAMS = $(TESTS) diff --git a/src/lib/log/interprocess/tests/Makefile.in b/src/lib/log/interprocess/tests/Makefile.in new file mode 100644 index 0000000..dcbb165 --- /dev/null +++ b/src/lib/log/interprocess/tests/Makefile.in @@ -0,0 +1,1024 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = $(am__EXEEXT_1) +@HAVE_GTEST_TRUE@am__append_1 = run_unittests +noinst_PROGRAMS = $(am__EXEEXT_2) +subdir = src/lib/log/interprocess/tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \ + $(top_srcdir)/m4macros/ax_cpp11.m4 \ + $(top_srcdir)/m4macros/ax_cpp20.m4 \ + $(top_srcdir)/m4macros/ax_crypto.m4 \ + $(top_srcdir)/m4macros/ax_find_library.m4 \ + $(top_srcdir)/m4macros/ax_gssapi.m4 \ + $(top_srcdir)/m4macros/ax_gtest.m4 \ + $(top_srcdir)/m4macros/ax_isc_rpath.m4 \ + $(top_srcdir)/m4macros/ax_netconf.m4 \ + $(top_srcdir)/m4macros/libtool.m4 \ + $(top_srcdir)/m4macros/ltoptions.m4 \ + $(top_srcdir)/m4macros/ltsugar.m4 \ + $(top_srcdir)/m4macros/ltversion.m4 \ + $(top_srcdir)/m4macros/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_GTEST_TRUE@am__EXEEXT_1 = run_unittests$(EXEEXT) +am__EXEEXT_2 = $(am__EXEEXT_1) +PROGRAMS = $(noinst_PROGRAMS) +am__run_unittests_SOURCES_DIST = run_unittests.cc \ + interprocess_sync_file_unittest.cc \ + interprocess_sync_null_unittest.cc +@HAVE_GTEST_TRUE@am_run_unittests_OBJECTS = \ +@HAVE_GTEST_TRUE@ run_unittests-run_unittests.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-interprocess_sync_file_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-interprocess_sync_null_unittest.$(OBJEXT) +run_unittests_OBJECTS = $(am_run_unittests_OBJECTS) +am__DEPENDENCIES_1 = +@HAVE_GTEST_TRUE@run_unittests_DEPENDENCIES = $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/unittests/libutil_unittests.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ +@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +run_unittests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(run_unittests_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + ./$(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Po \ + ./$(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Po \ + ./$(DEPDIR)/run_unittests-run_unittests.Po +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(run_unittests_SOURCES) +DIST_SOURCES = $(am__run_unittests_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_INCLUDES = @BOOST_INCLUDES@ +BOOST_LIBS = @BOOST_LIBS@ +BOTAN_TOOL = @BOTAN_TOOL@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONTRIB_DIR = @CONTRIB_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ +CRYPTO_INCLUDES = @CRYPTO_INCLUDES@ +CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPTO_PACKAGE = @CRYPTO_PACKAGE@ +CRYPTO_RPATH = @CRYPTO_RPATH@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@ +DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@ +DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@ +DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@ +DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@ +DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@ +DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@ +DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@ +DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@ +DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@ +DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@ +DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@ +DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@ +DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@ +DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_INCLUDES = @GTEST_INCLUDES@ +GTEST_LDADD = @GTEST_LDADD@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_SOURCE = @GTEST_SOURCE@ +HAVE_NETCONF = @HAVE_NETCONF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KEA_CXXFLAGS = @KEA_CXXFLAGS@ +KEA_SRCID = @KEA_SRCID@ +KRB5_CONFIG = @KRB5_CONFIG@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@ +LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@ +LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@ +LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@ +LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@ +LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@ +LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@ +LIBYANG_LIBS = @LIBYANG_LIBS@ +LIBYANG_PREFIX = @LIBYANG_PREFIX@ +LIBYANG_VERSION = @LIBYANG_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@ +LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +PERL = @PERL@ +PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PKGPYTHONDIR = @PKGPYTHONDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PLANTUML = @PLANTUML@ +PREMIUM_DIR = @PREMIUM_DIR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SEP = @SEP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINXBUILD = @SPHINXBUILD@ +SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@ +SR_PLUGINS_PATH = @SR_PLUGINS_PATH@ +SR_REPO_PATH = @SR_REPO_PATH@ +STRIP = @STRIP@ +SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@ +SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@ +SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@ +SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@ +SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@ +SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@ +SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@ +SYSREPO_LIBS = @SYSREPO_LIBS@ +SYSREPO_PREFIX = @SYSREPO_PREFIX@ +SYSREPO_VERSION = @SYSREPO_VERSION@ +USE_LCOV = @USE_LCOV@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . +# XXX: we'll pollute the top builddir for creating a temporary test file +# used to bind a UNIX domain socket so we can minimize the risk of exceeding +# the limit of file name path size. +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib \ + $(BOOST_INCLUDES) \ + -DTEST_DATA_TOPBUILDDIR=\"$(abs_top_builddir)\" +AM_CXXFLAGS = $(KEA_CXXFLAGS) +@USE_STATIC_LINK_TRUE@AM_LDFLAGS = -static +CLEANFILES = *.gcno *.gcda +TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) +@HAVE_GTEST_TRUE@run_unittests_SOURCES = run_unittests.cc \ +@HAVE_GTEST_TRUE@ interprocess_sync_file_unittest.cc \ +@HAVE_GTEST_TRUE@ interprocess_sync_null_unittest.cc +@HAVE_GTEST_TRUE@run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +@HAVE_GTEST_TRUE@run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) +@HAVE_GTEST_TRUE@run_unittests_LDADD = $(top_builddir)/src/lib/log/interprocess/libkea-log_interprocess.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/unittests/libutil_unittests.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ +@HAVE_GTEST_TRUE@ $(GTEST_LDADD) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/log/interprocess/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/log/interprocess/tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +run_unittests$(EXEEXT): $(run_unittests_OBJECTS) $(run_unittests_DEPENDENCIES) $(EXTRA_run_unittests_DEPENDENCIES) + @rm -f run_unittests$(EXEEXT) + $(AM_V_CXXLD)$(run_unittests_LINK) $(run_unittests_OBJECTS) $(run_unittests_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-run_unittests.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +run_unittests-run_unittests.o: run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.o -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_unittests-run_unittests.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc + +run_unittests-run_unittests.obj: run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.obj -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_unittests-run_unittests.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi` + +run_unittests-interprocess_sync_file_unittest.o: interprocess_sync_file_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-interprocess_sync_file_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Tpo -c -o run_unittests-interprocess_sync_file_unittest.o `test -f 'interprocess_sync_file_unittest.cc' || echo '$(srcdir)/'`interprocess_sync_file_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Tpo $(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='interprocess_sync_file_unittest.cc' object='run_unittests-interprocess_sync_file_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-interprocess_sync_file_unittest.o `test -f 'interprocess_sync_file_unittest.cc' || echo '$(srcdir)/'`interprocess_sync_file_unittest.cc + +run_unittests-interprocess_sync_file_unittest.obj: interprocess_sync_file_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-interprocess_sync_file_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Tpo -c -o run_unittests-interprocess_sync_file_unittest.obj `if test -f 'interprocess_sync_file_unittest.cc'; then $(CYGPATH_W) 'interprocess_sync_file_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/interprocess_sync_file_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Tpo $(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='interprocess_sync_file_unittest.cc' object='run_unittests-interprocess_sync_file_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-interprocess_sync_file_unittest.obj `if test -f 'interprocess_sync_file_unittest.cc'; then $(CYGPATH_W) 'interprocess_sync_file_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/interprocess_sync_file_unittest.cc'; fi` + +run_unittests-interprocess_sync_null_unittest.o: interprocess_sync_null_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-interprocess_sync_null_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Tpo -c -o run_unittests-interprocess_sync_null_unittest.o `test -f 'interprocess_sync_null_unittest.cc' || echo '$(srcdir)/'`interprocess_sync_null_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Tpo $(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='interprocess_sync_null_unittest.cc' object='run_unittests-interprocess_sync_null_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-interprocess_sync_null_unittest.o `test -f 'interprocess_sync_null_unittest.cc' || echo '$(srcdir)/'`interprocess_sync_null_unittest.cc + +run_unittests-interprocess_sync_null_unittest.obj: interprocess_sync_null_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-interprocess_sync_null_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Tpo -c -o run_unittests-interprocess_sync_null_unittest.obj `if test -f 'interprocess_sync_null_unittest.cc'; then $(CYGPATH_W) 'interprocess_sync_null_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/interprocess_sync_null_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Tpo $(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='interprocess_sync_null_unittest.cc' object='run_unittests-interprocess_sync_null_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-interprocess_sync_null_unittest.obj `if test -f 'interprocess_sync_null_unittest.cc'; then $(CYGPATH_W) 'interprocess_sync_null_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/interprocess_sync_null_unittest.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/run_unittests-interprocess_sync_file_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-interprocess_sync_null_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) check-am install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-TESTS check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib/log/interprocess/tests/interprocess_sync_file_unittest.cc b/src/lib/log/interprocess/tests/interprocess_sync_file_unittest.cc new file mode 100644 index 0000000..d80f288 --- /dev/null +++ b/src/lib/log/interprocess/tests/interprocess_sync_file_unittest.cc @@ -0,0 +1,153 @@ +// Copyright (C) 2012-2015,2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/interprocess/interprocess_sync_file.h> + +#include <util/unittests/check_valgrind.h> +#include <util/unittests/interprocess_util.h> +#include <gtest/gtest.h> +#include <unistd.h> + +using namespace std; +using namespace isc::log::interprocess; +using isc::util::unittests::parentReadState; + +namespace { +TEST(InterprocessSyncFileTest, BadFile) { + InterprocessSyncFile sync("/no-such--dir/or--file"); + InterprocessSyncLocker locker(sync); + + EXPECT_FALSE(locker.isLocked()); + ASSERT_THROW(locker.lock(), InterprocessSyncFileError); +} + +TEST(InterprocessSyncFileTest, TestLock) { + InterprocessSyncFile sync("test"); + InterprocessSyncLocker locker(sync); + + EXPECT_FALSE(locker.isLocked()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.isLocked()); + + if (!isc::util::unittests::runningOnValgrind()) { + + int fds[2]; + + // Here, we check that a lock has been taken by forking and + // checking from the child that a lock exists. This has to be + // done from a separate process as we test by trying to lock the + // range again on the lock file. The lock attempt would pass if + // done from the same process for the granted range. The lock + // attempt must fail to pass our check. + + EXPECT_EQ(0, pipe(fds)); + + if (fork() == 0) { + unsigned char locked = 0; + // Child writes to pipe + close(fds[0]); + + InterprocessSyncFile sync2("test"); + InterprocessSyncLocker locker2(sync2); + + if (!locker2.tryLock()) { + EXPECT_FALSE(locker2.isLocked()); + locked = 1; + } else { + EXPECT_TRUE(locker2.isLocked()); + } + + ssize_t bytes_written = write(fds[1], &locked, sizeof(locked)); + EXPECT_EQ(sizeof(locked), bytes_written); + + close(fds[1]); + exit(0); + } else { + // Parent reads from pipe + close(fds[1]); + + const unsigned char locked = parentReadState(fds[0]); + + close(fds[0]); + + EXPECT_EQ(1, locked); + } + } + + EXPECT_TRUE(locker.unlock()); + EXPECT_FALSE(locker.isLocked()); + + EXPECT_EQ (0, remove(TEST_DATA_TOPBUILDDIR "/test_lockfile")); +} + +TEST(InterprocessSyncFileTest, TestMultipleFilesDirect) { + InterprocessSyncFile sync("test1"); + InterprocessSyncLocker locker(sync); + + EXPECT_TRUE(locker.lock()); + + InterprocessSyncFile sync2("test2"); + InterprocessSyncLocker locker2(sync2); + EXPECT_TRUE(locker2.lock()); + EXPECT_TRUE(locker2.unlock()); + + EXPECT_TRUE(locker.unlock()); + + EXPECT_EQ (0, remove(TEST_DATA_TOPBUILDDIR "/test1_lockfile")); + EXPECT_EQ (0, remove(TEST_DATA_TOPBUILDDIR "/test2_lockfile")); +} + +TEST(InterprocessSyncFileTest, TestMultipleFilesForked) { + InterprocessSyncFile sync("test1"); + InterprocessSyncLocker locker(sync); + + EXPECT_TRUE(locker.lock()); + + if (!isc::util::unittests::runningOnValgrind()) { + + int fds[2]; + + EXPECT_EQ(0, pipe(fds)); + + if (fork() == 0) { + unsigned char locked = 0xff; + // Child writes to pipe + close(fds[0]); + + InterprocessSyncFile sync2("test2"); + InterprocessSyncLocker locker2(sync2); + + if (locker2.tryLock()) { + locked = 0; + } + + ssize_t bytes_written = write(fds[1], &locked, sizeof(locked)); + EXPECT_EQ(sizeof(locked), bytes_written); + + close(fds[1]); + exit(0); + } else { + // Parent reads from pipe + close(fds[1]); + + const unsigned char locked = parentReadState(fds[0]); + + close(fds[0]); + + EXPECT_EQ(0, locked); + } + + EXPECT_EQ (0, remove(TEST_DATA_TOPBUILDDIR "/test2_lockfile")); + } + + EXPECT_TRUE(locker.unlock()); + + EXPECT_EQ (0, remove(TEST_DATA_TOPBUILDDIR "/test1_lockfile")); +} + +} // unnamed namespace diff --git a/src/lib/log/interprocess/tests/interprocess_sync_null_unittest.cc b/src/lib/log/interprocess/tests/interprocess_sync_null_unittest.cc new file mode 100644 index 0000000..4f12e37 --- /dev/null +++ b/src/lib/log/interprocess/tests/interprocess_sync_null_unittest.cc @@ -0,0 +1,69 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/interprocess/interprocess_sync_null.h> +#include <gtest/gtest.h> + +using namespace std; +using namespace isc::log::interprocess; + +namespace { + +TEST(InterprocessSyncNullTest, TestNull) { + InterprocessSyncNull sync("test1"); + InterprocessSyncLocker locker(sync); + + // Check if the is_locked_ flag is set correctly during lock(). + EXPECT_FALSE(locker.isLocked()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.isLocked()); + + // lock() must always return true (this is called 4 times, just an + // arbitrary number) + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.lock()); + + // Check if the is_locked_ flag is set correctly during unlock(). + EXPECT_TRUE(locker.isLocked()); + EXPECT_TRUE(locker.unlock()); + EXPECT_FALSE(locker.isLocked()); + + // unlock() must always return true (this is called 4 times, just an + // arbitrary number) + EXPECT_TRUE(locker.unlock()); + EXPECT_TRUE(locker.unlock()); + EXPECT_TRUE(locker.unlock()); + EXPECT_TRUE(locker.unlock()); + + // Check if the is_locked_ flag is set correctly during tryLock(). + EXPECT_FALSE(locker.isLocked()); + EXPECT_TRUE(locker.tryLock()); + EXPECT_TRUE(locker.isLocked()); + + // tryLock() must always return true (this is called 4 times, just an + // arbitrary number) + EXPECT_TRUE(locker.tryLock()); + EXPECT_TRUE(locker.tryLock()); + EXPECT_TRUE(locker.tryLock()); + EXPECT_TRUE(locker.tryLock()); + + // Random order (should all return true) + EXPECT_TRUE(locker.unlock()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.tryLock()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.unlock()); + EXPECT_TRUE(locker.lock()); + EXPECT_TRUE(locker.tryLock()); + EXPECT_TRUE(locker.unlock()); + EXPECT_TRUE(locker.unlock()); +} + +} diff --git a/src/lib/log/interprocess/tests/run_unittests.cc b/src/lib/log/interprocess/tests/run_unittests.cc new file mode 100644 index 0000000..0a12720 --- /dev/null +++ b/src/lib/log/interprocess/tests/run_unittests.cc @@ -0,0 +1,22 @@ +// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <gtest/gtest.h> +#include <util/unittests/run_all.h> +#include <stdlib.h> + +// This file uses TEST_DATA_TOPBUILDDIR macro, which must point to a writable +// directory. It will be used for creating a logger lockfile. + +int +main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + + setenv("KEA_LOCKFILE_DIR", TEST_DATA_TOPBUILDDIR, 1); + return (isc::util::unittests::run_all()); +} diff --git a/src/lib/log/log_dbglevels.cc b/src/lib/log/log_dbglevels.cc new file mode 100644 index 0000000..0863d15 --- /dev/null +++ b/src/lib/log/log_dbglevels.cc @@ -0,0 +1,25 @@ +// Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +namespace isc { +namespace log { + +/// This is given a value of 0 as that is the level selected if debugging is +/// enabled without giving a level. +extern const int DBGLVL_START_SHUT = 0; +extern const int DBGLVL_COMMAND = 10; +extern const int DBGLVL_PKT_HANDLING = 15; +extern const int DBGLVL_COMMAND_DATA = 20; + +extern const int DBGLVL_TRACE_BASIC = 40; +extern const int DBGLVL_TRACE_BASIC_DATA = 45; +extern const int DBGLVL_TRACE_DETAIL = 50; +extern const int DBGLVL_TRACE_DETAIL_DATA = 55; + +} +} diff --git a/src/lib/log/log_dbglevels.h b/src/lib/log/log_dbglevels.h new file mode 100644 index 0000000..2d449c7 --- /dev/null +++ b/src/lib/log/log_dbglevels.h @@ -0,0 +1,83 @@ +// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOG_DBGLVLS_H +#define LOG_DBGLVLS_H + +/// \file +/// +/// When a message is logged with DEBUG severity, the debug level associated +/// with the message is also specified. This debug level is a number +/// ranging from 0 to 99; the idea is that the higher the debug level, the +/// more detailed the message. +/// +/// If debug messages are being logged, the logging system allows them to be +/// filtered by debug level - only messages logged with a level equal to or +/// less than the set debug level will be output. (For example, if the +/// filter is set to 30, only debug messages logged with levels in the range +/// 0 to 30 will be output; messages logged with levels 31 to 99 will be +/// suppressed.) +/// +/// Levels of 30 or below are reserved for debug messages that are most +/// likely to be useful for an administrator. Levels 31 to 99 are for use by +/// someone familiar with the code. "Useful for an administrator" is, +/// admittedly, a subjective term: it is loosely defined as messages helping +/// someone diagnose a problem that they could solve without needing to dive +/// into the code. So it covers things like start-up steps and configuration +/// messages. +/// +/// In practice, this means that levels of 30 and below are most-likely to +/// be used by the top-level programs, and 31 and above by the various +/// libraries. +/// +/// This file defines a set of standard debug levels for use across all loggers. +/// In this way users can have some expectation of what will be output when +/// enabling debugging. Symbols are prefixed DBGLVL so as not to clash with +/// DBG_ symbols in the various modules. + +namespace isc { +namespace log { + +/// Process startup/shutdown debug messages. Note that these are _debug_ +/// messages, as other messages related to startup and shutdown may be output +/// with another severity. For example, when the authoritative server starts +/// up, the "server started" message could be output at a severity of INFO. +/// "Server starting" and messages indicating the stages in startup should be +/// debug messages output at this severity. +extern const int DBGLVL_START_SHUT; + +/// This debug level is reserved for logging the exchange of messages/commands +/// between processes, including configuration messages. +extern const int DBGLVL_COMMAND; + +/// This debug level is reserved for logging the details of packet handling, such +/// as dropping the packet for various reasons. +extern const int DBGLVL_PKT_HANDLING; + +/// If the commands have associated data, this level is when they are printed. +/// This includes configuration messages. +extern const int DBGLVL_COMMAND_DATA; + +// The following constants are suggested values for common operations. +// Depending on the exact nature of the code, modules may or may not use these +// levels. + +/// Trace basic operations. +extern const int DBGLVL_TRACE_BASIC; + +/// Trace data associated with the basic operations. +extern const int DBGLVL_TRACE_BASIC_DATA; + +/// Trace detailed operations. +extern const int DBGLVL_TRACE_DETAIL; + +/// Trace data associated with detailed operations. +extern const int DBGLVL_TRACE_DETAIL_DATA; + +} // log namespace +} // isc namespace + +#endif // LOG_DBGLVLS_H diff --git a/src/lib/log/log_formatter.cc b/src/lib/log/log_formatter.cc new file mode 100644 index 0000000..1ce33f4 --- /dev/null +++ b/src/lib/log/log_formatter.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> +#include <log/log_formatter.h> + +#include <cassert> + +#ifdef ENABLE_LOGGER_CHECKS +#include <iostream> +#endif + +using namespace std; +using namespace boost; + +namespace isc { +namespace log { + +void +replacePlaceholder(std::string& message, const string& arg, + const unsigned placeholder) { + const string mark("%" + lexical_cast<string>(placeholder)); + size_t pos(message.find(mark)); + if (pos != string::npos) { + do { + message.replace(pos, mark.size(), arg); + pos = message.find(mark, pos + arg.size()); + } while (pos != string::npos); + } else { +#ifdef ENABLE_LOGGER_CHECKS + // We're missing the placeholder, so throw an exception + isc_throw(MismatchedPlaceholders, "Missing logger placeholder '" << mark << "' for value '" + << arg << "' in message '" + << message << "'"); +#else + // We're missing the placeholder, so add some complain + message.append(" @@Missing logger placeholder '" + mark + "' for value '" + arg + "'@@"); +#endif /* ENABLE_LOGGER_CHECKS */ + } +} + +void +checkExcessPlaceholders(std::string& message, + unsigned int placeholder) { + const string mark("%" + lexical_cast<string>(placeholder)); + const size_t pos(message.find(mark)); + if (pos != string::npos) { + // Excess placeholders were found. If we enable the harsh check, + // abort it. Note: ideally we'd like to throw MismatchedPlaceholders, + // but we can't at least for now because this function is called from + // the Formatter's destructor. +#ifdef ENABLE_LOGGER_CHECKS + // Also, make sure we print the message so we can identify which + // identifier has the problem. + cerr << "Excess logger placeholder '" << mark << "' still exists in message '" << message + << "'." << endl; + assert(false); +#else + message.append(" @@Excess logger placeholder '" + mark + "' still exists@@"); +#endif /* ENABLE_LOGGER_CHECKS */ + } +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/log_formatter.h b/src/lib/log/log_formatter.h new file mode 100644 index 0000000..7fc67f1 --- /dev/null +++ b/src/lib/log/log_formatter.h @@ -0,0 +1,263 @@ +// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOG_FORMATTER_H +#define LOG_FORMATTER_H + +#include <cstddef> +#include <string> +#include <iostream> + +#include <exceptions/exceptions.h> +#include <log/logger_level.h> + +#include <boost/make_shared.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/lexical_cast.hpp> + +namespace isc { +namespace log { + +/// \brief Format Failure +/// +/// This exception is used to wrap a bad_lexical_cast exception thrown during +/// formatting an argument. + +class FormatFailure : public isc::Exception { +public: + FormatFailure(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + + +/// \brief Mismatched Placeholders +/// +/// This exception is used when the number of placeholders do not match +/// the number of arguments passed to the formatter. + +class MismatchedPlaceholders : public isc::Exception { +public: + MismatchedPlaceholders(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + + +/// +/// \brief Internal excess placeholder checker +/// +/// This is used internally by the Formatter to check for excess +/// placeholders (and fewer arguments). +void +checkExcessPlaceholders(std::string& message, unsigned int placeholder); + +/// +/// \brief The internal replacement routine +/// +/// This is used internally by the Formatter. Replaces a placeholder +/// in the message by replacement. If the placeholder is not found, +/// it adds a complain at the end. +void +replacePlaceholder(std::string& message, const std::string& replacement, + const unsigned placeholder); + +/// +/// \brief The log message formatter +/// +/// This class allows us to format logging messages conveniently. We +/// call something like logger.warn(WARN_MSG).arg(15).arg(dnsMsg). This +/// outputs some text with placeholders replaced by the arguments, if +/// the logging verbosity is at WARN level or more. +/// +/// To make this work, we use the Formatter. The warn (or whatever logging +/// function) returns a Formatter object. That one holds the string to be +/// output with the placeholders. It also remembers if there should be any +/// output at all (eg. if the logging is enabled for this level). When there's +/// no .arg call on the object, it is destroyed right away and we use the +/// destructor to output the text (but only in case we should output anything). +/// +/// If there's an .arg call, we return reference to the same object, so another +/// .arg can be called on it. After the last .arg call is done, the object is +/// destroyed and, again, we can produce the output. +/// +/// Of course, if the logging is turned off, we don't bother with any replacing +/// and just return. +/// +/// User of logging code should not really care much about this class, only +/// call the .arg method to generate the correct output. +/// +/// The class is a template to allow easy testing. Also, we want everything +/// here in the header anyway and it doesn't depend on the details of what +/// Logger really is, so it doesn't hurt anything. +/// +/// Also, if you are interested in the internals, you might find the copy +/// constructor a bit strange. It deactivates the original formatter. We don't +/// really want to support copying of the Formatter by user, but C++ needs a +/// copy constructor when returning from the logging functions, so we need one. +/// And if we did not deactivate the original Formatter, that one would get +/// destroyed before any call to .arg, producing an output, and then the one +/// the .arg calls are called on would get destroyed as well, producing output +/// again. So, think of this behavior as soul moving from one to another. +template<class Logger> class Formatter { +private: + /// \brief The logger we will use to output the final message. + /// + /// If NULL, we are not active and should not produce anything. + mutable Logger* logger_; + + /// \brief Message severity + Severity severity_; + + /// \brief The messages with %1, %2... placeholders + boost::shared_ptr<std::string> message_; + + /// \brief Which will be the next placeholder to replace + unsigned nextPlaceholder_; + + +public: + /// \brief Constructor of "active" formatter + /// + /// This will create a formatter. If the arguments are set, it + /// will be active (will produce output). If you leave them all as NULL, + /// it will create an inactive Formatter -- one that'll produce no output. + /// + /// It is not expected to be called by user of logging system directly. + /// + /// \param severity The severity of the message (DEBUG, ERROR etc.) + /// \param message The message with placeholders. We take ownership of + /// it and we will modify the string. Must not be NULL unless + /// logger is also NULL, but it's not checked. + /// \param logger The logger where the final output will go, or NULL + /// if no output is wanted. + Formatter(const Severity& severity = NONE, + boost::shared_ptr<std::string> message = boost::make_shared<std::string>(), + Logger* logger = NULL) : + logger_(logger), severity_(severity), message_(message), + nextPlaceholder_(0) { + } + + /// \brief Copy constructor + /// + /// "Control" is passed to the created object in that it is the created object + /// that will have responsibility for outputting the formatted message - the + /// object being copied relinquishes that responsibility. + Formatter(const Formatter& other) : + logger_(other.logger_), severity_(other.severity_), + message_(other.message_), nextPlaceholder_(other.nextPlaceholder_) { + other.logger_ = NULL; + } + + /// \brief Destructor. + // + /// This is the place where output happens if the formatter is active. + ~Formatter() { + if (logger_) { + try { + checkExcessPlaceholders(*message_, ++nextPlaceholder_); + logger_->output(severity_, *message_); + } catch (...) { + // Catch and ignore all exceptions here. + } + } + } + + /// \brief Assignment operator + /// + /// Essentially the same function as the assignment operator - the object being + /// assigned to takes responsibility for outputting the message. + Formatter& operator =(const Formatter& other) { + if (&other != this) { + logger_ = other.logger_; + severity_ = other.severity_; + message_ = other.message_; + nextPlaceholder_ = other.nextPlaceholder_; + other.logger_ = NULL; + } + + return *this; + } + + /// \brief Replaces another placeholder + /// + /// Replaces another placeholder and returns a new formatter with it. + /// Deactivates the current formatter. In case the formatter is not active, + /// only produces another inactive formatter. + /// + /// \param value The argument to place into the placeholder. + template<class Arg> Formatter& arg(const Arg& value) { + if (logger_) { + try { + return (arg(boost::lexical_cast<std::string>(value))); + } catch (const boost::bad_lexical_cast& ex) { + // The formatting of the log message got wrong, we don't want + // to output it. + deactivate(); + // A bad_lexical_cast during a conversion to a string is + // *extremely* unlikely to fail. However, there is nothing + // in the documentation that rules it out, so we need to handle + // it. As it is a potentially very serious problem, throw the + // exception detailing the problem with as much information as + // we can. (Note that this does not include 'value' - + // boost::lexical_cast failed to convert it to a string, so an + // attempt to do so here would probably fail as well.) + isc_throw(FormatFailure, "bad_lexical_cast in call to " + "Formatter::arg(): " << ex.what()); + } + } else { + return (*this); + } + } + + /// \brief String version of arg. + /// + /// \param arg The text to place into the placeholder. + Formatter& arg(const std::string& arg) { + if (logger_) { + // Note that this method does a replacement and returns the + // modified string. If there are multiple invocations of arg() (e.g. + // logger.info(msgid).arg(xxx).arg(yyy)...), each invocation + // operates on the string returned by the previous one. This + // sequential operation means that if we had a message like "%1 %2", + // and called .arg("%2").arg(42), we would get "42 42"; the first + // call replaces the %1" with "%2" and the second replaces all + // occurrences of "%2" with 42. (Conversely, the sequence + // .arg(42).arg("%1") would return "42 %1" - there are no recursive + // replacements). + try { + replacePlaceholder(*message_, arg, ++nextPlaceholder_); + } catch (...) { + // Something went wrong here, the log message is broken, so + // we don't want to output it, nor we want to check all the + // placeholders were used (because they won't be). + deactivate(); + throw; + } + } + return (*this); + } + + /// \brief Turn off the output of this logger. + /// + /// If the logger would output anything at the end, now it won't. + /// Also, this turns off the strict checking of placeholders, if + /// it is compiled in. + /// + /// The expected use is when there was an exception processing + /// the arguments for the message. + void deactivate() { + if (logger_) { + message_.reset(); + logger_ = NULL; + } + } +}; + +} // namespace log +} // namespace isc + +#endif diff --git a/src/lib/log/log_messages.cc b/src/lib/log/log_messages.cc new file mode 100644 index 0000000..65d6bd8 --- /dev/null +++ b/src/lib/log/log_messages.cc @@ -0,0 +1,63 @@ +// File created from ../../../src/lib/log/log_messages.mes + +#include <cstddef> +#include <log/message_types.h> +#include <log/message_initializer.h> + +namespace isc { +namespace log { + +extern const isc::log::MessageID LOG_BAD_DESTINATION = "LOG_BAD_DESTINATION"; +extern const isc::log::MessageID LOG_BAD_SEVERITY = "LOG_BAD_SEVERITY"; +extern const isc::log::MessageID LOG_BAD_STREAM = "LOG_BAD_STREAM"; +extern const isc::log::MessageID LOG_DUPLICATE_MESSAGE_ID = "LOG_DUPLICATE_MESSAGE_ID"; +extern const isc::log::MessageID LOG_DUPLICATE_NAMESPACE = "LOG_DUPLICATE_NAMESPACE"; +extern const isc::log::MessageID LOG_INPUT_OPEN_FAIL = "LOG_INPUT_OPEN_FAIL"; +extern const isc::log::MessageID LOG_INVALID_MESSAGE_ID = "LOG_INVALID_MESSAGE_ID"; +extern const isc::log::MessageID LOG_NAMESPACE_EXTRA_ARGS = "LOG_NAMESPACE_EXTRA_ARGS"; +extern const isc::log::MessageID LOG_NAMESPACE_INVALID_ARG = "LOG_NAMESPACE_INVALID_ARG"; +extern const isc::log::MessageID LOG_NAMESPACE_NO_ARGS = "LOG_NAMESPACE_NO_ARGS"; +extern const isc::log::MessageID LOG_NO_MESSAGE_ID = "LOG_NO_MESSAGE_ID"; +extern const isc::log::MessageID LOG_NO_MESSAGE_TEXT = "LOG_NO_MESSAGE_TEXT"; +extern const isc::log::MessageID LOG_NO_SUCH_MESSAGE = "LOG_NO_SUCH_MESSAGE"; +extern const isc::log::MessageID LOG_OPEN_OUTPUT_FAIL = "LOG_OPEN_OUTPUT_FAIL"; +extern const isc::log::MessageID LOG_PREFIX_EXTRA_ARGS = "LOG_PREFIX_EXTRA_ARGS"; +extern const isc::log::MessageID LOG_PREFIX_INVALID_ARG = "LOG_PREFIX_INVALID_ARG"; +extern const isc::log::MessageID LOG_READING_LOCAL_FILE = "LOG_READING_LOCAL_FILE"; +extern const isc::log::MessageID LOG_READ_ERROR = "LOG_READ_ERROR"; +extern const isc::log::MessageID LOG_UNRECOGNIZED_DIRECTIVE = "LOG_UNRECOGNIZED_DIRECTIVE"; +extern const isc::log::MessageID LOG_WRITE_ERROR = "LOG_WRITE_ERROR"; + +} // namespace log +} // namespace isc + +namespace { + +const char* values[] = { + "LOG_BAD_DESTINATION", "unrecognized log destination: %1", + "LOG_BAD_SEVERITY", "unrecognized log severity: %1", + "LOG_BAD_STREAM", "bad log console output stream: %1", + "LOG_DUPLICATE_MESSAGE_ID", "duplicate message ID (%1) in compiled code", + "LOG_DUPLICATE_NAMESPACE", "line %1: duplicate $NAMESPACE directive found", + "LOG_INPUT_OPEN_FAIL", "unable to open message file %1 for input: %2", + "LOG_INVALID_MESSAGE_ID", "line %1: invalid message identification '%2'", + "LOG_NAMESPACE_EXTRA_ARGS", "line %1: $NAMESPACE directive has too many arguments", + "LOG_NAMESPACE_INVALID_ARG", "line %1: $NAMESPACE directive has an invalid argument ('%2')", + "LOG_NAMESPACE_NO_ARGS", "line %1: no arguments were given to the $NAMESPACE directive", + "LOG_NO_MESSAGE_ID", "line %1: message definition line found without a message ID", + "LOG_NO_MESSAGE_TEXT", "line %1: line found containing a message ID ('%2') and no text", + "LOG_NO_SUCH_MESSAGE", "could not replace message text for '%1': no such message", + "LOG_OPEN_OUTPUT_FAIL", "unable to open %1 for output: %2", + "LOG_PREFIX_EXTRA_ARGS", "line %1: $PREFIX directive has too many arguments", + "LOG_PREFIX_INVALID_ARG", "line %1: $PREFIX directive has an invalid argument ('%2')", + "LOG_READING_LOCAL_FILE", "reading local message file %1", + "LOG_READ_ERROR", "error reading from message file %1: %2", + "LOG_UNRECOGNIZED_DIRECTIVE", "line %1: unrecognized directive '%2'", + "LOG_WRITE_ERROR", "error writing to %1: %2", + NULL +}; + +const isc::log::MessageInitializer initializer(values); + +} // Anonymous namespace + diff --git a/src/lib/log/log_messages.h b/src/lib/log/log_messages.h new file mode 100644 index 0000000..d8af641 --- /dev/null +++ b/src/lib/log/log_messages.h @@ -0,0 +1,35 @@ +// File created from ../../../src/lib/log/log_messages.mes + +#ifndef LOG_MESSAGES_H +#define LOG_MESSAGES_H + +#include <log/message_types.h> + +namespace isc { +namespace log { + +extern const isc::log::MessageID LOG_BAD_DESTINATION; +extern const isc::log::MessageID LOG_BAD_SEVERITY; +extern const isc::log::MessageID LOG_BAD_STREAM; +extern const isc::log::MessageID LOG_DUPLICATE_MESSAGE_ID; +extern const isc::log::MessageID LOG_DUPLICATE_NAMESPACE; +extern const isc::log::MessageID LOG_INPUT_OPEN_FAIL; +extern const isc::log::MessageID LOG_INVALID_MESSAGE_ID; +extern const isc::log::MessageID LOG_NAMESPACE_EXTRA_ARGS; +extern const isc::log::MessageID LOG_NAMESPACE_INVALID_ARG; +extern const isc::log::MessageID LOG_NAMESPACE_NO_ARGS; +extern const isc::log::MessageID LOG_NO_MESSAGE_ID; +extern const isc::log::MessageID LOG_NO_MESSAGE_TEXT; +extern const isc::log::MessageID LOG_NO_SUCH_MESSAGE; +extern const isc::log::MessageID LOG_OPEN_OUTPUT_FAIL; +extern const isc::log::MessageID LOG_PREFIX_EXTRA_ARGS; +extern const isc::log::MessageID LOG_PREFIX_INVALID_ARG; +extern const isc::log::MessageID LOG_READING_LOCAL_FILE; +extern const isc::log::MessageID LOG_READ_ERROR; +extern const isc::log::MessageID LOG_UNRECOGNIZED_DIRECTIVE; +extern const isc::log::MessageID LOG_WRITE_ERROR; + +} // namespace log +} // namespace isc + +#endif // LOG_MESSAGES_H diff --git a/src/lib/log/log_messages.mes b/src/lib/log/log_messages.mes new file mode 100644 index 0000000..3c28d2c --- /dev/null +++ b/src/lib/log/log_messages.mes @@ -0,0 +1,138 @@ +# Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# \brief Message Utility Message File +# +# This is the source of the set of messages generated by the message and +# logging components. The associated .h and .cc files are created by hand from +# this file though and are not built during the build process; this is to avoid +# the chicken-and-egg situation where we need the files to build the message +# compiler, yet we need the compiler to build the files. + +$NAMESPACE isc::log + +% LOG_BAD_DESTINATION unrecognized log destination: %1 +A logger destination value was given that was not recognized. The +destination should be one of "console", "file", or "syslog". + +% LOG_BAD_SEVERITY unrecognized log severity: %1 +A logger severity value was given that was not recognized. The severity +should be one of "DEBUG", "INFO", "WARN", "ERROR", "FATAL" or "NONE". + +% LOG_BAD_STREAM bad log console output stream: %1 +Logging has been configured so that output is written to the terminal +(console) but the stream on which it is to be written is not recognized. +Allowed values are "stdout" and "stderr". + +% LOG_DUPLICATE_MESSAGE_ID duplicate message ID (%1) in compiled code +During start-up, Kea detected that the given message identification +had been defined multiple times in the Kea code. This indicates a +programming error; please submit a bug report. + +% LOG_DUPLICATE_NAMESPACE line %1: duplicate $NAMESPACE directive found +When reading a message file, more than one $NAMESPACE directive was found. +(This directive is used to set a C++ namespace when generating header +files during software development.) Such a condition is regarded as an +error and the read will be abandoned. + +% LOG_INPUT_OPEN_FAIL unable to open message file %1 for input: %2 +The program was not able to open the specified input message file for +the reason given. + +% LOG_INVALID_MESSAGE_ID line %1: invalid message identification '%2' +An invalid message identification (ID) has been found during the read of +a message file. Message IDs should comprise only alphanumeric characters +and the underscore, and should not start with a digit. + +% LOG_NAMESPACE_EXTRA_ARGS line %1: $NAMESPACE directive has too many arguments +The $NAMESPACE directive in a message file takes a single argument, a +namespace in which all the generated symbol names are placed. This error +is generated when the compiler finds a $NAMESPACE directive with more +than one argument. + +% LOG_NAMESPACE_INVALID_ARG line %1: $NAMESPACE directive has an invalid argument ('%2') +The $NAMESPACE argument in a message file should be a valid C++ namespace. +This message is output if the simple check on the syntax of the string +carried out by the reader fails. + +% LOG_NAMESPACE_NO_ARGS line %1: no arguments were given to the $NAMESPACE directive +The $NAMESPACE directive in a message file takes a single argument, +a C++ namespace in which all the generated symbol names are placed. +This error is generated when the compiler finds a $NAMESPACE directive +with no arguments. + +% LOG_NO_MESSAGE_ID line %1: message definition line found without a message ID +Within a message file, message are defined by lines starting with a "%". +The rest of the line should comprise the message ID and text describing +the message. This error indicates the message compiler found a line in +the message file comprising just the "%" and nothing else. + +% LOG_NO_MESSAGE_TEXT line %1: line found containing a message ID ('%2') and no text +Within a message file, message are defined by lines starting with a "%". +The rest of the line should comprise the message ID and text describing +the message. This error indicates the message compiler found a line +in the message file comprising just the "%" and message identification, +but no text. + +% LOG_NO_SUCH_MESSAGE could not replace message text for '%1': no such message +During start-up a local message file was read. A line with the listed +message identification was found in the file, but the identification is +not one contained in the compiled-in message dictionary. This message +may appear a number of times in the file, once for every such unknown +message identification. + +There are several reasons why this message may appear: + +- The message ID has been misspelled in the local message file. + +- The program outputting the message may not use that particular message +(e.g. it originates in a module not used by the program). + +- The local file was written for an earlier version of the Kea software +and the later version no longer generates that message. + +Whatever the reason, there is no impact on the operation of Kea. + +% LOG_OPEN_OUTPUT_FAIL unable to open %1 for output: %2 +Originating within the logging code, the program was not able to open +the specified output file for the reason given. + +% LOG_PREFIX_EXTRA_ARGS line %1: $PREFIX directive has too many arguments +Within a message file, the $PREFIX directive takes a single argument, +a prefix to be added to the symbol names when a C++ file is created. +This error is generated when the compiler finds a $PREFIX directive with +more than one argument. + +Note: the $PREFIX directive is deprecated and will be removed in a future +version of Kea. + +% LOG_PREFIX_INVALID_ARG line %1: $PREFIX directive has an invalid argument ('%2') +Within a message file, the $PREFIX directive takes a single argument, +a prefix to be added to the symbol names when a C++ file is created. +As such, it must adhere to restrictions on C++ symbol names (e.g. may +only contain alphanumeric characters or underscores, and may nor start +with a digit). A $PREFIX directive was found with an argument (given +in the message) that violates those restrictions. + +Note: the $PREFIX directive is deprecated and will be removed in a future +version of Kea. + +% LOG_READING_LOCAL_FILE reading local message file %1 +This is an informational message output by Kea when it starts to read +a local message file. (A local message file may replace the text of +one or more messages; the ID of the message will not be changed though.) + +% LOG_READ_ERROR error reading from message file %1: %2 +The specified error was encountered reading from the named message file. + +% LOG_UNRECOGNIZED_DIRECTIVE line %1: unrecognized directive '%2' +Within a message file, a line starting with a dollar symbol was found +(indicating the presence of a directive) but the first word on the line +(shown in the message) was not recognized. + +% LOG_WRITE_ERROR error writing to %1: %2 +The specified error was encountered by the message compiler when writing +to the named output file. diff --git a/src/lib/log/logger.cc b/src/lib/log/logger.cc new file mode 100644 index 0000000..e036a09 --- /dev/null +++ b/src/lib/log/logger.cc @@ -0,0 +1,220 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <stdarg.h> +#include <stdio.h> + +#include <log/logger.h> +#include <log/logger_impl.h> +#include <log/logger_name.h> +#include <log/logger_support.h> +#include <log/message_dictionary.h> +#include <log/message_types.h> + +#include <util/strutil.h> + +using namespace std; + +namespace isc { +namespace log { + +LoggerImpl* +Logger::getLoggerPtr() { + if (!initialized_) { + lock_guard<mutex> lk(mutex_); + if (!initialized_) { + initLoggerImpl(); + } + initialized_ = true; + } + return (loggerptr_); +} + +// Initialize underlying logger, but only if logging has been initialized. +void +Logger::initLoggerImpl() { + if (isLoggingInitialized()) { + loggerptr_ = new LoggerImpl(name_); + } else { + isc_throw(LoggingNotInitialized, "attempt to access logging function " + "before logging has been initialized"); + } +} + +// Destructor. + +Logger::~Logger() { + delete loggerptr_; + + // The next statement is required for the Kea hooks framework, where a + // statically-linked Kea loads and unloads multiple libraries. See the hooks + // documentation for more details. + loggerptr_ = 0; +} + +// Get Version +std::string +Logger::getVersion() { + return (LoggerImpl::getVersion()); +} + +// Get Name of Logger + +std::string +Logger::getName() { + return (getLoggerPtr()->getName()); +} + +// Set the severity for logging. + +void +Logger::setSeverity(isc::log::Severity severity, int dbglevel) { + getLoggerPtr()->setSeverity(severity, dbglevel); +} + +// Return the severity of the logger. + +isc::log::Severity +Logger::getSeverity() { + return (getLoggerPtr()->getSeverity()); +} + +// Get Effective Severity Level for Logger + +isc::log::Severity +Logger::getEffectiveSeverity() { + return (getLoggerPtr()->getEffectiveSeverity()); +} + +// Debug level (only relevant if messages of severity DEBUG are being logged). + +int +Logger::getDebugLevel() { + return (getLoggerPtr()->getDebugLevel()); +} + +// Effective debug level (only relevant if messages of severity DEBUG are being +// logged). + +int +Logger::getEffectiveDebugLevel() { + return (getLoggerPtr()->getEffectiveDebugLevel()); +} + +// Check on the current severity settings + +bool +Logger::isDebugEnabled(int dbglevel) { + return (getLoggerPtr()->isDebugEnabled(dbglevel)); +} + +bool +Logger::isInfoEnabled() { + return (getLoggerPtr()->isInfoEnabled()); +} + +bool +Logger::isWarnEnabled() { + return (getLoggerPtr()->isWarnEnabled()); +} + +bool +Logger::isErrorEnabled() { + return (getLoggerPtr()->isErrorEnabled()); +} + +bool +Logger::isFatalEnabled() { + return (getLoggerPtr()->isFatalEnabled()); +} + +// Format a message: looks up the message text in the dictionary and formats +// it, replacing tokens with arguments. +// +// Owing to the use of variable arguments, this must be inline (hence the +// definition of the macro). Also note that it expects that the message buffer +// "message" is declared in the compilation unit. + +// Output methods + +void +Logger::output(const Severity& severity, const std::string& message) { + getLoggerPtr()->outputRaw(severity, message); +} + +Logger::Formatter +Logger::debug(int dbglevel, const isc::log::MessageID& ident) { + if (isDebugEnabled(dbglevel)) { + return (Formatter(DEBUG, getLoggerPtr()->lookupMessage(ident), + this)); + } else { + return (Formatter()); + } +} + +Logger::Formatter +Logger::info(const isc::log::MessageID& ident) { + if (isInfoEnabled()) { + return (Formatter(INFO, getLoggerPtr()->lookupMessage(ident), + this)); + } else { + return (Formatter()); + } +} + +Logger::Formatter +Logger::warn(const isc::log::MessageID& ident) { + if (isWarnEnabled()) { + return (Formatter(WARN, getLoggerPtr()->lookupMessage(ident), + this)); + } else { + return (Formatter()); + } +} + +Logger::Formatter +Logger::error(const isc::log::MessageID& ident) { + if (isErrorEnabled()) { + return (Formatter(ERROR, getLoggerPtr()->lookupMessage(ident), + this)); + } else { + return (Formatter()); + } +} + +Logger::Formatter +Logger::fatal(const isc::log::MessageID& ident) { + if (isFatalEnabled()) { + return (Formatter(FATAL, getLoggerPtr()->lookupMessage(ident), + this)); + } else { + return (Formatter()); + } +} + +// Replace the interprocess synchronization object + +void +Logger::setInterprocessSync(isc::log::interprocess::InterprocessSync* sync) { + getLoggerPtr()->setInterprocessSync(sync); +} + +bool +Logger::hasAppender(OutputOption::Destination const destination) { + return getLoggerPtr()->hasAppender(destination); +} + +// Comparison (testing only) + +bool +Logger::operator==(Logger& other) { + return (*getLoggerPtr() == *other.getLoggerPtr()); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger.h b/src/lib/log/logger.h new file mode 100644 index 0000000..78a82ff --- /dev/null +++ b/src/lib/log/logger.h @@ -0,0 +1,369 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_H +#define LOGGER_H + +#include <atomic> +#include <cstdlib> +#include <cstring> +#include <mutex> +#include <string> + +#include <exceptions/exceptions.h> +#include <log/logger_level.h> +#include <log/message_types.h> +#include <log/log_formatter.h> +#include <log/output_option.h> + +namespace isc { +namespace log { + +namespace interprocess { +// Forward declaration to hide implementation details from normal +// applications. +class InterprocessSync; +} + +/// \page LoggingApi Logging API +/// \section LoggingApiOverview Overview +/// Kea logging uses the concepts of the widely-used Java logging +/// package log4j (https://logging.apache.org/log4j/), albeit implemented +/// in C++ using an open-source port. Features of the system are: +/// +/// - Within the code objects - known as loggers - can be created and +/// used to log messages. These loggers have names; those with the +/// same name share characteristics (such as output destination). +/// - Loggers have a hierarchical relationship, with each logger being +/// the child of another logger, except for the top of the hierarchy, the +/// root logger. If a logger does not log a message, it is passed to the +/// parent logger. +/// - Messages can be logged at severity levels of FATAL, ERROR, WARN, INFO +/// or DEBUG. The DEBUG level has further sub-levels numbered 0 (least +/// informative) to 99 (most informative). +/// - Each logger has a severity level set associated with it. When a +/// message is logged, it is output only if it is logged at a level equal +/// to the logger severity level or greater, e.g. if the logger's severity +/// is WARN, only messages logged at WARN, ERROR or FATAL will be output. +/// +/// \section LoggingApiLoggerNames Kea Logger Names +/// Within Kea, the root logger root logger is given the name of the +/// program (via the stand-alone function setRootLoggerName()). Other loggers +/// are children of the root logger and are named "<program>.<sublogger>". +/// This name appears in logging output, allowing users to identify both +/// the Kea program and the component within the program that generated +/// the message. +/// +/// When creating a logger, the abbreviated name "<sublogger>" can be used; +/// the program name will be prepended to it when the logger is created. +/// In this way, individual libraries can have their own loggers without +/// worrying about the program in which they are used, but: +/// - The origin of the message will be clearly identified. +/// - The same component can have different options (e.g. logging severity) +/// in different programs at the same time. +/// +/// \section LoggingApiLoggingMessages Logging Messages +/// Instead of embedding the text of messages within the code, each message +/// is referred to using a symbolic name. The logging code uses this name as +/// a key in a dictionary from which the message text is obtained. Such a +/// system allows for the optional replacement of message text at run time. +/// More details about the message dictionary (and the compiler used to create +/// the symbol definitions) can be found in other modules in the src/lib/log +/// directory. +/// +/// \section LoggingApiImplementationIssues Implementation Issues +/// Owing to the way that the logging is implemented, notably that loggers can +/// be declared as static external objects, there is a restriction on the +/// length of the name of a logger component (i.e. the length of +/// the string passed to the Logger constructor) to a maximum of 31 characters. +/// There is no reason for this particular value other than limiting the amount +/// of memory used. It is defined by the constant Logger::MAX_LOGGER_NAME_SIZE, +/// and can be made larger (or smaller) if so desired. + +class LoggerImpl; // Forward declaration of the implementation class + +/// \brief Bad Interprocess Sync +/// +/// Exception thrown if a bad InterprocessSync object (such as null) is +/// used. +class BadInterprocessSync : public isc::Exception { +public: + BadInterprocessSync(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + +/// \brief Logger Name Error +/// +/// Exception thrown if a logger name is too short or too long. +class LoggerNameError : public isc::Exception { +public: + LoggerNameError(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + +/// \brief Logger Name is null +/// +/// Exception thrown if a logger name is null +class LoggerNameNull : public isc::Exception { +public: + LoggerNameNull(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + +/// \brief Logging Not Initialized +/// +/// Exception thrown if an attempt is made to access a logging function +/// if the logging system has not been initialized. +class LoggingNotInitialized : public isc::Exception { +public: + LoggingNotInitialized(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + +/// \brief Logger Class +/// +/// This class is the main class used for logging. Use comprises: +/// +/// 1. Constructing a logger by instantiating it with a specific name. (If the +/// same logger is in multiple functions within a file, overhead can be +/// minimized by declaring it as a file-wide static variable.) +/// 2. Using the error(), info() etc. methods to log an error. (However, it is +/// recommended to use the LOG_ERROR, LOG_INFO etc. macros defined in macros.h. +/// These will avoid the potentially-expensive evaluation of arguments if the +/// severity is such that the message will be suppressed.) + +class Logger { +public: + /// Maximum size of a logger name + static const size_t MAX_LOGGER_NAME_SIZE = 31; + + /// \brief Constructor + /// + /// Creates/attaches to a logger of a specific name. + /// + /// \param name Name of the logger. If the name is that of the root name, + /// this creates an instance of the root logger; otherwise it creates a + /// child of the root logger. + /// + /// \note The name of the logger may be no longer than MAX_LOGGER_NAME_SIZE + /// else the program will throw an exception. This restriction allows + /// loggers to be declared statically: the name is stored in a fixed-size + /// array to avoid the need to allocate heap storage during program + /// initialization (which causes problems on some operating systems). + /// + /// \note Note also that there is no constructor taking a std::string. This + /// minimizes the possibility of initializing a static logger with a + /// string, so leading to problems mentioned above. + Logger(const char* name) : loggerptr_(0), initialized_(false) { + + // Validate the name of the logger. + if (name) { + // Name not null, is it too short or too long? + size_t namelen = std::strlen(name); + if ((namelen == 0) || (namelen > MAX_LOGGER_NAME_SIZE)) { + isc_throw(LoggerNameError, "'" << name << "' is not a valid " + << "name for a logger: valid names must be between 1 " + << "and " << MAX_LOGGER_NAME_SIZE << " characters in " + << "length"); + } + } else { + isc_throw(LoggerNameNull, "logger names may not be null"); + } + + // Do the copy, ensuring a trailing null in all cases. + std::strncpy(name_, name, MAX_LOGGER_NAME_SIZE); + name_[MAX_LOGGER_NAME_SIZE] = '\0'; + } + + /// \brief Destructor + virtual ~Logger(); + + /// \brief Version + static std::string getVersion(); + + /// \brief The formatter used to replace placeholders + typedef isc::log::Formatter<Logger> Formatter; + + /// \brief Get Name of Logger + /// + /// \return The full name of the logger (including the root name) + virtual std::string getName(); + + /// \brief Set Severity Level for Logger + /// + /// Sets the level at which this logger will log messages. If none is set, + /// the level is inherited from the parent. + /// + /// \param severity Severity level to log + /// \param dbglevel If the severity is DEBUG, this is the debug level. + /// This can be in the range 1 to 100 and controls the verbosity. A value + /// outside these limits is silently coerced to the nearest boundary. + virtual void setSeverity(isc::log::Severity severity, int dbglevel = 1); + + /// \brief Get Severity Level for Logger + /// + /// \return The current logging level of this logger. In most cases though, + /// the effective logging level is what is required. + virtual isc::log::Severity getSeverity(); + + /// \brief Get Effective Severity Level for Logger + /// + /// \return The effective severity level of the logger. This is the same + /// as getSeverity() if the logger has a severity level set, but otherwise + /// is the severity of the parent. + virtual isc::log::Severity getEffectiveSeverity(); + + /// \brief Return DEBUG Level + /// + /// \return Current setting of debug level. This is returned regardless of + /// whether the severity is set to debug. + virtual int getDebugLevel(); + + /// \brief Get Effective Debug Level for Logger + /// + /// \return The effective debug level of the logger. This is the same + /// as getDebugLevel() if the logger has a debug level set, but otherwise + /// is the debug level of the parent. + virtual int getEffectiveDebugLevel(); + + /// \brief Returns if Debug Message Should Be Output + /// + /// \param dbglevel Level for which debugging is checked. Debugging is + /// enabled only if the logger has DEBUG enabled and if the dbglevel + /// checked is less than or equal to the debug level set for the logger. + virtual bool isDebugEnabled(int dbglevel = MIN_DEBUG_LEVEL); + + /// \brief Is INFO Enabled? + virtual bool isInfoEnabled(); + + /// \brief Is WARNING Enabled? + virtual bool isWarnEnabled(); + + /// \brief Is ERROR Enabled? + virtual bool isErrorEnabled(); + + /// \brief Is FATAL Enabled? + virtual bool isFatalEnabled(); + + /// \brief Output Debug Message + /// + /// \param dbglevel Debug level, ranging between 0 and 99. Higher numbers + /// are used for more verbose output. + /// \param ident Message identification. + Formatter debug(int dbglevel, const MessageID& ident); + + /// \brief Output Informational Message + /// + /// \param ident Message identification. + Formatter info(const MessageID& ident); + + /// \brief Output Warning Message + /// + /// \param ident Message identification. + Formatter warn(const MessageID& ident); + + /// \brief Output Error Message + /// + /// \param ident Message identification. + Formatter error(const MessageID& ident); + + /// \brief Output Fatal Message + /// + /// \param ident Message identification. + Formatter fatal(const MessageID& ident); + + /// \brief Replace the interprocess synchronization object + /// + /// If this method is called with null as the argument, it throws a + /// BadInterprocessSync exception. + /// + /// \note This method is intended to be used only within this log library + /// and its tests. Normal application shouldn't use it (in fact, + /// normal application shouldn't even be able to instantiate + /// InterprocessSync objects). + /// + /// \param sync The logger uses this synchronization object for + /// synchronizing output of log messages. It should be deletable and + /// the ownership is transferred to the logger. If null is passed, + /// a BadInterprocessSync exception is thrown. + void setInterprocessSync(isc::log::interprocess::InterprocessSync* sync); + + /// @brief Check if this logger has an appender of the given type. + /// + /// @param destination the appender type to be checked: console, file or syslog + /// + /// @return true if an appender of the given type is found, false otherwise + bool hasAppender(OutputOption::Destination const destination); + + /// \brief Equality + /// + /// Check if two instances of this logger refer to the same stream. + /// + /// \return true if the logger objects are instances of the same logger. + bool operator==(Logger& other); + +private: + friend class isc::log::Formatter<Logger>; + + /// \brief Raw output function + /// + /// This is used by the formatter to output formatted output. + /// + /// \param severity Severity of the message being output. + /// \param message Text of the message to be output. + void output(const Severity& severity, const std::string& message); + + /// \brief Copy Constructor + /// + /// Disabled (marked private) as it makes no sense to copy the logger - + /// just create another one of the same name. + Logger(const Logger&); + + /// \brief Assignment Operator + /// + /// Disabled (marked private) as it makes no sense to copy the logger - + /// just create another one of the same name. + Logger& operator=(const Logger&); + + /// \brief Initialize Implementation + /// + /// Returns the logger pointer. If not yet set, the implementation class is + /// initialized. + /// + /// The main reason for this is to allow loggers to be declared statically + /// before the underlying logging system is initialized. However, any + /// attempt to access a logging method on any logger before initialization - + /// regardless of whether is is statically or automatically declared - will + /// cause a "LoggingNotInitialized" exception to be thrown. + /// + /// \return Returns pointer to implementation + LoggerImpl* getLoggerPtr(); + + /// \brief Initialize Underlying Implementation and Set loggerptr_ + void initLoggerImpl(); + + ///< Pointer to underlying logger + LoggerImpl* loggerptr_; + + ///< Copy of the logger name + char name_[MAX_LOGGER_NAME_SIZE + 1]; + + ///< Mutex to protect the internal state + std::mutex mutex_; + + ///< Flag which indicates if logger is initialized + std::atomic<bool> initialized_; +}; + +} // namespace log +} // namespace isc + + +#endif // LOGGER_H diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc new file mode 100644 index 0000000..f0e5298 --- /dev/null +++ b/src/lib/log/logger_impl.cc @@ -0,0 +1,231 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + + +#include <algorithm> +#include <cstring> +#include <iomanip> +#include <iostream> +#include <stdarg.h> +#include <stdio.h> +#include <sstream> + +#include <boost/make_shared.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/static_assert.hpp> +#include <boost/algorithm/string.hpp> + +#include <log4cplus/configurator.h> +#include <log4cplus/consoleappender.h> +#include <log4cplus/fileappender.h> +#include <log4cplus/loggingmacros.h> +#include <log4cplus/syslogappender.h> +#include <log4cplus/version.h> + +#include <log/logger.h> +#include <log/logger_impl.h> +#include <log/logger_level.h> +#include <log/logger_level_impl.h> +#include <log/logger_name.h> +#include <log/logger_manager.h> +#include <log/message_dictionary.h> +#include <log/message_types.h> +#include <log/interprocess/interprocess_sync_file.h> +#include <log/interprocess/interprocess_sync_null.h> + +#include <util/strutil.h> + +// Note: as log4cplus and the Kea logger have many concepts in common, and +// thus many similar names, to disambiguate types we don't "use" the log4cplus +// namespace: instead, all log4cplus types are explicitly qualified. + +using namespace std; + +namespace isc { +namespace log { + +/// @brief detects whether file locking is enabled or disabled +/// +/// The lockfile is enabled by default. The only way to disable it is to +/// set KEA_LOCKFILE_DIR variable to 'none'. +/// @return true if lockfile is enabled, false otherwise +bool lockfileEnabled() { + const char* const env = getenv("KEA_LOCKFILE_DIR"); + if (env && boost::iequals(string(env), string("none"))) { + return (false); + } + + return (true); +} + +// Constructor. The setting of logger_ must be done when the variable is +// constructed (instead of being left to the body of the function); at least +// one compiler requires that all member variables be constructed before the +// constructor is run, but log4cplus::Logger (the type of logger_) has no +// default constructor. +LoggerImpl::LoggerImpl(const string& name) : + name_(expandLoggerName(name)), + logger_(log4cplus::Logger::getInstance(name_)) +{ + if (lockfileEnabled()) { + sync_ = new interprocess::InterprocessSyncFile("logger"); + } else { + sync_ = new interprocess::InterprocessSyncNull("logger"); + } +} + +// Destructor. (Here because of virtual declaration.) + +LoggerImpl::~LoggerImpl() { + delete sync_; +} + +/// \brief Version +std::string +LoggerImpl::getVersion() { + std::ostringstream ver; + ver << "log4cplus "; + ver << log4cplus::versionStr; + return (ver.str()); +} + +// Set the severity for logging. +void +LoggerImpl::setSeverity(isc::log::Severity severity, int dbglevel) { + Level level(severity, dbglevel); + logger_.setLogLevel(LoggerLevelImpl::convertFromBindLevel(level)); +} + +// Return severity level +isc::log::Severity +LoggerImpl::getSeverity() { + Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel()); + return level.severity; +} + +// Return current debug level (only valid if current severity level is DEBUG). +int +LoggerImpl::getDebugLevel() { + Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel()); + return level.dbglevel; +} + +// Get effective severity. Either the current severity or, if not set, the +// severity of the root level. +isc::log::Severity +LoggerImpl::getEffectiveSeverity() { + Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel()); + return level.severity; +} + +// Return effective debug level (only valid if current effective severity level +// is DEBUG). +int +LoggerImpl::getEffectiveDebugLevel() { + Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel()); + return level.dbglevel; +} + + +// Output a general message +boost::shared_ptr<string> +LoggerImpl::lookupMessage(const MessageID& ident) { + return (boost::make_shared<string>(string(ident) + " " + + MessageDictionary::globalDictionary()->getText(ident))); +} + +// Replace the interprocess synchronization object + +void +LoggerImpl::setInterprocessSync(interprocess::InterprocessSync* sync) { + if (sync == NULL) { + isc_throw(BadInterprocessSync, + "NULL was passed to setInterprocessSync()"); + } + + delete sync_; + sync_ = sync; +} + +void +LoggerImpl::outputRaw(const Severity& severity, const string& message) { + // Use a mutex locker for mutual exclusion from other threads in + // this process. + std::lock_guard<std::mutex> mutex_locker(LoggerManager::getMutex()); + + // Use an interprocess sync locker for mutual exclusion from other + // processes to avoid log messages getting interspersed. + interprocess::InterprocessSyncLocker locker(*sync_); + + if (!locker.lock()) { + LOG4CPLUS_ERROR(logger_, "Unable to lock logger lockfile"); + } + + switch (severity) { + case DEBUG: + LOG4CPLUS_DEBUG(logger_, message); + break; + + case INFO: + LOG4CPLUS_INFO(logger_, message); + break; + + case WARN: + LOG4CPLUS_WARN(logger_, message); + break; + + case ERROR: + LOG4CPLUS_ERROR(logger_, message); + break; + + case FATAL: + LOG4CPLUS_FATAL(logger_, message); + break; + + case NONE: + break; + + default: + LOG4CPLUS_ERROR(logger_, + "Unsupported severity in LoggerImpl::outputRaw(): " + << severity); + } + + if (!locker.unlock()) { + LOG4CPLUS_ERROR(logger_, "Unable to unlock logger lockfile"); + } +} + +bool +LoggerImpl::hasAppender(OutputOption::Destination const destination) { + // Get the appender for the name under which this logger is registered. + log4cplus::SharedAppenderPtrList appenders( + log4cplus::Logger::getInstance(name_).getAllAppenders()); + + // If there are no appenders, they might be under the root name. + if (appenders.size() == 0) { + appenders = log4cplus::Logger::getInstance(getRootLoggerName()).getAllAppenders(); + } + + for (log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> logger : appenders) { + if (destination == OutputOption::DEST_CONSOLE && + dynamic_cast<log4cplus::ConsoleAppender*>(logger.get())) { + return true; + } else if (destination == OutputOption::DEST_FILE && + dynamic_cast<log4cplus::FileAppender*>(logger.get())) { + return true; + } else if (destination == OutputOption::DEST_SYSLOG && + dynamic_cast<log4cplus::SysLogAppender*>(logger.get())) { + return true; + } + } + return false; +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_impl.h b/src/lib/log/logger_impl.h new file mode 100644 index 0000000..d7dad45 --- /dev/null +++ b/src/lib/log/logger_impl.h @@ -0,0 +1,208 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_IMPL_H +#define LOGGER_IMPL_H + +#include <stdarg.h> +#include <time.h> + +#include <iostream> +#include <cstdlib> +#include <string> +#include <map> +#include <utility> + +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +// log4cplus logger header file +#include <log4cplus/logger.h> + +// Kea logger files +#include <log/logger_level_impl.h> +#include <log/message_types.h> +#include <log/interprocess/interprocess_sync.h> +#include <log/output_option.h> + +namespace isc { +namespace log { + +/// \brief Console Logger Implementation +/// +/// The logger uses a "pimpl" idiom for implementation, where the base logger +/// class contains little more than a pointer to the implementation class, and +/// all actions are carried out by the latter. +/// +/// This particular implementation is based on log4cplus (from sourceforge: +/// http://log4cplus.sourceforge.net). Particular items of note: +/// +/// a) Kea loggers have names of the form "program.sublogger". In other +/// words, each of the loggers is a sub-logger of the main program logger. +/// In log4cplus, there is a root logger (called "root" according to the +/// documentation, but actually unnamed) and all loggers created are subloggers +/// if it. +/// +/// In this implementation, the log4cplus root logger is unused. Instead, the +/// Kea root logger is created as a child of the log4cplus root logger, +/// and all other loggers used in the program are created as sub-loggers of +/// that. In this way, the logging system can just include the name of the +/// logger in each message without the need to specially consider if the +/// message is the root logger or not. +/// +/// b) The idea of debug levels is implemented. See logger_level.h and +/// logger_level_impl.h for more details on this. + +class LoggerImpl : public boost::noncopyable { +public: + + /// \brief Constructor + /// + /// Creates a logger of the specific name. + /// + /// \param name Name of the logger. + LoggerImpl(const std::string& name); + + + /// \brief Destructor + virtual ~LoggerImpl(); + + + /// \brief Version + static std::string getVersion(); + + + /// \brief Get the full name of the logger (including the root name) + virtual std::string getName() { + return (name_); + } + + + /// \brief Set Severity Level for Logger + /// + /// Sets the level at which this logger will log messages. If none is set, + /// the level is inherited from the parent. + /// + /// \param severity Severity level to log + /// \param dbglevel If the severity is DEBUG, this is the debug level. + /// This can be in the range 0 to 99 and controls the verbosity. A value + /// outside these limits is silently coerced to the nearest boundary. + virtual void setSeverity(Severity severity, int dbglevel = 1); + + + /// \brief Get Severity Level for Logger + /// + /// \return The current logging level of this logger. In most cases though, + /// the effective logging level is what is required. + virtual Severity getSeverity(); + + + /// \brief Get Effective Severity Level for Logger + /// + /// \return The effective severity level of the logger. This is the same + /// as getSeverity() if the logger has a severity level set, but otherwise + /// is the severity of the parent. + virtual Severity getEffectiveSeverity(); + + + /// \brief Return debug level + /// + /// \return Current setting of debug level. This will be zero if the + /// the current severity level is not DEBUG. + virtual int getDebugLevel(); + + + /// \brief Return effective debug level + /// + /// \return Current setting of effective debug level. This will be zero if + /// the current effective severity level is not DEBUG. + virtual int getEffectiveDebugLevel(); + + + /// \brief Returns if Debug Message Should Be Output + /// + /// \param dbglevel Level for which debugging is checked. Debugging is + /// enabled only if the logger has DEBUG enabled and if the dbglevel + /// checked is less than or equal to the debug level set for the logger. + virtual bool isDebugEnabled(int dbglevel = MIN_DEBUG_LEVEL) { + Level level(DEBUG, dbglevel); + return logger_.isEnabledFor(LoggerLevelImpl::convertFromBindLevel(level)); + } + + /// \brief Is INFO Enabled? + virtual bool isInfoEnabled() { + return (logger_.isEnabledFor(log4cplus::INFO_LOG_LEVEL)); + } + + /// \brief Is WARNING Enabled? + virtual bool isWarnEnabled() { + return (logger_.isEnabledFor(log4cplus::WARN_LOG_LEVEL)); + } + + /// \brief Is ERROR Enabled? + virtual bool isErrorEnabled() { + return (logger_.isEnabledFor(log4cplus::ERROR_LOG_LEVEL)); + } + + /// \brief Is FATAL Enabled? + virtual bool isFatalEnabled() { + return (logger_.isEnabledFor(log4cplus::FATAL_LOG_LEVEL)); + } + + /// \brief Raw output + /// + /// Writes the message with time into the log. Used by the Formatter + /// to produce output. + /// + /// \param severity Severity of the message. (This controls the prefix + /// label output with the message text.) + /// \param message Text of the message. + void outputRaw(const Severity& severity, const std::string& message); + + /// \brief Look up message text in dictionary + /// + /// This gets you the unformatted text of message for given ID. + boost::shared_ptr<std::string> lookupMessage(const MessageID& id); + + /// \brief Replace the interprocess synchronization object + /// + /// If this method is called with NULL as the argument, it throws a + /// BadInterprocessSync exception. + /// + /// \param sync The logger uses this synchronization object for + /// synchronizing output of log messages. It should be deletable and + /// the ownership is transferred to the logger implementation. + /// If NULL is passed, a BadInterprocessSync exception is thrown. + void setInterprocessSync(isc::log::interprocess::InterprocessSync* sync); + + /// @brief Check if this logger has an appender of the given type. + /// + /// @param destination the appender type to be checked: console, file or syslog + /// + /// @return true if an appender of the given type is found, false otherwise + bool hasAppender(OutputOption::Destination const destination); + + /// \brief Equality + /// + /// Check if two instances of this logger refer to the same stream. + /// (This method is principally for testing.) + /// + /// \return true if the logger objects are instances of the same logger. + bool operator==(const LoggerImpl& other) const { + return (name_ == other.name_); + } + +private: + std::string name_; ///< Full name of this logger + log4cplus::Logger logger_; ///< Underlying log4cplus logger + isc::log::interprocess::InterprocessSync* sync_; +}; + +} // namespace log +} // namespace isc + + +#endif // LOGGER_IMPL_H diff --git a/src/lib/log/logger_level.cc b/src/lib/log/logger_level.cc new file mode 100644 index 0000000..195d600 --- /dev/null +++ b/src/lib/log/logger_level.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/logger_level.h> +#include <log/macros.h> +#include <log/log_messages.h> + +#include <boost/algorithm/string.hpp> + + +namespace isc { +namespace log { + +isc::log::Severity +getSeverity(const std::string& sev_str) { + if (boost::iequals(sev_str, "DEBUG")) { + return isc::log::DEBUG; + } else if (boost::iequals(sev_str, "INFO")) { + return isc::log::INFO; + } else if (boost::iequals(sev_str, "WARN")) { + return isc::log::WARN; + } else if (boost::iequals(sev_str, "ERROR")) { + return isc::log::ERROR; + } else if (boost::iequals(sev_str, "FATAL")) { + return isc::log::FATAL; + } else if (boost::iequals(sev_str, "NONE")) { + return isc::log::NONE; + } else { + Logger logger("log"); + LOG_ERROR(logger, LOG_BAD_SEVERITY).arg(sev_str); + return isc::log::INFO; + } +} + + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_level.h b/src/lib/log/logger_level.h new file mode 100644 index 0000000..7732868 --- /dev/null +++ b/src/lib/log/logger_level.h @@ -0,0 +1,68 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_LEVEL_H +#define LOGGER_LEVEL_H + +#include <string> + +namespace isc { +namespace log { + +/// \brief Severity Levels +/// +/// Defines the severity levels for logging. This is shared between the logger +/// and the implementations classes. +/// +/// N.B. The order of the levels - DEBUG less than INFO less that WARN etc. is +/// implicitly assumed in several implementations. They must not be changed. + +typedef enum { + DEFAULT = 0, // Default to logging level of the parent + DEBUG = 1, + INFO = 2, + WARN = 3, + ERROR = 4, + FATAL = 5, + NONE = 6 // Disable logging +} Severity; + +/// Minimum/maximum debug levels. + +const int MIN_DEBUG_LEVEL = 0; +const int MAX_DEBUG_LEVEL = 99; + +/// \brief Log level structure +/// +/// A simple pair structure that provides suitable names for the members. It +/// holds a combination of logging severity and debug level. +struct Level { + Severity severity; ///< Logging severity + int dbglevel; ///< Debug level + + Level(Severity sev = DEFAULT, int dbg = MIN_DEBUG_LEVEL) : + severity(sev), dbglevel(dbg) + {} + + // Default assignment and copy constructor is appropriate +}; + +/// \brief Returns the isc::log::Severity value represented by the given string +/// +/// This must be one of the strings "DEBUG", "INFO", "WARN", "ERROR", "FATAL" or +/// "NONE". (Case is not important, but the string most not contain leading or +/// trailing spaces.) +/// +/// \param sev_str The string representing severity value +/// +/// \return The severity. If the string is not recognized, an error will be +/// logged and the string will return isc::log::INFO. +isc::log::Severity getSeverity(const std::string& sev_str); + +} // namespace log +} // namespace isc + +#endif // LOGGER_LEVEL_H diff --git a/src/lib/log/logger_level_impl.cc b/src/lib/log/logger_level_impl.cc new file mode 100644 index 0000000..a4aba73 --- /dev/null +++ b/src/lib/log/logger_level_impl.cc @@ -0,0 +1,215 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <algorithm> +#include <string.h> +#include <iostream> +#include <boost/lexical_cast.hpp> + +#include <log4cplus/logger.h> + +#include <log/logger_level.h> +#include <log/logger_level_impl.h> +#include <log/logimpl_messages.h> +#include <log/macros.h> + +using namespace log4cplus; +using namespace std; + +namespace { +isc::log::Logger logger("log"); +} + +namespace isc { +namespace log { + +// Convert Kea level to a log4cplus logging level. +log4cplus::LogLevel +LoggerLevelImpl::convertFromBindLevel(const Level& level) { + + // Kea logging levels are small integers so we can do a table lookup + static const log4cplus::LogLevel log4cplus_levels[] = { + log4cplus::NOT_SET_LOG_LEVEL, + log4cplus::DEBUG_LOG_LEVEL, + log4cplus::INFO_LOG_LEVEL, + log4cplus::WARN_LOG_LEVEL, + log4cplus::ERROR_LOG_LEVEL, + log4cplus::FATAL_LOG_LEVEL, + log4cplus::OFF_LOG_LEVEL + }; + + // ... with compile-time checks to ensure that table indexes are correct. + BOOST_STATIC_ASSERT(static_cast<int>(DEFAULT) == 0); + BOOST_STATIC_ASSERT(static_cast<int>(DEBUG) == 1); + BOOST_STATIC_ASSERT(static_cast<int>(INFO) == 2); + BOOST_STATIC_ASSERT(static_cast<int>(WARN) == 3); + BOOST_STATIC_ASSERT(static_cast<int>(ERROR) == 4); + BOOST_STATIC_ASSERT(static_cast<int>(FATAL) == 5); + BOOST_STATIC_ASSERT(static_cast<int>(NONE) == 6); + + // Do the conversion + if (level.severity == DEBUG) { + + // Debug severity, so the log4cplus level returned depends on the + // debug level. Silently limit the debug level to the range + // MIN_DEBUG_LEVEL to MAX_DEBUG_LEVEL (avoids the hassle of throwing + // and catching exceptions and besides, this is for debug information). + int limited = std::max(MIN_DEBUG_LEVEL, + std::min(level.dbglevel, MAX_DEBUG_LEVEL)); + LogLevel newlevel = static_cast<int>(DEBUG_LOG_LEVEL - + (limited - MIN_DEBUG_LEVEL)); + return (static_cast<log4cplus::LogLevel>(newlevel)); + + } else { + + // Can do a table lookup to speed things up. There is no need to check + // that the index is out of range. That the variable is of type + // isc::log::Severity ensures that it must be one of the Severity enum + // members - conversion of a numeric value to an enum is not permitted. + return (log4cplus_levels[level.severity]); + } +} + +// Convert log4cplus logging level to Kea debug level. It is up to the +// caller to validate that the debug level is valid. +Level +LoggerLevelImpl::convertToBindLevel(const log4cplus::LogLevel loglevel) { + + // Not easy to do a table lookup as the numerical values of log4cplus levels + // are quite high. + if (loglevel <= log4cplus::NOT_SET_LOG_LEVEL) { + return (Level(DEFAULT)); + + } else if (loglevel <= log4cplus::DEBUG_LOG_LEVEL) { + + // Debug severity, so extract the debug level from the numeric value. + // If outside the limits, change the severity to the level above or + // below. + int dbglevel = MIN_DEBUG_LEVEL + + static_cast<int>(log4cplus::DEBUG_LOG_LEVEL) - + static_cast<int>(loglevel); + if (dbglevel > MAX_DEBUG_LEVEL) { + return (Level(DEFAULT)); + } else if (dbglevel < MIN_DEBUG_LEVEL) { + return (Level(INFO)); + } + return (Level(DEBUG, dbglevel)); + + } else if (loglevel <= log4cplus::INFO_LOG_LEVEL) { + return (Level(INFO)); + + } else if (loglevel <= log4cplus::WARN_LOG_LEVEL) { + return (Level(WARN)); + + } else if (loglevel <= log4cplus::ERROR_LOG_LEVEL) { + return (Level(ERROR)); + + } else if (loglevel <= log4cplus::FATAL_LOG_LEVEL) { + return (Level(FATAL)); + + } + + return (Level(NONE)); +} + + +// Convert string to appropriate logging level +log4cplus::LogLevel +LoggerLevelImpl::logLevelFromString(const log4cplus::tstring& level) { + + std::string name = level; // Get to known type + size_t length = name.size(); // Length of the string + + if (length < 5) { + + // String can't possibly start DEBUG so we don't know what it is. + // As per documentation, return NOT_SET level. + return (NOT_SET_LOG_LEVEL); + } else { + if (strncasecmp(name.c_str(), "DEBUG", 5) == 0) { + + // String starts "DEBUG" (or "debug" or any case mixture). The + // rest of the string - if any - should be a number. + if (length == 5) { + + // It is plain "DEBUG". Take this as level 0. + return (DEBUG_LOG_LEVEL); + } else { + + // Try converting the remainder to an integer. The "5" is + // the length of the string "DEBUG". Note that if the number + // is outside the range of debug levels, it is coerced to the + // nearest limit. Thus a level of DEBUG509 will end up as + // if DEBUG99 has been specified. + try { + int dbglevel = boost::lexical_cast<int>(name.substr(5)); + if (dbglevel < MIN_DEBUG_LEVEL) { + LOG_WARN(logger, LOGIMPL_BELOW_MIN_DEBUG).arg(dbglevel) + .arg(MIN_DEBUG_LEVEL); + dbglevel = MIN_DEBUG_LEVEL; + + } else if (dbglevel > MAX_DEBUG_LEVEL) { + LOG_WARN(logger, LOGIMPL_ABOVE_MAX_DEBUG).arg(dbglevel) + .arg(MAX_DEBUG_LEVEL); + dbglevel = MAX_DEBUG_LEVEL; + + } + return convertFromBindLevel(Level(DEBUG, dbglevel)); + } + catch (const boost::bad_lexical_cast&) { + LOG_ERROR(logger, LOGIMPL_BAD_DEBUG_STRING).arg(name); + return (NOT_SET_LOG_LEVEL); + } + } + } else { + + // Unknown string - return default. Log4cplus will call any other + // registered conversion functions to interpret it. + return (NOT_SET_LOG_LEVEL); + } + } +} + +// Convert logging level to string. If the level is a valid debug level, +// return the string DEBUG, else return the empty string. +#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0) +LoggerLevelImpl::LogLevelString +#else +const LoggerLevelImpl::LogLevelString& +#endif +LoggerLevelImpl::logLevelToString(log4cplus::LogLevel level) { + Level bindlevel = convertToBindLevel(level); + Severity& severity = bindlevel.severity; + int& dbglevel = bindlevel.dbglevel; + static LoggerLevelImpl::LogLevelString debug_ = tstring("DEBUG"); + static LoggerLevelImpl::LogLevelString empty_ = tstring(); + + if ((severity == DEBUG) && + ((dbglevel >= MIN_DEBUG_LEVEL) && (dbglevel <= MAX_DEBUG_LEVEL))) { + return (debug_); + } + + // Unknown, so return empty string for log4cplus to try other conversion + // functions. + return (empty_); +} + +// Initialization. Register the conversion functions with the LogLevelManager. +void +LoggerLevelImpl::init() { + + // Get the singleton log-level manager. + LogLevelManager& manager = getLogLevelManager(); + + // Register the conversion functions + manager.pushFromStringMethod(LoggerLevelImpl::logLevelFromString); + manager.pushToStringMethod(LoggerLevelImpl::logLevelToString); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_level_impl.h b/src/lib/log/logger_level_impl.h new file mode 100644 index 0000000..77da5f7 --- /dev/null +++ b/src/lib/log/logger_level_impl.h @@ -0,0 +1,126 @@ +// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_LEVEL_IMPL_H +#define LOGGER_LEVEL_IMPL_H + +#include <log4cplus/logger.h> +#include <log4cplus/version.h> +#include <log/logger_level.h> + +namespace isc { +namespace log { + +/// \brief Implementation aspects of logging levels +/// +/// This extends the log4cplus level set to allow 100 debug levels. +/// +/// First some terminology, as the use of the term "level" gets confusing. The +/// code and comments here use the term "level" in two contexts: +/// +/// Logging level: The category of messages to log. By default log4cplus +/// defines the following logging levels: OFF_LOG_LEVEL, FATAL_LOG_LEVEL, +/// ERROR_LOG_LEVEL, WARN_LOG_LEVEL, INFO_LOG_LEVEL, DEBUG_LOG_LEVEL, +/// TRACE_LOG_LEVEL, ALL_LOG_LEVEL (which here will be abbreviated OFF, FATAL +/// etc.). Within the context of Kea, OFF, TRACE and ALL are not used +/// and the idea of DEBUG has been extended, as will be seen below. In +/// Kea terms, this is known as "severity"; the "logging level" usage will +/// usually be used when talking about log4cplus aspects of the idea (as +/// log4cplus uses that terminology). +/// +/// Debug level: This is a number that ranges from 0 to 99 and is used by the +/// application to control the detail of debug output. A value of 0 gives the +/// highest-level debug output; a value of 99 gives the most verbose and most +/// detailed. Debug messages (or whatever debug level) are only ever output +/// when the logging level is set to DEBUG. (Note that the numbers 0 and 99 +/// are not hard-coded - they are the constants MIN_DEBUG_LEVEL and +/// MAX_DEBUG_LEVEL.) +/// +/// With log4cplus, the various logging levels have a numeric value associated +/// with them, such that FATAL > ERROR > WARNING etc. This suggests that the +/// idea of debug levels can be incorporated into the existing logging level +/// scheme by assigning them appropriate numeric values, i.e. +/// +/// WARNING > INFO > DEBUG > DEBUG - 1 > DEBUG - 2 > ... > DEBUG - 99 +/// +/// Setting a numeric level of DEBUG enables the basic messages; setting higher +/// debug levels (corresponding to lower numeric logging levels) will enable +/// progressively more messages. The lowest debug level (0) is chosen such that +/// it corresponds to the default level of DEBUG. +/// +/// This class comprises nothing more than static methods to aid the conversion +/// of logging levels between log4cplus and Kea, and to register those +/// levels with log4cplus. + +class LoggerLevelImpl { +public: + +typedef log4cplus::tstring LogLevelString; + + /// \brief Convert Kea level to log4cplus logging level + /// + /// Converts the Kea severity level into a log4cplus logging level. + /// If the severity is DEBUG, the current Kea debug level is taken + /// into account when doing the conversion. + /// + /// \param level Kea severity and debug level + /// + /// \return Equivalent log4cplus logging level. + static + log4cplus::LogLevel convertFromBindLevel(const isc::log::Level& level); + + /// \brief Convert log4cplus logging level to Kea logging level + /// + /// Converts the log4cplus log level into a Kea severity level. + /// The log4cplus log level may be non-standard in which case it is + /// encoding a Kea debug level as well. + /// + /// \param loglevel log4cplus log level + /// + /// \return Equivalent Kea severity and debug level + static + isc::log::Level convertToBindLevel(const log4cplus::LogLevel loglevel); + + /// \brief Convert string to log4cplus logging level + /// + /// Kea extends the set of logging levels in log4cplus with a group + /// of debug levels. These are given names DEBUG0 through DEBUG99 (with + /// DEBUG0 being equivalent to DEBUG, the standard log level. If the name + /// is DEBUGn but n lies outside the range of debug levels, debug level + /// specifies is coerced to the nearest valid value. If the string is just + /// not recognized, a NOT_SET_LOG_LEVEL is returned. + /// + /// \param level String representing the logging level. + /// + /// \return Corresponding log4cplus log level + static + log4cplus::LogLevel logLevelFromString(const log4cplus::tstring& level); + + /// \brief Convert log level to string + /// + /// If the log level is one of the extended debug levels, the string DEBUG + /// is returned, otherwise the empty string. + /// + /// \param level Extended logging level + /// + /// \return Equivalent string. +#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0) + static LogLevelString logLevelToString(log4cplus::LogLevel level); +#else + static const LogLevelString& logLevelToString(log4cplus::LogLevel level); +#endif + + /// \brief Initialize extended logging levels + /// + /// This must be called once, after log4cplus has been initialized. It + /// registers the level/string converter functions. + static void init(); +}; + +} // namespace log +} // namespace isc + +#endif // LOGGER_LEVEL_IMPL_H diff --git a/src/lib/log/logger_manager.cc b/src/lib/log/logger_manager.cc new file mode 100644 index 0000000..1890706 --- /dev/null +++ b/src/lib/log/logger_manager.cc @@ -0,0 +1,216 @@ +// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <algorithm> +#include <vector> + +#include <log/logger.h> +#include <log/logger_manager.h> +#include <log/logger_manager_impl.h> +#include <log/logger_name.h> +#include <log/logger_support.h> +#include <log/log_messages.h> +#include <log/macros.h> +#include <log/message_dictionary.h> +#include <log/message_exception.h> +#include <log/message_initializer.h> +#include <log/message_reader.h> +#include <log/message_types.h> +#include <log/interprocess/interprocess_sync_null.h> + +using namespace std; + +// Older log4cplus versions (1.2.0) don't have the initializer.h header that +// would allow explicit initialization. Newer versions (2.0.4 for sure, possibly +// older as well) have it and it's recommended to use it. We detect whether +// it's present or not and do explicit initialization if possible. +#ifdef LOG4CPLUS_INITIALIZER_H +#include <log4cplus/initializer.h> +namespace { +log4cplus::Initializer initializer; +} +#endif + +namespace { + +// Logger used for logging messages within the logging code itself. +isc::log::Logger logger("log"); + +// Static stores for the initialization severity and debug level. +// These are put in methods to avoid a "static initialization fiasco". + +isc::log::Severity& initSeverity() { + static isc::log::Severity severity = isc::log::INFO; + return (severity); +} + +int& initDebugLevel() { + static int dbglevel = 0; + return (dbglevel); +} + +std::string& initRootName() { + static std::string root(isc::log::getDefaultRootLoggerName()); + return (root); +} + +} // Anonymous namespace + + +namespace isc { +namespace log { + +// Constructor - create the implementation class. +LoggerManager::LoggerManager() { + impl_ = new LoggerManagerImpl(); +} + +// Destructor - get rid of the implementation class +LoggerManager::~LoggerManager() { + delete impl_; +} + +// Initialize processing +void +LoggerManager::processInit() { + impl_->processInit(); +} + +// Process logging specification +void +LoggerManager::processSpecification(const LoggerSpecification& spec) { + impl_->processSpecification(spec); +} + +// End Processing +void +LoggerManager::processEnd() { + impl_->processEnd(); +} + + +/// Logging system initialization + +void +LoggerManager::init(const std::string& root, isc::log::Severity severity, + int dbglevel, const char* file, bool buffer) +{ + // Load in the messages declared in the program and registered by + // statically-declared MessageInitializer objects. + MessageInitializer::loadDictionary(); + + // Save name, severity and debug level for later. No need to save the + // file name as once the local message file is read the messages will + // not be lost. + initRootName() = root; + initSeverity() = severity; + initDebugLevel() = dbglevel; + + // Create the Kea root logger and set the default severity and + // debug level. This is the logger that has the name of the application. + // All other loggers created in this application will be its children. + setRootLoggerName(root); + + // Initialize the implementation logging. After this point, some basic + // logging has been set up and messages can be logged. + // However, they will not appear until a logging specification has been + // processed (or the program exits), see TODO + LoggerManagerImpl::init(severity, dbglevel, buffer); + setLoggingInitialized(); + + // Check if there were any duplicate message IDs in the default dictionary + // and if so, log them. Log using the logging facility logger. + logDuplicatedMessages(); + + // Replace any messages with local ones (if given) + if (file) { + readLocalMessageFile(file); + } + + // Ensure that the mutex is constructed and ready at this point. + (void) getMutex(); +} + +void +LoggerManager::logDuplicatedMessages() { + const list<string>& duplicates = MessageInitializer::getDuplicates(); + if (!duplicates.empty()) { + + // There are duplicates present. This list itself may contain + // duplicates; if so, the message ID is listed as many times as + // there are duplicates. + for (list<string>::const_iterator i = duplicates.begin(); + i != duplicates.end(); ++i) { + LOG_WARN(logger, LOG_DUPLICATE_MESSAGE_ID).arg(*i); + } + MessageInitializer::clearDuplicates(); + } +} + + +// Read local message file +// TODO This should be done after the configuration has been read so that +// the file can be placed in the local configuration +void +LoggerManager::readLocalMessageFile(const char* file) { + + const MessageDictionaryPtr& dictionary = MessageDictionary::globalDictionary(); + MessageReader reader(dictionary.get()); + + // Turn off use of any lock files. This is because this logger can + // be used by standalone programs which may not have write access to + // the local state directory (to create lock files). So we switch to + // using a null interprocess sync object here. + logger.setInterprocessSync( + new isc::log::interprocess::InterprocessSyncNull("logger")); + + try { + + logger.info(LOG_READING_LOCAL_FILE).arg(file); + reader.readFile(file, MessageReader::REPLACE); + + // File successfully read. As each message in the file is supposed to + // replace one in the dictionary, any ID read that can't be located in + // the dictionary will not be used. To aid problem diagnosis, the + // unknown message IDs are listed. + MessageReader::MessageIDCollection unknown = reader.getNotAdded(); + for (MessageReader::MessageIDCollection::const_iterator + i = unknown.begin(); i != unknown.end(); ++i) { + string message_id = boost::lexical_cast<string>(*i); + logger.warn(LOG_NO_SUCH_MESSAGE).arg(message_id); + } + } + catch (const MessageException& e) { + MessageID ident = e.id(); + vector<string> args = e.arguments(); + + // Log the variable number of arguments. The actual message will be + // logged when the error_message variable is destroyed. + Formatter<isc::log::Logger> error_message = logger.error(ident); + for (vector<string>::size_type i = 0; i < args.size(); ++i) { + error_message = error_message.arg(args[i]); + } + } +} + +// Reset logging to settings passed to init() +void +LoggerManager::reset() { + setRootLoggerName(initRootName()); + LoggerManagerImpl::reset(initSeverity(), initDebugLevel()); +} + +std::mutex& +LoggerManager::getMutex() { + static std::mutex mutex; + + return (mutex); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_manager.h b/src/lib/log/logger_manager.h new file mode 100644 index 0000000..1ddea6d --- /dev/null +++ b/src/lib/log/logger_manager.h @@ -0,0 +1,173 @@ +// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_MANAGER_H +#define LOGGER_MANAGER_H + +#include <exceptions/exceptions.h> +#include <log/logger_specification.h> + +#include <boost/noncopyable.hpp> + +#include <mutex> + +// Generated if, when updating the logging specification, an unknown +// destination is encountered. +class UnknownLoggingDestination : public isc::Exception { +public: + UnknownLoggingDestination(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) + {} +}; + +namespace isc { +namespace log { + +class LoggerManagerImpl; + +/// \brief Logger Manager +/// +/// The logger manager class exists to process the set of logger specifications +/// and use them to set up the logging in the program appropriately. +/// +/// To isolate the underlying implementation from basic processing, the +/// LoggerManager is implemented using the "pimpl" idiom. + +class LoggerManager : public boost::noncopyable { +public: + /// \brief Constructor + LoggerManager(); + + /// \brief Destructor + ~LoggerManager(); + + /// \brief Process Specifications + /// + /// Replaces the current logging configuration by the one given. + /// + /// \param start Iterator pointing to the start of the collection of + /// logging specifications. + /// \param finish Iterator pointing to the end of the collection of + /// logging specification. + template <typename T> + void process(T start, T finish) { + processInit(); + for (T i = start; i != finish; ++i) { + processSpecification(*i); + } + processEnd(); + } + + /// \brief Process a single specification + /// + /// A convenience function for a single specification. + /// + /// \param spec Specification to process + void process(const LoggerSpecification& spec) { + processInit(); + processSpecification(spec); + processEnd(); + } + + /// \brief Process 'empty' specification + /// + /// This will disable any existing output options, and set + /// the logging to go to the built-in default (stdout). + /// If the logger has been initialized with buffering enabled, + /// all log messages up to now shall be printed to stdout. + /// + /// This is mainly useful in scenarios where buffering is needed, + /// but it turns out there are no logging specifications to + /// handle. + void process() { + processInit(); + processEnd(); + } + + /// \brief Run-Time Initialization + /// + /// Performs run-time initialization of the logger system, in particular + /// supplying the root logger name and name of a replacement message file. + /// + /// This must be the first logging function called in the program. If + /// an attempt is made to log a message before this is function is called, + /// the results will be dependent on the underlying logging package. + /// + /// Any duplicate log IDs encountered are reported as warning, after which + /// the global duplicates vector is cleared + /// + /// \param root Name of the root logger. This should be set to the name of + /// the program. + /// \param severity Severity at which to log + /// \param dbglevel Debug severity (ignored if "severity" is not "DEBUG") + /// \param file Name of the local message file. This must be NULL if there + /// is no local message file. + /// \param buffer If true, all log messages will be buffered until one of + /// the \c process() methods is called. If false, initial logging + /// shall go to the default output (i.e. stdout) + static void init(const std::string& root, + isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, const char* file = NULL, + bool buffer = false); + + /// \brief List duplicated log messages. + /// + /// Lists the duplicated log messages using warning severity. Then, it + /// clears the list of duplicated messages. This method is called by the + /// \c init method and by the \c isc::hooks::LibraryManager when the new + /// hooks library is loaded. + static void logDuplicatedMessages(); + + /// \brief Reset logging + /// + /// Resets logging to whatever was set in the call to init(), expect for + /// the buffer option. + static void reset(); + + /// \brief Read local message file + /// + /// Reads the local message file into the global dictionary, overwriting + /// existing messages. If the file contained any message IDs not in the + /// dictionary, they are listed in a warning message. + /// + /// \param file Name of the local message file + static void readLocalMessageFile(const char* file); + + /// \brief Return a process-global mutex that's used for mutual + /// exclusion among threads of a single process during logging + /// calls. + static std::mutex& getMutex(); + +private: + /// \brief Initialize Processing + /// + /// Initializes the processing of a list of specifications by resetting all + /// loggers to their defaults, which is to pass the message to their + /// parent logger. (Except for the root logger, where the default action is + /// to output the message.) + void processInit(); + + /// \brief Process Logging Specification + /// + /// Processes the given specification. It is assumed at this point that + /// either the logger does not exist or has been made inactive. + void processSpecification(const LoggerSpecification& spec); + + /// \brief End Processing + /// + /// Place holder for finish processing. + /// TODO: Check that the root logger has something enabled + void processEnd(); + + // Members + LoggerManagerImpl* impl_; ///< Pointer to implementation +}; + +} // namespace log +} // namespace isc + + +#endif // LOGGER_MANAGER_H diff --git a/src/lib/log/logger_manager_impl.cc b/src/lib/log/logger_manager_impl.cc new file mode 100644 index 0000000..946e163 --- /dev/null +++ b/src/lib/log/logger_manager_impl.cc @@ -0,0 +1,322 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <algorithm> +#include <iostream> +#include <array> + +#include <log4cplus/logger.h> +#include <log4cplus/configurator.h> +#include <log4cplus/hierarchy.h> +#include <log4cplus/consoleappender.h> +#include <log4cplus/fileappender.h> +#include <log4cplus/syslogappender.h> +#include <log4cplus/helpers/loglog.h> +#include <log4cplus/version.h> + +#include <log/logger.h> +#include <log/logger_support.h> +#include <log/logger_level_impl.h> +#include <log/logger_manager.h> +#include <log/logger_manager_impl.h> +#include <log/log_messages.h> +#include <log/logger_name.h> +#include <log/logger_specification.h> +#include <log/buffer_appender_impl.h> + +#include <exceptions/isc_assert.h> + +#include <boost/lexical_cast.hpp> + +using namespace std; +using boost::lexical_cast; + +namespace isc { +namespace log { + +// Reset hierarchy of loggers back to default settings. This removes all +// appenders from loggers, sets their severity to NOT_SET (so that events are +// passed back to the parent) and resets the root logger to logging +// informational messages. (This last is not a log4cplus default, so we have to +// explicitly reset the logging severity.) +void +LoggerManagerImpl::processInit() { + storeBufferAppenders(); + + log4cplus::Logger::getDefaultHierarchy().resetConfiguration(); + initRootLogger(); +} + +// Flush the BufferAppenders at the end of processing a new specification +void +LoggerManagerImpl::processEnd() { + flushBufferAppenders(); +} + +// Process logging specification. Set up the common states then dispatch to +// add output specifications. +void +LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) { + string const& name(spec.getName()); + string const& root_logger_name(getRootLoggerName()); + + log4cplus::Logger logger = log4cplus::Logger::getInstance(expandLoggerName(name)); + + // Set severity level according to specification entry. + logger.setLogLevel(LoggerLevelImpl::convertFromBindLevel( + Level(spec.getSeverity(), spec.getDbglevel()))); + + // Set the additive flag. + logger.setAdditivity(spec.getAdditive()); + + // Replace all appenders for this logger. + logger.removeAllAppenders(); + + if (name == root_logger_name) { + // Store a copy of the root specification. It might be required later. + root_spec_ = spec; + } + + // Output options given? + if (spec.optionCount() > 0) { + // If there are output options provided, continue with the given spec. + appenderFactory(logger, spec); + } else { + // If there are no output options, inherit them from the root logger. + // It's important that root_spec_.getName() is not used further since it + // may be different than the logger being configured here. + appenderFactory(logger, root_spec_); + } +} + +void +LoggerManagerImpl::appenderFactory(log4cplus::Logger& logger, + LoggerSpecification const& spec) { + for (OutputOption const& i : spec) { + switch (i.destination) { + case OutputOption::DEST_CONSOLE: + createConsoleAppender(logger, i); + break; + + case OutputOption::DEST_FILE: + createFileAppender(logger, i); + break; + + case OutputOption::DEST_SYSLOG: + createSyslogAppender(logger, i); + break; + + default: + // Not a valid destination. As we are in the middle of updating + // logging destinations, we could be in the situation where + // there are no valid appenders. For this reason, throw an + // exception. + isc_throw(UnknownLoggingDestination, + "Unknown logging destination, code = " << i.destination); + } + } +} + +// Console appender - log to either stdout or stderr. +void +LoggerManagerImpl::createConsoleAppender(log4cplus::Logger& logger, + const OutputOption& opt) +{ + log4cplus::SharedAppenderPtr console( + new log4cplus::ConsoleAppender( + (opt.stream == OutputOption::STR_STDERR), opt.flush)); + + setAppenderLayout(console, (opt.pattern.empty() ? + OutputOption::DEFAULT_CONSOLE_PATTERN : opt.pattern)); + logger.addAppender(console); +} + +// File appender. Depending on whether a maximum size is given, either +// a standard file appender or a rolling file appender will be created. +// In the case of the latter, we set "UseLockFile" to true so that +// log4cplus internally avoids race in rolling over the files by multiple +// processes. This feature isn't supported in log4cplus 1.0.x, but setting +// the property unconditionally is okay as unknown properties are simply +// ignored. +void +LoggerManagerImpl::createFileAppender(log4cplus::Logger& logger, + const OutputOption& opt) +{ + // Append to existing file + const std::ios::openmode mode = std::ios::app; + + log4cplus::SharedAppenderPtr fileapp; + if (opt.maxsize == 0) { + fileapp = log4cplus::SharedAppenderPtr(new log4cplus::FileAppender( + opt.filename, mode, opt.flush)); + } else { + log4cplus::helpers::Properties properties; + properties.setProperty("File", opt.filename); + + // log4cplus supports file sizes past INT_MAX only in suffixed format. + // Convert from integer. + uint64_t maxsize(opt.maxsize); + size_t i(0); + while (std::numeric_limits<int32_t>::max() < maxsize && i < 2) { + maxsize /= 1000; + ++i; + } + std::array<std::string, 3> const suffixes({"", "KB", "MB"}); + std::string const max_file_size(to_string(maxsize) + suffixes[i]); + + // If maxsize is still past INT_MAX, it will overflow in log4cplus, + // so stop here instead. + if (std::numeric_limits<int32_t>::max() < maxsize) { + isc_throw(BadValue, "expected maxsize < " + << std::numeric_limits<int32_t>::max() + << "MB, but instead got " << max_file_size); + } + + properties.setProperty("MaxFileSize", max_file_size); + properties.setProperty("MaxBackupIndex", + lexical_cast<string>(opt.maxver)); + properties.setProperty("ImmediateFlush", opt.flush ? "true" : "false"); + properties.setProperty("UseLockFile", "true"); + fileapp = log4cplus::SharedAppenderPtr( + new log4cplus::RollingFileAppender(properties)); + } + + setAppenderLayout(fileapp, (opt.pattern.empty() ? + OutputOption::DEFAULT_FILE_PATTERN : opt.pattern)); + logger.addAppender(fileapp); +} + +void +LoggerManagerImpl::createBufferAppender(log4cplus::Logger& logger) { + log4cplus::SharedAppenderPtr bufferapp(new internal::BufferAppender()); + bufferapp->setName("buffer"); + logger.addAppender(bufferapp); + // Since we do not know at what level the loggers will end up + // running, set it to the highest for now + logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL); +} + +// Syslog appender. +void +LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger, + const OutputOption& opt) +{ + log4cplus::helpers::Properties properties; + properties.setProperty("ident", getRootLoggerName()); + properties.setProperty("facility", opt.facility); + log4cplus::SharedAppenderPtr syslogapp( + new log4cplus::SysLogAppender(properties)); + setAppenderLayout(syslogapp, (opt.pattern.empty() ? + OutputOption::DEFAULT_SYSLOG_PATTERN : opt.pattern)); + logger.addAppender(syslogapp); +} + + +// One-time initialization of the log4cplus system +void +LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel, + bool buffer) +{ + // Set up basic configurator. This attaches a ConsoleAppender to the + // root logger with suitable output. This is used until we we have + // actually read the logging configuration, in which case the output + // may well be changed. + log4cplus::BasicConfigurator config; + config.configure(); + + // Add the additional debug levels + LoggerLevelImpl::init(); + + initRootLogger(severity, dbglevel, buffer); +} + +// Reset logging to default configuration. This closes all appenders +// and resets the root logger to output INFO messages to the console. +// It is principally used in testing. +void +LoggerManagerImpl::reset(isc::log::Severity severity, int dbglevel) +{ + // Initialize the root logger + initRootLogger(severity, dbglevel); +} + +// Initialize the root logger +void LoggerManagerImpl::initRootLogger(isc::log::Severity severity, + int dbglevel, bool buffer) +{ + log4cplus::Logger::getDefaultHierarchy().resetConfiguration(); + + // Disable log4cplus' own logging, unless --enable-debug was + // specified to configure. Note that this does not change + // LogLog's levels (that is still just INFO). +#ifndef ENABLE_DEBUG + log4cplus::helpers::LogLog::getLogLog()->setQuietMode(true); +#endif + + // Set the log4cplus root to not output anything - effectively we are + // ignoring it. + log4cplus::Logger::getRoot().setLogLevel(log4cplus::OFF_LOG_LEVEL); + + // Set the level for the Kea root logger to the given severity and + // debug level. + log4cplus::Logger kea_root = log4cplus::Logger::getInstance( + getRootLoggerName()); + kea_root.setLogLevel(LoggerLevelImpl::convertFromBindLevel( + Level(severity, dbglevel))); + + if (buffer) { + createBufferAppender(kea_root); + } else { + OutputOption opt; + createConsoleAppender(kea_root, opt); + } +} + + +void LoggerManagerImpl::setAppenderLayout( + log4cplus::SharedAppenderPtr& appender, + std::string pattern) +{ + // Finally the text of the message + appender->setLayout( +#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0) + auto_ptr<log4cplus::Layout> +#else + unique_ptr<log4cplus::Layout> +#endif + (new log4cplus::PatternLayout(pattern))); +} + +void LoggerManagerImpl::storeBufferAppenders() { + // Walk through all loggers, and find any buffer appenders there + log4cplus::LoggerList loggers = log4cplus::Logger::getCurrentLoggers(); + log4cplus::LoggerList::iterator it; + for (it = loggers.begin(); it != loggers.end(); ++it) { + log4cplus::SharedAppenderPtr buffer_appender = + it->getAppender("buffer"); + if (buffer_appender) { + buffer_appender_store_.push_back(buffer_appender); + } + } +} + +void LoggerManagerImpl::flushBufferAppenders() { + std::vector<log4cplus::SharedAppenderPtr> copy; + buffer_appender_store_.swap(copy); + + std::vector<log4cplus::SharedAppenderPtr>::iterator it; + for (it = copy.begin(); it != copy.end(); ++it) { + internal::BufferAppender* app = + dynamic_cast<internal::BufferAppender*>(it->get()); + isc_throw_assert(app); + app->flush(); + } +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_manager_impl.h b/src/lib/log/logger_manager_impl.h new file mode 100644 index 0000000..c459cfe --- /dev/null +++ b/src/lib/log/logger_manager_impl.h @@ -0,0 +1,197 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_MANAGER_IMPL_H +#define LOGGER_MANAGER_IMPL_H + +#include <string> + +#include <log4cplus/appender.h> +#include <log/logger_level.h> +#include <log/logger_specification.h> + +// Forward declaration to avoid need to include log4cplus header file here. +namespace log4cplus { +class Logger; +class Appender; +} + +namespace isc { +namespace log { + +// Forward declarations +struct OutputOption; + +/// \brief Logger Manager Implementation +/// +/// This is the implementation of the logger manager for the log4cplus +/// underlying logger. +/// +/// As noted in logger_manager.h, the logger manager class exists to set up the +/// logging given a set of specifications. This class handles the processing +/// of those specifications. +/// +/// Note: the logging has been implemented using a "pimpl" idiom to conceal +/// the underlying implementation (log4cplus) from the Kea interface. +/// This requires that there be an implementation class, even though in this +/// case, all the implementation class methods can be declared static. + +class LoggerManagerImpl { +public: + + /// \brief Constructor + LoggerManagerImpl() {} + + /// \brief Initialize Processing + /// + /// This resets the hierarchy of loggers back to their defaults. This means + /// that all non-root loggers (if they exist) are set to NOT_SET, and the + /// root logger reset to logging informational messages. + void processInit(); + + /// \brief Process Specification + /// + /// Processes the specification for a single logger. + /// + /// \param spec Logging specification for this logger + void processSpecification(const LoggerSpecification& spec); + + /// \brief End Processing + /// + /// Terminates the processing of the logging specifications. + void processEnd(); + + /// \brief Implementation-specific initialization + /// + /// Sets the basic configuration for logging (the root logger has INFO and + /// more severe messages routed to stdout). Unless this function (or + /// process() with a valid specification for all loggers that will log + /// messages) is called before a message is logged, log4cplus will output + /// a message to stderr noting that logging has not been initialized. + /// + /// It is assumed here that the name of the Kea root logger can be + /// obtained from the global function getRootLoggerName(). + /// + /// \param severity Severity to be associated with this logger + /// \param dbglevel Debug level associated with the root logger + /// \param buffer If true, all log messages will be buffered until one of + /// the \c process() methods is called. If false, initial logging + /// shall go to the default output (i.e. stdout) + static void init(isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, bool buffer = false); + + /// \brief Reset logging + /// + /// Resets to default configuration (root logger logging to the console + /// with INFO severity). + /// + /// \param severity Severity to be associated with this logger + /// \param dbglevel Debug level associated with the root logger + static void reset(isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0); + +private: + /// @brief Decides what appender to create. + /// + /// Delegates to the other functions that create appenders based on what's + /// in spec. + /// + /// @param logger log4cplus logger to which the appender must be attached + /// @param spec the configured specification consisting of output options + static void appenderFactory(log4cplus::Logger& logger, + LoggerSpecification const& spec); + + /// \brief Create console appender + /// + /// Creates an object that, when attached to a logger, will log to one + /// of the output streams (stdout or stderr). + /// + /// \param logger Log4cplus logger to which the appender must be attached. + /// \param opt Output options for this appender. + static void createConsoleAppender(log4cplus::Logger& logger, + const OutputOption& opt); + + /// \brief Create file appender + /// + /// Creates an object that, when attached to a logger, will log to a + /// specified file. This also includes the ability to "roll" files when + /// they reach a specified size. + /// + /// \param logger Log4cplus logger to which the appender must be attached. + /// \param opt Output options for this appender. + static void createFileAppender(log4cplus::Logger& logger, + const OutputOption& opt); + + /// \brief Create syslog appender + /// + /// Creates an object that, when attached to a logger, will log to the + /// syslog file. + /// + /// \param logger Log4cplus logger to which the appender must be attached. + /// \param opt Output options for this appender. + static void createSyslogAppender(log4cplus::Logger& logger, + const OutputOption& opt); + + /// \brief Create buffered appender + /// + /// Appends an object to the logger that will store the log events sent + /// to the logger. These log messages are replayed to the logger in + /// processEnd(). + /// + /// \param logger Log4cplus logger to which the appender must be attached. + static void createBufferAppender(log4cplus::Logger& logger); + + /// \brief Set default layout and severity for root logger + /// + /// Initializes the root logger to Kea defaults - console or buffered + /// output and the passed severity/debug level. + /// + /// \param severity Severity of messages that the logger should output. + /// \param dbglevel Debug level if severity = DEBUG + /// \param buffer If true, all log messages will be buffered until one of + /// the \c process() methods is called. If false, initial logging + /// shall go to the default output (i.e. stdout) + static void initRootLogger(isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, bool buffer = false); + + /// \brief Set layout for an appender + /// + /// Sets the layout of the specified appender to one suitable for file + /// or console output: + /// + /// \param appender Appender for which this pattern is to be set. + /// \param pattern Log message format pattern + static void setAppenderLayout(log4cplus::SharedAppenderPtr& appender, + std::string pattern); + + /// \brief Store all buffer appenders + /// + /// When processing a new specification, this method can be used + /// to keep a list of the buffer appenders; the caller can then + /// process the specification, and call \c flushBufferAppenders() + /// to flush and clear the list + void storeBufferAppenders(); + + /// \brief Flush the stored buffer appenders + /// + /// This flushes the list of buffer appenders stored in + /// \c storeBufferAppenders(), and clears it + void flushBufferAppenders(); + + /// @brief Only used between processInit() and processEnd(), to temporarily + /// store the buffer appenders in order to flush them after + /// processSpecification() calls have been completed + std::vector<log4cplus::SharedAppenderPtr> buffer_appender_store_; + + /// @brief A hard copy of the specification for the root logger used for + /// inheritance by child loggers. + LoggerSpecification root_spec_; +}; + +} // namespace log +} // namespace isc + +#endif // LOGGER_MANAGER_IMPL_H diff --git a/src/lib/log/logger_name.cc b/src/lib/log/logger_name.cc new file mode 100644 index 0000000..39a79cc --- /dev/null +++ b/src/lib/log/logger_name.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <string> +#include <log/logger_name.h> + +namespace isc { +namespace log { + +namespace { + +// Obtain the root logger name in a way that is safe for statically-initialized +// objects. + +std::string& +getRootLoggerNameInternal() { + static std::string root_name; + return (root_name); +} + +} // Anonymous namespace + +void +setRootLoggerName(const std::string& name) { + getRootLoggerNameInternal() = name; +} + +const std::string& getRootLoggerName() { + return (getRootLoggerNameInternal()); +} + +const std::string& getDefaultRootLoggerName() { + static std::string root_name("kea"); + return (root_name); +} + +std::string expandLoggerName(const std::string& name) { + + // Are we the root logger, or does the logger name start with + // the string "<root_logger_name>.". If so, use a logger + // whose name is the one given. + if ((name == getRootLoggerName()) || + (name.find(getRootLoggerName() + std::string(".")) == 0)) { + return (name); + + } + + // Anything else is assumed to be a sub-logger of the root logger. + return (getRootLoggerName() + "." + name); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_name.h b/src/lib/log/logger_name.h new file mode 100644 index 0000000..08090cb --- /dev/null +++ b/src/lib/log/logger_name.h @@ -0,0 +1,55 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_NAME_H +#define LOGGER_NAME_H + +#include <string> + +/// \brief Define Name of Root Logger +/// +/// In BIND-10, the name root logger of a program is the name of the program +/// itself (in contrast to packages such as log4cplus where the root logger name +// is something like "root"). These trivial functions allow the setting and +// getting of that name by the logger classes. + +namespace isc { +namespace log { + +/// \brief Set root logger name +/// +/// This function should be called by the program's initialization code before +/// any logging functions are called. +/// +/// \param name Name of the root logger. This should be the program name. +void setRootLoggerName(const std::string& name); + +/// \brief Get root logger name +/// +/// \return Name of the root logger. +const std::string& getRootLoggerName(); + + +/// @brief Returns the default ('kea') root logger name +/// +/// @return The default name of root logger. +const std::string& getDefaultRootLoggerName(); + +/// \brief Expand logger name +/// +/// Given a logger name, returns the fully-expanded logger name. If the name +/// starts with the root logger name, it is returned as-is. Otherwise it is +/// prefixed with the root logger name. +/// +/// \param name Name to expand. +/// +/// \return Fully-expanded logger name. +std::string expandLoggerName(const std::string& name); + +} +} + +#endif // LOGGER_NAME_H diff --git a/src/lib/log/logger_specification.h b/src/lib/log/logger_specification.h new file mode 100644 index 0000000..906c2dc --- /dev/null +++ b/src/lib/log/logger_specification.h @@ -0,0 +1,148 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_SPECIFICATION_H +#define LOGGER_SPECIFICATION_H + +#include <stdint.h> +#include <stdlib.h> + +#include <log/logger_level.h> +#include <log/output_option.h> + +/// \brief Logger Specification +/// +/// The logging configuration options are a list of logger specifications, each +/// of which represents a logger and the options for its appenders. +/// +/// Unlike OutputOption (which is a struct), this contains a bit more +/// structure and is concealed in a class. + +#include <vector> + +namespace isc { +namespace log { + +class LoggerSpecification { +public: + typedef std::vector<OutputOption>::iterator iterator; + typedef std::vector<OutputOption>::const_iterator const_iterator; + + /// \brief Constructor + /// + /// \param name Name of the logger. + /// \param severity Severity at which this logger logs + /// \param dbglevel Debug level + /// \param additive true to cause message logged with this logger to be + /// passed to the parent for logging. + LoggerSpecification(const std::string& name = "", + isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, bool additive = false) : + name_(name), severity_(severity), dbglevel_(dbglevel), + additive_(additive) + {} + + /// \brief Set the name of the logger. + /// + /// \param name Name of the logger. + void setName(const std::string& name) { + name_ = name; + } + + /// \return Return logger name. + std::string getName() const { + return name_; + } + + /// \brief Set the severity. + /// + /// \param severity New severity of the logger. + void setSeverity(isc::log::Severity severity) { + severity_ = severity; + } + + /// \return Return logger severity. + isc::log::Severity getSeverity() const { + return severity_; + } + + /// \brief Set the debug level. + /// + /// \param dbglevel New debug level of the logger. + void setDbglevel(int dbglevel) { + dbglevel_ = dbglevel; + } + + /// \return Return logger debug level + int getDbglevel() const { + return dbglevel_; + } + + /// \brief Set the additive flag. + /// + /// \param additive New value of the additive flag. + void setAdditive(bool additive) { + additive_ = additive; + } + + /// \return Return additive flag. + bool getAdditive() const { + return additive_; + } + + /// \brief Add output option. + /// + /// \param option Option to add to the list. + void addOutputOption(const OutputOption& option) { + options_.push_back(option); + } + + /// \return Iterator to start of output options. + iterator begin() { + return options_.begin(); + } + + /// \return Iterator to start of output options. + const_iterator begin() const { + return options_.begin(); + } + + /// \return Iterator to end of output options. + iterator end() { + return options_.end(); + } + + /// \return Iterator to end of output options. + const_iterator end() const { + return options_.end(); + } + + /// \return Number of output specification options. + size_t optionCount() const { + return options_.size(); + } + + /// \brief Reset back to defaults. + void reset() { + name_ = ""; + severity_ = isc::log::INFO; + dbglevel_ = 0; + additive_ = false; + options_.clear(); + } + +private: + std::string name_; ///< Logger name + isc::log::Severity severity_; ///< Severity for this logger + int dbglevel_; ///< Debug level + bool additive_; ///< Chaining output + std::vector<OutputOption> options_; ///< Logger options +}; + +} // namespace log +} // namespace isc + +#endif // LOGGER_SPECIFICATION_H diff --git a/src/lib/log/logger_support.cc b/src/lib/log/logger_support.cc new file mode 100644 index 0000000..9431edd --- /dev/null +++ b/src/lib/log/logger_support.cc @@ -0,0 +1,119 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <string> +#include <log/logger_support.h> +#include <log/logger_manager.h> +#include <log/logger_name.h> + +using namespace std; + +namespace { + +// Flag to hold logging initialization state. +bool logging_init_state = false; + +} // Anonymous namespace + +namespace isc { +namespace log { + +// Return initialization state. +bool +isLoggingInitialized() { + return (logging_init_state); +} + +// Set initialization state. (Note: as logging can be initialized via a direct +// call to LoggerManager::init(), this function is called from there, not from +// the initialization functions in this file. +void +setLoggingInitialized(bool state) { + logging_init_state = state; +} + +// Logger Run-Time Initialization. + +void +initLogger(const string& root, isc::log::Severity severity, int dbglevel, + const char* file, bool buffer) { + LoggerManager::init(root, severity, dbglevel, file, buffer); +} + +// Reset characteristics of the root logger to that set by the environment +// variables KEA_LOGGER_SEVERITY, KEA_LOGGER_DBGLEVEL and KEA_LOGGER_DESTINATION. + +void +setDefaultLoggingOutput(bool verbose) { + + using namespace isc::log; + + // Constants: not declared static as this is function is expected to be + // called once only + const string DEVNULL = "/dev/null"; + const string STDOUT = "stdout"; + const string STDERR = "stderr"; + const string SYSLOG = "syslog"; + const string SYSLOG_COLON = "syslog:"; + + // Get the destination. If not specified, assume /dev/null. (The default + // severity for unit tests is DEBUG, which generates a lot of output. + // Routing the logging to /dev/null will suppress that, whilst still + // ensuring that the code paths are tested.) + const char* destination = getenv("KEA_LOGGER_DESTINATION"); + const string dest((destination == NULL) ? DEVNULL : destination); + + // Prepare the objects to define the logging specification + LoggerSpecification spec(getRootLoggerName(), + keaLoggerSeverity(verbose ? isc::log::DEBUG : + isc::log::INFO), + keaLoggerDbglevel(isc::log::MAX_DEBUG_LEVEL)); + OutputOption option; + + // Set up output option according to destination specification + if (dest == STDOUT) { + option.destination = OutputOption::DEST_CONSOLE; + option.stream = OutputOption::STR_STDOUT; + + } else if (dest == STDERR) { + option.destination = OutputOption::DEST_CONSOLE; + option.stream = OutputOption::STR_STDERR; + + } else if (dest == SYSLOG) { + option.destination = OutputOption::DEST_SYSLOG; + // Use default specified in OutputOption constructor for the + // syslog destination + + } else if (dest.find(SYSLOG_COLON) == 0) { + option.destination = OutputOption::DEST_SYSLOG; + // Must take account of the string actually being "syslog:" + if (dest == SYSLOG_COLON) { + cerr << "**ERROR** value for KEA_LOGGER_DESTINATION of " << + SYSLOG_COLON << " is invalid, " << SYSLOG << + " will be used instead\n"; + // Use default for logging facility + + } else { + // Everything else in the string is the facility name + option.facility = dest.substr(SYSLOG_COLON.size()); + } + + } else { + // Not a recognized destination, assume a file. + option.destination = OutputOption::DEST_FILE; + option.filename = dest; + } + + // ... and set the destination + spec.addOutputOption(option); + LoggerManager manager; + manager.process(spec); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_support.h b/src/lib/log/logger_support.h new file mode 100644 index 0000000..515ab11 --- /dev/null +++ b/src/lib/log/logger_support.h @@ -0,0 +1,78 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_SUPPORT_H +#define LOGGER_SUPPORT_H + +#include <unistd.h> + +#include <string> +#include <log/logger.h> +#include <log/logger_unittest_support.h> + +/// \file +/// \brief Logging initialization functions +/// +/// Contains a set of functions relating to logging initialization that are +/// used by the production code. + +namespace isc { +namespace log { + +/// \brief Is logging initialized? +/// +/// As some underlying logging implementations can behave unpredictably if they +/// have not been initialized when a logging function is called, their +/// initialization state is tracked. The logger functions will check this flag +/// and throw an exception if logging is not initialized at that point. +/// +/// \return true if logging has been initialized, false if not +bool isLoggingInitialized(); + +/// \brief Set state of "logging initialized" flag +/// +/// \param state State to set the flag to. (This is expected to be "true" - the +/// default - for all code apart from specific unit tests.) +void setLoggingInitialized(bool state = true); + +/// \brief Run-time initialization +/// +/// Performs run-time initialization of the logger in particular supplying: +/// +/// - Name of the root logger +/// - The severity (and if applicable, debug level) for the root logger. +/// - Name of a local message file, containing localization of message text. +/// +/// This function is likely to change over time as more debugging options are +/// held in the configuration database. +/// +/// \param root Name of the root logger +/// \param severity Severity at which to log +/// \param dbglevel Debug severity (ignored if "severity" is not "DEBUG") +/// \param file Name of the local message file. +/// \param buffer If true, all log messages will be buffered until one of +/// the \c process() methods is called. If false, initial logging +/// shall go to the default output (i.e. stdout) +void initLogger(const std::string& root, + isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, const char* file = NULL, + bool buffer = false); + +/// \brief Reset root logger characteristics +/// +/// This is a simplified interface into the resetting of the characteristics +/// of the root logger. It is aimed for use in unit tests and initial +/// phase of bring up before logging configuration is parsed and applied. +/// It uses KEA_LOGGER_DESTINATION environment variable to specify +/// logging destination. +/// @param verbose defines whether logging should be verbose or not +void setDefaultLoggingOutput(bool verbose = true); + + +} // namespace log +} // namespace isc + +#endif // LOGGER_SUPPORT_H diff --git a/src/lib/log/logger_unittest_support.cc b/src/lib/log/logger_unittest_support.cc new file mode 100644 index 0000000..fc01c6e --- /dev/null +++ b/src/lib/log/logger_unittest_support.cc @@ -0,0 +1,101 @@ +// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <iostream> +#include <algorithm> +#include <string> + +#include <log/logger_level.h> +#include <log/logger_name.h> +#include <log/logger_manager.h> +#include <log/logger_specification.h> +#include <log/logger_unittest_support.h> +#include <log/logger_support.h> +#include <log/output_option.h> + +using namespace std; + +namespace isc { +namespace log { + +// Get the logging severity. This is defined by the environment variable +// KEA_LOGGER_SEVERITY, and can be one of "DEBUG", "INFO", "WARN", "ERROR" +// of "FATAL". (Note that the string must be in upper case with no leading +// of trailing blanks.) If not present, the default severity passed to the +// function is returned. +isc::log::Severity +keaLoggerSeverity(isc::log::Severity defseverity) { + const char* sev_char = getenv("KEA_LOGGER_SEVERITY"); + if (sev_char) { + return (isc::log::getSeverity(sev_char)); + } + return (defseverity); +} + +// Get the debug level. This is defined by the environment variable +// KEA_LOGGER_DBGLEVEL. If not defined, a default value passed to the function +// is returned. +int +keaLoggerDbglevel(int defdbglevel) { + const char* dbg_char = getenv("KEA_LOGGER_DBGLEVEL"); + if (dbg_char) { + int level = 0; + try { + level = boost::lexical_cast<int>(dbg_char); + if (level < MIN_DEBUG_LEVEL) { + std::cerr << "**ERROR** debug level of " << level + << " is invalid - a value of " << MIN_DEBUG_LEVEL + << " will be used\n"; + level = MIN_DEBUG_LEVEL; + } else if (level > MAX_DEBUG_LEVEL) { + std::cerr << "**ERROR** debug level of " << level + << " is invalid - a value of " << MAX_DEBUG_LEVEL + << " will be used\n"; + level = MAX_DEBUG_LEVEL; + } + } catch (...) { + // Error, but not fatal to the test + std::cerr << "**ERROR** Unable to translate " + "KEA_LOGGER_DBGLEVEL - a value of 0 will be used\n"; + } + return (level); + } + + return (defdbglevel); +} + +// Logger Run-Time Initialization via Environment Variables +void initLogger(isc::log::Severity severity, int dbglevel) { + + // Root logger name is defined by the environment variable KEA_LOGGER_ROOT. + // If not present, the name is "kea". + const char* root = getenv("KEA_LOGGER_ROOT"); + if (! root) { + // If not present, the name is "kea". + root = isc::log::getDefaultRootLoggerName().c_str(); + } + + // Set the local message file + const char* localfile = getenv("KEA_LOGGER_LOCALMSG"); + + // Set a directory for creating lockfiles when running tests + setenv("KEA_LOCKFILE_DIR", TOP_BUILDDIR, 0); + + // Initialize logging + initLogger(root, severity, dbglevel, localfile); + + // Now set reset the output destination of the root logger, overriding + // the default severity, debug level and destination with those specified + // in the environment variables. (The two-step approach is used as the + // setUnitTestRootLoggerCharacteristics() function is used in several + // places in the Kea tests, and it avoid duplicating code.) + isc::log::setDefaultLoggingOutput(); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/logger_unittest_support.h b/src/lib/log/logger_unittest_support.h new file mode 100644 index 0000000..5b3f874 --- /dev/null +++ b/src/lib/log/logger_unittest_support.h @@ -0,0 +1,111 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOGGER_UNITTEST_SUPPORT_H +#define LOGGER_UNITTEST_SUPPORT_H + +#include <string> +#include <log/logger.h> + +/// \file +/// \brief Miscellaneous logging functions used by the unit tests. +/// +/// As the configuration database is usually unavailable during unit tests, +/// the functions defined here allow a limited amount of logging configuration +/// through the use of environment variables + +namespace isc { +namespace log { + +/// \brief Run-Time Initialization for Unit Tests from Environment +/// +/// Performs run-time initialization of the logger via the setting of +/// environment variables. These are: +/// +/// - KEA_LOGGER_ROOT\n +/// Name of the root logger. If not given, the string "kea" will be used. +/// +/// - KEA_LOGGER_SEVERITY\n +/// Severity of messages that will be logged. This must be one of the strings +/// "DEBUG", "INFO", "WARN", "ERROR", "FATAL" or "NONE". (Must be upper case +/// and must not contain leading or trailing spaces.) If not specified (or if +/// specified but incorrect), the default passed as argument to this function +/// (currently DEBUG) will be used. +/// +/// - KEA_LOGGER_DBGLEVEL\n +/// Ignored if the level is not DEBUG, this should be a number between 0 and +/// 99 indicating the logging severity. The default is 0. If outside these +/// limits or if not a number, The value passed to this function (default +/// of MAX_DEBUG_LEVEL) is used. +/// +/// - KEA_LOGGER_LOCALMSG\n +/// If defined, the path specification of a file that contains message +/// definitions replacing ones in the default dictionary. +/// +/// - KEA_LOGGER_DESTINATION\n +/// If defined, the destination of the logging output. This can be one of: +/// - \c stdout Send output to stdout. +/// - \c stderr Send output to stderr +/// - \c syslog Send output to syslog using the facility local0. +/// - \c syslog:xxx Send output to syslog, using the facility xxx. ("xxx" +/// should be one of the syslog facilities such as "local0".) There must +/// be a colon between "syslog" and "xxx +/// - \c other Anything else is interpreted as the name of a file to which +/// output is appended. If the file does not exist, it is created. +/// +/// Any errors in the settings cause messages to be output to stderr. +/// +/// This function is aimed at test programs, allowing the default settings to +/// be overridden by the tester. It is not intended for use in production +/// code. +/// +/// @note: Do NOT use this function in production code as it creates +/// lockfile in the build dir. That's ok for tests, but not +/// ok for production code. +/// +/// @todo: Rename. This function overloads the initLogger() function that can +/// be used to initialize production programs. This may lead to confusion. +void initLogger(isc::log::Severity severity = isc::log::DEBUG, + int dbglevel = isc::log::MAX_DEBUG_LEVEL); + + +/// \brief Obtains logging severity from KEA_LOGGER_SEVERITY +/// +/// Support function called by the unit test logging initialization code. +/// It returns the logging severity defined by KEA_LOGGER_SEVERITY. If +/// not defined it returns the default passed to it. +/// +/// \param defseverity Default severity used if KEA_LOGGER_SEVERITY is not +// defined. +/// +/// \return Severity to use for the logging. +isc::log::Severity keaLoggerSeverity(isc::log::Severity defseverity); + + +/// \brief Obtains logging debug level from KEA_LOGGER_DBGLEVEL +/// +/// Support function called by the unit test logging initialization code. +/// It returns the logging debug level defined by KEA_LOGGER_DBGLEVEL. If +/// not defined, it returns the default passed to it. +/// +/// N.B. If there is an error, a message is written to stderr and a value +/// related to the error is used. (This is because (a) logging is not yet +/// initialized, hence only the error stream is known to exist, and (b) this +/// function is only used in unit test logging initialization, so incorrect +/// selection of a level is not really an issue.) +/// +/// \param defdbglevel Default debug level to be used if KEA_LOGGER_DBGLEVEL +/// is not defined. +/// +/// \return Debug level to use. +int keaLoggerDbglevel(int defdbglevel); + +} // namespace log +} // namespace isc + + + +#endif // LOGGER_UNITTEST_SUPPORT_H diff --git a/src/lib/log/logging.dox b/src/lib/log/logging.dox new file mode 100644 index 0000000..8dbc02f --- /dev/null +++ b/src/lib/log/logging.dox @@ -0,0 +1,698 @@ +// Copyright (C) 2013-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Note: the prefix "log" to all labels is an abbreviation for "Logging" +// and is used to prevent a clash with symbols in any other Doxygen file. + +/** +@page logKeaLogging Kea Logging + +@section logBasicIdeas Basic Ideas + +The Kea logging system is based on the log4J logging system +common in Java development, and includes the following ideas: + +- A set of severity levels. +- A hierarchy of logging sources. +- Separation of message use from message text. + +@subsection logSeverity Message Severity +Each message logged by Kea has a severity associated with it, ranging +from FATAL - the most severe - to DEBUG - messages output as the code +executes to facilitate debugging. In order of decreasing severity, +the levels are: + +<dl> +<dt>FATAL</dt> +<dd>The program has encountered an error that is so severe that it +cannot continue (or there is no point in continuing). For example, an +unhandled exception generated deep within the code has been caught by the +top-level program. When a fatal error has been logged, the program will +exit immediately (or shortly afterwards) after dumping some diagnostic +information.</dd> + +<dt>ERROR</dt> +<dd>Something has happened such that the program can continue but the +results for the current (or future) operations cannot be guaranteed to +be correct, or the results will be correct but the service is impaired. +For example, the program started but attempts to open one or more network +interfaces failed.</dd> + +<dt>WARN</dt> +<dd>(Warning) An unusual event happened. Although the program will +continue working normally, the event was sufficiently out of the ordinary +to warrant drawing attention to it. For example, the authoritative +server loaded a zone that contained no resource records.</dd> + +<dt>INFO</dt> +<dd>(Information) A normal but significant event has occurred that should +be recorded, e.g. the program has started or is just about to terminate, +a new zone has been created, etc.</dd> + +<dt>DEBUG</dt> +<dd>Debug messages are output at this severity. Each message also +has a debug level associated with it, ranging from 0 (the default) +for high-level messages and level 99 (the maximum) for the lowest +level.</dd> +</dl> + +When logging is enabled for a component, it is enabled for a particular +severity level and all higher severities. So if logging is enabled +for INFO messages, WARN, ERROR and FATAL messages will also be logged, +but not DEBUG ones. If enabled for ERROR, only ERROR and FATAL messages +will be logged. + +As noted above, DEBUG messages are also associated with a debug level. +This allows the developer to control the amount of debugging information +produced; the higher the debug level, the more information is output. +For example, if debugging the NSAS (nameserver address store), debug +levels might be assigned as follows: a level 0 debug message records +the creation of a new zone, a level 10 logs every timeout when trying +to get a nameserver address, a level of 50 records every query for an +address and a level of 70 records every update of the round-trip time. + +Like severities, levels are cumulative; so if level 25 is set as the +debug level, all debug messages associated levels 0 to 25 (inclusive) +will be output. In fact, it is probably easier to visualize the debug +levels as part of the severity system: +@code +FATAL Most severe +ERROR +WARN +INFO +DEBUG level 0 +DEBUG level 1 + : +DEBUG level 99 Least severe +@endcode +When a particular debug level is set, it - and all debug levels and +severities above it - will be logged. + +To try to ensure that the information from different modules is roughly +comparable for the same debug level, a set of standard debug levels has +been defined for common types of debug output. (These can be found in +@ref log_dbglevels.h) However, modules are free to set their own debug +levels or define additional ones. + +@subsection logHierarchical Hierarchical Logging System + +When a program writes a message to the logging system, it does so using an +instance of the @ref isc::log::Logger class. As well as performing the +write of the message, the logger identifies the source of the message: +different sources can write to different destinations and can log +different severities of messages. For example, the logger associated +with the resolver's cache code could write debugging and other messages +to a file while all other components only write messages relating to +errors to the syslog file. + +The loggers are hierarchical in that each logger is the child of another +logger. The top of the hierarchy is the root logger; this does not +have a parent. The reason for this hierarchy is that unless a logger +explicitly assigns a value to an attribute (such as severity of messages +it should log), it picks it up the value from the parent. In Kea, +each component (kea-dhcp4, kea-dhcp-ddns etc.) has a root logger (named +after the program) and every other logger in the component is a child +of that. So in the example above, the error/syslog attributes could be +associated with the kea-resolver logger while the logger associated with +the cache sets its own values for the debug/file attributes. + +More information about the logging hierarchy can be found in the section +on Logging configuration in the <a +href="https://kea.readthedocs.io/">Kea Administrator +Reference Manual</a>. + +@subsection logSeparationUseText Separation of Messages Use from Message Text + +Separating the use of the message from the text associated with it - +in essence, defining message text in an external file - allows for the +replacement the supplied text of the messages with a local language version. +It also means that other attributes can be associated with the message, +for example, an explanation of the meaning of the message and other +information such as remedial action in the case of errors. + +Each message has an identifier such as "LOG_WRITE_ERROR". +Within the program, this is the symbol passed to the logging system +which uses the symbol as an index into a dictionary to retrieve the message +associated with it (e.g. "unable to open %1 for input"), after which it +substitutes any message parameters (in this example, the name of the file +where the write operation failed) and logs the result to the destination. + +In Kea, the default text for each message is linked into the +program. Each program is able to read a locally-defined message file +when it starts, updating the stored definitions with site-specific text. +When the message is logged, the updated text is output. However, the +message identifier is always included in the output so that the origin +of the message can be identified even if the text has been changed. + +@note Local message files have not yet been implemented in Kea. + + + +@section logDeveloperUse Using Logging in a Kea Component + +The steps in using the logging system in a Kea component (such as +an executable or library) are: + +<ol> +<li>Create a message file. This defines messages by an identification +string and text that explains the message in more detail. Ideally the +file should have a file type of ".mes".</li> + +<li>Run it through the message compiler to produce the files for your +module. This step should be included in the build process. The message +compiler is a Kea program and is one of the first programs built and +linked in the build process. As a result, it should be available for +compiling the message files of all Kea components and libraries. + +For C++ development, the message compiler produces two files in the +default directory, having the same name as the input file but with file +types of ".h" and ".cc".</li> + +<li>Include the resultant files in your source code to define message symbols, +and compile the code and link it into your program.</li> + +<li>Declare loggers in your code and use them to log messages.</li> + +<li>Call the logger initialization function in the program's main module.</li> + +</ol> + +The following sections describe these steps in more detail. + + +@subsection logMessageFiles Create a Message File + +A message file contains message definitions. Typically there +will be one message file for each component that uses Kea logging. +An example file could be: + +@code +# Example message file + +$NAMESPACE isc::log + +% LOG_UNRECOGNIZED_DIRECTIVE line %1: unrecognized directive '%2' +A line starting with a dollar symbol was found, but the first word on the line +(shown in the message) was not a recognized message compiler directive. + +% LOG_WRITE_ERROR error writing to %1: %2 +The specified error was encountered by the message compiler when writing to +the named output file. +@endcode + +Points to note are: + +<ul> +<li>Leading and trailing spaces are trimmed from each line before it +is processed. Although the above example has every line starting at +column 1, the lines could be indented if desired.</li> + +<li>Lines starting with "#" are comments are are ignored. Comments must +be on a line by themselves; inline comments will be interpreted as part +of the text of that line.</li> + +<li>Lines starting with "$" are directives. At present, just one +directive is recognized: + <dl> + <dt>$NAMESPACE <namespace-name></dt> + <dd>The sole argument is the name of the namespace in which the + symbols are created. In the absence of a $NAMESPACE directive, + symbols will be put in the anonymous namespace.</dd> + </dl> +</li> + +<li>Lines starting with "%" are message definitions and comprise the message +identification and the message text. For example: +@code +% LOG_WRITE_ERROR error writing to %1: %2 +@endcode + +There may be zero or more spaces between the leading "%" and the +message identification (which, in the example above, is the string +"LOG_WRITE_ERROR").</li> + +<li>The message identification can be any string of letters, digits and +underscores, but must not start with a digit.</li> + +<li>The rest of the line - from the first non-space character to the +last non- space character - is the text of the message. There are no +restrictions on what characters may be in this text, other than they be +printable (so both single-quote (') and double-quote (") characters are +allowed). The message text may include replacement tokens (the strings +"%1", "%2" etc.). When a message is logged, these are replaced with the +arguments passed to the logging call: %1 refers to the first argument, +%2 to the second etc. Within the message text, the placeholders can +appear in any order and placeholders can be repeated. Otherwise, the +message is printed unmodified.</li> + +<li>Remaining lines indicate an explanation for the preceding message. +The explanation can comprise multiple paragraphs, the paragraphs being +separated by blank lines. These lines are intended to be processed by a +separate program to generate an error messages manual; they are ignored +by the message compiler.</li> + +<li>Except when used to separate paragraphs in the message explanation, +blank lines are ignored.</li> +</ul> + +Although there are few restriction on what can be in the message +identification and text, there are a number of conventions used by Kea, +both in the contents of the message and in the usage. All code +should adhere to these: + +<ul> +<li>Message identifications should include at least one underscore. +The component before the first underscore is a string indicating the +origin of the message, and the remainder describes the condition. +So in the example above, the LOG indicates that the error originated +from the logging library and the "WRITE_ERROR" indicates that there was +a problem in a write operation.</li> + +<li>The part of the message identification describing the error (e.g. +"WRITE_ERROR" in the example above) should comprise no more than +two or three words separated by underscores. An excessive number +of words or overly long message identification should be avoided; +such information should be put in the text of the message. For example, +"RECEIVED_EMPTY_HOSTNAME_FROM_CLIENT" is excessively long, +"EMPTY_HOSTNAME" being better.</li> + +<li>Similarly, the text of the message should be reasonably concise. It should +include enough information (possibly supplied at run-time in the form of +parameters) to allow further investigations to be undertaken if required. + +Taking the above example, a suitable error message to indicate that the +resolver has failed to read a name from an upstream authoritative server +could be: + +@code +% RESOLVER_FETCH_ERROR fetch from %1 failed, error code %2 (%3) +@endcode + +... where %1 indicates the name or IP address of the server to which the +fetch was sent, %2 the errno value returned and %3 the message associated +with that error number (retrieved via a call to "strerror()"). + +</li> + +<li>The message should not have a comma after the message identification. +The message text should neither start with a capital letter (unless +the first word is a proper noun or is normally written in capitals) +nor end with a period. The message reporting system takes care of such +punctuation.</li> + +<li>The parameters substituted into the message text should not include +line breaks. Messages are normally output to the syslog file which +has the inbuilt assumption of one line per message. Splitting a message +across multiple lines makes it awkward to search the file for messages +and associated information.</li> + +<li>The message identifier should be unique across the entire Kea +system. (An error will be reported at system start-up if an identifier +is repeated.)</li> + +<li>A particular message identifier should only be used at one place in +the Kea code. In this way, if the message indicates a problem, the +code in question can be quickly identified.</li> + +<li>The explanation of the message - the free-form text following the +message identification - appears in the Kea message manual. It +should: + +<ul> +<li>Describe the severity of the message (debug, informational etc.)</li> + +<li>Expand on the text of the message. In some cases, such as +debug messages, the message text may provide more or less sufficient +description. For warnings and errors, the explanation should provide +sufficient background to the problem to allow a non-developer to +understand the issue and to begin fault-finding. If possible, the +explanation should also include suggested remedial action.</li> +</ul> +</ul> + +@subsection logSourceFiles Produce Source Files +The message file created in the previous step is then run through the +message compiler to produce source files that are included in the Kea +programs. + +@subsubsection logMessageCompiler Message Compiler +The message compiler is a program built in the src/log/compiler directory. +It is invoked by the command: +@code +kea-msg-compiler [-h] [-v] [-d dir] <message-file> +@endcode +"-v" prints the version number and exits; "-h" prints brief help text. +Finally, the "-d" switch directs the compiler to produce the output +files in the specified directory (the default being the current +working directory). + +<b>C++ Files</b><br/> + +<ol> +<li>A C++ header file (called <message-file-name>.h) holding lines of +the form: +@code +namespace <namespace-name> { + extern const isc::log::MessageID LOG_BAD_DESTINATION; + extern const isc::log::MessageID LOG_BAD_SEVERITY; + : +} +@endcode +The symbols define keys in the global message dictionary, with +the namespace enclosing the symbols set by the $NAMESPACE directive. +(This is the reason for the restriction on message identifiers - they +have to be valid C++ symbol names.)</li> + +<li>A C++ source file (called <message-file-name>.cc) that holds the definitions +of the global symbols and code to insert the symbols and messages into +an internal dictionary. + +Symbols are defined to be equal to strings equal to the identifier, e.g. +@code +extern const isc::log::MessageID LOG_BAD_DESTINATION = "LOG_BAD_DESTINATION"; +extern const isc::log::MessageID LOG_BAD_SEVERITY = "LOG_BAD_SEVERITY"; + : +@endcode +(The current implementation allows symbols to be compared. However, +use of strings should not be assumed - a future implementation may change +this.) In addition, the file declares an array of identifiers/messages +and an object to add them to the global dictionary, e.g.: +@code +namespace { + const char* values[] = { + "LOG_BAD_DESTINATION", "unrecognized log destination: %1", + "LOG_BAD_SEVERITY", "unrecognized log severity: %1", + : + NULL + }; + const isc::log::MessageInitializer initializer(values); +} +@endcode + +The constructor of the @ref isc::log::MessageInitializer object retrieves +the singleton global @ref isc::log::MessageDictionary object (created +using standard methods to avoid the "static initialization fiasco") and +adds each identifier and associated text to it. These constructors are run +when the program starts; a check is made as each identifier is added and, +if the identifier already exists in the dictionary, a warning message +is printed to the main logging output when logging is finally enabled. +The appearance of such a message indicates a programming error. +</li> +</ol> + +@subsubsection logMakefile Include Message Compilation in Makefile +The source file for the messages is the ".mes" file, but the files +used by the code which must be compiled and linked are the output of +the message compiler. (The compiler is produced very early on in the +Kea build sequence, so is available for use in the building of +subsequent components.) To allow this, certain dependencies must be +included in the Makefile.am for each component that uses logging. + +<b>Including Message files in C++ Component Builds</b><br/> +The following segment from the "hooks" Makefile.am illustrates +the entries needed. +@code +# Ensure that the message file is included in the distribution +EXTRA_DIST = hooks_messages.mes + +# If we want to get rid of all generated messages files, we need to use +# make maintainer-clean. The proper way to introduce custom commands for +# that operation is to define maintainer-clean-local target. However, +# make maintainer-clean also removes Makefile, so running configure script +# is required. To make it easy to rebuild messages without going through +# reconfigure, a new target messages-clean has been added. +maintainer-clean-local: + rm -f hooks_messages.h hooks_messages.cc + +# To regenerate messages files, one can do: +# +# make messages-clean +# make messages +# +# This is needed only when a .mes file is modified. +messages-clean: maintainer-clean-local + +if GENERATE_MESSAGES + +# Define rule to build logging source files from message file +messages: hooks_messages.h hooks_messages.cc + @echo Message files regenerated + +hooks_messages.h hooks_messages.cc: hooks_messages.mes + $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/hooks/hooks_messages.mes + +else + +messages hooks_messages.h hooks_messages.cc: + @echo Messages generation disabled. Configure with --enable-generate-messages to enable it. + +endif +@endcode +The first rule adds a hook to make maintainer-clean which is the standard +way to regenerate all messages files. The second rule adds the new +messages-clean target to regenerate local messages files. + +The GENERATE_MESSAGES conditional part is the (re)generation of +the messages files. When configured with --enable-generate-messages +and the source (.mes file) is newer these files are generated using +the Kea message compiler. When configured without --enable-generate-messages +(the default) and the source (.mes file) is newer a message is emitted. + +Not shown are the Makefile.am lines where the .h and .cc file are used. These +are the same as other lines specifying .h and .cc source files. + +And finally please note the message header (e.g. hooks_messages.h) +should be installed, i.e. in the include_HEADERS list. + +@subsection logUsage Using Logging Files in Program Development + +@subsubsection logCppUsage Use in a C++ Program or Module +To use logging in a C++ program or module: + +<ol> +<li>Build the message header file and source file as described above.</li> + +<li>In each C++ file in which logging is to be used, declare a logger +through which the message will be logged. + +@code +isc::log::Logger logger("name"); +@endcode +This declaration can be per-function, or it can be declared statically +in file scope. The string passed to the constructor is the name of +the logger (it can be any string) and is used when configuring it. +(Remember though that the name of root logger for the program will be +prepended to the name chosen. So if, for example, the name "cache" +is chosen and the model is included in the "kea-resolver" program, the +full name of the logger will be "kea-resolver.cache".) Loggers with +the same name share the same configuration. For this reason if, as is +usual, messages logged in different files in the same component (e.g. +hooks module, nameserver address store, etc.) originate from loggers +with the same name, the logger declaration can be placed into a header +file.</li> + +<li>Issue logging calls using supplied macros in "log/macros.h", e.g. +@code +LOG_ERROR(logger, LOG_WRITE_ERROR).arg("output.txt"); +LOG_DEBUG(nsas_logger, NSAS_DBG_TRACE, NSAS_LOOKUP_CANCEL).arg(zone); +@endcode +All macros (with the exception of LOG_DEBUG) take two arguments: +the C++ logger object that will be used to log the message, and the +identification of the message to be logged. LOG_DEBUG takes three +arguments, the additional one being the debug level associated with +the message. The .arg() call appended to the end of the LOG_XXX() +macro handles the arguments to the message. A chain of these is used +in cases where a message takes multiple arguments, e.g. +@code +LOG_DEBUG(nsas_logger, NSAS_DBG_RTT, NSAS_UPDATE_RTT) + .arg(addresses_[family][index].getAddress().toText()) + .arg(old_rtt).arg(new_rtt); +@endcode +Using the macros is more efficient than direct calls to the methods on +the logger class: they avoid the overhead of evaluating the parameters +to arg() if the logging settings are such that the message is not going +to be output (e.g. it is a DEBUG message and the logging is set to output +messages of INFO severity or above).</li> + +<li>The main program unit must include a call to isc::log::initLogger() +(described in more detail below) to set the initial logging severity, debug log +level, and external message file. +</ol> + +@subsection logInitialization Logging Initialization +In all cases, if an attempt is made to use a logging method before +the logging has been initialized, the program will terminate with a +LoggingNotInitialized exception. + +@subsection logInitializationCpp C++ Initialization +Logging Initialization is carried out by calling @ref +isc::log::initLogger(). There are two variants to the call, one for +use by production programs and one for use by unit tests. + +@subsubsection logInitializationCppVariant1 Variant #1, Used by Production Programs +The call that should be used by all production programs is: +@code +void isc::log::initLogger(const std::string& root, + isc::log::Severity severity = isc::log::INFO, + int dbglevel = 0, const char* file = NULL, + bool buffer = false); +@endcode +Arguments are: +<dl> +<dt><code>root</code></dt> +<dd>Name of the root logger. This should be the name of the program +(e.g. "kea-auth") and is used when configuring logging.</dd> + +<dt><code>severity</code></dt> +<dd>Default severity that the program will start logging with. Although +this may be overridden when the program obtains its configuration from +the configuration database, this is the severity that it used until then. +The logging severity is one of the enum defined in @ref logger.h, i.e. + +@code +isc::log::DEBUG +isc::log::INFO +isc::log::WARN +isc::log::ERROR +isc::log::FATAL +isc::log::NONE +@endcode + +(The level NONE may be used to disable logging.) +</dd> + +<dt><code>dbglevel</code></dt> +<dd>The debug log level is only interpreted when the severity is +isc::log::DEBUG and is an integer ranging from 0 to 99. 0 should be +used for the highest-level debug messages and 99 for the lowest-level +(and typically more verbose) messages.</dd> + +<dt><code>file</code></dt> +<dd>The name of a local message file. This will be read and its +definitions used to replace the compiled-in text of the messages. +The default value of NULL indicates that no local message file is +supplied.</dd> + +<dt><code>buffer</code></dt> +<dd>If set to true, initial log messages will be internally buffered, +until the first time a logger specification is processed. This +way the program can use logging before even processing its logging +configuration. As soon as any specification is processed (even an +empty one), the buffered log messages will be flushed according to +the specification. Note that if this option is used, the program +SHOULD call one of the @ref isc::log::LoggerManager::process() calls. +If the program exits before this is done, all log messages are dumped +in a raw format to stdout (so that no messages get lost).</dd> +</dl> + +@subsubsection logInitializationCppVariant2 Variant #2, Used by Unit Tests +@code +void isc::log::initLogger() +@endcode +This is the call that should be used by unit tests. In this variant, +all the options are supplied by environment variables: it should not +be used for production programs to avoid the chance that the program +operation is affected by inadvertently-defined environment variables. The +environment variables are: + +<dl> +<dt>KEA_LOGGER_ROOT</dt> +<dd>Sets the "root" for the unit test. If not defined, the name "kea" +is used.</dd> + +<dt>KEA_LOGGER_SEVERITY</dt> +<dd>The severity to set for the root logger in the unit test. +Valid values are "DEBUG", "INFO", "WARN", "ERROR", "FATAL" and "NONE". +If not defined, "INFO" is used.</dd> + +<dt>KEA_LOGGER_DBGLEVEL</dt> +<dd>If KEA_LOGGER_SEVERITY is set to "DEBUG", the debug level. This can +be a number between 0 and 99, and defaults to 0.</dd> + +<dt>KEA_LOGGER_LOCALMSG</dt> +<dd>If defined, points to a local message file. The default is not to +use a local message file.</dd> + +<dt>KEA_LOGGER_DESTINATION</dt> +<dd>The location to which log message are written. This can be one of: +<ul> +<li><b>stdout</b> Message are written to stdout.</li> +<li><b>stderr</b> Messages are written to stderr.</li> +<li><b>syslog[:facility]</b> Messages are written to syslog. If the +optional "facility" is used, the messages are written using that facility. +(This defaults to "local0" if not specified.)</li> +<li><b>Anything else</b> Interpreted as the name of a file to which +output is appended. If the file does not exist, a new one is opened.</li> +</ul> +In the case of "stdout", "stderr" and "syslog", they must be written exactly +as is - no leading or trailing spaces, and in lower-case.</dd> +</dl> + +@subsection logInitializationHooks Hooks Specific Notes +All hooks libraries should use Kea logging mechanisms. The loggers and the +library specific log messages are created in the same way as for the core +Kea modules. The loggers created within the hook library belong to the +logging hierarchy of the Kea process and their configuration can be +controlled from the Kea configuration file. If the configuration file doesn't +contain the specific configuration for the logger used in the library, +this logger is given the configuration of the root Kea logger. + +The hook libraries are loaded dynamically. This requires that the global log +messages dictionary, holding the mapping of specific log message +identifiers to the actual messages, is updated to include the messages +specified in the hook library when the library is loaded. Conversely, the +messages have to be removed from the dictionary when the library is unloaded. + +The new messages are added to the global dictionary using the +@ref isc::log::MessageInitializer::loadDictionary static function. It is +called by the @ref isc::hooks::LibraryManager::loadLibrary for each loaded +library. + +When the library is unloaded, the instance of the +@ref isc::log::MessageInitializer defined in the library is destroyed +and its destructor removes the messages registered by the destroyed +instance from the global dictionary. + +The hook library itself must not perform any action to register or +unregister log messages in the global dictionary! + +@section logNotes Notes on the Use of Logging +One thing that should always be kept in mind is whether the logging +could be used as a means for a DOS attack. For example, if a warning +message is logged every time an invalid packet is received, an attacker +could simply send large numbers of invalid packets. Of course, warnings +could be disabled (or just warnings for that that particular logger), +but nevertheless the message is an attack vector. As a general rule, +if the message can be triggered by a user action, it can be used as an +attack vector. + +There are two approaches to get round this: +<ol> +<li>Log messages generated by such user actions as DEBUG messages. DEBUG +is not enabled by default, so these events will not be recorded unless +DEBUG is specifically enabled. Choosing a suitable debug level for +such messages will select only those messages and not the more general +debug messages.</li> + +<li>Record system-related and packet-related messages via different +loggers. As the loggers are independent and the severity levels +independent, fine-tuning of what and what is not recorded can be achieved.</li> + +</ol> + +@section logMTConsiderations Multi-Threading Consideration for Logging + +Logging is thread safe: messages emitted at the same time do not mix. + +When the KEA_LOCKFILE_DIR environment variable is not set to none +Logging to files is multi-process safe too: for instance two servers +can be configured to put log messages in the same file. + +The @c isc::log::Logger class initializes its implementation in a lazy +(i.e. on demand) but thread safe way so it is always initialized at most +once even in a multi-threaded environment. + +*/ diff --git a/src/lib/log/logimpl_messages.cc b/src/lib/log/logimpl_messages.cc new file mode 100644 index 0000000..12a6442 --- /dev/null +++ b/src/lib/log/logimpl_messages.cc @@ -0,0 +1,29 @@ +// File created from ../../../src/lib/log/logimpl_messages.mes + +#include <cstddef> +#include <log/message_types.h> +#include <log/message_initializer.h> + +namespace isc { +namespace log { + +extern const isc::log::MessageID LOGIMPL_ABOVE_MAX_DEBUG = "LOGIMPL_ABOVE_MAX_DEBUG"; +extern const isc::log::MessageID LOGIMPL_BAD_DEBUG_STRING = "LOGIMPL_BAD_DEBUG_STRING"; +extern const isc::log::MessageID LOGIMPL_BELOW_MIN_DEBUG = "LOGIMPL_BELOW_MIN_DEBUG"; + +} // namespace log +} // namespace isc + +namespace { + +const char* values[] = { + "LOGIMPL_ABOVE_MAX_DEBUG", "debug level of %1 is too high and will be set to the maximum of %2", + "LOGIMPL_BAD_DEBUG_STRING", "debug string '%1' has invalid format", + "LOGIMPL_BELOW_MIN_DEBUG", "debug level of %1 is too low and will be set to the minimum of %2", + NULL +}; + +const isc::log::MessageInitializer initializer(values); + +} // Anonymous namespace + diff --git a/src/lib/log/logimpl_messages.h b/src/lib/log/logimpl_messages.h new file mode 100644 index 0000000..e0813d6 --- /dev/null +++ b/src/lib/log/logimpl_messages.h @@ -0,0 +1,18 @@ +// File created from ../../../src/lib/log/logimpl_messages.mes + +#ifndef LOGIMPL_MESSAGES_H +#define LOGIMPL_MESSAGES_H + +#include <log/message_types.h> + +namespace isc { +namespace log { + +extern const isc::log::MessageID LOGIMPL_ABOVE_MAX_DEBUG; +extern const isc::log::MessageID LOGIMPL_BAD_DEBUG_STRING; +extern const isc::log::MessageID LOGIMPL_BELOW_MIN_DEBUG; + +} // namespace log +} // namespace isc + +#endif // LOGIMPL_MESSAGES_H diff --git a/src/lib/log/logimpl_messages.mes b/src/lib/log/logimpl_messages.mes new file mode 100644 index 0000000..8af43fc --- /dev/null +++ b/src/lib/log/logimpl_messages.mes @@ -0,0 +1,35 @@ +# Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# \brief Logger Implementation Messages +# +# This holds messages generated by the underlying logger implementation. They +# are likely to be specific to that implementation, and may well change if the +# underlying implementation is changed. For that reason, they have been put +# in a separate file. + +$NAMESPACE isc::log + +% LOGIMPL_ABOVE_MAX_DEBUG debug level of %1 is too high and will be set to the maximum of %2 +A message from the interface to the underlying logger implementation reporting +that the debug level (as set by an internally-created string DEBUGn, where n +is an integer, e.g. DEBUG22) is above the maximum allowed value and has +been reduced to that value. The appearance of this message may indicate +a programming error - please submit a bug report. + +% LOGIMPL_BAD_DEBUG_STRING debug string '%1' has invalid format +A message from the interface to the underlying logger implementation +reporting that an internally-created string used to set the debug level +is not of the correct format (it should be of the form DEBUGn, where n +is an integer, e.g. DEBUG22). The appearance of this message indicates +a programming error - please submit a bug report. + +% LOGIMPL_BELOW_MIN_DEBUG debug level of %1 is too low and will be set to the minimum of %2 +A message from the interface to the underlying logger implementation reporting +that the debug level (as set by an internally-created string DEBUGn, where n +is an integer, e.g. DEBUG22) is below the minimum allowed value and has +been increased to that value. The appearance of this message may indicate +a programming error - please submit a bug report. diff --git a/src/lib/log/macros.h b/src/lib/log/macros.h new file mode 100644 index 0000000..f8336d6 --- /dev/null +++ b/src/lib/log/macros.h @@ -0,0 +1,43 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef LOG_MACROS_H +#define LOG_MACROS_H + +#include <log/logger.h> +#include <log/log_dbglevels.h> + +/// \brief Macro to conveniently test debug output and log it +#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE) \ + if (!(LOGGER).isDebugEnabled((LEVEL))) { \ + } else \ + (LOGGER).debug((LEVEL), (MESSAGE)) + +/// \brief Macro to conveniently test info output and log it +#define LOG_INFO(LOGGER, MESSAGE) \ + if (!(LOGGER).isInfoEnabled()) { \ + } else \ + (LOGGER).info((MESSAGE)) + +/// \brief Macro to conveniently test warn output and log it +#define LOG_WARN(LOGGER, MESSAGE) \ + if (!(LOGGER).isWarnEnabled()) { \ + } else \ + (LOGGER).warn((MESSAGE)) + +/// \brief Macro to conveniently test error output and log it +#define LOG_ERROR(LOGGER, MESSAGE) \ + if (!(LOGGER).isErrorEnabled()) { \ + } else \ + (LOGGER).error((MESSAGE)) + +/// \brief Macro to conveniently test fatal output and log it +#define LOG_FATAL(LOGGER, MESSAGE) \ + if (!(LOGGER).isFatalEnabled()) { \ + } else \ + (LOGGER).fatal((MESSAGE)) + +#endif diff --git a/src/lib/log/message_dictionary.cc b/src/lib/log/message_dictionary.cc new file mode 100644 index 0000000..5271e46 --- /dev/null +++ b/src/lib/log/message_dictionary.cc @@ -0,0 +1,121 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <cstddef> +#include <log/message_dictionary.h> +#include <log/message_types.h> + +using namespace std; + +namespace isc { +namespace log { + +// Constructor + +MessageDictionary::MessageDictionary() : dictionary_(), empty_("") { +} + +// (Virtual) Destructor + +MessageDictionary::~MessageDictionary() { +} + +// Add message and note if ID already exists + +bool +MessageDictionary::add(const std::string& ident, const std::string& text) { + Dictionary::iterator i = dictionary_.find(ident); + bool not_found = (i == dictionary_.end()); + if (not_found) { + + // Message not already in the dictionary, so add it. + dictionary_[ident] = text; + } + + return (not_found); +} + +// Add message and note if ID does not already exist + +bool +MessageDictionary::replace(const std::string& ident, const std::string& text) { + Dictionary::iterator i = dictionary_.find(ident); + bool found = (i != dictionary_.end()); + if (found) { + + // Exists, so replace it. + dictionary_[ident] = text; + } + + return (found); +} + +bool +MessageDictionary::erase(const std::string& ident, const std::string& text) { + Dictionary::iterator mes = dictionary_.find(ident); + // Both the ID and the text must match. + bool found = (mes != dictionary_.end() && (mes->second == text)); + if (found) { + dictionary_.erase(mes); + } + return (found); +} + +// Load a set of messages + +vector<std::string> +MessageDictionary::load(const char* messages[]) { + vector<std::string> duplicates; + int i = 0; + while (messages[i]) { + // ID present, so point to text. + ++i; + if (messages[i]) { + const MessageID ident(messages[i - 1]); + // Text not null, note it and point to next ident. + const std::string text(messages[i]); + ++i; + + // Add ID and text to message dictionary, noting if the ID was + // already present. + bool added = add(ident, text); + if (!added) { + duplicates.push_back(boost::lexical_cast<string>(ident)); + } + } + } + return (duplicates); +} + +// Return message text or blank string. A reference is returned to a string +// in the dictionary - this is fine, as the string is immediately used for +// output. + +const string& +MessageDictionary::getText(const std::string& ident) const { + Dictionary::const_iterator i = dictionary_.find(ident); + if (i == dictionary_.end()) { + return (empty_); + } else { + return (i->second); + } +} + +// Return global dictionary + +const MessageDictionaryPtr& +MessageDictionary::globalDictionary() { + static MessageDictionaryPtr global(new MessageDictionary()); + return (global); +} + + + + +} // namespace log +} // namespace isc diff --git a/src/lib/log/message_dictionary.h b/src/lib/log/message_dictionary.h new file mode 100644 index 0000000..6afc0f0 --- /dev/null +++ b/src/lib/log/message_dictionary.h @@ -0,0 +1,208 @@ +// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef MESSAGE_DICTIONARY_H +#define MESSAGE_DICTIONARY_H + +#include <cstddef> +#include <string> +#include <map> +#include <vector> + +#include <boost/lexical_cast.hpp> +#include <boost/shared_ptr.hpp> + +#include <log/message_types.h> + +namespace isc { +namespace log { + +/// \brief Forward declaration of \c MessageDictionary +class MessageDictionary; + +/// \brief Shared pointer to the \c MessageDictionary. +typedef boost::shared_ptr<MessageDictionary> MessageDictionaryPtr; + +/// \brief Message Dictionary +/// +/// The message dictionary is a wrapper around a std::map object, and allows +/// message text to be retrieved given the string identification. +/// +/// Adding text occurs in two modes: +/// +/// Through the "Add" method, ID/text mappings are added to the dictionary +/// unless the ID already exists. This is designed for use during program +/// initialization, where a local message may supplant a compiled-in message. +/// +/// Through the "Replace" method, ID/text mappings are added to the dictionary +/// only if the ID already exists. This is for use when a message file is +/// supplied to replace messages provided with the program. +/// +/// Although the class can be used stand-alone, it does supply a static method +/// to return a particular instance - the "global" dictionary. + +class MessageDictionary { +public: + + typedef std::map<std::string, std::string> Dictionary; + typedef Dictionary::const_iterator const_iterator; + + /// \brief Constructor + MessageDictionary(); + + /// \brief Virtual Destructor + virtual ~MessageDictionary(); + + /// \brief Add Message + /// + /// Adds a message to the dictionary. If the ID already exists, the ID is + /// added to the overflow vector. + /// + /// \param ident Identification of the message to add + /// \param text Message text + /// + /// \return true if the message was added to the dictionary, false if the + /// message existed and it was not added. + virtual bool add(const MessageID& ident, const std::string& text) { + return (add(boost::lexical_cast<std::string>(ident), text)); + } + + /// \brief Add Message + /// + /// Alternate signature. + /// + /// \param ident Identification of the message to add + /// \param text Message text + /// + /// \return true if the message was added to the dictionary, false if the + /// message existed and it was not added. + virtual bool add (const std::string& ident, const std::string& text); + + + /// \brief Replace Message + /// + /// Replaces a message in the dictionary. If the ID does not exist, it is + /// added to the overflow vector. + /// + /// \param ident Identification of the message to replace + /// \param text Message text + /// + /// \return true if the message was added to the dictionary, false if the + /// message did not exist and it was not added. + virtual bool replace(const MessageID& ident, const std::string& text) { + return (replace(boost::lexical_cast<std::string>(ident), text)); + } + + /// \brief Replace Message + /// + /// Alternate signature. + /// + /// \param ident Identification of the message to replace + /// \param text Message text + /// + /// \return true if the message was added to the dictionary, false if the + /// message did not exist and it was not added. + virtual bool replace(const std::string& ident, const std::string& text); + + + /// \brief Removes the specified message from the dictionary. + /// + /// Checks if both the message identifier and the text match the message + /// in the dictionary before removal. If the text doesn't match it is + /// an indication that the message which removal is requested is a + /// duplicate of another message. This may occur when two Kea modules + /// register messages with the same identifier. When one of the modules + /// is unloaded and the relevant messages are unregistered, there is a + /// need to make sure that the message registered by the other module + /// is not accidentally removed. Hence, the additional check for the + /// text match is needed. + /// + /// \param ident Identification of the message to remove. + /// \param text Message text + /// + /// \return true of the message has been removed, false if the message + /// couldn't be found. + virtual bool erase(const std::string& ident, const std::string& text); + + /// \brief Load Dictionary + /// + /// Designed to be used during the initialization of programs, this + /// accepts a set of (ID, text) pairs as a one-dimensional array of + /// const char* and adds them to the dictionary. The messages are added + /// using "Add". + /// + /// \param elements null-terminated array of const char* alternating ID and + /// message text. This should be an odd number of elements long, the last + /// element being NULL. If it is an even number of elements long, the + /// last ID is ignored. + /// + /// \return Vector of message IDs that were not loaded because an ID of the + /// same name already existing in the dictionary. This vector may be + /// empty. + virtual std::vector<std::string> load(const char* elements[]); + + /// \brief Get Message Text + /// + /// Given an ID, retrieve associated message text. + /// + /// \param ident Message identification + /// + /// \return Text associated with message or empty string if the ID is not + /// recognized. (Note: this precludes an ID being associated with an empty + /// string.) + virtual const std::string& getText(const MessageID& ident) const { + return(getText(boost::lexical_cast<std::string>(ident))); + } + + + /// \brief Get Message Text + /// + /// Alternate signature. + /// + /// \param ident Message identification + /// + /// \return Text associated with message or empty string if the ID is not + /// recognized. (Note: this precludes an ID being associated with an empty + /// string.) + virtual const std::string& getText(const std::string& ident) const; + + + /// \brief Number of Items in Dictionary + /// + /// \return Number of items in the dictionary + virtual size_t size() const { + return (dictionary_.size()); + } + + + /// \brief Return begin() iterator of internal map + const_iterator begin() const { + return (dictionary_.begin()); + } + + + /// \brief Return end() iterator of internal map + const_iterator end() const { + return (dictionary_.end()); + } + + + /// \brief Return Global Dictionary + /// + /// Returns a pointer to the singleton global dictionary. + /// + /// \return Pointer to global dictionary. + static const MessageDictionaryPtr& globalDictionary(); + +private: + Dictionary dictionary_; ///< Holds the ID to text lookups + const std::string empty_; ///< Empty string +}; + +} // namespace log +} // namespace isc + +#endif // MESSAGE_DICTIONARY_H diff --git a/src/lib/log/message_exception.h b/src/lib/log/message_exception.h new file mode 100644 index 0000000..f5c77cf --- /dev/null +++ b/src/lib/log/message_exception.h @@ -0,0 +1,112 @@ +// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef MESSAGE_EXCEPTION_H +#define MESSAGE_EXCEPTION_H + +#include <exceptions/exceptions.h> +#include <log/message_types.h> + +#include <stdexcept> +#include <string> +#include <vector> + +#include <boost/lexical_cast.hpp> + +namespace isc { +namespace log { + +/// \brief Message Exception +/// +/// Used in the message reader, this simple exception class allows a message +/// code and its arguments to be encapsulated in an exception and thrown +/// up the stack. + +class MessageException : public isc::Exception { +public: + + /// \brief Constructor + /// + /// \param file Filename where the exception occurred. + /// \param line Line where exception occurred. + /// \param what Text description of the problem. + /// \param id Message identification. + /// \param lineno Line number on which error occurred (if > 0). + MessageException(const char* file, size_t line, const char* what, + MessageID id, int lineno) + : isc::Exception(file, line, what), id_(id), lineno_(lineno) + { + if (lineno_ > 0) { + args_.push_back(boost::lexical_cast<std::string>(lineno)); + } + } + + /// \brief Constructor + /// + /// \param file Filename where the exception occurred. + /// \param line Line where exception occurred. + /// \param what Text description of the problem. + /// \param id Message identification. + /// \param arg1 First message argument. + /// \param lineno Line number on which error occurred (if > 0). + MessageException(const char* file, size_t line, const char* what, + MessageID id, const std::string& arg1, int lineno) + : isc::Exception(file, line, what), id_(id), lineno_(lineno) + { + if (lineno > 0) { + args_.push_back(boost::lexical_cast<std::string>(lineno)); + } + args_.push_back(arg1); + } + + /// \brief Constructor + /// + /// \param file Filename where the exception occurred. + /// \param line Line where exception occurred. + /// \param what Text description of the problem. + /// \param id Message identification. + /// \param arg1 First message argument. + /// \param arg2 Second message argument. + /// \param lineno Line number on which error occurred (if > 0). + MessageException(const char* file, size_t line, const char *what, + MessageID id, const std::string& arg1, + const std::string& arg2, int lineno) + : isc::Exception(file, line, what), id_(id), lineno_(lineno) + { + if (lineno > 0) { + args_.push_back(boost::lexical_cast<std::string>(lineno)); + } + args_.push_back(arg1); + args_.push_back(arg2); + } + + /// \brief Destructor + ~MessageException() {} + + /// \brief Return Message ID + /// + /// \return Message identification + MessageID id() const { + return id_; + } + + /// \brief Return Arguments + /// + /// \return Exception Arguments + std::vector<std::string> arguments() const { + return (args_); + } + +private: + MessageID id_; // Exception ID + std::vector<std::string> args_; // Exception arguments + int lineno_; +}; + +} // namespace log +} // namespace isc + +#endif // MESSAGE_EXCEPTION_H diff --git a/src/lib/log/message_initializer.cc b/src/lib/log/message_initializer.cc new file mode 100644 index 0000000..a7c85ed --- /dev/null +++ b/src/lib/log/message_initializer.cc @@ -0,0 +1,137 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/message_dictionary.h> +#include <log/message_initializer.h> +#include <algorithm> +#include <cassert> +#include <cstdlib> + + +namespace { + +using namespace isc::log; + +/// @brief Returns the shared pointer to the list of pointers to the +/// log messages defined. +/// +/// The returned pointer must be held in the \c MessageInitializer object +/// throughout its lifetime to make sure that the object doesn't outlive +/// the list and may still access it in the destructor. The returned +/// pointer is shared between all \c MessageInitializer instances. +LoggerValuesListPtr +getNonConstLoggerValues() { + static LoggerValuesListPtr logger_values(new LoggerValuesList()); + return (logger_values); +} + +/// @brief Returns the pointer to the list of message duplicates. +/// +/// The returned pointer must be held in the \c MessageInitializer object +/// throughout its lifetime to make sure that the object doesn't outlive +/// the list and may still access it in the destructor. The returned +/// pointer is shared between all \c MessageInitializer instances. +LoggerDuplicatesListPtr +getNonConstDuplicates() { + static LoggerDuplicatesListPtr duplicates(new LoggerDuplicatesList()); + return (duplicates); +} +} // end unnamed namespace + + +namespace isc { +namespace log { + +MessageInitializer::MessageInitializer(const char* values[]) + : values_(values), + global_dictionary_(MessageDictionary::globalDictionary()), + global_logger_values_(getNonConstLoggerValues()), + global_logger_duplicates_(getNonConstDuplicates()) { + global_logger_values_->push_back(values); +} + +MessageInitializer::~MessageInitializer() { + // Search for the pointer to pending messages belonging to our instance. + LoggerValuesList::iterator my_messages = std::find(global_logger_values_->begin(), + global_logger_values_->end(), + values_); + bool pending = (my_messages != global_logger_values_->end()); + // Our messages are still pending, so let's remove them from the list + // of pending messages. + if (pending) { + global_logger_values_->erase(my_messages); + + } else { + // Our messages are not pending, so they might have been loaded to + // the dictionary and/or duplicates. + int i = 0; + while (values_[i]) { + // Check if the unloaded message is registered as duplicate. If it is, + // remove it from the duplicates list. + LoggerDuplicatesList::iterator dup = + std::find(global_logger_duplicates_->begin(), + global_logger_duplicates_->end(), + values_[i]); + if (dup != global_logger_duplicates_->end()) { + global_logger_duplicates_->erase(dup); + + } else { + global_dictionary_->erase(values_[i], values_[i + 1]); + } + i += 2; + } + } +} + +// Return the number of arrays registered but not yet loaded. + +size_t +MessageInitializer::getPendingCount() { + return (getNonConstLoggerValues()->size()); +} + +// Load the messages in the arrays registered in the logger_values array +// into the global dictionary. + +void +MessageInitializer::loadDictionary(bool ignore_duplicates) { + const MessageDictionaryPtr& global = MessageDictionary::globalDictionary(); + const LoggerValuesListPtr& logger_values = getNonConstLoggerValues(); + + for (LoggerValuesList::const_iterator values = logger_values->begin(); + values != logger_values->end(); ++values) { + std::vector<std::string> repeats = global->load(*values); + + // Append the IDs in the list just loaded (the "repeats") to the + // global list of duplicate IDs. + if (!ignore_duplicates && !repeats.empty()) { + const LoggerDuplicatesListPtr& duplicates = getNonConstDuplicates(); + duplicates->insert(duplicates->end(), repeats.begin(), repeats.end()); + } + } + + // ... and mark that the messages have been loaded. (This avoids a lot + // of "duplicate message ID" messages in some of the unit tests where the + // logging initialization code may be called multiple times.) + logger_values->clear(); +} + +// Return reference to duplicates vector +const std::list<std::string>& +MessageInitializer::getDuplicates() { + return (*getNonConstDuplicates()); +} + +// Clear the duplicates vector +void +MessageInitializer::clearDuplicates() { + getNonConstDuplicates()->clear(); +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/message_initializer.h b/src/lib/log/message_initializer.h new file mode 100644 index 0000000..7f40f9b --- /dev/null +++ b/src/lib/log/message_initializer.h @@ -0,0 +1,170 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef MESSAGEINITIALIZER_H +#define MESSAGEINITIALIZER_H + +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> +#include <cstdlib> +#include <list> +#include <string> + +namespace isc { +namespace log { + +// Declare the MessageDictionary class to allow a pointer to it to be defined. +class MessageDictionary; + +/// @name Type definitions for containers shared among instances of the class. +/// +//\{ +/// \brief List of pointers to the messages. +typedef std::list<const char**> LoggerValuesList; +/// \brief Shared pointer to the list of pointers to the messages. +typedef boost::shared_ptr<LoggerValuesList> LoggerValuesListPtr; + +/// \brief List of duplicated messages. +typedef std::list<std::string> LoggerDuplicatesList; +/// \brief Shared pointer to the list of duplicated messages. +typedef boost::shared_ptr<LoggerDuplicatesList> LoggerDuplicatesListPtr; +//\} + +/// \brief Initialize Message Dictionary +/// +/// This is a helper class to add a set of message IDs and associated text to +/// the global dictionary. +/// +/// It should be declared outside an execution unit and initialized with +/// an array of values, alternating identifier, associated text and ending with +/// a NULL, e.g. +/// +/// static const char* values[] = { +/// "IDENT1", "message for ident 1", +/// "IDENT2", "message for ident 2", +/// : +/// NULL +/// }; +/// MessageInitializer xyz(values); +/// +/// All that needed is for the module containing the definitions to be +/// included in the execution unit. +/// +/// Dynamically loaded modules should call the initializer as well on the +/// moment they are instantiated. +/// +/// To avoid static initialization fiasco problems, the containers shared by +/// all instances of this class are dynamically allocated on first use, and +/// held in the smart pointers which are de-allocated only when all instances +/// of the class are destructed. After the object has been created with the +/// constructor, the \c MessageInitializer::loadDictionary static function is +/// called to populate the messages defined in various instances of the +/// \c MessageInitializer class to the global dictionary. +/// +/// When messages are added to the dictionary, the are added via the +/// MessageDictionary::add() method, so any duplicates are stored in the +/// global dictionary's overflow lince whence they can be retrieved at +/// run-time. + +class MessageInitializer : public boost::noncopyable { +public: + + /// \brief Constructor + /// + /// Adds a pointer to the array of messages to the global array of + /// pointers to message arrays. + /// + /// \param values NULL-terminated array of alternating identifier strings + /// and associated message text. N.B. This object stores a pointer to the + /// passed array; the array MUST remain valid at least until + /// loadDictionary() has been called. + MessageInitializer(const char* values[]); + + /// \brief Destructor + /// + /// Removes pending messages from the array or loaded messages from the + /// global dictionary. + /// + /// If the messages initialized with the destructed have already been + /// loaded to the global dictionary the destructor will remove these + /// messages and preserve messages loaded by other instances of the + /// \c MessageInitializer. If there are any duplicates, only the instance + /// of the duplicated message initialized by the destructed object will + /// be removed. + ~MessageInitializer(); + + /// \brief Obtain pending load count + /// + /// Returns the number of message arrays that will be loaded by the next + /// call to loadDictionary(). + /// + /// \return Number of registered message arrays. This is reset to zero + /// when loadDictionary() is called. + static size_t getPendingCount(); + + /// \brief Run-Time Initialization + /// + /// Loops through the internal array of pointers to message arrays + /// and adds the messages to the internal dictionary. This is called + /// during run-time initialization. + /// + /// \param ignore_duplicates If true, duplicate IDs, and IDs already + /// loaded, are ignored instead of stored in the global duplicates + /// list. + static void loadDictionary(bool ignore_duplicates = false); + + /// \brief Return Duplicates + /// + /// When messages are added to the global dictionary, any duplicates are + /// recorded. They can later be output through the logging system. + /// + /// \return List of duplicate message IDs when the global dictionary was + /// loaded. Note that the duplicates list itself may contain duplicates. + static const std::list<std::string>& getDuplicates(); + + /// \brief Clear the static duplicates list + /// + /// Empties the list returned by getDuplicates() + static void clearDuplicates(); + +private: + + /// \brief Holds the pointer to the array of messages. + const char** values_; + + /// \brief Holds the pointer to the global dictionary. + /// + /// One or more instances of \c MessageInitializer are created statically, + /// the \c MessageDictionary being created by the first one to run. As the + /// \c MessageDictionary is also accessed by the \c MessageInitializer + /// destructor, a smart pointer to it is kept. This avoids the possibility + /// that, during shutdown, the \c MessageDictionary is destroyed before all + /// instances of \c MessageInitializer. + boost::shared_ptr<MessageDictionary> global_dictionary_; + + /// \brief Holds the shared pointer to the list of pointers to the + /// log messages defined by various instances of this class. + /// + /// This pointer must be initialized in the constructor and held + /// throughout the lifetime of the \c MessageInitializer object. This + /// prevents static deinitialization fiasco when trying to access the + /// values in the list from the destructor of this class. + LoggerValuesListPtr global_logger_values_; + + /// \brief Holds the shared pointer to the collection od duplicated + /// messages. + /// + /// This pointer must be initialized in the constructor and held + /// throughout the lifetime of the \c MessageInitializer object. This + /// prevents static deinitialization fiasco when trying to access the + /// values in the list from the destructor of this class. + LoggerDuplicatesListPtr global_logger_duplicates_; +}; + +} // namespace log +} // namespace isc + +#endif // MESSAGEINITIALIZER_H diff --git a/src/lib/log/message_reader.cc b/src/lib/log/message_reader.cc new file mode 100644 index 0000000..2b48608 --- /dev/null +++ b/src/lib/log/message_reader.cc @@ -0,0 +1,279 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <errno.h> +#include <string.h> + +#include <iostream> +#include <fstream> + +#include <exceptions/isc_assert.h> +#include <log/log_messages.h> +#include <log/message_exception.h> +#include <log/message_reader.h> +#include <util/strutil.h> + +using namespace std; + +namespace { +const char DIRECTIVE_FLAG = '$'; // Starts each directive +const char MESSAGE_FLAG = '%'; // Starts each message +} + + +namespace isc { +namespace log { + +// Read the file. + +void +MessageReader::readFile(const string& file, MessageReader::Mode mode) { + + // Ensure the non-added collection is empty: we could be re-using this + // object. + not_added_.clear(); + + // Open the file. + ifstream infile(file.c_str()); + if (infile.fail()) { + isc_throw_4(MessageException, "Failed to open message file", + LOG_INPUT_OPEN_FAIL, file, strerror(errno), 0); + } + + // Loop round reading it. As we process the file one line at a time, + // keep a track of line number of aid diagnosis of problems. + string line; + getline(infile, line); + lineno_ = 0; + + while (infile.good()) { + ++lineno_; + processLine(line, mode); + getline(infile, line); + } + + // Why did the loop terminate? + if (!infile.eof()) { + isc_throw_4(MessageException, "Error reading message file", + LOG_READ_ERROR, file, strerror(errno), 0); + } + infile.close(); +} + +// Parse a line of the file. + +void +MessageReader::processLine(const string& line, MessageReader::Mode mode) { + + // Get rid of leading and trailing spaces + string text = isc::util::str::trim(line); + + if (text.empty()) { + ; // Ignore blank lines + + } else if (text[0] == DIRECTIVE_FLAG) { + parseDirective(text); // Process directives + + + } else if (text[0] == MESSAGE_FLAG) { + parseMessage(text, mode); // Process message definition line + + } else { + ; // Other lines are extended message + // description so are ignored + } +} + +// Process directive + +void +MessageReader::parseDirective(const std::string& text) { + + + // Break into tokens + vector<string> tokens = isc::util::str::tokens(text); + + // Uppercase directive and branch on valid ones + isc::util::str::uppercase(tokens[0]); + if (tokens[0] == string("$PREFIX")) { + parsePrefix(tokens); + + } else if (tokens[0] == string("$NAMESPACE")) { + parseNamespace(tokens); + + } else { + + // Unrecognized directive + isc_throw_3(MessageException, "Unrecognized directive", + LOG_UNRECOGNIZED_DIRECTIVE, tokens[0], + lineno_); + } +} + +// Process $PREFIX +void +MessageReader::parsePrefix(const vector<string>& tokens) { + + // Should not get here unless there is something in the tokens array. + isc_throw_assert(!tokens.empty()); + + // Process $PREFIX. With no arguments, the prefix is set to the empty + // string. One argument sets the prefix to the to its value and more than + // one argument is invalid. + if (tokens.size() == 1) { + prefix_ = ""; + + } else if (tokens.size() == 2) { + prefix_ = tokens[1]; + + // Token is potentially valid providing it only contains alphabetic + // and numeric characters (and underscores) and does not start with a + // digit. + if (invalidSymbol(prefix_)) { + isc_throw_3(MessageException, "Invalid prefix", + LOG_PREFIX_INVALID_ARG, prefix_, lineno_); + } + + } else { + + // Too many arguments + isc_throw_2(MessageException, "Too many arguments", + LOG_PREFIX_EXTRA_ARGS, lineno_); + } +} + +// Check if string is an invalid C++ symbol. It is valid if comprises only +// alphanumeric characters and underscores, and does not start with a digit. +// (Owing to the logic of the rest of the code, we check for its invalidity, +// not its validity.) +bool +MessageReader::invalidSymbol(const string& symbol) { + static const string valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789_"; + return ( symbol.empty() || + (symbol.find_first_not_of(valid_chars) != string::npos) || + (std::isdigit(symbol[0]))); +} + +// Process $NAMESPACE. A lot of the processing is similar to that of $PREFIX, +// except that only limited checks will be done on the namespace (to avoid a +// lot of parsing and separating out of the namespace components.) Also, unlike +// $PREFIX, there can only be one $NAMESPACE in a file. + +void +MessageReader::parseNamespace(const vector<string>& tokens) { + + // Check argument count + if (tokens.size() < 2) { + isc_throw_2(MessageException, "No arguments", LOG_NAMESPACE_NO_ARGS, + lineno_); + + } else if (tokens.size() > 2) { + isc_throw_2(MessageException, "Too many arguments", + LOG_NAMESPACE_EXTRA_ARGS, lineno_); + + } + + // Token is potentially valid providing it only contains alphabetic + // and numeric characters (and underscores and colons). As noted above, + // we won't be exhaustive - after all, and code containing the resultant + // namespace will have to be compiled, and the compiler will catch errors. + static const string valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789_:"; + if (tokens[1].find_first_not_of(valid_chars) != string::npos) { + isc_throw_3(MessageException, "Invalid argument", + LOG_NAMESPACE_INVALID_ARG, tokens[1], lineno_); + } + + // All OK - unless the namespace has already been set. + if (ns_.size() != 0) { + isc_throw_2(MessageException, "Duplicate namespace", + LOG_DUPLICATE_NAMESPACE, lineno_); + } + + // Prefix has not been set, so set it and return success. + ns_ = tokens[1]; +} + +// Process message. By the time this method is called, the line has been +// stripped of leading and trailing spaces. The first character of the string +// is the message introducer, so we can get rid of that. The remainder is +// a line defining a message. +// +// The first token on the line, when concatenated to the prefix and converted to +// upper-case, is the message ID. The first of the line from the next token +// on is the message text. + +void +MessageReader::parseMessage(const std::string& text, MessageReader::Mode mode) { + + static string delimiters("\t\n "); // Delimiters + + // The line passed should be at least one character long and start with the + // message introducer (else we should not have got here). + isc_throw_assert((text.size() >= 1) && (text[0] == MESSAGE_FLAG)); + + // A line comprising just the message introducer is not valid. + if (text.size() == 1) { + isc_throw_3(MessageException, "No message ID", LOG_NO_MESSAGE_ID, + text, lineno_); + } + + // Strip off the introducer and any leading space after that. + string message_line = isc::util::str::trim(text.substr(1)); + + // Look for the first delimiter. + size_t first_delim = message_line.find_first_of(delimiters); + if (first_delim == string::npos) { + + // Just a single token in the line - this is not valid + isc_throw_3(MessageException, "No message text", LOG_NO_MESSAGE_TEXT, + message_line, lineno_); + } + + // Extract the first token into the message ID, preceding it with the + // current prefix, then convert to upper-case. If the prefix is not set, + // perform the valid character check now - the string will become a C++ + // symbol so we may as well identify problems early. + string ident = prefix_ + message_line.substr(0, first_delim); + if (prefix_.empty()) { + if (invalidSymbol(ident)) { + isc_throw_3(MessageException, "Invalid message ID", + LOG_INVALID_MESSAGE_ID, ident, lineno_); + } + } + isc::util::str::uppercase(ident); + + // Locate the start of the message text + size_t first_text = message_line.find_first_not_of(delimiters, first_delim); + if (first_text == string::npos) { + + // ?? This happens if there are trailing delimiters, which should not + // occur as we have stripped trailing spaces off the line. Just treat + // this as a single-token error for simplicity's sake. + isc_throw_3(MessageException, "No message text", LOG_NO_MESSAGE_TEXT, + message_line, lineno_); + } + + // Add the result to the dictionary and to the non-added list if the add to + // the dictionary fails. + bool added; + if (mode == ADD) { + added = dictionary_->add(ident, message_line.substr(first_text)); + } else { + added = dictionary_->replace(ident, message_line.substr(first_text)); + } + if (!added) { + not_added_.push_back(ident); + } +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/message_reader.h b/src/lib/log/message_reader.h new file mode 100644 index 0000000..65fdb2b --- /dev/null +++ b/src/lib/log/message_reader.h @@ -0,0 +1,207 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef MESSAGE_READER_H +#define MESSAGE_READER_H + +#include <map> +#include <string> +#include <vector> + +#include <log/message_dictionary.h> +#include <log/message_types.h> + +namespace isc { +namespace log { + +/// \brief Read Message File +/// +/// Reads a message file and creates a map of identifier against the text of the +/// message. This map can be retrieved for subsequent processing. + +class MessageReader { +public: + + /// \brief Read Mode + /// + /// If ADD, messages are added to the dictionary if the ID does not exist + /// there. If it does, the ID is added to the dictionary's overflow + /// vector. + /// + /// If REPLACE, the dictionary is only modified if the message ID already + /// exists in it. New message IDs are added to the overflow vector. + typedef enum { + ADD, + REPLACE + } Mode; + + /// \brief Visible collection types + typedef std::vector<std::string> MessageIDCollection; + + /// \brief Constructor + /// + /// Default constructor. All work is done in the main readFile code (so + /// that a status return can be returned instead of needing to throw an + /// exception). + /// + /// \param dictionary Dictionary to which messages read read from the file + /// are added. (This should be a local dictionary when the class is used in + /// the message compiler, and the global dictionary when used in a server. + /// The ownership of the dictionary object is not transferred - the caller + /// is responsible for managing the lifetime of the dictionary. + MessageReader(MessageDictionary* dictionary = NULL) : + dictionary_(dictionary), lineno_(0) + {} + + /// \brief Virtual Destructor + virtual ~MessageReader() + {} + + /// \brief Get Dictionary + /// + /// Returns the pointer to the dictionary object. Note that ownership is + /// not transferred - the caller should not delete it. + /// + /// \return Pointer to current dictionary object + MessageDictionary* getDictionary() const { + return (dictionary_); + } + + + /// \brief Set Dictionary + /// + /// Sets the current dictionary object. + /// + /// \param dictionary New dictionary object. The ownership of the dictionary + /// object is not transferred - the caller is responsible for managing the + /// lifetime of the dictionary. + void setDictionary(MessageDictionary* dictionary) { + dictionary_ = dictionary; + } + + + /// \brief Read File + /// + /// This is the main method of the class and reads in the file, parses it, + /// and stores the result in the message dictionary. + /// + /// \param file Name of the message file. + /// \param mode Addition mode. See the description of the "Mode" enum. + virtual void readFile(const std::string& file, Mode mode = ADD); + + + /// \brief Process Line + /// + /// Parses a text line and adds it to the message map. Although this is + /// for use in readFile, it can also be used to add individual messages + /// to the message map. + /// + /// \param line Line of text to process + /// \param mode If a message line, how to add the message to the dictionary. + virtual void processLine(const std::string& line, Mode mode = ADD); + + + /// \brief Get Namespace + /// + /// \return Argument to the $NAMESPACE directive (if present) + virtual std::string getNamespace() const { + return (ns_); + } + + + /// \brief Clear Namespace + /// + /// Clears the current namespace. + virtual void clearNamespace() { + ns_ = ""; + } + + + /// \brief Get Prefix + /// + /// \return Argument to the $PREFIX directive (if present) + virtual std::string getPrefix() const { + return (prefix_); + } + + + /// \brief Clear Prefix + /// + /// Clears the current prefix. + virtual void clearPrefix() { + prefix_ = ""; + } + + + /// \brief Get Not-Added List + /// + /// Returns the list of IDs that were not added during the last + /// read of the file. + /// + /// \return Collection of messages not added + MessageIDCollection getNotAdded() const { + return (not_added_); + } + +private: + + /// \brief Handle a Message Definition + /// + /// Passed a line that should contain a message, this processes that line + /// and adds it to the dictionary according to the mode setting. + /// + /// \param line Line of text + /// \param ADD or REPLACE depending on how the reader is operating. (See + /// the description of the Mode typedef for details.) + void parseMessage(const std::string& line, Mode mode); + + + /// \brief Handle Directive + /// + /// Passed a line starting with a "$", this handles the processing of + /// directives. + /// + /// \param line Line of text that starts with "$", + void parseDirective(const std::string& line); + + + /// \brief Parse $PREFIX line + /// + /// \param tokens $PREFIX line split into tokens + void parsePrefix(const std::vector<std::string>& tokens); + + + /// \brief Parse $NAMESPACE line + /// + /// \param tokens $NAMESPACE line split into tokens + void parseNamespace(const std::vector<std::string>& tokens); + + /// \brief Check for invalid C++ symbol name + /// + /// The message ID (or concatenation of prefix and message ID) will be used + /// as the name of a symbol in C++ code. This function checks if the name + /// is invalid (contains anything other than alphanumeric characters or + /// underscores, or starts with a digit). + /// + /// \param symbol name to check to see if it is an invalid C++ symbol. + /// + /// \return true if the name is invalid, false if it is valid. + bool invalidSymbol(const std::string& symbol); + + + + /// Attributes + MessageDictionary* dictionary_; ///< Dictionary to add messages to + MessageIDCollection not_added_; ///< List of IDs not added + int lineno_; ///< Number of last line read + std::string prefix_; ///< Argument of $PREFIX statement + std::string ns_; ///< Argument of $NAMESPACE statement +}; + +} // namespace log +} // namespace isc + +#endif // MESSAGE_READER_H diff --git a/src/lib/log/message_types.h b/src/lib/log/message_types.h new file mode 100644 index 0000000..6991bd6 --- /dev/null +++ b/src/lib/log/message_types.h @@ -0,0 +1,29 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef MESSAGE_TYPES_H +#define MESSAGE_TYPES_H + +#include <string.h> + +namespace isc { +namespace log { + +typedef const char* MessageID; + +/// \brief Compare MessageID for Equality +/// +/// \param m1 First message ID +/// \param m2 Second message ID +/// \return true if they are equal, false if not +bool equalMessageID(const MessageID& m1, const MessageID& m2); + +} // namespace log +} // namespace isc + + + +#endif // MESSAGE_TYPES_H diff --git a/src/lib/log/output_option.cc b/src/lib/log/output_option.cc new file mode 100644 index 0000000..0073c7f --- /dev/null +++ b/src/lib/log/output_option.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <string> + +#include <boost/algorithm/string.hpp> + +#include <log/log_messages.h> +#include <log/macros.h> +#include <log/output_option.h> + +namespace isc { +namespace log { + +/// Default layout pattern for console logs +const std::string OutputOption::DEFAULT_CONSOLE_PATTERN = "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c/%i.%t] %m\n"; + +/// Default layout pattern for file logs +const std::string OutputOption::DEFAULT_FILE_PATTERN = "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c/%i.%t] %m\n"; + +/// Default layout pattern for syslog logs +const std::string OutputOption::DEFAULT_SYSLOG_PATTERN = "%-5p [%c.%t] %m\n"; + +OutputOption::Destination +getDestination(const std::string& dest_str) { + if (boost::iequals(dest_str, "console")) { + return OutputOption::DEST_CONSOLE; + } else if (boost::iequals(dest_str, "file")) { + return OutputOption::DEST_FILE; + } else if (boost::iequals(dest_str, "syslog")) { + return OutputOption::DEST_SYSLOG; + } else { + Logger logger("log"); + LOG_ERROR(logger, LOG_BAD_DESTINATION).arg(dest_str); + return OutputOption::DEST_CONSOLE; + } +} + +OutputOption::Stream +getStream(const std::string& stream_str) { + if (boost::iequals(stream_str, "stderr")) { + return OutputOption::STR_STDERR; + } else if (boost::iequals(stream_str, "stdout")) { + return OutputOption::STR_STDOUT; + } else { + Logger logger("log"); + LOG_ERROR(logger, LOG_BAD_STREAM).arg(stream_str); + return OutputOption::STR_STDOUT; + } +} + +} // namespace log +} // namespace isc diff --git a/src/lib/log/output_option.h b/src/lib/log/output_option.h new file mode 100644 index 0000000..09d9d3d --- /dev/null +++ b/src/lib/log/output_option.h @@ -0,0 +1,85 @@ +// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef OUTPUT_OPTION_H +#define OUTPUT_OPTION_H + +#include <stdint.h> +#include <stdlib.h> +#include <string> + +/// \brief Logger Output Option +/// +/// The logging configuration options are a list of logger specifications, each +/// with one or more output options. This class represents an output option; +/// one or more of these are attached to a LoggerSpecification object which is +/// then passed to the LoggerManager to configure the logger. +/// +/// Although there are three distinct output types (console, file, syslog) and +/// the options for each do not really overlap. Although it is tempting to +/// define a base OutputOption class and derive a class for each type +/// (ConsoleOutputOptions etc.), it would be messy to use in practice. At +/// some point the exact class would have to be known to get the class-specific +/// options and the (pointer to) the base class cast to the appropriate type. +/// Instead, this "struct" contains the union of all output options; it is up +/// to the caller to cherry-pick the members it needs. +/// +/// One final note: this object holds data and does no computation. For this +/// reason, it is a "struct" and members are accessed directly instead of +/// through methods. + +namespace isc { +namespace log { + +struct OutputOption { + + /// Default layout pattern for console logs + static const std::string DEFAULT_CONSOLE_PATTERN; + /// Default layout pattern for file logs + static const std::string DEFAULT_FILE_PATTERN; + /// Default layout pattern for syslog logs + static const std::string DEFAULT_SYSLOG_PATTERN; + + /// Destinations. Prefixed "DEST_" to avoid problems with the C stdio.h + /// FILE type. + typedef enum { + DEST_CONSOLE = 0, + DEST_FILE = 1, + DEST_SYSLOG = 2 + } Destination; + + /// If console, stream on which messages are output + typedef enum { + STR_STDOUT = 1, + STR_STDERR = 2 + } Stream; + + /// \brief Constructor + OutputOption() : destination(DEST_CONSOLE), stream(STR_STDERR), + flush(true), facility("LOCAL0"), filename(""), + maxsize(0), maxver(0), pattern("") + {} + + /// Members. + + Destination destination; ///< Where the output should go + Stream stream; ///< stdout/stderr if console output + bool flush; ///< true to flush after each message + std::string facility; ///< syslog facility + std::string filename; ///< Filename if file output + uint64_t maxsize; ///< 0 if no maximum size + unsigned int maxver; ///< Maximum versions (none if <= 0) + std::string pattern; ///< log content pattern +}; + +OutputOption::Destination getDestination(const std::string& dest_str); +OutputOption::Stream getStream(const std::string& stream_str); + + +} // namespace log +} // namespace isc + +#endif // OUTPUT_OPTION_H diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am new file mode 100644 index 0000000..55240aa --- /dev/null +++ b/src/lib/log/tests/Makefile.am @@ -0,0 +1,158 @@ +SUBDIRS = . + +# Define the flags used in each set of tests. +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES) + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +AM_LDADD = +AM_LDADD += $(top_builddir)/src/lib/log/libkea-log.la +AM_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la +AM_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +AM_LDADD += $(LOG4CPLUS_LIBS) $(GTEST_LDADD) + +AM_LDFLAGS = +if USE_STATIC_LINK +AM_LDFLAGS += -static +endif + +CLEANFILES = *.gcno *.gcda *.lock + +EXTRA_DIST = log_test_messages.mes + +# Helper programs used in shell tests +TEST_HELPERS = logger_example +logger_example_SOURCES = logger_example.cc +logger_example_CPPFLAGS = $(AM_CPPFLAGS) +logger_example_CXXFLAGS = $(AM_CXXFLAGS) +logger_example_LDADD = $(AM_LDADD) +logger_example_LDFLAGS = $(AM_LDFLAGS) + +TEST_HELPERS += init_logger_test +init_logger_test_SOURCES = init_logger_test.cc +init_logger_test_CPPFLAGS = $(AM_CPPFLAGS) +init_logger_test_CXXFLAGS = $(AM_CXXFLAGS) +init_logger_test_LDADD = $(AM_LDADD) +init_logger_test_LDFLAGS = $(AM_LDFLAGS) + +TEST_HELPERS += buffer_logger_test +buffer_logger_test_SOURCES = buffer_logger_test.cc +buffer_logger_test_CPPFLAGS = $(AM_CPPFLAGS) +buffer_logger_test_CXXFLAGS = $(AM_CXXFLAGS) +buffer_logger_test_LDADD = $(AM_LDADD) +buffer_logger_test_LDFLAGS = $(AM_LDFLAGS) + +TEST_HELPERS += logger_lock_test +logger_lock_test_SOURCES = logger_lock_test.cc +logger_lock_test_SOURCES += log_test_messages.cc log_test_messages.h +logger_lock_test_CPPFLAGS = $(AM_CPPFLAGS) +logger_lock_test_CXXFLAGS = $(AM_CXXFLAGS) +logger_lock_test_LDADD = $(AM_LDADD) +logger_lock_test_LDFLAGS = $(AM_LDFLAGS) + +# Don't install helper binaries. +noinst_PROGRAMS = $(TEST_HELPERS) + +# Shell tests. These are principally tests where the global logging environment +# is affected, and where the output needs to be compared with stored output +# (where "cut" and "diff" are useful utilities). +SHTESTS = +SHTESTS += buffer_logger_test.sh +SHTESTS += console_test.sh +SHTESTS += destination_test.sh +SHTESTS += init_logger_test.sh +SHTESTS += local_file_test.sh +SHTESTS += logger_lock_test.sh +SHTESTS += severity_test.sh + +# As with every file generated by ./configure, clean them up when running +# "make distclean", but not on "make clean". +DISTCLEANFILES = tempdir.h +DISTCLEANFILES += $(SHTESTS) + +if HAVE_GTEST + +TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) + +# Set of unit tests for the general logging classes +PROGRAM_TESTS = run_unittests +run_unittests_SOURCES = run_unittests.cc +run_unittests_SOURCES += log_formatter_unittest.cc +run_unittests_SOURCES += logger_level_impl_unittest.cc +run_unittests_SOURCES += logger_level_unittest.cc +run_unittests_SOURCES += logger_manager_unittest.cc +run_unittests_SOURCES += logger_name_unittest.cc +run_unittests_SOURCES += logger_support_unittest.cc +run_unittests_SOURCES += logger_unittest.cc +run_unittests_SOURCES += logger_specification_unittest.cc +run_unittests_SOURCES += message_dictionary_unittest.cc +run_unittests_SOURCES += message_reader_unittest.cc +run_unittests_SOURCES += output_option_unittest.cc +run_unittests_SOURCES += buffer_appender_unittest.cc +run_unittests_SOURCES += log_test_messages.cc log_test_messages.h +run_unittests_CPPFLAGS = $(AM_CPPFLAGS) +run_unittests_CXXFLAGS = $(AM_CXXFLAGS) +run_unittests_LDADD = $(AM_LDADD) +run_unittests_LDFLAGS = $(AM_LDFLAGS) + +# logging initialization tests. These are put in a separate program to +# ensure that the initialization status at the start of each test is known, +# and to prevent circumstances where the execution of one test affects the +# starting conditions of the next. +PROGRAM_TESTS += initializer_unittests_1 +initializer_unittests_1_SOURCES = run_initializer_unittests.cc +initializer_unittests_1_SOURCES += message_initializer_1_unittest.cc +initializer_unittests_1_SOURCES += message_initializer_1a_unittest.cc +initializer_unittests_1_CPPFLAGS = $(AM_CPPFLAGS) +initializer_unittests_1_CXXFLAGS = $(AM_CXXFLAGS) +initializer_unittests_1_LDADD = $(AM_LDADD) +initializer_unittests_1_LDFLAGS = $(AM_LDFLAGS) + +# Run C++ tests on "make check". +TESTS = $(PROGRAM_TESTS) + +# Run shell tests on "make check". +check_SCRIPTS = $(SHTESTS) +TESTS += $(SHTESTS) + +# Don't install test binaries. +noinst_PROGRAMS += $(PROGRAM_TESTS) + +endif + +# Don't install shell tests. +noinst_SCRIPTS = $(SHTESTS) + +# If we want to get rid of all generated messages files, we need to use +# make maintainer-clean. The proper way to introduce custom commands for +# that operation is to define maintainer-clean-local target. However, +# make maintainer-clean also removes Makefile, so running configure script +# is required. To make it easy to rebuild messages without going through +# reconfigure, a new target messages-clean has been added. +maintainer-clean-local: + rm -f log_test_messages.h log_test_messages.cc + +# To regenerate messages files, one can do: +# +# make messages-clean +# make messages +# +# This is needed only when a .mes file is modified. +messages-clean: maintainer-clean-local + +if GENERATE_MESSAGES + +# Define rule to build logging source files from message file +messages: log_test_messages.h log_test_messages.cc + @echo Message files regenerated + +log_test_messages.h log_test_messages.cc: log_test_messages.mes + $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/log/tests/log_test_messages.mes + +else + +messages log_test_messages.h log_test_messages.cc: + @echo Messages generation disabled. Configure with --enable-generate-messages to enable it. + +endif diff --git a/src/lib/log/tests/Makefile.in b/src/lib/log/tests/Makefile.in new file mode 100644 index 0000000..721a9e7 --- /dev/null +++ b/src/lib/log/tests/Makefile.in @@ -0,0 +1,1602 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@USE_STATIC_LINK_TRUE@am__append_1 = -static +noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_3) +@HAVE_GTEST_TRUE@TESTS = $(am__EXEEXT_2) $(SHTESTS) + +# Don't install test binaries. +@HAVE_GTEST_TRUE@am__append_2 = $(PROGRAM_TESTS) +subdir = src/lib/log/tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \ + $(top_srcdir)/m4macros/ax_cpp11.m4 \ + $(top_srcdir)/m4macros/ax_cpp20.m4 \ + $(top_srcdir)/m4macros/ax_crypto.m4 \ + $(top_srcdir)/m4macros/ax_find_library.m4 \ + $(top_srcdir)/m4macros/ax_gssapi.m4 \ + $(top_srcdir)/m4macros/ax_gtest.m4 \ + $(top_srcdir)/m4macros/ax_isc_rpath.m4 \ + $(top_srcdir)/m4macros/ax_netconf.m4 \ + $(top_srcdir)/m4macros/libtool.m4 \ + $(top_srcdir)/m4macros/ltoptions.m4 \ + $(top_srcdir)/m4macros/ltsugar.m4 \ + $(top_srcdir)/m4macros/ltversion.m4 \ + $(top_srcdir)/m4macros/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = buffer_logger_test.sh console_test.sh \ + destination_test.sh init_logger_test.sh local_file_test.sh \ + logger_lock_test.sh severity_test.sh tempdir.h +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = logger_example$(EXEEXT) init_logger_test$(EXEEXT) \ + buffer_logger_test$(EXEEXT) logger_lock_test$(EXEEXT) +@HAVE_GTEST_TRUE@am__EXEEXT_2 = run_unittests$(EXEEXT) \ +@HAVE_GTEST_TRUE@ initializer_unittests_1$(EXEEXT) +@HAVE_GTEST_TRUE@am__EXEEXT_3 = $(am__EXEEXT_2) +PROGRAMS = $(noinst_PROGRAMS) +am_buffer_logger_test_OBJECTS = \ + buffer_logger_test-buffer_logger_test.$(OBJEXT) +buffer_logger_test_OBJECTS = $(am_buffer_logger_test_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(top_builddir)/src/lib/log/libkea-log.la \ + $(top_builddir)/src/lib/util/unittests/libutil_unittests.la \ + $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +buffer_logger_test_DEPENDENCIES = $(am__DEPENDENCIES_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +buffer_logger_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(buffer_logger_test_CXXFLAGS) $(CXXFLAGS) \ + $(buffer_logger_test_LDFLAGS) $(LDFLAGS) -o $@ +am_init_logger_test_OBJECTS = \ + init_logger_test-init_logger_test.$(OBJEXT) +init_logger_test_OBJECTS = $(am_init_logger_test_OBJECTS) +init_logger_test_DEPENDENCIES = $(am__DEPENDENCIES_2) +init_logger_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(init_logger_test_CXXFLAGS) $(CXXFLAGS) \ + $(init_logger_test_LDFLAGS) $(LDFLAGS) -o $@ +am__initializer_unittests_1_SOURCES_DIST = \ + run_initializer_unittests.cc message_initializer_1_unittest.cc \ + message_initializer_1a_unittest.cc +@HAVE_GTEST_TRUE@am_initializer_unittests_1_OBJECTS = initializer_unittests_1-run_initializer_unittests.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ initializer_unittests_1-message_initializer_1_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ initializer_unittests_1-message_initializer_1a_unittest.$(OBJEXT) +initializer_unittests_1_OBJECTS = \ + $(am_initializer_unittests_1_OBJECTS) +@HAVE_GTEST_TRUE@initializer_unittests_1_DEPENDENCIES = \ +@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_2) +initializer_unittests_1_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) \ + $(initializer_unittests_1_LDFLAGS) $(LDFLAGS) -o $@ +am_logger_example_OBJECTS = logger_example-logger_example.$(OBJEXT) +logger_example_OBJECTS = $(am_logger_example_OBJECTS) +logger_example_DEPENDENCIES = $(am__DEPENDENCIES_2) +logger_example_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(logger_example_CXXFLAGS) $(CXXFLAGS) \ + $(logger_example_LDFLAGS) $(LDFLAGS) -o $@ +am_logger_lock_test_OBJECTS = \ + logger_lock_test-logger_lock_test.$(OBJEXT) \ + logger_lock_test-log_test_messages.$(OBJEXT) +logger_lock_test_OBJECTS = $(am_logger_lock_test_OBJECTS) +logger_lock_test_DEPENDENCIES = $(am__DEPENDENCIES_2) +logger_lock_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) \ + $(logger_lock_test_LDFLAGS) $(LDFLAGS) -o $@ +am__run_unittests_SOURCES_DIST = run_unittests.cc \ + log_formatter_unittest.cc logger_level_impl_unittest.cc \ + logger_level_unittest.cc logger_manager_unittest.cc \ + logger_name_unittest.cc logger_support_unittest.cc \ + logger_unittest.cc logger_specification_unittest.cc \ + message_dictionary_unittest.cc message_reader_unittest.cc \ + output_option_unittest.cc buffer_appender_unittest.cc \ + log_test_messages.cc log_test_messages.h +@HAVE_GTEST_TRUE@am_run_unittests_OBJECTS = \ +@HAVE_GTEST_TRUE@ run_unittests-run_unittests.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-log_formatter_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_level_impl_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_level_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_manager_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_name_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_support_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-logger_specification_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-message_dictionary_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-message_reader_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-output_option_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-buffer_appender_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-log_test_messages.$(OBJEXT) +run_unittests_OBJECTS = $(am_run_unittests_OBJECTS) +@HAVE_GTEST_TRUE@run_unittests_DEPENDENCIES = $(am__DEPENDENCIES_2) +run_unittests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(run_unittests_CXXFLAGS) $(CXXFLAGS) $(run_unittests_LDFLAGS) \ + $(LDFLAGS) -o $@ +SCRIPTS = $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + ./$(DEPDIR)/buffer_logger_test-buffer_logger_test.Po \ + ./$(DEPDIR)/init_logger_test-init_logger_test.Po \ + ./$(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Po \ + ./$(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Po \ + ./$(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Po \ + ./$(DEPDIR)/logger_example-logger_example.Po \ + ./$(DEPDIR)/logger_lock_test-log_test_messages.Po \ + ./$(DEPDIR)/logger_lock_test-logger_lock_test.Po \ + ./$(DEPDIR)/run_unittests-buffer_appender_unittest.Po \ + ./$(DEPDIR)/run_unittests-log_formatter_unittest.Po \ + ./$(DEPDIR)/run_unittests-log_test_messages.Po \ + ./$(DEPDIR)/run_unittests-logger_level_impl_unittest.Po \ + ./$(DEPDIR)/run_unittests-logger_level_unittest.Po \ + ./$(DEPDIR)/run_unittests-logger_manager_unittest.Po \ + ./$(DEPDIR)/run_unittests-logger_name_unittest.Po \ + ./$(DEPDIR)/run_unittests-logger_specification_unittest.Po \ + ./$(DEPDIR)/run_unittests-logger_support_unittest.Po \ + ./$(DEPDIR)/run_unittests-logger_unittest.Po \ + ./$(DEPDIR)/run_unittests-message_dictionary_unittest.Po \ + ./$(DEPDIR)/run_unittests-message_reader_unittest.Po \ + ./$(DEPDIR)/run_unittests-output_option_unittest.Po \ + ./$(DEPDIR)/run_unittests-run_unittests.Po +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(buffer_logger_test_SOURCES) $(init_logger_test_SOURCES) \ + $(initializer_unittests_1_SOURCES) $(logger_example_SOURCES) \ + $(logger_lock_test_SOURCES) $(run_unittests_SOURCES) +DIST_SOURCES = $(buffer_logger_test_SOURCES) \ + $(init_logger_test_SOURCES) \ + $(am__initializer_unittests_1_SOURCES_DIST) \ + $(logger_example_SOURCES) $(logger_lock_test_SOURCES) \ + $(am__run_unittests_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/buffer_logger_test.sh.in \ + $(srcdir)/console_test.sh.in $(srcdir)/destination_test.sh.in \ + $(srcdir)/init_logger_test.sh.in \ + $(srcdir)/local_file_test.sh.in \ + $(srcdir)/logger_lock_test.sh.in $(srcdir)/severity_test.sh.in \ + $(srcdir)/tempdir.h.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_INCLUDES = @BOOST_INCLUDES@ +BOOST_LIBS = @BOOST_LIBS@ +BOTAN_TOOL = @BOTAN_TOOL@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONTRIB_DIR = @CONTRIB_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ +CRYPTO_INCLUDES = @CRYPTO_INCLUDES@ +CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPTO_PACKAGE = @CRYPTO_PACKAGE@ +CRYPTO_RPATH = @CRYPTO_RPATH@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@ +DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@ +DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@ +DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@ +DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@ +DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@ +DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@ +DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@ +DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@ +DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@ +DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@ +DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@ +DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@ +DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@ +DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_INCLUDES = @GTEST_INCLUDES@ +GTEST_LDADD = @GTEST_LDADD@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_SOURCE = @GTEST_SOURCE@ +HAVE_NETCONF = @HAVE_NETCONF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KEA_CXXFLAGS = @KEA_CXXFLAGS@ +KEA_SRCID = @KEA_SRCID@ +KRB5_CONFIG = @KRB5_CONFIG@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@ +LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@ +LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@ +LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@ +LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@ +LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@ +LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@ +LIBYANG_LIBS = @LIBYANG_LIBS@ +LIBYANG_PREFIX = @LIBYANG_PREFIX@ +LIBYANG_VERSION = @LIBYANG_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@ +LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +PERL = @PERL@ +PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PKGPYTHONDIR = @PKGPYTHONDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PLANTUML = @PLANTUML@ +PREMIUM_DIR = @PREMIUM_DIR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SEP = @SEP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINXBUILD = @SPHINXBUILD@ +SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@ +SR_PLUGINS_PATH = @SR_PLUGINS_PATH@ +SR_REPO_PATH = @SR_REPO_PATH@ +STRIP = @STRIP@ +SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@ +SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@ +SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@ +SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@ +SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@ +SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@ +SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@ +SYSREPO_LIBS = @SYSREPO_LIBS@ +SYSREPO_PREFIX = @SYSREPO_PREFIX@ +SYSREPO_VERSION = @SYSREPO_VERSION@ +USE_LCOV = @USE_LCOV@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . + +# Define the flags used in each set of tests. +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib \ + $(BOOST_INCLUDES) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES) +AM_CXXFLAGS = $(KEA_CXXFLAGS) +AM_LDADD = $(top_builddir)/src/lib/log/libkea-log.la \ + $(top_builddir)/src/lib/util/unittests/libutil_unittests.la \ + $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \ + $(LOG4CPLUS_LIBS) $(GTEST_LDADD) +AM_LDFLAGS = $(am__append_1) +CLEANFILES = *.gcno *.gcda *.lock +EXTRA_DIST = log_test_messages.mes + +# Helper programs used in shell tests +TEST_HELPERS = logger_example init_logger_test buffer_logger_test \ + logger_lock_test +logger_example_SOURCES = logger_example.cc +logger_example_CPPFLAGS = $(AM_CPPFLAGS) +logger_example_CXXFLAGS = $(AM_CXXFLAGS) +logger_example_LDADD = $(AM_LDADD) +logger_example_LDFLAGS = $(AM_LDFLAGS) +init_logger_test_SOURCES = init_logger_test.cc +init_logger_test_CPPFLAGS = $(AM_CPPFLAGS) +init_logger_test_CXXFLAGS = $(AM_CXXFLAGS) +init_logger_test_LDADD = $(AM_LDADD) +init_logger_test_LDFLAGS = $(AM_LDFLAGS) +buffer_logger_test_SOURCES = buffer_logger_test.cc +buffer_logger_test_CPPFLAGS = $(AM_CPPFLAGS) +buffer_logger_test_CXXFLAGS = $(AM_CXXFLAGS) +buffer_logger_test_LDADD = $(AM_LDADD) +buffer_logger_test_LDFLAGS = $(AM_LDFLAGS) +logger_lock_test_SOURCES = logger_lock_test.cc log_test_messages.cc \ + log_test_messages.h +logger_lock_test_CPPFLAGS = $(AM_CPPFLAGS) +logger_lock_test_CXXFLAGS = $(AM_CXXFLAGS) +logger_lock_test_LDADD = $(AM_LDADD) +logger_lock_test_LDFLAGS = $(AM_LDFLAGS) + +# Shell tests. These are principally tests where the global logging environment +# is affected, and where the output needs to be compared with stored output +# (where "cut" and "diff" are useful utilities). +SHTESTS = buffer_logger_test.sh console_test.sh destination_test.sh \ + init_logger_test.sh local_file_test.sh logger_lock_test.sh \ + severity_test.sh + +# As with every file generated by ./configure, clean them up when running +# "make distclean", but not on "make clean". +DISTCLEANFILES = tempdir.h $(SHTESTS) +@HAVE_GTEST_TRUE@TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) + +# Set of unit tests for the general logging classes + +# logging initialization tests. These are put in a separate program to +# ensure that the initialization status at the start of each test is known, +# and to prevent circumstances where the execution of one test affects the +# starting conditions of the next. +@HAVE_GTEST_TRUE@PROGRAM_TESTS = run_unittests initializer_unittests_1 +@HAVE_GTEST_TRUE@run_unittests_SOURCES = run_unittests.cc \ +@HAVE_GTEST_TRUE@ log_formatter_unittest.cc \ +@HAVE_GTEST_TRUE@ logger_level_impl_unittest.cc \ +@HAVE_GTEST_TRUE@ logger_level_unittest.cc \ +@HAVE_GTEST_TRUE@ logger_manager_unittest.cc \ +@HAVE_GTEST_TRUE@ logger_name_unittest.cc \ +@HAVE_GTEST_TRUE@ logger_support_unittest.cc logger_unittest.cc \ +@HAVE_GTEST_TRUE@ logger_specification_unittest.cc \ +@HAVE_GTEST_TRUE@ message_dictionary_unittest.cc \ +@HAVE_GTEST_TRUE@ message_reader_unittest.cc \ +@HAVE_GTEST_TRUE@ output_option_unittest.cc \ +@HAVE_GTEST_TRUE@ buffer_appender_unittest.cc \ +@HAVE_GTEST_TRUE@ log_test_messages.cc log_test_messages.h +@HAVE_GTEST_TRUE@run_unittests_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@run_unittests_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@run_unittests_LDADD = $(AM_LDADD) +@HAVE_GTEST_TRUE@run_unittests_LDFLAGS = $(AM_LDFLAGS) +@HAVE_GTEST_TRUE@initializer_unittests_1_SOURCES = \ +@HAVE_GTEST_TRUE@ run_initializer_unittests.cc \ +@HAVE_GTEST_TRUE@ message_initializer_1_unittest.cc \ +@HAVE_GTEST_TRUE@ message_initializer_1a_unittest.cc +@HAVE_GTEST_TRUE@initializer_unittests_1_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@initializer_unittests_1_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@initializer_unittests_1_LDADD = $(AM_LDADD) +@HAVE_GTEST_TRUE@initializer_unittests_1_LDFLAGS = $(AM_LDFLAGS) + +# Run shell tests on "make check". +@HAVE_GTEST_TRUE@check_SCRIPTS = $(SHTESTS) + +# Don't install shell tests. +noinst_SCRIPTS = $(SHTESTS) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/log/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/log/tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +buffer_logger_test.sh: $(top_builddir)/config.status $(srcdir)/buffer_logger_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +console_test.sh: $(top_builddir)/config.status $(srcdir)/console_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +destination_test.sh: $(top_builddir)/config.status $(srcdir)/destination_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +init_logger_test.sh: $(top_builddir)/config.status $(srcdir)/init_logger_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +local_file_test.sh: $(top_builddir)/config.status $(srcdir)/local_file_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +logger_lock_test.sh: $(top_builddir)/config.status $(srcdir)/logger_lock_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +severity_test.sh: $(top_builddir)/config.status $(srcdir)/severity_test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tempdir.h: $(top_builddir)/config.status $(srcdir)/tempdir.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +buffer_logger_test$(EXEEXT): $(buffer_logger_test_OBJECTS) $(buffer_logger_test_DEPENDENCIES) $(EXTRA_buffer_logger_test_DEPENDENCIES) + @rm -f buffer_logger_test$(EXEEXT) + $(AM_V_CXXLD)$(buffer_logger_test_LINK) $(buffer_logger_test_OBJECTS) $(buffer_logger_test_LDADD) $(LIBS) + +init_logger_test$(EXEEXT): $(init_logger_test_OBJECTS) $(init_logger_test_DEPENDENCIES) $(EXTRA_init_logger_test_DEPENDENCIES) + @rm -f init_logger_test$(EXEEXT) + $(AM_V_CXXLD)$(init_logger_test_LINK) $(init_logger_test_OBJECTS) $(init_logger_test_LDADD) $(LIBS) + +initializer_unittests_1$(EXEEXT): $(initializer_unittests_1_OBJECTS) $(initializer_unittests_1_DEPENDENCIES) $(EXTRA_initializer_unittests_1_DEPENDENCIES) + @rm -f initializer_unittests_1$(EXEEXT) + $(AM_V_CXXLD)$(initializer_unittests_1_LINK) $(initializer_unittests_1_OBJECTS) $(initializer_unittests_1_LDADD) $(LIBS) + +logger_example$(EXEEXT): $(logger_example_OBJECTS) $(logger_example_DEPENDENCIES) $(EXTRA_logger_example_DEPENDENCIES) + @rm -f logger_example$(EXEEXT) + $(AM_V_CXXLD)$(logger_example_LINK) $(logger_example_OBJECTS) $(logger_example_LDADD) $(LIBS) + +logger_lock_test$(EXEEXT): $(logger_lock_test_OBJECTS) $(logger_lock_test_DEPENDENCIES) $(EXTRA_logger_lock_test_DEPENDENCIES) + @rm -f logger_lock_test$(EXEEXT) + $(AM_V_CXXLD)$(logger_lock_test_LINK) $(logger_lock_test_OBJECTS) $(logger_lock_test_LDADD) $(LIBS) + +run_unittests$(EXEEXT): $(run_unittests_OBJECTS) $(run_unittests_DEPENDENCIES) $(EXTRA_run_unittests_DEPENDENCIES) + @rm -f run_unittests$(EXEEXT) + $(AM_V_CXXLD)$(run_unittests_LINK) $(run_unittests_OBJECTS) $(run_unittests_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer_logger_test-buffer_logger_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_logger_test-init_logger_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger_example-logger_example.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger_lock_test-log_test_messages.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger_lock_test-logger_lock_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-buffer_appender_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-log_formatter_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-log_test_messages.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_level_impl_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_level_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_manager_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_name_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_specification_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_support_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-logger_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-message_dictionary_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-message_reader_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-output_option_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-run_unittests.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +buffer_logger_test-buffer_logger_test.o: buffer_logger_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(buffer_logger_test_CPPFLAGS) $(CPPFLAGS) $(buffer_logger_test_CXXFLAGS) $(CXXFLAGS) -MT buffer_logger_test-buffer_logger_test.o -MD -MP -MF $(DEPDIR)/buffer_logger_test-buffer_logger_test.Tpo -c -o buffer_logger_test-buffer_logger_test.o `test -f 'buffer_logger_test.cc' || echo '$(srcdir)/'`buffer_logger_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer_logger_test-buffer_logger_test.Tpo $(DEPDIR)/buffer_logger_test-buffer_logger_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_logger_test.cc' object='buffer_logger_test-buffer_logger_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(buffer_logger_test_CPPFLAGS) $(CPPFLAGS) $(buffer_logger_test_CXXFLAGS) $(CXXFLAGS) -c -o buffer_logger_test-buffer_logger_test.o `test -f 'buffer_logger_test.cc' || echo '$(srcdir)/'`buffer_logger_test.cc + +buffer_logger_test-buffer_logger_test.obj: buffer_logger_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(buffer_logger_test_CPPFLAGS) $(CPPFLAGS) $(buffer_logger_test_CXXFLAGS) $(CXXFLAGS) -MT buffer_logger_test-buffer_logger_test.obj -MD -MP -MF $(DEPDIR)/buffer_logger_test-buffer_logger_test.Tpo -c -o buffer_logger_test-buffer_logger_test.obj `if test -f 'buffer_logger_test.cc'; then $(CYGPATH_W) 'buffer_logger_test.cc'; else $(CYGPATH_W) '$(srcdir)/buffer_logger_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer_logger_test-buffer_logger_test.Tpo $(DEPDIR)/buffer_logger_test-buffer_logger_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_logger_test.cc' object='buffer_logger_test-buffer_logger_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(buffer_logger_test_CPPFLAGS) $(CPPFLAGS) $(buffer_logger_test_CXXFLAGS) $(CXXFLAGS) -c -o buffer_logger_test-buffer_logger_test.obj `if test -f 'buffer_logger_test.cc'; then $(CYGPATH_W) 'buffer_logger_test.cc'; else $(CYGPATH_W) '$(srcdir)/buffer_logger_test.cc'; fi` + +init_logger_test-init_logger_test.o: init_logger_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(init_logger_test_CPPFLAGS) $(CPPFLAGS) $(init_logger_test_CXXFLAGS) $(CXXFLAGS) -MT init_logger_test-init_logger_test.o -MD -MP -MF $(DEPDIR)/init_logger_test-init_logger_test.Tpo -c -o init_logger_test-init_logger_test.o `test -f 'init_logger_test.cc' || echo '$(srcdir)/'`init_logger_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/init_logger_test-init_logger_test.Tpo $(DEPDIR)/init_logger_test-init_logger_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='init_logger_test.cc' object='init_logger_test-init_logger_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(init_logger_test_CPPFLAGS) $(CPPFLAGS) $(init_logger_test_CXXFLAGS) $(CXXFLAGS) -c -o init_logger_test-init_logger_test.o `test -f 'init_logger_test.cc' || echo '$(srcdir)/'`init_logger_test.cc + +init_logger_test-init_logger_test.obj: init_logger_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(init_logger_test_CPPFLAGS) $(CPPFLAGS) $(init_logger_test_CXXFLAGS) $(CXXFLAGS) -MT init_logger_test-init_logger_test.obj -MD -MP -MF $(DEPDIR)/init_logger_test-init_logger_test.Tpo -c -o init_logger_test-init_logger_test.obj `if test -f 'init_logger_test.cc'; then $(CYGPATH_W) 'init_logger_test.cc'; else $(CYGPATH_W) '$(srcdir)/init_logger_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/init_logger_test-init_logger_test.Tpo $(DEPDIR)/init_logger_test-init_logger_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='init_logger_test.cc' object='init_logger_test-init_logger_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(init_logger_test_CPPFLAGS) $(CPPFLAGS) $(init_logger_test_CXXFLAGS) $(CXXFLAGS) -c -o init_logger_test-init_logger_test.obj `if test -f 'init_logger_test.cc'; then $(CYGPATH_W) 'init_logger_test.cc'; else $(CYGPATH_W) '$(srcdir)/init_logger_test.cc'; fi` + +initializer_unittests_1-run_initializer_unittests.o: run_initializer_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -MT initializer_unittests_1-run_initializer_unittests.o -MD -MP -MF $(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Tpo -c -o initializer_unittests_1-run_initializer_unittests.o `test -f 'run_initializer_unittests.cc' || echo '$(srcdir)/'`run_initializer_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Tpo $(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_initializer_unittests.cc' object='initializer_unittests_1-run_initializer_unittests.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -c -o initializer_unittests_1-run_initializer_unittests.o `test -f 'run_initializer_unittests.cc' || echo '$(srcdir)/'`run_initializer_unittests.cc + +initializer_unittests_1-run_initializer_unittests.obj: run_initializer_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -MT initializer_unittests_1-run_initializer_unittests.obj -MD -MP -MF $(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Tpo -c -o initializer_unittests_1-run_initializer_unittests.obj `if test -f 'run_initializer_unittests.cc'; then $(CYGPATH_W) 'run_initializer_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_initializer_unittests.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Tpo $(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_initializer_unittests.cc' object='initializer_unittests_1-run_initializer_unittests.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -c -o initializer_unittests_1-run_initializer_unittests.obj `if test -f 'run_initializer_unittests.cc'; then $(CYGPATH_W) 'run_initializer_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_initializer_unittests.cc'; fi` + +initializer_unittests_1-message_initializer_1_unittest.o: message_initializer_1_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -MT initializer_unittests_1-message_initializer_1_unittest.o -MD -MP -MF $(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Tpo -c -o initializer_unittests_1-message_initializer_1_unittest.o `test -f 'message_initializer_1_unittest.cc' || echo '$(srcdir)/'`message_initializer_1_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Tpo $(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_initializer_1_unittest.cc' object='initializer_unittests_1-message_initializer_1_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -c -o initializer_unittests_1-message_initializer_1_unittest.o `test -f 'message_initializer_1_unittest.cc' || echo '$(srcdir)/'`message_initializer_1_unittest.cc + +initializer_unittests_1-message_initializer_1_unittest.obj: message_initializer_1_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -MT initializer_unittests_1-message_initializer_1_unittest.obj -MD -MP -MF $(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Tpo -c -o initializer_unittests_1-message_initializer_1_unittest.obj `if test -f 'message_initializer_1_unittest.cc'; then $(CYGPATH_W) 'message_initializer_1_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_initializer_1_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Tpo $(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_initializer_1_unittest.cc' object='initializer_unittests_1-message_initializer_1_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -c -o initializer_unittests_1-message_initializer_1_unittest.obj `if test -f 'message_initializer_1_unittest.cc'; then $(CYGPATH_W) 'message_initializer_1_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_initializer_1_unittest.cc'; fi` + +initializer_unittests_1-message_initializer_1a_unittest.o: message_initializer_1a_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -MT initializer_unittests_1-message_initializer_1a_unittest.o -MD -MP -MF $(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Tpo -c -o initializer_unittests_1-message_initializer_1a_unittest.o `test -f 'message_initializer_1a_unittest.cc' || echo '$(srcdir)/'`message_initializer_1a_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Tpo $(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_initializer_1a_unittest.cc' object='initializer_unittests_1-message_initializer_1a_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -c -o initializer_unittests_1-message_initializer_1a_unittest.o `test -f 'message_initializer_1a_unittest.cc' || echo '$(srcdir)/'`message_initializer_1a_unittest.cc + +initializer_unittests_1-message_initializer_1a_unittest.obj: message_initializer_1a_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -MT initializer_unittests_1-message_initializer_1a_unittest.obj -MD -MP -MF $(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Tpo -c -o initializer_unittests_1-message_initializer_1a_unittest.obj `if test -f 'message_initializer_1a_unittest.cc'; then $(CYGPATH_W) 'message_initializer_1a_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_initializer_1a_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Tpo $(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_initializer_1a_unittest.cc' object='initializer_unittests_1-message_initializer_1a_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(initializer_unittests_1_CPPFLAGS) $(CPPFLAGS) $(initializer_unittests_1_CXXFLAGS) $(CXXFLAGS) -c -o initializer_unittests_1-message_initializer_1a_unittest.obj `if test -f 'message_initializer_1a_unittest.cc'; then $(CYGPATH_W) 'message_initializer_1a_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_initializer_1a_unittest.cc'; fi` + +logger_example-logger_example.o: logger_example.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_example_CPPFLAGS) $(CPPFLAGS) $(logger_example_CXXFLAGS) $(CXXFLAGS) -MT logger_example-logger_example.o -MD -MP -MF $(DEPDIR)/logger_example-logger_example.Tpo -c -o logger_example-logger_example.o `test -f 'logger_example.cc' || echo '$(srcdir)/'`logger_example.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logger_example-logger_example.Tpo $(DEPDIR)/logger_example-logger_example.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_example.cc' object='logger_example-logger_example.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_example_CPPFLAGS) $(CPPFLAGS) $(logger_example_CXXFLAGS) $(CXXFLAGS) -c -o logger_example-logger_example.o `test -f 'logger_example.cc' || echo '$(srcdir)/'`logger_example.cc + +logger_example-logger_example.obj: logger_example.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_example_CPPFLAGS) $(CPPFLAGS) $(logger_example_CXXFLAGS) $(CXXFLAGS) -MT logger_example-logger_example.obj -MD -MP -MF $(DEPDIR)/logger_example-logger_example.Tpo -c -o logger_example-logger_example.obj `if test -f 'logger_example.cc'; then $(CYGPATH_W) 'logger_example.cc'; else $(CYGPATH_W) '$(srcdir)/logger_example.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logger_example-logger_example.Tpo $(DEPDIR)/logger_example-logger_example.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_example.cc' object='logger_example-logger_example.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_example_CPPFLAGS) $(CPPFLAGS) $(logger_example_CXXFLAGS) $(CXXFLAGS) -c -o logger_example-logger_example.obj `if test -f 'logger_example.cc'; then $(CYGPATH_W) 'logger_example.cc'; else $(CYGPATH_W) '$(srcdir)/logger_example.cc'; fi` + +logger_lock_test-logger_lock_test.o: logger_lock_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -MT logger_lock_test-logger_lock_test.o -MD -MP -MF $(DEPDIR)/logger_lock_test-logger_lock_test.Tpo -c -o logger_lock_test-logger_lock_test.o `test -f 'logger_lock_test.cc' || echo '$(srcdir)/'`logger_lock_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logger_lock_test-logger_lock_test.Tpo $(DEPDIR)/logger_lock_test-logger_lock_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_lock_test.cc' object='logger_lock_test-logger_lock_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -c -o logger_lock_test-logger_lock_test.o `test -f 'logger_lock_test.cc' || echo '$(srcdir)/'`logger_lock_test.cc + +logger_lock_test-logger_lock_test.obj: logger_lock_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -MT logger_lock_test-logger_lock_test.obj -MD -MP -MF $(DEPDIR)/logger_lock_test-logger_lock_test.Tpo -c -o logger_lock_test-logger_lock_test.obj `if test -f 'logger_lock_test.cc'; then $(CYGPATH_W) 'logger_lock_test.cc'; else $(CYGPATH_W) '$(srcdir)/logger_lock_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logger_lock_test-logger_lock_test.Tpo $(DEPDIR)/logger_lock_test-logger_lock_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_lock_test.cc' object='logger_lock_test-logger_lock_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -c -o logger_lock_test-logger_lock_test.obj `if test -f 'logger_lock_test.cc'; then $(CYGPATH_W) 'logger_lock_test.cc'; else $(CYGPATH_W) '$(srcdir)/logger_lock_test.cc'; fi` + +logger_lock_test-log_test_messages.o: log_test_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -MT logger_lock_test-log_test_messages.o -MD -MP -MF $(DEPDIR)/logger_lock_test-log_test_messages.Tpo -c -o logger_lock_test-log_test_messages.o `test -f 'log_test_messages.cc' || echo '$(srcdir)/'`log_test_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logger_lock_test-log_test_messages.Tpo $(DEPDIR)/logger_lock_test-log_test_messages.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_test_messages.cc' object='logger_lock_test-log_test_messages.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -c -o logger_lock_test-log_test_messages.o `test -f 'log_test_messages.cc' || echo '$(srcdir)/'`log_test_messages.cc + +logger_lock_test-log_test_messages.obj: log_test_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -MT logger_lock_test-log_test_messages.obj -MD -MP -MF $(DEPDIR)/logger_lock_test-log_test_messages.Tpo -c -o logger_lock_test-log_test_messages.obj `if test -f 'log_test_messages.cc'; then $(CYGPATH_W) 'log_test_messages.cc'; else $(CYGPATH_W) '$(srcdir)/log_test_messages.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logger_lock_test-log_test_messages.Tpo $(DEPDIR)/logger_lock_test-log_test_messages.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_test_messages.cc' object='logger_lock_test-log_test_messages.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logger_lock_test_CPPFLAGS) $(CPPFLAGS) $(logger_lock_test_CXXFLAGS) $(CXXFLAGS) -c -o logger_lock_test-log_test_messages.obj `if test -f 'log_test_messages.cc'; then $(CYGPATH_W) 'log_test_messages.cc'; else $(CYGPATH_W) '$(srcdir)/log_test_messages.cc'; fi` + +run_unittests-run_unittests.o: run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.o -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_unittests-run_unittests.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc + +run_unittests-run_unittests.obj: run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.obj -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_unittests-run_unittests.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi` + +run_unittests-log_formatter_unittest.o: log_formatter_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-log_formatter_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-log_formatter_unittest.Tpo -c -o run_unittests-log_formatter_unittest.o `test -f 'log_formatter_unittest.cc' || echo '$(srcdir)/'`log_formatter_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-log_formatter_unittest.Tpo $(DEPDIR)/run_unittests-log_formatter_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_formatter_unittest.cc' object='run_unittests-log_formatter_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-log_formatter_unittest.o `test -f 'log_formatter_unittest.cc' || echo '$(srcdir)/'`log_formatter_unittest.cc + +run_unittests-log_formatter_unittest.obj: log_formatter_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-log_formatter_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-log_formatter_unittest.Tpo -c -o run_unittests-log_formatter_unittest.obj `if test -f 'log_formatter_unittest.cc'; then $(CYGPATH_W) 'log_formatter_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/log_formatter_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-log_formatter_unittest.Tpo $(DEPDIR)/run_unittests-log_formatter_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_formatter_unittest.cc' object='run_unittests-log_formatter_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-log_formatter_unittest.obj `if test -f 'log_formatter_unittest.cc'; then $(CYGPATH_W) 'log_formatter_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/log_formatter_unittest.cc'; fi` + +run_unittests-logger_level_impl_unittest.o: logger_level_impl_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_level_impl_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_level_impl_unittest.Tpo -c -o run_unittests-logger_level_impl_unittest.o `test -f 'logger_level_impl_unittest.cc' || echo '$(srcdir)/'`logger_level_impl_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_level_impl_unittest.Tpo $(DEPDIR)/run_unittests-logger_level_impl_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_level_impl_unittest.cc' object='run_unittests-logger_level_impl_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_level_impl_unittest.o `test -f 'logger_level_impl_unittest.cc' || echo '$(srcdir)/'`logger_level_impl_unittest.cc + +run_unittests-logger_level_impl_unittest.obj: logger_level_impl_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_level_impl_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_level_impl_unittest.Tpo -c -o run_unittests-logger_level_impl_unittest.obj `if test -f 'logger_level_impl_unittest.cc'; then $(CYGPATH_W) 'logger_level_impl_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_level_impl_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_level_impl_unittest.Tpo $(DEPDIR)/run_unittests-logger_level_impl_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_level_impl_unittest.cc' object='run_unittests-logger_level_impl_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_level_impl_unittest.obj `if test -f 'logger_level_impl_unittest.cc'; then $(CYGPATH_W) 'logger_level_impl_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_level_impl_unittest.cc'; fi` + +run_unittests-logger_level_unittest.o: logger_level_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_level_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_level_unittest.Tpo -c -o run_unittests-logger_level_unittest.o `test -f 'logger_level_unittest.cc' || echo '$(srcdir)/'`logger_level_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_level_unittest.Tpo $(DEPDIR)/run_unittests-logger_level_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_level_unittest.cc' object='run_unittests-logger_level_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_level_unittest.o `test -f 'logger_level_unittest.cc' || echo '$(srcdir)/'`logger_level_unittest.cc + +run_unittests-logger_level_unittest.obj: logger_level_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_level_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_level_unittest.Tpo -c -o run_unittests-logger_level_unittest.obj `if test -f 'logger_level_unittest.cc'; then $(CYGPATH_W) 'logger_level_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_level_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_level_unittest.Tpo $(DEPDIR)/run_unittests-logger_level_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_level_unittest.cc' object='run_unittests-logger_level_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_level_unittest.obj `if test -f 'logger_level_unittest.cc'; then $(CYGPATH_W) 'logger_level_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_level_unittest.cc'; fi` + +run_unittests-logger_manager_unittest.o: logger_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_manager_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_manager_unittest.Tpo -c -o run_unittests-logger_manager_unittest.o `test -f 'logger_manager_unittest.cc' || echo '$(srcdir)/'`logger_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_manager_unittest.Tpo $(DEPDIR)/run_unittests-logger_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_manager_unittest.cc' object='run_unittests-logger_manager_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_manager_unittest.o `test -f 'logger_manager_unittest.cc' || echo '$(srcdir)/'`logger_manager_unittest.cc + +run_unittests-logger_manager_unittest.obj: logger_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_manager_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_manager_unittest.Tpo -c -o run_unittests-logger_manager_unittest.obj `if test -f 'logger_manager_unittest.cc'; then $(CYGPATH_W) 'logger_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_manager_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_manager_unittest.Tpo $(DEPDIR)/run_unittests-logger_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_manager_unittest.cc' object='run_unittests-logger_manager_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_manager_unittest.obj `if test -f 'logger_manager_unittest.cc'; then $(CYGPATH_W) 'logger_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_manager_unittest.cc'; fi` + +run_unittests-logger_name_unittest.o: logger_name_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_name_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_name_unittest.Tpo -c -o run_unittests-logger_name_unittest.o `test -f 'logger_name_unittest.cc' || echo '$(srcdir)/'`logger_name_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_name_unittest.Tpo $(DEPDIR)/run_unittests-logger_name_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_name_unittest.cc' object='run_unittests-logger_name_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_name_unittest.o `test -f 'logger_name_unittest.cc' || echo '$(srcdir)/'`logger_name_unittest.cc + +run_unittests-logger_name_unittest.obj: logger_name_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_name_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_name_unittest.Tpo -c -o run_unittests-logger_name_unittest.obj `if test -f 'logger_name_unittest.cc'; then $(CYGPATH_W) 'logger_name_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_name_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_name_unittest.Tpo $(DEPDIR)/run_unittests-logger_name_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_name_unittest.cc' object='run_unittests-logger_name_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_name_unittest.obj `if test -f 'logger_name_unittest.cc'; then $(CYGPATH_W) 'logger_name_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_name_unittest.cc'; fi` + +run_unittests-logger_support_unittest.o: logger_support_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_support_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_support_unittest.Tpo -c -o run_unittests-logger_support_unittest.o `test -f 'logger_support_unittest.cc' || echo '$(srcdir)/'`logger_support_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_support_unittest.Tpo $(DEPDIR)/run_unittests-logger_support_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_support_unittest.cc' object='run_unittests-logger_support_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_support_unittest.o `test -f 'logger_support_unittest.cc' || echo '$(srcdir)/'`logger_support_unittest.cc + +run_unittests-logger_support_unittest.obj: logger_support_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_support_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_support_unittest.Tpo -c -o run_unittests-logger_support_unittest.obj `if test -f 'logger_support_unittest.cc'; then $(CYGPATH_W) 'logger_support_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_support_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_support_unittest.Tpo $(DEPDIR)/run_unittests-logger_support_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_support_unittest.cc' object='run_unittests-logger_support_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_support_unittest.obj `if test -f 'logger_support_unittest.cc'; then $(CYGPATH_W) 'logger_support_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_support_unittest.cc'; fi` + +run_unittests-logger_unittest.o: logger_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_unittest.Tpo -c -o run_unittests-logger_unittest.o `test -f 'logger_unittest.cc' || echo '$(srcdir)/'`logger_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_unittest.Tpo $(DEPDIR)/run_unittests-logger_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_unittest.cc' object='run_unittests-logger_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_unittest.o `test -f 'logger_unittest.cc' || echo '$(srcdir)/'`logger_unittest.cc + +run_unittests-logger_unittest.obj: logger_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_unittest.Tpo -c -o run_unittests-logger_unittest.obj `if test -f 'logger_unittest.cc'; then $(CYGPATH_W) 'logger_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_unittest.Tpo $(DEPDIR)/run_unittests-logger_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_unittest.cc' object='run_unittests-logger_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_unittest.obj `if test -f 'logger_unittest.cc'; then $(CYGPATH_W) 'logger_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_unittest.cc'; fi` + +run_unittests-logger_specification_unittest.o: logger_specification_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_specification_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-logger_specification_unittest.Tpo -c -o run_unittests-logger_specification_unittest.o `test -f 'logger_specification_unittest.cc' || echo '$(srcdir)/'`logger_specification_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_specification_unittest.Tpo $(DEPDIR)/run_unittests-logger_specification_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_specification_unittest.cc' object='run_unittests-logger_specification_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_specification_unittest.o `test -f 'logger_specification_unittest.cc' || echo '$(srcdir)/'`logger_specification_unittest.cc + +run_unittests-logger_specification_unittest.obj: logger_specification_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-logger_specification_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-logger_specification_unittest.Tpo -c -o run_unittests-logger_specification_unittest.obj `if test -f 'logger_specification_unittest.cc'; then $(CYGPATH_W) 'logger_specification_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_specification_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-logger_specification_unittest.Tpo $(DEPDIR)/run_unittests-logger_specification_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='logger_specification_unittest.cc' object='run_unittests-logger_specification_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-logger_specification_unittest.obj `if test -f 'logger_specification_unittest.cc'; then $(CYGPATH_W) 'logger_specification_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/logger_specification_unittest.cc'; fi` + +run_unittests-message_dictionary_unittest.o: message_dictionary_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-message_dictionary_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-message_dictionary_unittest.Tpo -c -o run_unittests-message_dictionary_unittest.o `test -f 'message_dictionary_unittest.cc' || echo '$(srcdir)/'`message_dictionary_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-message_dictionary_unittest.Tpo $(DEPDIR)/run_unittests-message_dictionary_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_dictionary_unittest.cc' object='run_unittests-message_dictionary_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-message_dictionary_unittest.o `test -f 'message_dictionary_unittest.cc' || echo '$(srcdir)/'`message_dictionary_unittest.cc + +run_unittests-message_dictionary_unittest.obj: message_dictionary_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-message_dictionary_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-message_dictionary_unittest.Tpo -c -o run_unittests-message_dictionary_unittest.obj `if test -f 'message_dictionary_unittest.cc'; then $(CYGPATH_W) 'message_dictionary_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_dictionary_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-message_dictionary_unittest.Tpo $(DEPDIR)/run_unittests-message_dictionary_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_dictionary_unittest.cc' object='run_unittests-message_dictionary_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-message_dictionary_unittest.obj `if test -f 'message_dictionary_unittest.cc'; then $(CYGPATH_W) 'message_dictionary_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_dictionary_unittest.cc'; fi` + +run_unittests-message_reader_unittest.o: message_reader_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-message_reader_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-message_reader_unittest.Tpo -c -o run_unittests-message_reader_unittest.o `test -f 'message_reader_unittest.cc' || echo '$(srcdir)/'`message_reader_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-message_reader_unittest.Tpo $(DEPDIR)/run_unittests-message_reader_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_reader_unittest.cc' object='run_unittests-message_reader_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-message_reader_unittest.o `test -f 'message_reader_unittest.cc' || echo '$(srcdir)/'`message_reader_unittest.cc + +run_unittests-message_reader_unittest.obj: message_reader_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-message_reader_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-message_reader_unittest.Tpo -c -o run_unittests-message_reader_unittest.obj `if test -f 'message_reader_unittest.cc'; then $(CYGPATH_W) 'message_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_reader_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-message_reader_unittest.Tpo $(DEPDIR)/run_unittests-message_reader_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_reader_unittest.cc' object='run_unittests-message_reader_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-message_reader_unittest.obj `if test -f 'message_reader_unittest.cc'; then $(CYGPATH_W) 'message_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_reader_unittest.cc'; fi` + +run_unittests-output_option_unittest.o: output_option_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-output_option_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-output_option_unittest.Tpo -c -o run_unittests-output_option_unittest.o `test -f 'output_option_unittest.cc' || echo '$(srcdir)/'`output_option_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-output_option_unittest.Tpo $(DEPDIR)/run_unittests-output_option_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='output_option_unittest.cc' object='run_unittests-output_option_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-output_option_unittest.o `test -f 'output_option_unittest.cc' || echo '$(srcdir)/'`output_option_unittest.cc + +run_unittests-output_option_unittest.obj: output_option_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-output_option_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-output_option_unittest.Tpo -c -o run_unittests-output_option_unittest.obj `if test -f 'output_option_unittest.cc'; then $(CYGPATH_W) 'output_option_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/output_option_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-output_option_unittest.Tpo $(DEPDIR)/run_unittests-output_option_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='output_option_unittest.cc' object='run_unittests-output_option_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-output_option_unittest.obj `if test -f 'output_option_unittest.cc'; then $(CYGPATH_W) 'output_option_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/output_option_unittest.cc'; fi` + +run_unittests-buffer_appender_unittest.o: buffer_appender_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-buffer_appender_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-buffer_appender_unittest.Tpo -c -o run_unittests-buffer_appender_unittest.o `test -f 'buffer_appender_unittest.cc' || echo '$(srcdir)/'`buffer_appender_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-buffer_appender_unittest.Tpo $(DEPDIR)/run_unittests-buffer_appender_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_appender_unittest.cc' object='run_unittests-buffer_appender_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-buffer_appender_unittest.o `test -f 'buffer_appender_unittest.cc' || echo '$(srcdir)/'`buffer_appender_unittest.cc + +run_unittests-buffer_appender_unittest.obj: buffer_appender_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-buffer_appender_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-buffer_appender_unittest.Tpo -c -o run_unittests-buffer_appender_unittest.obj `if test -f 'buffer_appender_unittest.cc'; then $(CYGPATH_W) 'buffer_appender_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/buffer_appender_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-buffer_appender_unittest.Tpo $(DEPDIR)/run_unittests-buffer_appender_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_appender_unittest.cc' object='run_unittests-buffer_appender_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-buffer_appender_unittest.obj `if test -f 'buffer_appender_unittest.cc'; then $(CYGPATH_W) 'buffer_appender_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/buffer_appender_unittest.cc'; fi` + +run_unittests-log_test_messages.o: log_test_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-log_test_messages.o -MD -MP -MF $(DEPDIR)/run_unittests-log_test_messages.Tpo -c -o run_unittests-log_test_messages.o `test -f 'log_test_messages.cc' || echo '$(srcdir)/'`log_test_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-log_test_messages.Tpo $(DEPDIR)/run_unittests-log_test_messages.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_test_messages.cc' object='run_unittests-log_test_messages.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-log_test_messages.o `test -f 'log_test_messages.cc' || echo '$(srcdir)/'`log_test_messages.cc + +run_unittests-log_test_messages.obj: log_test_messages.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-log_test_messages.obj -MD -MP -MF $(DEPDIR)/run_unittests-log_test_messages.Tpo -c -o run_unittests-log_test_messages.obj `if test -f 'log_test_messages.cc'; then $(CYGPATH_W) 'log_test_messages.cc'; else $(CYGPATH_W) '$(srcdir)/log_test_messages.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-log_test_messages.Tpo $(DEPDIR)/run_unittests-log_test_messages.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='log_test_messages.cc' object='run_unittests-log_test_messages.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-log_test_messages.obj `if test -f 'log_test_messages.cc'; then $(CYGPATH_W) 'log_test_messages.cc'; else $(CYGPATH_W) '$(srcdir)/log_test_messages.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-recursive +all-am: Makefile $(PROGRAMS) $(SCRIPTS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/buffer_logger_test-buffer_logger_test.Po + -rm -f ./$(DEPDIR)/init_logger_test-init_logger_test.Po + -rm -f ./$(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Po + -rm -f ./$(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Po + -rm -f ./$(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Po + -rm -f ./$(DEPDIR)/logger_example-logger_example.Po + -rm -f ./$(DEPDIR)/logger_lock_test-log_test_messages.Po + -rm -f ./$(DEPDIR)/logger_lock_test-logger_lock_test.Po + -rm -f ./$(DEPDIR)/run_unittests-buffer_appender_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-log_formatter_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-log_test_messages.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_level_impl_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_level_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_name_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_specification_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_support_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-message_dictionary_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-message_reader_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-output_option_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/buffer_logger_test-buffer_logger_test.Po + -rm -f ./$(DEPDIR)/init_logger_test-init_logger_test.Po + -rm -f ./$(DEPDIR)/initializer_unittests_1-message_initializer_1_unittest.Po + -rm -f ./$(DEPDIR)/initializer_unittests_1-message_initializer_1a_unittest.Po + -rm -f ./$(DEPDIR)/initializer_unittests_1-run_initializer_unittests.Po + -rm -f ./$(DEPDIR)/logger_example-logger_example.Po + -rm -f ./$(DEPDIR)/logger_lock_test-log_test_messages.Po + -rm -f ./$(DEPDIR)/logger_lock_test-logger_lock_test.Po + -rm -f ./$(DEPDIR)/run_unittests-buffer_appender_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-log_formatter_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-log_test_messages.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_level_impl_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_level_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_name_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_specification_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_support_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-logger_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-message_dictionary_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-message_reader_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-output_option_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) check-am install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-TESTS check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-local mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# If we want to get rid of all generated messages files, we need to use +# make maintainer-clean. The proper way to introduce custom commands for +# that operation is to define maintainer-clean-local target. However, +# make maintainer-clean also removes Makefile, so running configure script +# is required. To make it easy to rebuild messages without going through +# reconfigure, a new target messages-clean has been added. +maintainer-clean-local: + rm -f log_test_messages.h log_test_messages.cc + +# To regenerate messages files, one can do: +# +# make messages-clean +# make messages +# +# This is needed only when a .mes file is modified. +messages-clean: maintainer-clean-local + +# Define rule to build logging source files from message file +@GENERATE_MESSAGES_TRUE@messages: log_test_messages.h log_test_messages.cc +@GENERATE_MESSAGES_TRUE@ @echo Message files regenerated + +@GENERATE_MESSAGES_TRUE@log_test_messages.h log_test_messages.cc: log_test_messages.mes +@GENERATE_MESSAGES_TRUE@ $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/lib/log/tests/log_test_messages.mes + +@GENERATE_MESSAGES_FALSE@messages log_test_messages.h log_test_messages.cc: +@GENERATE_MESSAGES_FALSE@ @echo Messages generation disabled. Configure with --enable-generate-messages to enable it. + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib/log/tests/buffer_appender_unittest.cc b/src/lib/log/tests/buffer_appender_unittest.cc new file mode 100644 index 0000000..f52d833 --- /dev/null +++ b/src/lib/log/tests/buffer_appender_unittest.cc @@ -0,0 +1,138 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> +#include <gtest/gtest.h> + +#include <log/macros.h> +#include <log/logger_support.h> +#include <log/log_messages.h> +#include <log/buffer_appender_impl.h> + +#include <log4cplus/loggingmacros.h> +#include <log4cplus/logger.h> +#include <log4cplus/nullappender.h> +#include <log4cplus/spi/loggingevent.h> + +using namespace isc::log; +using namespace isc::log::internal; + +namespace isc { +namespace log { + +/// \brief Specialized test class +/// +/// In order to test append() somewhat directly, this +/// class implements one more method (addEvent) +class TestBufferAppender : public BufferAppender { +public: + void addEvent(const log4cplus::spi::InternalLoggingEvent& event) { + append(event); + } +}; + +class BufferAppenderTest : public ::testing::Test { +protected: + BufferAppenderTest() : buffer_appender1(new TestBufferAppender()), + appender1(buffer_appender1), + buffer_appender2(new TestBufferAppender()), + appender2(buffer_appender2), + logger(log4cplus::Logger::getInstance("buffer")) + { + logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL); + } + + ~BufferAppenderTest() { + // If any log messages are left, we don't care, get rid of them, + // by flushing them to a null appender + // Given the 'messages should not get lost' approach of the logging + // system, not flushing them to a null appender would cause them + // to be dumped to stdout as the test is destroyed, making + // unnecessarily messy test output. + log4cplus::SharedAppenderPtr null_appender( + new log4cplus::NullAppender()); + logger.removeAllAppenders(); + logger.addAppender(null_appender); + buffer_appender1->flush(); + buffer_appender2->flush(); + } + + TestBufferAppender* buffer_appender1; + log4cplus::SharedAppenderPtr appender1; + TestBufferAppender* buffer_appender2; + log4cplus::SharedAppenderPtr appender2; + log4cplus::Logger logger; +}; + +// Test that log events are indeed stored, and that they are +// flushed to the new appenders of their logger +TEST_F(BufferAppenderTest, flush) { + ASSERT_EQ(0, buffer_appender1->getBufferSize()); + ASSERT_EQ(0, buffer_appender2->getBufferSize()); + + // Create a Logger, log a few messages with the first appender + logger.addAppender(appender1); + LOG4CPLUS_INFO(logger, "Foo"); + ASSERT_EQ(1, buffer_appender1->getBufferSize()); + LOG4CPLUS_INFO(logger, "Foo"); + ASSERT_EQ(2, buffer_appender1->getBufferSize()); + LOG4CPLUS_INFO(logger, "Foo"); + ASSERT_EQ(3, buffer_appender1->getBufferSize()); + + // Second buffer should still be empty + ASSERT_EQ(0, buffer_appender2->getBufferSize()); + + // Replace the appender by the second one, and call flush; + // this should cause all events to be moved to the second buffer + logger.removeAllAppenders(); + logger.addAppender(appender2); + buffer_appender1->flush(); + ASSERT_EQ(0, buffer_appender1->getBufferSize()); + ASSERT_EQ(3, buffer_appender2->getBufferSize()); +} + +// Once flushed, logging new messages with the same buffer should fail +TEST_F(BufferAppenderTest, addAfterFlush) { + logger.addAppender(appender1); + buffer_appender1->flush(); + EXPECT_THROW(LOG4CPLUS_INFO(logger, "Foo"), LogBufferAddAfterFlush); + // It should not have been added + ASSERT_EQ(0, buffer_appender1->getBufferSize()); + + // But logging should work again as long as a different buffer is used + logger.removeAllAppenders(); + logger.addAppender(appender2); + LOG4CPLUS_INFO(logger, "Foo"); + ASSERT_EQ(1, buffer_appender2->getBufferSize()); +} + +TEST_F(BufferAppenderTest, addDirectly) { + // A few direct calls + log4cplus::spi::InternalLoggingEvent event("buffer", + log4cplus::INFO_LOG_LEVEL, + "Bar", "file", 123); + buffer_appender1->addEvent(event); + ASSERT_EQ(1, buffer_appender1->getBufferSize()); + + // Do one from a smaller scope to make sure destruction doesn't harm + { + log4cplus::spi::InternalLoggingEvent event2("buffer", + log4cplus::INFO_LOG_LEVEL, + "Bar", "file", 123); + buffer_appender1->addEvent(event2); + } + ASSERT_EQ(2, buffer_appender1->getBufferSize()); + + // And flush them to the next + logger.removeAllAppenders(); + logger.addAppender(appender2); + buffer_appender1->flush(); + ASSERT_EQ(0, buffer_appender1->getBufferSize()); + ASSERT_EQ(2, buffer_appender2->getBufferSize()); +} + +} +} diff --git a/src/lib/log/tests/buffer_logger_test.cc b/src/lib/log/tests/buffer_logger_test.cc new file mode 100644 index 0000000..956e2f1 --- /dev/null +++ b/src/lib/log/tests/buffer_logger_test.cc @@ -0,0 +1,66 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/macros.h> +#include <log/logger_support.h> +#include <log/logger_manager.h> +#include <log/log_messages.h> +#include <log/interprocess/interprocess_sync_null.h> + +using namespace isc::log; + +namespace { +void usage() { + std::cout << "Usage: buffer_logger_test [-n]" << std::endl; +} +} // end unnamed namespace + +/// \brief Test InitLogger +/// +/// A program used in testing the logger that initializes logging with +/// buffering enabled, so that initial log messages are not immediately +/// logged, but are not lost (they should be logged the moment process() +/// is called. +/// +/// If -n is given as an argument, process() is never called. In this +/// case, upon exit, all leftover log messages should be printed to +/// stdout, but without normal logging additions (such as time and +/// logger name) +int +main(int argc, char** argv) { + bool do_process = true; + int opt; + while ((opt = getopt(argc, argv, "n")) != -1) { + switch (opt) { + case 'n': + do_process = false; + break; + default: + usage(); + return (1); + } + } + + // Note, level is INFO, so DEBUG should normally not show + // up. Unless process is never called (at which point it + // will end up in the dump at the end). + initLogger("buffertest", isc::log::INFO, 0, NULL, true); + Logger logger("log"); + // No need for file interprocess locking in this test + logger.setInterprocessSync( + new isc::log::interprocess::InterprocessSyncNull("logger")); + LOG_INFO(logger, LOG_BAD_SEVERITY).arg("info"); + LOG_DEBUG(logger, 50, LOG_BAD_DESTINATION).arg("debug-50"); + LOG_INFO(logger, LOG_BAD_SEVERITY).arg("info"); + // process should cause them to be logged + if (do_process) { + LoggerManager logger_manager; + logger_manager.process(); + } + return (0); +} diff --git a/src/lib/log/tests/buffer_logger_test.sh.in b/src/lib/log/tests/buffer_logger_test.sh.in new file mode 100644 index 0000000..975df97 --- /dev/null +++ b/src/lib/log/tests/buffer_logger_test.sh.in @@ -0,0 +1,45 @@ +#!/bin/sh + +# Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Checks that the initLogger() call uses for unit tests respects the setting of +# the buffer value + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +tempfile="@abs_builddir@/buffer_logger_test_tempfile_$$" + +printf 'Checking that buffer initialization works:\n' + +test_start 'buffer-logger.buffer-including-process()-call' +cat > $tempfile << . +INFO [buffertest.log] LOG_BAD_SEVERITY unrecognized log severity: info +INFO [buffertest.log] LOG_BAD_SEVERITY unrecognized log severity: info +. +./buffer_logger_test 2>&1 | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish 0 + +test_start 'buffer-logger.buffer-excluding-process()-call' +cat > $tempfile << . +INFO [buffertest.log]: LOG_BAD_SEVERITY unrecognized log severity: info +DEBUG [buffertest.log]: LOG_BAD_DESTINATION unrecognized log destination: debug-50 +INFO [buffertest.log]: LOG_BAD_SEVERITY unrecognized log severity: info +. +./buffer_logger_test -n 2>&1 | diff $tempfile - +test_finish 0 + +# Tidy up. +rm -f $tempfile diff --git a/src/lib/log/tests/console_test.sh.in b/src/lib/log/tests/console_test.sh.in new file mode 100644 index 0000000..7c5ebeb --- /dev/null +++ b/src/lib/log/tests/console_test.sh.in @@ -0,0 +1,54 @@ +#!/bin/sh + +# Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# The logger supports the idea of a "console" logger than logs to either stdout +# or stderr. This test checks that both these options work. + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +tempfile="@abs_builddir@/console_test_tempfile_$$" + +# Look at tempfile and check that the count equals the expected count +passfail() { + count=$(wc -l $tempfile | awk '{print $1}') + if [ "${count}" -eq "${1}" ]; then + test_finish 0 + else + test_finish 1 + fi +} + +test_start 'console-output.stdout' +rm -f $tempfile +./logger_example -c stdout -s error 1> $tempfile 2> /dev/null +passfail 4 + +test_start 'console-output.stdout-not-stderr' +rm -f $tempfile +./logger_example -c stdout -s error 1> /dev/null 2> $tempfile +passfail 0 + +test_start 'console-output.stderr' +rm -f $tempfile +./logger_example -c stderr -s error 1> /dev/null 2> $tempfile +passfail 4 + +test_start 'console-output.stderr-not-stdout' +rm -f $tempfile +./logger_example -c stderr -s error 1> $tempfile 2> /dev/null +passfail 0 + +# Tidy up +rm -f $tempfile diff --git a/src/lib/log/tests/destination_test.sh.in b/src/lib/log/tests/destination_test.sh.in new file mode 100644 index 0000000..86fc415 --- /dev/null +++ b/src/lib/log/tests/destination_test.sh.in @@ -0,0 +1,85 @@ +#!/bin/sh + +# Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Checks that the logger will route messages to the chosen destination. + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +tempfile="@abs_builddir@/destination_test_tempfile_$$" +destfile1_tmp="@abs_builddir@/destination_test_destfile_1_tmp_$$" +destfile2_tmp="@abs_builddir@/destination_test_destfile_2_tmp_$$" +destfile1="@abs_builddir@/destination_test_destfile_1_$$" +destfile2="@abs_builddir@/destination_test_destfile_2_$$" + +printf '1. One logger, multiple destinations:\n' + +cat > $tempfile << . +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +. +rm -f $destfile1 $destfile2 +./logger_example -s error -f $destfile1_tmp -f $destfile2_tmp + +# strip the pids and thread ids +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile1_tmp > $destfile1 +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile2_tmp > $destfile2 +# strip the thread ids + +test_start 'logger-destination.one-logger-file-1' +cut -d' ' -f3- $destfile1 | diff $tempfile - +test_finish $? + +test_start 'logger-destination.one-logger-file-2' +cut -d' ' -f3- $destfile2 | diff $tempfile - +test_finish $? + +# Tidy up. +rm -f $tempfile $destfile1_tmp $destfile2_tmp $destfile1 $destfile2 + +printf '2. Two loggers, different destinations and severities:\n' +rm -f $destfile1 $destfile2 +./logger_example -l example -s info -f $destfile1_tmp -l alpha -s warn -f $destfile2_tmp + +# strip the pids and thread ids +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile1_tmp > $destfile1 +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile2_tmp > $destfile2 + +# All output for example and example.beta should have gone to destfile1. +# Output for example.alpha should have done to destfile2. + +test_start 'logger-destination.multiples-loggers-file-1' +cat > $tempfile << . +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file +WARN [example] LOG_BAD_STREAM bad log console output stream: example +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +WARN [example.beta] LOG_BAD_STREAM bad log console output stream: beta_warn +INFO [example.beta] LOG_READ_ERROR error reading from message file beta: info +. +cut -d' ' -f3- $destfile1 | diff $tempfile - +test_finish $? + +test_start 'logger-destination.multiples-loggers-file-2' +cat > $tempfile << . +WARN [example.alpha] LOG_READ_ERROR error reading from message file a.txt: dummy reason +. +cut -d' ' -f3- $destfile2 | diff $tempfile - +test_finish $? + +# Tidy up. +rm -f $tempfile $destfile1_tmp $destfile2_tmp $destfile1 $destfile2 diff --git a/src/lib/log/tests/init_logger_test.cc b/src/lib/log/tests/init_logger_test.cc new file mode 100644 index 0000000..02862fd --- /dev/null +++ b/src/lib/log/tests/init_logger_test.cc @@ -0,0 +1,36 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/macros.h> +#include <log/logger_support.h> +#include <log/log_messages.h> + +using namespace isc::log; + +/// \brief Test InitLogger +/// +/// A program used in testing the logger that initializes logging using +/// initLogger(), then outputs several messages at different severities and +/// debug levels. An external script sets the environment variables and checks +/// that they have the desired effect. + +int +main(int, char**) { + initLogger(); + Logger logger("log"); + + LOG_DEBUG(logger, 0, LOG_BAD_DESTINATION).arg("debug-0"); + LOG_DEBUG(logger, 50, LOG_BAD_DESTINATION).arg("debug-50"); + LOG_DEBUG(logger, 99, LOG_BAD_DESTINATION).arg("debug-99"); + LOG_INFO(logger, LOG_BAD_SEVERITY).arg("info"); + LOG_WARN(logger, LOG_BAD_STREAM).arg("warn"); + LOG_ERROR(logger, LOG_DUPLICATE_MESSAGE_ID).arg("error"); + LOG_FATAL(logger, LOG_NO_MESSAGE_ID).arg("fatal"); + + return (0); +} diff --git a/src/lib/log/tests/init_logger_test.sh.in b/src/lib/log/tests/init_logger_test.sh.in new file mode 100644 index 0000000..348008d --- /dev/null +++ b/src/lib/log/tests/init_logger_test.sh.in @@ -0,0 +1,96 @@ +#!/bin/sh + +# Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Checks that the initLogger() call uses for unit tests respects the setting of +# the environment variables. + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +tempfile="@abs_builddir@/init_logger_test_tempfile_$$" +destfile_tmp="@abs_builddir@/init_logger_test_destfile_tmp_$$" +destfile="@abs_builddir@/init_logger_test_destfile_$$" + +printf '1. Checking that KEA_LOGGER_SEVERITY/KEA_LOGGER_DBGLEVEL work:\n' + +test_start 'init-logger.severity=DEBUG,dbglevel=99' +cat > $tempfile << . +DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0 +DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50 +DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-99 +INFO [kea.log] LOG_BAD_SEVERITY unrecognized log severity: info +WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn +ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code +FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +KEA_LOGGER_DESTINATION=stdout KEA_LOGGER_SEVERITY=DEBUG KEA_LOGGER_DBGLEVEL=99 ./init_logger_test | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +test_start 'init-logger.severity=DEBUG,dbglevel=50' +cat > $tempfile << . +DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0 +DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50 +INFO [kea.log] LOG_BAD_SEVERITY unrecognized log severity: info +WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn +ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code +FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +KEA_LOGGER_DESTINATION=stdout KEA_LOGGER_SEVERITY=DEBUG KEA_LOGGER_DBGLEVEL=50 ./init_logger_test | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +test_start 'init-logger.severity=WARN' +cat > $tempfile << . +WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn +ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code +FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +KEA_LOGGER_DESTINATION=stdout KEA_LOGGER_SEVERITY=WARN ./init_logger_test | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +printf '2. Checking that KEA_LOGGER_DESTINATION works:\n' + +test_start 'init-logger.stdout' +cat > $tempfile << . +FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID +. +rm -f $destfile_tmp $destfile +KEA_LOGGER_SEVERITY=FATAL KEA_LOGGER_DESTINATION=stdout ./init_logger_test 1> $destfile_tmp +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile_tmp > $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +test_finish $? + +test_start 'init-logger.stderr' +rm -f $destfile_tmp $destfile +KEA_LOGGER_SEVERITY=FATAL KEA_LOGGER_DESTINATION=stderr ./init_logger_test 2> $destfile_tmp +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile_tmp > $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +test_finish $? + +test_start 'init-logger.file' +rm -f $destfile_tmp $destfile +KEA_LOGGER_SEVERITY=FATAL KEA_LOGGER_DESTINATION=$destfile_tmp ./init_logger_test +sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' < $destfile_tmp > $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +test_finish $? + +# Note: can't automatically test syslog output. + +# Tidy up. +rm -f $tempfile $destfile_tmp $destfile diff --git a/src/lib/log/tests/local_file_test.sh.in b/src/lib/log/tests/local_file_test.sh.in new file mode 100644 index 0000000..c1e7a53 --- /dev/null +++ b/src/lib/log/tests/local_file_test.sh.in @@ -0,0 +1,66 @@ +#!/bin/sh + +# Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Checks that a local message file can override the definitions in the message +# dictionary. + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +localmes="@abs_builddir@/localdef_mes_$$" +tempfile="@abs_builddir@/run_time_init_test_tempfile_$$" + +# Create the local message file for testing + +cat > $localmes << . +% LOG_NOTHERE this message is not in the global dictionary +% LOG_READ_ERROR replacement read error, parameters: '%1' and '%2' +% LOG_READING_LOCAL_FILE replacement read local message file, parameter is '%1' +. + +test_start 'local-file.local-message-replacement' +cat > $tempfile << . +WARN [example.log] LOG_NO_SUCH_MESSAGE could not replace message text for 'LOG_NOTHERE': no such message +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE replacement read local message file, parameter is 'dummy/file' +WARN [example] LOG_BAD_STREAM bad log console output stream: example +WARN [example.alpha] LOG_READ_ERROR replacement read error, parameters: 'a.txt' and 'dummy reason' +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +WARN [example.beta] LOG_BAD_STREAM bad log console output stream: beta_warn +. +./logger_example -c stdout -s warn $localmes | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +test_start 'local-file.read-error-reporting' +cat > $tempfile << . +ERROR [example.log] LOG_INPUT_OPEN_FAIL unable to open message file $localmes for input: No such file or directory +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file +WARN [example] LOG_BAD_STREAM bad log console output stream: example +WARN [example.alpha] LOG_READ_ERROR error reading from message file a.txt: dummy reason +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +WARN [example.beta] LOG_BAD_STREAM bad log console output stream: beta_warn +. +rm -f $localmes +./logger_example -c stdout -s warn $localmes | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +# Tidy up. +rm -f $tempfile diff --git a/src/lib/log/tests/log_formatter_unittest.cc b/src/lib/log/tests/log_formatter_unittest.cc new file mode 100644 index 0000000..4bd0405 --- /dev/null +++ b/src/lib/log/tests/log_formatter_unittest.cc @@ -0,0 +1,181 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> +#include <gtest/gtest.h> + +#include <util/unittests/resource.h> +#include <util/unittests/check_valgrind.h> + +#include <log/log_formatter.h> +#include <log/logger_level.h> + +#include <vector> +#include <string> + +using namespace std; + +namespace { + +class FormatterTest : public ::testing::Test { +protected: + typedef pair<isc::log::Severity, string> Output; + typedef isc::log::Formatter<FormatterTest> Formatter; + vector<Output> outputs; +public: + void output(const isc::log::Severity& prefix, const string& message) { + outputs.push_back(Output(prefix, message)); + } + // Just shortcut for new string + boost::shared_ptr<string> s(const char* text) { + return (boost::make_shared<string>(text)); + } +}; + +// Create an inactive formatter and check it doesn't produce any output +TEST_F(FormatterTest, inactive) { + Formatter(); + EXPECT_EQ(0, outputs.size()); +} + +// Create an active formatter and check it produces output. Does no arg +// substitution yet +TEST_F(FormatterTest, active) { + Formatter(isc::log::INFO, s("Text of message"), this); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("Text of message", outputs[0].second); +} + +// No output even when we have an arg on the inactive formatter +TEST_F(FormatterTest, inactiveArg) { + Formatter().arg("Hello"); + EXPECT_EQ(0, outputs.size()); +} + +// Create an active formatter and replace a placeholder with string +TEST_F(FormatterTest, stringArg) { + { + SCOPED_TRACE("C++ string"); + Formatter(isc::log::INFO, s("Hello %1"), this).arg(string("World")); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("Hello World", outputs[0].second); + } + { + SCOPED_TRACE("C++ string"); + Formatter(isc::log::INFO, s("Hello %1"), this).arg(string("Internet")); + ASSERT_EQ(2, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[1].first); + EXPECT_EQ("Hello Internet", outputs[1].second); + } +} + +// Test the .deactivate() method +TEST_F(FormatterTest, deactivate) { + Formatter(isc::log::INFO, s("Text of message"), this).deactivate(); + // If there was no .deactivate, it should have output it. + // But not now. + ASSERT_EQ(0, outputs.size()); +} + +// Can convert to string +TEST_F(FormatterTest, intArg) { + Formatter(isc::log::INFO, s("The answer is %1"), this).arg(42); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("The answer is 42", outputs[0].second); +} + +// Can use multiple arguments at different places +TEST_F(FormatterTest, multiArg) { + Formatter(isc::log::INFO, s("The %2 are %1"), this).arg("switched"). + arg("arguments"); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("The arguments are switched", outputs[0].second); +} + +#ifdef ENABLE_LOGGER_CHECKS + +TEST_F(FormatterTest, mismatchedPlaceholders) { + // Throws MismatchedPlaceholders exception if the placeholder is missing + // for a supplied argument. + EXPECT_THROW(Formatter(isc::log::INFO, s("Missing the second %1"), this). + arg("argument").arg("missing"), + isc::log::MismatchedPlaceholders); + +#ifdef EXPECT_DEATH + // Likewise, if there's a redundant placeholder (or missing argument), the + // check detects it and aborts the program. Due to the restriction of the + // current implementation, it doesn't throw. + if (!isc::util::unittests::runningOnValgrind()) { + EXPECT_DEATH({ + isc::util::unittests::dontCreateCoreDumps(); + Formatter(isc::log::INFO, s("Too many arguments in %1 %2"), this). + arg("only one"); + }, ".*"); + } +#endif /* EXPECT_DEATH */ + // Mixed case of above two: the exception will be thrown due to the missing + // placeholder. The other check is disabled due to that. + EXPECT_THROW(Formatter(isc::log::INFO, s("Missing the first %2"), this). + arg("missing").arg("argument"), + isc::log::MismatchedPlaceholders); +} + +#else + +// If logger checks are not enabled, nothing is thrown +TEST_F(FormatterTest, mismatchedPlaceholders) { + Formatter(isc::log::INFO, s("Missing the second %1"), this). + arg("argument").arg("missing"); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("Missing the second argument " + "@@Missing logger placeholder '%2' for value 'missing'@@", + outputs[0].second); + + EXPECT_NO_THROW(Formatter(isc::log::INFO, + s("Too many arguments in %1 %2"), this). + arg("only one")); + ASSERT_EQ(2, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[1].first); + EXPECT_EQ("Too many arguments in only one %2 " + "@@Excess logger placeholder '%2' still exists@@", + outputs[1].second); + + EXPECT_NO_THROW(Formatter(isc::log::INFO, s("Missing the first %2"), this). + arg("missing").arg("argument")); + ASSERT_EQ(3, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[2].first); + EXPECT_EQ("Missing the first argument " + "@@Missing logger placeholder '%1' for value 'missing'@@", + outputs[2].second); +} + +#endif /* ENABLE_LOGGER_CHECKS */ + +// Can replace multiple placeholders +TEST_F(FormatterTest, multiPlaceholder) { + Formatter(isc::log::INFO, s("The %1 is the %1"), this). + arg("first rule of tautology club"); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("The first rule of tautology club is " + "the first rule of tautology club", outputs[0].second); +} + +// Test we can cope with replacement containing the placeholder +TEST_F(FormatterTest, noRecurse) { + // If we recurse, this will probably eat all the memory and crash + Formatter(isc::log::INFO, s("%1"), this).arg("%1 %1"); + ASSERT_EQ(1, outputs.size()); + EXPECT_EQ(isc::log::INFO, outputs[0].first); + EXPECT_EQ("%1 %1", outputs[0].second); +} + +} diff --git a/src/lib/log/tests/log_test_messages.cc b/src/lib/log/tests/log_test_messages.cc new file mode 100644 index 0000000..5cb25ad --- /dev/null +++ b/src/lib/log/tests/log_test_messages.cc @@ -0,0 +1,25 @@ +// File created from ../../../../src/lib/log/tests/log_test_messages.mes + +#include <cstddef> +#include <log/message_types.h> +#include <log/message_initializer.h> + +namespace isc { +namespace log { + +extern const isc::log::MessageID LOG_LOCK_TEST_MESSAGE = "LOG_LOCK_TEST_MESSAGE"; + +} // namespace log +} // namespace isc + +namespace { + +const char* values[] = { + "LOG_LOCK_TEST_MESSAGE", "this is a test message.", + NULL +}; + +const isc::log::MessageInitializer initializer(values); + +} // Anonymous namespace + diff --git a/src/lib/log/tests/log_test_messages.h b/src/lib/log/tests/log_test_messages.h new file mode 100644 index 0000000..96553f5 --- /dev/null +++ b/src/lib/log/tests/log_test_messages.h @@ -0,0 +1,16 @@ +// File created from ../../../../src/lib/log/tests/log_test_messages.mes + +#ifndef LOG_TEST_MESSAGES_H +#define LOG_TEST_MESSAGES_H + +#include <log/message_types.h> + +namespace isc { +namespace log { + +extern const isc::log::MessageID LOG_LOCK_TEST_MESSAGE; + +} // namespace log +} // namespace isc + +#endif // LOG_TEST_MESSAGES_H diff --git a/src/lib/log/tests/log_test_messages.mes b/src/lib/log/tests/log_test_messages.mes new file mode 100644 index 0000000..f7bee43 --- /dev/null +++ b/src/lib/log/tests/log_test_messages.mes @@ -0,0 +1,18 @@ +# Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# \brief Message Utility Message File +# +# This is the source of the set of messages generated by the message and +# logging components. The associated .h and .cc files are created by hand from +# this file though and are not built during the build process; this is to avoid +# the chicken-and-egg situation where we need the files to build the message +# compiler, yet we need the compiler to build the files. + +$NAMESPACE isc::log + +% LOG_LOCK_TEST_MESSAGE this is a test message. +This is a log message used in testing. diff --git a/src/lib/log/tests/logger_example.cc b/src/lib/log/tests/logger_example.cc new file mode 100644 index 0000000..ff3d512 --- /dev/null +++ b/src/lib/log/tests/logger_example.cc @@ -0,0 +1,306 @@ +// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// \brief Example Program +/// +/// Simple example program showing how to use the logger. The various +/// command-line options let most aspects of the logger be exercised, so +/// making this a useful tool for testing. +/// +/// See the usage() method for details of use. + +#include <config.h> + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <boost/lexical_cast.hpp> + +#include <iostream> +#include <string> +#include <vector> + +#include <util/strutil.h> + +#include <log/logger.h> +#include <log/logger_level.h> +#include <log/logger_manager.h> +#include <log/logger_name.h> +#include <log/logger_specification.h> +#include <log/macros.h> + +// Include a set of message definitions. +#include <log/log_messages.h> +#include <log/interprocess/interprocess_sync_null.h> + +using namespace isc::log; +using namespace std; +using isc::log::interprocess::InterprocessSyncNull; + +// Print usage information + +void usage() { + cout << +"logger_support_test [-h | [logger_spec] [[logger_spec]...]]\n" +"\n" +" -h Print this message and exit\n" +"\n" +"The rest of the command line comprises the set of logger specifications.\n" +"Each specification is of the form:\n" +"\n" +" -l logger [-s severity] [-d dbglevel] output_spec] [[output_spec] ...\n" +"\n" +"where:\n" +"\n" +" -l logger Give the name of the logger to which the following\n" +" output specifications will apply.\n" +"\n" +"Each logger is followed by the indication of the severity it is logging\n" +"and, if applicable, its debug level:\n" +"\n" +" -d dbglevel Debug level. Only interpreted if the severity is 'debug'\n" +" this is a number between 0 and 99.\n" +" -s severity Set the severity of messages output. 'severity' is one\n" +" of 'debug', 'info', 'warn', 'error', 'fatal', the default\n" +" being 'info'.\n" +"\n" +"The output specifications - there may be more than one per logger - detail\n" +"the output streams attached to the logger. These are of the form:\n" +"\n" +" -c stream | -f file [-m maxver] [-z maxsize] | -y facility\n" +"\n" +"These are:\n" +"\n" +" -c stream Send output to the console. 'stream' is one of 'stdout'\n" +" of 'stderr'.\n" +" -f file Send output to specified file, appending to existing file\n" +" if one exists.\n" +" -y facility Send output to the syslog file with the given facility\n" +" name (e.g. local1, cron etc.)\n" +"\n" +"The following can be specified for the file logger:\n" +"\n" +" -m maxver If file rolling is selected (by the maximum file size being\n" +" non-zero), the maximum number of versions to keep (defaults\n" +" to 0)\n" +" -z maxsize Maximum size of the file before the file is closed and a\n" +" new one opened. The default of 0 means no maximum size.\n" +"\n" +"If none of -c, -f or -y is given, by default, output is sent to stdout. If no\n" +"logger is specified, the default is the program's root logger ('example').\n"; + +} + + +// The program sets the attributes on the root logger and logs a set of +// messages. Looking at the output determines whether the program worked. + +int main(int argc, char** argv) { + const char* ROOT_NAME = "example"; + + bool sw_found = false; // Set true if switch found + bool c_found = false; // Set true if "-c" found + bool f_found = false; // Set true if "-f" found + bool y_found = false; // Set true if "-y" found + int option; // For getopt() processing + OutputOption def_opt; // Default output option - used + // for initialization + LoggerSpecification cur_spec(ROOT_NAME);// Current specification + OutputOption cur_opt; // Current output option + vector<LoggerSpecification> loggers; // Set of logger specifications + std::string severity; // Severity set for logger + + // Initialize logging system - set the root logger name. + LoggerManager manager; + manager.init(ROOT_NAME); + + // In the parsing loop that follows, the construction of the logging + // specification is always "one behind". In other words, the parsing of + // command-line options updates the current logging specification/output + // options. When the flag indicating a new logger or output specification + // is encountered, the previous one is added to the list. + // + // One complication is that there is deemed to be a default active when + // the parsing starts (console output for the Kea root logger). This + // is included in the logging specifications UNLESS the first switch on + // the command line is a "-l" flag starting a new logger. To track this, + // the "sw_found" flag is set when a switch is completely processed. The + // processing of "-l" will only add information for a previous logger to + // the list if this flag is set. + while ((option = getopt(argc, argv, "hc:d:f:l:m:s:y:z:")) != -1) { + switch (option) { + case 'c': // Console output + // New output spec. If one was currently active, add it to the + // list and reset the current output option to the defaults. + if (c_found || f_found || y_found) { + cur_spec.addOutputOption(cur_opt); + cur_opt = def_opt; + f_found = y_found = false; + } + + // Set the output option for this switch. + c_found = true; + cur_opt.destination = OutputOption::DEST_CONSOLE; + if (strcmp(optarg, "stdout") == 0) { + cur_opt.stream = OutputOption::STR_STDOUT; + + } else if (strcmp(optarg, "stderr") == 0) { + cur_opt.stream = OutputOption::STR_STDERR; + + } else { + cerr << "Unrecognized console option: " << optarg << "\n"; + return (1); + } + break; + + case 'd': // Debug level + cur_spec.setDbglevel(boost::lexical_cast<int>(optarg)); + break; + + case 'f': // File output specification + // New output spec. If one was currently active, add it to the + // list and reset the current output option to the defaults. + if (c_found || f_found || y_found) { + cur_spec.addOutputOption(cur_opt); + cur_opt = def_opt; + c_found = y_found = false; + } + + // Set the output option for this switch. + f_found = true; + cur_opt.destination = OutputOption::DEST_FILE; + cur_opt.filename = optarg; + break; + + case 'h': // Help + usage(); + return (0); + + case 'l': // Logger + // If a current specification is active, add the last output option + // to it, add it to the list and reset. A specification is active + // if at least one switch has been previously found. + if (sw_found) { + cur_spec.addOutputOption(cur_opt); + loggers.push_back(cur_spec); + cur_spec.reset(); + } + + // Set the logger name + cur_spec.setName(std::string(optarg)); + + // Reset the output option to the default. + cur_opt = def_opt; + + // Indicate nothing is found to prevent the console option (the + // default output option) being added to the output list if an + // output option is found. + c_found = f_found = y_found = false; + break; + + case 'm': // Maximum file version + if (!f_found) { + std::cerr << "Attempt to set maximum version (-m) " + "outside of file output specification\n"; + return (1); + } + try { + cur_opt.maxver = boost::lexical_cast<unsigned int>(optarg); + } catch (const boost::bad_lexical_cast&) { + std::cerr << "Maximum version (-m) argument must be a positive " + "integer\n"; + return (1); + } + break; + + case 's': // Severity + severity = optarg; + isc::util::str::uppercase(severity); + cur_spec.setSeverity(getSeverity(severity)); + break; + + case 'y': // Syslog output + // New output spec. If one was currently active, add it to the + // list and reset the current output option to the defaults. + if (c_found || f_found || y_found) { + cur_spec.addOutputOption(cur_opt); + cur_opt = def_opt; + c_found = f_found = false; + } + y_found = true; + cur_opt.destination = OutputOption::DEST_SYSLOG; + cur_opt.facility = optarg; + break; + + case 'z': // Maximum size + if (! f_found) { + std::cerr << "Attempt to set file size (-z) " + "outside of file output specification\n"; + return (1); + } + try { + cur_opt.maxsize = boost::lexical_cast<size_t>(optarg); + } catch (const boost::bad_lexical_cast&) { + std::cerr << "File size (-z) argument must be a positive " + "integer\n"; + return (1); + } + break; + + + default: + std::cerr << "Unrecognized option: " << + static_cast<char>(option) << "\n"; + return (1); + } + + // Have found at least one command-line switch, so note the fact. + sw_found = true; + } + + // Add the current (unfinished specification) to the list. + cur_spec.addOutputOption(cur_opt); + loggers.push_back(cur_spec); + + // Set the logging options. + manager.process(loggers.begin(), loggers.end()); + + // Set the local file + if (optind < argc) { + LoggerManager::readLocalMessageFile(argv[optind]); + } + + // Log a few messages to different loggers. Here, we switch to using + // null interprocess sync objects for the loggers below as the + // logger example can be used as a standalone program (which may not + // have write access to a local state directory to create + // lockfiles). + isc::log::Logger logger_ex(ROOT_NAME); + logger_ex.setInterprocessSync(new InterprocessSyncNull("logger")); + isc::log::Logger logger_alpha("alpha"); + logger_alpha.setInterprocessSync(new InterprocessSyncNull("logger")); + isc::log::Logger logger_beta("beta"); + logger_beta.setInterprocessSync(new InterprocessSyncNull("logger")); + + LOG_FATAL(logger_ex, LOG_WRITE_ERROR).arg("test1").arg("42"); + LOG_ERROR(logger_ex, LOG_READING_LOCAL_FILE).arg("dummy/file"); + LOG_WARN(logger_ex, LOG_BAD_STREAM).arg("example"); + LOG_WARN(logger_alpha, LOG_READ_ERROR).arg("a.txt").arg("dummy reason"); + LOG_INFO(logger_alpha, LOG_INPUT_OPEN_FAIL).arg("example.msg").arg("dummy reason"); + LOG_DEBUG(logger_ex, 0, LOG_READING_LOCAL_FILE).arg("example/0"); + LOG_DEBUG(logger_ex, 24, LOG_READING_LOCAL_FILE).arg("example/24"); + LOG_DEBUG(logger_ex, 25, LOG_READING_LOCAL_FILE).arg("example/25"); + LOG_DEBUG(logger_ex, 26, LOG_READING_LOCAL_FILE).arg("example/26"); + LOG_FATAL(logger_beta, LOG_BAD_SEVERITY).arg("beta_fatal"); + LOG_ERROR(logger_beta, LOG_BAD_DESTINATION).arg("beta_error"); + LOG_WARN(logger_beta, LOG_BAD_STREAM).arg("beta_warn"); + LOG_INFO(logger_beta, LOG_READ_ERROR).arg("beta").arg("info"); + LOG_DEBUG(logger_beta, 25, LOG_BAD_SEVERITY).arg("beta/25"); + LOG_DEBUG(logger_beta, 26, LOG_BAD_SEVERITY).arg("beta/26"); + + return (0); +} diff --git a/src/lib/log/tests/logger_level_impl_unittest.cc b/src/lib/log/tests/logger_level_impl_unittest.cc new file mode 100644 index 0000000..c82be69 --- /dev/null +++ b/src/lib/log/tests/logger_level_impl_unittest.cc @@ -0,0 +1,168 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <iostream> +#include <string> + +#include <gtest/gtest.h> +#include <boost/static_assert.hpp> +#include <boost/lexical_cast.hpp> + +#include <log/logger_level_impl.h> +#include <log/logger_support.h> +#include <log4cplus/logger.h> + +using namespace isc::log; +using namespace std; + +class LoggerLevelImplTest : public ::testing::Test { +protected: + LoggerLevelImplTest() { + // Ensure logging set to default for unit tests + setDefaultLoggingOutput(); + } + + ~LoggerLevelImplTest() + {} +}; + + +// Checks that the log4cplus and Kea levels convert correctly +TEST_F(LoggerLevelImplTest, DefaultConversionFromBind) { + log4cplus::LogLevel fatal = + LoggerLevelImpl::convertFromBindLevel(Level(FATAL)); + EXPECT_EQ(log4cplus::FATAL_LOG_LEVEL, fatal); + + log4cplus::LogLevel error = + LoggerLevelImpl::convertFromBindLevel(Level(ERROR)); + EXPECT_EQ(log4cplus::ERROR_LOG_LEVEL, error); + + log4cplus::LogLevel warn = + LoggerLevelImpl::convertFromBindLevel(Level(WARN)); + EXPECT_EQ(log4cplus::WARN_LOG_LEVEL, warn); + + log4cplus::LogLevel info = + LoggerLevelImpl::convertFromBindLevel(Level(INFO)); + EXPECT_EQ(log4cplus::INFO_LOG_LEVEL, info); + + log4cplus::LogLevel debug = + LoggerLevelImpl::convertFromBindLevel(Level(DEBUG)); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL, debug); +} + +// Checks that the debug severity and level converts correctly +TEST_F(LoggerLevelImplTest, DebugConversionFromBind) { + log4cplus::LogLevel debug0 = + LoggerLevelImpl::convertFromBindLevel(Level(DEBUG, 0)); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - 0, debug0); + + log4cplus::LogLevel debug1 = + LoggerLevelImpl::convertFromBindLevel(Level(DEBUG, 1)); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - 1, debug1); + + log4cplus::LogLevel debug99 = + LoggerLevelImpl::convertFromBindLevel(Level(DEBUG, 99)); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - 99, debug99); + + // Out of range should be coerced to the nearest boundary + log4cplus::LogLevel debug_1 = + LoggerLevelImpl::convertFromBindLevel(Level(DEBUG, MIN_DEBUG_LEVEL - 1)); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL, debug_1); + + log4cplus::LogLevel debug100 = + LoggerLevelImpl::convertFromBindLevel(Level(DEBUG, MAX_DEBUG_LEVEL + 1)); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - MAX_DEBUG_LEVEL, debug100); +} + +// Do the checks the other way +static void +test_convert_to(const char* trace, isc::log::Severity severity, int dbglevel, + log4cplus::LogLevel level) +{ + SCOPED_TRACE(trace); + Level test = LoggerLevelImpl::convertToBindLevel(level); + EXPECT_EQ(severity, test.severity); + EXPECT_EQ(dbglevel, test.dbglevel); +} + +TEST_F(LoggerLevelImplTest, ConversionToBind) { + test_convert_to("FATAL", FATAL, MIN_DEBUG_LEVEL, log4cplus::FATAL_LOG_LEVEL); + test_convert_to("ERROR", ERROR, MIN_DEBUG_LEVEL, log4cplus::ERROR_LOG_LEVEL); + test_convert_to("WARN", WARN , MIN_DEBUG_LEVEL, log4cplus::WARN_LOG_LEVEL); + test_convert_to("INFO", INFO , MIN_DEBUG_LEVEL, log4cplus::INFO_LOG_LEVEL); + test_convert_to("DEBUG", DEBUG, MIN_DEBUG_LEVEL, log4cplus::DEBUG_LOG_LEVEL); + + test_convert_to("DEBUG0", DEBUG, MIN_DEBUG_LEVEL + 0, + (log4cplus::DEBUG_LOG_LEVEL)); + test_convert_to("DEBUG1", DEBUG, MIN_DEBUG_LEVEL + 1, + (log4cplus::DEBUG_LOG_LEVEL - 1)); + test_convert_to("DEBUG2", DEBUG, MIN_DEBUG_LEVEL + 2, + (log4cplus::DEBUG_LOG_LEVEL - 2)); + test_convert_to("DEBUG99", DEBUG, MIN_DEBUG_LEVEL + 99, + (log4cplus::DEBUG_LOG_LEVEL - 99)); + + // ... and some invalid valid values + test_convert_to("DEBUG-1", INFO, MIN_DEBUG_LEVEL, + (log4cplus::DEBUG_LOG_LEVEL + 1)); + BOOST_STATIC_ASSERT(MAX_DEBUG_LEVEL == 99); + test_convert_to("DEBUG+100", DEFAULT, 0, + (log4cplus::DEBUG_LOG_LEVEL - MAX_DEBUG_LEVEL - 1)); +} + +// Check that we can convert from a string to the new log4cplus levels +TEST_F(LoggerLevelImplTest, FromString) { + + // Test all valid values + for (int i = MIN_DEBUG_LEVEL; i <= MAX_DEBUG_LEVEL; ++i) { + std::string token = string("DEBUG") + boost::lexical_cast<std::string>(i); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - i, + LoggerLevelImpl::logLevelFromString(token)); + } + + // ... in lowercase too + for (int i = MIN_DEBUG_LEVEL; i <= MAX_DEBUG_LEVEL; ++i) { + std::string token = string("debug") + boost::lexical_cast<std::string>(i); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - i, + LoggerLevelImpl::logLevelFromString(token)); + } + + // A few below the minimum + for (int i = MIN_DEBUG_LEVEL - 5; i < MIN_DEBUG_LEVEL; ++i) { + std::string token = string("DEBUG") + boost::lexical_cast<std::string>(i); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL, LoggerLevelImpl::logLevelFromString(token)); + } + + // ... and above the maximum + for (int i = MAX_DEBUG_LEVEL + 1; i < MAX_DEBUG_LEVEL + 5; ++i) { + std::string token = string("DEBUG") + boost::lexical_cast<std::string>(i); + EXPECT_EQ(log4cplus::DEBUG_LOG_LEVEL - MAX_DEBUG_LEVEL, + LoggerLevelImpl::logLevelFromString(token)); + } + + // Invalid strings. + EXPECT_EQ(log4cplus::NOT_SET_LOG_LEVEL, + LoggerLevelImpl::logLevelFromString("DEBU")); + EXPECT_EQ(log4cplus::NOT_SET_LOG_LEVEL, + LoggerLevelImpl::logLevelFromString("unrecognized")); +} + +// ... and check the conversion back again. All levels should convert to "DEBUG". +TEST_F(LoggerLevelImplTest, ToString) { + + for (int i = MIN_DEBUG_LEVEL; i <= MAX_DEBUG_LEVEL; ++i) { + EXPECT_EQ(std::string("DEBUG"), + LoggerLevelImpl::logLevelToString(log4cplus::DEBUG_LOG_LEVEL - i)); + } + + // ... and that out of range stuff returns an empty string. + EXPECT_EQ(std::string(), + LoggerLevelImpl::logLevelToString(log4cplus::DEBUG_LOG_LEVEL + 1)); + EXPECT_EQ(std::string(), + LoggerLevelImpl::logLevelToString( + log4cplus::DEBUG_LOG_LEVEL - MAX_DEBUG_LEVEL - 100)); +} diff --git a/src/lib/log/tests/logger_level_unittest.cc b/src/lib/log/tests/logger_level_unittest.cc new file mode 100644 index 0000000..ccaecd9 --- /dev/null +++ b/src/lib/log/tests/logger_level_unittest.cc @@ -0,0 +1,78 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <iostream> +#include <string> + +#include <gtest/gtest.h> + +#include <log/logger.h> +#include <log/logger_manager.h> +#include <log/log_messages.h> +#include <log/logger_support.h> + +using namespace isc; +using namespace isc::log; +using namespace std; + +class LoggerLevelTest : public ::testing::Test { +protected: + LoggerLevelTest() { + // Logger initialization is done in main(). As logging tests may + // alter the default logging output, it is reset here. + setDefaultLoggingOutput(); + } + ~LoggerLevelTest() { + LoggerManager::reset(); + } +}; + + +// Checks that the logger is named correctly. + +TEST_F(LoggerLevelTest, Creation) { + + // Default + isc::log::Level level1; + EXPECT_EQ(isc::log::DEFAULT, level1.severity); + EXPECT_EQ(isc::log::MIN_DEBUG_LEVEL, level1.dbglevel); + + // Single argument constructor. + isc::log::Level level2(isc::log::FATAL); + EXPECT_EQ(isc::log::FATAL, level2.severity); + EXPECT_EQ(isc::log::MIN_DEBUG_LEVEL, level2.dbglevel); + + // Two-argument constructor + isc::log::Level level3(isc::log::DEBUG, 42); + EXPECT_EQ(isc::log::DEBUG, level3.severity); + EXPECT_EQ(42, level3.dbglevel); +} + +TEST_F(LoggerLevelTest, getSeverity) { + EXPECT_EQ(DEBUG, getSeverity("DEBUG")); + EXPECT_EQ(DEBUG, getSeverity("debug")); + EXPECT_EQ(DEBUG, getSeverity("DeBuG")); + EXPECT_EQ(INFO, getSeverity("INFO")); + EXPECT_EQ(INFO, getSeverity("info")); + EXPECT_EQ(INFO, getSeverity("iNfO")); + EXPECT_EQ(WARN, getSeverity("WARN")); + EXPECT_EQ(WARN, getSeverity("warn")); + EXPECT_EQ(WARN, getSeverity("wARn")); + EXPECT_EQ(ERROR, getSeverity("ERROR")); + EXPECT_EQ(ERROR, getSeverity("error")); + EXPECT_EQ(ERROR, getSeverity("ERRoR")); + EXPECT_EQ(FATAL, getSeverity("FATAL")); + EXPECT_EQ(FATAL, getSeverity("fatal")); + EXPECT_EQ(FATAL, getSeverity("FAtaL")); + + // bad values should default to stdout + EXPECT_EQ(INFO, getSeverity("some bad value")); + EXPECT_EQ(INFO, getSeverity("")); + + LoggerManager::reset(); +} diff --git a/src/lib/log/tests/logger_lock_test.cc b/src/lib/log/tests/logger_lock_test.cc new file mode 100644 index 0000000..9908800 --- /dev/null +++ b/src/lib/log/tests/logger_lock_test.cc @@ -0,0 +1,101 @@ +// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/macros.h> +#include <log/logger_support.h> +#include <log/logger_manager.h> +#include <log/log_messages.h> +#include <log/interprocess/interprocess_sync.h> +#include <log/tests/log_test_messages.h> + +#include <mutex> +#include <iostream> + +#include <boost/noncopyable.hpp> + +using namespace std; +using namespace isc::log; + +/// \brief RAII safe mutex checker. +class CheckMutex : boost::noncopyable { +public: + /// \brief Exception thrown when the mutex is already locked. + struct AlreadyLocked : public isc::InvalidParameter { + AlreadyLocked(const char* file, size_t line, const char* what) : + isc::InvalidParameter(file, line, what) + {} + }; + + /// \brief Constructor. + /// + /// \throw AlreadyLocked if the mutex is already locked. + CheckMutex(mutex& mutex) : mutex_(mutex) { + if (!mutex.try_lock()) { + isc_throw(AlreadyLocked, "The mutex is already locked"); + } + } + + /// \brief Destructor. + /// + /// Unlocks the mutex. + ~CheckMutex() { + mutex_.unlock(); + } + +private: + mutex& mutex_; +}; + +class MockLoggingSync : public isc::log::interprocess::InterprocessSync { +public: + /// \brief Constructor + MockLoggingSync(const std::string& component_name) : + InterprocessSync(component_name) + {} + +protected: + virtual bool lock() { + // We first check if the logger acquired a lock on the + // LoggerManager mutex. + try { + CheckMutex check(LoggerManager::getMutex()); + } catch (const CheckMutex::AlreadyLocked&) { + cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: MUTEXLOCK\n"; + } + + cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: LOCK\n"; + return (true); + } + + virtual bool tryLock() { + cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: TRYLOCK\n"; + return (true); + } + + virtual bool unlock() { + cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: UNLOCK\n"; + return (true); + } +}; + +/// \brief Test logger lock sequence +/// +/// A program used in testing the logger. It verifies that (1) an +/// interprocess sync lock is first acquired by the logger, (2) the +/// message is logged by the logger, and (3) the lock is released in +/// that sequence. +int +main(int, char**) { + initLogger(); + Logger logger("log"); + logger.setInterprocessSync(new MockLoggingSync("log")); + + LOG_INFO(logger, LOG_LOCK_TEST_MESSAGE); + + return (0); +} diff --git a/src/lib/log/tests/logger_lock_test.sh.in b/src/lib/log/tests/logger_lock_test.sh.in new file mode 100644 index 0000000..2cea0f0 --- /dev/null +++ b/src/lib/log/tests/logger_lock_test.sh.in @@ -0,0 +1,38 @@ +#!/bin/sh + +# Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Checks that the locker interprocess sync locks are acquired and +# released correctly. + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +tempfile="@abs_builddir@/logger_lock_test_tempfile_$$" +destfile="@abs_builddir@/logger_lock_test_destfile_$$" + +test_start 'logger_lock' +cat > $tempfile << . +LOGGER_LOCK_TEST: MUTEXLOCK +LOGGER_LOCK_TEST: LOCK +INFO [kea.log] LOG_LOCK_TEST_MESSAGE this is a test message. +LOGGER_LOCK_TEST: UNLOCK +. +rm -f $destfile +KEA_LOGGER_SEVERITY=INFO KEA_LOGGER_DESTINATION=stdout ./logger_lock_test | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' > $destfile +cut -d' ' -f3- $destfile | diff $tempfile - +test_finish $? + +# Tidy up. +rm -f $tempfile $destfile diff --git a/src/lib/log/tests/logger_manager_unittest.cc b/src/lib/log/tests/logger_manager_unittest.cc new file mode 100644 index 0000000..6bde1db --- /dev/null +++ b/src/lib/log/tests/logger_manager_unittest.cc @@ -0,0 +1,511 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <stdio.h> +#include <unistd.h> + +#include <fstream> +#include <iostream> +#include <string> + +#include <gtest/gtest.h> + +#include <boost/scoped_array.hpp> +#include <boost/lexical_cast.hpp> + +#include <exceptions/exceptions.h> + +#include <log/macros.h> +#include <log/log_messages.h> +#include <log/logger.h> +#include <log/logger_level.h> +#include <log/logger_manager.h> +#include <log/logger_name.h> +#include <log/logger_specification.h> +#include <log/message_initializer.h> +#include <log/output_option.h> +#include <log/tests/tempdir.h> +#include <testutils/gtest_utils.h> + +#include <sys/types.h> +#include <regex.h> + +using namespace isc; +using namespace isc::log; +using namespace std; + +/// \brief LoggerManager Test +class LoggerManagerTest : public ::testing::Test { +public: + LoggerManagerTest() { + // Initialization of logging is done in main() + } + + ~LoggerManagerTest() { + LoggerManager::reset(); + } +}; + +// Convenience class to create the specification for the logger "filelogger", +// which, as the name suggests, logs to a file. It remembers the file name and +// deletes the file when instance of the class is destroyed. +class SpecificationForFileLogger { +public: + + // Constructor - allocate file and create the specification object + SpecificationForFileLogger() : spec_(), name_(createTempFilename()), + logname_("filelogger") { + + // Set the output to a temporary file. + OutputOption option; + option.destination = OutputOption::DEST_FILE; + option.filename = name_; + + // Set target output to the file logger. The defaults indicate + // INFO severity. + spec_.setName(logname_); + spec_.addOutputOption(option); + } + + // Destructor, remove the file. This is only a test, so ignore failures + ~SpecificationForFileLogger() { + if (! name_.empty()) { + static_cast<void>(remove(name_.c_str())); + + // Depending on the log4cplus version, a lock file may also be + // created. + static_cast<void>(remove((name_ + ".lock").c_str())); + } + } + + // Return reference to the logging specification for this loggger + LoggerSpecification& getSpecification() { + return spec_; + } + + // Return name of the logger + string getLoggerName() const { + return logname_; + } + + // Return name of the file + string getFileName() const { + return name_; + } + + // Create temporary filename + // + // The compiler warns against tmpnam() and suggests mkstemp instead. + // Unfortunately, this creates the filename and opens it. So we need to + // close and delete the file before returning the name. Also, the name + // is based on the template supplied and the name of the temporary + // directory may vary between systems. So translate TMPDIR and if that + // does not exist, use /tmp. + // + // \return Temporary file name + static std::string createTempFilename() { + string filename = TEMP_DIR + "/kea_logger_manager_test_XXXXXX"; + + // Copy into writable storage for the call to mkstemp + boost::scoped_array<char> tname(new char[filename.size() + 1]); + strcpy(tname.get(), filename.c_str()); + + // Create file, close and delete it, and store the name for later. + // There is still a race condition here, albeit a small one. + int filenum = mkstemp(tname.get()); + if (filenum == -1) { + isc_throw(Exception, "Unable to obtain unique filename"); + } + close(filenum); + + return (string(tname.get())); + } + + +private: + LoggerSpecification spec_; // Specification for this file logger + string name_; // Name of the output file + string logname_; // Name of this logger +}; + +// Convenience function to read an output log file and check that each line +// contains the expected message ID +// +// \param filename Name of the file to check +// \param start Iterator pointing to first expected message ID +// \param finish Iterator pointing to last expected message ID +template <typename T> +void checkFileContents(const std::string& filename, T start, T finish) { + + // Access the file for input + ifstream infile(filename.c_str()); + if (! infile.good()) { + FAIL() << "Unable to open the logging file " << filename; + } + + // Iterate round the expected message IDs and check that they appear in + // the string. + string line; // Line read from the file + + T i = start; // Iterator + getline(infile, line); + int lineno = 1; + + while ((i != finish) && (infile.good())) { + + // Check that the message ID appears in the line. + EXPECT_TRUE(line.find(string(*i)) != string::npos) + << "Expected to find " << string(*i) << " on line " << lineno + << " of logging file " << filename; + + // Go for the next line + ++i; + getline(infile, line); + ++lineno; + } + + // Why did the loop end? + EXPECT_TRUE(i == finish) << "Did not reach the end of the message ID list"; + EXPECT_TRUE(infile.eof()) << "Did not reach the end of the logging file"; + + // File will close when the instream is deleted at the end of this + // function. +} + +// Check that the logger correctly creates something logging to a file. +TEST_F(LoggerManagerTest, FileLogger) { + + // Create a specification for the file logger and use the manager to + // connect the "filelogger" logger to it. + SpecificationForFileLogger file_spec; + + // For the first test, we want to check that the file is created + // if it does not already exist. So delete the temporary file before + // logging the first message. + static_cast<void>(remove(file_spec.getFileName().c_str())); + + // Set up the file appenders. + LoggerManager manager; + manager.process(file_spec.getSpecification()); + + // Try logging to the file. Local scope is set to ensure that the logger + // is destroyed before we reset the global logging. We record what we + // put in the file for a later comparison. + vector<MessageID> ids; + { + + // Scope-limit the logger to ensure it is destroyed after the brief + // check. This adds weight to the idea that the logger will not + // keep the file open. + Logger logger(file_spec.getLoggerName().c_str()); + + LOG_FATAL(logger, LOG_DUPLICATE_MESSAGE_ID).arg("test"); + ids.push_back(LOG_DUPLICATE_MESSAGE_ID); + + LOG_FATAL(logger, LOG_DUPLICATE_NAMESPACE).arg("test"); + ids.push_back(LOG_DUPLICATE_NAMESPACE); + } + LoggerManager::reset(); + + // At this point, the output file should contain two lines with messages + // LOG_DUPLICATE_MESSAGE_ID and LOG_DUPLICATE_NAMESPACE messages - test this. + checkFileContents(file_spec.getFileName(), ids.begin(), ids.end()); + + // Re-open the file (we have to assume that it was closed when we + // reset the logger - there is no easy way to check) and check that + // new messages are appended to it. We use the alternative + // invocation of process() here to check it works. + vector<LoggerSpecification> spec(1, file_spec.getSpecification()); + manager.process(spec.begin(), spec.end()); + + // Create a new instance of the logger and log three more messages. + Logger logger(file_spec.getLoggerName().c_str()); + + LOG_FATAL(logger, LOG_NO_SUCH_MESSAGE).arg("test"); + ids.push_back(LOG_NO_SUCH_MESSAGE); + + LOG_FATAL(logger, LOG_INVALID_MESSAGE_ID).arg("test").arg("test2"); + ids.push_back(LOG_INVALID_MESSAGE_ID); + + LOG_FATAL(logger, LOG_NO_MESSAGE_ID).arg("42"); + ids.push_back(LOG_NO_MESSAGE_ID); + + // Close the file and check again + LoggerManager::reset(); + checkFileContents(file_spec.getFileName(), ids.begin(), ids.end()); +} + +// Check if the file rolls over when it gets above a certain size. +TEST_F(LoggerManagerTest, FileSizeRollover) { + // Set to a suitable minimum that log4cplus can cope with. + static const size_t SIZE_LIMIT = 204800; + + // Set up the name of the file. + SpecificationForFileLogger file_spec; + LoggerSpecification& spec = file_spec.getSpecification(); + + // Expand the option to ensure that a maximum version size is set. + LoggerSpecification::iterator opt = spec.begin(); + EXPECT_TRUE(opt != spec.end()); + opt->maxsize = SIZE_LIMIT; // Bytes + opt->maxver = 2; + + // The current output file does not exist (the creation of file_spec + // ensures that. Check that previous versions don't either. + vector<string> prev_name; + for (int i = 0; i < 3; ++i) { + prev_name.push_back(file_spec.getFileName() + "." + + boost::lexical_cast<string>(i + 1)); + (void) remove(prev_name[i].c_str()); + } + + // Generate an argument for a message that ensures that the message when + // logged will be over that size. + string big_arg(SIZE_LIMIT, 'x'); + + // Set up the file logger + LoggerManager manager; + manager.process(spec); + + // Log the message twice using different message IDs. This should generate + // three files as for the log4cplus implementation, the files appear to + // be rolled after the message is logged. + { + Logger logger(file_spec.getLoggerName().c_str()); + LOG_FATAL(logger, LOG_NO_SUCH_MESSAGE).arg(big_arg); + LOG_FATAL(logger, LOG_DUPLICATE_NAMESPACE).arg(big_arg); + } + + // Check them. + LoggerManager::reset(); // Ensure files are closed + + vector<MessageID> ids; + ids.push_back(LOG_NO_SUCH_MESSAGE); + checkFileContents(prev_name[1], ids.begin(), ids.end()); + + ids.clear(); + ids.push_back(LOG_DUPLICATE_NAMESPACE); + checkFileContents(prev_name[0], ids.begin(), ids.end()); + + // Log another message and check that the files have rotated and that + // a .3 version does not exist. + manager.process(spec); + { + Logger logger(file_spec.getLoggerName().c_str()); + LOG_FATAL(logger, LOG_NO_MESSAGE_TEXT).arg("42").arg(big_arg); + } + + LoggerManager::reset(); // Ensure files are closed + + // Check that the files have moved. + ids.clear(); + ids.push_back(LOG_DUPLICATE_NAMESPACE); + checkFileContents(prev_name[1], ids.begin(), ids.end()); + + ids.clear(); + ids.push_back(LOG_NO_MESSAGE_TEXT); + checkFileContents(prev_name[0], ids.begin(), ids.end()); + + // ... and check that the .3 version does not exist. + ifstream file3(prev_name[2].c_str(), ifstream::in); + EXPECT_FALSE(file3.good()); + + // Tidy up + for (vector<string>::size_type i = 0; i < prev_name.size(); ++i) { + (void) remove(prev_name[i].c_str()); + } +} + +// Check if an exception is thrown if maxsize is too large. +TEST_F(LoggerManagerTest, TooLargeMaxsize) { + // Set up the name of the file. + SpecificationForFileLogger file_spec; + LoggerSpecification& spec(file_spec.getSpecification()); + + // UINT64_MAX should be large enough. + LoggerSpecification::iterator opt = spec.begin(); + EXPECT_TRUE(opt != spec.end()); + opt->maxsize = std::numeric_limits<uint64_t>::max(); // bytes + + // Set up the file logger. + LoggerManager manager; + EXPECT_THROW_MSG(manager.process(spec), BadValue, + "expected maxsize < 2147483647MB, but instead got " + "18446744073709MB"); + + opt->maxsize = 1000000LL * (std::numeric_limits<int32_t>::max() + 1LL); // bytes + EXPECT_THROW_MSG(manager.process(spec), BadValue, + "expected maxsize < 2147483647MB, but instead got " + "2147483648MB"); +} + +namespace { // begin unnamed namespace + +// When we begin to use C++11, we could replace use of POSIX API with +// <regex>. + +class RegexHolder { +public: + RegexHolder(const char* expr, const int flags = REG_EXTENDED) { + const int rc = regcomp(®ex_, expr, flags); + if (rc) { + regfree(®ex_); + throw; + } + } + + ~RegexHolder() { + regfree(®ex_); + } + + regex_t* operator*() { + return (®ex_); + } + +private: + regex_t regex_; +}; + +} // end of unnamed namespace + +// Check that the logger correctly outputs the full formatted layout +// pattern. +TEST_F(LoggerManagerTest, checkLayoutPattern) { + // Create a specification for the file logger and use the manager to + // connect the "filelogger" logger to it. + SpecificationForFileLogger file_spec; + + // For the first test, we want to check that the file is created + // if it does not already exist. So delete the temporary file before + // logging the first message. + static_cast<void>(remove(file_spec.getFileName().c_str())); + + // Set up the file appenders. + LoggerManager manager; + manager.process(file_spec.getSpecification()); + + // Try logging to the file. Local scope is set to ensure that the logger + // is destroyed before we reset the global logging. + { + Logger logger(file_spec.getLoggerName().c_str()); + LOG_FATAL(logger, LOG_DUPLICATE_MESSAGE_ID).arg("test"); + } + + LoggerManager::reset(); + + // Access the file for input + const std::string& filename = file_spec.getFileName(); + ifstream infile(filename.c_str()); + if (! infile.good()) { + FAIL() << "Unable to open the logging file " << filename; + } + + std::string line; + std::getline(infile, line); + + RegexHolder regex(// %D{%Y-%m-%d %H:%M:%S.%q} + "^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}[[:space:]]" + "[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\\.[[:digit:]]+[[:space:]]" + // %-5p + "[[:alpha:]]{1,5}[[:space:]]" + // [%c/%i/%t] + "\\[[[:alnum:]\\-\\.]+/[[:digit:]]+\\.(0x)?[[:xdigit:]]+\\][[:space:]]" + ); + + const int re = regexec(*regex, line.c_str(), 0, NULL, 0); + ASSERT_EQ(0, re) + << "Logged message does not match expected layout pattern"; +} + +// Check that after calling the logDuplicatedMessages, the duplicated +// messages are removed. +TEST_F(LoggerManagerTest, logDuplicatedMessages) { + // Original set should not have duplicates. + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); + + // This just defines 1, but we'll add it a number of times. + const char* dupe[] = { + "DUPE", "dupe", + NULL + }; + const MessageInitializer init_message_initializer_1(dupe); + const MessageInitializer init_message_initializer_2(dupe); + + MessageInitializer::loadDictionary(); + // Should have a duplicate now. + ASSERT_EQ(1, MessageInitializer::getDuplicates().size()); + + // The logDuplicatedMessages, besides logging, should also remove the + // duplicates. + LoggerManager::logDuplicatedMessages(); + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); +} + +// Check that output options can be inherited. +TEST_F(LoggerManagerTest, outputOptionsInheritance) { + LoggerManager manager; + SpecificationForFileLogger file_spec; + vector<LoggerSpecification> specs; + + // Create the root logger configuration with a file output option. + string root_name(getRootLoggerName()); + LoggerSpecification root_spec(root_name); + OutputOption root_option; + root_option.destination = OutputOption::DEST_FILE; + root_option.filename = file_spec.getFileName(); + root_option.pattern = "%p %m\n"; + root_spec.addOutputOption(root_option); + specs.push_back(root_spec); + + // Create a child logger configuration without any output options. + // It should inherit the output option from the root logger. + string foo_name(root_name + ".foo"); + LoggerSpecification foo_spec(foo_name); + specs.push_back(foo_spec); + + // Create another child logger configuration with a console output option. + string bar_name(root_name + ".bar"); + LoggerSpecification bar_spec(bar_name); + OutputOption bar_option; + bar_option.destination = OutputOption::DEST_CONSOLE; + bar_option.pattern = "%p %m\n"; + bar_spec.addOutputOption(bar_option); + specs.push_back(bar_spec); + + // Check the number of output options for each specification. + EXPECT_EQ(root_spec.optionCount(), 1); + EXPECT_EQ(foo_spec.optionCount(), 0); + EXPECT_EQ(bar_spec.optionCount(), 1); + + // Process all the specifications. + manager.process(specs.begin(), specs.end()); + + // Log two messages each. + Logger root_logger(root_name.c_str()); + Logger foo_logger(foo_name.c_str()); + Logger bar_logger(bar_name.c_str()); + LOG_INFO(root_logger, "from root logger 1"); + LOG_INFO(foo_logger, "from foo logger 1"); + LOG_INFO(bar_logger, "from bar logger 1"); + LOG_INFO(root_logger, "from root logger 2"); + LOG_INFO(foo_logger, "from foo logger 2"); + LOG_INFO(bar_logger, "from bar logger 2"); + + // Check that root and foo were logged to file and that bar which + // had an explicit console configuration did not. + std::ifstream ifs(file_spec.getFileName()); + std::stringstream s; + s << ifs.rdbuf(); + std::string const result(s.str()); + EXPECT_NE(result.find("INFO from root logger 1"), string::npos); + EXPECT_NE(result.find("INFO from foo logger 1"), string::npos); + EXPECT_EQ(result.find("INFO from bar logger 1"), string::npos); + EXPECT_NE(result.find("INFO from root logger 2"), string::npos); + EXPECT_NE(result.find("INFO from foo logger 2"), string::npos); + EXPECT_EQ(result.find("INFO from bar logger 2"), string::npos); +} diff --git a/src/lib/log/tests/logger_name_unittest.cc b/src/lib/log/tests/logger_name_unittest.cc new file mode 100644 index 0000000..9048bf2 --- /dev/null +++ b/src/lib/log/tests/logger_name_unittest.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <string> + +#include <gtest/gtest.h> + +#include <log/logger_name.h> + +using namespace isc; +using namespace isc::log; + +// Test class. To avoid disturbing the root logger configuration in other +// tests in the suite, the root logger name is saved in the constructor and +// restored in the destructor. However, this is a bit chicken and egg, as the +// functions used to do the save and restore are those being tested... +// +// Note that the root name is originally set by the initialization of the +// logging configuration done in main(). + +class LoggerNameTest : public ::testing::Test { +public: + LoggerNameTest() : + name_(getRootLoggerName()) + {} + ~LoggerNameTest() { + setRootLoggerName(name_); + } + +private: + std::string name_; ///< Saved name +}; + +// Check setting and getting of root name + +TEST_F(LoggerNameTest, RootNameSetGet) { + const std::string name1 = "test1"; + const std::string name2 = "test2"; + + // Check that Set/Get works + setRootLoggerName(name1); + EXPECT_EQ(name1, getRootLoggerName()); + + // We could not test that the root logger name is initialized + // correctly (as there is one instance of it and we don't know + // when this test will be run) so to check that setName() actually + // does change the name, run the test again with a different name. + // + // (There was always the outside chance that the root logger name + // was initialized with name1 and that setName() has no effect.) + setRootLoggerName(name2); + EXPECT_EQ(name2, getRootLoggerName()); +} + +// Check expansion of name + +TEST_F(LoggerNameTest, ExpandLoggerName) { + const std::string ROOT = "example"; + const std::string NAME = "something"; + const std::string FULL_NAME = ROOT + "." + NAME; + + setRootLoggerName(ROOT); + EXPECT_EQ(ROOT, expandLoggerName(ROOT)); + EXPECT_EQ(FULL_NAME, expandLoggerName(NAME)); + EXPECT_EQ(FULL_NAME, expandLoggerName(FULL_NAME)); +} + +// Checks that the default logger name is returned properly. +TEST_F(LoggerNameTest, default) { + EXPECT_EQ("kea", getDefaultRootLoggerName()); +} diff --git a/src/lib/log/tests/logger_specification_unittest.cc b/src/lib/log/tests/logger_specification_unittest.cc new file mode 100644 index 0000000..be9da6e --- /dev/null +++ b/src/lib/log/tests/logger_specification_unittest.cc @@ -0,0 +1,90 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <string> + +#include <gtest/gtest.h> + +#include <log/logger_specification.h> +#include <log/output_option.h> + +using namespace isc::log; +using namespace std; + +// Check default initialization. +TEST(LoggerSpecificationTest, DefaultInitialization) { + LoggerSpecification spec; + + EXPECT_EQ(string(""), spec.getName()); + EXPECT_EQ(isc::log::INFO, spec.getSeverity()); + EXPECT_EQ(0, spec.getDbglevel()); + EXPECT_FALSE(spec.getAdditive()); + EXPECT_EQ(0, spec.optionCount()); +} + +// Non-default initialization +TEST(LoggerSpecificationTest, Initialization) { + LoggerSpecification spec("alpha", isc::log::ERROR, 42, true); + + EXPECT_EQ(string("alpha"), spec.getName()); + EXPECT_EQ(isc::log::ERROR, spec.getSeverity()); + EXPECT_EQ(42, spec.getDbglevel()); + EXPECT_TRUE(spec.getAdditive()); + EXPECT_EQ(0, spec.optionCount()); +} + +// Get/Set tests +TEST(LoggerSpecificationTest, SetGet) { + LoggerSpecification spec; + + spec.setName("gamma"); + EXPECT_EQ(string("gamma"), spec.getName()); + + spec.setSeverity(isc::log::FATAL); + EXPECT_EQ(isc::log::FATAL, spec.getSeverity()); + + spec.setDbglevel(7); + EXPECT_EQ(7, spec.getDbglevel()); + + spec.setAdditive(true); + EXPECT_TRUE(spec.getAdditive()); + + // Should not affect option count + EXPECT_EQ(0, spec.optionCount()); +} + +// Check option setting +TEST(LoggerSpecificationTest, AddOption) { + OutputOption option1; + option1.destination = OutputOption::DEST_FILE; + option1.filename = "/tmp/example.log"; + option1.maxsize = 123456; + + OutputOption option2; + option2.destination = OutputOption::DEST_SYSLOG; + option2.facility = "LOCAL7"; + + LoggerSpecification spec; + spec.addOutputOption(option1); + spec.addOutputOption(option2); + EXPECT_EQ(2, spec.optionCount()); + + // Iterate through them + LoggerSpecification::const_iterator i = spec.begin(); + + EXPECT_EQ(OutputOption::DEST_FILE, i->destination); + EXPECT_EQ(string("/tmp/example.log"), i->filename); + EXPECT_EQ(123456, i->maxsize); + + ++i; + EXPECT_EQ(OutputOption::DEST_SYSLOG, i->destination); + EXPECT_EQ(string("LOCAL7"), i->facility); + + ++i; + EXPECT_TRUE(i == spec.end()); +} diff --git a/src/lib/log/tests/logger_support_unittest.cc b/src/lib/log/tests/logger_support_unittest.cc new file mode 100644 index 0000000..3f2943c --- /dev/null +++ b/src/lib/log/tests/logger_support_unittest.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <gtest/gtest.h> +#include <log/logger_support.h> +#include <log/log_messages.h> + +using namespace isc::log; + +class LoggerSupportTest : public ::testing::Test { +protected: + LoggerSupportTest() { + // Logger initialization is done in main(). As logging tests may + // alter the default logging output, it is reset here. + setDefaultLoggingOutput(); + } + ~LoggerSupportTest() { + } +}; + +// Check that the initialized flag can be manipulated. This is a bit chicken- +// -and-egg: we want to reset to the flag to the original value at the end +// of the test, so use the functions to do that. But we are trying to check +// that these functions in fact work. + +TEST_F(LoggerSupportTest, InitializedFlag) { + bool current_flag = isLoggingInitialized(); + + // check we can flip the flag. + setLoggingInitialized(!current_flag); + EXPECT_NE(current_flag, isLoggingInitialized()); + setLoggingInitialized(!isLoggingInitialized()); + EXPECT_EQ(current_flag, isLoggingInitialized()); + + // Check we can set it to explicit values (tests that a call to the "set" + // function does not just flip the flag). + setLoggingInitialized(false); + EXPECT_FALSE(isLoggingInitialized()); + setLoggingInitialized(false); + EXPECT_FALSE(isLoggingInitialized()); + + setLoggingInitialized(true); + EXPECT_TRUE(isLoggingInitialized()); + setLoggingInitialized(true); + EXPECT_TRUE(isLoggingInitialized()); + + // Reset to original value + setLoggingInitialized(current_flag); +} + +// Check that a logger will throw an exception if logging has not been +// initialized. + +TEST_F(LoggerSupportTest, LoggingInitializationCheck) { + + // Assert that logging has been initialized (it should be in main()). + bool current_flag = isLoggingInitialized(); + EXPECT_TRUE(current_flag); + + // Flag that it has not been initialized and declare a logger. Any logging + // operation should then throw. + setLoggingInitialized(false); + isc::log::Logger test_logger("test"); + + EXPECT_THROW(test_logger.isDebugEnabled(), LoggingNotInitialized); + EXPECT_THROW(test_logger.info(LOG_INPUT_OPEN_FAIL), LoggingNotInitialized); + + // ... and check that they work when logging is initialized. + setLoggingInitialized(true); + EXPECT_NO_THROW(test_logger.isDebugEnabled()); + EXPECT_NO_THROW(test_logger.info(LOG_INPUT_OPEN_FAIL).arg("foo").arg("bar")); +} diff --git a/src/lib/log/tests/logger_unittest.cc b/src/lib/log/tests/logger_unittest.cc new file mode 100644 index 0000000..cc2fb95 --- /dev/null +++ b/src/lib/log/tests/logger_unittest.cc @@ -0,0 +1,508 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <gtest/gtest.h> + +#include <util/unittests/resource.h> +#include <util/unittests/check_valgrind.h> + +#include <log/logger.h> +#include <log/logger_manager.h> +#include <log/logger_name.h> +#include <log/logger_support.h> +#include <log/log_messages.h> +#include <log/interprocess/interprocess_sync_file.h> +#include <log/output_option.h> +#include <log/tests/log_test_messages.h> + +#include <iostream> +#include <string> + +using namespace isc; +using namespace isc::log; +using namespace std; + +/// \brief Logger Test +/// +/// As the logger is only a shell around the implementation, this tests also +/// checks the logger implementation class as well. + +class LoggerTest : public ::testing::Test { +public: + LoggerTest() { + // Initialize logging before each test, even if it is already done in main(). + isc::log::initLogger(); + } + ~LoggerTest() { + LoggerManager::reset(); + } +}; + +// Check version + +TEST_F(LoggerTest, Version) { + EXPECT_NO_THROW(Logger::getVersion()); +} + +// Checks that the logger is named correctly. + +TEST_F(LoggerTest, Name) { + + // Create a logger + Logger logger("alpha"); + + // ... and check the name + EXPECT_EQ(getRootLoggerName() + string(".alpha"), logger.getName()); +} + +// This test attempts to get two instances of a logger with the same name +// and checks that they are in fact the same logger. + +TEST_F(LoggerTest, GetLogger) { + + const char* name1 = "alpha"; + const char* name2 = "beta"; + + // Instantiate two loggers that should be the same + Logger logger1(name1); + Logger logger2(name1); + // And check they equal + EXPECT_TRUE(logger1 == logger2); + + // Instantiate another logger with another name and check that it + // is different to the previously instantiated ones. + Logger logger3(name2); + EXPECT_FALSE(logger1 == logger3); +} + +// Check that the logger levels are get set properly. + +TEST_F(LoggerTest, Severity) { + + // Create a logger + Logger logger("alpha"); + + // Now check the levels + logger.setSeverity(isc::log::NONE); + EXPECT_EQ(isc::log::NONE, logger.getSeverity()); + + logger.setSeverity(isc::log::FATAL); + EXPECT_EQ(isc::log::FATAL, logger.getSeverity()); + + logger.setSeverity(isc::log::ERROR); + EXPECT_EQ(isc::log::ERROR, logger.getSeverity()); + + logger.setSeverity(isc::log::WARN); + EXPECT_EQ(isc::log::WARN, logger.getSeverity()); + + logger.setSeverity(isc::log::INFO); + EXPECT_EQ(isc::log::INFO, logger.getSeverity()); + + logger.setSeverity(isc::log::DEBUG); + EXPECT_EQ(isc::log::DEBUG, logger.getSeverity()); + + logger.setSeverity(isc::log::DEFAULT); + EXPECT_EQ(isc::log::DEFAULT, logger.getSeverity()); +} + +// Check that the debug level is set correctly. + +TEST_F(LoggerTest, DebugLevels) { + + // Create a logger + Logger logger("alpha"); + + // Debug level should be 0 if not at debug severity + logger.setSeverity(isc::log::NONE, 20); + EXPECT_EQ(0, logger.getDebugLevel()); + + logger.setSeverity(isc::log::INFO, 42); + EXPECT_EQ(0, logger.getDebugLevel()); + + // Should be the value set if the severity is set to DEBUG though. + logger.setSeverity(isc::log::DEBUG, 32); + EXPECT_EQ(32, logger.getDebugLevel()); + + logger.setSeverity(isc::log::DEBUG, 97); + EXPECT_EQ(97, logger.getDebugLevel()); + + // Try the limits + logger.setSeverity(isc::log::DEBUG, -1); + EXPECT_EQ(0, logger.getDebugLevel()); + + logger.setSeverity(isc::log::DEBUG, 0); + EXPECT_EQ(0, logger.getDebugLevel()); + + logger.setSeverity(isc::log::DEBUG, 1); + EXPECT_EQ(1, logger.getDebugLevel()); + + logger.setSeverity(isc::log::DEBUG, 98); + EXPECT_EQ(98, logger.getDebugLevel()); + + logger.setSeverity(isc::log::DEBUG, 99); + EXPECT_EQ(99, logger.getDebugLevel()); + + logger.setSeverity(isc::log::DEBUG, 100); + EXPECT_EQ(99, logger.getDebugLevel()); +} + +// Check that changing the parent and child severity does not affect the +// other. + +TEST_F(LoggerTest, SeverityInheritance) { + + // Create two loggers. We cheat here as we know that the underlying + // implementation will set a parent-child relationship if the loggers + // are named <parent> and <parent>.<child>. + Logger parent("alpha"); + Logger child("alpha.beta"); + + // By default, newly created loggers should have a level of DEFAULT + // (i.e. default to parent) + EXPECT_EQ(isc::log::DEFAULT, parent.getSeverity()); + EXPECT_EQ(isc::log::DEFAULT, child.getSeverity()); + + // Set the severity of the parent to debug and check what is + // reported by the child. + parent.setSeverity(isc::log::DEBUG, 42); + EXPECT_EQ(42, parent.getDebugLevel()); + EXPECT_EQ(0, child.getDebugLevel()); + EXPECT_EQ(42, child.getEffectiveDebugLevel()); + + // Setting the child to DEBUG severity should set its own + // debug level. + child.setSeverity(isc::log::DEBUG, 53); + EXPECT_EQ(53, child.getDebugLevel()); + EXPECT_EQ(53, child.getEffectiveDebugLevel()); + + // If the child severity is set to something other than DEBUG, + // the debug level should be reported as 0. + child.setSeverity(isc::log::ERROR); + EXPECT_EQ(0, child.getDebugLevel()); + EXPECT_EQ(0, child.getEffectiveDebugLevel()); +} + +// Check that changing the parent and child debug level does not affect +// the other. + +TEST_F(LoggerTest, DebugLevelInheritance) { + + // Create two loggers. We cheat here as we know that the underlying + // implementation will set a parent-child relationship if the loggers + // are named <parent> and <parent>.<child>. + Logger parent("alpha"); + Logger child("alpha.beta"); + + // By default, newly created loggers should have a level of DEFAULT + // (i.e. default to parent) + EXPECT_EQ(isc::log::DEFAULT, parent.getSeverity()); + EXPECT_EQ(isc::log::DEFAULT, child.getSeverity()); + + // Set the severity of the child to something other than the default - + // check it changes and that of the parent does not. + child.setSeverity(isc::log::INFO); + EXPECT_EQ(isc::log::DEFAULT, parent.getSeverity()); + EXPECT_EQ(isc::log::INFO, child.getSeverity()); + + // Reset the child severity and set that of the parent + child.setSeverity(isc::log::DEFAULT); + EXPECT_EQ(isc::log::DEFAULT, parent.getSeverity()); + EXPECT_EQ(isc::log::DEFAULT, child.getSeverity()); + parent.setSeverity(isc::log::WARN); + EXPECT_EQ(isc::log::WARN, parent.getSeverity()); + EXPECT_EQ(isc::log::DEFAULT, child.getSeverity()); +} + +// Check that severity is inherited. + +TEST_F(LoggerTest, EffectiveSeverityInheritance) { + + // Create two loggers. We cheat here as we know that the underlying + // implementation will set a parent-child relationship if the loggers + // are named <parent> and <parent>.<child>. + Logger parent("test6"); + Logger child("test6.beta"); + + // By default, newly created loggers should have a level of DEFAULT + // (i.e. default to parent) and the root should have a default severity + // of INFO. However, the latter is only enforced when created by the + // RootLogger class, so explicitly set it for the parent for now. + parent.setSeverity(isc::log::INFO); + EXPECT_EQ(isc::log::INFO, parent.getEffectiveSeverity()); + + EXPECT_EQ(isc::log::DEFAULT, child.getSeverity()); + EXPECT_EQ(isc::log::INFO, child.getEffectiveSeverity()); + + // Set the severity of the child to something other than the default - + // check it changes and that of the parent does not. + child.setSeverity(isc::log::FATAL); + EXPECT_EQ(isc::log::INFO, parent.getEffectiveSeverity()); + EXPECT_EQ(isc::log::FATAL, child.getEffectiveSeverity()); + + // Reset the child severity and check again. + child.setSeverity(isc::log::DEFAULT); + EXPECT_EQ(isc::log::INFO, parent.getEffectiveSeverity()); + EXPECT_EQ(isc::log::INFO, child.getEffectiveSeverity()); + + // Change the parent's severity and check it is reflects in the child. + parent.setSeverity(isc::log::WARN); + EXPECT_EQ(isc::log::WARN, parent.getEffectiveSeverity()); + EXPECT_EQ(isc::log::WARN, child.getEffectiveSeverity()); +} + +// Test the isXxxxEnabled methods. + +TEST_F(LoggerTest, IsXxxEnabled) { + + Logger logger("test7"); + + logger.setSeverity(isc::log::INFO); + EXPECT_FALSE(logger.isDebugEnabled()); + EXPECT_TRUE(logger.isInfoEnabled()); + EXPECT_TRUE(logger.isWarnEnabled()); + EXPECT_TRUE(logger.isErrorEnabled()); + EXPECT_TRUE(logger.isFatalEnabled()); + + logger.setSeverity(isc::log::WARN); + EXPECT_FALSE(logger.isDebugEnabled()); + EXPECT_FALSE(logger.isInfoEnabled()); + EXPECT_TRUE(logger.isWarnEnabled()); + EXPECT_TRUE(logger.isErrorEnabled()); + EXPECT_TRUE(logger.isFatalEnabled()); + + logger.setSeverity(isc::log::ERROR); + EXPECT_FALSE(logger.isDebugEnabled()); + EXPECT_FALSE(logger.isInfoEnabled()); + EXPECT_FALSE(logger.isWarnEnabled()); + EXPECT_TRUE(logger.isErrorEnabled()); + EXPECT_TRUE(logger.isFatalEnabled()); + + logger.setSeverity(isc::log::FATAL); + EXPECT_FALSE(logger.isDebugEnabled()); + EXPECT_FALSE(logger.isInfoEnabled()); + EXPECT_FALSE(logger.isWarnEnabled()); + EXPECT_FALSE(logger.isErrorEnabled()); + EXPECT_TRUE(logger.isFatalEnabled()); + + // Check various debug levels + + logger.setSeverity(isc::log::DEBUG); + EXPECT_TRUE(logger.isDebugEnabled()); + EXPECT_TRUE(logger.isInfoEnabled()); + EXPECT_TRUE(logger.isWarnEnabled()); + EXPECT_TRUE(logger.isErrorEnabled()); + EXPECT_TRUE(logger.isFatalEnabled()); + + logger.setSeverity(isc::log::DEBUG, 45); + EXPECT_TRUE(logger.isDebugEnabled()); + EXPECT_TRUE(logger.isInfoEnabled()); + EXPECT_TRUE(logger.isWarnEnabled()); + EXPECT_TRUE(logger.isErrorEnabled()); + EXPECT_TRUE(logger.isFatalEnabled()); + + // Create a child logger with no severity set, and check that it reflects + // the severity of the parent logger. + + Logger child("test7.child"); + logger.setSeverity(isc::log::FATAL); + EXPECT_FALSE(child.isDebugEnabled()); + EXPECT_FALSE(child.isInfoEnabled()); + EXPECT_FALSE(child.isWarnEnabled()); + EXPECT_FALSE(child.isErrorEnabled()); + EXPECT_TRUE(child.isFatalEnabled()); + + logger.setSeverity(isc::log::INFO); + EXPECT_FALSE(child.isDebugEnabled()); + EXPECT_TRUE(child.isInfoEnabled()); + EXPECT_TRUE(child.isWarnEnabled()); + EXPECT_TRUE(child.isErrorEnabled()); + EXPECT_TRUE(child.isFatalEnabled()); +} + +// Within the Debug level there are 100 debug levels. Test that we know +// when to issue a debug message. + +TEST_F(LoggerTest, IsDebugEnabledLevel) { + + Logger logger("test8"); + + int MID_LEVEL = (MIN_DEBUG_LEVEL + MAX_DEBUG_LEVEL) / 2; + + logger.setSeverity(isc::log::DEBUG); + EXPECT_TRUE(logger.isDebugEnabled(MIN_DEBUG_LEVEL)); + EXPECT_FALSE(logger.isDebugEnabled(MID_LEVEL)); + EXPECT_FALSE(logger.isDebugEnabled(MAX_DEBUG_LEVEL)); + + logger.setSeverity(isc::log::DEBUG, MIN_DEBUG_LEVEL); + EXPECT_TRUE(logger.isDebugEnabled(MIN_DEBUG_LEVEL)); + EXPECT_FALSE(logger.isDebugEnabled(MID_LEVEL)); + EXPECT_FALSE(logger.isDebugEnabled(MAX_DEBUG_LEVEL)); + + logger.setSeverity(isc::log::DEBUG, MID_LEVEL); + EXPECT_TRUE(logger.isDebugEnabled(MIN_DEBUG_LEVEL)); + EXPECT_TRUE(logger.isDebugEnabled(MID_LEVEL - 1)); + EXPECT_TRUE(logger.isDebugEnabled(MID_LEVEL)); + EXPECT_FALSE(logger.isDebugEnabled(MID_LEVEL + 1)); + EXPECT_FALSE(logger.isDebugEnabled(MAX_DEBUG_LEVEL)); + + logger.setSeverity(isc::log::DEBUG, MAX_DEBUG_LEVEL); + EXPECT_TRUE(logger.isDebugEnabled(MIN_DEBUG_LEVEL)); + EXPECT_TRUE(logger.isDebugEnabled(MID_LEVEL)); + EXPECT_TRUE(logger.isDebugEnabled(MAX_DEBUG_LEVEL)); +} + +// Check that loggers with invalid names give an error. + +TEST_F(LoggerTest, LoggerNameLength) { + // Null name + EXPECT_THROW(Logger(NULL), LoggerNameNull); + + // Declare space for the logger name. The length of names checked + // will range from 0 through MAX_LOGGER_NAME_SIZE + 1: to allow for + // the trailing null, at least one more byte than the longest name size + // must be reserved. + char name[Logger::MAX_LOGGER_NAME_SIZE + 2]; + + // Zero-length name should throw an exception + name[0] = '\0'; + EXPECT_THROW({ + Logger dummy(name); + }, LoggerNameError); + + // Work through all valid names. + for (size_t i = 0; i < Logger::MAX_LOGGER_NAME_SIZE; ++i) { + + // Append a character to the name and check that a logger with that + // name can be created without throwing an exception. + name[i] = 'X'; + name[i + 1] = '\0'; + EXPECT_NO_THROW({ + Logger dummy(name); + }) << "Size of logger name is " << (i + 1); + } + + // ... and check that an overly long name throws an exception. + name[Logger::MAX_LOGGER_NAME_SIZE] = 'X'; + name[Logger::MAX_LOGGER_NAME_SIZE + 1] = '\0'; + EXPECT_THROW({ + Logger dummy(name); + }, LoggerNameError); + +} + +TEST_F(LoggerTest, setInterprocessSync) { + // Create a logger + Logger logger("alpha"); + + EXPECT_THROW(logger.setInterprocessSync(NULL), BadInterprocessSync); +} + +class MockSync : public isc::log::interprocess::InterprocessSync { +public: + /// \brief Constructor + MockSync(const std::string& component_name) : + InterprocessSync(component_name), was_locked_(false), + was_unlocked_(false) + {} + + bool wasLocked() const { + return (was_locked_); + } + + bool wasUnlocked() const { + return (was_unlocked_); + } + +protected: + bool lock() { + was_locked_ = true; + return (true); + } + + bool tryLock() { + return (true); + } + + bool unlock() { + was_unlocked_ = true; + return (true); + } + +private: + bool was_locked_; + bool was_unlocked_; +}; + +// Checks that the logger logs exclusively and other Kea components +// are locked out. + +TEST_F(LoggerTest, Lock) { + // Create a logger + Logger logger("alpha"); + + // Setup our own mock sync object so that we can intercept the lock + // call and check if a lock has been taken. + MockSync* sync = new MockSync("logger"); + logger.setInterprocessSync(sync); + + // Log a message and put things into play. + logger.setSeverity(isc::log::INFO, 100); + logger.info(LOG_LOCK_TEST_MESSAGE); + + EXPECT_TRUE(sync->wasLocked()); + EXPECT_TRUE(sync->wasUnlocked()); +} + +// Checks that hasAppender() reports +TEST_F(LoggerTest, HasAppender) { + // Create a logger. + Logger logger("logger"); + + // By default, loggers have a file appender to /dev/null. + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_CONSOLE)); + EXPECT_TRUE(logger.hasAppender(OutputOption::DEST_FILE)); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_SYSLOG)); + + // -- Create some specifications. -- + + OutputOption console; + console.destination = OutputOption::DEST_CONSOLE; + LoggerSpecification spec_console("logger"); + spec_console.addOutputOption(console); + + OutputOption file; + file.destination = OutputOption::DEST_FILE; + file.filename = "/dev/null"; + LoggerSpecification spec_file("logger"); + spec_file.addOutputOption(file); + + OutputOption syslog; + syslog.destination = OutputOption::DEST_SYSLOG; + LoggerSpecification spec_syslog("logger"); + spec_syslog.addOutputOption(syslog); + + LoggerManager manager; + + // Check console. + manager.process(spec_console); + EXPECT_TRUE(logger.hasAppender(OutputOption::DEST_CONSOLE)); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_FILE)); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_SYSLOG)); + + // Check file. + manager.process(spec_file); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_CONSOLE)); + EXPECT_TRUE(logger.hasAppender(OutputOption::DEST_FILE)); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_SYSLOG)); + + // Check syslog. + manager.process(spec_syslog); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_CONSOLE)); + EXPECT_FALSE(logger.hasAppender(OutputOption::DEST_FILE)); + EXPECT_TRUE(logger.hasAppender(OutputOption::DEST_SYSLOG)); +} diff --git a/src/lib/log/tests/message_dictionary_unittest.cc b/src/lib/log/tests/message_dictionary_unittest.cc new file mode 100644 index 0000000..8613393 --- /dev/null +++ b/src/lib/log/tests/message_dictionary_unittest.cc @@ -0,0 +1,219 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <cstddef> +#include <string> +#include <gtest/gtest.h> +#include <log/message_dictionary.h> +#include <log/message_initializer.h> +#include <log/message_types.h> + +using namespace isc; +using namespace isc::log; +using namespace std; + +// set up another message initializer. This will add a symbol found in the +// logging library and a symbol not found in the logging library. When the +// global dictionary is loaded, the former should be marked as a duplicate +// and the latter should be present. + +namespace { +const char* values[] = { + // This message for DUPLICATE_NAMESPACE must be copied from + // ../log_messages.mes; otherwise logger check might fail. + "LOG_DUPLICATE_NAMESPACE", "line %1: duplicate $NAMESPACE directive found", + "NEWSYM", "new symbol added", + NULL +}; + +MessageInitializer init(values); +} + +class MessageDictionaryTest : public ::testing::Test { +protected: + MessageDictionaryTest() : + alpha_id("ALPHA"), alpha_text("This is alpha"), + beta_id("BETA"), beta_text("This is beta"), + gamma_id("GAMMA"), gamma_text("This is gamma") + { + } + + MessageID alpha_id; + std::string alpha_text; + MessageID beta_id; + std::string beta_text; + MessageID gamma_id; + std::string gamma_text; + +}; + +// Check that adding messages works + +TEST_F(MessageDictionaryTest, Add) { + MessageDictionary dictionary; + EXPECT_EQ(0, dictionary.size()); + + // Add a few messages and check that we can look them up and that there is + // nothing in the overflow vector. + EXPECT_TRUE(dictionary.add(alpha_id, alpha_text)); + EXPECT_TRUE(dictionary.add(beta_id, beta_text)); + EXPECT_EQ(2, dictionary.size()); + + EXPECT_EQ(alpha_text, dictionary.getText(alpha_id)); + EXPECT_EQ(beta_text, dictionary.getText(beta_id)); + EXPECT_EQ(string(""), dictionary.getText(gamma_id)); + + // Try adding a duplicate with different text. It should not replace the + // current text and the ID should be in the overflow section. + EXPECT_FALSE(dictionary.add(alpha_id, gamma_text)); + EXPECT_EQ(2, dictionary.size()); +} + +// Check that replacing messages works. + +TEST_F(MessageDictionaryTest, Replace) { + MessageDictionary dictionary; + EXPECT_EQ(0, dictionary.size()); + + // Try to replace a non-existent message + EXPECT_FALSE(dictionary.replace(alpha_id, alpha_text)); + EXPECT_EQ(0, dictionary.size()); + + // Add a couple of messages. + EXPECT_TRUE(dictionary.add(alpha_id, alpha_text)); + EXPECT_TRUE(dictionary.add(beta_id, beta_text)); + EXPECT_EQ(2, dictionary.size()); + + // Replace an existing message + EXPECT_TRUE(dictionary.replace(alpha_id, gamma_text)); + EXPECT_EQ(2, dictionary.size()); + EXPECT_EQ(gamma_text, dictionary.getText(alpha_id)); + + // ... and replace non-existent message (but now the dictionary has some + // items in it). + EXPECT_FALSE(dictionary.replace(gamma_id, alpha_text)); + EXPECT_EQ(2, dictionary.size()); + EXPECT_EQ(string(""), dictionary.getText(gamma_id)); +} + +// Check that removing message works. + +TEST_F(MessageDictionaryTest, erase) { + MessageDictionary dictionary; + ASSERT_NO_THROW(dictionary.erase(alpha_id, alpha_text)); + ASSERT_EQ(0, dictionary.size()); + + // Add a couple of messages. + EXPECT_TRUE(dictionary.add(alpha_id, alpha_text)); + EXPECT_TRUE(dictionary.add(beta_id, beta_text)); + // There is no sense to continue if messages haven't been added. + ASSERT_EQ(2, dictionary.size()); + + // Remove one with the existing ID, but non-matching text. It + // should not remove any message. + EXPECT_FALSE(dictionary.erase(beta_id, alpha_text)); + + // Now, remove the message with matching ID and text. + EXPECT_TRUE(dictionary.erase(beta_id, beta_text)); + EXPECT_EQ(1, dictionary.size()); + // The other entry should still exist. + EXPECT_EQ(alpha_text, dictionary.getText(alpha_id)); + + // And remove the other message. + EXPECT_TRUE(dictionary.erase(alpha_id, alpha_text)); + EXPECT_EQ(0, dictionary.size()); +} + +// Load test + +TEST_F(MessageDictionaryTest, LoadTest) { + static const char* data1[] = { + "ALPHA", "This is alpha", + "BETA", "This is beta", + "GAMMA", "This is gamma", + NULL + }; + + static const char* data2[] = { + "DELTA", "This is delta", + "EPSILON", "This is epsilon", + "ETA", NULL + }; + + MessageDictionary dictionary1; + EXPECT_EQ(0, dictionary1.size()); + + // Load a dictionary1. + vector<string> duplicates = dictionary1.load(data1); + EXPECT_EQ(3, dictionary1.size()); + EXPECT_EQ(string(data1[1]), dictionary1.getText(data1[0])); + EXPECT_EQ(string(data1[3]), dictionary1.getText(data1[2])); + EXPECT_EQ(string(data1[5]), dictionary1.getText(data1[4])); + EXPECT_EQ(0, duplicates.size()); + + // Attempt an overwrite + duplicates = dictionary1.load(data1); + EXPECT_EQ(3, dictionary1.size()); + EXPECT_EQ(3, duplicates.size()); + + // Try a new dictionary but with an incorrect number of elements + MessageDictionary dictionary2; + EXPECT_EQ(0, dictionary2.size()); + + duplicates = dictionary2.load(data2); + EXPECT_EQ(2, dictionary2.size()); + EXPECT_EQ(string(data2[1]), dictionary2.getText(data2[0])); + EXPECT_EQ(string(data2[3]), dictionary2.getText(data2[2])); + EXPECT_EQ(string(""), dictionary2.getText(data2[4])); + EXPECT_EQ(0, duplicates.size()); +} + +// Check for some non-existent items + +TEST_F(MessageDictionaryTest, Lookups) { + static const char* data[] = { + "ALPHA", "This is alpha", + "BETA", "This is beta", + "GAMMA", "This is gamma", + NULL + }; + + MessageDictionary dictionary; + vector<string> duplicates = dictionary.load(data); + EXPECT_EQ(3, dictionary.size()); + EXPECT_EQ(0, duplicates.size()); + + // Valid lookups + EXPECT_EQ(string("This is alpha"), dictionary.getText("ALPHA")); + EXPECT_EQ(string("This is beta"), dictionary.getText("BETA")); + EXPECT_EQ(string("This is gamma"), dictionary.getText("GAMMA")); + + // ... and invalid ones + EXPECT_EQ(string(""), dictionary.getText("XYZZY")); + EXPECT_EQ(string(""), dictionary.getText("")); + EXPECT_EQ(string(""), dictionary.getText("\n\n\n")); +} + +// Check that the global dictionary is a singleton. + +TEST_F(MessageDictionaryTest, GlobalTest) { + const MessageDictionaryPtr& global = MessageDictionary::globalDictionary(); + const MessageDictionaryPtr& global2 = MessageDictionary::globalDictionary(); + EXPECT_TRUE(global2 == global); +} + +// Check that the global dictionary has detected the duplicate and the +// new symbol. + +TEST_F(MessageDictionaryTest, GlobalLoadTest) { + // There were duplicates but the vector should be cleared in init() now + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); + + string text = MessageDictionary::globalDictionary()->getText("NEWSYM"); + EXPECT_EQ(string("new symbol added"), text); +} diff --git a/src/lib/log/tests/message_initializer_1_unittest.cc b/src/lib/log/tests/message_initializer_1_unittest.cc new file mode 100644 index 0000000..c34139a --- /dev/null +++ b/src/lib/log/tests/message_initializer_1_unittest.cc @@ -0,0 +1,251 @@ +// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <log/message_dictionary.h> +#include <log/message_initializer.h> +#include <boost/lexical_cast.hpp> +#include <boost/scoped_ptr.hpp> +#include <gtest/gtest.h> +#include <string> + +using namespace isc; +using namespace isc::log; +using namespace std; + +// Declare a set of messages to go into the global dictionary. + +namespace { +const char* values1[] = { + "GLOBAL1", "global message one", + "GLOBAL2", "global message two", + NULL +}; + +const char* values2[] = { + "GLOBAL3", "global message three", + "GLOBAL4", "global message four", + NULL +}; + +const char* values3[] = { + "GLOBAL7", "global message seven", + "GLOBAL8", "global message eight", + NULL +}; + +const char* values4[] = { + "GLOBAL8", "global message eight", + "GLOBAL9", "global message nine", + NULL +}; + +/// @brief Scoped pointer to the @c MessageInitializer object. +typedef boost::scoped_ptr<MessageInitializer> MessageInitializerPtr; + +} + +// Statically initialize the global dictionary with those messages. Three sets +// are used to check that the declaration of separate initializer objects +// really does combine the messages. (The third set - declaring message IDs +// GLOBAL5 and GLOBAL6) is declared in the separately-compiled file, +// message_identifier_initializer_1a_unittest.cc.) + +const MessageInitializer init_message_initializer_unittest_1(values1); +const MessageInitializer init_message_initializer_unittest_2(values2); + +// Check that the global dictionary is initialized with the specified +// messages. + +namespace { +void +messageTest() { + static bool done = false; + + // Execute once. + if (done) { + return; + } else { + done = true; + } + + const MessageDictionaryPtr& global = MessageDictionary::globalDictionary(); + + // Pointers to the message arrays should have been stored, but none of the + // messages should yet be in the dictionary. + for (int i = 1; i <= 6; ++i) { + string symbol = string("GLOBAL") + boost::lexical_cast<std::string>(i); + EXPECT_EQ(string(""), global->getText(symbol)); + } + + // Load the dictionary - this should clear the message array pending count. + // (N.B. We do not check for a known value before the call, only that the + // value is not zero. This is because libraries against which the test + // is linked may have registered their own message arrays.) + EXPECT_NE(0, MessageInitializer::getPendingCount()); + MessageInitializer::loadDictionary(); + EXPECT_EQ(0, MessageInitializer::getPendingCount()); + + // ... and check the messages loaded. + EXPECT_EQ(string("global message one"), global->getText("GLOBAL1")); + EXPECT_EQ(string("global message two"), global->getText("GLOBAL2")); + EXPECT_EQ(string("global message three"), global->getText("GLOBAL3")); + EXPECT_EQ(string("global message four"), global->getText("GLOBAL4")); + EXPECT_EQ(string("global message five"), global->getText("GLOBAL5")); + EXPECT_EQ(string("global message six"), global->getText("GLOBAL6")); +} +} + +// Check that destroying the MessageInitializer causes the relevant +// messages to be removed from the dictionary. + +TEST(MessageInitializerTest1, dynamicLoadUnload) { + // Try first messageTest. + messageTest(); + + // Obtain the instance of the global dictionary. + const MessageDictionaryPtr& global = MessageDictionary::globalDictionary(); + + // Dynamically create the first initializer. + MessageInitializerPtr init1(new MessageInitializer(values3)); + EXPECT_EQ(1, MessageInitializer::getPendingCount()); + + // Dynamically create the second initializer. + MessageInitializerPtr init2(new MessageInitializer(values4)); + EXPECT_EQ(2, MessageInitializer::getPendingCount()); + + // Load messages from both initializers to the global dictionary. + MessageInitializer::loadDictionary(); + // There should be no pending messages. + EXPECT_EQ(0, MessageInitializer::getPendingCount()); + + // Make sure that the messages have been loaded. + EXPECT_EQ("global message seven", global->getText("GLOBAL7")); + EXPECT_EQ("global message eight", global->getText("GLOBAL8")); + EXPECT_EQ("global message nine", global->getText("GLOBAL9")); + + // Destroy the first initializer. The first message should be removed. + // The second message should not be removed because it is also held + // by another object. + init1.reset(); + EXPECT_TRUE(global->getText("GLOBAL7").empty()); + EXPECT_EQ("global message eight", global->getText("GLOBAL8")); + EXPECT_EQ("global message nine", global->getText("GLOBAL9")); + + // Destroy the second initializer. Now, all messages should be + // unregistered. + init2.reset(); + EXPECT_TRUE(global->getText("GLOBAL7").empty()); + EXPECT_TRUE(global->getText("GLOBAL8").empty()); + EXPECT_TRUE(global->getText("GLOBAL9").empty()); +} + +// Check that destroying the MessageInitializer removes pending messages. + +TEST(MessageInitializerTest1, dynamicUnloadPending) { + // Try first messageTest. + messageTest(); + + // Obtain the instance of the global dictionary. + const MessageDictionaryPtr& global = MessageDictionary::globalDictionary(); + + // Dynamically create the first initializer. + MessageInitializerPtr init1(new MessageInitializer(values3)); + ASSERT_EQ(1, MessageInitializer::getPendingCount()); + + // Create second initializer without committing the first set + // of messages to the dictionary. + MessageInitializerPtr init2(new MessageInitializer(values4)); + ASSERT_EQ(2, MessageInitializer::getPendingCount()); + + // Destroy the first initializer and make sure that the number of + // pending message sets drops to 1. + init1.reset(); + ASSERT_EQ(1, MessageInitializer::getPendingCount()); + + // Now destroy the second initializer and make sure that there are + // no pending messages. + init2.reset(); + ASSERT_EQ(0, MessageInitializer::getPendingCount()); + + init1.reset(new MessageInitializer(values3)); + ASSERT_EQ(1, MessageInitializer::getPendingCount()); + + // Load the messages to the dictionary and make sure there are no pending + // messages. + MessageInitializer::loadDictionary(); + EXPECT_EQ(0, MessageInitializer::getPendingCount()); + + // Create the second initializer. There should be one pending set of + // messages. + init2.reset(new MessageInitializer(values4)); + ASSERT_EQ(1, MessageInitializer::getPendingCount()); + + // Make sure that the messages defined by the first initializer + // are in the dictionary. + ASSERT_EQ("global message seven", global->getText("GLOBAL7")); + ASSERT_EQ("global message eight", global->getText("GLOBAL8")); + ASSERT_TRUE(global->getText("GLOBAL9").empty()); + + // Destroy the second initializer. There should be no pending messages + // now. + init2.reset(); + ASSERT_EQ(0, MessageInitializer::getPendingCount()); + + // Loading the messages should be no-op. + MessageInitializer::loadDictionary(); + ASSERT_EQ(0, MessageInitializer::getPendingCount()); + + // Make sure that the messages loaded from the first initializer + // are not affected. + ASSERT_EQ("global message seven", global->getText("GLOBAL7")); + ASSERT_EQ("global message eight", global->getText("GLOBAL8")); + ASSERT_TRUE(global->getText("GLOBAL9").empty()); + + // And remove them. + init1.reset(); + EXPECT_TRUE(global->getText("GLOBAL7").empty()); + EXPECT_TRUE(global->getText("GLOBAL8").empty()); + EXPECT_TRUE(global->getText("GLOBAL9").empty()); +} + +TEST(MessageInitializerTest1, duplicates) { + // Try first messageTest. + messageTest(); + + // Original set should not have dupes + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); + + // This just defines 1, but we'll add it a number of times + const char* dupe[] = { + "DUPE", "dupe", + NULL + }; + const MessageInitializer init_message_initializer_unittest_1(dupe); + const MessageInitializer init_message_initializer_unittest_2(dupe); + + MessageInitializer::loadDictionary(); + // Should be a dupe now + ASSERT_EQ(1, MessageInitializer::getDuplicates().size()); + + // clear them + MessageInitializer::clearDuplicates(); + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); + + // Do it again to make sure, let's explicitly provide false now + const MessageInitializer init_message_initializer_unittest_3(dupe); + MessageInitializer::loadDictionary(false); + ASSERT_EQ(1, MessageInitializer::getDuplicates().size()); + + // Loading with ignore_duplicates=true should result in no (reported) + // dupes + MessageInitializer::clearDuplicates(); + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); + const MessageInitializer init_message_initializer_unittest_4(dupe); + MessageInitializer::loadDictionary(true); + ASSERT_EQ(0, MessageInitializer::getDuplicates().size()); +} diff --git a/src/lib/log/tests/message_initializer_1a_unittest.cc b/src/lib/log/tests/message_initializer_1a_unittest.cc new file mode 100644 index 0000000..3e2b86b --- /dev/null +++ b/src/lib/log/tests/message_initializer_1a_unittest.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// The sole purpose of this file is to provide a set of message definitions +// in a separate compilation unit from the one in which their presence is +// checked. This tests that merely declaring the MessageInitializer object +// is enough to include the definitions in the global dictionary. + +#include <config.h> + +#include <log/message_initializer.h> + +using namespace isc::log; + +// Declare a set of messages to go into the global dictionary. + +namespace { + +const char* values3[] = { + "GLOBAL5", "global message five", + "GLOBAL6", "global message six", + NULL +}; + +} + +// Register the messages for loading into the global dictionary +const MessageInitializer init_message_initializer_unittest_3(values3); diff --git a/src/lib/log/tests/message_reader_unittest.cc b/src/lib/log/tests/message_reader_unittest.cc new file mode 100644 index 0000000..4dd6435 --- /dev/null +++ b/src/lib/log/tests/message_reader_unittest.cc @@ -0,0 +1,269 @@ +// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <algorithm> +#include <string> +#include <gtest/gtest.h> + +#include <log/log_messages.h> +#include <log/message_dictionary.h> +#include <log/message_exception.h> +#include <log/message_reader.h> + +using namespace isc; +using namespace isc::log; +using namespace std; + +class MessageReaderTest : public ::testing::Test { +protected: + MessageReaderTest() : dictionary_(), reader_() + { + dictionary_ = new MessageDictionary(); + reader_.setDictionary(dictionary_); + } + + ~MessageReaderTest() { + delete dictionary_; + } + + MessageDictionary* dictionary_; // Dictionary to add messages to + MessageReader reader_; // Default reader object +}; + + +// Check the get/set dictionary calls (using a local reader and dictionary). + +TEST_F(MessageReaderTest, GetSetDictionary) { + MessageReader reader; + EXPECT_TRUE(reader.getDictionary() == NULL); + + MessageDictionary dictionary; + reader.setDictionary(&dictionary); + EXPECT_EQ(&dictionary, reader.getDictionary()); +} + +// Check for parsing blank lines and comments. These should not add to the +// dictionary and each parse should return success. + +TEST_F(MessageReaderTest, BlanksAndComments) { + + // Ensure that the dictionary is empty. + EXPECT_EQ(0, dictionary_->size()); + + // Add a number of blank lines and comments and check that (a) they are + // parsed successfully ... + EXPECT_NO_THROW(reader_.processLine("")); + EXPECT_NO_THROW(reader_.processLine(" ")); + EXPECT_NO_THROW(reader_.processLine(" \n ")); + EXPECT_NO_THROW(reader_.processLine("# This is a comment")); + EXPECT_NO_THROW(reader_.processLine("\t\t # Another comment")); + EXPECT_NO_THROW(reader_.processLine(" A description line")); + EXPECT_NO_THROW(reader_.processLine("# A comment")); + EXPECT_NO_THROW(reader_.processLine(" +# A description line")); + + // ... and (b) nothing gets added to either the map or the not-added section. + EXPECT_EQ(0, dictionary_->size()); + vector<string> not_added = reader_.getNotAdded(); + EXPECT_EQ(0, not_added.size()); +} + + +// Local test to check that processLine generates the right exception. + +void +processLineException(MessageReader& reader, const char* what, + const MessageID& expected) { + + try { + reader.processLine(what); + FAIL() << "MessageReader::processLine() should throw an exception " << + " with message ID " << expected << " for '" << what << "'\n"; + } catch (const MessageException& e) { + EXPECT_EQ(boost::lexical_cast<string>(expected), + boost::lexical_cast<string>(e.id())); + } catch (...) { + FAIL() << "Unknown exception thrown by MessageReader::processLine()\n"; + } +} + +// Check that it recognizes invalid directives + +TEST_F(MessageReaderTest, InvalidDirectives) { + + // Check that a "$" with nothing else generates an error + processLineException(reader_, "$", LOG_UNRECOGNIZED_DIRECTIVE); + processLineException(reader_, "$xyz", LOG_UNRECOGNIZED_DIRECTIVE); +} + +// Check that it can parse a prefix + +TEST_F(MessageReaderTest, Prefix) { + + // Check that no $PREFIX is present + EXPECT_EQ(string(""), reader_.getPrefix()); + + // Check that a $PREFIX directive with no argument is OK + EXPECT_NO_THROW(reader_.processLine("$PREFIX")); + + // Check a $PREFIX with multiple arguments is invalid + processLineException(reader_, "$prefix A B", LOG_PREFIX_EXTRA_ARGS); + + // Prefixes should be alphanumeric (with underscores) and not start + // with a number. + processLineException(reader_, "$prefix ab[cd", LOG_PREFIX_INVALID_ARG); + processLineException(reader_, "$prefix 123", LOG_PREFIX_INVALID_ARG); + processLineException(reader_, "$prefix 1ABC", LOG_PREFIX_INVALID_ARG); + + // A valid prefix should be accepted + EXPECT_NO_THROW(reader_.processLine("$PREFIX dlm__")); + EXPECT_EQ(string("dlm__"), reader_.getPrefix()); + + // And check that the parser fails on invalid prefixes... + processLineException(reader_, "$prefix 1ABC", LOG_PREFIX_INVALID_ARG); + + // Check that we can clear the prefix as well + reader_.clearPrefix(); + EXPECT_EQ(string(""), reader_.getPrefix()); + + EXPECT_NO_THROW(reader_.processLine("$PREFIX dlm__")); + EXPECT_EQ(string("dlm__"), reader_.getPrefix()); + EXPECT_NO_THROW(reader_.processLine("$PREFIX")); + EXPECT_EQ(string(""), reader_.getPrefix()); +} + +// Check that it can parse a namespace + +TEST_F(MessageReaderTest, Namespace) { + + // Check that no $NAMESPACE is present + EXPECT_EQ(string(""), reader_.getNamespace()); + + // Check that a $NAMESPACE directive with no argument generates an error. + processLineException(reader_, "$NAMESPACE", LOG_NAMESPACE_NO_ARGS); + + // Check a $NAMESPACE with multiple arguments is invalid + processLineException(reader_, "$namespace A B", LOG_NAMESPACE_EXTRA_ARGS); + + // Namespaces should be alphanumeric (with underscores and colons) + processLineException(reader_, "$namespace ab[cd", LOG_NAMESPACE_INVALID_ARG); + + // A valid $NAMESPACE should be accepted + EXPECT_NO_THROW(reader_.processLine("$NAMESPACE isc")); + EXPECT_EQ(string("isc"), reader_.getNamespace()); + + // (Check that we can clear the namespace) + reader_.clearNamespace(); + EXPECT_EQ(string(""), reader_.getNamespace()); + + // Check that a valid namespace can include colons + EXPECT_NO_THROW(reader_.processLine("$NAMESPACE isc::log")); + EXPECT_EQ(string("isc::log"), reader_.getNamespace()); + + // Check that the indication of the anonymous namespace will be recognized. + reader_.clearNamespace(); + EXPECT_NO_THROW(reader_.processLine("$NAMESPACE ::")); + EXPECT_EQ(string("::"), reader_.getNamespace()); + + // ... and that another $NAMESPACE is rejected + processLineException(reader_, "$NAMESPACE ABC", LOG_DUPLICATE_NAMESPACE); +} + +// Check that it can parse a line + +TEST_F(MessageReaderTest, ValidMessageAddDefault) { + + // Add a couple of valid messages + reader_.processLine("% GLOBAL1\t\tthis is message global one\n"); + reader_.processLine("%GLOBAL2 this is message global two"); + + // ... and check them + EXPECT_EQ(string("this is message global one"), + dictionary_->getText("GLOBAL1")); + EXPECT_EQ(string("this is message global two"), + dictionary_->getText("GLOBAL2")); + EXPECT_EQ(2, dictionary_->size()); + + // ... and ensure no messages were not added + vector<string> not_added = reader_.getNotAdded(); + EXPECT_EQ(0, not_added.size()); +} + +TEST_F(MessageReaderTest, ValidMessageAdd) { + + // Add a couple of valid messages + reader_.processLine("%GLOBAL1\t\tthis is message global one\n", + MessageReader::ADD); + reader_.processLine("% GLOBAL2 this is message global two", + MessageReader::ADD); + + // ... and check them + EXPECT_EQ(string("this is message global one"), + dictionary_->getText("GLOBAL1")); + EXPECT_EQ(string("this is message global two"), + dictionary_->getText("GLOBAL2")); + EXPECT_EQ(2, dictionary_->size()); + + // ... and ensure no messages were not added + vector<string> not_added = reader_.getNotAdded(); + EXPECT_EQ(0, not_added.size()); +} + +TEST_F(MessageReaderTest, ValidMessageReplace) { + + dictionary_->add("GLOBAL1", "original global1 message"); + dictionary_->add("GLOBAL2", "original global2 message"); + + // Replace a couple of valid messages + reader_.processLine("% GLOBAL1\t\tthis is message global one\n", + MessageReader::REPLACE); + reader_.processLine("% GLOBAL2 this is message global two", + MessageReader::REPLACE); + + // ... and check them + EXPECT_EQ(string("this is message global one"), + dictionary_->getText("GLOBAL1")); + EXPECT_EQ(string("this is message global two"), + dictionary_->getText("GLOBAL2")); + EXPECT_EQ(2, dictionary_->size()); + + // ... and ensure no messages were not added + vector<string> not_added = reader_.getNotAdded(); + EXPECT_EQ(0, not_added.size()); +} + +// Do checks on overflows, although this essentially duplicates the checks +// in MessageDictionary. + +TEST_F(MessageReaderTest, Overflows) { + + // Add a couple of valid messages + reader_.processLine("% GLOBAL1\t\tthis is message global one\n"); + reader_.processLine("% GLOBAL2 this is message global two"); + + // Add a duplicate in ADD mode. + reader_.processLine("% GLOBAL1\t\tthis is a replacement for global one"); + + // Replace a non-existent one in REPLACE mode + reader_.processLine("% LOCAL\t\tthis is a new message", + MessageReader::REPLACE); + + // Check what is in the dictionary. + EXPECT_EQ(string("this is message global one"), + dictionary_->getText("GLOBAL1")); + EXPECT_EQ(string("this is message global two"), + dictionary_->getText("GLOBAL2")); + EXPECT_EQ(2, dictionary_->size()); + + // ... and ensure no overflows + vector<string> not_added = reader_.getNotAdded(); + ASSERT_EQ(2, not_added.size()); + + sort(not_added.begin(), not_added.end()); + EXPECT_EQ(string("GLOBAL1"), not_added[0]); + EXPECT_EQ(string("LOCAL"), not_added[1]); +} diff --git a/src/lib/log/tests/output_option_unittest.cc b/src/lib/log/tests/output_option_unittest.cc new file mode 100644 index 0000000..bf922a9 --- /dev/null +++ b/src/lib/log/tests/output_option_unittest.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <string> + +#include <gtest/gtest.h> + +#include <log/output_option.h> + +using namespace isc::log; +using namespace std; + +// As OutputOption is a struct, the only meaningful test is to check that it +// initializes correctly. + +TEST(OutputOptionTest, Initialization) { + OutputOption option; + + EXPECT_EQ(OutputOption::DEST_CONSOLE, option.destination); + EXPECT_EQ(OutputOption::STR_STDERR, option.stream); + EXPECT_TRUE(option.flush); + EXPECT_EQ(string("LOCAL0"), option.facility); + EXPECT_EQ(string(""), option.filename); + EXPECT_EQ(0, option.maxsize); + EXPECT_EQ(0, option.maxver); +} + +TEST(OutputOption, getDestination) { + EXPECT_EQ(OutputOption::DEST_CONSOLE, getDestination("console")); + EXPECT_EQ(OutputOption::DEST_CONSOLE, getDestination("CONSOLE")); + EXPECT_EQ(OutputOption::DEST_CONSOLE, getDestination("CoNSoLE")); + EXPECT_EQ(OutputOption::DEST_FILE, getDestination("file")); + EXPECT_EQ(OutputOption::DEST_FILE, getDestination("FILE")); + EXPECT_EQ(OutputOption::DEST_FILE, getDestination("fIlE")); + EXPECT_EQ(OutputOption::DEST_SYSLOG, getDestination("syslog")); + EXPECT_EQ(OutputOption::DEST_SYSLOG, getDestination("SYSLOG")); + EXPECT_EQ(OutputOption::DEST_SYSLOG, getDestination("SYSlog")); + + // bad values should default to DEST_CONSOLE + EXPECT_EQ(OutputOption::DEST_CONSOLE, getDestination("SOME_BAD_VALUE")); +} + +TEST(OutputOption, getStream) { + EXPECT_EQ(OutputOption::STR_STDOUT, getStream("stdout")); + EXPECT_EQ(OutputOption::STR_STDOUT, getStream("STDOUT")); + EXPECT_EQ(OutputOption::STR_STDOUT, getStream("STdouT")); + EXPECT_EQ(OutputOption::STR_STDERR, getStream("stderr")); + EXPECT_EQ(OutputOption::STR_STDERR, getStream("STDERR")); + EXPECT_EQ(OutputOption::STR_STDERR, getStream("StDeRR")); + + // bad values should default to stdout + EXPECT_EQ(OutputOption::STR_STDOUT, getStream("some bad value")); + EXPECT_EQ(OutputOption::STR_STDOUT, getStream("")); +} + diff --git a/src/lib/log/tests/run_initializer_unittests.cc b/src/lib/log/tests/run_initializer_unittests.cc new file mode 100644 index 0000000..7765c14 --- /dev/null +++ b/src/lib/log/tests/run_initializer_unittests.cc @@ -0,0 +1,19 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <stdlib.h> +#include <gtest/gtest.h> +#include <util/unittests/run_all.h> + +#include <log/logger_support.h> + +int +main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return (isc::util::unittests::run_all()); +} diff --git a/src/lib/log/tests/run_unittests.cc b/src/lib/log/tests/run_unittests.cc new file mode 100644 index 0000000..2753b0b --- /dev/null +++ b/src/lib/log/tests/run_unittests.cc @@ -0,0 +1,20 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <stdlib.h> +#include <gtest/gtest.h> +#include <util/unittests/run_all.h> + +#include <log/logger_support.h> + +int +main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + isc::log::initLogger(); + return (isc::util::unittests::run_all()); +} diff --git a/src/lib/log/tests/severity_test.sh.in b/src/lib/log/tests/severity_test.sh.in new file mode 100644 index 0000000..02376f8 --- /dev/null +++ b/src/lib/log/tests/severity_test.sh.in @@ -0,0 +1,74 @@ +#!/bin/sh + +# Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Checks that the logger will limit the output of messages less severe than +# the severity/debug setting. + +# Exit with error if commands exit with non-zero and if undefined variables are +# used. +set -eu + +# Include common test library. +# shellcheck disable=SC1091 +# SC1091: Not following: ... was not specified as input (see shellcheck -x). +. "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh" + +tempfile="@abs_builddir@/severity_test_tempfile_$$" + +test_start 'severity.default-parameters' +cat > $tempfile << . +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file +WARN [example] LOG_BAD_STREAM bad log console output stream: example +WARN [example.alpha] LOG_READ_ERROR error reading from message file a.txt: dummy reason +INFO [example.alpha] LOG_INPUT_OPEN_FAIL unable to open message file example.msg for input: dummy reason +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +WARN [example.beta] LOG_BAD_STREAM bad log console output stream: beta_warn +INFO [example.beta] LOG_READ_ERROR error reading from message file beta: info +. +./logger_example -c stdout | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +test_start 'severity.filter' +cat > $tempfile << . +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +. +./logger_example -c stdout -s error | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +test_start 'severity.debug-level' +cat > $tempfile << . +FATAL [example] LOG_WRITE_ERROR error writing to test1: 42 +ERROR [example] LOG_READING_LOCAL_FILE reading local message file dummy/file +WARN [example] LOG_BAD_STREAM bad log console output stream: example +WARN [example.alpha] LOG_READ_ERROR error reading from message file a.txt: dummy reason +INFO [example.alpha] LOG_INPUT_OPEN_FAIL unable to open message file example.msg for input: dummy reason +DEBUG [example] LOG_READING_LOCAL_FILE reading local message file example/0 +DEBUG [example] LOG_READING_LOCAL_FILE reading local message file example/24 +DEBUG [example] LOG_READING_LOCAL_FILE reading local message file example/25 +FATAL [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta_fatal +ERROR [example.beta] LOG_BAD_DESTINATION unrecognized log destination: beta_error +WARN [example.beta] LOG_BAD_STREAM bad log console output stream: beta_warn +INFO [example.beta] LOG_READ_ERROR error reading from message file beta: info +DEBUG [example.beta] LOG_BAD_SEVERITY unrecognized log severity: beta/25 +. +./logger_example -c stdout -s debug -d 25 | \ + sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\.\(0x\)\{0,1\}\([0-9A-Fa-f]\{1,\}\)\]/[\1]/' | \ + cut -d' ' -f3- | diff $tempfile - +test_finish $? + +# Tidy up +rm -f $tempfile diff --git a/src/lib/log/tests/tempdir.h.in b/src/lib/log/tests/tempdir.h.in new file mode 100644 index 0000000..c805844 --- /dev/null +++ b/src/lib/log/tests/tempdir.h.in @@ -0,0 +1,21 @@ +// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef TEMPDIR_H +#define TEMPDIR_H + +/// \brief Define temporary directory +/// +/// Defines the temporary directory in which temporary files used by the +/// unit tests are created. + +#include <string> + +namespace { +std::string TEMP_DIR("@builddir@"); +} + +#endif // TEMPDIR_H |