BIND 10 trac2445, updated. 512ccc6d8b7bc49b085289226407fe741ebe7a54 [2445] Remove LogBuffer singleton

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Dec 7 10:55:59 UTC 2012


The branch, trac2445 has been updated
       via  512ccc6d8b7bc49b085289226407fe741ebe7a54 (commit)
       via  1378932f029f1e74cc606013778863161feca8e4 (commit)
       via  dfebd6128b4088ba489080cea7c53f141dce90ab (commit)
      from  231bfc60a9327295a2431f7d04ed5a26962d6236 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 512ccc6d8b7bc49b085289226407fe741ebe7a54
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Dec 7 11:55:01 2012 +0100

    [2445] Remove LogBuffer singleton
    
    LogBuffers are now members of BufferAppender instances, and the singleton has been removed. LoggerManagerImpl keeps them (if any) around while processing a new specification, and flushes them when done.

commit 1378932f029f1e74cc606013778863161feca8e4
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Dec 7 10:44:57 2012 +0100

    [2445] Address smaller points in logbuffer code
    
    - update README
    - copy vector of event on flush
    - only use very basic functions in case of flush-on-destruct

commit dfebd6128b4088ba489080cea7c53f141dce90ab
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Dec 7 09:58:56 2012 +0100

    [2445] Rename log_buffer and its namespace
    
    To prevent accidental outside use, all LogBugger (and BufferAppender) code is in the namespace isc::log::internal now, and the files have been renamed to _impl

-----------------------------------------------------------------------

Summary of changes:
 src/lib/log/Makefile.am                           |    2 +-
 src/lib/log/README                                |   10 ++--
 src/lib/log/{log_buffer.cc => log_buffer_impl.cc} |   33 +++++-------
 src/lib/log/{log_buffer.h => log_buffer_impl.h}   |   31 +++++++----
 src/lib/log/logger_manager_impl.cc                |   38 +++++++++++---
 src/lib/log/logger_manager_impl.h                 |   28 ++++++++--
 src/lib/log/tests/buffer_logger_test.sh.in        |    6 +--
 src/lib/log/tests/log_buffer_unittest.cc          |   57 +++++++++++----------
 8 files changed, 129 insertions(+), 76 deletions(-)
 rename src/lib/log/{log_buffer.cc => log_buffer_impl.cc} (80%)
 rename src/lib/log/{log_buffer.h => log_buffer_impl.h} (88%)

-----------------------------------------------------------------------
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index 4a621cb..e9074f8 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -31,7 +31,7 @@ libb10_log_la_SOURCES += message_initializer.cc message_initializer.h
 libb10_log_la_SOURCES += message_reader.cc message_reader.h
 libb10_log_la_SOURCES += message_types.h
 libb10_log_la_SOURCES += output_option.cc output_option.h
-libb10_log_la_SOURCES += log_buffer.cc log_buffer.h
+libb10_log_la_SOURCES += log_buffer_impl.cc log_buffer_impl.h
 
 EXTRA_DIST  = README
 EXTRA_DIST += logimpl_messages.mes
diff --git a/src/lib/log/README b/src/lib/log/README
index 613779e..2a7af28 100644
--- a/src/lib/log/README
+++ b/src/lib/log/README
@@ -366,11 +366,11 @@ 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 LoggerManager's process() calls. If the
-program exits before this is done, all log messages are dumped in a shortened
-format to stdout (so that no messages get lost). If you are using the built-in
-logging configuration handling in ModuleCCSession, this is automatically
-handled.
+the program SHOULD call one of the LoggerManager's process() calls (if you
+are using the built-in logging configuration handling in ModuleCCSession,
+this is automatically handled). 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).
 
 Variant #2, Used by Unit Tests
 ------------------------------
