Browse Source

[master]Merge branch 'master' of ssh://git.bind10.isc.org/var/bind10/git/bind10

fix conflict in changelog
Jeremy C. Reed 12 years ago
parent
commit
77249210b9

+ 10 - 1
ChangeLog

@@ -1,8 +1,17 @@
-587.	[bug]*		jreed
+588.	[bug]*		jreed
 	b10-xfrout: Log message id XFROUT_QUERY_QUOTA_EXCCEEDED
 	b10-xfrout: Log message id XFROUT_QUERY_QUOTA_EXCCEEDED
 	changed to XFROUT_QUERY_QUOTA_EXCEEDED.
 	changed to XFROUT_QUERY_QUOTA_EXCEEDED.
 	(git be41be890f1349ae4c870a887f7acd99ba1eaac5)
 	(git be41be890f1349ae4c870a887f7acd99ba1eaac5)
 
 
+587.	[bug]		jelte
+	When used from python, the dynamic datasource factory now
+	explicitely loads the logging messages dictionary, so that correct
+	logging messages does not depend on incidental earlier import
+	statements. Also, the sqlite3-specific log messages have been moved
+	from the general datasource library to the sqlite3 datasource
+	(which also explicitely loads its messages).
+	(Trac 2746, git 1c004d95a8b715500af448683e4a07e9b66ea926)
+
 586.	[func]		marcin
 586.	[func]		marcin
 	libdhcp++: Removed unnecesary calls to the function which
 	libdhcp++: Removed unnecesary calls to the function which
 	validates option definitions used to create instances of options
 	validates option definitions used to create instances of options

+ 6 - 1
src/lib/datasrc/Makefile.am

@@ -19,6 +19,7 @@ static.zone: static.zone.pre $(top_builddir)/config.h $(top_srcdir)/AUTHORS
 	$(SED) -e 's/\(.*\)/AUTHORS.BIND.	0	CH	TXT	"\1"/' $(top_srcdir)/AUTHORS >>$@
 	$(SED) -e 's/\(.*\)/AUTHORS.BIND.	0	CH	TXT	"\1"/' $(top_srcdir)/AUTHORS >>$@
 
 
 CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
 CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
+CLEANFILES += sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc
 CLEANFILES += datasrc_config.h
 CLEANFILES += datasrc_config.h
 CLEANFILES += static.zone
 CLEANFILES += static.zone
 
 
@@ -45,6 +46,7 @@ pkglib_LTLIBRARIES = sqlite3_ds.la static_ds.la
 
 
 sqlite3_ds_la_SOURCES = sqlite3_accessor.h sqlite3_accessor.cc
 sqlite3_ds_la_SOURCES = sqlite3_accessor.h sqlite3_accessor.cc
 sqlite3_ds_la_SOURCES += sqlite3_accessor_link.cc
 sqlite3_ds_la_SOURCES += sqlite3_accessor_link.cc
+nodist_sqlite3_ds_la_SOURCES = sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc
 sqlite3_ds_la_LDFLAGS = -module -avoid-version
 sqlite3_ds_la_LDFLAGS = -module -avoid-version
 sqlite3_ds_la_LDFLAGS += -no-undefined -version-info 1:0:0
 sqlite3_ds_la_LDFLAGS += -no-undefined -version-info 1:0:0
 sqlite3_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
 sqlite3_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
@@ -65,10 +67,13 @@ libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/datasrc/memory/libdatasrc_me
 libb10_datasrc_la_LIBADD += $(SQLITE_LIBS)
 libb10_datasrc_la_LIBADD += $(SQLITE_LIBS)
 
 
 BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
 BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
+BUILT_SOURCES += sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc
 datasrc_messages.h datasrc_messages.cc: Makefile datasrc_messages.mes
 datasrc_messages.h datasrc_messages.cc: Makefile datasrc_messages.mes
 	$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/datasrc/datasrc_messages.mes
 	$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/datasrc/datasrc_messages.mes
