summaryrefslogtreecommitdiffstats
path: root/src/lib/log
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/log')
-rw-r--r--src/lib/log/Makefile.am119
-rw-r--r--src/lib/log/Makefile.in1258
-rw-r--r--src/lib/log/buffer_appender_impl.cc96
-rw-r--r--src/lib/log/buffer_appender_impl.h110
-rw-r--r--src/lib/log/compiler/Makefile.am24
-rw-r--r--src/lib/log/compiler/Makefile.in878
-rw-r--r--src/lib/log/compiler/message.cc543
-rw-r--r--src/lib/log/interprocess/Makefile.am21
-rw-r--r--src/lib/log/interprocess/Makefile.in854
-rw-r--r--src/lib/log/interprocess/README13
-rw-r--r--src/lib/log/interprocess/interprocess_sync.h143
-rw-r--r--src/lib/log/interprocess/interprocess_sync_file.cc132
-rw-r--r--src/lib/log/interprocess/interprocess_sync_file.h85
-rw-r--r--src/lib/log/interprocess/interprocess_sync_null.cc38
-rw-r--r--src/lib/log/interprocess/interprocess_sync_null.h58
-rw-r--r--src/lib/log/interprocess/tests/Makefile.am36
-rw-r--r--src/lib/log/interprocess/tests/Makefile.in1024
-rw-r--r--src/lib/log/interprocess/tests/interprocess_sync_file_unittest.cc153
-rw-r--r--src/lib/log/interprocess/tests/interprocess_sync_null_unittest.cc69
-rw-r--r--src/lib/log/interprocess/tests/run_unittests.cc22
-rw-r--r--src/lib/log/log_dbglevels.cc25
-rw-r--r--src/lib/log/log_dbglevels.h83
-rw-r--r--src/lib/log/log_formatter.cc68
-rw-r--r--src/lib/log/log_formatter.h263
-rw-r--r--src/lib/log/log_messages.cc63
-rw-r--r--src/lib/log/log_messages.h35
-rw-r--r--src/lib/log/log_messages.mes138
-rw-r--r--src/lib/log/logger.cc220
-rw-r--r--src/lib/log/logger.h369
-rw-r--r--src/lib/log/logger_impl.cc231
-rw-r--r--src/lib/log/logger_impl.h208
-rw-r--r--src/lib/log/logger_level.cc42
-rw-r--r--src/lib/log/logger_level.h68
-rw-r--r--src/lib/log/logger_level_impl.cc215
-rw-r--r--src/lib/log/logger_level_impl.h126
-rw-r--r--src/lib/log/logger_manager.cc216
-rw-r--r--src/lib/log/logger_manager.h173
-rw-r--r--src/lib/log/logger_manager_impl.cc322
-rw-r--r--src/lib/log/logger_manager_impl.h197
-rw-r--r--src/lib/log/logger_name.cc58
-rw-r--r--src/lib/log/logger_name.h55
-rw-r--r--src/lib/log/logger_specification.h148
-rw-r--r--src/lib/log/logger_support.cc119
-rw-r--r--src/lib/log/logger_support.h78
-rw-r--r--src/lib/log/logger_unittest_support.cc101
-rw-r--r--src/lib/log/logger_unittest_support.h111
-rw-r--r--src/lib/log/logging.dox698
-rw-r--r--src/lib/log/logimpl_messages.cc29
-rw-r--r--src/lib/log/logimpl_messages.h18
-rw-r--r--src/lib/log/logimpl_messages.mes35
-rw-r--r--src/lib/log/macros.h43
-rw-r--r--src/lib/log/message_dictionary.cc121
-rw-r--r--src/lib/log/message_dictionary.h208
-rw-r--r--src/lib/log/message_exception.h112
-rw-r--r--src/lib/log/message_initializer.cc137
-rw-r--r--src/lib/log/message_initializer.h170
-rw-r--r--src/lib/log/message_reader.cc279
-rw-r--r--src/lib/log/message_reader.h207
-rw-r--r--src/lib/log/message_types.h29
-rw-r--r--src/lib/log/output_option.cc58
-rw-r--r--src/lib/log/output_option.h85
-rw-r--r--src/lib/log/tests/Makefile.am158
-rw-r--r--src/lib/log/tests/Makefile.in1602
-rw-r--r--src/lib/log/tests/buffer_appender_unittest.cc138
-rw-r--r--src/lib/log/tests/buffer_logger_test.cc66
-rw-r--r--src/lib/log/tests/buffer_logger_test.sh.in45
-rw-r--r--src/lib/log/tests/console_test.sh.in54
-rw-r--r--src/lib/log/tests/destination_test.sh.in85
-rw-r--r--src/lib/log/tests/init_logger_test.cc36
-rw-r--r--src/lib/log/tests/init_logger_test.sh.in96
-rw-r--r--src/lib/log/tests/local_file_test.sh.in66
-rw-r--r--src/lib/log/tests/log_formatter_unittest.cc181
-rw-r--r--src/lib/log/tests/log_test_messages.cc25
-rw-r--r--src/lib/log/tests/log_test_messages.h16
-rw-r--r--src/lib/log/tests/log_test_messages.mes18
-rw-r--r--src/lib/log/tests/logger_example.cc306
-rw-r--r--src/lib/log/tests/logger_level_impl_unittest.cc168
-rw-r--r--src/lib/log/tests/logger_level_unittest.cc78
-rw-r--r--src/lib/log/tests/logger_lock_test.cc101
-rw-r--r--src/lib/log/tests/logger_lock_test.sh.in38
-rw-r--r--src/lib/log/tests/logger_manager_unittest.cc511
-rw-r--r--src/lib/log/tests/logger_name_unittest.cc76
-rw-r--r--src/lib/log/tests/logger_specification_unittest.cc90
-rw-r--r--src/lib/log/tests/logger_support_unittest.cc77
-rw-r--r--src/lib/log/tests/logger_unittest.cc508
-rw-r--r--src/lib/log/tests/message_dictionary_unittest.cc219
-rw-r--r--src/lib/log/tests/message_initializer_1_unittest.cc251
-rw-r--r--src/lib/log/tests/message_initializer_1a_unittest.cc31
-rw-r--r--src/lib/log/tests/message_reader_unittest.cc269
-rw-r--r--src/lib/log/tests/output_option_unittest.cc60
-rw-r--r--src/lib/log/tests/run_initializer_unittests.cc19
-rw-r--r--src/lib/log/tests/run_unittests.cc20
-rw-r--r--src/lib/log/tests/severity_test.sh.in74
-rw-r--r--src/lib/log/tests/tempdir.h.in21
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 &lt;dir&gt; | <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 &lt;dir&gt; 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
+/// &lt;name&gt;_&lt;ext&gt;, where &lt;name&gt; is the name of the file, and &lt;ext&gt;
+/// 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=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ 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 &lt;namespace-name&gt;</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=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ 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(&regex_, expr, flags);
+ if (rc) {
+ regfree(&regex_);
+ throw;
+ }
+ }
+
+ ~RegexHolder() {
+ regfree(&regex_);
+ }
+
+ regex_t* operator*() {
+ return (&regex_);
+ }
+
+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