diff --git a/src/lib/log/log_buffer.cc b/src/lib/log/log_buffer.cc
deleted file mode 100644
index 5c29d20..0000000
--- a/src/lib/log/log_buffer.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <log/log_buffer.h>
-#include <log4cplus/loglevel.h>
-
-#include <boost/scoped_ptr.hpp>
-#include <iostream>
-
-namespace isc {
-namespace log {
-
-LogBuffer& getLogBuffer() {
-    static boost::scoped_ptr<LogBuffer> log_buffer(NULL);
-    if (!log_buffer) {
-        log_buffer.reset(new LogBuffer);
-    }
-    return (*log_buffer);
-}
-
-LogBuffer::~LogBuffer() {
-    // 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();
-    } catch (...) {
-        // Ok if we can't even seem to dump to stdout, never mind.
-    }
-}
-
-void
-LogBuffer::add(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_pt
-    std::auto_ptr<log4cplus::spi::InternalLoggingEvent> event_aptr =
-        event.clone();
-    boost::shared_ptr<log4cplus::spi::InternalLoggingEvent> event_sptr(
-        event_aptr.release());
-    stored_.push_back(event_sptr);
-}
-
-void
-LogBuffer::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).
-    // So we print a slightly shortened format (it really only excludes
-    // the time and the pid)
-    LoggerEventPtrList::const_iterator it;
-    const log4cplus::LogLevelManager& manager =
-        log4cplus::getLogLevelManager();
-    for (it = stored_.begin(); it != stored_.end(); ++it) {
-        std::cout << manager.toString((*it)->getLogLevel()) << " " <<
-                     "[" << (*it)->getLoggerName() << "] " <<
-                     (*it)->getMessage() << std::endl;
-    }
-    stored_.clear();
-}
-
-void
-LogBuffer::flush() {
-    LoggerEventPtrList::const_iterator it;
-    for (it = stored_.begin(); it != stored_.end(); ++it) {
-        log4cplus::Logger logger =
-            log4cplus::Logger::getInstance((*it)->getLoggerName());
-
-        logger.log((*it)->getLogLevel(), (*it)->getMessage());
-    }
-    stored_.clear();
-    flushed_ = true;
-}
-
-size_t
-LogBuffer::getBufferSize() const {
-    return (stored_.size());
-}
-
-void
-BufferAppender::append(const log4cplus::spi::InternalLoggingEvent& event) {
-    buffer_.add(event);
-}
-
-} // end namespace log
-} // end namespace isc
diff --git a/src/lib/log/log_buffer.h b/src/lib/log/log_buffer.h
deleted file mode 100644
index 9e41533..0000000
--- a/src/lib/log/log_buffer.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#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 {
-
-/// \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 list of logger events
-typedef std::vector<boost::shared_ptr<log4cplus::spi::InternalLoggingEvent> >
-    LoggerEventPtrList;
-
-/// \brief Buffering class for logging event
-///
-/// This class is used to store logging events; it simply keeps any
-/// event that is passed to \c add(), 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 add() is called after flush().
-///
-/// If the LogBuffer instance is destroyed before being flushed, it will
-/// dump any event it has left to stdout.
-class LogBuffer {
-
-public:
-    LogBuffer() : flushed_(false) {};
-
-    ~LogBuffer();
-
-    /// \brief add the given event to the list of stored events
-    ///
-    /// This is called by the BufferAppender.
-    ///
-    /// \param event The event to store
-    /// \exception LogBufferAddAfterFlush if this method is called
-    ///            when \c flush() has been called previously
-    void add(const log4cplus::spi::InternalLoggingEvent& event);
-
-    /// \brief Flush all stored events to their loggers
-    ///
-    /// All events are replayed to their loggers (which should have
-    /// other appenders when this is called.
-    /// Once this method has been called, no more events can be
-    /// added trough calls to \c add(); if \c add() is called after flush(),
-    /// an exception will be raised.
-    void flush();
-
-    /// \brief Returns number of stored events
-    ///
-    /// Mostly for testing purposes
-    size_t getBufferSize() const;
-private:
-    /// \brief Simplified flush() to stdout
-    ///
-    /// Used in the desctructor; all remainging stored events are
-    /// printed to stdout, in case flush() was never called.
-    void flushStdout();
-    LoggerEventPtrList stored_;
-    bool flushed_;
-};
-
-/// \brief Log4cplus appender for our buffer
-///
-/// This class can be set as an Appender for log4cplus loggers
-///
-/// When logging an event, it will not actually log anything, but
-/// merely add it to the singleton LogBuffer instance
-class BufferAppender : public log4cplus::Appender {
-public:
-    /// \brief Constructor
-    ///
-    /// \note Only a reference to the LogBuffer is stored, so
-    /// this buffer must remain in scope during the lifetime of
-    /// the appender. In general, only one buffer would be needed,
-    /// and for that purpose there is the singleton instance
-    /// that can be reached using \c getLogBuffer()
-    BufferAppender(LogBuffer& buffer) : buffer_(buffer) {}
-    virtual void close() {}
-protected:
-    virtual void append(const log4cplus::spi::InternalLoggingEvent& event);
-private:
-    LogBuffer& buffer_;
-};
-
-/// \brief Getter for the singleton instance of the log buffer
-LogBuffer& getLogBuffer();
-
-} // end namespace log
-} // end namespace isc
-
-#endif // LOG_BUFFER_H
-
diff --git a/src/lib/log/log_buffer_impl.cc b/src/lib/log/log_buffer_impl.cc
new file mode 100644
index 0000000..05cfe3c
--- /dev/null
+++ b/src/lib/log/log_buffer_impl.cc
@@ -0,0 +1,99 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <log/log_buffer_impl.h>
+
+#include <log4cplus/loglevel.h>
+#include <boost/scoped_ptr.hpp>
+#include <cstdio>
+
+namespace isc {
+namespace log {
+namespace internal {
+
+LogBuffer::~LogBuffer() {
+    // 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();
+    } catch (...) {
+        // Ok if we can't even seem to dump to stdout, never mind.
+    }
+}
+
+void
+LogBuffer::add(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_pt
+    std::auto_ptr<log4cplus::spi::InternalLoggingEvent> event_aptr =
+        event.clone();
+    boost::shared_ptr<log4cplus::spi::InternalLoggingEvent> event_sptr(
+        event_aptr.release());
+    stored_.push_back(event_sptr);
+}
+
+void
+LogBuffer::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).
+    // So we print a raw format (it excludes the time and the pid, and
+    // it prints severity as a number)
+    LoggerEventPtrList::const_iterator it;
+    for (it = stored_.begin(); it != stored_.end(); ++it) {
+        std::printf("Severity=%d [%s]: %s\n", (*it)->getLogLevel(),
+                    (*it)->getLoggerName().c_str(),
+                    (*it)->getMessage().c_str());
+    }
+    stored_.clear();
+}
+
+void
+LogBuffer::flush() {
+    LoggerEventPtrList stored_copy;
+    stored_.swap(stored_copy);
+
+    LoggerEventPtrList::const_iterator it;
+    for (it = stored_copy.begin(); it != stored_copy.end(); ++it) {
+        log4cplus::Logger logger =
+            log4cplus::Logger::getInstance((*it)->getLoggerName());
+
+        logger.log((*it)->getLogLevel(), (*it)->getMessage());
+    }
+    stored_.clear();
+    flushed_ = true;
+}
+
+size_t
+LogBuffer::getBufferSize() const {
+    return (stored_.size());
+}
+
+void
+BufferAppender::append(const log4cplus::spi::InternalLoggingEvent& event) {
+    buffer_.add(event);
+}
+
+} // end namespace internal
+} // end namespace log
+} // end namespace isc
diff --git a/src/lib/log/log_buffer_impl.h b/src/lib/log/log_buffer_impl.h
new file mode 100644
index 0000000..7e4d0d5
--- /dev/null
+++ b/src/lib/log/log_buffer_impl.h
@@ -0,0 +1,142 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#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 list of logger events
+typedef std::vector<boost::shared_ptr<log4cplus::spi::InternalLoggingEvent> >
+    LoggerEventPtrList;
+
+/// \brief Buffering class for logging event
+///
+/// This class is used to store logging events; it simply keeps any
+/// event that is passed to \c add(), 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 add() is called after flush().
+///
+/// If the LogBuffer instance is destroyed before being flushed, it will
+/// dump any event it has left to stdout.
+class LogBuffer {
+
+public:
+    LogBuffer() : flushed_(false) {};
+
+    ~LogBuffer();
+
+    /// \brief add the given event to the list of stored events
+    ///
+    /// This is called by the BufferAppender.
+    ///
+    /// \param event The event to store
+    /// \exception LogBufferAddAfterFlush if this method is called
+    ///            when \c flush() has been called previously
+    void add(const log4cplus::spi::InternalLoggingEvent& event);
+
+    /// \brief Flush all stored events to their loggers
+    ///
+    /// All events are replayed to their loggers (which should have
+    /// other appenders when this is called.
+    /// Once this method has been called, no more events can be
+    /// added trough calls to \c add(); if \c add() is called after flush(),
+    /// an exception will be raised.
+    /// If flush for any reason fails, the remaining events are dropped.
+    void flush();
+
+    /// \brief Returns number of stored events
+    ///
+    /// Mostly for testing purposes
+    size_t getBufferSize() const;
+private:
+    /// \brief Simplified flush() to stdout
+    ///
+    /// Used in the desctructor; all remainging stored events are
+    /// printed to stdout, in case flush() was never called.
+    void flushStdout();
+    LoggerEventPtrList stored_;
+    bool flushed_;
+};
+
+/// \brief Log4cplus appender for our buffer
+///
+/// This class can be set as an Appender for log4cplus loggers
+///
+/// When logging an event, it will not actually log anything, but
+/// merely add it to its internal LogBuffer
+class BufferAppender : public log4cplus::Appender {
+public:
+    /// \brief Constructor
+    ///
+    /// Constructs a BufferAppender with its own LogBuffer instance
+    BufferAppender() {}
+    virtual void close() {}
+
+    /// \brief Flush the internal buffer
+    void flush() {
+        buffer_.flush();
+    }
+
+    /// \brief Access to the internal log buffer
+    ///
+    /// This is mostly for testing
+    LogBuffer& getLogBuffer() {
+        return (buffer_);
+    }
+
+protected:
+    virtual void append(const log4cplus::spi::InternalLoggingEvent& event);
+private:
+    LogBuffer buffer_;
+};
+
+} // end namespace internal
+} // end namespace log
+} // end namespace isc
+
+#endif // LOG_BUFFER_H
+
diff --git a/src/lib/log/logger_manager_impl.cc b/src/lib/log/logger_manager_impl.cc
index f67116d..4283cdc 100644
--- a/src/lib/log/logger_manager_impl.cc
+++ b/src/lib/log/logger_manager_impl.cc
@@ -30,7 +30,7 @@
 #include <log/log_messages.h>
 #include <log/logger_name.h>
 #include <log/logger_specification.h>