+sqlite3_datasrc_messages.h sqlite3_datasrc_messages.cc: Makefile sqlite3_datasrc_messages.mes
+	$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/datasrc/sqlite3_datasrc_messages.mes
 
 
-EXTRA_DIST = datasrc_messages.mes static.zone.pre
+EXTRA_DIST = datasrc_messages.mes sqlite3_datasrc_messages.mes static.zone.pre
 
 
 zonedir = $(pkgdatadir)
 zonedir = $(pkgdatadir)
 zone_DATA = static.zone
 zone_DATA = static.zone

+ 0 - 125
src/lib/datasrc/datasrc_messages.mes

@@ -550,131 +550,6 @@ given domain or record.  The code is 1 for error and 2 for not implemented.
 While processing a wildcard, a referral was met. But it wasn't possible to get
 While processing a wildcard, a referral was met. But it wasn't possible to get
 enough information for it.  The code is 1 for error, 2 for not implemented.
 enough information for it.  The code is 1 for error, 2 for not implemented.
 
 
-% DATASRC_SQLITE_CLOSE closing SQLite database
-Debug information. The SQLite data source is closing the database file.
-
-% DATASRC_SQLITE_COMPATIBLE_VERSION database schema V%1.%2 not up to date (expecting V%3.%4) but is compatible
-The version of the SQLite3 database schema used to hold the zone data
-is not the latest one - the current version of BIND 10 was written
-with a later schema version in mind.  However, the database is
-compatible with the current version of BIND 10, and BIND 10 will run
-without any problems.
-
-Consult the release notes for your version of BIND 10.  Depending on
-the changes made to the database schema, it is possible that improved
-performance could result if the database were upgraded.
-
-% DATASRC_SQLITE_CONNCLOSE Closing sqlite database
-The database file is no longer needed and is being closed.
-
-% DATASRC_SQLITE_CONNOPEN Opening sqlite database file '%1'
-The database file is being opened so it can start providing data.
-
-% DATASRC_SQLITE_CREATE SQLite data source created
-Debug information. An instance of SQLite data source is being created.
-
-% DATASRC_SQLITE_DESTROY SQLite data source destroyed
-Debug information. An instance of SQLite data source is being destroyed.
-
-% DATASRC_SQLITE_DROPCONN SQLite3Database is being deinitialized
-The object around a database connection is being destroyed.
-
-% DATASRC_SQLITE_ENCLOSURE looking for zone containing '%1'
-Debug information. The SQLite data source is trying to identify which zone
-should hold this domain.
-
-% DATASRC_SQLITE_ENCLOSURE_NOT_FOUND no zone contains '%1'
-Debug information. The last SQLITE_ENCLOSURE query was unsuccessful; there's
-no such zone in our data.
-
-% DATASRC_SQLITE_FIND looking for RRset '%1/%2'
-Debug information. The SQLite data source is looking up a resource record
-set.
-
-% DATASRC_SQLITE_FINDADDRS looking for A/AAAA addresses for '%1'
-Debug information. The data source is looking up the addresses for given
-domain name.
-
-% DATASRC_SQLITE_FINDADDRS_BAD_CLASS class mismatch looking for addresses ('%1' and '%2')
-The SQLite data source was looking up A/AAAA addresses, but the data source
-contains different class than the query was for.
-
-% DATASRC_SQLITE_FINDEXACT looking for exact RRset '%1/%2'
-Debug information. The SQLite data source is looking up an exact resource
-record.
-
-% DATASRC_SQLITE_FINDEXACT_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
-The SQLite data source was looking up an exact RRset, but the data source
-contains different class than the query was for.
-
-% DATASRC_SQLITE_FINDREC looking for record '%1/%2'
-Debug information. The SQLite data source is looking up records of given name
-and type in the database.
-
-% DATASRC_SQLITE_FINDREF looking for referral at '%1'
-Debug information. The SQLite data source is identifying if this domain is
-a referral and where it goes.
-
-% DATASRC_SQLITE_FINDREF_BAD_CLASS class mismatch looking for referral ('%1' and '%2')
-The SQLite data source was trying to identify if there's a referral. But
-it contains different class than the query was for.
-
-% DATASRC_SQLITE_FIND_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
-The SQLite data source was looking up an RRset, but the data source contains
-different class than the query was for.
-
-% DATASRC_SQLITE_FIND_NSEC3 looking for NSEC3 in zone '%1' for hash '%2'
-Debug information. We're trying to look up a NSEC3 record in the SQLite data
-source.
-
-% DATASRC_SQLITE_FIND_NSEC3_NO_ZONE no such zone '%1'
-The SQLite data source was asked to provide a NSEC3 record for given zone.
-But it doesn't contain that zone.
-
-% DATASRC_SQLITE_INCOMPATIBLE_VERSION database schema V%1.%2 incompatible with version (V%3.%4) expected
-The version of the SQLite3 database schema used to hold the zone data
-is incompatible with the version expected by BIND 10.  As a result,
-BIND 10 is unable to run using the database file as the data source.
-
-The database should be updated using the means described in the BIND
-10 documentation.
-
-% DATASRC_SQLITE_NEWCONN SQLite3Database is being initialized
-A wrapper object to hold database connection is being initialized.
-
-% DATASRC_SQLITE_OPEN opening SQLite database '%1'
-Debug information. The SQLite data source is loading an SQLite database in
-the provided file.
-
-% DATASRC_SQLITE_PREVIOUS looking for name previous to '%1'
-This is a debug message.  The name given was not found, so the program
-is searching for the next name higher up the hierarchy (e.g. if
-www.example.com were queried for and not found, the software searches
-for the "previous" name, example.com).
-
-% DATASRC_SQLITE_PREVIOUS_NO_ZONE no zone containing '%1'
-The name given was not found, so the program is searching for the next
-name higher up the hierarchy (e.g. if www.example.com were queried
-for and not found, the software searches for the "previous" name,
-example.com). However, this name is not contained in any zone in the
-data source. This is an error since it indicates a problem in the earlier
-processing of the query.
-
-% DATASRC_SQLITE_SETUP setting up new SQLite3 database in '%1'
-The database for SQLite data source was found empty. It is assumed this is the
-first run and it is being initialized with current schema.  It'll still contain
-no data, but it will be ready for use. If this is indeed the first run of
-BIND 10, it is to be expected and completely harmless. If you just configured
-a data source to point to an existing file and you see this, you may have
-misspelled the file name.
-
-% DATASRC_SQLITE_SETUP_OLD_API setting up new SQLite database
-The database for SQLite data source was found empty. It is assumed this is the
-first run and it is being initialized with current schema.  It'll still contain
-no data, but it will be ready for use. This is similar to DATASRC_SQLITE_SETUP
-message, but it is logged from the old API. You should never see it, since the
-API is deprecated.
-
 % DATASRC_STATIC_CLASS_NOT_CH static data source can handle CH class only
 % DATASRC_STATIC_CLASS_NOT_CH static data source can handle CH class only
 An error message indicating that a query requesting a RR for a class other
 An error message indicating that a query requesting a RR for a class other
 that CH was sent to the static data source (which only handles CH queries).
 that CH was sent to the static data source (which only handles CH queries).

