BIND 10 trac558, updated. a7cbba998123e58d89a9d0da2d77afa184ea357e [trac558] Update Logger Initialization

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Feb 9 14:42:47 UTC 2011


The branch, trac558 has been updated
       via  a7cbba998123e58d89a9d0da2d77afa184ea357e (commit)
       via  13a3b9f237b1e29489804ccb5a25612cbea511f4 (commit)
       via  0c25e92e3d59db2012909c9bb4c9663e220a9522 (commit)
       via  3cddfb8bd95782eba2fa6c5935a9298500dcdd6a (commit)
       via  f059f96f5c390ffe7a3835ada1e4c6be4502985b (commit)
       via  b786dfa77ef76b5486367a40dfcc5f8b8681db52 (commit)
      from  10b0c31c6762cfde1e466039d18e159a601f867f (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 a7cbba998123e58d89a9d0da2d77afa184ea357e
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Feb 9 14:14:02 2011 +0000

    [trac558] Update Logger Initialization
    
    Updated the initialization function to take the logger name.  Also
    added code to detect (and log) if duplicate message IDs were
    compiled into the system.

commit 13a3b9f237b1e29489804ccb5a25612cbea511f4
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Feb 9 12:30:29 2011 +0000

    [trac558] Remove macros from logger formatting
    
    Argumennt information is now passed to the implementation class, which
    looks up the format string in the global dictionary and performs the
    argument substitution.

commit 0c25e92e3d59db2012909c9bb4c9663e220a9522
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Feb 9 12:09:03 2011 +0000

    [trac558] Return reference to dictionary string
    
    Returns a reference to a string in the message dictionary instead of
    a copy of it.

commit 3cddfb8bd95782eba2fa6c5935a9298500dcdd6a
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Feb 9 12:02:33 2011 +0000

    [trac558] Return reference to the global dictionary, not a pointer

commit f059f96f5c390ffe7a3835ada1e4c6be4502985b
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Feb 9 11:44:40 2011 +0000

    [trac558] Make Set/Get Root Logger Name a pair of functions
    
    Adopted suggestion by jinmei to remove the RootLoggerName class and
    make them a pair of functions.  Also optimised use of the root name
    in the logger implementation class.

commit b786dfa77ef76b5486367a40dfcc5f8b8681db52
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Feb 9 11:35:35 2011 +0000

    [trac558] Make message IDs external symbols
    
    The .h file now contains external references to message IDs and
    the .cc file contains both the definition and the initialization
    of the global dictionary with the associated text.

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

Summary of changes:
 src/lib/log/Makefile.am                           |    2 +-
 src/lib/log/compiler/message.cc                   |  213 ++++++++-------------
 src/lib/log/logger.cc                             |   47 ++---
 src/lib/log/logger_impl.cc                        |   72 ++++----
 src/lib/log/logger_impl.h                         |   47 +++---
 src/lib/log/logger_support.cc                     |   44 +++--
 src/lib/log/logger_support.h                      |   17 +-
 src/lib/log/message_dictionary.cc                 |   13 +-
 src/lib/log/message_dictionary.h                  |    6 +-
 src/lib/log/message_initializer.cc                |   17 ++-
 src/lib/log/message_initializer.h                 |   47 ++---
 src/lib/log/message_types.cc                      |   37 ----
 src/lib/log/messagedef.cc                         |   38 +++-
 src/lib/log/messagedef.h                          |   53 ++----
 src/lib/log/messagedef.mes                        |   11 +
 src/lib/log/root_logger_name.cc                   |   13 +-
 src/lib/log/root_logger_name.h                    |   44 +----
 src/lib/log/tests/Makefile.am                     |    2 -
 src/lib/log/tests/logger_support_test.cc          |    3 +-
 src/lib/log/tests/logger_unittest.cc              |   16 +-
 src/lib/log/tests/message_dictionary_unittest.cc  |   48 ++++-
 src/lib/log/tests/message_initializer_unittest.cc |   14 +-
 src/lib/log/tests/message_types_unittest.cc       |   39 ----
 src/lib/log/tests/message_types_unittest_2.cc     |   22 --
 src/lib/log/tests/root_logger_name_unittest.cc    |    8 +-
 src/lib/log/tests/run_time_init_test.sh.in        |    3 +-
 26 files changed, 374 insertions(+), 502 deletions(-)
 delete mode 100644 src/lib/log/message_types.cc
 delete mode 100644 src/lib/log/tests/message_types_unittest.cc
 delete mode 100644 src/lib/log/tests/message_types_unittest_2.cc

-----------------------------------------------------------------------
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index 1f91eda..b362eba 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -20,7 +20,7 @@ liblog_la_SOURCES += message_dictionary.cc message_dictionary.h
 liblog_la_SOURCES += message_exception.h message_exception.cc
 liblog_la_SOURCES += message_initializer.cc message_initializer.h
 liblog_la_SOURCES += message_reader.cc message_reader.h
-liblog_la_SOURCES += message_types.h message_types.cc
+liblog_la_SOURCES += message_types.h
 liblog_la_SOURCES += root_logger_name.cc root_logger_name.h
 liblog_la_SOURCES += strutil.h strutil.cc
 # liblog_la_SOURCES += xdebuglevel.cc xdebuglevel.h
diff --git a/src/lib/log/compiler/message.cc b/src/lib/log/compiler/message.cc
index db38458..e6a0cb5 100644
--- a/src/lib/log/compiler/message.cc
+++ b/src/lib/log/compiler/message.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011  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
@@ -46,7 +46,7 @@ static const char* VERSION = "1.0-0";
 ///
 /// \li A .h file containing message definition
 /// \li A .cc file containing code that adds the messages to the program's
-/// message disctionary at start-up time.
+/// message dictionary at start-up time.
 ///
 /// Alternatively, the program can produce a .py file that contains the
 /// message definitions.
@@ -80,12 +80,9 @@ version() {
 void
 usage() {
     cout <<
-        "Usage: message [-h] [-p] [-v] <message-file>\n" <<
+        "Usage: message [-h] [-v] <message-file>\n" <<
         "\n" <<
         "-h       Print this message and exit\n" <<
-        "-p       Output a Python module holding the message definitions.\n" <<
-        "         By default a C++ header file and implementation file are\n" <<
-        "         written.\n" <<
         "-v       Print the program version and exit\n" <<
         "\n" <<
         "<message-file> is the name of the input message file.\n";
@@ -108,12 +105,10 @@ currentTime() {
 
     // Convert to string and strip out the trailing newline
     string current_time = buffer;
-    return (isc::strutil::trim(current_time));
+    return isc::strutil::trim(current_time);
 }
 
 
-
-
 /// \brief Create Header Sentinel
 ///
 /// Given the name of a file, create an #ifdef sentinel name.  The name is
@@ -131,7 +126,7 @@ sentinel(Filename& file) {
     string ext = file.extension();
     string sentinel_text = "__" + name + "_" + ext.substr(1);
     isc::strutil::uppercase(sentinel_text);
-    return (sentinel_text);
+    return sentinel_text;
 }
 
 
@@ -158,7 +153,7 @@ quoteString(const string& instring) {
         outstring += instring[i];
     }
 
-    return (outstring);
+    return outstring;
 }
 
 
@@ -172,16 +167,16 @@ quoteString(const string& instring) {
 /// \return Sorted list of message IDs
 
 vector<string>
-sortedIdentifiers(MessageDictionary* dictionary) {
+sortedIdentifiers(MessageDictionary& dictionary) {
     vector<string> ident;
 
-    for (MessageDictionary::const_iterator i = dictionary->begin();
-         i != dictionary->end(); ++i) {
+    for (MessageDictionary::const_iterator i = dictionary.begin();
+         i != dictionary.end(); ++i) {
         ident.push_back(i->first);
     }
     sort(ident.begin(), ident.end());
 
-    return (ident);
+    return ident;
 }
 
 
@@ -202,28 +197,16 @@ sortedIdentifiers(MessageDictionary* dictionary) {
 vector<string>
 splitNamespace(string ns) {
 
-    vector<string>  components;
-
-    if (ns == "::") {
-
-        // Unnamed namespace
-        components.push_back("");
-
-    } else {
-
-        // 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.
-        components = isc::strutil::tokens(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, ":");
     }
 
-    return (components);
+    // ... and return the vector of namespace components split on the single
+    // colon.
+    return isc::strutil::tokens(ns, ":");
 }
 
 
@@ -231,18 +214,12 @@ splitNamespace(string ns) {
 ///
 /// Writes the lines listing the namespaces in use.
 void
-writeOpeningNamespace(ostream& output, vector<string>& ns) {
+writeOpeningNamespace(ostream& output, const vector<string>& ns) {
     if (!ns.empty()) {
-        if (ns[0].empty()) {
-
-            // Empty namespace
-            output << "namespace {\n";
-        } else {
 
-            // Output namespaces in correct order
-            for (int i = 0; i < ns.size(); ++i) {
-                output << "namespace " << ns[i] << " {\n";
-            }
+        // Output namespaces in correct order
+        for (int i = 0; i < ns.size(); ++i) {
+            output << "namespace " << ns[i] << " {\n";
         }
         output << "\n";
     }
@@ -253,14 +230,10 @@ writeOpeningNamespace(ostream& output, vector<string>& ns) {
 ///
 /// Writes the lines listing the namespaces in use.
 void
-writeClosingNamespace(ostream& output, vector<string>& ns) {
+writeClosingNamespace(ostream& output, const vector<string>& ns) {
     if (!ns.empty()) {
-        if (ns[0].empty()) {
-            output << "} // Unnamed namespace\n";
-        } else {
-            for (int i = ns.size() - 1; i >= 0; --i) {
-                output << "} // namespace " << ns[i] << "\n";
-            }
+        for (int i = ns.size() - 1; i >= 0; --i) {
+            output << "} // namespace " << ns[i] << "\n";
         }
         output << "\n";
     }
@@ -279,8 +252,8 @@ writeClosingNamespace(ostream& output, vector<string>& ns) {
 /// \param dictionary Dictionary holding the message definitions.
 
 void
-writeHeaderFile(const string& file, const string& prefix, const string& ns,
-    string& mi_name, MessageDictionary* dictionary)
+writeHeaderFile(const string& file, const string& prefix,
+        const vector<string>& ns_components, MessageDictionary& dictionary)
 {
     Filename message_file(file);
     Filename header_file(message_file.useAsDefault(".h"));
@@ -308,52 +281,20 @@ writeHeaderFile(const string& file, const string& prefix, const string& ns,
              "#define "  << sentinel_text << "\n" <<
              "\n" <<
              "#include <log/message_types.h>\n" <<
-             "#include <log/message_initializer.h>\n" <<
              "\n";
 
-        // Namespaces
-        vector<string> ns_components = splitNamespace(ns);
+        // Write the message identifiers, bounded by a namespace declaration
         writeOpeningNamespace(hfile, ns_components);
 
-        // Now the m,essage identifications themselves.
         vector<string> idents = sortedIdentifiers(dictionary);
         for (vector<string>::const_iterator j = idents.begin();
             j != idents.end(); ++j) {
-            hfile << "static const isc::log::MessageID " << prefix << *j <<
-                " = \"" << *j << "\";\n";
+            hfile << "extern const isc::log::MessageID " << prefix << *j << ";\n";
         }
         hfile << "\n";
 
-        // Close off namespaces if appropriate.
         writeClosingNamespace(hfile, ns_components);
 
-        // Now create the reference to the message initializer to ensure that
-        // it gets run at program startup.  Note that even the instantiator
-        // object is given its own unique name - multiple message header files
-        // might be included in the file, and identical multiple static names
-        // would clash.
-
-        hfile <<
-            "namespace isc {\n" <<
-            "namespace log {\n" <<
-            "\n" <<
-            "// The next two objects are needed to bring the default message\n" <<
-            "// definitions into the program.  They make sure that the file\n" <<
-            "// containing the message text is included in the link process.\n" <<
-            "//\n" <<
-            "// The objects are uniquely named (with file name and date and\n" <<
-            "// time of compilation) to avoid clashes with other objects of\n" <<
-            "// the same type, either by another #include or as a global\n" <<
-            "// symbol in another module.\n" <<
-            "\n" <<
-            "extern MessageInitializer " << mi_name << ";\n" <<
-            "static MessageInstantiator instantiate_" << mi_name << "(\n" <<
-            "   &" << mi_name << ");\n" <<
-            "\n" <<
-            "} // namespace log\n" <<
-            "} // namespace isc\n";
-
-
         // ... and finally the postamble
         hfile << "#endif // " << sentinel_text << "\n";
 
@@ -384,12 +325,13 @@ replaceNonAlphaNum(char c) {
 
 /// \brief Write Program File
 ///
-/// Writes the C++ source code file.  This defines an external objects whose
-/// constructor is run at initialization time.  The constructor adds the message
-/// definitions to the main global dictionary.
+/// 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.
 
-string
-writeProgramFile(const string& file, MessageDictionary* dictionary)
+void
+writeProgramFile(const string& file, const string& prefix,
+    const vector<string>& ns_components, MessageDictionary& dictionary)
 {
     Filename message_file(file);
     Filename program_file(message_file.useAsDefault(".cc"));
@@ -410,47 +352,51 @@ writeProgramFile(const string& file, MessageDictionary* dictionary)
                 currentTime() << "\n" <<
              "\n" <<
              "#include <cstddef>\n" <<
+             "#include <log/message_types.h>\n" <<
              "#include <log/message_initializer.h>\n" <<
-             "\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 " << prefix << *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.
-        vector<string> idents = sortedIdentifiers(dictionary);
+        idents = sortedIdentifiers(dictionary);
         for (vector<string>::const_iterator i = idents.begin();
             i != idents.end(); ++i) {
                 ccfile << "    \"" << *i << "\", \"" <<
-                    quoteString(dictionary->getText(*i)) << "\",\n";
+                    quoteString(dictionary.getText(*i)) << "\",\n";
         }
 
+
         // ... and the postamble
         ccfile <<
             "    NULL\n" <<
             "};\n" <<
             "\n" <<
-            "} // Anonymous namespace\n" <<
-            "\n";
-
-        // Now construct a unique name.  We don't put the message initializer as
-        // a static variable or in an anonymous namespace lest the C++
-        // compiler's optimizer decides it can optimise it away.
-        string unique_name = program_file.name() + program_file.extension() +
-            "_" + currentTime();
-        transform(unique_name.begin(), unique_name.end(), unique_name.begin(),
-            replaceNonAlphaNum);
-
-        // ... and write the initialization code
-        ccfile <<
-            "namespace isc {\n" <<
-            "namespace log {\n" <<
+            "isc::log::MessageInitializer initializer(values);\n" <<
             "\n" <<
-            "MessageInitializer " << unique_name << "(values);\n" <<
-            "\n" <<
-            "} // namespace log\n" <<
-            "} // namespace isc\n" <<
+            "} // Anonymous namespace\n" <<
             "\n";
 
+ 
         // Report errors (if any) and exit
         if (ccfile.fail()) {
             throw MessageException(MSG_WRITERR, program_file.fullName(),
@@ -458,8 +404,6 @@ writeProgramFile(const string& file, MessageDictionary* dictionary)
         }
 
         ccfile.close();
-
-        return (unique_name);
     }
     catch (MessageException&) {
         ccfile.close();
@@ -518,15 +462,15 @@ main(int argc, char** argv) {
         switch (opt) {
             case 'h':
                 usage();
-                return (0);
+                return 0;
 
             case 'v':
                 version();
-                return (0);
+                return 0;
 
             default:
                 // A message will have already been output about the error.
-                return (1);
+                return 1;
         }
     }
 
@@ -534,11 +478,11 @@ main(int argc, char** argv) {
     if (optind < (argc - 1)) {
         cout << "Error: excess arguments in command line\n";
         usage();
-        return (1);
+        return 1;
     } else if (optind >= argc) {
         cout << "Error: missing message file\n";
         usage();
-        return (1);
+        return 1;
     }
     string message_file = argv[optind];
 
@@ -551,31 +495,36 @@ main(int argc, char** argv) {
         MessageReader reader(&dictionary);
         reader.readFile(message_file);
 
-        // Write the file that defines the message text
-        std::string mi_name =
-            writeProgramFile(message_file, &dictionary);
+        // 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, reader.getPrefix(), ns_components,
+            dictionary);
+
+        // Write the file that defines the message symbols and text
+        writeProgramFile(message_file, reader.getPrefix(), ns_components,
+            dictionary);
 
-        // Now write the header file.
-        writeHeaderFile(message_file, reader.getPrefix(), reader.getNamespace(),
-            mi_name, &dictionary);
 
         // Finally, warn of any duplicates encountered.
         warnDuplicates(reader);
     }
     catch (MessageException& e) {
         // Create an error message from the ID and the text
-        MessageDictionary* global = MessageDictionary::globalDictionary();
+        MessageDictionary& global = MessageDictionary::globalDictionary();
         string text = e.id();
         text += ", ";
-        text += global->getText(e.id());
+        text += global.getText(e.id());
 
         // Format with arguments
         text = isc::strutil::format(text, e.arguments());
         cerr << text << "\n";
 
-        return (1);
+        return 1;
     }
 
-    return (0);
+    return 0;
 
 }
diff --git a/src/lib/log/logger.cc b/src/lib/log/logger.cc
index 522b70e..935e214 100644
--- a/src/lib/log/logger.cc
+++ b/src/lib/log/logger.cc
@@ -110,18 +110,6 @@ Logger::isFatalEnabled() {
 // definition of the macro).  Also note that it expects that the message buffer
 // "message" is declared in the compilation unit.
 
-#define MESSAGE_SIZE (512)
-
-#define FORMAT_MESSAGE(message) \
-    { \
-    MessageDictionary* global = MessageDictionary::globalDictionary(); \
-    string format = global->getText(ident); \
-    va_list ap; \
-    va_start(ap, ident); \
-    vsnprintf(message, sizeof(message), format.c_str(), ap); \
-    message[sizeof(message) - 1] = '\0'; \
-    va_end(ap); \
-    }
     
 
 // Output methods
@@ -129,45 +117,50 @@ Logger::isFatalEnabled() {
 void
 Logger::debug(int dbglevel, const isc::log::MessageID& ident, ...) {
     if (isDebugEnabled(dbglevel)) {
-        char message[MESSAGE_SIZE];
-        FORMAT_MESSAGE(message);
-        getLoggerPtr()->debug(ident, message);
+        va_list ap;
+        va_start(ap, ident);
+        getLoggerPtr()->debug(ident, ap);
+        va_end(ap);
     }
 }
 
 void
 Logger::info(const isc::log::MessageID& ident, ...) {
     if (isInfoEnabled()) {
-        char message[MESSAGE_SIZE];
-        FORMAT_MESSAGE(message);
-        getLoggerPtr()->info(ident, message);
+        va_list ap;
+        va_start(ap, ident);
+        getLoggerPtr()->info(ident, ap);
+        va_end(ap);
     }
 }
 
 void
 Logger::warn(const isc::log::MessageID& ident, ...) {
     if (isWarnEnabled()) {
-        char message[MESSAGE_SIZE];
-        FORMAT_MESSAGE(message);
-        getLoggerPtr()->warn(ident, message);
+        va_list ap;
+        va_start(ap, ident);
+        getLoggerPtr()->warn(ident, ap);
+        va_end(ap);
     }
 }
 
 void
 Logger::error(const isc::log::MessageID& ident, ...) {
     if (isErrorEnabled()) {
-        char message[MESSAGE_SIZE];
-        FORMAT_MESSAGE(message);
-        getLoggerPtr()->error(ident, message);
+        va_list ap;
+        va_start(ap, ident);
+        getLoggerPtr()->error(ident, ap);
+        va_end(ap);
     }
 }
 
 void
 Logger::fatal(const isc::log::MessageID& ident, ...) {
     if (isFatalEnabled()) {
-        char message[MESSAGE_SIZE];
-        FORMAT_MESSAGE(message);
-        getLoggerPtr()->fatal(ident, message);
+        va_list ap;
+        va_start(ap, ident);
+        getLoggerPtr()->fatal(ident, ap);
+        va_end(ap);
     }
 }
 
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
index 1199914..9b16b97 100644
--- a/src/lib/log/logger_impl.cc
+++ b/src/lib/log/logger_impl.cc
@@ -38,22 +38,22 @@ namespace log {
 LoggerImpl::LoggerInfoMap LoggerImpl::logger_info_;
 LoggerImpl::LoggerInfo LoggerImpl::root_logger_info_(isc::log::INFO, 0);
 
-// Destructor. (Here because of virtual declaration.)
-
-LoggerImpl::~LoggerImpl() {
+// Constructor
+LoggerImpl::LoggerImpl(const std::string& name, bool)
+{
+    // Are we the root logger?
+    if (name == getRootLoggerName()) { 
+        is_root_ = true;
+        name_ = name;
+    } else {
+        is_root_ = false;
+        name_ = getRootLoggerName() + "." + name;
+    }
 }
 
-// Return the name of the logger (fully-qualified with the root name if
-// possible).
+// Destructor. (Here because of virtual declaration.)
 
-string LoggerImpl::getName() {
-    string root_name = RootLoggerName::getName();
-    if (root_name.empty() || (name_ == root_name)) {
-        return (name_);
-    }
-    else {
-        return (root_name + "." + name_);
-    }
+LoggerImpl::~LoggerImpl() {
 }
 
 // Set the severity for logging.
@@ -64,7 +64,7 @@ LoggerImpl::setSeverity(isc::log::Severity severity, int dbglevel) {
     // Silently coerce the debug level into the valid range of 0 to 99
 
     int debug_level = max(MIN_DEBUG_LEVEL, min(MAX_DEBUG_LEVEL, dbglevel));
-    if (isRootLogger()) {
+    if (is_root_) {
 
         // Can only set severity for the root logger, you can't disable it.
         // Any attempt to do so is silently ignored.
@@ -93,7 +93,7 @@ LoggerImpl::setSeverity(isc::log::Severity severity, int dbglevel) {
 isc::log::Severity
 LoggerImpl::getSeverity() {
 
-    if (isRootLogger()) {
+    if (is_root_) {
         return (root_logger_info_.severity);
     }
     else {
@@ -112,9 +112,11 @@ LoggerImpl::getSeverity() {
 
 isc::log::Severity
 LoggerImpl::getEffectiveSeverity() {
-    if (! isRootLogger()) {
 
-        // Not root logger, look this logger up in the map.
+    if (!is_root_ && !logger_info_.empty()) {
+
+        // Not root logger and there is at least one item in the info map for a
+        // logger.
         LoggerInfoMap::iterator i = logger_info_.find(name_);
         if (i != logger_info_.end()) {
 
@@ -133,9 +135,10 @@ LoggerImpl::getEffectiveSeverity() {
 int
 LoggerImpl::getDebugLevel() {
 
-    if (! isRootLogger()) {
+    if (!is_root_ && !logger_info_.empty()) {
 
-        // Not root logger, look this logger up in the map.
+        // Not root logger and there is something in the map, check if there
+        // is a setting for this one.
         LoggerInfoMap::iterator i = logger_info_.find(name_);
         if (i != logger_info_.end()) {
 
@@ -164,21 +167,10 @@ LoggerImpl::getDebugLevel() {
 bool
 LoggerImpl::isDebugEnabled(int dbglevel) {
 
-    if (logger_info_.empty()) {
-
-        // Nothing set, return information from the root logger.
-        return ((root_logger_info_.severity <= isc::log::DEBUG) &&
-            (root_logger_info_.dbglevel >= dbglevel));
-    }
-
-    // Something is in the general logger map, so we need to look up the
-    // information.  We don't use getSeverity() and getDebugLevel() separately
-    // as each involves a lookup in the map, something that we can optimise
-    // here.
+    if (!is_root_ && !logger_info_.empty()) {
 
-    if (! isRootLogger()) {
-
-        // Not root logger, look this logger up in the map.
+        // Not root logger and there is something in the map, check if there
+        // is a setting for this one.
         LoggerInfoMap::iterator i = logger_info_.find(name_);
         if (i != logger_info_.end()) {
 
@@ -194,9 +186,9 @@ LoggerImpl::isDebugEnabled(int dbglevel) {
     // Must be the root logger, or this logger is defaulting to the root logger
     // settings.
     if (root_logger_info_.severity <= isc::log::DEBUG) {
-        return (root_logger_info_.dbglevel > dbglevel);
+        return (root_logger_info_.dbglevel >= dbglevel);
     } else {
-        return (false);
+       return (false);
     }
 }
 
@@ -204,8 +196,14 @@ LoggerImpl::isDebugEnabled(int dbglevel) {
 
 void
 LoggerImpl::output(const char* sev_text, const MessageID& ident,
-    const char* text)
+    va_list ap)
 {
+    char message[512];      // Should be large enough for any message
+
+    // Obtain text of the message and substitute arguments.
+    const string format = MessageDictionary::globalDictionary().getText(ident);
+    vsnprintf(message, sizeof(message), format.c_str(), ap);
+    message[sizeof(message) - 1] = '\0';    // Guarantee trailing NULL
 
     // Get the time in a struct tm format, and convert to text
     time_t t_time;
@@ -218,7 +216,7 @@ LoggerImpl::output(const char* sev_text, const MessageID& ident,
 
     // Now output.
     std::cout << chr_time << " " << sev_text << " [" << getName() << "] " <<
-        ident << ", " << text << "\n";
+        ident << ", " << message << "\n";
 }
 
 } // namespace log
diff --git a/src/lib/log/logger_impl.h b/src/lib/log/logger_impl.h
index 989581a..b8c2736 100644
--- a/src/lib/log/logger_impl.h
+++ b/src/lib/log/logger_impl.h
@@ -15,6 +15,7 @@
 #ifndef __LOGGER_IMPL_H
 #define __LOGGER_IMPL_H
 
+#include <stdarg.h>
 #include <time.h>
 
 #include <cstdlib>
@@ -74,8 +75,7 @@ public:
     ///
     /// \param exit_delete This argument is present to get round a bug in
     /// the log4cxx implementation.  It is unused here.
-    LoggerImpl(const std::string& name, bool) : name_(name)
-    {}
+    LoggerImpl(const std::string& name, bool);
 
 
     /// \brief Destructor
@@ -83,15 +83,8 @@ public:
 
 
     /// \brief Get the full name of the logger (including the root name)
-    virtual std::string getName();
-
-
-    /// \brief Check if this is the root logger
-    ///
-    /// \return true if the name of this logger is the same as that of the
-    /// root logger.
-    virtual bool isRootLogger() const {
-        return (name_ == RootLoggerName::getName());
+    virtual std::string getName() {
+        return (name_);
     }
 
 
@@ -183,17 +176,18 @@ public:
     ///
     /// \param sev_text Severity level as a text string
     /// \param ident Message identification
-    /// \param text Text to log
+    /// \param ap Variable argument list holding message arguments
     void output(const char* sev_text, const MessageID& ident,
-        const char* text);
+        va_list ap);
 
 
     /// \brief Output Debug Message
     ///
     /// \param ident Message identification.
     /// \param text Text to log
-    void debug(const MessageID& ident, const char* text) {
-        output("DEBUG", ident, text);
+    /// \param ap Variable argument list holding message arguments
+    void debug(const MessageID& ident, va_list ap) {
+        output("DEBUG", ident, ap);
     }
 
 
@@ -201,32 +195,36 @@ public:
     ///
     /// \param ident Message identification.
     /// \param text Text to log
-    void info(const MessageID& ident, const char* text) {
-        output("INFO ", ident, text);
+    /// \param ap Variable argument list holding message arguments
+    void info(const MessageID& ident, va_list ap) {
+        output("INFO ", ident, ap);
     }
 
     /// \brief Output Warning Message
     ///
     /// \param ident Message identification.
     /// \param text Text to log
-    void warn(const MessageID& ident, const char* text) {
-        output("WARN ", ident, text);
+    /// \param ap Variable argument list holding message arguments
+    void warn(const MessageID& ident, va_list ap) {
+        output("WARN ", ident, ap);
     }
 
     /// \brief Output Error Message
     ///
     /// \param ident Message identification.
     /// \param text Text to log
-    void error(const MessageID& ident, const char* text) {
-        output("ERROR", ident, text);
+    /// \param ap Variable argument list holding message arguments
+    void error(const MessageID& ident, va_list ap) {
+        output("ERROR", ident, ap);
     }
 
     /// \brief Output Fatal Message
     ///
     /// \param ident Message identification.
     /// \param text Text to log
-    void fatal(const MessageID& ident, const char* text) {
-        output("FATAL", ident, text);
+    /// \param ap Variable argument list holding message arguments
+    void fatal(const MessageID& ident, va_list ap) {
+        output("FATAL", ident, ap);
     }
 
     /// \brief Equality
@@ -251,7 +249,8 @@ public:
 
 
 private:
-    std::string          name_;                 ///< Name of this logger
+    bool                is_root_;           ///< true if a root logger
+    std::string         name_;              ///< Name of this logger
 
     // Split the status of the root logger from this logger.  If - is will
     // probably be the usual case - no per-logger setting is enabled, a
diff --git a/src/lib/log/logger_support.cc b/src/lib/log/logger_support.cc
index 0b588fe..a08ba0a 100644
--- a/src/lib/log/logger_support.cc
+++ b/src/lib/log/logger_support.cc
@@ -24,6 +24,8 @@
 /// These functions will be replaced once the code has bneen written to obtain
 /// the logging parameters from the configuration database.
 
+#include <algorithm>
+#include <string>
 #include <vector>
 #include <boost/lexical_cast.hpp>
 
@@ -32,6 +34,7 @@
 #include <log/messagedef.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/root_logger_name.h>
@@ -41,7 +44,8 @@ namespace log {
 
 using namespace std;
 
-// Declare a logger for the logging subsystem
+// Declare a logger for the logging subsystem.  This is a sub-logger of the
+// root logger and is used in all functions in this file.
 Logger logger("log");
 
 
@@ -55,9 +59,10 @@ Logger logger("log");
 static void
 readLocalMessageFile(const char* file) {
     
-    MessageDictionary* dictionary = MessageDictionary::globalDictionary();
-    MessageReader reader(dictionary);
+    MessageDictionary& dictionary = MessageDictionary::globalDictionary();
+    MessageReader reader(&dictionary);
     try {
+        logger.info(MSG_RDLOCMES, file);
         reader.readFile(file, MessageReader::REPLACE);
 
         // File successfully read, list the duplicates
@@ -89,20 +94,33 @@ readLocalMessageFile(const char* file) {
 /// Logger Run-Time Initialization
 
 void
-runTimeInit(isc::log::Severity severity, int dbglevel, const char* file) {
+init(const string& root, isc::log::Severity severity, int dbglevel,
+    const char* file) {
 
-    // Create the application root logger.  This is the logger that has the
-    // name of the application (and is one level down from the log4cxx root
-    // logger).  All other loggers created in this application will be its
-    // child.
-    //
-    // The main purpose of the application root logger is to provide the root
-    // name in output message for all other loggers.
-    Logger logger(RootLoggerName::getName());
+    // Create the application 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);
+    Logger root_logger(isc::log::getRootLoggerName(), true);
 
     // Set the severity associated with it.  If no other logger has a severity,
     // this will be the default.
-    logger.setSeverity(severity, dbglevel);
+    root_logger.setSeverity(severity, dbglevel);
+
+    // Check if there were any duplicate message IDs in the default dictionary
+    // and if so, log them.  Log using the logging facility root logger.
+    vector<string>& duplicates = MessageInitializer::getDuplicates();
+    if (!duplicates.empty()) {
+
+        // There are - sort and remove any duplicates.
+        sort(duplicates.begin(), duplicates.end());
+        vector<string>::iterator new_end =
+            unique(duplicates.begin(), duplicates.end());
+        for (vector<string>::iterator i = duplicates.begin(); i != new_end; ++i) {
+            logger.warn(MSG_DUPMSGID, i->c_str());
+        }
+
+    }
 
     // Replace any messages with local ones (if given)
     if (file) {
diff --git a/src/lib/log/logger_support.h b/src/lib/log/logger_support.h
index b736337..a3aea81 100644
--- a/src/lib/log/logger_support.h
+++ b/src/lib/log/logger_support.h
@@ -15,6 +15,7 @@
 #ifndef __LOGGER_SUPPORT_H
 #define __LOGGER_SUPPORT_H
 
+#include <string>
 #include <log/logger.h>
 
 namespace isc {
@@ -22,17 +23,21 @@ namespace log {
 
 /// \brief Run-Time Initialization
 ///
-/// This code will be used until the logger is fully integrated into the BIND-10
-/// configuration database.  It performs run-time initialization of the logger,
-/// in particular supplying run-time choices to it:
+/// Performs run-time initialization of the logger in particular supplying:
 ///
-/// * The severity (and if applicable, debug level) at which to log
-/// * Name of a local message file, containing localisation of message text.
+/// - Name of the root logger
+/// - The severity (and if applicable, debug level) for the root logger.
+/// - Name of a local message file, containing localisation 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 severiy (ignored if "severity" is not "DEBUG")
 /// \param file Name of the local message file.
-void runTimeInit(isc::log::Severity severity, int dbglevel, const char* file);
+void init(const std::string& root, isc::log::Severity severity, int dbglevel,
+    const char* file);
 
 } // namespace log
 } // namespace isc
diff --git a/src/lib/log/message_dictionary.cc b/src/lib/log/message_dictionary.cc
index 1387f63..85046bd 100644
--- a/src/lib/log/message_dictionary.cc
+++ b/src/lib/log/message_dictionary.cc
@@ -84,13 +84,16 @@ MessageDictionary::load(const char* messages[]) {
     return (duplicates);
 }
 
-// Return message text or blank string
+// 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.
 
-string
+const string&
 MessageDictionary::getText(const string& ident) const {
+    static const string empty("");
     Dictionary::const_iterator i = dictionary_.find(ident);
     if (i == dictionary_.end()) {
-        return (string(""));
+        return (empty);
     }
     else {
         return (i->second);
@@ -99,10 +102,10 @@ MessageDictionary::getText(const string& ident) const {
 
 // Return global dictionary
 
-MessageDictionary*
+MessageDictionary&
 MessageDictionary::globalDictionary() {
     static MessageDictionary global;
-    return (&global);
+    return (global);
 }
 
 
diff --git a/src/lib/log/message_dictionary.h b/src/lib/log/message_dictionary.h
index d1bac06..0caa3ea 100644
--- a/src/lib/log/message_dictionary.h
+++ b/src/lib/log/message_dictionary.h
@@ -136,7 +136,7 @@ public:
     /// \return Text associated with message or empty string if the ID is not
     /// recognised.  (Note: this precludes an ID being associated with an empty
     /// string.)
-    virtual std::string getText(const MessageID& ident) const {
+    virtual const std::string& getText(const MessageID& ident) const {
         return(getText(boost::lexical_cast<std::string>(ident)));
     }
 
@@ -150,7 +150,7 @@ public:
     /// \return Text associated with message or empty string if the ID is not
     /// recognised.  (Note: this precludes an ID being associated with an empty
     /// string.)
-    virtual std::string getText(const std::string& ident) const;
+    virtual const std::string& getText(const std::string& ident) const;
 
 
     /// \brief Number of Items in Dictionary
@@ -178,7 +178,7 @@ public:
     /// Returns a pointer to the singleton global dictionary.
     ///
     /// \return Pointer to global dictionary.
-    static MessageDictionary* globalDictionary();
+    static MessageDictionary& globalDictionary();
 
 private:
     Dictionary       dictionary_;   ///< Holds the ID to text lookups
diff --git a/src/lib/log/message_initializer.cc b/src/lib/log/message_initializer.cc
index a9d5203..0113497 100644
--- a/src/lib/log/message_initializer.cc
+++ b/src/lib/log/message_initializer.cc
@@ -22,13 +22,22 @@ namespace log {
 // associated text into it.
 
 MessageInitializer::MessageInitializer(const char* values[]) {
-    MessageDictionary* global = MessageDictionary::globalDictionary();
-    global->load(values);
+    MessageDictionary& global = MessageDictionary::globalDictionary();
+    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 (!repeats.empty()) {
+        std::vector<std::string>& duplicates = getDuplicates();
+        duplicates.insert(duplicates.end(), repeats.begin(), repeats.end());
+    }
 }
 
-// Dummy constructor for the MessageInstantiator
+// Return reference to duplicate array
 
-MessageInstantiator::MessageInstantiator(MessageInitializer*) {
+std::vector<std::string>& MessageInitializer::getDuplicates() {
+    static std::vector<std::string> duplicates;
+    return (duplicates);
 }
 
 } // namespace log
diff --git a/src/lib/log/message_initializer.h b/src/lib/log/message_initializer.h
index ee9a2cd..7516823 100644
--- a/src/lib/log/message_initializer.h
+++ b/src/lib/log/message_initializer.h
@@ -15,6 +15,8 @@
 #ifndef __MESSAGEINITIALIZER_H
 #define __MESSAGEINITIALIZER_H
 
+#include <string>
+#include <vector>
 #include <log/message_dictionary.h>
 
 namespace isc {
@@ -50,40 +52,21 @@ public:
 
     /// \brief Constructor
     ///
-    /// The only method in the class, this adds the array of values to the
-    /// global dictionary.
+    /// Adds the array of values to the global dictionary, and notes any
+    /// duplicates.
+    ///
+    /// \param values NULL-terminated array of alternating identifier strings
+    /// and associated message text.
     MessageInitializer(const char* values[]);
-};
-
-/// \brief Instantiate Message Initializer
-///
-/// A problem with the MessageInitializer class is that an instance of it is
-/// created in an external file and initialization of a set of messages requires
-/// that that file be included in the link.  Unfortunately, if there is no
-/// reference to the MessageInitializer object, we cannot guarantee that that
-/// will be the case.\n
-/// \n
-/// The MessageInitializer object is created as a global object, so in theory
-/// an "extern" reference to it should work.  However, that reference may well
-/// be optimised away.  To overcome this, the MessageInstantiator class is
-/// used.\n
-/// \n
-/// In the message header file, an instance of MessageInstantiator is created
-/// that takes the extern reference to the MessageInitializer as its constructor
-/// argument.  The constructor - declared in another file - is a no-op.  But as
-/// the linker doesn't know, it must resolve the reference, hence pulling in the
-/// file containing the MessageInitializer.
-///\n
-/// Note that there is no problem about the static initialization fiasco here -
-/// a pointer to the MessageInitializer is passed to the MessageInstantiator,
-/// not the object itself; at the MessageInstantiator does nothing with the
-/// pointer and does not touch the MessageInitializer.  So it doesn't matter
-/// whether or not the MessageInitializer's constructor has been called when the
-/// MessageInstantiator runs.
 
-class MessageInstantiator {
-public:
-    MessageInstantiator(MessageInitializer* dummy);
+    /// \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 std::vector<std::string>& getDuplicates();
 };
 
 } // namespace log
diff --git a/src/lib/log/message_types.cc b/src/lib/log/message_types.cc
deleted file mode 100644
index 3d64634..0000000
--- a/src/lib/log/message_types.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2011  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 <string.h>
-#include <log/message_types.h>
-
-namespace isc {
-namespace log {
-
-// Compare MessageID for Equality
-
-bool equalMessageID(const MessageID& m1, const MessageID& m2) {
-
-    // Attempt to optimise the check.  If both are the same instance of the
-    // message ID, the check for addresses will successed.  If both are the
-    // same message ID but declared in a separate files (so different
-    // addresses but pointing to the same string), the string equality check
-    // will work.
-    return ((m1 == m2) || (strcmp(m1, m2) == 0));
-}
-
-} // namespace log
-} // namespace isc
-
-
-
diff --git a/src/lib/log/messagedef.cc b/src/lib/log/messagedef.cc
index a2ceeec..12f1d5b 100644
--- a/src/lib/log/messagedef.cc
+++ b/src/lib/log/messagedef.cc
@@ -1,13 +1,39 @@
-// File created from messagedef.mes on Tue Feb  8 18:01:54 2011
+// File created from messagedef.mes on Wed Feb  9 13:09:05 2011
 
 #include <cstddef>
+#include <log/message_types.h>
 #include <log/message_initializer.h>
 
+namespace isc {
+namespace log {
+
+extern const isc::log::MessageID MSG_DUPLNS = "DUPLNS";
+extern const isc::log::MessageID MSG_DUPLPRFX = "DUPLPRFX";
+extern const isc::log::MessageID MSG_DUPMSGID = "DUPMSGID";
+extern const isc::log::MessageID MSG_IDNOTFND = "IDNOTFND";
+extern const isc::log::MessageID MSG_NSEXTRARG = "NSEXTRARG";
+extern const isc::log::MessageID MSG_NSINVARG = "NSINVARG";
+extern const isc::log::MessageID MSG_NSNOARG = "NSNOARG";
+extern const isc::log::MessageID MSG_ONETOKEN = "ONETOKEN";
+extern const isc::log::MessageID MSG_OPENIN = "OPENIN";
+extern const isc::log::MessageID MSG_OPENOUT = "OPENOUT";
+extern const isc::log::MessageID MSG_PRFEXTRARG = "PRFEXTRARG";
+extern const isc::log::MessageID MSG_PRFINVARG = "PRFINVARG";
+extern const isc::log::MessageID MSG_PRFNOARG = "PRFNOARG";
+extern const isc::log::MessageID MSG_RDLOCMES = "RDLOCMES";
+extern const isc::log::MessageID MSG_READERR = "READERR";
+extern const isc::log::MessageID MSG_UNRECDIR = "UNRECDIR";
+extern const isc::log::MessageID MSG_WRITERR = "WRITERR";
+
+} // namespace log
+} // namespace isc
+
 namespace {
 
 const char* values[] = {
     "DUPLNS", "duplicate $NAMESPACE directive found",
     "DUPLPRFX", "duplicate $PREFIX directive found",
+    "DUPMSGID", "duplicate ID found in source code: %s",
     "IDNOTFND", "could not replace message for '%s': no such message identification",
     "NSEXTRARG", "$NAMESPACE directive has too many arguments",
     "NSINVARG", "$NAMESPACE directive has an invalid argument ('%s')",
@@ -18,18 +44,14 @@ const char* values[] = {
     "PRFEXTRARG", "$PREFIX directive has too many arguments",
     "PRFINVARG", "$PREFIX directive has an invalid argument ('%s')",
     "PRFNOARG", "no arguments were given to the $PREFIX directive",
+    "RDLOCMES", "reading local message file %s",
     "READERR", "error reading from %s: %s",
     "UNRECDIR", "unrecognised directive '%s'",
     "WRITERR", "error writing to %s: %s",
     NULL
 };
 
-} // Anonymous namespace
-
-namespace isc {
-namespace log {
+isc::log::MessageInitializer initializer(values);
 
-MessageInitializer messagedef_cc_Tue_Feb__8_18_01_54_2011(values);
+} // Anonymous namespace
 
-} // namespace log
-} // namespace isc
diff --git a/src/lib/log/messagedef.h b/src/lib/log/messagedef.h
index 8ad536e..829835a 100644
--- a/src/lib/log/messagedef.h
+++ b/src/lib/log/messagedef.h
@@ -1,49 +1,32 @@
-// File created from messagedef.mes on Tue Feb  8 18:01:54 2011
+// File created from messagedef.mes on Wed Feb  9 13:09:05 2011
 
 #ifndef __MESSAGEDEF_H
 #define __MESSAGEDEF_H
 
 #include <log/message_types.h>
-#include <log/message_initializer.h>
 
 namespace isc {
 namespace log {
 
-static const isc::log::MessageID MSG_DUPLNS = "DUPLNS";
-static const isc::log::MessageID MSG_DUPLPRFX = "DUPLPRFX";
-static const isc::log::MessageID MSG_IDNOTFND = "IDNOTFND";
-static const isc::log::MessageID MSG_NSEXTRARG = "NSEXTRARG";
-static const isc::log::MessageID MSG_NSINVARG = "NSINVARG";
-static const isc::log::MessageID MSG_NSNOARG = "NSNOARG";
-static const isc::log::MessageID MSG_ONETOKEN = "ONETOKEN";
-static const isc::log::MessageID MSG_OPENIN = "OPENIN";
-static const isc::log::MessageID MSG_OPENOUT = "OPENOUT";
-static const isc::log::MessageID MSG_PRFEXTRARG = "PRFEXTRARG";
-static const isc::log::MessageID MSG_PRFINVARG = "PRFINVARG";
-static const isc::log::MessageID MSG_PRFNOARG = "PRFNOARG";
-static const isc::log::MessageID MSG_READERR = "READERR";
-static const isc::log::MessageID MSG_UNRECDIR = "UNRECDIR";
-static const isc::log::MessageID MSG_WRITERR = "WRITERR";
+extern const isc::log::MessageID MSG_DUPLNS;
+extern const isc::log::MessageID MSG_DUPLPRFX;
+extern const isc::log::MessageID MSG_DUPMSGID;
+extern const isc::log::MessageID MSG_IDNOTFND;
+extern const isc::log::MessageID MSG_NSEXTRARG;
+extern const isc::log::MessageID MSG_NSINVARG;
+extern const isc::log::MessageID MSG_NSNOARG;
+extern const isc::log::MessageID MSG_ONETOKEN;
+extern const isc::log::MessageID MSG_OPENIN;
+extern const isc::log::MessageID MSG_OPENOUT;
+extern const isc::log::MessageID MSG_PRFEXTRARG;
+extern const isc::log::MessageID MSG_PRFINVARG;
+extern const isc::log::MessageID MSG_PRFNOARG;
+extern const isc::log::MessageID MSG_RDLOCMES;
+extern const isc::log::MessageID MSG_READERR;
+extern const isc::log::MessageID MSG_UNRECDIR;
+extern const isc::log::MessageID MSG_WRITERR;
 
 } // namespace log
 } // namespace isc
 
-namespace isc {
-namespace log {
-
-// The next two objects are needed to bring the default message
-// definitions into the program.  They make sure that the file
-// containing the message text is included in the link process.
-//
-// The objects are uniquely named (with file name and date and
-// time of compilation) to avoid clashes with other objects of
-// the same type, either by another #include or as a global
-// symbol in another module.
-
-extern MessageInitializer messagedef_cc_Tue_Feb__8_18_01_54_2011;
-static MessageInstantiator instantiate_messagedef_cc_Tue_Feb__8_18_01_54_2011(
-   &messagedef_cc_Tue_Feb__8_18_01_54_2011);
-
-} // namespace log
-} // namespace isc
 #endif // __MESSAGEDEF_H
diff --git a/src/lib/log/messagedef.mes b/src/lib/log/messagedef.mes
index 277a357..11312da 100644
--- a/src/lib/log/messagedef.mes
+++ b/src/lib/log/messagedef.mes
@@ -23,6 +23,13 @@ $NAMESPACE isc::log
 # chicken-and-egg situation where we need the files to build the message
 # compiler, yet we need the compiler to build the files.
 
+DUPMSGID  duplicate ID found in source code: %s
++ The same message identification appears in more that one file in the BIND10
++ source code.  Every message logged by BIND10 should have a unique
++ identification associated with it, so this indicates a failure in the build
++ process.  The develops should locate the duplicate IDs and alter one (or more)
++ of them.
+
 DUPLNS    duplicate $NAMESPACE directive found
 + When reading a message file, more than one $NAMESPACE directive was found.  In
 + this version of the code, such a condition is regarded as an error and the
@@ -91,6 +98,10 @@ PRFNOARG    no arguments were given to the $PREFIX directive
 + symbol names when a C++ .h file is created.  This error is generated when the
 + compiler finds a $PREFIX directive with no arguments.
 
+RDLOCMES    reading local message file %s
++ This is an informational message output on BIND start-up when it is about to
++ read a supplied local message file.
+
 READERR     error reading from %s: %s
 + The specified error was encountered reading from the named input file.
 
diff --git a/src/lib/log/root_logger_name.cc b/src/lib/log/root_logger_name.cc
index 5a233cd..34f1b41 100644
--- a/src/lib/log/root_logger_name.cc
+++ b/src/lib/log/root_logger_name.cc
@@ -18,10 +18,17 @@
 namespace isc {
 namespace log {
 
-std::string& RootLoggerName::rootName() {
-    static std::string root_name("");
-    return (root_name);
+static std::string root_name_;
+
+void
+setRootLoggerName(const std::string& name) {
+    root_name_ = name;
+}
+
+const std::string& getRootLoggerName() {
+    return root_name_;
 }
 
+
 }
 }
diff --git a/src/lib/log/root_logger_name.h b/src/lib/log/root_logger_name.h
index c80d800..1002567 100644
--- a/src/lib/log/root_logger_name.h
+++ b/src/lib/log/root_logger_name.h
@@ -27,45 +27,13 @@
 namespace isc {
 namespace log {
 
-class RootLoggerName {
-public:
-
-    /// \brief Constructor
-    ///
-    /// Sets the root logger name.  Although the name is static, setting the
-    /// name in the constructor allows static initialization of the name by
-    /// declaring an external instance of the class in the main execution unit.
-    RootLoggerName(const std::string& name) {
-        setName(name);
-    } 
-
-    /// \brief Set Root Logger Name
-    ///
-    /// \param name Name of the root logger.  This should be the program
-    /// name.
-    static void setName(const std::string& name) {
-        rootName() = name;
-    }
+/// \brief Set Root Logger Name
+///
+/// \param name Name of the root logger.  This should be the program
+/// name.
 
-    /// \brief Get Root Logger Name
-    ///
-    /// \return Name of the root logger.
-    static std::string getName() {
-        return (rootName());
-    }
-    
-private:
-    /// \brief Store Root Logger Name
-    ///
-    /// Access the singleton root logger name.  This is stored as a static
-    /// variable inside a method to avoid the "static initialization fiasco";
-    /// when accessed by another class during initialization, the name will be
-    /// instantiated. (Else it will be only by chance that it is instantiated
-    /// before the cassling class.)
-    ///
-    /// \return Name addisnged to the root logger.
-    static std::string& rootName();
-};
+void setRootLoggerName(const std::string& name);
+const std::string& getRootLoggerName();
 
 }
 }
diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am
index 8589501..9693270 100644
--- a/src/lib/log/tests/Makefile.am
+++ b/src/lib/log/tests/Makefile.am
@@ -22,8 +22,6 @@ run_unittests_SOURCES += message_dictionary_unittest.cc
 run_unittests_SOURCES += message_reader_unittest.cc
 run_unittests_SOURCES += message_initializer_unittest.cc
 run_unittests_SOURCES += message_initializer_unittest_2.cc
-run_unittests_SOURCES += message_types_unittest.cc
-run_unittests_SOURCES += message_types_unittest_2.cc
 run_unittests_SOURCES += strutil_unittest.cc
 # run_unittests_SOURCES += xdebuglevel_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
diff --git a/src/lib/log/tests/logger_support_test.cc b/src/lib/log/tests/logger_support_test.cc
index 7320862..ec77e6f 100644
--- a/src/lib/log/tests/logger_support_test.cc
+++ b/src/lib/log/tests/logger_support_test.cc
@@ -32,7 +32,6 @@
 using namespace isc::log;
 
 // Declare root logger and a loggers to use an example.
-RootLoggerName root("alpha");
 Logger logger_ex("example");
 Logger logger_dlm("dlm");
 
@@ -90,7 +89,7 @@ int main(int argc, char** argv) {
     }
 
     // Update the logging parameters
-    runTimeInit(severity, dbglevel, localfile);
+    init("alpha", severity, dbglevel, localfile);
 
     // Log a few messages
     logger_ex.fatal(MSG_WRITERR, "test1", "42");
diff --git a/src/lib/log/tests/logger_unittest.cc b/src/lib/log/tests/logger_unittest.cc
index 9504a5c..268515f 100644
--- a/src/lib/log/tests/logger_unittest.cc
+++ b/src/lib/log/tests/logger_unittest.cc
@@ -65,7 +65,7 @@ protected:
 TEST_F(LoggerTest, Name) {
 
     // Create a logger
-    RootLoggerName::setName("test1");
+    setRootLoggerName("test1");
     Logger logger("alpha");
 
     // ... and check the name
@@ -79,7 +79,7 @@ TEST_F(LoggerTest, GetLogger) {
 
     // Set the root logger name (not strictly needed, but this will be the
     // case in the program(.
-    RootLoggerName::setName("test2");
+    setRootLoggerName("test2");
 
     const string name1 = "alpha";
     const string name2 = "beta";
@@ -101,7 +101,7 @@ TEST_F(LoggerTest, GetLogger) {
 TEST_F(LoggerTest, Severity) {
 
     // Create a logger
-    RootLoggerName::setName("test3");
+    setRootLoggerName("test3");
     TestLogger logger("alpha");
 
     // Now check the levels
@@ -132,7 +132,7 @@ TEST_F(LoggerTest, Severity) {
 TEST_F(LoggerTest, DebugLevels) {
 
     // Create a logger
-    RootLoggerName::setName("test4");
+    setRootLoggerName("test4");
     TestLogger logger("alpha");
 
     // Debug level should be 0 if not at debug severity
@@ -178,7 +178,7 @@ TEST_F(LoggerTest, SeverityInheritance) {
     // implementation (in this case log4cxx) will set a parent-child
     // relationship if the loggers are named <parent> and <parent>.<child>.
 
-    RootLoggerName::setName("test5");
+    setRootLoggerName("test5");
     TestLogger parent("alpha");
     TestLogger child("alpha.beta");
 
@@ -210,7 +210,7 @@ TEST_F(LoggerTest, EffectiveSeverityInheritance) {
     // implementation (in this case log4cxx) will set a parent-child
     // relationship if the loggers are named <parent> and <parent>.<child>.
 
-    RootLoggerName::setName("test6");
+    setRootLoggerName("test6");
     Logger parent("test6");
     Logger child("test6.beta");
 
@@ -245,7 +245,7 @@ TEST_F(LoggerTest, EffectiveSeverityInheritance) {
 
 TEST_F(LoggerTest, IsXxxEnabled) {
 
-    RootLoggerName::setName("test7");
+    setRootLoggerName("test7");
     Logger logger("test7");
 
     logger.setSeverity(isc::log::INFO);
@@ -316,7 +316,7 @@ TEST_F(LoggerTest, IsXxxEnabled) {
 
 TEST_F(LoggerTest, IsDebugEnabledLevel) {
 
-    RootLoggerName::setName("test8");
+    setRootLoggerName("test8");
     Logger logger("test8");
 
     int MID_LEVEL = (MIN_DEBUG_LEVEL + MAX_DEBUG_LEVEL) / 2;
diff --git a/src/lib/log/tests/message_dictionary_unittest.cc b/src/lib/log/tests/message_dictionary_unittest.cc
index 4b36070..8ae179a 100644
--- a/src/lib/log/tests/message_dictionary_unittest.cc
+++ b/src/lib/log/tests/message_dictionary_unittest.cc
@@ -16,12 +16,29 @@
 #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.
+
+static const char* values[] = {
+    "DUPLNS", "duplicate $NAMESPACE directive found",
+    "NEWSYM", "new symbol added",
+    NULL
+};
+
+MessageInitializer init(values);
+
+
+
+
 class MessageDictionaryTest : public ::testing::Test {
 protected:
     MessageDictionaryTest() : 
@@ -40,17 +57,6 @@ protected:
 
 };
 
-
-// Check that the global dictionary is a singleton.
-
-TEST_F(MessageDictionaryTest, GlobalTest) {
-    MessageDictionary* global = MessageDictionary::globalDictionary();
-    EXPECT_FALSE(NULL == global);
-
-    MessageDictionary* global2 = MessageDictionary::globalDictionary();
-    EXPECT_EQ(global2, global);
-}
-
 // Check that adding messages works
 
 TEST_F(MessageDictionaryTest, Add) {
@@ -169,3 +175,23 @@ TEST_F(MessageDictionaryTest, Lookups) {
     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) {
+    MessageDictionary& global = MessageDictionary::globalDictionary();
+    MessageDictionary& global2 = MessageDictionary::globalDictionary();
+    EXPECT_TRUE(&global2 == &global);
+}
+
+// Check that the global dictionary has detected the duplicate and the
+// new symbol.
+
+TEST_F(MessageDictionaryTest, GlobalLoadTest) {
+    vector<string>& duplicates = MessageInitializer::getDuplicates();
+    ASSERT_EQ(1, duplicates.size());
+    EXPECT_EQ(string("DUPLNS"), duplicates[0]);
+
+    string text = MessageDictionary::globalDictionary().getText("NEWSYM");
+    EXPECT_EQ(string("new symbol added"), text);
+}
\ No newline at end of file
diff --git a/src/lib/log/tests/message_initializer_unittest.cc b/src/lib/log/tests/message_initializer_unittest.cc
index bc38588..71d31a5 100644
--- a/src/lib/log/tests/message_initializer_unittest.cc
+++ b/src/lib/log/tests/message_initializer_unittest.cc
@@ -59,12 +59,12 @@ protected:
 // messages.
 
 TEST_F(MessageInitializerTest, MessageTest) {
-    MessageDictionary* global = MessageDictionary::globalDictionary();
+    MessageDictionary& global = MessageDictionary::globalDictionary();
 
-    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"));
+    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"));
 }
diff --git a/src/lib/log/tests/message_types_unittest.cc b/src/lib/log/tests/message_types_unittest.cc
deleted file mode 100644
index 0c95c48..0000000
--- a/src/lib/log/tests/message_types_unittest.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2011  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 <gtest/gtest.h>
-#include <log/message_types.h>
-#include <log/messagedef.h>
-
-using namespace isc::log;
-
-class MessageTypesTest : public ::testing::Test {
-public:
-    MessageTypesTest()
-    {
-    }
-};
-
-MessageID MessageTypeTest_MSG_DUPLNS();
-
-
-// Check that the message type equality check works.  This compares
-// two message IDs in the "messagedef.h" file declared here, with
-// the returned ID (which should be MSG_DUPLNS) declared elsewhere.
-
-TEST_F(MessageTypesTest, EqualID) {
-    EXPECT_TRUE(equalMessageID(MSG_DUPLNS, MSG_DUPLNS));
-    EXPECT_FALSE(equalMessageID(MSG_DUPLNS, MSG_DUPLPRFX));
-    EXPECT_TRUE(equalMessageID(MSG_DUPLNS, MessageTypeTest_MSG_DUPLNS()));
-}
diff --git a/src/lib/log/tests/message_types_unittest_2.cc b/src/lib/log/tests/message_types_unittest_2.cc
deleted file mode 100644
index cc51734..0000000
--- a/src/lib/log/tests/message_types_unittest_2.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2011  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/message_types.h>
-#include <log/messagedef.h>
-
-// Return a value for testing in message_types_unittest.cc
-
-isc::log::MessageID MessageTypeTest_MSG_DUPLNS() {
-    return (isc::log::MSG_DUPLNS);
-}
diff --git a/src/lib/log/tests/root_logger_name_unittest.cc b/src/lib/log/tests/root_logger_name_unittest.cc
index a16a9ea..91896df 100644
--- a/src/lib/log/tests/root_logger_name_unittest.cc
+++ b/src/lib/log/tests/root_logger_name_unittest.cc
@@ -35,8 +35,8 @@ TEST_F(RootLoggerNameTest, SetGet) {
     const std::string name2 = "test2";
 
     // Check that Set/Get works
-    RootLoggerName::setName(name1);
-    EXPECT_EQ(name1, RootLoggerName::getName());
+    setRootLoggerName(name1);
+    EXPECT_EQ(name1, getRootLoggerName());
 
     // We could not test that the root logger name is initialised
     // correctly (as there is one instance of it and we don't know
@@ -45,6 +45,6 @@ TEST_F(RootLoggerNameTest, SetGet) {
     //
     // (There was always the outside chance that the root logger name
     // was initialised with name1 and that setName() has no effect.)
-    RootLoggerName::setName(name2);
-    EXPECT_EQ(name2, RootLoggerName::getName());
+    setRootLoggerName(name2);
+    EXPECT_EQ(name2, getRootLoggerName());
 }
diff --git a/src/lib/log/tests/run_time_init_test.sh.in b/src/lib/log/tests/run_time_init_test.sh.in
index 68e42da..0d86c39 100755
--- a/src/lib/log/tests/run_time_init_test.sh.in
+++ b/src/lib/log/tests/run_time_init_test.sh.in
@@ -73,9 +73,8 @@ WARN  [alpha.log] IDNOTFND, could not replace message for 'NOTHERE': no such mes
 FATAL [alpha.example] WRITERR, error writing to test1: 42
 ERROR [alpha.example] UNRECDIR, replacement unrecognised directive message, parameter is 'false'
 WARN  [alpha.dlm] READERR, replacement read error, parameters: 'a.txt' and 'dummy test'
-INFO  [alpha.dlm] OPENIN, unable to open message file example.msg for input: dummy test
 .
-./logger_support_test $localmes | cut -d' ' -f3- | diff $tempfile -
+./logger_support_test -s warn $localmes | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 rm -f $localmes




More information about the bind10-changes mailing list