-#include <log/log_buffer.h>
+#include <log/log_buffer_impl.h>
 
 using namespace std;
 
@@ -44,6 +44,8 @@ namespace log {
 // explicitly reset the logging severity.)
 void
 LoggerManagerImpl::processInit() {
+    storeBufferAppenders();
+
     log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
     initRootLogger();
 }
@@ -51,16 +53,15 @@ LoggerManagerImpl::processInit() {
 // Flush the LogBuffer at the end of processing a new specification
 void
 LoggerManagerImpl::processEnd() {
-    getLogBuffer().flush();
+    flushBufferAppenders();
 }
 
 // Process logging specification.  Set up the common states then dispatch to
 // add output specifications.
 void
 LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
-    log4cplus::Logger logger;
-    // If this is an 'empty' specification, just set the root logger
-    logger = log4cplus::Logger::getInstance(expandLoggerName(spec.getName()));
+    log4cplus::Logger logger = log4cplus::Logger::getInstance(
+                                   expandLoggerName(spec.getName()));
 
     // Set severity level according to specification entry.
     logger.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
@@ -141,7 +142,7 @@ LoggerManagerImpl::createFileAppender(log4cplus::Logger& logger,
 
 void
 LoggerManagerImpl::createBufferAppender(log4cplus::Logger& logger) {
-    log4cplus::SharedAppenderPtr bufferapp(new BufferAppender(getLogBuffer()));
+    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
@@ -240,5 +241,30 @@ void LoggerManagerImpl::setSyslogAppenderLayout(
     appender->setLayout(layout);
 }
 
+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());
+        app->flush();
+    }
+}
+
 } // namespace log
 } // namespace isc