+ 1 - 0
src/lib/datasrc/sqlite3_accessor.cc

@@ -23,6 +23,7 @@
 #include <dns/name.h>
 #include <dns/name.h>
 
 
 #include <datasrc/sqlite3_accessor.h>
 #include <datasrc/sqlite3_accessor.h>
+#include <datasrc/sqlite3_datasrc_messages.h>
 #include <datasrc/logger.h>
 #include <datasrc/logger.h>
 #include <datasrc/data_source.h>
 #include <datasrc/data_source.h>
 #include <datasrc/factory.h>
 #include <datasrc/factory.h>

+ 5 - 0
src/lib/datasrc/sqlite3_accessor_link.cc

@@ -19,6 +19,8 @@
 #include <datasrc/sqlite3_accessor.h>
 #include <datasrc/sqlite3_accessor.h>
 #include <datasrc/database.h>
 #include <datasrc/database.h>
 
 
+#include <log/message_initializer.h>
+
 #include <string>
 #include <string>
 
 
 using namespace std;
 using namespace std;
@@ -77,6 +79,9 @@ checkConfig(ConstElementPtr config, ElementPtr errors) {
 
 
 DataSourceClient *
 DataSourceClient *
 createInstance(isc::data::ConstElementPtr config, std::string& error) {
 createInstance(isc::data::ConstElementPtr config, std::string& error) {
+    // Initialize the logging dictionary
+    isc::log::MessageInitializer::loadDictionary(true);
+
     ElementPtr errors(Element::createList());
     ElementPtr errors(Element::createList());
     if (!checkConfig(config, errors)) {
     if (!checkConfig(config, errors)) {
         error = "Configuration error: " + errors->str();
         error = "Configuration error: " + errors->str();

+ 142 - 0
src/lib/datasrc/sqlite3_datasrc_messages.mes

@@ -0,0 +1,142 @@
+# Copyright (C) 2013  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.
+
+$NAMESPACE isc::datasrc
+
+# \brief Messages for the SQLITE3 data source backend
+
+% DATASRC_SQLITE_CLOSE closing SQLite database
+Debug information. The SQLite data source is closing the database file.
+
+% DATASRC_SQLITE_COMPATIBLE_VERSION database schema V%1.%2 not up to date (expecting V%3.%4) but is compatible
+The version of the SQLite3 database schema used to hold the zone data
+is not the latest one - the current version of BIND 10 was written
+with a later schema version in mind.  However, the database is
+compatible with the current version of BIND 10, and BIND 10 will run
+without any problems.
+
+Consult the release notes for your version of BIND 10.  Depending on
+the changes made to the database schema, it is possible that improved
+performance could result if the database were upgraded.
+
+% DATASRC_SQLITE_CONNCLOSE Closing sqlite database
+The database file is no longer needed and is being closed.
+
+% DATASRC_SQLITE_CONNOPEN Opening sqlite database file '%1'
+The database file is being opened so it can start providing data.
+
+% DATASRC_SQLITE_CREATE SQLite data source created
+Debug information. An instance of SQLite data source is being created.
+
+% DATASRC_SQLITE_DESTROY SQLite data source destroyed
+Debug information. An instance of SQLite data source is being destroyed.
+
+% DATASRC_SQLITE_DROPCONN SQLite3Database is being deinitialized
+The object around a database connection is being destroyed.
+
+% DATASRC_SQLITE_ENCLOSURE looking for zone containing '%1'
+Debug information. The SQLite data source is trying to identify which zone
+should hold this domain.
+
+% DATASRC_SQLITE_ENCLOSURE_NOT_FOUND no zone contains '%1'
+Debug information. The last SQLITE_ENCLOSURE query was unsuccessful; there's
+no such zone in our data.
+
+% DATASRC_SQLITE_FIND looking for RRset '%1/%2'
+Debug information. The SQLite data source is looking up a resource record
+set.
+
+% DATASRC_SQLITE_FINDADDRS looking for A/AAAA addresses for '%1'
+Debug information. The data source is looking up the addresses for given
+domain name.
+
+% DATASRC_SQLITE_FINDADDRS_BAD_CLASS class mismatch looking for addresses ('%1' and '%2')
+The SQLite data source was looking up A/AAAA addresses, but the data source
+contains different class than the query was for.
+
+% DATASRC_SQLITE_FINDEXACT looking for exact RRset '%1/%2'
+Debug information. The SQLite data source is looking up an exact resource
+record.
+
+% DATASRC_SQLITE_FINDEXACT_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
+The SQLite data source was looking up an exact RRset, but the data source
+contains different class than the query was for.
+
+% DATASRC_SQLITE_FINDREC looking for record '%1/%2'
+Debug information. The SQLite data source is looking up records of given name
+and type in the database.
+
+% DATASRC_SQLITE_FINDREF looking for referral at '%1'
+Debug information. The SQLite data source is identifying if this domain is
+a referral and where it goes.
+
+% DATASRC_SQLITE_FINDREF_BAD_CLASS class mismatch looking for referral ('%1' and '%2')
+The SQLite data source was trying to identify if there's a referral. But
+it contains different class than the query was for.
+
+% DATASRC_SQLITE_FIND_BAD_CLASS class mismatch looking for an RRset ('%1' and '%2')
+The SQLite data source was looking up an RRset, but the data source contains
+different class than the query was for.
+
+% DATASRC_SQLITE_FIND_NSEC3 looking for NSEC3 in zone '%1' for hash '%2'
+Debug information. We're trying to look up a NSEC3 record in the SQLite data
+source.
+
+% DATASRC_SQLITE_FIND_NSEC3_NO_ZONE no such zone '%1'
+The SQLite data source was asked to provide a NSEC3 record for given zone.
+But it doesn't contain that zone.
+
+% DATASRC_SQLITE_INCOMPATIBLE_VERSION database schema V%1.%2 incompatible with version (V%3.%4) expected
+The version of the SQLite3 database schema used to hold the zone data
+is incompatible with the version expected by BIND 10.  As a result,
+BIND 10 is unable to run using the database file as the data source.
+
+The database should be updated using the means described in the BIND
+10 documentation.
+
+% DATASRC_SQLITE_NEWCONN SQLite3Database is being initialized
+A wrapper object to hold database connection is being initialized.
+
+% DATASRC_SQLITE_OPEN opening SQLite database '%1'
+Debug information. The SQLite data source is loading an SQLite database in
+the provided file.
+
+% DATASRC_SQLITE_PREVIOUS looking for name previous to '%1'
+This is a debug message.  The name given was not found, so the program
+is searching for the next name higher up the hierarchy (e.g. if
+www.example.com were queried for and not found, the software searches
+for the "previous" name, example.com).
+
+% DATASRC_SQLITE_PREVIOUS_NO_ZONE no zone containing '%1'
+The name given was not found, so the program is searching for the next
+name higher up the hierarchy (e.g. if www.example.com were queried
+for and not found, the software searches for the "previous" name,
+example.com). However, this name is not contained in any zone in the
+data source. This is an error since it indicates a problem in the earlier
+processing of the query.
+
+% DATASRC_SQLITE_SETUP setting up new SQLite3 database in '%1'
+The database for SQLite data source was found empty. It is assumed this is the
+first run and it is being initialized with current schema.  It'll still contain
+no data, but it will be ready for use. If this is indeed the first run of
+BIND 10, it is to be expected and completely harmless. If you just configured
+a data source to point to an existing file and you see this, you may have
+misspelled the file name.
+
+% DATASRC_SQLITE_SETUP_OLD_API setting up new SQLite database
+The database for SQLite data source was found empty. It is assumed this is the
+first run and it is being initialized with current schema.  It'll still contain
+no data, but it will be ready for use. This is similar to DATASRC_SQLITE_SETUP
+message, but it is logged from the old API. You should never see it, since the
+API is deprecated.

+ 3 - 1
src/lib/datasrc/tests/Makefile.am

@@ -62,6 +62,8 @@ run_unittests_SOURCES += zone_loader_unittest.cc
 # We need the actual module implementation in the tests (they are not part
 # We need the actual module implementation in the tests (they are not part
 # of libdatasrc)
 # of libdatasrc)
 run_unittests_SOURCES += $(top_srcdir)/src/lib/datasrc/sqlite3_accessor.cc
 run_unittests_SOURCES += $(top_srcdir)/src/lib/datasrc/sqlite3_accessor.cc
+# Also, as of #2746, sqlite3-specific log messages are in a separate file
+nodist_run_unittests_SOURCES = $(abs_top_builddir)/src/lib/datasrc/sqlite3_datasrc_messages.cc
 
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
 run_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
@@ -71,7 +73,7 @@ run_unittests_LDADD = $(common_ldadd)
 noinst_PROGRAMS+= $(TESTS)
 noinst_PROGRAMS+= $(TESTS)
 
 
 # For the factory unit tests, we need to specify that we want
 # For the factory unit tests, we need to specify that we want
-# the loadable backend libraries from the build tree, and not from 
+# the loadable backend libraries from the build tree, and not from
 # the installation directory. Therefore we build it into a separate
 # the installation directory. Therefore we build it into a separate
 # binary, and call that from check-local with B10_FROM_BUILD set.
 # binary, and call that from check-local with B10_FROM_BUILD set.
 # Also, we only want to do this when static building is not used,
 # Also, we only want to do this when static building is not used,

+ 5 - 7
src/lib/log/logger_manager.cc

@@ -121,19 +121,17 @@ LoggerManager::init(const std::string& root, isc::log::Severity severity,
 
 
     // Check if there were any duplicate message IDs in the default dictionary
     // Check if there were any duplicate message IDs in the default dictionary
     // and if so, log them.  Log using the logging facility logger.
     // and if so, log them.  Log using the logging facility logger.
-    vector<string>& duplicates = MessageInitializer::getDuplicates();
+    const vector<string>& duplicates = MessageInitializer::getDuplicates();
     if (!duplicates.empty()) {
     if (!duplicates.empty()) {
 
 
-        // There are duplicates present.  This will be listed in alphabetic
-        // order of message ID, so they need to be sorted.  This list itself may
-        // contain duplicates; if so, the message ID is listed as many times as
+        // There are duplicates present. This list itself may contain
+        // duplicates; if so, the message ID is listed as many times as
         // there are duplicates.
         // there are duplicates.
-        sort(duplicates.begin(), duplicates.end());
-        for (vector<string>::iterator i = duplicates.begin();
+        for (vector<string>::const_iterator i = duplicates.begin();
              i != duplicates.end(); ++i) {
              i != duplicates.end(); ++i) {
             LOG_WARN(logger, LOG_DUPLICATE_MESSAGE_ID).arg(*i);
             LOG_WARN(logger, LOG_DUPLICATE_MESSAGE_ID).arg(*i);
         }
         }
-
+        MessageInitializer::clearDuplicates();
     }
     }
 
 
     // Replace any messages with local ones (if given)
     // Replace any messages with local ones (if given)

+ 3 - 0
src/lib/log/logger_manager.h

@@ -100,6 +100,9 @@ public:
     /// an attempt is made to log a message before this is function is called,
     /// an attempt is made to log a message before this is function is called,
     /// the results will be dependent on the underlying logging package.
     /// the results will be dependent on the underlying logging package.
     ///
     ///
+    /// Any duplicate log IDs encountered are reported as warning, after which
+    /// the global duplicates vector is cleared
+    ///
     /// \param root Name of the root logger.  This should be set to the name of
     /// \param root Name of the root logger.  This should be set to the name of
     ///        the program.
     ///        the program.
     /// \param severity Severity at which to log
     /// \param severity Severity at which to log

+ 18 - 7
src/lib/log/message_initializer.cc

@@ -42,7 +42,13 @@ size_t& getIndex() {
     return (index);
     return (index);
 }
 }
 
 
+// Return the duplicates singleton version (non-const for local use)
+std::vector<std::string>&
+getNonConstDuplicates() {
+    static std::vector<std::string> duplicates;
+    return (duplicates);
 }
 }
+} // end unnamed namespace
 
 
 
 
 namespace isc {
 namespace isc {
@@ -67,7 +73,7 @@ MessageInitializer::getPendingCount() {
 // into the global dictionary.
 // into the global dictionary.
 
 
 void
 void
-MessageInitializer::loadDictionary() {
+MessageInitializer::loadDictionary(bool ignore_duplicates) {
     MessageDictionary& global = MessageDictionary::globalDictionary();
     MessageDictionary& global = MessageDictionary::globalDictionary();
 
 
     for (size_t i = 0; i < getIndex(); ++i) {
     for (size_t i = 0; i < getIndex(); ++i) {
@@ -75,8 +81,8 @@ MessageInitializer::loadDictionary() {
 
 
         // Append the IDs in the list just loaded (the "repeats") to the
         // Append the IDs in the list just loaded (the "repeats") to the
         // global list of duplicate IDs.
         // global list of duplicate IDs.
-        if (!repeats.empty()) {
-            std::vector<std::string>& duplicates = getDuplicates();
+        if (!ignore_duplicates && !repeats.empty()) {
+            std::vector<std::string>& duplicates = getNonConstDuplicates();
             duplicates.insert(duplicates.end(), repeats.begin(),
             duplicates.insert(duplicates.end(), repeats.begin(),
                               repeats.end());
                               repeats.end());
         }
         }
@@ -88,11 +94,16 @@ MessageInitializer::loadDictionary() {
     getIndex() = 0;
     getIndex() = 0;
 }
 }
 
 
-// Return reference to duplicate array
+// Return reference to duplicates vector
+const std::vector<std::string>&
+MessageInitializer::getDuplicates() {
+    return (getNonConstDuplicates());
+}
 
 
-std::vector<std::string>& MessageInitializer::getDuplicates() {
-    static std::vector<std::string> duplicates;
-    return (duplicates);
+// Clear the duplicates vector
+void
+MessageInitializer::clearDuplicates() {
+    getNonConstDuplicates().clear();
 }
 }
 
 
 } // namespace log
 } // namespace log

+ 14 - 2
src/lib/log/message_initializer.h

@@ -43,6 +43,9 @@ namespace log {
 /// All that needed is for the module containing the definitions to be
 /// All that needed is for the module containing the definitions to be
 /// included in the execution unit.
 /// included in the execution unit.
 ///
 ///
+/// Dynamically loaded modules should call the initializer as well on the
+/// moment they are instantiated.
+///
 /// To avoid static initialization fiasco problems, the initialization is
 /// To avoid static initialization fiasco problems, the initialization is
 /// carried out in two stages:
 /// carried out in two stages:
 /// - The constructor adds a pointer to the values array to a pre-defined array
 /// - The constructor adds a pointer to the values array to a pre-defined array
@@ -93,7 +96,11 @@ public:
     /// Loops through the internal array of pointers to message arrays
     /// Loops through the internal array of pointers to message arrays
     /// and adds the messages to the internal dictionary.  This is called
     /// and adds the messages to the internal dictionary.  This is called
     /// during run-time initialization.
     /// during run-time initialization.
-    static void loadDictionary();
+    ///
+    /// \param ignore_duplicates If true, duplicate IDs, and IDs already
+    ///        loaded, are ignored instead of stored in the global duplicates
+    ///        vector.
+    static void loadDictionary(bool ignore_duplicates = false);
 
 
     /// \brief Return Duplicates
     /// \brief Return Duplicates
     ///
     ///
@@ -102,7 +109,12 @@ public:
     ///
     ///
     /// \return List of duplicate message IDs when the global dictionary was
     /// \return List of duplicate message IDs when the global dictionary was
     /// loaded.  Note that the duplicates list itself may contain duplicates.
     /// loaded.  Note that the duplicates list itself may contain duplicates.
-    static std::vector<std::string>& getDuplicates();
+    static const std::vector<std::string>& getDuplicates();
+
+    /// \brief Clear the static duplicates vector
+    ///
+    /// Empties the vector returned by getDuplicates()
+    static void clearDuplicates();
 };
 };
 
 
 } // namespace log
 } // namespace log

+ 2 - 3
src/lib/log/tests/message_dictionary_unittest.cc

@@ -189,9 +189,8 @@ TEST_F(MessageDictionaryTest, GlobalTest) {
 // new symbol.
 // new symbol.
 
 
 TEST_F(MessageDictionaryTest, GlobalLoadTest) {
 TEST_F(MessageDictionaryTest, GlobalLoadTest) {
-    vector<string>& duplicates = MessageInitializer::getDuplicates();
-    ASSERT_EQ(1, duplicates.size());
-    EXPECT_EQ(string("LOG_DUPLICATE_NAMESPACE"), duplicates[0]);
+    // There were duplicates but the vector should be cleared in init() now
+    ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
 
 
     string text = MessageDictionary::globalDictionary().getText("NEWSYM");
     string text = MessageDictionary::globalDictionary().getText("NEWSYM");
     EXPECT_EQ(string("new symbol added"), text);
     EXPECT_EQ(string("new symbol added"), text);

+ 34 - 0
src/lib/log/tests/message_initializer_1_unittest.cc

@@ -77,3 +77,37 @@ TEST(MessageInitializerTest1, MessageTest) {
     EXPECT_EQ(string("global message five"), global.getText("GLOBAL5"));
     EXPECT_EQ(string("global message five"), global.getText("GLOBAL5"));
     EXPECT_EQ(string("global message six"), global.getText("GLOBAL6"));
     EXPECT_EQ(string("global message six"), global.getText("GLOBAL6"));
 }
 }
+
+TEST(MessageInitializerTest1, Duplicates) {
+    // Original set should not have dupes
+    ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+
+    // This just defines 1, but we'll add it a number of times
+    const char* dupe[] = {
+        "DUPE", "dupe",
+        NULL
+    };
+    const MessageInitializer init_message_initializer_unittest_1(dupe);
+    const MessageInitializer init_message_initializer_unittest_2(dupe);
+
+    MessageInitializer::loadDictionary();
+    // Should be a dupe now
+    ASSERT_EQ(1, MessageInitializer::getDuplicates().size());
+
+    // clear them
+    MessageInitializer::clearDuplicates();
+    ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+
+    // Do it again to make sure, let's explicitely provide false now
+    const MessageInitializer init_message_initializer_unittest_3(dupe);
+    MessageInitializer::loadDictionary(false);
+    ASSERT_EQ(1, MessageInitializer::getDuplicates().size());
+
+    // Loading with ignore_duplicates=true should result in no (reported)
+    // dupes
+    MessageInitializer::clearDuplicates();
+    ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+    const MessageInitializer init_message_initializer_unittest_4(dupe);
+    MessageInitializer::loadDictionary(true);
+    ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
+}

+ 4 - 0
src/lib/python/isc/datasrc/datasrc.cc

@@ -23,6 +23,8 @@
 #include <datasrc/sqlite3_accessor.h>
 #include <datasrc/sqlite3_accessor.h>
 #include <datasrc/zone_loader.h>
 #include <datasrc/zone_loader.h>
 
 
+#include <log/message_initializer.h>
+
 #include "datasrc.h"
 #include "datasrc.h"
 #include "client_python.h"
 #include "client_python.h"
 #include "finder_python.h"
 #include "finder_python.h"
@@ -276,6 +278,8 @@ PyModuleDef iscDataSrc = {
 
 
 PyMODINIT_FUNC
 PyMODINIT_FUNC
 PyInit_datasrc(void) {
 PyInit_datasrc(void) {
+    isc::log::MessageInitializer::loadDictionary();
+
     PyObject* mod = PyModule_Create(&iscDataSrc);
     PyObject* mod = PyModule_Create(&iscDataSrc);
     if (mod == NULL) {
     if (mod == NULL) {
         return (NULL);
         return (NULL);

+ 4 - 2
tests/lettuce/features/example.feature

@@ -161,11 +161,13 @@ Feature: Example feature
         A query for www.example.org should have rcode NOERROR
         A query for www.example.org should have rcode NOERROR
         Wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
         Wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
         Then set bind10 configuration data_sources/classes/IN[0]/params to {"database_file": "data/empty_db.sqlite3"}
         Then set bind10 configuration data_sources/classes/IN[0]/params to {"database_file": "data/empty_db.sqlite3"}
-        And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN
+        # The 'not missing placeholder' check is for #2743
+        And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN not Missing placeholder
         A query for www.example.org should have rcode REFUSED
         A query for www.example.org should have rcode REFUSED
         Wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
         Wait for new bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
         Then set bind10 configuration data_sources/classes/IN[0]/params to {"database_file": "data/example.org.sqlite3"}
         Then set bind10 configuration data_sources/classes/IN[0]/params to {"database_file": "data/example.org.sqlite3"}
-        And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN
+        # The 'not missing placeholder' check is for #2743
+        And wait for new bind10 stderr message DATASRC_SQLITE_CONNOPEN not Missing placeholder
         A query for www.example.org should have rcode NOERROR
         A query for www.example.org should have rcode NOERROR
 
 
     Scenario: two bind10 instances
     Scenario: two bind10 instances