diff --git a/src/lib/log/logger_manager_impl.h b/src/lib/log/logger_manager_impl.h
index ef6f811..bcb2fc7 100644
--- a/src/lib/log/logger_manager_impl.h
+++ b/src/lib/log/logger_manager_impl.h
@@ -58,7 +58,7 @@ public:
     /// This resets the hierachy 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.
-    static void processInit();
+    void processInit();
 
     /// \brief Process Specification
     ///
@@ -70,7 +70,7 @@ public:
     /// \brief End Processing
     ///
     /// Terminates the processing of the logging specifications.
-    static void processEnd();
+    void processEnd();
 
     /// \brief Implementation-specific initialization
     ///
@@ -136,9 +136,8 @@ private:
     /// \brief Create buffered appender
     ///
     /// Appends an object to the logger that will store the log events sent
-    /// to the logger in the singleton \c LogBuffer instance. These log
-    /// messages are replayed to the logger when the LogBuffer instance is
-    /// flushed (which is done at the end of \c ProcessSpecification().
+    /// 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);
@@ -175,6 +174,25 @@ private:
     ///
     /// \param appender Appender for which this pattern is to be set.
     static void setSyslogAppenderLayout(log4cplus::SharedAppenderPtr& appender);
+
+    /// \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();
+
+    /// 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_;
 };
 
 } // namespace log
diff --git a/src/lib/log/tests/buffer_logger_test.sh.in b/src/lib/log/tests/buffer_logger_test.sh.in
index 42d3773..5fbdc62 100755
--- a/src/lib/log/tests/buffer_logger_test.sh.in
+++ b/src/lib/log/tests/buffer_logger_test.sh.in
@@ -46,9 +46,9 @@ passfail $?
 
 echo -n  "   - 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
+Severity=20000 [buffertest.log]: LOG_BAD_SEVERITY unrecognized log severity: info
+Severity=10000 [buffertest.log]: LOG_BAD_DESTINATION unrecognized log destination: debug-50
+Severity=20000 [buffertest.log]: LOG_BAD_SEVERITY unrecognized log severity: info
 .
 ./buffer_logger_test -n 2>&1 | diff $tempfile -
 passfail $?
diff --git a/src/lib/log/tests/log_buffer_unittest.cc b/src/lib/log/tests/log_buffer_unittest.cc
index 0d6da8f..cf33b60 100644
--- a/src/lib/log/tests/log_buffer_unittest.cc
+++ b/src/lib/log/tests/log_buffer_unittest.cc
@@ -18,7 +18,7 @@
 #include <log/macros.h>
 #include <log/logger_support.h>
 #include <log/log_messages.h>
-#include <log/log_buffer.h>
+#include <log/log_buffer_impl.h>
 
 #include <log4cplus/loggingmacros.h>
 #include <log4cplus/logger.h>
@@ -26,14 +26,17 @@
 #include <log4cplus/spi/loggingevent.h>
 
 using namespace isc::log;
+using namespace isc::log::internal;
 
 namespace isc {
 namespace log {
 
 class LogBufferTest : public ::testing::Test {
 protected:
-    LogBufferTest() : appender1(new BufferAppender(buffer1)),
-                      appender2(new BufferAppender(buffer2)),
+    LogBufferTest() : buffer_appender1(new BufferAppender()),
+                      buffer_appender2(new BufferAppender()),
+                      appender1(buffer_appender1),
+                      appender2(buffer_appender2),
                       logger(log4cplus::Logger::getInstance("buffer"))
     {
         logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL);
@@ -50,12 +53,14 @@ protected:
             new log4cplus::NullAppender());
         logger.removeAllAppenders();
         logger.addAppender(null_appender);
-        buffer1.flush();
-        buffer2.flush();
+        buffer_appender1->flush();
+        buffer_appender2->flush();
     }
 
-    LogBuffer buffer1;
-    LogBuffer buffer2;
+    //LogBuffer buffer_appender1->getLogBuffer().
+    //LogBuffer buffer_appender2->getLogBuffer().
+    BufferAppender* buffer_appender1;
+    BufferAppender* buffer_appender2;
     log4cplus::SharedAppenderPtr appender1;
     log4cplus::SharedAppenderPtr appender2;
     log4cplus::Logger logger;
@@ -64,43 +69,43 @@ protected:
 // Test that log events are indeed stored, and that they are
 // flushed to the new appenders of their logger
 TEST_F(LogBufferTest, flush) {
-    ASSERT_EQ(0, buffer1.getBufferSize());
-    ASSERT_EQ(0, buffer2.getBufferSize());
+    ASSERT_EQ(0, buffer_appender1->getLogBuffer().getBufferSize());
+    ASSERT_EQ(0, buffer_appender2->getLogBuffer().getBufferSize());
 
     // Create a Logger, log a few messages with the first appender
     logger.addAppender(appender1);
     LOG4CPLUS_INFO(logger, "Foo");
-    ASSERT_EQ(1, buffer1.getBufferSize());
+    ASSERT_EQ(1, buffer_appender1->getLogBuffer().getBufferSize());
     LOG4CPLUS_INFO(logger, "Foo");
-    ASSERT_EQ(2, buffer1.getBufferSize());
+    ASSERT_EQ(2, buffer_appender1->getLogBuffer().getBufferSize());
     LOG4CPLUS_INFO(logger, "Foo");
-    ASSERT_EQ(3, buffer1.getBufferSize());
+    ASSERT_EQ(3, buffer_appender1->getLogBuffer().getBufferSize());
 
     // Second buffer should still be empty
-    ASSERT_EQ(0, buffer2.getBufferSize());
+    ASSERT_EQ(0, buffer_appender2->getLogBuffer().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);
-    buffer1.flush();
-    ASSERT_EQ(0, buffer1.getBufferSize());
-    ASSERT_EQ(3, buffer2.getBufferSize());
+    buffer_appender1->flush();
+    ASSERT_EQ(0, buffer_appender1->getLogBuffer().getBufferSize());
+    ASSERT_EQ(3, buffer_appender2->getLogBuffer().getBufferSize());
 }
 
 // Once flushed, logging new messages with the same buffer should fail
 TEST_F(LogBufferTest, addAfterFlush) {
     logger.addAppender(appender1);
-    buffer1.flush();
+    buffer_appender1->flush();
     EXPECT_THROW(LOG4CPLUS_INFO(logger, "Foo"), LogBufferAddAfterFlush);
     // It should not have been added
-    ASSERT_EQ(0, buffer1.getBufferSize());
+    ASSERT_EQ(0, buffer_appender1->getLogBuffer().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, buffer2.getBufferSize());
+    ASSERT_EQ(1, buffer_appender2->getLogBuffer().getBufferSize());
 }
 
 TEST_F(LogBufferTest, addDirectly) {
@@ -108,24 +113,24 @@ TEST_F(LogBufferTest, addDirectly) {
     log4cplus::spi::InternalLoggingEvent event("buffer",
                                                log4cplus::INFO_LOG_LEVEL,
                                                "Bar", "file", 123);
-    buffer1.add(event);
-    ASSERT_EQ(1, buffer1.getBufferSize());
+    buffer_appender1->getLogBuffer().add(event);
+    ASSERT_EQ(1, buffer_appender1->getLogBuffer().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);
-        buffer1.add(event2);
+        buffer_appender1->getLogBuffer().add(event2);
     }
-    ASSERT_EQ(2, buffer1.getBufferSize());
+    ASSERT_EQ(2, buffer_appender1->getLogBuffer().getBufferSize());
 
     // And flush them to the next
     logger.removeAllAppenders();
     logger.addAppender(appender2);
-    buffer1.flush();
-    ASSERT_EQ(0, buffer1.getBufferSize());
-    ASSERT_EQ(2, buffer2.getBufferSize());
+    buffer_appender1->flush();
+    ASSERT_EQ(0, buffer_appender1->getLogBuffer().getBufferSize());
+    ASSERT_EQ(2, buffer_appender2->getLogBuffer().getBufferSize());
 }
 
 }



More information about the bind10-changes mailing list