BIND 10 trac1924, updated. e62a5e2f0da16fd93c019450b7072e56d90c1359 [1924] Update mocks with the new parameter
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Feb 1 07:55:39 UTC 2013
The branch, trac1924 has been updated
discards 266bfcd67adafe326c13c6d835f5875628972d9f (commit)
discards 666395baa9b73aca0312787b683a7d3a96e7ca86 (commit)
discards 8431fb8b25cde01d16bfdefdc52b2eb2b07cb756 (commit)
discards ac23914ba629242fa651b4d68b61e9e5380c0643 (commit)
discards 2a1e4152da4fb42c78e57ada20de7e6a4d64da51 (commit)
discards 4df79169011293abac9c08a1cc47e4f16f5e1750 (commit)
discards 73ca6b06d15e426c0d57c41a0e126d7433acc598 (commit)
discards fe0db0adf0796432ace4794c157efc2bfb79e008 (commit)
discards 269cd1867284c4ebf44ebabacadc99c6413bcacb (commit)
discards ed8243603f26e46d8ae48f0fb4bac7545c5ff4c9 (commit)
discards 583de5551d162a5feb89bf5759e573b32d80f142 (commit)
discards 57f3e532a4cb9ef57484b638cfb53296dc403e95 (commit)
discards 31707f9fd9a78add4895394d0168d5664184b18f (commit)
discards 5cfbdc70c17f139c6c0d7d74afba76240ecd0474 (commit)
discards 76f20bfafceeca8bceefda457fe64904d4d21c59 (commit)
discards 44699b4b18162581cd1dd39be5fb76ca536012e6 (commit)
discards 8ed7d3706940a9a822503426fe4c09f3bf995610 (commit)
discards 717d619224d93b6dc6da0cf6267deffc31e130ad (commit)
discards 10fece1ac6ec02b033f00689fc31ac4f93570dda (commit)
discards 9a7784d748031b97dbb5a55fed84dcca254096d5 (commit)
discards 2ca96761f12b10e51faa6e394617baffbb68afdd (commit)
discards b122fa56ec0caf72e351f973c9ef337b2b3122c1 (commit)
discards ed2adc060ea123c5a6fec274950fdc68cde48059 (commit)
discards 4c4e2711beeb2eed8104055cf66dd4e8151c4fd1 (commit)
discards 93716b025a4755a8a2cbf250a9e4187741dbc9bb (commit)
discards 21a9a30e94cfa668daef86935894d6b5257179f0 (commit)
discards f7c0e1bf2a90711cd6df426b17465eedafaade00 (commit)
discards 4dd6c4cc1c15974d1009c489f2e26e987479ea77 (commit)
discards f94444fe1c05288c12f6255bb3552a8c8166745a (commit)
discards d4032a6703f672811b92811c10998d8eb718eec6 (commit)
discards 12807b1d6e3a0846198bcc062978c077ac101b91 (commit)
discards b22bc32b2776aa8904ee4fae2e9f6b075eace0f4 (commit)
discards df5cb12f60fc4f22b24218a54bf428f403cabe22 (commit)
discards 72383e89593fdc91a83b0ffe875a4fdb5114fbfc (commit)
discards 79b78d6538b85a97e1a84aec63928a6bd0251218 (commit)
discards 2352105cc77dd16a583c8f4fdcaf9d680e450344 (commit)
discards 2a742e19fb8c128456c90b9ae679d2a4806313d3 (commit)
discards 4760fba1fcc4d0fdb762b69cd6090002b9190be1 (commit)
discards 5e9d101a16146d2bb60f128cba65083b72e04086 (commit)
discards ad274a49ad5f36231b8997240272c89b4edf0c2f (commit)
discards 6ff25a392e3d15ae5a9aa1ca11a4badeb95bf39d (commit)
discards cc9e3303451d440894ce918ae5f1e0d55b30f650 (commit)
discards dcd93a56893257541fbe19fcd112f7fdda5cb7bb (commit)
discards 1a235092e9050f116b87a1edc5b2b6095aacc9e8 (commit)
discards 79a33db9ed37ba4715b35d1d9c74dcc550a50788 (commit)
discards 44fe82eeedff8f69053c6f455134a256daab3340 (commit)
discards 97953d08e3259263743138dcc81ef4332e585e39 (commit)
discards 9859c1d73774b09bab6aee9dc8082428097aeae9 (commit)
discards cd2c2c8ec6cf8a335897176339c8150228be4a36 (commit)
discards 779d9312bf84dcf7ce26bd1b1d6276179e026ad2 (commit)
discards 848cc407b16d4874dc5abec493248cd64db018c6 (commit)
discards 9dbce1aa52c7342dc4fe4292983d33b826fc4217 (commit)
discards 40bbfbc8f6fcfa08154b0c76ddbb41c2725f24f7 (commit)
discards 0a94c9b7778c06dcadd0cf77ccf785afe53dc0b7 (commit)
discards 0bd3e904e235bf19714dd6c39de6fd7810541d31 (commit)
discards 555bf4c3d7d588de640091b4bf677c130d34d94d (commit)
discards e4e606091def44d790b193fbcfe74623dd31ef43 (commit)
discards 1f6f8905d7319519c6f2ebd5864eeb4d6d700d03 (commit)
discards 09c24690d48f8b8b7239668216b8fed9bac179e0 (commit)
discards 4d6c30931eee834bb63b11fabec9d84390a9f6b7 (commit)
discards eb1b9e524157d9c378ba0350fe3217d56dbc0665 (commit)
discards f6882b13b9264d0d64345a341a73c75ae6d9c535 (commit)
discards 0d69610ffffd701cd3a6fb2645f9ff24b69cb3b7 (commit)
discards e382b73b40ea40386202d1c91dfe57c8a4efc11f (commit)
discards f0ad7b6307f49bb7bc4a45311e6f1b33b42dd885 (commit)
discards f485d39ab6e394bc034b990f872572c3700d0312 (commit)
discards a55716a04087917db71ff5b224b922d05ec6d6c6 (commit)
discards 769bbb5edb0fe537e497ebe1a9fc3dfc130a5866 (commit)
discards 631366a33bb06d01547c0789edfadde7a17228bd (commit)
discards e05c0b3ebb376233dd9648732fb5c992bb72e242 (commit)
discards a60ee6bbefe447f7ce863641dd88cdb1d3f0766b (commit)
discards d7fd34a4bf69c07812461671ac8d8f0dde0ee440 (commit)
discards 1bb3b6b661cc500b2a7cad2447347a23b7b1fadc (commit)
discards d5a2bb8d02bb017405ac6f79e2eeffcb7fd23052 (commit)
discards 9de5d287390383e072dbb2c4cbf9d60253893e41 (commit)
discards 2887502a9e0084cb16c79aba684a65f9d4fda69a (commit)
via e62a5e2f0da16fd93c019450b7072e56d90c1359 (commit)
via 7919cceebc8fbeb56e7808133880aeba14b79217 (commit)
via e220a4ed9277845220c8550f24e87c16422d9dee (commit)
via 9e8e9cb336031bf88a5f458d9c96afb0549f3042 (commit)
via 98928031fc761eec73838139b2e3e5e9502eedf1 (commit)
via c9ba856c4cc0f98b33cbeb030fedec3b29ee0e0c (commit)
via 10166e33f1d08985830a8bf5804af40c00328b86 (commit)
via 4f49376c5dee81bcc140f1445e762f62ee92e29f (commit)
via 3e94ba20d52e2c62243af504f95f5b3134efd0f7 (commit)
via 86a88ca3f958089b8d586d77f0e501f2792320d3 (commit)
via 85b7b8462a2bab6084aa724a9fe85208d2c80f84 (commit)
via 6d9b521367bc30b39209551ccbea6c8e20e140d8 (commit)
via 079a6684785bb75f1ae2c2c2ebfc1838831e783d (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (266bfcd67adafe326c13c6d835f5875628972d9f)
\
N -- N -- N (e62a5e2f0da16fd93c019450b7072e56d90c1359)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
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 e62a5e2f0da16fd93c019450b7072e56d90c1359
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Jan 31 15:09:25 2013 +0100
[1924] Update mocks with the new parameter
commit 7919cceebc8fbeb56e7808133880aeba14b79217
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Jan 31 15:05:23 2013 +0100
[1924] Send the want_answer header from C++
commit e220a4ed9277845220c8550f24e87c16422d9dee
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Jan 31 15:01:57 2013 +0100
[1924] Test for the C++ want_answer parameter
commit 9e8e9cb336031bf88a5f458d9c96afb0549f3042
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Jan 31 14:15:20 2013 +0100
[1924] Unittest for the original C++ group_sendmsg
commit 98928031fc761eec73838139b2e3e5e9502eedf1
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Jan 31 12:49:30 2013 +0100
[1924] Method to read messages sent over wire in tests
Not used yet, the test needs to be yet written.
commit c9ba856c4cc0f98b33cbeb030fedec3b29ee0e0c
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jan 30 14:46:43 2013 +0100
[1924] Add python group_sent want_reply parameter
So the reporting of errors can be turned on from python.
commit 10166e33f1d08985830a8bf5804af40c00328b86
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jan 30 14:23:58 2013 +0100
[1924] (minor) Style cleanups
* Spaces
* Remove commented-out code
* Use full relative path to header
commit 4f49376c5dee81bcc140f1445e762f62ee92e29f
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jan 30 14:22:21 2013 +0100
[1924] Provide proper headers
It wouldn't be needed in practice, but provide headers as close to if it
was sent by another client as reasonable and possible.
Also test we can explicitly say we don't want the answer, instead of
having just the default.
commit 3e94ba20d52e2c62243af504f95f5b3134efd0f7
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jan 30 11:17:27 2013 +0100
[1924] Send the errors about missing recipient
If the msgq finds no recipient to send to and the sender wants an
answer, provide an error as the answer. Also check the error messages
look sane in tests.
commit 86a88ca3f958089b8d586d77f0e501f2792320d3
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 28 16:23:16 2013 +0100
[1924] (minor) Docstrings for the tests
commit 85b7b8462a2bab6084aa724a9fe85208d2c80f84
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 28 16:20:09 2013 +0100
[1924] Decode the delivered messages in test
Decode the messages to see they are not errors. Check they contain
correct data and they are delivered to the correct socket.
Parsing of the errors is not present yet, it needs to be found out how
such an error looks like.
commit 6d9b521367bc30b39209551ccbea6c8e20e140d8
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 28 15:54:40 2013 +0100
[1924] Skeleton of the test for delivery errors
Let the msgq send several messages, some of them are deliverable, some
of them not. Some require reporting of error, some don't. Check it
generates the errors in the right moments and delivers the messages that
can be.
The test is not complete yet, we don't have parsing of the messages.
commit 079a6684785bb75f1ae2c2c2ebfc1838831e783d
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jan 28 15:08:30 2013 +0100
[1924] Mark a place to add the error handling
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 12 -
src/bin/auth/auth_messages.mes | 3 -
src/bin/auth/main.cc | 32 +--
src/bin/cmdctl/cmdctl.py.in | 2 -
src/bin/cmdctl/cmdctl_messages.mes | 3 -
src/bin/msgq/msgq.py.in | 180 +++++-------
src/bin/msgq/msgq_messages.mes | 54 +---
src/bin/msgq/tests/msgq_test.py | 293 ++++++++-----------
src/bin/stats/stats.py.in | 2 -
src/bin/stats/stats_httpd.py.in | 52 ++--
src/bin/stats/stats_httpd_messages.mes | 43 ++-
src/bin/stats/stats_messages.mes | 3 -
src/bin/xfrin/tests/xfrin_test.py | 89 +-----
src/bin/xfrin/xfrin.py.in | 74 ++---
src/bin/xfrin/xfrin_messages.mes | 20 --
src/bin/xfrout/xfrout.py.in | 3 +-
src/bin/xfrout/xfrout_messages.mes | 3 -
src/bin/zonemgr/zonemgr.py.in | 2 +-
src/bin/zonemgr/zonemgr_messages.mes | 2 +-
src/lib/cc/cc_messages.mes | 4 -
src/lib/cc/session.cc | 9 +-
src/lib/cc/session.h | 19 +-
src/lib/cc/tests/session_unittests.cc | 182 +++++++++++-
src/lib/config/tests/fake_session.cc | 2 +-
src/lib/config/tests/fake_session.h | 3 +-
src/lib/datasrc/database.cc | 19 +-
src/lib/datasrc/datasrc_messages.mes | 24 +-
src/lib/datasrc/memory/treenode_rrset.cc | 7 +-
src/lib/datasrc/memory/treenode_rrset.h | 29 +-
src/lib/datasrc/memory/zone_data.cc | 30 --
src/lib/datasrc/memory/zone_data.h | 57 +---
src/lib/datasrc/memory/zone_data_updater.cc | 11 -
src/lib/datasrc/memory/zone_finder.cc | 78 +----
src/lib/datasrc/memory/zone_finder.h | 14 -
src/lib/datasrc/rrset_collection_base.h | 54 ++--
src/lib/datasrc/tests/database_unittest.cc | 20 +-
.../datasrc/tests/master_loader_callbacks_test.cc | 2 +-
.../tests/memory/treenode_rrset_unittest.cc | 47 +--
.../tests/memory/zone_data_loader_unittest.cc | 19 +-
src/lib/datasrc/tests/memory/zone_data_unittest.cc | 28 +-
.../tests/memory/zone_data_updater_unittest.cc | 19 +-
.../datasrc/tests/memory/zone_finder_unittest.cc | 303 +++++---------------
src/lib/datasrc/tests/zone_loader_unittest.cc | 19 +-
src/lib/datasrc/zone.h | 68 ++---
src/lib/datasrc/zone_finder.h | 1 +
src/lib/datasrc/zone_loader.cc | 3 +-
src/lib/dns/python/rrset_collection_python_inc.cc | 39 +--
src/lib/dns/rrset_collection_base.h | 38 +--
src/lib/python/isc/cc/Makefile.am | 15 +-
src/lib/python/isc/cc/logger.py | 26 --
src/lib/python/isc/cc/pycc_messages.mes | 20 --
src/lib/python/isc/cc/session.py | 15 +-
src/lib/python/isc/cc/tests/session_test.py | 30 +-
src/lib/python/isc/config/cfgmgr.py | 3 +-
src/lib/python/isc/config/cfgmgr_messages.mes | 3 -
src/lib/python/isc/datasrc/updater_inc.cc | 51 +---
src/lib/python/isc/log_messages/Makefile.am | 2 -
src/lib/python/isc/log_messages/pycc_messages.py | 1 -
src/lib/python/isc/xfrin/diff.py | 13 -
src/lib/python/isc/xfrin/tests/diff_tests.py | 49 +---
src/lib/testutils/mockups.h | 2 +-
.../xfrin/retransfer_master_nons.conf.orig | 48 ----
tests/lettuce/data/example.org-nons.sqlite3 | Bin 15360 -> 0 bytes
tests/lettuce/features/bindctl_commands.feature | 2 +-
tests/lettuce/features/stats_httpd.feature | 16 --
tests/lettuce/features/terrain/http.py | 41 ---
tests/lettuce/features/terrain/steps.py | 2 +-
tests/lettuce/features/terrain/terrain.py | 6 -
tests/lettuce/features/xfrin_bind10.feature | 60 +---
69 files changed, 727 insertions(+), 1698 deletions(-)
mode change 100755 => 100644 src/bin/stats/stats_httpd.py.in
delete mode 100644 src/lib/python/isc/cc/logger.py
delete mode 100644 src/lib/python/isc/cc/pycc_messages.mes
delete mode 100644 src/lib/python/isc/log_messages/pycc_messages.py
delete mode 100644 tests/lettuce/configurations/xfrin/retransfer_master_nons.conf.orig
delete mode 100644 tests/lettuce/data/example.org-nons.sqlite3
delete mode 100644 tests/lettuce/features/stats_httpd.feature
delete mode 100644 tests/lettuce/features/terrain/http.py
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 32a9108..7f8cbde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,3 @@
-562. [func]* vorner
- The b10-xfrin now performs basic sanity check on just received
- zone. It'll reject severely broken zones (such as missng NS
- records).
- (Trac #2439, git 44699b4b18162581cd1dd39be5fb76ca536012e6)
-
-561. [bug] kambe, jelte
- b10-stats-httpd no longer dumps request information to the console,
- but uses the bind10 logging system. Additionally, the logging
- identifiers have been changed from STATHTTPD_* to STATSHTTPD_*
- (Trac #1897, git 93716b025a4755a8a2cbf250a9e4187741dbc9bb)
-
560. [bug] jinmei
b10-auth now sets the TTL of SOA RR for negative responses to
the minimum of the RR TTL and the minimum TTL of the SOA RDATA
diff --git a/src/bin/auth/auth_messages.mes b/src/bin/auth/auth_messages.mes
index 28b9623..d93da51 100644
--- a/src/bin/auth/auth_messages.mes
+++ b/src/bin/auth/auth_messages.mes
@@ -312,9 +312,6 @@ been created and is initializing. The AUTH_SERVER_STARTED message will be
output when initialization has successfully completed and the server starts
accepting queries.
-% AUTH_SERVER_EXITING exiting
-The authoritative server is exiting.
-
% AUTH_SERVER_FAILED server failed: %1
The authoritative server has encountered a fatal error and is terminating. The
reason for the failure is included in the message.
diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc
index 9b42628..e90d199 100644
--- a/src/bin/auth/main.cc
+++ b/src/bin/auth/main.cc
@@ -44,7 +44,6 @@
#include <server_common/socket_request.h>
#include <boost/bind.hpp>
-#include <boost/scoped_ptr.hpp>
#include <sys/types.h>
#include <sys/socket.h>
@@ -153,11 +152,10 @@ main(int argc, char* argv[]) {
int ret = 0;
// XXX: we should eventually pass io_service here.
- boost::scoped_ptr<AuthSrv> auth_server_; // placeholder
- boost::scoped_ptr<Session> cc_session;
- boost::scoped_ptr<Session> xfrin_session;
+ Session* cc_session = NULL;
+ Session* xfrin_session = NULL;
bool xfrin_session_established = false; // XXX (see Trac #287)
- boost::scoped_ptr<ModuleCCSession> config_session;
+ ModuleCCSession* config_session = NULL;
XfroutClient xfrout_client(getXfroutSocketPath());
SocketSessionForwarder ddns_forwarder(getDDNSSocketPath());
try {
@@ -169,8 +167,7 @@ main(int argc, char* argv[]) {
specfile = string(AUTH_SPECFILE_LOCATION);
}
- auth_server_.reset(new AuthSrv(xfrout_client, ddns_forwarder));
- auth_server = auth_server_.get();
+ auth_server = new AuthSrv(xfrout_client, ddns_forwarder);
LOG_INFO(auth_logger, AUTH_SERVER_CREATED);
SimpleCallback* checkin = auth_server->getCheckinProvider();
@@ -182,7 +179,7 @@ main(int argc, char* argv[]) {
auth_server->setDNSService(dns_service);
LOG_DEBUG(auth_logger, DBG_AUTH_START, AUTH_DNS_SERVICES_CREATED);
- cc_session.reset(new Session(io_service.get_io_service()));
+ cc_session = new Session(io_service.get_io_service());
LOG_DEBUG(auth_logger, DBG_AUTH_START, AUTH_CONFIG_CHANNEL_CREATED);
// Initialize the Socket Requestor
isc::server_common::initSocketRequestor(*cc_session, AUTH_NAME);
@@ -194,18 +191,18 @@ main(int argc, char* argv[]) {
// updateConfig() for listen_on and in initializing TSIG keys below).
// Until then all operations on the CC session will take place
// synchronously.
- config_session.reset(new ModuleCCSession(specfile, *cc_session,
- my_config_handler,
- my_command_handler, false));
+ config_session = new ModuleCCSession(specfile, *cc_session,
+ my_config_handler,
+ my_command_handler, false);
LOG_DEBUG(auth_logger, DBG_AUTH_START, AUTH_CONFIG_CHANNEL_ESTABLISHED);
- xfrin_session.reset(new Session(io_service.get_io_service()));
+ xfrin_session = new Session(io_service.get_io_service());
LOG_DEBUG(auth_logger, DBG_AUTH_START, AUTH_XFRIN_CHANNEL_CREATED);
xfrin_session->establish(NULL);
xfrin_session_established = true;
LOG_DEBUG(auth_logger, DBG_AUTH_START, AUTH_XFRIN_CHANNEL_ESTABLISHED);
- auth_server->setXfrinSession(xfrin_session.get());
+ auth_server->setXfrinSession(xfrin_session);
// Configure the server. configureAuthServer() is expected to install
// all initial configurations, but as a short term workaround we
@@ -213,7 +210,7 @@ main(int argc, char* argv[]) {
// updateConfig().
// if server load configure failed, we won't exit, give user second
// chance to correct the configure.
- auth_server->setConfigSession(config_session.get());
+ auth_server->setConfigSession(config_session);
try {
configureAuthServer(*auth_server, config_session->getFullConfig());
auth_server->updateConfig(ElementPtr());
@@ -231,7 +228,7 @@ main(int argc, char* argv[]) {
config_session->addRemoteConfig("data_sources",
boost::bind(datasrcConfigHandler,
auth_server, &first_time,
- config_session.get(),
+ config_session,
_1, _2, _3),
false);
@@ -263,7 +260,10 @@ main(int argc, char* argv[]) {
config_session->removeRemoteConfig("data_sources");
}
- LOG_INFO(auth_logger, AUTH_SERVER_EXITING);
+ delete xfrin_session;
+ delete config_session;
+ delete cc_session;
+ delete auth_server;
return (ret);
}
diff --git a/src/bin/cmdctl/cmdctl.py.in b/src/bin/cmdctl/cmdctl.py.in
index 80064a9..b026612 100755
--- a/src/bin/cmdctl/cmdctl.py.in
+++ b/src/bin/cmdctl/cmdctl.py.in
@@ -650,6 +650,4 @@ if __name__ == '__main__':
if httpd:
httpd.shutdown()
- logger.info(CMDCTL_EXITING)
-
sys.exit(result)
diff --git a/src/bin/cmdctl/cmdctl_messages.mes b/src/bin/cmdctl/cmdctl_messages.mes
index 32afce3..5fbb430 100644
--- a/src/bin/cmdctl/cmdctl_messages.mes
+++ b/src/bin/cmdctl/cmdctl_messages.mes
@@ -43,9 +43,6 @@ specific error is printed in the message.
This debug message indicates that the given command has been sent to
the given module.
-% CMDCTL_EXITING exiting
-The b10-cmdctl daemon is exiting.
-
% CMDCTL_NO_SUCH_USER username not found in user database: %1
A login attempt was made to b10-cmdctl, but the username was not known.
Users can be added with the tool b10-cmdctl-usermgr.
diff --git a/src/bin/msgq/msgq.py.in b/src/bin/msgq/msgq.py.in
index 9bf0b85..ea2e2d7 100755
--- a/src/bin/msgq/msgq.py.in
+++ b/src/bin/msgq/msgq.py.in
@@ -70,22 +70,6 @@ SPECFILE_LOCATION = SPECFILE_PATH + "/msgq.spec"
class MsgQReceiveError(Exception): pass
-class MsgQCloseOnReceive(Exception):
- '''Exception raised when reading data from a socket results in "shutdown.
-
- This can be either getting 0-length data or via ECONNRESET socket.error
- exception. This class holds whether it happens in the middle of reading
- (i.e. after reading some) via partial_read parameter, which is set to True
- if and only if so. This will be used by an upper layer cathing the
- exception to distinguish severity of the event.
-
- "'''
- def __init__(self, reason, partial_read):
- self.partial_read = partial_read
- self.__reason = reason
- def __str__(self):
- return self.__reason
-
class SubscriptionManager:
def __init__(self, cfgmgr_ready):
"""
@@ -327,22 +311,23 @@ class MsgQ:
lname = self.newlname()
self.lnames[lname] = newsocket
- logger.debug(TRACE_BASIC, MSGQ_SOCKET_REGISTERED, newsocket.fileno(),
- lname)
-
if self.poller:
self.poller.register(newsocket, select.POLLIN)
else:
self.add_kqueue_socket(newsocket)
+ def process_socket(self, fd):
+ """Process a read on a socket."""
+ if not fd in self.sockets:
+ logger.error(MSGQ_READ_UNKNOWN_FD, fd)
+ return
+ sock = self.sockets[fd]
+ self.process_packet(fd, sock)
+
def kill_socket(self, fd, sock):
"""Fully close down the socket."""
- # Unregister events on the socket. Note that we don't have to do
- # this for kqueue because the registered events are automatically
- # deleted when the corresponding socket is closed.
if self.poller:
self.poller.unregister(sock)
-
self.subs.unsubscribe_all(sock)
lname = [ k for k, v in self.lnames.items() if v == sock ][0]
del self.lnames[lname]
@@ -352,36 +337,24 @@ class MsgQ:
del self.sendbuffs[fd]
logger.debug(TRACE_BASIC, MSGQ_SOCK_CLOSE, fd)
- def __getbytes(self, fd, sock, length, continued):
+ def getbytes(self, fd, sock, length):
"""Get exactly the requested bytes, or raise an exception if
- EOF.
-
- continued is set to True if this method is called to complete
- already read data.
- """
+ EOF."""
received = b''
while len(received) < length:
try:
data = sock.recv(length - len(received))
-
- # If the remote client has closed the socket there seems to be
- # two possible cases: getting ECONNRESET or receiving empty data.
- # These cases are possible in normal operation, so we report them
- # using MsgQCloseOnReceive.
- except socket.error as err:
- if err.errno == errno.ECONNRESET:
- raise MsgQCloseOnReceive(str(err), continued)
- raise MsgQReceiveError(str(err))
+ except socket.error:
+ raise MsgQReceiveError(socket.error)
if len(data) == 0:
- raise MsgQCloseOnReceive("EOF", continued)
+ raise MsgQReceiveError("EOF")
received += data
- continued = True
return received
def read_packet(self, fd, sock):
"""Read a correctly formatted packet. Will raise exceptions if
something fails."""
- lengths = self.__getbytes(fd, sock, 6, False)
+ lengths = self.getbytes(fd, sock, 6)
overall_length, routing_length = struct.unpack(">IH", lengths)
if overall_length < 2:
raise MsgQReceiveError("overall_length < 2")
@@ -392,9 +365,9 @@ class MsgQ:
raise MsgQReceiveError("routing_length == 0")
data_length = overall_length - routing_length
# probably need to sanity check lengths here...
- routing = self.__getbytes(fd, sock, routing_length, True)
+ routing = self.getbytes(fd, sock, routing_length)
if data_length > 0:
- data = self.__getbytes(fd, sock, data_length, True)
+ data = self.getbytes(fd, sock, data_length)
else:
data = None
return (routing, data)
@@ -403,15 +376,8 @@ class MsgQ:
"""Process one packet."""
try:
routing, data = self.read_packet(fd, sock)
- except (MsgQReceiveError, MsgQCloseOnReceive) as err:
- # If it's MsgQCloseOnReceive and that happens without reading
- # any data, it basically means the remote clinet has closed the
- # socket, so we log it as debug information. Otherwise, it's
- # a somewhat unexpected event, so we consider it an "error".
- if isinstance(err, MsgQCloseOnReceive) and not err.partial_read:
- logger.debug(TRACE_BASIC, MSGQ_CLOSE_ON_RECV, fd)
- else:
- logger.error(MSGQ_RECV_ERR, fd, err)
+ except MsgQReceiveError as err:
+ logger.error(MSGQ_RECV_ERR, fd, err)
self.kill_socket(fd, sock)
return
@@ -462,12 +428,9 @@ class MsgQ:
def sendmsg(self, sock, env, msg = None):
self.send_prepared_msg(sock, self.preparemsg(env, msg))
- def _send_data(self, sock, data):
+ def __send_data(self, sock, data):
"""
- Send a piece of data to the given socket. This method is
- essentially "private" to MsgQ, but defined as if it were "protected"
- for easier access from tests.
-
+ Send a piece of data to the given socket.
Parameters:
sock: The socket to send to
data: The list of bytes to send
@@ -483,17 +446,15 @@ class MsgQ:
sock.setblocking(0)
return sock.send(data)
except socket.error as e:
- if e.errno in [ errno.EAGAIN, errno.EWOULDBLOCK, errno.EINTR ]:
+ if e.errno in [ errno.EAGAIN,
+ errno.EWOULDBLOCK,
+ errno.EINTR ]:
return 0
- elif e.errno in [ errno.EPIPE, errno.ECONNRESET, errno.ENOBUFS ]:
- # EPIPE happens if the remote module has terminated by the time
- # of this send; its severity can vary, but in many cases it
- # shouldn't be critical, so we log it separately as a warning.
- if e.errno == errno.EPIPE:
- logger.warn(MSGQ_CLOSE_ON_SEND, sock.fileno())
- else:
- logger.error(MSGQ_SEND_ERR, sock.fileno(),
- errno.errorcode[e.errno])
+ elif e.errno in [ errno.EPIPE,
+ errno.ECONNRESET,
+ errno.ENOBUFS ]:
+ logger.error(MSGQ_SEND_ERR, sock.fileno(),
+ errno.errorcode[e.errno])
self.kill_socket(sock.fileno(), sock)
return None
else:
@@ -508,7 +469,7 @@ class MsgQ:
if fileno in self.sendbuffs:
amount_sent = 0
else:
- amount_sent = self._send_data(sock, msg)
+ amount_sent = self.__send_data(sock, msg)
if amount_sent is None:
# Socket has been killed, drop the send
return
@@ -528,7 +489,7 @@ class MsgQ:
last_sent = now
if self.poller:
self.poller.register(fileno, select.POLLIN |
- select.POLLOUT)
+ select.POLLOUT)
else:
self.add_kqueue_socket(sock, True)
self.sendbuffs[fileno] = (last_sent, buff)
@@ -537,7 +498,7 @@ class MsgQ:
# Try to send some data from the buffer
(_, msg) = self.sendbuffs[fileno]
sock = self.sockets[fileno]
- amount_sent = self._send_data(sock, msg)
+ amount_sent = self.__send_data(sock, msg)
if amount_sent is not None:
# Keep the rest
msg = msg[amount_sent:]
@@ -570,6 +531,7 @@ class MsgQ:
instance = routing["instance"]
to = routing["to"]
if group == None or instance == None:
+ # FIXME: Should we log them instead?
return # ignore invalid packets entirely
if to == "*":
@@ -578,14 +540,42 @@ class MsgQ:
if to in self.lnames:
sockets = [ self.lnames[to] ]
else:
- return # recipient doesn't exist
+ sockets = []
msg = self.preparemsg(routing, data)
if sock in sockets:
+ # Don't bounce to self
sockets.remove(sock)
- for socket in sockets:
- self.send_prepared_msg(socket, msg)
+
+ if sockets:
+ for socket in sockets:
+ self.send_prepared_msg(socket, msg)
+ elif routing.get("wants_reply") and "reply" not in routing:
+ # We have no recipients. But the sender insists on a reply
+ # (and the message isn't a reply itself). We need to send
+ # an error to satisfy the senders hurger for response, since
+ # nobody else will do that.
+
+ # The real errors would be positive, 1 most probably. We use
+ # negative errors for delivery errors to distinguish them a
+ # little. We probably should have a way to provide more data
+ # in the error message.
+ payload = isc.config.ccsession.create_answer(-1,
+ "No such recipient")
+ # We create the header based on the current one. But we don't
+ # want to mangle it for the caller, so we get a copy. A shallow
+ # one should be enough, we modify the dict only.
+ header = routing.copy()
+ header["reply"] = routing["seq"]
+ header["from"] = 'msgq' # Dummy lname not assigned to clients
+ header["to"] = routing["from"]
+ # We keep the seq as it is. We don't need to track the message
+ # and provided the sender always uses a new one, it won't know
+ # we're cheating, since we won't send it two same either.
+ errmsg = self.preparemsg(header, payload)
+ # Send it back.
+ self.send_prepared_msg(sock, errmsg)
def process_command_subscribe(self, sock, routing, data):
group = routing["group"]
@@ -631,11 +621,12 @@ class MsgQ:
self.running = False
break
else:
- writable = event & select.POLLOUT
- readable = not writable and (event & select.POLLIN)
- if not writable and not readable:
+ if event & select.POLLOUT:
+ self.__process_write(fd)
+ elif event & select.POLLIN:
+ self.process_socket(fd)
+ else:
logger.error(MSGQ_POLL_UNKNOWN_EVENT, fd, event)
- self._process_fd(fd, writable, readable, False)
def run_kqueue(self):
while self.running:
@@ -654,31 +645,14 @@ class MsgQ:
self.running = False
break;
else:
- fd = event.ident
- writable = event.filter == select.KQ_FILTER_WRITE
- readable = (event.filter == select.KQ_FILTER_READ and
- event.data > 0)
- closed = (not readable and
- (event.flags & select.KQ_EV_EOF))
- self._process_fd(fd, writable, readable, closed)
-
- def _process_fd(self, fd, writable, readable, closed):
- '''Process a single FD: unified subroutine of run_kqueue/poller.
-
- closed can be True only in the case of kqueue. This is essentially
- private but is defined as if it were "protected" so it's callable
- from tests.
-
- '''
- # We need to check if FD is still in the sockets dict, because
- # it's possible that the socket has been "killed" while processing
- # other FDs; it's even possible it's killed within this method.
- if writable and fd in self.sockets:
- self.__process_write(fd)
- if readable and fd in self.sockets:
- self.process_packet(fd, self.sockets[fd])
- if closed and fd in self.sockets:
- self.kill_socket(fd, self.sockets[fd])
+ if event.filter == select.KQ_FILTER_WRITE:
+ self.__process_write(event.ident)
+ if event.filter == select.KQ_FILTER_READ and \
+ event.data > 0:
+ self.process_socket(event.ident)
+ elif event.flags & select.KQ_EV_EOF:
+ self.kill_socket(event.ident,
+ self.sockets[event.ident])
def stop(self):
# Signal it should terminate.
@@ -815,5 +789,3 @@ if __name__ == "__main__":
pass
msgq.shutdown()
-
- logger.info(MSGQ_EXITING)
diff --git a/src/bin/msgq/msgq_messages.mes b/src/bin/msgq/msgq_messages.mes
index ad5c326..75e4227 100644
--- a/src/bin/msgq/msgq_messages.mes
+++ b/src/bin/msgq/msgq_messages.mes
@@ -23,31 +23,6 @@
This is a debug message. The message queue has little bit of special handling
for the configuration manager. This special handling is happening now.
-% MSGQ_CLOSE_ON_RECV Reading from socket canceled as it's closed: FD=%1
-A debug message. The msgq daemon was notified of a read event on a
-socket, but its initial read operation failed because the remote
-client has closed its socket. This is possible in a normal operation
-when a module shuts down.
-
-% MSGQ_CLOSE_ON_SEND Sending to socket failed as already closed (okay to ignore on shutdown): FD=%1
-The msgq daemon tries to send some data to a client module, but it
-failed because the socket has been closed. This normally means the
-client terminates (for some reason - either gracefully or as a crash)
-while other modules try to send a message to the terminated module.
-Since msgq doesn't keep track of the status of client modules, this
-can happen and is not really an error for msgq; however, it can still
-be an unexpected event for the BIND 10 system as a whole in that this
-particular message is lost, so it's logged as a warning. If this
-message is logged for a running BIND 10 system, it's suggested to
-check other log messages; there may be an error from other modules
-reporting a missing response message. One common, less critical case
-where this message is logged is during shutdown. The ordering of
-process shutdown is basically arbitrary at this moment, so it's
-possible that some module tries to send a "quitting" message to some
-other module but the latter has already shut down. Such cases are
-generally non critical, but you may want to check other possible error
-messages.
-
% MSGQ_COMMAND Running command %1 with arguments %2
Debug message. The message queue received a command and it is running it.
@@ -59,9 +34,6 @@ the message queue version and version of the module.
% MSGQ_CONFIG_DATA Received configuration update for the msgq: %1
Debug message. The message queue received a configuration update, handling it.
-% MSGQ_EXITING exiting
-The msgq daemon is exiting.
-
% MSGQ_HDR_DECODE_ERR Error decoding header received from socket %1: %2
The socket with mentioned file descriptor sent a packet. However, it was not
possible to decode the routing header of the packet. The packet is ignored.
@@ -69,11 +41,6 @@ This may be caused by a programmer error (one of the components sending invalid
data) or possibly by incompatible version of msgq and the component (but that's
unlikely, as the protocol is not changed often).
-% MSGQ_INVALID_CMD Received invalid command: %1
-An unknown command listed in the log has been received. It is ignored. This
-indicates either a programmer error (eg. a typo in the command name) or
-incompatible version of a module and message queue daemon.
-
% MSGQ_LISTENER_FAILED Failed to initialize listener on socket file '%1': %2
The message queue daemon tried to listen on a file socket (the path is in the
message), but it failed. The error from the operating system is logged.
@@ -96,17 +63,23 @@ happen and it is either a programmer error or OS bug. The event is ignored. The
number noted as the event is the raw encoded value, which might be useful to
the authors when figuring the problem out.
+% MSGQ_READ_UNKNOWN_FD Got read on strange socket %1
+The OS reported a file descriptor is ready to read. But the daemon doesn't know
+the mentioned file descriptor, which is either a programmer error or OS bug.
+The read event is ignored.
+
% MSGQ_RECV_ERR Error reading from socket %1: %2
There was a low-level error when reading from a socket. The error is logged and
-the corresponding socket is dropped. The errors include receiving
-broken or (non empty but) incomplete data. In either case it suggests
-something unexpected happens within the BIND 10 system; it's probably
-better to restart the system, and if it continues it should be
-reported as a bug.
+the corresponding socket is dropped.
% MSGQ_RECV_HDR Received header: %1
Debug message. This message includes the whole routing header of a packet.
+% MSGQ_INVALID_CMD Received invalid command: %1
+An unknown command listed in the log has been received. It is ignored. This
+indicates either a programmer error (eg. a typo in the command name) or
+incompatible version of a module and message queue daemon.
+
% MSGQ_SEND_ERR Error while sending to socket %1: %2
There was a low-level error when sending data to a socket. The error is logged
and the corresponding socket is dropped.
@@ -114,11 +87,6 @@ and the corresponding socket is dropped.
% MSGQ_SHUTDOWN Stopping Msgq
Debug message. The message queue is shutting down.
-% MSGQ_SOCKET_REGISTERED Registered a socket descriptor %1 with lname %2
-Debug message. The msgq daemon accepted a session request on the
-shown descriptor of socket and assigned a unique identifier (lname)
-for the client on that socket.
-
% MSGQ_SOCK_CLOSE Closing socket fd %1
Debug message. Closing the mentioned socket.
diff --git a/src/bin/msgq/tests/msgq_test.py b/src/bin/msgq/tests/msgq_test.py
index bcd9bc7..1748c17 100644
--- a/src/bin/msgq/tests/msgq_test.py
+++ b/src/bin/msgq/tests/msgq_test.py
@@ -1,4 +1,3 @@
-import msgq
from msgq import SubscriptionManager, MsgQ
import unittest
@@ -12,6 +11,8 @@ import threading
import isc.cc
import collections
import isc.log
+import struct
+import json
#
# Currently only the subscription part and some sending is implemented...
@@ -141,6 +142,120 @@ class TestSubscriptionManager(unittest.TestCase):
self.sm.subscribe('ConfigManager', '*', 's3')
self.assertEqual(1, self.__cfgmgr_ready_called)
+class MsgQTest(unittest.TestCase):
+ """
+ Tests for the behaviour of MsgQ. This is for the core of MsgQ, other
+ subsystems are in separate test fixtures.
+ """
+ def setUp(self):
+ self.__msgq = MsgQ()
+
+ def parse_msg(self, msg):
+ """
+ Parse a binary representation of message to the routing header and the
+ data payload. It assumes the message is correctly encoded and the
+ payload is not omitted. It'd probably throw in other cases, but we
+ don't use it in such situations in this test.
+ """
+ (length, header_len) = struct.unpack('>IH', msg[:6])
+ header = json.loads(msg[6:6 + header_len].decode('utf-8'))
+ data = json.loads(msg[6 + header_len:].decode('utf-8'))
+ return (header, data)
+
+ def test_undeliverable_errors(self):
+ """
+ Send several packets through the MsgQ and check it generates
+ undeliverable notifications under the correct circumstances.
+ """
+ sent_messages = []
+ def fake_end_prepared_msg(socket, msg):
+ sent_messages.append((socket, msg))
+ self.__msgq.send_prepared_msg = fake_end_prepared_msg
+ # These would be real sockets in the MsgQ, but we pass them as
+ # parameters only, so we don't need them to be. We use simple
+ # integers to tell one from another.
+ sender = 1
+ recipient = 2
+ # The routing headers and data to test with.
+ routing = {
+ 'to': '*',
+ 'from': 'sender',
+ 'group': 'group',
+ 'instance': '*',
+ 'seq': 42
+ }
+ data = {
+ "data": "Just some data"
+ }
+ # Send the message. No recipient, but errors are not requested,
+ # so none is generated.
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual([], sent_messages)
+ # It should act the same if we explicitly say we do not want replies.
+ routing["wants_reply"] = False
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual([], sent_messages)
+ # Ask for errors if it can't be delivered.
+ routing["wants_reply"] = True
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual(1, len(sent_messages))
+ self.assertEqual(1, sent_messages[0][0])
+ self.assertEqual(({
+ 'group': 'group',
+ 'instance': '*',
+ 'reply': 42,
+ 'seq': 42,
+ 'from': 'msgq',
+ 'to': 'sender',
+ 'wants_reply': True
+ }, {'result': [-1, "No such recipient"]}),
+ self.parse_msg(sent_messages[0][1]))
+ # the reply header too.
+ sent_messages = []
+ # If the message is a reply itself, we never generate the errors, even
+ # if they can't be delivered. This is partly because the answer reuses
+ # the old header (which would then inherit the wants_reply flag) and
+ # partly we want to avoid loops of errors that can't be delivered.
+ # If a reply can't be delivered, the sender can't do much anyway even
+ # if notified.
+ routing["reply"] = 3
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual([], sent_messages)
+ # If there are recipients (but no "reply" header), the error should not
+ # be sent and the message should get delivered.
+ del routing["reply"]
+ self.__msgq.subs.find = lambda group, instance: [recipient]
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual(1, len(sent_messages))
+ self.assertEqual(2, sent_messages[0][0]) # The recipient
+ self.assertEqual((routing, data), self.parse_msg(sent_messages[0][1]))
+ sent_messages = []
+ # When we send a direct message and the recipient is not there, we get
+ # the error too
+ routing["to"] = "lname"
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual(1, len(sent_messages))
+ self.assertEqual(1, sent_messages[0][0])
+ self.assertEqual(({
+ 'group': 'group',
+ 'instance': '*',
+ 'reply': 42,
+ 'seq': 42,
+ 'from': 'msgq',
+ 'to': 'sender',
+ 'wants_reply': True
+ }, {'result': [-1, "No such recipient"]}),
+ self.parse_msg(sent_messages[0][1]))
+ sent_messages = []
+ # But when the recipient is there, it is delivered and no error is
+ # generated.
+ self.__msgq.lnames["lname"] = recipient
+ self.__msgq.process_command_send(sender, routing, data)
+ self.assertEqual(1, len(sent_messages))
+ self.assertEqual(2, sent_messages[0][0]) # The recipient
+ self.assertEqual((routing, data), self.parse_msg(sent_messages[0][1]))
+ sent_messages = []
+
class DummySocket:
"""
Dummy socket class.
@@ -560,182 +675,6 @@ class ThreadTests(unittest.TestCase):
test_thread.join(60)
self.assertTrue(self.__result)
-class SocketTests(unittest.TestCase):
- '''Test cases for micro behaviors related to socket operations.
-
- Some cases are covered as part of other tests, but in this fixture
- we check more details of specific method related socket operation,
- with the help mock classes to avoid expensive overhead.
-
- '''
- class MockSocket():
- '''A mock socket used instead of standard socket objects.'''
- def __init__(self):
- self.ex_on_send = None # raised from send() if not None
- self.recv_result = b'test' # dummy data or exception
- self.blockings = [] # history of setblocking() params
- def setblocking(self, on):
- self.blockings.append(on)
- def send(self, data):
- if self.ex_on_send is not None:
- raise self.ex_on_send
- return 10 # arbitrary choice
- def recv(self, len):
- if isinstance(self.recv_result, Exception):
- raise self.recv_result
- ret = self.recv_result
- self.recv_result = b'' # if called again, return empty data
- return ret
- def fileno(self):
- return 42 # arbitrary choice
-
- class LoggerWrapper():
- '''A simple wrapper of logger to inspect log messages.'''
- def __init__(self, logger):
- self.error_called = 0
- self.warn_called = 0
- self.debug_called = 0
- self.orig_logger = logger
- def error(self, *args):
- self.error_called += 1
- self.orig_logger.error(*args)
- def warn(self, *args):
- self.warn_called += 1
- self.orig_logger.warn(*args)
- def debug(self, *args):
- self.debug_called += 1
- self.orig_logger.debug(*args)
-
- def mock_kill_socket(self, fileno, sock):
- '''A replacement of MsgQ.kill_socket method for inspection.'''
- self.__killed_socket = (fileno, sock)
- if fileno in self.__msgq.sockets:
- del self.__msgq.sockets[fileno]
-
- def setUp(self):
- self.__msgq = MsgQ()
- self.__msgq.kill_socket = self.mock_kill_socket
- self.__sock = self.MockSocket()
- self.__data = b'dummy'
- self.__msgq.sockets[42] = self.__sock
- self.__msgq.sendbuffs[42] = (None, b'testdata')
- self.__sock_error = socket.error()
- self.__killed_socket = None
- self.__logger = self.LoggerWrapper(msgq.logger)
- msgq.logger = self.__logger
-
- def tearDown(self):
- msgq.logger = self.__logger.orig_logger
-
- def test_send_data(self):
- # Successful case: _send_data() returns the hardcoded value, and
- # setblocking() is called twice with the expected parameters
- self.assertEqual(10, self.__msgq._send_data(self.__sock, self.__data))
- self.assertEqual([0, 1], self.__sock.blockings)
- self.assertIsNone(self.__killed_socket)
-
- def test_send_data_interrupt(self):
- '''send() is interruptted. send_data() returns 0, sock isn't killed.'''
- expected_blockings = []
- for eno in [errno.EAGAIN, errno.EWOULDBLOCK, errno.EINTR]:
- self.__sock_error.errno = eno
- self.__sock.ex_on_send = self.__sock_error
- self.assertEqual(0, self.__msgq._send_data(self.__sock,
- self.__data))
- expected_blockings.extend([0, 1])
- self.assertEqual(expected_blockings, self.__sock.blockings)
- self.assertIsNone(self.__killed_socket)
-
- def test_send_data_error(self):
- '''Unexpected error happens on send(). The socket is killed.
-
- If the error is EPIPE, it's logged at the warn level; otherwise
- an error message is logged.
-
- '''
- expected_blockings = []
- expected_errors = 0
- expected_warns = 0
- for eno in [errno.EPIPE, errno.ECONNRESET, errno.ENOBUFS]:
- self.__sock_error.errno = eno
- self.__sock.ex_on_send = self.__sock_error
- self.__killed_socket = None # clear any previuos value
- self.assertEqual(None, self.__msgq._send_data(self.__sock,
- self.__data))
- self.assertEqual((42, self.__sock), self.__killed_socket)
- expected_blockings.extend([0, 1])
- self.assertEqual(expected_blockings, self.__sock.blockings)
-
- if eno == errno.EPIPE:
- expected_warns += 1
- else:
- expected_errors += 1
- self.assertEqual(expected_errors, self.__logger.error_called)
- self.assertEqual(expected_warns, self.__logger.warn_called)
-
- def test_process_fd_read_after_bad_write(self):
- '''Check the specific case of write fail followed by read attempt.
-
- The write failure results in kill_socket, then read shouldn't tried.
-
- '''
- self.__sock_error.errno = errno.EPIPE
- self.__sock.ex_on_send = self.__sock_error
- self.__msgq.process_socket = None # if called, trigger an exception
- self.__msgq._process_fd(42, True, True, False) # shouldn't crash
-
- # check the socket is deleted from the fileno=>sock dictionary
- self.assertEqual({}, self.__msgq.sockets)
-
- def test_process_fd_close_after_bad_write(self):
- '''Similar to the previous, but for checking dup'ed kill attempt'''
- self.__sock_error.errno = errno.EPIPE
- self.__sock.ex_on_send = self.__sock_error
- self.__msgq._process_fd(42, True, False, True) # shouldn't crash
- self.assertEqual({}, self.__msgq.sockets)
-
- def test_process_fd_writer_after_close(self):
- '''Emulate a "writable" socket has been already closed and killed.'''
- # This just shouldn't crash
- self.__msgq._process_fd(4200, True, False, False)
-
- def test_process_packet(self):
- '''Check some failure cases in handling an incoming message.'''
- expected_errors = 0
- expected_debugs = 0
-
- # if socket.recv() fails due to socket.error, it will be logged
- # as error or debug depending on the errno. In either case the socket
- # will be killed.
- for eno in [errno.ENOBUFS, errno.ECONNRESET]:
- self.__sock_error.errno = eno
- self.__sock.recv_result = self.__sock_error
- self.__killed_socket = None # clear any previuos value
- self.__msgq.process_packet(42, self.__sock)
- self.assertEqual((42, self.__sock), self.__killed_socket)
- if eno == errno.ENOBUFS:
- expected_errors += 1
- else:
- expected_debugs += 1
- self.assertEqual(expected_errors, self.__logger.error_called)
- self.assertEqual(expected_debugs, self.__logger.debug_called)
-
- # if socket.recv() returns empty data, the result depends on whether
- # there's any preceding data; in the second case below, at least
- # 6 bytes of data will be expected, and the second call to our faked
- # recv() returns empty data. In that case it will logged as error.
- for recv_data in [b'', b'short']:
- self.__sock.recv_result = recv_data
- self.__killed_socket = None
- self.__msgq.process_packet(42, self.__sock)
- self.assertEqual((42, self.__sock), self.__killed_socket)
- if len(recv_data) == 0:
- expected_debugs += 1
- else:
- expected_errors += 1
- self.assertEqual(expected_errors, self.__logger.error_called)
- self.assertEqual(expected_debugs, self.__logger.debug_called)
-
if __name__ == '__main__':
isc.log.resetUnitTestRootLogger()
unittest.main()
diff --git a/src/bin/stats/stats.py.in b/src/bin/stats/stats.py.in
index 3692814..7123c53 100755
--- a/src/bin/stats/stats.py.in
+++ b/src/bin/stats/stats.py.in
@@ -696,5 +696,3 @@ if __name__ == "__main__":
sys.exit(1)
except KeyboardInterrupt as kie:
logger.info(STATS_STOPPED_BY_KEYBOARD)
-
- logger.info(STATS_EXITING)
diff --git a/src/bin/stats/stats_httpd.py.in b/src/bin/stats/stats_httpd.py.in
old mode 100755
new mode 100644
index 659f8f4..057b8ca
--- a/src/bin/stats/stats_httpd.py.in
+++ b/src/bin/stats/stats_httpd.py.in
@@ -43,8 +43,8 @@ isc.log.init("b10-stats-httpd", buffer=True)
logger = isc.log.Logger("stats-httpd")
# Some constants for debug levels.
-DBG_STATSHTTPD_INIT = logger.DBGLVL_START_SHUT
-DBG_STATSHTTPD_MESSAGING = logger.DBGLVL_COMMAND
+DBG_STATHTTPD_INIT = logger.DBGLVL_START_SHUT
+DBG_STATHTTPD_MESSAGING = logger.DBGLVL_COMMAND
# If B10_FROM_SOURCE is set in the environment, we use data files
# from a directory relative to that, otherwise we use the ones
@@ -187,11 +187,11 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
# Couldn't find neither specified module name nor
# specified item name
self.send_error(404)
- logger.error(STATSHTTPD_SERVER_DATAERROR, err)
+ logger.error(STATHTTPD_SERVER_DATAERROR, err)
return None
except Exception as err:
self.send_error(500)
- logger.error(STATSHTTPD_SERVER_ERROR, err)
+ logger.error(STATHTTPD_SERVER_ERROR, err)
return None
else:
self.send_response(200)
@@ -201,14 +201,6 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
self.end_headers()
return body
- def log_message(self, format, *args):
- """overrides the parent method log_message()
- to use the bind10 logging framework.
- """
- logger.debug(DBG_STATSHTTPD_MESSAGING, STATSHTTPD_HTTPLOG,
- self.address_string(),
- format%args)
-
class HttpServerError(Exception):
"""Exception class for HttpServer class. It is intended to be
passed from the HttpServer object to the StatsHttpd object."""
@@ -271,7 +263,7 @@ class StatsHttpd:
def open_mccs(self):
"""Opens a ModuleCCSession object"""
# create ModuleCCSession
- logger.debug(DBG_STATSHTTPD_INIT, STATSHTTPD_STARTING_CC_SESSION)
+ logger.debug(DBG_STATHTTPD_INIT, STATHTTPD_STARTING_CC_SESSION)
self.mccs = isc.config.ModuleCCSession(
SPECFILE_LOCATION, self.config_handler, self.command_handler)
self.cc_session = self.mccs._session
@@ -282,7 +274,7 @@ class StatsHttpd:
return
self.mccs.send_stopping()
- logger.debug(DBG_STATSHTTPD_INIT, STATSHTTPD_CLOSING_CC_SESSION)
+ logger.debug(DBG_STATHTTPD_INIT, STATHTTPD_CLOSING_CC_SESSION)
self.mccs.close()
self.mccs = None
@@ -325,7 +317,7 @@ class StatsHttpd:
server_address, HttpHandler,
self.xml_handler, self.xsd_handler, self.xsl_handler,
self.write_log)
- logger.info(STATSHTTPD_STARTED, server_address[0],
+ logger.info(STATHTTPD_STARTED, server_address[0],
server_address[1])
return httpd
except (socket.gaierror, socket.error,
@@ -341,7 +333,7 @@ class StatsHttpd:
"""Closes sockets for HTTP"""
while len(self.httpd)>0:
ht = self.httpd.pop()
- logger.info(STATSHTTPD_CLOSING, ht.server_address[0],
+ logger.info(STATHTTPD_CLOSING, ht.server_address[0],
ht.server_address[1])
ht.server_close()
@@ -377,7 +369,7 @@ class StatsHttpd:
def stop(self):
"""Stops the running StatsHttpd objects. Closes CC session and
HTTP handling sockets"""
- logger.info(STATSHTTPD_SHUTDOWN)
+ logger.info(STATHTTPD_SHUTDOWN)
self.close_httpd()
self.close_mccs()
self.running = False
@@ -395,7 +387,7 @@ class StatsHttpd:
def config_handler(self, new_config):
"""Config handler for the ModuleCCSession object. It resets
addresses and ports to listen HTTP requests on."""
- logger.debug(DBG_STATSHTTPD_MESSAGING, STATSHTTPD_HANDLE_CONFIG,
+ logger.debug(DBG_STATHTTPD_MESSAGING, STATHTTPD_HANDLE_CONFIG,
new_config)
errors = []
if not self.mccs.get_module_spec().\
@@ -413,7 +405,7 @@ class StatsHttpd:
try:
self.open_httpd()
except HttpServerError as err:
- logger.error(STATSHTTPD_SERVER_ERROR, err)
+ logger.error(STATHTTPD_SERVER_ERROR, err)
# restore old config
self.load_config(old_config)
self.open_httpd()
@@ -425,18 +417,18 @@ class StatsHttpd:
"""Command handler for the ModuleCCSesson object. It handles
"status" and "shutdown" commands."""
if command == "status":
- logger.debug(DBG_STATSHTTPD_MESSAGING,
- STATSHTTPD_RECEIVED_STATUS_COMMAND)
+ logger.debug(DBG_STATHTTPD_MESSAGING,
+ STATHTTPD_RECEIVED_STATUS_COMMAND)
return isc.config.ccsession.create_answer(
0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")")
elif command == "shutdown":
- logger.debug(DBG_STATSHTTPD_MESSAGING,
- STATSHTTPD_RECEIVED_SHUTDOWN_COMMAND)
+ logger.debug(DBG_STATHTTPD_MESSAGING,
+ STATHTTPD_RECEIVED_SHUTDOWN_COMMAND)
self.running = False
return isc.config.ccsession.create_answer(0)
else:
- logger.debug(DBG_STATSHTTPD_MESSAGING,
- STATSHTTPD_RECEIVED_UNKNOWN_COMMAND, command)
+ logger.debug(DBG_STATHTTPD_MESSAGING,
+ STATHTTPD_RECEIVED_UNKNOWN_COMMAND, command)
return isc.config.ccsession.create_answer(
1, "Unknown command: " + str(command))
@@ -621,15 +613,13 @@ if __name__ == "__main__":
stats_httpd = StatsHttpd()
stats_httpd.start()
except OptionValueError as ove:
- logger.fatal(STATSHTTPD_BAD_OPTION_VALUE, ove)
+ logger.fatal(STATHTTPD_BAD_OPTION_VALUE, ove)
sys.exit(1)
except isc.cc.session.SessionError as se:
- logger.fatal(STATSHTTPD_CC_SESSION_ERROR, se)
+ logger.fatal(STATHTTPD_CC_SESSION_ERROR, se)
sys.exit(1)
except HttpServerError as hse:
- logger.fatal(STATSHTTPD_START_SERVER_INIT_ERROR, hse)
+ logger.fatal(STATHTTPD_START_SERVER_INIT_ERROR, hse)
sys.exit(1)
except KeyboardInterrupt as kie:
- logger.info(STATSHTTPD_STOPPED_BY_KEYBOARD)
-
- logger.info(STATSHTTPD_EXITING)
+ logger.info(STATHTTPD_STOPPED_BY_KEYBOARD)
diff --git a/src/bin/stats/stats_httpd_messages.mes b/src/bin/stats/stats_httpd_messages.mes
index 511289f..ad2e97f 100644
--- a/src/bin/stats/stats_httpd_messages.mes
+++ b/src/bin/stats/stats_httpd_messages.mes
@@ -15,90 +15,81 @@
# No namespace declaration - these constants go in the global namespace
# of the stats_httpd_messages python module.
-% STATSHTTPD_BAD_OPTION_VALUE bad command line argument: %1
+% STATHTTPD_BAD_OPTION_VALUE bad command line argument: %1
The stats-httpd module was called with a bad command-line argument
and will not start.
-% STATSHTTPD_CC_SESSION_ERROR error connecting to message bus: %1
+% STATHTTPD_CC_SESSION_ERROR error connecting to message bus: %1
The stats-httpd module was unable to connect to the BIND 10 command
and control bus. A likely problem is that the message bus daemon
(b10-msgq) is not running. The stats-httpd module will now shut down.
-% STATSHTTPD_CLOSING closing %1#%2
+% STATHTTPD_CLOSING closing %1#%2
The stats-httpd daemon will stop listening for requests on the given
address and port number.
-% STATSHTTPD_CLOSING_CC_SESSION stopping cc session
+% STATHTTPD_CLOSING_CC_SESSION stopping cc session
Debug message indicating that the stats-httpd module is disconnecting
from the command and control bus.
-% STATSHTTPD_EXITING exiting
-The stats HTTP server is exiting.
-
-% STATSHTTPD_HANDLE_CONFIG reading configuration: %1
+% STATHTTPD_HANDLE_CONFIG reading configuration: %1
The stats-httpd daemon has received new configuration data and will now
process it. The (changed) data is printed.
-% STATSHTTPD_HTTPLOG %1 %2
-Debug HTTP log message. These are the messages logged by the http server
-instance. For most logs, the message shows HTTP client and query
-information like HTTP method, URI, and status code, but the http server
-can also log other information, such as extended status reports.
-
-% STATSHTTPD_RECEIVED_SHUTDOWN_COMMAND shutdown command received
+% STATHTTPD_RECEIVED_SHUTDOWN_COMMAND shutdown command received
A shutdown command was sent to the stats-httpd module, and it will
now shut down.
-% STATSHTTPD_RECEIVED_STATUS_COMMAND received command to return status
+% STATHTTPD_RECEIVED_STATUS_COMMAND received command to return status
A status command was sent to the stats-httpd module, and it will
respond with 'Stats Httpd is up.' and its PID.
-% STATSHTTPD_RECEIVED_UNKNOWN_COMMAND received unknown command: %1
+% STATHTTPD_RECEIVED_UNKNOWN_COMMAND received unknown command: %1
An unknown command has been sent to the stats-httpd module. The
stats-httpd module will respond with an error, and the command will
be ignored.
-% STATSHTTPD_SERVER_DATAERROR HTTP server data error: %1
+% STATHTTPD_SERVER_DATAERROR HTTP server data error: %1
An internal error occurred while handling an HTTP request. An HTTP 404
response will be sent back, and the specific error is printed. This
is an error condition that likely points the specified data
corresponding to the requested URI is incorrect.
-% STATSHTTPD_SERVER_ERROR HTTP server error: %1
+% STATHTTPD_SERVER_ERROR HTTP server error: %1
An internal error occurred while handling an HTTP request. An HTTP 500
response will be sent back, and the specific error is printed. This
is an error condition that likely points to a module that is not
responding correctly to statistic requests.
-% STATSHTTPD_SERVER_INIT_ERROR HTTP server initialization error: %1
+% STATHTTPD_SERVER_INIT_ERROR HTTP server initialization error: %1
There was a problem initializing the HTTP server in the stats-httpd
module upon receiving its configuration data. The most likely cause
is a port binding problem or a bad configuration value. The specific
error is printed in the message. The new configuration is ignored,
and an error is sent back.
-% STATSHTTPD_SHUTDOWN shutting down
+% STATHTTPD_SHUTDOWN shutting down
The stats-httpd daemon is shutting down.
-% STATSHTTPD_STARTED listening on %1#%2
+% STATHTTPD_STARTED listening on %1#%2
The stats-httpd daemon will now start listening for requests on the
given address and port number.
-% STATSHTTPD_STARTING_CC_SESSION starting cc session
+% STATHTTPD_STARTING_CC_SESSION starting cc session
Debug message indicating that the stats-httpd module is connecting to
the command and control bus.
-% STATSHTTPD_START_SERVER_INIT_ERROR HTTP server initialization error: %1
+% STATHTTPD_START_SERVER_INIT_ERROR HTTP server initialization error: %1
There was a problem initializing the HTTP server in the stats-httpd
module upon startup. The most likely cause is that it was not able
to bind to the listening port. The specific error is printed, and the
module will shut down.
-% STATSHTTPD_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
+% STATHTTPD_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
There was a keyboard interrupt signal to stop the stats-httpd
daemon. The daemon will now shut down.
-% STATSHTTPD_UNKNOWN_CONFIG_ITEM unknown configuration item: %1
+% STATHTTPD_UNKNOWN_CONFIG_ITEM unknown configuration item: %1
The stats-httpd daemon received a configuration update from the
configuration manager. However, one of the items in the
configuration is unknown. The new configuration is ignored, and an
diff --git a/src/bin/stats/stats_messages.mes b/src/bin/stats/stats_messages.mes
index b6f0b16..3960c26 100644
--- a/src/bin/stats/stats_messages.mes
+++ b/src/bin/stats/stats_messages.mes
@@ -24,9 +24,6 @@ The stats module was unable to connect to the BIND 10 command and
control bus. A likely problem is that the message bus daemon
(b10-msgq) is not running. The stats module will now shut down.
-% STATS_EXITING exiting
-The stats module process is exiting.
-
% STATS_RECEIVED_INVALID_STATISTICS_DATA received invalid statistics data from %1
Invalid statistics data has been received from the module while
polling and it has been discarded.
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index 2370708..99c5e1e 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -153,19 +153,13 @@ class MockCC(MockModuleCCSession):
def remove_remote_config(self, module_name):
pass
-class MockRRsetCollection:
- '''
- A mock RRset collection. We don't use it really (we mock the method that
- it is passed to too), so it's empty.
- '''
- pass
-
class MockDataSourceClient():
'''A simple mock data source client.
This class provides a minimal set of wrappers related the data source
API that would be used by Diff objects. For our testing purposes they
- only keep track of the history of the changes.
+ only keep truck of the history of the changes.
+
'''
def __init__(self):
self.force_fail = False # if True, raise an exception on commit
@@ -223,12 +217,6 @@ class MockDataSourceClient():
self._journaling_enabled = journaling
return self
- def get_rrset_collection(self):
- '''
- Pretend to be a zone updater and provide a (dummy) rrset collection.
- '''
- return MockRRsetCollection()
-
def add_rrset(self, rrset):
self.diffs.append(('add', rrset))
@@ -738,27 +726,11 @@ class TestXfrinConnection(unittest.TestCase):
'tsig_1st': None,
'tsig_2nd': None
}
- self.__orig_check_zone = xfrin.check_zone
- xfrin.check_zone = self.__check_zone
- self._check_zone_result = True
- self._check_zone_params = None
def tearDown(self):
self.conn.close()
if os.path.exists(TEST_DB_FILE):
os.remove(TEST_DB_FILE)
- xfrin.check_zone = self.__orig_check_zone
-
- def __check_zone(self, name, rrclass, rrsets, callbacks):
- '''
- A mock function used instead of dns.check_zone.
- '''
- self._check_zone_params = (name, rrclass, rrsets, callbacks)
- # Call both callbacks to see they do nothing. This checks
- # the transfer depends on the result only.
- callbacks[0]("Test error")
- callbacks[1]("Test warning")
- return self._check_zone_result
def _create_normal_response_data(self):
# This helper method creates a simple sequence of DNS messages that
@@ -853,7 +825,6 @@ class TestAXFR(TestXfrinConnection):
def tearDown(self):
time.time = self.orig_time_time
- super().tearDown()
def __create_mock_tsig(self, key, error, has_last_signature=True):
# This helper function creates a MockTSIGContext for a given key
@@ -1326,33 +1297,6 @@ class TestAXFR(TestXfrinConnection):
[[('add', ns_rr), ('add', a_rr), ('add', soa_rrset)]],
self.conn._datasrc_client.committed_diffs)
- def test_axfr_response_fail_validation(self):
- """
- Test we reject a zone transfer if it fails the check_zone validation.
- """
- a_rr = self._create_a('192.0.2.1')
- self.conn._send_query(RRType.AXFR())
- self.conn.reply_data = self.conn.create_response_data(
- questions=[Question(TEST_ZONE_NAME, TEST_RRCLASS,
- RRType.AXFR())],
- # begin serial=1230, end serial=1234. end will be used.
- answers=[begin_soa_rrset, a_rr, soa_rrset])
- # Make it fail the validation
- self._check_zone_result = False
- self.assertRaises(XfrinZoneError, self.conn._handle_xfrin_responses)
- self.assertEqual(type(XfrinAXFREnd()), type(self.conn.get_xfrstate()))
- self.assertEqual([], self.conn._datasrc_client.committed_diffs)
- # Check the validation is called with the correct parameters
- self.assertEqual(TEST_ZONE_NAME, self._check_zone_params[0])
- self.assertEqual(TEST_RRCLASS, self._check_zone_params[1])
- self.assertTrue(isinstance(self._check_zone_params[2],
- MockRRsetCollection))
- # Check we can safely call the callbacks. They have no sideeffects
- # we can check (checking logging is hard), but we at least check
- # they don't crash.
- self._check_zone_params[3][0]("Test error")
- self._check_zone_params[3][1]("Test warning")
-
def test_axfr_response_extra(self):
'''Test with an extra RR after the end of AXFR session.
@@ -1555,15 +1499,6 @@ class TestAXFR(TestXfrinConnection):
self.conn.response_generator = self._create_normal_response_data
self.assertEqual(self.conn.do_xfrin(False), XFRIN_FAIL)
- def test_do_xfrin_invalid_zone(self):
- """
- Test receiving an invalid zone. We mock the check and see the whole
- transfer is rejected.
- """
- self._check_zone_result = False
- self.conn.response_generator = self._create_normal_response_data
- self.assertEqual(self.conn.do_xfrin(False), XFRIN_FAIL)
-
def test_do_soacheck_and_xfrin(self):
self.conn.response_generator = self._create_soa_response_data
self.assertEqual(self.conn.do_xfrin(True), XFRIN_OK)
@@ -1641,26 +1576,6 @@ class TestIXFRResponse(TestXfrinConnection):
[[('delete', begin_soa_rrset), ('add', soa_rrset)]],
self.conn._datasrc_client.committed_diffs)
- def test_ixfr_response_fail_validation(self):
- '''
- An IXFR that fails validation later on. Check it is rejected.
- '''
- self.conn.reply_data = self.conn.create_response_data(
- questions=[Question(TEST_ZONE_NAME, TEST_RRCLASS, RRType.IXFR())],
- answers=[soa_rrset, begin_soa_rrset, soa_rrset, soa_rrset])
- self._check_zone_result = False
- self.assertRaises(XfrinZoneError, self.conn._handle_xfrin_responses)
- self.assertEqual([], self.conn._datasrc_client.committed_diffs)
- self.assertEqual(TEST_ZONE_NAME, self._check_zone_params[0])
- self.assertEqual(TEST_RRCLASS, self._check_zone_params[1])
- self.assertTrue(isinstance(self._check_zone_params[2],
- MockRRsetCollection))
- # Check we can safely call the callbacks. They have no sideeffects
- # we can check (checking logging is hard), but we at least check
- # they don't crash.
- self._check_zone_params[3][0]("Test error")
- self._check_zone_params[3][1]("Test warning")
-
def test_ixfr_response_multi_sequences(self):
'''Similar to the previous case, but with multiple diff seqs.
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 66fbc52..da0f207 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -36,7 +36,6 @@ from isc.xfrin.diff import Diff
from isc.server_common.auth_command import auth_loadzone_command
from isc.server_common.tsig_keyring import init_keyring, get_keyring
from isc.log_messages.xfrin_messages import *
-from isc.dns import *
isc.log.init("b10-xfrin", buffer=True)
logger = isc.log.Logger("xfrin")
@@ -46,6 +45,13 @@ logger = isc.log.Logger("xfrin")
DBG_PROCESS = logger.DBGLVL_TRACE_BASIC
DBG_COMMANDS = logger.DBGLVL_TRACE_DETAIL
+try:
+ from pydnspp import *
+except ImportError as e:
+ # C++ loadable module may not be installed; even so the xfrin process
+ # must keep running, so we warn about it and move forward.
+ logger.error(XFRIN_IMPORT_DNS, str(e))
+
isc.util.process.rename()
# If B10_FROM_BUILD is set in the environment, we use data files
@@ -94,17 +100,8 @@ class XfrinProtocolError(Exception):
'''
pass
-class XfrinZoneError(Exception):
- '''
- An exception raised when the received zone is broken enough to be unusable.
- '''
- pass
-
class XfrinZoneUptodate(Exception):
- '''
- Thrown when the zone is already up to date, so there's no need to download
- the zone. This is not really an error case (but it's still an exceptional
- condition and the control flow is different than usual).
+ '''TBD
'''
pass
@@ -430,10 +427,10 @@ class XfrinIXFRAdd(XfrinState):
conn.get_transfer_stats().ixfr_changeset_count += 1
soa_serial = get_soa_serial(rr.get_rdata()[0])
if soa_serial == conn._end_serial:
- # The final part is there. Finish the transfer by
- # checking the last TSIG (if required), the zone data and
- # commiting.
- conn.finish_transfer()
+ # The final part is there. Check all was signed
+ # and commit it to the database.
+ conn._check_response_tsig_last()
+ conn._diff.commit()
self.set_xfrstate(conn, XfrinIXFREnd())
return True
elif soa_serial != conn._current_serial:
@@ -503,11 +500,15 @@ class XfrinAXFREnd(XfrinState):
"""
Final processing after processing an entire AXFR session.
- This simply calls the finish_transfer method of the connection
- that ensures it is signed by TSIG (if required), the zone data
- is valid and commits it.
+ In this process all the AXFR changes are committed to the
+ data source.
+
+ There might be more actions here, but for now we simply return False,
+ indicating there will be no more message to receive.
+
"""
- conn.finish_transfer()
+ conn._check_response_tsig_last()
+ conn._diff.commit()
return False
class XfrinTransferStats:
@@ -804,31 +805,6 @@ class XfrinConnection(asyncore.dispatcher):
raise XfrinProtocolError('TSIG verify fail: no TSIG on last '+
'message')
- def __validate_error(self, reason):
- '''
- Used as error callback below.
- '''
- logger.error(XFRIN_ZONE_INVALID, self._zone_name, self._rrclass,
- reason)
-
- def __validate_warning(self, reason):
- '''
- Used as warning callback below.
- '''
- logger.warn(XFRIN_ZONE_WARN, self._zone_name, self._rrclass, reason)
-
- def finish_transfer(self):
- """
- Perform any necessary checks after a transfer. Then complete the
- transfer by commiting the transaction into the data source.
- """
- self._check_response_tsig_last()
- if not check_zone(self._zone_name, self._rrclass,
- self._diff.get_rrset_collection(),
- (self.__validate_error, self.__validate_warning)):
- raise XfrinZoneError('Validation of the new zone failed')
- self._diff.commit()
-
def __parse_soa_response(self, msg, response_data):
'''Parse a response to SOA query and extract the SOA from answer.
@@ -974,15 +950,7 @@ class XfrinConnection(asyncore.dispatcher):
# of trying another primary server, etc, but for now we treat it
# as "success".
pass
- except XfrinZoneError:
- # The log message doesn't contain the exception text, since there's
- # only one place where the exception is thrown now and it'd be the
- # same generic message every time.
- logger.error(XFRIN_INVALID_ZONE_DATA, self.zone_str(),
- format_addrinfo(self._master_addrinfo))
- ret = XFRIN_FAIL
except XfrinProtocolError as e:
- # FIXME: Why is this .info? Even the messageID contains "ERROR".
logger.info(XFRIN_XFR_TRANSFER_PROTOCOL_ERROR, req_str,
self.zone_str(),
format_addrinfo(self._master_addrinfo), str(e))
@@ -1738,7 +1706,5 @@ def main(xfrin_class, use_signal=True):
if xfrind:
xfrind.shutdown()
- logger.info(XFRIN_EXITING)
-
if __name__ == '__main__':
main(Xfrin)
diff --git a/src/bin/xfrin/xfrin_messages.mes b/src/bin/xfrin/xfrin_messages.mes
index 20959e2..a40781a 100644
--- a/src/bin/xfrin/xfrin_messages.mes
+++ b/src/bin/xfrin/xfrin_messages.mes
@@ -60,9 +60,6 @@ error is given in the log message.
There was an error opening a connection to the master. The error is
shown in the log message.
-% XFRIN_EXITING exiting
-The xfrin daemon is exiting.
-
% XFRIN_GOT_INCREMENTAL_RESP got incremental response for %1
In an attempt of IXFR processing, the beginning SOA of the first difference
(following the initial SOA that specified the final SOA for all the
@@ -80,11 +77,6 @@ is not equal to the requested SOA serial.
There was an error importing the python DNS module pydnspp. The most
likely cause is a PYTHONPATH problem.
-% XFRIN_INVALID_ZONE_DATA zone %1 received from %2 is broken and unusable
-The zone was received, but it failed sanity validation. The previous version
-of zone (if any is available) will be used. Look for previous
-XFRIN_ZONE_INVALID messages to see the exact problem(s).
-
% XFRIN_IXFR_TRANSFER_SUCCESS incremental IXFR transfer of zone %1 succeeded (messages: %2, changesets: %3, deletions: %4, additions: %5, bytes: %6, run time: %7 seconds, %8 bytes/second)
The IXFR transfer for the given zone was successful.
The provided information contains the following values:
@@ -240,12 +232,6 @@ zones at a higher level. In future it is more likely that a separate
zone management framework is provided, and the situation where the
given zone isn't found in xfrout will be treated as an error.
-% XFRIN_ZONE_INVALID Newly received zone %1/%2 fails validation: %3
-The zone was received successfully, but it failed validation. The problem
-is severe enough that the new version of zone is discarded and the old version,
-if any, will stay in use. New transfer will be attempted after some time.
-The problem needs to be fixed in the zone data on the remote server.
-
% XFRIN_ZONE_MULTIPLE_SOA Zone %1 has %2 SOA RRs
On starting an xfrin session, it is identified that the zone to be
transferred has multiple SOA RRs. Such a zone is broken, but could be
@@ -272,9 +258,3 @@ the latest version of the zone. But if the primary server is known to
be the real source of the zone, some unexpected inconsistency may have
happened, and you may want to take a closer look. In this case xfrin
doesn't perform subsequent zone transfer.
-
-% XFRIN_ZONE_WARN Newly received zone %1/%2 has a problem: %3
-The zone was received successfully, but when checking it, it was discovered
-there's some issue with it. It might be correct, but it should be checked
-and possibly fixed on the remote server. The problem is described in the
-message. The problem does not stop the zone from being used.
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index c1885a9..f869955 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -1274,7 +1274,7 @@ if '__main__' == __name__:
xfrout_server = XfroutServer()
xfrout_server.run()
except KeyboardInterrupt:
- logger.info(XFROUT_STOPPED_BY_KEYBOARD)
+ logger.INFO(XFROUT_STOPPED_BY_KEYBOARD)
except SessionError as e:
logger.error(XFROUT_CC_SESSION_ERROR, str(e))
except ModuleCCSessionError as e:
@@ -1287,4 +1287,3 @@ if '__main__' == __name__:
if xfrout_server:
xfrout_server.shutdown()
- logger.info(XFROUT_EXITING)
diff --git a/src/bin/xfrout/xfrout_messages.mes b/src/bin/xfrout/xfrout_messages.mes
index 6b88d27..d48aa24 100644
--- a/src/bin/xfrout/xfrout_messages.mes
+++ b/src/bin/xfrout/xfrout_messages.mes
@@ -32,9 +32,6 @@ configuration manager b10-cfgmgr is not running.
The xfrout process encountered an error when installing the configuration at
startup time. Details of the error are included in the log message.
-% XFROUT_EXITING exiting
-The xfrout daemon is exiting.
-
% XFROUT_FETCH_REQUEST_ERROR socket error while fetching a request from the auth daemon
There was a socket error while contacting the b10-auth daemon to
fetch a transfer request. The auth daemon may have shutdown.
diff --git a/src/bin/zonemgr/zonemgr.py.in b/src/bin/zonemgr/zonemgr.py.in
index 7fa5f7d..0412e3f 100755
--- a/src/bin/zonemgr/zonemgr.py.in
+++ b/src/bin/zonemgr/zonemgr.py.in
@@ -714,4 +714,4 @@ if '__main__' == __name__:
if zonemgrd and zonemgrd.running:
zonemgrd.shutdown()
- logger.info(ZONEMGR_SHUTDOWN)
+ logger.debug(DBG_START_SHUT, ZONEMGR_SHUTDOWN)
diff --git a/src/bin/zonemgr/zonemgr_messages.mes b/src/bin/zonemgr/zonemgr_messages.mes
index a9cc094..4f58271 100644
--- a/src/bin/zonemgr/zonemgr_messages.mes
+++ b/src/bin/zonemgr/zonemgr_messages.mes
@@ -114,7 +114,7 @@ connecting to the command channel daemon. The most usual cause of this
problem is that the daemon is not running.
% ZONEMGR_SHUTDOWN zone manager has shut down
-The zone manager has shut down completely.
+A debug message, output when the zone manager has shut down completely.
% ZONEMGR_STARTED zonemgr started
This informational message is output by zonemgr when all initialization
diff --git a/src/lib/cc/cc_messages.mes b/src/lib/cc/cc_messages.mes
index b561784..94b955a 100644
--- a/src/lib/cc/cc_messages.mes
+++ b/src/lib/cc/cc_messages.mes
@@ -60,10 +60,6 @@ and its length (2 bytes) is counted in the total length.
There should be data representing the length of message on the socket, but it
is not there.
-% CC_LNAME_RECEIVED received local name: %1
-Debug message: the local module received its unique identifier (name)
-from msgq on completion of establishing the session with msgq.
-
% CC_NO_MESSAGE no message ready to be received yet
The program polled for incoming messages, but there was no message waiting.
This is a debug message which may happen only after CC_GROUP_RECEIVE.
diff --git a/src/lib/cc/session.cc b/src/lib/cc/session.cc
index 1d3fac2..47923f0 100644
--- a/src/lib/cc/session.cc
+++ b/src/lib/cc/session.cc
@@ -333,7 +333,6 @@ Session::establish(const char* socket_file) {
recvmsg(routing, msg, false);
impl_->lname_ = msg->get("lname")->stringValue();
- LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_LNAME_RECEIVED).arg(impl_->lname_);
// At this point there's no risk of resource leak.
session_holder.clear();
@@ -474,20 +473,20 @@ Session::unsubscribe(std::string group, std::string instance) {
int
Session::group_sendmsg(ConstElementPtr msg, std::string group,
- std::string instance, std::string to)
+ std::string instance, std::string to, bool want_answer)
{
LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_SEND).arg(msg->str()).
arg(group);
ElementPtr env = Element::createMap();
long int nseq = ++impl_->sequence_;
-
+
env->set("type", Element::create("send"));
env->set("from", Element::create(impl_->lname_));
env->set("to", Element::create(to));
env->set("group", Element::create(group));
env->set("instance", Element::create(instance));
env->set("seq", Element::create(nseq));
- //env->set("msg", Element::create(msg->toWire()));
+ env->set("want_answer", Element::create(want_answer));
sendmsg(env, msg);
return (nseq);
@@ -514,7 +513,7 @@ Session::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
arg(newmsg->str());
ElementPtr env = Element::createMap();
long int nseq = ++impl_->sequence_;
-
+
env->set("type", Element::create("send"));
env->set("from", Element::create(impl_->lname_));
env->set("to", Element::create(envelope->get("from")->stringValue()));
diff --git a/src/lib/cc/session.h b/src/lib/cc/session.h
index a818291..e0ece56 100644
--- a/src/lib/cc/session.h
+++ b/src/lib/cc/session.h
@@ -82,7 +82,8 @@ namespace isc {
virtual int group_sendmsg(isc::data::ConstElementPtr msg,
std::string group,
std::string instance = "*",
- std::string to = "*") = 0;
+ std::string to = "*",
+ bool want_answer = false) = 0;
virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
isc::data::ConstElementPtr& msg,
bool nonblock = true,
@@ -128,10 +129,24 @@ namespace isc {
std::string instance = "*");
virtual void unsubscribe(std::string group,
std::string instance = "*");
+ /// \brief Send a message to a group.
+ ///
+ /// \todo Can someone explain how the group, instance and to work?
+ /// What is the desired semantics here?
+ /// \param msg The message to send.
+ /// \param group Part of addressing.
+ /// \param instance Part of addressing.
+ /// \param to Part of addressing.
+ /// \param want_answer Require an answer? If it is true and there's
+ /// no recipient, the message queue answers by an error
+ /// instead.
+ /// \return The squence number of the message sent. It can be used
+ /// to wait for an answer by group_recvmsg.
virtual int group_sendmsg(isc::data::ConstElementPtr msg,
std::string group,
std::string instance = "*",
- std::string to = "*");
+ std::string to = "*",
+ bool want_answer = false);
virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
isc::data::ConstElementPtr& msg,
bool nonblock = true,
diff --git a/src/lib/cc/tests/session_unittests.cc b/src/lib/cc/tests/session_unittests.cc
index 528dda9..eb7101a 100644
--- a/src/lib/cc/tests/session_unittests.cc
+++ b/src/lib/cc/tests/session_unittests.cc
@@ -19,16 +19,28 @@
// XXX: the ASIO header must be included before others. See session.cc.
#include <asio.hpp>
+#include <cc/session.h>
+#include <cc/data.h>
+#include <cc/tests/session_unittests_config.h>
+
#include <gtest/gtest.h>
#include <boost/bind.hpp>
#include <exceptions/exceptions.h>
-#include <cc/session.h>
-#include <cc/data.h>
-#include <session_unittests_config.h>
+#include <utility>
+#include <vector>
+#include <string>
+#include <iostream>
using namespace isc::cc;
+using std::pair;
+using std::vector;
+using std::string;
+using isc::data::ConstElementPtr;
+using isc::data::Element;
+
+namespace {
TEST(AsioSession, establish) {
asio::io_service io_service_;
@@ -50,9 +62,11 @@ TEST(AsioSession, establish) {
"/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
), isc::cc::SessionError
);
-
}
+/// \brief Pair holding header and data of a message sent over the wire.
+typedef pair<ConstElementPtr, ConstElementPtr> SentMessage;
+
// This class sets up a domain socket for the session to connect to
// it will impersonate the msgq a tiny bit (if setSendLname() has
// been called, it will send an 'answer' to the lname query that is
@@ -70,18 +84,16 @@ public:
boost::bind(&TestDomainSocket::acceptHandler,
this, _1));
}
-
+
~TestDomainSocket() {
socket_.close();
unlink(BIND10_TEST_SOCKET_FILE);
}
- void
- acceptHandler(const asio::error_code&) const {
+ void acceptHandler(const asio::error_code&) const {
}
- void
- sendmsg(isc::data::ElementPtr& env, isc::data::ElementPtr& msg) {
+ void sendmsg(isc::data::ElementPtr& env, isc::data::ElementPtr& msg) {
const std::string header_wire = env->toWire();
const std::string body_wire = msg->toWire();
const unsigned int length = 2 + header_wire.length() +
@@ -89,7 +101,7 @@ public:
const unsigned int length_net = htonl(length);
const unsigned short header_length = header_wire.length();
const unsigned short header_length_net = htons(header_length);
-
+
socket_.send(asio::buffer(&length_net, sizeof(length_net)));
socket_.send(asio::buffer(&header_length_net,
sizeof(header_length_net)));
@@ -97,8 +109,54 @@ public:
socket_.send(asio::buffer(body_wire.data(), body_wire.length()));
}
- void
- sendLname() {
+ /// \brief Read a message from the socket
+ ///
+ /// Read a message from the socket and parse it. Block until it is
+ /// read or error happens. If error happens, it asio::system_error.
+ ///
+ /// This method would block for ever if the sender is not sending.
+ /// But the whole test has a timeout of 10 seconds (see the
+ /// SessionTest::SetUp and SessionTest::TearDown).
+ ///
+ /// \note The method assumes the wire data are correct and does not check
+ /// it. Strange things might happen if it is not the case, but the
+ /// test would likely fail as a result, so we prefer simplicity here.
+ ///
+ /// \return Pair containing the header and body elements (in this order).
+ SentMessage readmsg() {
+ // The format is:
+ // <uint32_t in net order = total length>
+ // <uint16_t in net order = header length>
+ // <char * header length = the header>
+ // <char * the rest of the total length = the data>
+
+ // Read and convert the lengths first.
+ uint32_t total_len_data;
+ uint16_t header_len_data;
+ vector<asio::mutable_buffer> len_buffers;
+ len_buffers.push_back(asio::buffer(&total_len_data,
+ sizeof total_len_data));
+ len_buffers.push_back(asio::buffer(&header_len_data,
+ sizeof header_len_data));
+ asio::read(socket_, len_buffers);
+ const uint32_t total_len = ntohl(total_len_data);
+ const uint16_t header_len = ntohs(header_len_data);
+ string header, msg;
+ header.resize(header_len);
+ msg.resize(total_len - header_len - sizeof header_len_data);
+ vector<asio::mutable_buffer> data_buffers;
+ data_buffers.push_back(asio::buffer(&header[0], header.size()));
+ data_buffers.push_back(asio::buffer(&msg[0], msg.size()));
+ asio::read(socket_, data_buffers);
+ if (msg == "") { // The case of no msg present, for control messages
+ msg = "null";
+ }
+ // Extract the right data into each string and convert.
+ return (SentMessage(Element::fromWire(header),
+ Element::fromWire(msg)));
+ }
+
+ void sendLname() {
isc::data::ElementPtr lname_answer1 =
isc::data::Element::fromJSON("{ \"type\": \"lname\" }");
isc::data::ElementPtr lname_answer2 =
@@ -106,13 +164,12 @@ public:
sendmsg(lname_answer1, lname_answer2);
}
- void
- setSendLname() {
+ void setSendLname() {
// ignore whatever data we get, send back an lname
asio::async_read(socket_, asio::buffer(data_buf, 0),
boost::bind(&TestDomainSocket::sendLname, this));
}
-
+
private:
asio::io_service& io_service_;
asio::local::stream_protocol::endpoint ep_;
@@ -134,6 +191,49 @@ protected:
delete tds;
}
+ void SetUp() {
+ // There are blocking reads in some tests. We want to have a safety
+ // catch in case the sender didn't write enough. We set a timeout of
+ // 10 seconds per one test (which should really be enough even on
+ // slow machines). If the timeout happens, it kills the test and
+ // the whole test fails.
+ //alarm(10);
+ }
+
+ void TearDown() {
+ // Cancel the timeout scheduled in SetUp. We don't want to kill any
+ // of the other tests by it by accident.
+ alarm(0);
+ }
+
+ // Check two elements are equal
+ void elementsEqual(const ConstElementPtr& expected,
+ const ConstElementPtr& actual)
+ {
+ EXPECT_TRUE(expected->equals(*actual)) <<
+ "Elements differ, expected: " << expected->toWire() <<
+ ", got: " << actual->toWire();
+ }
+
+ // The same, but with one specified as string
+ void elementsEqual(const string& expected,
+ const ConstElementPtr& actual)
+ {
+ const ConstElementPtr expected_el(Element::fromJSON(expected));
+ elementsEqual(expected_el, actual);
+ }
+
+ // Check the session sent a message with the given header. The
+ // message is hardcoded.
+ void checkSentMessage(const string& expected_hdr,
+ const char* description)
+ {
+ SCOPED_TRACE(description);
+ const SentMessage msg(tds->readmsg());
+ elementsEqual(expected_hdr, msg.first);
+ elementsEqual("{\"test\": 42}", msg.second);
+ }
+
public:
// used in the handler test
// This handler first reads (and ignores) whatever message caused
@@ -249,3 +349,55 @@ TEST_F(SessionTest, get_socket_descr) {
// expect actual socket handle to be returned, not 0
EXPECT_LT(0, socket);
}
+
+// Test the group_sendmsg sends the correct data.
+TEST_F(SessionTest, group_sendmsg) {
+ // Connect
+ tds->setSendLname();
+ sess.establish(BIND10_TEST_SOCKET_FILE);
+ elementsEqual("{\"type\": \"getlname\"}", tds->readmsg().first);
+
+ const ConstElementPtr msg(Element::fromJSON("{\"test\": 42}"));
+ sess.group_sendmsg(msg, "group");
+ checkSentMessage("{"
+ " \"from\": \"foobar\","
+ " \"group\": \"group\","
+ " \"instance\": \"*\","
+ " \"seq\": 0,"
+ " \"to\": \"*\","
+ " \"type\": \"send\","
+ " \"want_answer\": False"
+ "}", "No instance");
+ sess.group_sendmsg(msg, "group", "instance", "recipient");
+ checkSentMessage("{"
+ " \"from\": \"foobar\","
+ " \"group\": \"group\","
+ " \"instance\": \"instance\","
+ " \"seq\": 1,"
+ " \"to\": \"recipient\","
+ " \"type\": \"send\","
+ " \"want_answer\": False"
+ "}", "With instance");
+ sess.group_sendmsg(msg, "group", "*", "*", true);
+ checkSentMessage("{"
+ " \"from\": \"foobar\","
+ " \"group\": \"group\","
+ " \"instance\": \"*\","
+ " \"seq\": 2,"
+ " \"to\": \"*\","
+ " \"type\": \"send\","
+ " \"want_answer\": True"
+ "}", "Want answer");
+ sess.group_sendmsg(msg, "group", "*", "*", false);
+ checkSentMessage("{"
+ " \"from\": \"foobar\","
+ " \"group\": \"group\","
+ " \"instance\": \"*\","
+ " \"seq\": 3,"
+ " \"to\": \"*\","
+ " \"type\": \"send\","
+ " \"want_answer\": False"
+ "}", "Doesn't want answer");
+}
+
+}
diff --git a/src/lib/config/tests/fake_session.cc b/src/lib/config/tests/fake_session.cc
index 157d4d6..56a30d4 100644
--- a/src/lib/config/tests/fake_session.cc
+++ b/src/lib/config/tests/fake_session.cc
@@ -183,7 +183,7 @@ FakeSession::unsubscribe(std::string group, std::string instance) {
int
FakeSession::group_sendmsg(ConstElementPtr msg, std::string group,
- std::string to, std::string)
+ std::string to, std::string, bool)
{
if (throw_on_send_) {
isc_throw(Exception, "Throw on send is set in FakeSession");
diff --git a/src/lib/config/tests/fake_session.h b/src/lib/config/tests/fake_session.h
index 7d3cfde..0dbaadb 100644
--- a/src/lib/config/tests/fake_session.h
+++ b/src/lib/config/tests/fake_session.h
@@ -61,7 +61,8 @@ public:
virtual int group_sendmsg(isc::data::ConstElementPtr msg,
std::string group,
std::string instance = "*",
- std::string to = "*");
+ std::string to = "*",
+ bool want_answer = false);
virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
isc::data::ConstElementPtr& msg,
bool nonblock = true,
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index f6d8252..0ca9226 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -1385,7 +1385,7 @@ DatabaseClient::getIterator(const isc::dns::Name& name,
return (iterator);
}
-/// \brief Database implementation of RRsetCollectionBase.
+/// \brief datasrc implementation of RRsetCollectionBase.
class RRsetCollection : public isc::datasrc::RRsetCollectionBase {
public:
/// \brief Constructor.
@@ -1393,11 +1393,26 @@ public:
isc::datasrc::RRsetCollectionBase(updater, rrclass)
{}
+ /// \brief Destructor
+ virtual ~RRsetCollection() {}
+
/// \brief A wrapper around \c disable() so that it can be used as a
/// public method. \c disable() is protected.
void disableWrapper() {
disable();
}
+
+protected:
+ // TODO: RRsetCollectionBase::Iter is not implemented and the
+ // following two methods just throw.
+
+ virtual RRsetCollectionBase::IterPtr getBeginning() {
+ isc_throw(NotImplemented, "This method is not implemented.");
+ }
+
+ virtual RRsetCollectionBase::IterPtr getEnd() {
+ isc_throw(NotImplemented, "This method is not implemented.");
+ }
};
//
@@ -1439,7 +1454,7 @@ public:
virtual ZoneFinder& getFinder() { return (*finder_); }
- virtual isc::dns::RRsetCollectionBase& getRRsetCollection() {
+ virtual isc::datasrc::RRsetCollectionBase& getRRsetCollection() {
if (!rrset_collection_) {
// This is only assigned the first time and remains for the
// lifetime of the DatabaseUpdater.
diff --git a/src/lib/datasrc/datasrc_messages.mes b/src/lib/datasrc/datasrc_messages.mes
index 5311203..6ac9db0 100644
--- a/src/lib/datasrc/datasrc_messages.mes
+++ b/src/lib/datasrc/datasrc_messages.mes
@@ -197,16 +197,6 @@ modify the database). This is what the client would do when such RRs
were given in a DNS response according to RFC2181. The data in
database should be checked and fixed.
-% DATASRC_DATABASE_JOURNALREADER_BADDATA failed to convert a diff to RRset in %1/%2 on %3 between %4 and %5: %6
-This is an error message indicating that a zone's diff is broken and
-the data source library failed to convert it to a valid RRset. The
-most likely cause of this is that someone has manually modified the
-zone's diff in the database and inserted invalid data as a result.
-The zone's name and class, database name, and the start and end
-serials, and an additional detail of the error are shown in the
-message. The administrator should examine the diff in the database
-to find any invalid data and fix it.
-
% DATASRC_DATABASE_JOURNALREADER_END %1/%2 on %3 from %4 to %5
This is a debug message indicating that the program (successfully)
reaches the end of sequences of a zone's differences. The zone's name
@@ -225,6 +215,16 @@ a zone's difference sequences from a database-based data source. The
zone's name and class, database name, and the start and end serials
are shown in the message.
+% DATASRC_DATABASE_JOURNALREADER_BADDATA failed to convert a diff to RRset in %1/%2 on %3 between %4 and %5: %6
+This is an error message indicating that a zone's diff is broken and
+the data source library failed to convert it to a valid RRset. The
+most likely cause of this is that someone has manually modified the
+zone's diff in the database and inserted invalid data as a result.
+The zone's name and class, database name, and the start and end
+serials, and an additional detail of the error are shown in the
+message. The administrator should examine the diff in the database
+to find any invalid data and fix it.
+
% DATASRC_DATABASE_NO_MATCH not match for %2/%3/%4 in %1
No match (not even a wildcard) was found in the named data source for the given
name/type/class in the data source.
@@ -442,10 +442,6 @@ shown name, the search tries the superdomain name that share the shown
www.example.com. with shown label count of 3, example.com. is being
tried).
-% DATASRC_MEM_FIND_TYPE_AT_ORIGIN origin query for type %1 in in-memory zone %2/%3 successful
-Debug information. A specific type RRset is requested at a zone origin
-of an in-memory zone and it is found.
-
% DATASRC_MEM_FIND_ZONE looking for zone '%1'
Debug information. A zone object for this zone is being searched for in the
in-memory data source.
diff --git a/src/lib/datasrc/memory/treenode_rrset.cc b/src/lib/datasrc/memory/treenode_rrset.cc
index c4e16a6..e7ed20c 100644
--- a/src/lib/datasrc/memory/treenode_rrset.cc
+++ b/src/lib/datasrc/memory/treenode_rrset.cc
@@ -59,7 +59,8 @@ TreeNodeRRset::getName() const {
const RRTTL&
TreeNodeRRset::getTTL() const {
if (ttl_ == NULL) {
- util::InputBuffer ttl_buffer(ttl_data_, sizeof(uint32_t));
+ util::InputBuffer ttl_buffer(rdataset_->getTTLData(),
+ sizeof(uint32_t));
ttl_ = new RRTTL(ttl_buffer);
}
@@ -168,7 +169,7 @@ TreeNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
// Render the main (non RRSIG) RRs
const size_t rendered_rdata_count =
writeRRs(renderer, rdataset_->getRdataCount(), name_labels,
- rdataset_->type, rrclass_, ttl_data_, reader,
+ rdataset_->type, rrclass_, rdataset_->getTTLData(), reader,
&RdataReader::iterateRdata);
if (renderer.isTruncated()) {
return (rendered_rdata_count);
@@ -179,7 +180,7 @@ TreeNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
// Render any RRSIGs, if we supposed to do so
const size_t rendered_rrsig_count = dnssec_ok_ ?
writeRRs(renderer, rrsig_count_, name_labels, RRType::RRSIG(),
- rrclass_, ttl_data_, reader,
+ rrclass_, rdataset_->getTTLData(), reader,
&RdataReader::iterateSingleSig) : 0;
return (rendered_rdata_count + rendered_rrsig_count);
diff --git a/src/lib/datasrc/memory/treenode_rrset.h b/src/lib/datasrc/memory/treenode_rrset.h
index 295a95a..460a704 100644
--- a/src/lib/datasrc/memory/treenode_rrset.h
+++ b/src/lib/datasrc/memory/treenode_rrset.h
@@ -112,34 +112,12 @@ public:
const RdataSet* rdataset, bool dnssec_ok) :
node_(node), rdataset_(rdataset),
rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
- dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL),
- ttl_data_(rdataset->getTTLData()), ttl_(NULL)
- {}
-
- /// \brief Constructor with a specific TTL.
- ///
- /// This constructor is mostly the same as the normal version, but takes
- /// an extra parameter, \c ttl_data. It's expected to point to a memory
- /// region at least for 32 bits, and the corresponding 32-bit data will
- /// be used as wire-format TTL value of the RRset, instead of the TTL
- /// associated with \c rdataset.
- ///
- /// It's the caller's responsibility to guarantee the memory region is
- /// valid and intact throughout the lifetime of the RRset.
- ///
- /// \throw None
- TreeNodeRRset(const dns::RRClass& rrclass, const ZoneNode* node,
- const RdataSet* rdataset, bool dnssec_ok,
- const void* ttl_data) :
- node_(node), rdataset_(rdataset),
- rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
- dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL),
- ttl_data_(ttl_data), ttl_(NULL)
+ dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL), ttl_(NULL)
{}
/// \brief Constructor for wildcard-expanded owner name.
///
- /// This constructor is mostly the same as the normal version, but takes
+ /// This constructor is mostly the same as the other version, but takes
/// an extra parameter, \c realname. It effectively overrides the owner
/// name of the RRset; wherever the owner name is used (e.g., in the
/// \c toWire() method), the specified name will be used instead of
@@ -155,7 +133,7 @@ public:
node_(node), rdataset_(rdataset),
rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
dnssec_ok_(dnssec_ok), name_(NULL), realname_(new dns::Name(realname)),
- ttl_data_(rdataset->getTTLData()), ttl_(NULL)
+ ttl_(NULL)
{}
virtual ~TreeNodeRRset() {
@@ -277,7 +255,6 @@ private:
const bool dnssec_ok_;
mutable dns::Name* name_;
const dns::Name* const realname_;
- const void* const ttl_data_;
mutable dns::RRTTL* ttl_;
};
diff --git a/src/lib/datasrc/memory/zone_data.cc b/src/lib/datasrc/memory/zone_data.cc
index d32fc87..cc31419 100644
--- a/src/lib/datasrc/memory/zone_data.cc
+++ b/src/lib/datasrc/memory/zone_data.cc
@@ -134,31 +134,6 @@ NSEC3Data::insertName(util::MemorySegment& mem_sgmt, const Name& name,
result == ZoneTree::ALREADYEXISTS) && node != NULL);
}
-namespace {
-// A helper to convert a TTL value in network byte order and set it in
-// ZoneData::min_ttl_. We can use util::OutputBuffer, but copy the logic
-// here to guarantee it is exception free.
-// Note: essentially this function is a local (re)implementation of the
-// standard htonl() library function, but we avoid relying on it in case it's
-// not available (it's not in the C++ standard library).
-void
-setTTLInNetOrder(uint32_t val, uint32_t* result) {
- uint8_t buf[4];
- buf[0] = static_cast<uint8_t>((val & 0xff000000) >> 24);
- buf[1] = static_cast<uint8_t>((val & 0x00ff0000) >> 16);
- buf[2] = static_cast<uint8_t>((val & 0x0000ff00) >> 8);
- buf[3] = static_cast<uint8_t>(val & 0x000000ff);
- std::memcpy(result, buf, sizeof(*result));
-}
-}
-
-ZoneData::ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
- zone_tree_(zone_tree), origin_node_(origin_node),
- min_ttl_(0) // tentatively set to silence static checkers
-{
- setTTLInNetOrder(RRTTL::MAX_TTL().getValue(), &min_ttl_);
-}
-
ZoneData*
ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
// ZoneTree::insert() and ZoneData allocation can throw. See also
@@ -203,11 +178,6 @@ ZoneData::insertName(util::MemorySegment& mem_sgmt, const Name& name,
result == ZoneTree::ALREADYEXISTS) && node != NULL);
}
-void
-ZoneData::setMinTTL(uint32_t min_ttl_val) {
- setTTLInNetOrder(min_ttl_val, &min_ttl_);
-}
-
} // namespace memory
} // namespace datasrc
} // datasrc isc
diff --git a/src/lib/datasrc/memory/zone_data.h b/src/lib/datasrc/memory/zone_data.h
index c6b3dcc..974ce24 100644
--- a/src/lib/datasrc/memory/zone_data.h
+++ b/src/lib/datasrc/memory/zone_data.h
@@ -287,7 +287,7 @@ private:
/// from NSEC to NSEC3 or vice versa, support incremental signing, or support
/// multiple sets of NSEC3 parameters.
///
-/// One other type of meta data is the status of the zone in terms of DNSSEC
+/// One last type of meta data is the status of the zone in terms of DNSSEC
/// signing. This class supports the following concepts:
/// - Whether the zone is signed or not, either with NSEC records or NSEC3
/// records.
@@ -315,15 +315,6 @@ private:
/// because we won't have to change the application code when we implement
/// the future separation.
///
-/// One last type of meta data is the zone's "minimum" TTL. It's expected
-/// to be a shortcut copy of the minimum field of the zone's SOA RDATA,
-/// and is expected to be used to create an SOA RR for a negative response,
-/// whose RR TTL may have to be set to this value according to RFC2308.
-/// This class is not aware of such usage, however, and only provides a
-/// simple getter and setter method for this value: \c getMinTTLData() and
-/// \c setMinTTL(). The user of this class is responsible for setting the
-/// value with \c setMinTTL() when it loads or updates the SOA RR.
-///
/// The intended usage of these two status concepts is to implement the
/// \c ZoneFinder::Context::isNSECSigned() and
/// \c ZoneFinder::Context::isNSEC3Signed() methods. A possible implementation
@@ -358,7 +349,9 @@ private:
/// allocator (\c create()), so the constructor is hidden as private.
///
/// It never throws an exception.
- ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node);
+ ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
+ zone_tree_(zone_tree), origin_node_(origin_node)
+ {}
// Zone node flags.
private:
@@ -420,7 +413,7 @@ public:
///
/// The class encapsulation ensures that the origin node always exists at
/// the same address, so this method always returns a non-NULL valid
- /// pointer.
+ /// valid pointer.
///
/// \throw none
const ZoneNode* getOriginNode() const {
@@ -463,26 +456,6 @@ public:
///
/// \throw none
const NSEC3Data* getNSEC3Data() const { return (nsec3_data_.get()); }
-
- /// \brief Return a pointer to the zone's minimum TTL data.
- ///
- /// The returned pointer points to a memory region that is valid at least
- /// for 32 bits, storing the zone's minimum TTL in the network byte
- /// order. The corresponding 32-bit value as an integer is initially
- /// set to the value of \c dns::RRTTL::MAX_TTL(), and, once
- /// \c setMinTTL() is called, set to the value specified at the latest
- /// call to \c setMinTTL().
- ///
- /// It returns opaque data to make it clear that unless the wire
- /// format data is necessary (e.g., when rendering it in a DNS message),
- /// it should be converted to, e.g., an \c RRTTL object explicitly.
- ///
- /// The returned pointer is valid as long as the \c ZoneData is valid,
- /// and the corresponding 32-bit data are the same until \c setMinTTL()
- /// is called.
- ///
- /// \throw none
- const void* getMinTTLData() const { return (&min_ttl_); }
//@}
///
@@ -579,32 +552,12 @@ public:
nsec3_data_ = nsec3_data;
return (old);
}
-
- /// \brief Set the zone's "minimum" TTL.
- ///
- /// This method updates the recorded minimum TTL of the zone data.
- /// It's expected to be identical to the value of the Minimum field
- /// of the SOA RR at the zone apex, but this method does not check the
- /// consistency; it's the caller's responsibility.
- ///
- /// While RFC2181 specifies the max TTL value to be 2^31-1, this method
- /// does not check the range; it accepts any unsigned 32-bit integer
- /// value. In practice, this shouldn't cause a problem, however, because
- /// the only expected usage of this value is to use the minimum of this
- /// value and SOA RR's TTL, and the latter is expected to be in the
- /// valid range.
- ///
- /// \throw None
- /// \param min_ttl_val The minimum TTL value as unsigned 32-bit integer
- /// in the host byte order.
- void setMinTTL(uint32_t min_ttl_val);
//@}
private:
const boost::interprocess::offset_ptr<ZoneTree> zone_tree_;
const boost::interprocess::offset_ptr<ZoneNode> origin_node_;
boost::interprocess::offset_ptr<NSEC3Data> nsec3_data_;
- uint32_t min_ttl_;
};
} // namespace memory
diff --git a/src/lib/datasrc/memory/zone_data_updater.cc b/src/lib/datasrc/memory/zone_data_updater.cc
index 5bde6d4..51ec03c 100644
--- a/src/lib/datasrc/memory/zone_data_updater.cc
+++ b/src/lib/datasrc/memory/zone_data_updater.cc
@@ -336,17 +336,6 @@ ZoneDataUpdater::addRdataSet(const Name& name, const RRType& rrtype,
// "NSEC signed")
zone_data_.setSigned(true);
}
-
- // If we are adding a new SOA at the origin, update zone's min TTL.
- // Note: if the input is broken and contains multiple SOAs, the load
- // or update will be rejected higher level. We just always (though
- // this should be only once in normal cases) update the TTL.
- if (rrset && rrtype == RRType::SOA() && is_origin) {
- // Our own validation ensures the RRset is not empty.
- zone_data_.setMinTTL(
- dynamic_cast<const generic::SOA&>(
- rrset->getRdataIterator()->getCurrent()).getMinimum());
- }
}
}
diff --git a/src/lib/datasrc/memory/zone_finder.cc b/src/lib/datasrc/memory/zone_finder.cc
index 56c4110..bc21869 100644
--- a/src/lib/datasrc/memory/zone_finder.cc
+++ b/src/lib/datasrc/memory/zone_finder.cc
@@ -23,13 +23,10 @@
#include <dns/name.h>
#include <dns/rrset.h>
#include <dns/rrtype.h>
-#include <dns/rrttl.h>
#include <dns/nsec3hash.h>
#include <datasrc/logger.h>
-#include <util/buffer.h>
-
#include <boost/scoped_ptr.hpp>
#include <boost/bind.hpp>
@@ -107,19 +104,14 @@ createTreeNodeRRset(const ZoneNode* node,
const RdataSet* rdataset,
const RRClass& rrclass,
ZoneFinder::FindOptions options,
- const Name* realname = NULL,
- const void* ttl_data = NULL)
+ const Name* realname = NULL)
{
const bool dnssec = ((options & ZoneFinder::FIND_DNSSEC) != 0);
- if (node && rdataset) {
- if (realname) {
+ if (node != NULL && rdataset != NULL) {
+ if (realname != NULL) {
return (TreeNodeRRsetPtr(new TreeNodeRRset(*realname, rrclass,
node, rdataset,
dnssec)));
- } else if (ttl_data) {
- assert(!realname); // these two cases should be mixed in our use
- return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
- dnssec, ttl_data)));
} else {
return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
dnssec)));
@@ -237,12 +229,6 @@ createNSEC3RRset(const ZoneNode* node, const RRClass& rrclass) {
ZoneFinder::FIND_DNSSEC));
}
-inline RRTTL
-createTTLFromData(const void* ttl_data) {
- util::InputBuffer b(ttl_data, sizeof(uint32_t));
- return (RRTTL(b));
-}
-
// convenience function to fill in the final details
//
// Set up ZoneFinderResultContext object as a return value of find(),
@@ -264,8 +250,7 @@ createFindResult(const RRClass& rrclass,
const RdataSet* rdataset,
ZoneFinder::FindOptions options,
bool wild = false,
- const Name* qname = NULL,
- bool use_minttl = false)
+ const Name* qname = NULL)
{
ZoneFinder::FindResultFlags flags = ZoneFinder::RESULT_DEFAULT;
const Name* rename = NULL;
@@ -283,15 +268,6 @@ createFindResult(const RRClass& rrclass,
}
}
- if (use_minttl && rdataset &&
- createTTLFromData(zone_data.getMinTTLData()) <
- createTTLFromData(rdataset->getTTLData())) {
- return (ZoneFinderResultContext(
- code,
- createTreeNodeRRset(node, rdataset, rrclass, options,
- rename, zone_data.getMinTTLData()),
- flags, zone_data, node, rdataset));
- }
return (ZoneFinderResultContext(code, createTreeNodeRRset(node, rdataset,
rrclass, options,
rename),
@@ -745,8 +721,8 @@ InMemoryZoneFinder::Context::findAdditional(
boost::shared_ptr<ZoneFinder::Context>
InMemoryZoneFinder::find(const isc::dns::Name& name,
- const isc::dns::RRType& type,
- const FindOptions options)
+ const isc::dns::RRType& type,
+ const FindOptions options)
{
return (ZoneFinderContextPtr(new Context(*this, options, rrclass_,
findInternal(name, type,
@@ -755,8 +731,8 @@ InMemoryZoneFinder::find(const isc::dns::Name& name,
boost::shared_ptr<ZoneFinder::Context>
InMemoryZoneFinder::findAll(const isc::dns::Name& name,
- std::vector<isc::dns::ConstRRsetPtr>& target,
- const FindOptions options)
+ std::vector<isc::dns::ConstRRsetPtr>& target,
+ const FindOptions options)
{
return (ZoneFinderContextPtr(new Context(*this, options, rrclass_,
findInternal(name,
@@ -765,44 +741,6 @@ InMemoryZoneFinder::findAll(const isc::dns::Name& name,
options))));
}
-// The implementation is a special case of the generic findInternal: we know
-// the qname should have an "exact match" and its node is accessible via
-// getOriginNode(); and, since there should be at least SOA RR at the origin
-// the case of CNAME can be eliminated (these should be guaranteed at the load
-// or update time, but even if they miss a corner case and allows a CNAME to
-// be added at origin, the zone is broken anyway, so we'd just let this
-// method return garbage, too). As a result, there can be only too cases
-// for the result codes: SUCCESS if the requested type of RR exists; NXRRSET
-// otherwise. Due to its simplicity we implement it separately, rather than
-// sharing the code with findInternal.
-boost::shared_ptr<ZoneFinder::Context>
-InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
- bool use_minttl,
- const FindOptions options)
-{
- const ZoneNode* const node = zone_data_.getOriginNode();
- const RdataSet* const found = RdataSet::find(node->getData(), type);
-
- if (found != NULL) {
- LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_FIND_TYPE_AT_ORIGIN).
- arg(type).arg(getOrigin()).arg(rrclass_);
- return (ZoneFinderContextPtr(
- new Context(*this, options, rrclass_,
- createFindResult(rrclass_, zone_data_, SUCCESS,
- node, found, options, false,
- NULL, use_minttl))));
- }
- return (ZoneFinderContextPtr(
- new Context(*this, options, rrclass_,
- createFindResult(rrclass_, zone_data_, NXRRSET,
- node,
- getNSECForNXRRSET(zone_data_,
- options,
- node),
- options, false, NULL,
- use_minttl))));
-}
-
ZoneFinderResultContext
InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
const isc::dns::RRType& type,
diff --git a/src/lib/datasrc/memory/zone_finder.h b/src/lib/datasrc/memory/zone_finder.h
index cd2bd58..254f5d2 100644
--- a/src/lib/datasrc/memory/zone_finder.h
+++ b/src/lib/datasrc/memory/zone_finder.h
@@ -60,16 +60,6 @@ public:
const isc::dns::RRType& type,
const FindOptions options = FIND_DEFAULT);
- /// \brief Search for an RRset of given RR type at the zone origin
- /// specialized for in-memory data source.
- ///
- /// This specialized version exploits internal data structure to find
- /// RRsets at the zone origin and (if \c use_minttl is true) extract
- /// the SOA Minimum TTL much more efficiently.
- virtual boost::shared_ptr<Context> findAtOrigin(
- const isc::dns::RRType& type, bool use_minttl,
- FindOptions options);
-
/// \brief Version of find that returns all types at once
///
/// It acts the same as find, just that when the correct node is found,
@@ -118,7 +108,3 @@ private:
} // namespace isc
#endif // DATASRC_MEMORY_ZONE_FINDER_H
-
-// Local Variables:
-// mode: c++
-// End:
diff --git a/src/lib/datasrc/rrset_collection_base.h b/src/lib/datasrc/rrset_collection_base.h
index 66b5825..c02df9a 100644
--- a/src/lib/datasrc/rrset_collection_base.h
+++ b/src/lib/datasrc/rrset_collection_base.h
@@ -22,33 +22,14 @@
namespace isc {
namespace datasrc {
+/// \brief A forward declaration
+class ZoneUpdater;
+
/// \brief datasrc derivation of \c isc::dns::RRsetCollectionBase.
///
-/// This is a default datasrc implementation of
-/// \c isc::dns::RRsetCollectionBase that adds datasrc related detail.
-///
-/// While it is a concrete class to be used along with a \c ZoneUpdater,
-/// specific \c ZoneUpdater implementations may derive from it and add
-/// additional detail. Unless you are implementing a \c ZoneUpdater, you
-/// must not use the constructor directly. Instead use the
-/// \c ZoneUpdater::getRRsetCollection() method to get a reference to
-/// the \c RRsetCollectionBase object for that \c ZoneUpdater. This is
-/// usually a singleton object and the API is designed with this in
-/// mind, because multiple \c RRsetCollectionBase objects cannot be used
-/// at the same time in most kinds of database implementations
-/// (esp. where iterators are in use). Specific \c ZoneUpdaters that can
-/// allow multiple \c RRsetCollection objects may provide additional
-/// API, but that is unspecified here.
-///
-/// There are some restrictions on when an \c RRsetCollection may be
-/// used. Though code may have a reference to an \c RRsetCollection
-/// object, it is not always valid to use it. Implementations of
-/// \c ZoneUpdater may disable an \c RRsetCollection previously returned
-/// by \c ZoneUpdater::getRRsetCollection() after \c commit() is called
-/// on the \c ZoneUpdater. An \c isc::dns::RRsetCollectionError
-/// exception will be thrown if an \c RRsetCollection is used when
-/// disabled. Please see the \c ZoneUpdater methods' documentation for
-/// more detail.
+/// This is an abstract class that adds datasrc related detail to
+/// \c isc::dns::RRsetCollectionBase. Derived classes need to complete
+/// the implementation (add iterator support, etc.) before using it.
class RRsetCollectionBase : public isc::dns::RRsetCollectionBase {
public:
/// \brief Constructor.
@@ -109,18 +90,18 @@ protected:
/// \brief See \c isc::dns::RRsetCollectionBase::getBeginning() for
/// documentation.
///
- /// \throw isc::NotImplemented as it's not implemented currently.
- virtual IterPtr getBeginning() {
- isc_throw(NotImplemented, "This method is not implemented.");
- }
+ /// \throw isc::dns::RRsetCollectionError if using the iterator
+ /// results in some underlying datasrc error, or if \c disable() was
+ /// called.
+ virtual IterPtr getBeginning() = 0;
/// \brief See \c isc::dns::RRsetCollectionBase::getEnd() for
/// documentation.
///
- /// \throw isc::NotImplemented as it's not implemented currently.
- virtual IterPtr getEnd() {
- isc_throw(NotImplemented, "This method is not implemented.");
- }
+ /// \throw isc::dns::RRsetCollectionError if using the iterator
+ /// results in some underlying datasrc error, or if \c disable() was
+ /// called.
+ virtual IterPtr getEnd() = 0;
private:
ZoneUpdater& updater_;
@@ -128,6 +109,13 @@ private:
bool disabled_;
};
+/// \brief A pointer-like type pointing to an
+/// \c isc::datasrc::RRsetCollectionBase object.
+///
+/// This type is used to handle RRsetCollections in a polymorphic manner
+/// in libdatasrc.
+typedef boost::shared_ptr<isc::datasrc::RRsetCollectionBase> RRsetCollectionPtr;
+
} // end of namespace datasrc
} // end of namespace isc
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index e52d9e9..c293540 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -4447,7 +4447,7 @@ public:
{}
ZoneUpdaterPtr updater;
- isc::dns::RRsetCollectionBase& collection;
+ isc::datasrc::RRsetCollectionBase& collection;
};
TYPED_TEST(RRsetCollectionTest, find) {
@@ -4592,14 +4592,7 @@ TYPED_TEST(RRsetCollectionAndUpdaterTest, updateThrows) {
// Now setup a new updater and call getRRsetCollection() on it.
this->updater_.reset();
this->updater_ = this->client_->getUpdater(this->zname_, false);
-
- // Just call getRRsetCollection() here. The test using .find() is
- // unnecessary for the purpose of this test case, but we have it to
- // use the result of getRRsetCollection() and silence some compiler
- // complaining about ignoring the return value of
- // getRRsetCollection().
- EXPECT_FALSE(this->updater_->getRRsetCollection().
- find(Name("www.example.org"), RRClass::IN(), RRType::MX()));
+ (void) this->updater_->getRRsetCollection();
// addRRset() must throw isc::InvalidOperation here.
EXPECT_THROW(this->updater_->addRRset(*this->rrset_),
@@ -4617,12 +4610,7 @@ TYPED_TEST(RRsetCollectionAndUpdaterTest, updateThrows) {
this->updater_.reset();
this->updater_ = this->client_->getUpdater(this->zname_, false);
this->updater_->addRRset(*this->rrset_);
-
- // Just call getRRsetCollection() here. The .find() is unnecessary,
- // but we have it to use the result of getRRsetCollection().
- this->updater_->getRRsetCollection().find(Name("www.example.org"),
- RRClass::IN(),
- RRType::MX());
+ (void) this->updater_->getRRsetCollection();
// deleteRRset() must throw isc::InvalidOperation here.
EXPECT_THROW(this->updater_->deleteRRset(*this->rrset_),
@@ -4632,7 +4620,7 @@ TYPED_TEST(RRsetCollectionAndUpdaterTest, updateThrows) {
// Test that using an RRsetCollection after calling commit() on the
// ZoneUpdater throws, as the RRsetCollection is disabled.
TYPED_TEST(RRsetCollectionAndUpdaterTest, useAfterCommitThrows) {
- isc::dns::RRsetCollectionBase& collection =
+ isc::datasrc::RRsetCollectionBase& collection =
this->updater_->getRRsetCollection();
// find() must not throw here.
diff --git a/src/lib/datasrc/tests/master_loader_callbacks_test.cc b/src/lib/datasrc/tests/master_loader_callbacks_test.cc
index fb4487a..dc44461 100644
--- a/src/lib/datasrc/tests/master_loader_callbacks_test.cc
+++ b/src/lib/datasrc/tests/master_loader_callbacks_test.cc
@@ -65,7 +65,7 @@ public:
virtual ZoneFinder& getFinder() {
isc_throw(isc::NotImplemented, "Not to be called in this test");
}
- virtual isc::dns::RRsetCollectionBase& getRRsetCollection() {
+ virtual isc::datasrc::RRsetCollectionBase& getRRsetCollection() {
isc_throw(isc::NotImplemented, "Not to be called in this test");
}
virtual void deleteRRset(const isc::dns::AbstractRRset&) {
diff --git a/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc b/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc
index c331eaa..02ad2bd 100644
--- a/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc
+++ b/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc
@@ -194,14 +194,8 @@ checkBasicFields(const AbstractRRset& actual_rrset, const RdataSet* rdataset,
// a temporary non-copyable object.
boost::shared_ptr<TreeNodeRRset>
createRRset(const RRClass& rrclass, const ZoneNode* node,
- const RdataSet* rdataset, bool dnssec_ok,
- const void* ttl_data = NULL)
+ const RdataSet* rdataset, bool dnssec_ok)
{
- if (ttl_data) {
- return (boost::shared_ptr<TreeNodeRRset>(
- new TreeNodeRRset(rrclass, node, rdataset, dnssec_ok,
- ttl_data)));
- }
return (boost::shared_ptr<TreeNodeRRset>(
new TreeNodeRRset(rrclass, node, rdataset, dnssec_ok)));
}
@@ -249,13 +243,6 @@ TEST_F(TreeNodeRRsetTest, create) {
true),
wildcard_rdataset_, match_name_, rrclass_, RRType::A(),
3600, 2, 1);
-
- // Constructed with explicit TTL
- const uint32_t ttl = 0; // use 0 to avoid byte-order conversion
- checkBasicFields(*createRRset(rrclass_, www_node_, a_rdataset_, true,
- &ttl),
- a_rdataset_, www_name_, rrclass_, RRType::A(), 0, 2,
- 1);
}
// The following two templated functions are helper to encapsulate the
@@ -350,21 +337,6 @@ TEST_F(TreeNodeRRsetTest, toWire) {
}
{
- SCOPED_TRACE("with RRSIG, DNSSEC OK, explicit TTL");
- const uint32_t ttl = 0;
- const TreeNodeRRset rrset(rrclass_, www_node_, a_rdataset_, true,
- &ttl);
- checkToWireResult(expected_renderer, actual_renderer, rrset,
- www_name_,
- textToRRset("www.example.com. 0 IN A 192.0.2.1\n"
- "www.example.com. 0 IN A 192.0.2.2"),
- textToRRset("www.example.com. 0 IN RRSIG "
- "A 5 2 3600 20120814220826 "
- "20120715220826 1234 example.com. FAKE"),
- true);
- }
-
- {
SCOPED_TRACE("with RRSIG, DNSSEC not OK");
const TreeNodeRRset rrset(rrclass_, www_node_, a_rdataset_, false);
checkToWireResult(expected_renderer, actual_renderer, rrset,
@@ -424,7 +396,7 @@ TEST_F(TreeNodeRRsetTest, toWire) {
const TreeNodeRRset rrset(rrclass_, www_node_, rrsig_only_rdataset_,
true);
checkToWireResult(expected_renderer, actual_renderer, rrset,
- www_name_, ConstRRsetPtr(), txt_rrsig_rrset_, true);
+ www_name_, ConstRRsetPtr(), txt_rrsig_rrset_,true);
}
{
@@ -435,7 +407,7 @@ TEST_F(TreeNodeRRsetTest, toWire) {
const TreeNodeRRset rrset(rrclass_, www_node_, rrsig_only_rdataset_,
false);
checkToWireResult(expected_renderer, actual_renderer, rrset,
- www_name_, ConstRRsetPtr(), txt_rrsig_rrset_, false);
+ www_name_, ConstRRsetPtr(), txt_rrsig_rrset_,false);
}
}
@@ -550,14 +522,6 @@ TEST_F(TreeNodeRRsetTest, toText) {
// Constructed with RRSIG, and it should be visible.
checkToText(*createRRset(rrclass_, www_node_, a_rdataset_, true),
a_rrset_, a_rrsig_rrset_);
- // Same as the previous, but with explicit TTL.
- const uint32_t ttl = 0;
- checkToText(*createRRset(rrclass_, www_node_, a_rdataset_, true, &ttl),
- textToRRset("www.example.com. 0 IN A 192.0.2.1\n"
- "www.example.com. 0 IN A 192.0.2.2"),
- textToRRset("www.example.com. 0 IN RRSIG A 5 2 3600 "
- "20120814220826 20120715220826 1234 example.com. "
- "FAKE"));
// Constructed with RRSIG, and it should be invisible.
checkToText(*createRRset(rrclass_, www_node_, a_rdataset_, false),
a_rrset_, ConstRRsetPtr());
@@ -592,11 +556,6 @@ TEST_F(TreeNodeRRsetTest, isSameKind) {
EXPECT_TRUE(rrset.isSameKind(*createRRset(rrclass_, www_node_,
a_rdataset_, true)));
- // Similar to the previous, but with explicit (different TTL) => still same
- const uint32_t ttl = 0;
- EXPECT_TRUE(rrset.isSameKind(*createRRset(rrclass_, www_node_,
- a_rdataset_, true, &ttl)));
-
// Same name (node), different type (rdataset) => not same kind
EXPECT_FALSE(rrset.isSameKind(*createRRset(rrclass_, www_node_,
aaaa_rdataset_, true)));
diff --git a/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc
index abc6f13..c005bf1 100644
--- a/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc
@@ -12,15 +12,13 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-#include <datasrc/memory/zone_data_loader.h>
+#include <dns/name.h>
+#include <dns/rrclass.h>
+
#include <datasrc/memory/rdataset.h>
#include <datasrc/memory/zone_data.h>
#include <datasrc/memory/zone_data_updater.h>
-
-#include <util/buffer.h>
-
-#include <dns/name.h>
-#include <dns/rrclass.h>
+#include <datasrc/memory/zone_data_loader.h>
#include "memory_segment_test.h"
@@ -64,13 +62,4 @@ TEST_F(ZoneDataLoaderTest, loadRRSIGFollowsNothing) {
// Teardown checks for memory segment leaks
}
-TEST_F(ZoneDataLoaderTest, zoneMinTTL) {
- // This should hold outside of the loader class, but we do double check.
- zone_data_ = loadZoneData(mem_sgmt_, zclass_, Name("example.org"),
- TEST_DATA_DIR
- "/example.org-nsec3-signed.zone");
- isc::util::InputBuffer b(zone_data_->getMinTTLData(), sizeof(uint32_t));
- EXPECT_EQ(RRTTL(1200), RRTTL(b));
-}
-
}
diff --git a/src/lib/datasrc/tests/memory/zone_data_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_unittest.cc
index ffbd0f6..1605fa2 100644
--- a/src/lib/datasrc/tests/memory/zone_data_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_unittest.cc
@@ -12,22 +12,19 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-#include <datasrc/memory/zone_data.h>
-#include <datasrc/memory/rdata_serialization.h>
-#include <datasrc/memory/rdataset.h>
-
#include "memory_segment_test.h"
#include <dns/rdataclass.h>
#include <exceptions/exceptions.h>
-#include <util/buffer.h>
-
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/rrclass.h>
-#include <dns/rrttl.h>
+
+#include <datasrc/memory/rdata_serialization.h>
+#include <datasrc/memory/rdataset.h>
+#include <datasrc/memory/zone_data.h>
#include <testutils/dnsmessage_test.h>
@@ -261,21 +258,4 @@ TEST_F(ZoneDataTest, isSigned) {
zone_data_->setSigned(false);
EXPECT_FALSE(zone_data_->isSigned());
}
-
-// A simple wrapper to reconstruct an RRTTL object from wire-format TTL
-// data (32 bits)
-RRTTL
-createRRTTL(const void* ttl_data) {
- isc::util::InputBuffer b(ttl_data, sizeof(uint32_t));
- return (RRTTL(b));
-}
-
-TEST_F(ZoneDataTest, minTTL) {
- // By default it's tentatively set to "max TTL"
- EXPECT_EQ(RRTTL::MAX_TTL(), createRRTTL(zone_data_->getMinTTLData()));
-
- // Explicitly set, then retrieve it.
- zone_data_->setMinTTL(1200);
- EXPECT_EQ(RRTTL(1200), createRRTTL(zone_data_->getMinTTLData()));
-}
}
diff --git a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
index 93ca0c9..63c69c8 100644
--- a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
@@ -12,10 +12,6 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-#include <datasrc/memory/zone_data_updater.h>
-#include <datasrc/memory/rdataset.h>
-#include <datasrc/memory/zone_data.h>
-
#include <testutils/dnsmessage_test.h>
#include <exceptions/exceptions.h>
@@ -23,7 +19,10 @@
#include <dns/name.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
-#include <dns/rrttl.h>
+
+#include <datasrc/memory/rdataset.h>
+#include <datasrc/memory/zone_data.h>
+#include <datasrc/memory/zone_data_updater.h>
#include "memory_segment_test.h"
@@ -87,16 +86,6 @@ getNode(isc::util::MemorySegment& mem_sgmt, const Name& name,
return (node);
}
-TEST_F(ZoneDataUpdaterTest, zoneMinTTL) {
- // If we add SOA, zone's min TTL will be updated.
- updater_->add(textToRRset(
- "example.org. 3600 IN SOA . . 0 0 0 0 1200",
- zclass_, zname_),
- ConstRRsetPtr());
- isc::util::InputBuffer b(zone_data_->getMinTTLData(), sizeof(uint32_t));
- EXPECT_EQ(RRTTL(1200), RRTTL(b));
-}
-
TEST_F(ZoneDataUpdaterTest, rrsigOnly) {
// RRSIG that doesn't have covered RRset can be added. The resulting
// rdataset won't have "normal" RDATA but sig RDATA.
diff --git a/src/lib/datasrc/tests/memory/zone_finder_unittest.cc b/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
index 055708d..42667da 100644
--- a/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
@@ -53,6 +53,19 @@ namespace {
using result::SUCCESS;
using result::EXIST;
+/// \brief expensive rrset converter
+///
+/// converts any specialized rrset (which may not have implemented some
+/// methods for efficiency) into a 'full' RRsetPtr, for easy use in test
+/// checks.
+///
+/// Done very inefficiently through text representation, speed should not
+/// be a concern here.
+ConstRRsetPtr
+convertRRset(ConstRRsetPtr src) {
+ return (textToRRset(src->toText()));
+}
+
/// \brief Test fixture for the InMemoryZoneFinder class
class InMemoryZoneFinderTest : public ::testing::Test {
// A straightforward pair of textual RR(set) and a RRsetPtr variable
@@ -92,6 +105,7 @@ protected:
ZoneFinder::FindResultFlags expected_flags =
ZoneFinder::RESULT_DEFAULT);
+public:
InMemoryZoneFinderTest() :
class_(RRClass::IN()),
origin_("example.org"),
@@ -105,7 +119,6 @@ protected:
// Note that this contains an out-of-zone RR, and due to the
// validation check of masterLoad() used below, we cannot add SOA.
const RRsetData zone_data[] = {
- {"example.org. 300 IN SOA . . 0 0 0 0 100", &rr_soa_},
{"example.org. 300 IN NS ns.example.org.", &rr_ns_},
{"example.org. 300 IN A 192.0.2.1", &rr_a_},
{"ns.example.org. 300 IN A 192.0.2.2", &rr_ns_a_},
@@ -172,18 +185,7 @@ protected:
};
for (unsigned int i = 0; zone_data[i].text != NULL; ++i) {
- if (zone_data[i].rrset == &rr_soa_) {
- // This is zone's SOA. We need to specify the origin for
- // textToRRset; otherwise it would throw.
- *zone_data[i].rrset = textToRRset(zone_data[i].text, class_,
- origin_);
- } else {
- // For other data, we should rather omit the origin (the root
- // name will be used by default); there's some out-of-zone
- // name, which would trigger an exception if we specified
- // origin_.
- *zone_data[i].rrset = textToRRset(zone_data[i].text);
- }
+ *zone_data[i].rrset = textToRRset(zone_data[i].text);
}
}
@@ -198,24 +200,6 @@ protected:
updater_.add(rrset, rrset->getRRsig());
}
- /// \brief expensive rrset converter
- ///
- /// converts any specialized rrset (which may not have implemented some
- /// methods for efficiency) into a 'full' RRsetPtr, for easy use in test
- /// checks.
- ///
- /// Done very inefficiently through text representation, speed should not
- /// be a concern here.
- ConstRRsetPtr
- convertRRset(ConstRRsetPtr src) {
- // If the type is SOA, textToRRset performs a stricter check, so we
- // should specify the origin. For now we don't use out-of-zone
- // owner names (e.g. for pathological cases) with this method, so it
- // works for all test data. If future changes break this assumption
- // we should adjust it.
- return (textToRRset(src->toText(), class_, origin_));
- }
-
// Some data to test with
const RRClass class_;
const Name origin_;
@@ -234,8 +218,6 @@ protected:
RRsetPtr
// Out of zone RRset
rr_out_,
- // SOA of example.org
- rr_soa_,
// NS of example.org
rr_ns_,
// A of ns.example.org
@@ -311,110 +293,75 @@ protected:
if (zone_finder == NULL) {
zone_finder = &zone_finder_;
}
+ const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
+ RRsetPtr(); // note we use the same type as of retval of getRRsig()
// The whole block is inside, because we need to check the result and
// we can't assign to FindResult
EXPECT_NO_THROW({
ZoneFinderContextPtr find_result(zone_finder->find(
name, rrtype, options));
- findTestCommon(name, result, find_result, check_answer,
- answer, expected_flags, options,
- check_wild_answer);
- });
- }
-
- void findAtOriginTest(const RRType& rrtype,
- ZoneFinder::Result result,
- bool check_answer = true,
- const ConstRRsetPtr& answer = ConstRRsetPtr(),
- ZoneFinder::FindResultFlags expected_flags =
- ZoneFinder::RESULT_DEFAULT,
- memory::InMemoryZoneFinder* zone_finder = NULL,
- ZoneFinder::FindOptions options =
- ZoneFinder::FIND_DEFAULT,
- bool use_minttl = false)
- {
- SCOPED_TRACE("findAtOriginTest for " + rrtype.toText());
-
- if (zone_finder == NULL) {
- zone_finder = &zone_finder_;
- }
- ZoneFinderContextPtr find_result(zone_finder->findAtOrigin(
- rrtype, use_minttl, options));
- findTestCommon(origin_, result, find_result, check_answer, answer,
- expected_flags, options, false);
- }
-
-private:
- void findTestCommon(const Name& name, ZoneFinder::Result result,
- ZoneFinderContextPtr find_result,
- bool check_answer,
- const ConstRRsetPtr& answer,
- ZoneFinder::FindResultFlags expected_flags,
- ZoneFinder::FindOptions options,
- bool check_wild_answer)
- {
- const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
- RRsetPtr(); // note we use the same type as of retval of getRRsig()
-
- // Check it returns correct answers
- EXPECT_EQ(result, find_result->code);
- EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
- find_result->isWildcard());
- EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0,
- find_result->isNSECSigned());
- EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0,
- find_result->isNSEC3Signed());
- if (check_answer) {
- if (!answer) {
- ASSERT_FALSE(find_result->rrset);
- } else {
- ASSERT_TRUE(find_result->rrset);
- ConstRRsetPtr result_rrset(convertRRset(find_result->rrset));
- rrsetCheck(answer, result_rrset);
- if (answer_sig && (options & ZoneFinder::FIND_DNSSEC) != 0) {
- ASSERT_TRUE(result_rrset->getRRsig());
- rrsetCheck(answer_sig, result_rrset->getRRsig());
- } else {
- EXPECT_FALSE(result_rrset->getRRsig());
+ // Check it returns correct answers
+ EXPECT_EQ(result, find_result->code);
+ EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
+ find_result->isWildcard());
+ EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
+ != 0, find_result->isNSECSigned());
+ EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
+ != 0, find_result->isNSEC3Signed());
+ if (check_answer) {
+ if (!answer) {
+ ASSERT_FALSE(find_result->rrset);
+ } else {
+ ASSERT_TRUE(find_result->rrset);
+ ConstRRsetPtr result_rrset(
+ convertRRset(find_result->rrset));
+ rrsetCheck(answer, result_rrset);
+ if (answer_sig &&
+ (options & ZoneFinder::FIND_DNSSEC) != 0) {
+ ASSERT_TRUE(result_rrset->getRRsig());
+ rrsetCheck(answer_sig, result_rrset->getRRsig());
+ } else {
+ EXPECT_FALSE(result_rrset->getRRsig());
+ }
+ }
+ } else if (check_wild_answer) {
+ ASSERT_NE(ConstRRsetPtr(), answer) <<
+ "Wrong test, don't check for wild names if you expect "
+ "empty answer";
+ ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
+ "No answer found";
+ // Build the expected answer using the given name and
+ // other parameter of the base wildcard RRset.
+ RRsetPtr wildanswer(new RRset(name, answer->getClass(),
+ answer->getType(),
+ answer->getTTL()));
+ RdataIteratorPtr expectedIt(answer->getRdataIterator());
+ for (; !expectedIt->isLast(); expectedIt->next()) {
+ wildanswer->addRdata(expectedIt->getCurrent());
+ }
+
+ ConstRRsetPtr result_rrset(
+ convertRRset(find_result->rrset));
+ rrsetCheck(wildanswer, result_rrset);
+
+ // Same for the RRSIG, if any.
+ if (answer_sig) {
+ ASSERT_TRUE(result_rrset->getRRsig());
+
+ RRsetPtr wildsig(new RRset(name,
+ answer_sig->getClass(),
+ RRType::RRSIG(),
+ answer_sig->getTTL()));
+ RdataIteratorPtr expectedIt(
+ answer_sig->getRdataIterator());
+ for (; !expectedIt->isLast(); expectedIt->next()) {
+ wildsig->addRdata(expectedIt->getCurrent());
+ }
+ rrsetCheck(wildsig, result_rrset->getRRsig());
+ }
}
- }
- } else if (check_wild_answer) {
- ASSERT_NE(ConstRRsetPtr(), answer) <<
- "Wrong test, don't check for wild names if you expect "
- "empty answer";
- ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
- "No answer found";
- // Build the expected answer using the given name and
- // other parameter of the base wildcard RRset.
- RRsetPtr wildanswer(new RRset(name, answer->getClass(),
- answer->getType(),
- answer->getTTL()));
- RdataIteratorPtr expectedIt(answer->getRdataIterator());
- for (; !expectedIt->isLast(); expectedIt->next()) {
- wildanswer->addRdata(expectedIt->getCurrent());
- }
-
- ConstRRsetPtr result_rrset(convertRRset(find_result->rrset));
- rrsetCheck(wildanswer, result_rrset);
-
- // Same for the RRSIG, if any.
- if (answer_sig) {
- ASSERT_TRUE(result_rrset->getRRsig());
-
- RRsetPtr wildsig(new RRset(name, answer_sig->getClass(),
- RRType::RRSIG(),
- answer_sig->getTTL()));
- RdataIteratorPtr expectedIt(
- answer_sig->getRdataIterator());
- for (; !expectedIt->isLast(); expectedIt->next()) {
- wildsig->addRdata(expectedIt->getCurrent());
- }
- rrsetCheck(wildsig, result_rrset->getRRsig());
- }
- }
+ });
}
-
-protected:
/**
* \brief Calls the findAll on the finder and checks the result.
*/
@@ -636,6 +583,7 @@ TEST_F(InMemoryZoneFinderTest, glue) {
findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
true, rr_child_ns_);
+
// If we do it in the "glue OK" mode, we should find the exact match.
findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
@@ -671,101 +619,6 @@ TEST_F(InMemoryZoneFinderTest, glue) {
NULL, ZoneFinder::FIND_GLUE_OK);
}
-TEST_F(InMemoryZoneFinderTest, findAtOrigin) {
- // Add origin NS.
- rr_ns_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
- "NS 5 3 3600 20120814220826 20120715220826 "
- "1234 example.org. FAKE"));
- addToZoneData(rr_ns_);
-
- // Specified type of RR exists, no DNSSEC
- findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
-
- // Specified type of RR exists, with DNSSEC
- findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_,
- ZoneFinder::RESULT_DEFAULT, NULL,
- ZoneFinder::FIND_DNSSEC);
-
- // Specified type of RR doesn't exist, no DNSSEC
- findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET);
-
- // Specified type of RR doesn't exist, with DNSSEC. First, make the
- // zone "NSEC-signed", then check.
- rr_nsec_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
- "NSEC 5 3 3600 20120814220826 "
- "20120715220826 1234 example.org. FAKE"));
- addToZoneData(rr_nsec_);
- findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, rr_nsec_,
- ZoneFinder::RESULT_NSEC_SIGNED, NULL,
- ZoneFinder::FIND_DNSSEC);
-
- // Specified type of RR doesn't exist, with DNSSEC, enabling NSEC3. First,
- // make the zone "NSEC3-signed" (by just installing NSEC3PARAM; we don't
- // need to add NSEC3s for the purpose of this test), then check.
- addToZoneData(textToRRset("example.org. 300 IN NSEC3PARAM "
- "1 0 12 aabbccdd"));
- findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
- ZoneFinder::RESULT_NSEC3_SIGNED, NULL,
- ZoneFinder::FIND_DNSSEC);
-}
-
-TEST_F(InMemoryZoneFinderTest, findAtOriginWithMinTTL) {
- // Install zone's SOA. This also sets internal zone data min TTL field.
- addToZoneData(rr_soa_);
-
- // Specify the use of min TTL, then the resulting TTL should be derived
- // from the SOA MINTTL (which is smaller).
- findAtOriginTest(RRType::SOA(), ZoneFinder::SUCCESS, true,
- textToRRset("example.org. 100 IN SOA . . 0 0 0 0 100",
- class_, origin_),
- ZoneFinder::RESULT_DEFAULT, NULL,
- ZoneFinder::FIND_DEFAULT, true);
-
- // Add signed NS for the following test.
- RRsetPtr ns_rrset(textToRRset("example.org. 300 IN NS ns.example.org."));
- ns_rrset->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
- "NS 5 3 3600 20120814220826 20120715220826 "
- "1234 example.org. FAKE"));
- addToZoneData(ns_rrset);
-
- // If DNSSEC is requested, TTL of the RRSIG should also be the min.
- ns_rrset->setTTL(RRTTL(100)); // reset TTL to the expected one
- findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, ns_rrset,
- ZoneFinder::RESULT_DEFAULT, NULL,
- ZoneFinder::FIND_DEFAULT, true);
-
- // If we don't request the use of min TTL, the original TTL will be used.
- findAtOriginTest(RRType::SOA(), ZoneFinder::SUCCESS, true, rr_soa_,
- ZoneFinder::RESULT_DEFAULT, NULL,
- ZoneFinder::FIND_DEFAULT, false);
-
- // If the found RRset has a smaller TTL than SOA, the original TTL should
- // win.
- rr_a_->setTTL(RRTTL(10));
- addToZoneData(rr_a_);
- findAtOriginTest(RRType::A(), ZoneFinder::SUCCESS, true, rr_a_,
- ZoneFinder::RESULT_DEFAULT, NULL,
- ZoneFinder::FIND_DEFAULT, true);
-
- // If no RRset is returned, use_minttl doesn't matter (it shouldn't cause
- // disruption)
- findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
- ZoneFinder::RESULT_DEFAULT, NULL,
- ZoneFinder::FIND_DEFAULT, true);
-
- // If it results in NXRRSET with NSEC, and if we specify the use of min
- // TTL, the NSEC and RRSIG should have the min TTL (again, though, this
- // use case is not really the intended one)
- rr_nsec_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
- "NSEC 5 3 3600 20120814220826 "
- "20120715220826 1234 example.org. FAKE"));
- addToZoneData(rr_nsec_);
- rr_nsec_->setTTL(RRTTL(100)); // reset it to the expected one
- findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, rr_nsec_,
- ZoneFinder::RESULT_NSEC_SIGNED, NULL,
- ZoneFinder::FIND_DNSSEC, true);
-}
-
/**
* \brief Test searching.
*
diff --git a/src/lib/datasrc/tests/zone_loader_unittest.cc b/src/lib/datasrc/tests/zone_loader_unittest.cc
index 4b42185..0f44074 100644
--- a/src/lib/datasrc/tests/zone_loader_unittest.cc
+++ b/src/lib/datasrc/tests/zone_loader_unittest.cc
@@ -14,7 +14,6 @@
#include <datasrc/zone_loader.h>
#include <datasrc/data_source.h>
-#include <datasrc/rrset_collection_base.h>
#include <datasrc/memory/zone_table_segment.h>
#include <datasrc/memory/memory_client.h>
@@ -164,16 +163,24 @@ public:
RRClass rrclass_;
};
-// Test implementation of RRsetCollectionBase. This is currently just a
-// wrapper around \c isc::datasrc::RRsetCollectionBase;
-// \c isc::datasrc::RRsetCollectionBase may become an abstract class in
-// the future.
+// Test implementation of RRsetCollectionBase.
class TestRRsetCollection : public isc::datasrc::RRsetCollectionBase {
public:
TestRRsetCollection(ZoneUpdater& updater,
const isc::dns::RRClass& rrclass) :
isc::datasrc::RRsetCollectionBase(updater, rrclass)
{}
+
+ virtual ~TestRRsetCollection() {}
+
+protected:
+ virtual RRsetCollectionBase::IterPtr getBeginning() {
+ isc_throw(isc::NotImplemented, "This method is not implemented.");
+ }
+
+ virtual RRsetCollectionBase::IterPtr getEnd() {
+ isc_throw(isc::NotImplemented, "This method is not implemented.");
+ }
};
// The updater isn't really correct according to the API. For example,
@@ -190,7 +197,7 @@ public:
virtual ZoneFinder& getFinder() {
return (finder_);
}
- virtual isc::dns::RRsetCollectionBase& getRRsetCollection() {
+ virtual isc::datasrc::RRsetCollectionBase& getRRsetCollection() {
if (!rrset_collection_) {
rrset_collection_.reset(new TestRRsetCollection(*this,
client_->rrclass_));
diff --git a/src/lib/datasrc/zone.h b/src/lib/datasrc/zone.h
index ca73bb5..a75f4a0 100644
--- a/src/lib/datasrc/zone.h
+++ b/src/lib/datasrc/zone.h
@@ -18,10 +18,10 @@
#include <dns/name.h>
#include <dns/rrset.h>
#include <dns/rrtype.h>
-#include <dns/rrset_collection_base.h>
#include <datasrc/exceptions.h>
#include <datasrc/result.h>
+#include <datasrc/rrset_collection_base.h>
#include <utility>
@@ -29,6 +29,8 @@ namespace isc {
namespace datasrc {
/// \brief A forward declaration
+class RRsetCollectionBase;
+
class ZoneFinder;
/// The base class to make updates to a single zone.
@@ -96,7 +98,7 @@ public:
/// Return an RRsetCollection for the updater.
///
/// This method returns an \c RRsetCollection for the updater,
- /// implementing the \c isc::dns::RRsetCollectionBase
+ /// implementing the \c isc::datasrc::RRsetCollectionBase
/// interface. Typically, the returned \c RRsetCollection is a
/// singleton for its \c ZoneUpdater. The returned RRsetCollection
/// object must not be used after its corresponding \c ZoneUpdater
@@ -106,51 +108,15 @@ public:
/// \c ZoneUpdater implementation.
///
/// The behavior of the RRsetCollection is similar to the behavior
- /// of the \c Zonefinder returned by \c getFinder(). In fact, it's
- /// redundant in a sense because one can implement the
- /// \c dns::RRsetCollectionBase interface using an updater and
- /// \c getFinder() interface (unless it's expected to support zone
- /// iteration, and the initial implementation of the \c RRsetCollection
- /// returned by this method doesn't support it). We still provide it
- /// as an updater's method so it will be easier for an updater
- /// implementation to customize the \c RRsetCollection implementation,
- /// and also for making it easy to impose restrictions described below.
- ///
- /// Specific data sources may have special restrictions. That's
- /// especially the case for database-based data sources. Such
- /// restrictions may also result in limiting the usage of the
- /// \c RRsetCollection as described in the following paragraphs. A
- /// specific updater implementation may provide more flexible
- /// behavior, but applications using this interface must assume
- /// the most restricted case unless it knows it uses a particular
- /// specialized updater implementation that loosens specific restrictions.
- ///
- /// To summarize the restrictions:
- /// - An application must not add or delete RRsets after
- /// \c getRRsetCollection() is called.
- /// - An application must not use the returned collection from
- /// \c getRRsetCollection() once \c commit() is called on the updater
- /// that generates the collection.
- ///
+ /// of the \c Zonefinder returned by \c getFinder().
/// Implementations of \c ZoneUpdater may not allow adding or
- /// deleting RRsets after \c getRRsetCollection() is called. This is
- /// because if an iterator of the collection is being used at that time
- /// the modification to the zone may break an internal assumption of the
- /// iterator and may result in unexpected behavior. Also, the iterator
- /// may conceptually hold a "reader lock" of the zone (in an implementation
- /// dependent manner), which would prevent the addition or deletion,
- /// surprising the caller (who would normally expect it to succeed).
- ///
- /// Implementations of \c ZoneUpdater may disable a previously returned
- /// \c RRsetCollection after \c commit() is called. This is because
- /// the returned \c RRsetCollection may internally rely on the conceptual
- /// transaction of the updater that generates the collection (which would
- /// be literally the case for database-based data sources), and once
- /// the transaction is committed anything that relies on it won't be valid.
- /// If an \c RRsetCollection is disabled, using methods such as \c find()
- /// and using its iterator would cause an exception to be thrown. See
- /// \c isc::datasrc::RRsetCollectionBase for details.
- virtual isc::dns::RRsetCollectionBase& getRRsetCollection() = 0;
+ /// deleting RRsets after \c getRRsetCollection() is called.
+ /// Implementations of \c ZoneUpdater may disable a previously
+ /// returned \c RRsetCollection after \c commit() is called. If an
+ /// \c RRsetCollection is disabled, using methods such as \c find()
+ /// and using its iterator would cause an exception to be
+ /// thrown. See \c isc::datasrc::RRsetCollectionBase for details.
+ virtual isc::datasrc::RRsetCollectionBase& getRRsetCollection() = 0;
/// Add an RRset to a zone via the updater
///
@@ -200,9 +166,8 @@ public:
/// \c DataSourceError exception.
///
/// Implementations of \c ZoneUpdater may not allow adding or
- /// deleting RRsets after \c getRRsetCollection() is called (see
- /// the description of \c getRRsetCollection()). In this case,
- /// implementations throw an \c InvalidOperation exception.
+ /// deleting RRsets after \c getRRsetCollection() is called. In this
+ /// case, implementations throw an \c InvalidOperation exception.
///
/// If journaling was requested when getting this updater, it will reject
/// to add the RRset if the squence doesn't look like and IXFR (see
@@ -276,9 +241,8 @@ public:
/// \c DataSourceError exception.
///
/// Implementations of \c ZoneUpdater may not allow adding or
- /// deleting RRsets after \c getRRsetCollection() is called (see
- /// the description of \c getRRsetCollection()). In this case,
- /// implementations throw an \c InvalidOperation exception.
+ /// deleting RRsets after \c getRRsetCollection() is called. In this
+ /// case, implementations throw an \c InvalidOperation exception.
///
/// If journaling was requested when getting this updater, it will reject
/// to add the RRset if the squence doesn't look like and IXFR (see
diff --git a/src/lib/datasrc/zone_finder.h b/src/lib/datasrc/zone_finder.h
index 83851f6..6e1cee0 100644
--- a/src/lib/datasrc/zone_finder.h
+++ b/src/lib/datasrc/zone_finder.h
@@ -21,6 +21,7 @@
#include <datasrc/exceptions.h>
#include <datasrc/result.h>
+#include <datasrc/rrset_collection_base.h>
#include <utility>
#include <vector>
diff --git a/src/lib/datasrc/zone_loader.cc b/src/lib/datasrc/zone_loader.cc
index d0f4a64..2c57b4f 100644
--- a/src/lib/datasrc/zone_loader.cc
+++ b/src/lib/datasrc/zone_loader.cc
@@ -20,12 +20,12 @@
#include <datasrc/zone_iterator.h>
#include <datasrc/zone.h>
#include <datasrc/logger.h>
+#include <datasrc/rrset_collection_base.h>
#include <dns/rrset.h>
#include <dns/zone_checker.h>
#include <dns/name.h>
#include <dns/rrclass.h>
-#include <dns/rrset_collection_base.h>
#include <boost/bind.hpp>
@@ -33,7 +33,6 @@
using isc::dns::Name;
using isc::dns::ConstRRsetPtr;
-using isc::dns::RRsetCollectionBase;
using isc::dns::MasterLoader;
using isc::dns::MasterLexer;
diff --git a/src/lib/dns/python/rrset_collection_python_inc.cc b/src/lib/dns/python/rrset_collection_python_inc.cc
index baf8ec8..f6eb8a3 100644
--- a/src/lib/dns/python/rrset_collection_python_inc.cc
+++ b/src/lib/dns/python/rrset_collection_python_inc.cc
@@ -36,41 +36,6 @@ Returns the RRset in the collection that exactly matches the given\n\
name, rrclass and rrtype. If no matching RRset is found, None is\n\
returned.\n\
\n\
-This method's implementations currently are not specified to handle\n\
-RRTypes such as RRSIG and NSEC3. This interface may be refined to\n\
-clarify this point in the future, and perhaps, provide additional API\n\
-for these RRType.\n\
-\n\
-As for RRSIG, there are some fundamental open questions. For example,\n\
-it's not clear whether we want to return all RRSIGs of the given name\n\
-covering any RR types (in which case, we need to figure out how), or\n\
-we need to extend the interface so we can specify the covered type. A\n\
-specific derived implementation may return something if type RRSIG is\n\
-specified, but this is not specified here at the base class level. So,\n\
-for RRSIGs the behavior should be assumed as undefined.\n\
-\n\
-As for NSEC3, it's not clear whether owner names (which included\n\
-hashed labels) are the best choice of search key, because in many\n\
-cases, what the application wants to find is an NSEC3 that has the\n\
-hash of some particular \"normal\" domain names. Also, if the\n\
-underlying implementation encapsulates a single zone, NSEC3 records\n\
-conceptually belong to a separate name space, which may cause\n\
-implementation difficulty.\n\
-\n\
-Behavior with meta types such as ANY and AXFR are also undefined. A\n\
-specific implementation may return something for these. But, unlike\n\
-the case of RRSIGs, these types of RRsets are not expected to be added\n\
-to any implementation of collection in the first place (by the\n\
-definition of \"meta types\"), so querying for such types is\n\
-basically an invalid operation. The API doesn't require\n\
-implementations to check this condition and reject it, so the behavior\n\
-is undefined. This interface will not be refined in future versions\n\
-for these meta types.\n\
-\n\
-Exceptions:\n\
- RRsetCollectionError if find() results in some implementation-\n\
- specific error.\n\
-\n\
Parameters:\n\
name (isc.dns.Name) The name of the RRset to search for.\n\
rrtype (isc.dns.RRType) The type of the RRset to search for.\n\
@@ -156,7 +121,7 @@ find(name, rrclass, rrtype) -> isc.dns.RRset\n\
Find a matching RRset in the collection.\n\
\n\
Returns the RRset in the collection that exactly matches the given\n\
-name, rrclass and rrtype. If no matching RRset is found, None is\n\
+name, rrclass and rrtype. If no matching RRset is found, NULL is\n\
returned.\n\
\n\
Parameters:\n\
@@ -164,7 +129,7 @@ Parameters:\n\
rrclass The class of the RRset to search for.\n\
rrtype The type of the RRset to search for.\n\
\n\
-Return Value(s): The RRset if found, None otherwise.\n\
+Return Value(s): The RRset if found, NULL otherwise.\n\
";
// Modifications
diff --git a/src/lib/dns/rrset_collection_base.h b/src/lib/dns/rrset_collection_base.h
index f7c9b6b..7ccf7b5 100644
--- a/src/lib/dns/rrset_collection_base.h
+++ b/src/lib/dns/rrset_collection_base.h
@@ -27,7 +27,7 @@ namespace dns {
/// \brief Error during RRsetCollectionBase find() operation
///
-/// This exception is thrown when calling an implementation of
+/// This exception is thrown when an calling implementation of
/// \c RRsetCollectionBase::find() results in an error which is not due
/// to unmatched data, but because of some other underlying error
/// condition.
@@ -58,37 +58,13 @@ public:
/// is found, \c NULL is returned.
///
/// This method's implementations currently are not specified to
- /// handle \c RRTypes such as RRSIG and NSEC3. This interface may be
- /// refined to clarify this point in the future, and perhaps, provide
- /// additional API for these RRType.
+ /// handle \c RRTypes such as RRSIG and NSEC3. RRSIGs are attached
+ /// to their corresponding \c RRset and it is not straightforward to
+ /// search for them. Searching for RRSIGs will return \c false
+ /// always. Support for RRSIGs may be added in the future.
///
- /// As for RRSIG, there are some fundamental open questions. For
- /// example, it's not clear whether we want to return all RRSIGs of
- /// the given name covering any RR types (in which case, we need to
- /// figure out how), or we need to extend the interface so we can
- /// specify the covered type. A specific derived implementation may
- /// return something if type RRSIG is specified, but this is not
- /// specified here at the base class level. So, for RRSIGs the
- /// behavior should be assumed as undefined.
- ///
- /// As for NSEC3, it's not clear whether owner names (which included
- /// hashed labels) are the best choice of search key, because in many
- /// cases, what the application wants to find is an NSEC3 that has the
- /// hash of some particular "normal" domain names. Also, if the underlying
- /// implementation encapsulates a single zone, NSEC3 records conceptually
- /// belong to a separate name space, which may cause implementation
- /// difficulty.
- ///
- /// Behavior with meta types such as ANY and AXFR are also
- /// undefined. A specific implementation may return something for
- /// these. But, unlike the case of RRSIGs, these types of RRsets
- /// are not expected to be added to any implementation of
- /// collection in the first place (by the definition of "meta
- /// types"), so querying for such types is basically an invalid
- /// operation. The API doesn't require implementations to check
- /// this condition and reject it, so the behavior is
- /// undefined. This interface will not be refined in future
- /// versions for these meta types.
+ /// Non-concrete types such as ANY and AXFR are unsupported and will
+ /// return \c false always.
///
/// \throw RRsetCollectionError if find() results in some
/// implementation-specific error.
diff --git a/src/lib/python/isc/cc/Makefile.am b/src/lib/python/isc/cc/Makefile.am
index ba6fe50..b0ba3b2 100644
--- a/src/lib/python/isc/cc/Makefile.am
+++ b/src/lib/python/isc/cc/Makefile.am
@@ -1,19 +1,6 @@
SUBDIRS = . tests
-python_PYTHON = __init__.py data.py session.py message.py logger.py
-BUILT_SOURCES = $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.py
-nodist_pylogmessage_PYTHON = $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.py
-pylogmessagedir = $(pyexecdir)/isc/log_messages/
-
-CLEANFILES = $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.py
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.pyc
-
-EXTRA_DIST = pycc_messages.mes
-
-# Define rule to build logging source files from message file
-$(PYTHON_LOGMSGPKG_DIR)/work/pycc_messages.py: pycc_messages.mes
- $(top_builddir)/src/lib/log/compiler/message \
- -d $(PYTHON_LOGMSGPKG_DIR)/work -p $(srcdir)/pycc_messages.mes
+python_PYTHON = __init__.py data.py session.py message.py
pythondir = $(pyexecdir)/isc/cc
diff --git a/src/lib/python/isc/cc/logger.py b/src/lib/python/isc/cc/logger.py
deleted file mode 100644
index 5fd440f..0000000
--- a/src/lib/python/isc/cc/logger.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2013 Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-""" This is a logging utility module for other modules of the cc library
-package.
-
-"""
-
-import isc.log
-
-# C++ version of the CC module uses 'cc'; using the same name does not
-# necessarily cause disruption, but we use a different name to minimize
-# possible confusion.
-logger = isc.log.Logger('pycc')
diff --git a/src/lib/python/isc/cc/pycc_messages.mes b/src/lib/python/isc/cc/pycc_messages.mes
deleted file mode 100644
index 997b899..0000000
--- a/src/lib/python/isc/cc/pycc_messages.mes
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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.
-
-# No namespace declaration - these constants go in the global namespace
-# of the libddns_messages python module.
-
-% PYCC_LNAME_RECEIVED received local name: %1
-Debug message: the local module received its unique identifier (name)
-from msgq on completion of establishing the session with msgq.
diff --git a/src/lib/python/isc/cc/session.py b/src/lib/python/isc/cc/session.py
index caac553..b6060ee 100644
--- a/src/lib/python/isc/cc/session.py
+++ b/src/lib/python/isc/cc/session.py
@@ -22,9 +22,6 @@ import threading
import bind10_config
import isc.cc.message
-import isc.log
-from isc.cc.logger import logger
-from isc.log_messages.pycc_messages import *
class ProtocolError(Exception): pass
class NetworkError(Exception): pass
@@ -33,7 +30,7 @@ class SessionTimeout(Exception): pass
class Session:
MSGQ_DEFAULT_TIMEOUT = 4000
-
+
def __init__(self, socket_file=None):
self._socket = None
self._lname = None
@@ -63,8 +60,6 @@ class Session:
self._lname = msg["lname"]
if not self._lname:
raise ProtocolError("Could not get local name")
- logger.debug(logger.DBGLVL_TRACE_BASIC, PYCC_LNAME_RECEIVED,
- self._lname)
except socket.error as se:
raise SessionError(se)
@@ -164,7 +159,7 @@ class Session:
if len(data) == 0: # server closed connection
raise ProtocolError("Read of 0 bytes: connection closed")
return data
-
+
def _receive_len_data(self):
"""Reads self._recv_len_size bytes of data from the socket into
self._recv_len_data
@@ -208,7 +203,7 @@ class Session:
# they may never both be non-zero (we are either starting
# a full read, or continuing one of the reads
assert self._recv_size == 0 or self._recv_len_size == 0
-
+
if self._recv_size == 0:
if self._recv_len_size == 0:
# both zero, start a new full read
@@ -261,7 +256,8 @@ class Session:
"instance": instance,
})
- def group_sendmsg(self, msg, group, instance = "*", to = "*"):
+ def group_sendmsg(self, msg, group, instance = "*", to = "*",
+ want_answer=False):
seq = self._next_sequence()
self.sendmsg({
"type": "send",
@@ -270,6 +266,7 @@ class Session:
"group": group,
"instance": instance,
"seq": seq,
+ "want_answer": want_answer
}, isc.cc.message.to_wire(msg))
return seq
diff --git a/src/lib/python/isc/cc/tests/session_test.py b/src/lib/python/isc/cc/tests/session_test.py
index e8656e7..05caf0a 100644
--- a/src/lib/python/isc/cc/tests/session_test.py
+++ b/src/lib/python/isc/cc/tests/session_test.py
@@ -381,18 +381,42 @@ class testSession(unittest.TestCase):
sent = sess._socket.readsentmsg_parsed()
self.assertEqual(sent, ({"from": "test_name", "seq": 2, "to": "*",
"instance": "*", "group": "my_group",
- "type": "send"}, {"hello": "a"}))
+ "type": "send", "want_answer": False},
+ {"hello": "a"}))
self.assertEqual(sess._sequence, 2)
sess.group_sendmsg({ 'hello': 'a' }, "my_group", "my_instance")
sent = sess._socket.readsentmsg_parsed()
- self.assertEqual(sent, ({"from": "test_name", "seq": 3, "to": "*", "instance": "my_instance", "group": "my_group", "type": "send"}, {"hello": "a"}))
+ self.assertEqual(sent, ({"from": "test_name", "seq": 3, "to": "*",
+ "instance": "my_instance",
+ "group": "my_group", "type": "send",
+ "want_answer": False},
+ {"hello": "a"}))
self.assertEqual(sess._sequence, 3)
sess.group_sendmsg({ 'hello': 'a' }, "your_group", "your_instance")
sent = sess._socket.readsentmsg_parsed()
- self.assertEqual(sent, ({"from": "test_name", "seq": 4, "to": "*", "instance": "your_instance", "group": "your_group", "type": "send"}, {"hello": "a"}))
+ self.assertEqual(sent, ({"from": "test_name", "seq": 4, "to": "*",
+ "instance": "your_instance",
+ "group": "your_group", "type": "send",
+ "want_answer": False},
+ {"hello": "a"}))
self.assertEqual(sess._sequence, 4)
+ # Test the optional want_answer parameter
+ sess.group_sendmsg({'hello': 'a'}, "group", want_answer=True)
+ sent = sess._socket.readsentmsg_parsed()
+ self.assertEqual(sent, ({"from": "test_name", "seq": 5, "to": "*",
+ "instance": "*", "group": "group", "type":
+ "send", "want_answer": True},
+ {"hello": "a"}))
+ self.assertEqual(sess._sequence, 5)
+ sess.group_sendmsg({'hello': 'a'}, "group", want_answer=False)
+ sent = sess._socket.readsentmsg_parsed()
+ self.assertEqual(sent, ({"from": "test_name", "seq": 6, "to": "*",
+ "instance": "*", "group": "group", "type":
+ "send", "want_answer": False},
+ {"hello": "a"}))
+ self.assertEqual(sess._sequence, 6)
def test_group_recvmsg(self):
# must this one do anything except not return messages with
diff --git a/src/lib/python/isc/config/cfgmgr.py b/src/lib/python/isc/config/cfgmgr.py
index cb7f1ea..9563cab 100644
--- a/src/lib/python/isc/config/cfgmgr.py
+++ b/src/lib/python/isc/config/cfgmgr.py
@@ -551,7 +551,7 @@ class ConfigManager:
def run(self):
"""Runs the configuration manager."""
self.running = True
- while self.running:
+ while (self.running):
# we just wait eternally for any command here, so disable
# timeouts for this specific recv
self.cc.set_timeout(0)
@@ -566,4 +566,3 @@ class ConfigManager:
# Only respond if there actually is something to respond with
if answer is not None:
self.cc.group_reply(env, answer)
- logger.info(CFGMGR_STOPPED_BY_COMMAND)
diff --git a/src/lib/python/isc/config/cfgmgr_messages.mes b/src/lib/python/isc/config/cfgmgr_messages.mes
index 37ba889..8701db3 100644
--- a/src/lib/python/isc/config/cfgmgr_messages.mes
+++ b/src/lib/python/isc/config/cfgmgr_messages.mes
@@ -61,9 +61,6 @@ error is given. The most likely cause is that the system does not have
write access to the configuration database file. The updated
configuration is not stored.
-% CFGMGR_STOPPED_BY_COMMAND received shutdown command, shutting down
-The configuration manager received a shutdown command, and is exiting.
-
% CFGMGR_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
There was a keyboard interrupt signal to stop the cfgmgr daemon. The
daemon will now shut down.
diff --git a/src/lib/python/isc/datasrc/updater_inc.cc b/src/lib/python/isc/datasrc/updater_inc.cc
index 87c8158..f040f85 100644
--- a/src/lib/python/isc/datasrc/updater_inc.cc
+++ b/src/lib/python/isc/datasrc/updater_inc.cc
@@ -187,9 +187,10 @@ Exceptions:\n\
\n\
";
-// Modifications:
-// - remove reference to isc.datasrc.RRsetCollectionBase (hidden for Python
-// wrapper)
+// Modifications
+// - isc.datasrc.RRsetCollectionBase => isc.dns.RRsetCollectionBase
+// (in the Python wrapper, the former is completely invisible)
+// - remove other reference to isc.datasrc.RRsetCollectionBase
const char* const ZoneUpdater_getRRsetCollection_doc = "\
get_rrset_collection() -> isc.dns.RRsetCollectionBase \n\
\n\
@@ -205,46 +206,10 @@ RRsetCollection returned has a behavior dependent on the ZoneUpdater\n\
implementation.\n\
\n\
The behavior of the RRsetCollection is similar to the behavior of the\n\
-Zonefinder returned by get_finder(). In fact, it's redundant in a\n\
-sense because one can implement the dns.RRsetCollectionBase interface\n\
-using an updater and get_finder() interface (unless it's expected to\n\
-support zone iteration, and the initial implementation of the\n\
-RRsetCollection returned by this method doesn't support it). We\n\
-still provide it as an updater's method so it will be easier for an\n\
-updater implementation to customize the RRsetCollection\n\
-implementation, and also for making it easy to impose restrictions\n\
-described below.\n\
-\n\
-Specific data sources may have special restrictions. That's especially\n\
-the case for database-based data sources. Such restrictions may also\n\
-result in limiting the usage of the RRsetCollection as described in\n\
-the following paragraphs. A specific updater implementation may\n\
-provide more flexible behavior, but applications using this interface\n\
-must assume the most restricted case unless it knows it uses a\n\
-particular specialized updater implementation that loosens specific\n\
-restrictions.\n\
-\n\
-- An application must not add or delete RRsets after\n\
- get_rrset_collection() is called.\n\
-- An application must not use the returned collection from\n\
- get_rrset_collection() once commit() is called on the updater that\n\
- generates the collection.\n\
-\n\
-Implementations of ZoneUpdater may not allow adding or deleting RRsets\n\
-after get_rrset_collection() is called. This is because if an\n\
-iterator of the collection is being used at that time the modification\n\
-to the zone may break an internal assumption of the iterator and may\n\
-result in unexpected behavior. Also, the iterator may conceptually\n\
-hold a \"reader lock\" of the zone (in an implementation dependent\n\
-manner), which would prevent the addition or deletion, surprising the\n\
-caller (who would normally expect it to succeed).\n\
-\n\
-Implementations of ZoneUpdater may disable a previously returned\n\
-RRsetCollection after commit() is called. This is because the returned\n\
-RRsetCollection may internally rely on the conceptual transaction of\n\
-the updater that generates the collection (which would be literally\n\
-the case for database-based data sources), and once the transaction is\n\
-committed anything that relies on it won't be valid. If an\n\
+Zonefinder returned by get_finder(). Implementations of ZoneUpdater\n\
+may not allow adding or deleting RRsets after get_rrset_collection()\n\
+is called. Implementations of ZoneUpdater may disable a previously\n\
+returned RRsetCollection after commit() is called. If an\n\
RRsetCollection is disabled, using methods such as find() and using\n\
its iterator would cause an exception to be thrown.\n\
\n\
diff --git a/src/lib/python/isc/log_messages/Makefile.am b/src/lib/python/isc/log_messages/Makefile.am
index 02523cd..97ff6e6 100644
--- a/src/lib/python/isc/log_messages/Makefile.am
+++ b/src/lib/python/isc/log_messages/Makefile.am
@@ -18,7 +18,6 @@ EXTRA_DIST += loadzone_messages.py
EXTRA_DIST += server_common_messages.py
EXTRA_DIST += dbutil_messages.py
EXTRA_DIST += msgq_messages.py
-EXTRA_DIST += pycc_messages.py
CLEANFILES = __init__.pyc
CLEANFILES += bind10_messages.pyc
@@ -38,7 +37,6 @@ CLEANFILES += loadzone_messages.pyc
CLEANFILES += server_common_messages.pyc
CLEANFILES += dbutil_messages.pyc
CLEANFILES += msgq_messages.pyc
-CLEANFILES += pycc_messages.pyc
CLEANDIRS = __pycache__
diff --git a/src/lib/python/isc/log_messages/pycc_messages.py b/src/lib/python/isc/log_messages/pycc_messages.py
deleted file mode 100644
index 77b3804..0000000
--- a/src/lib/python/isc/log_messages/pycc_messages.py
+++ /dev/null
@@ -1 +0,0 @@
-from work.pycc_messages import *
diff --git a/src/lib/python/isc/xfrin/diff.py b/src/lib/python/isc/xfrin/diff.py
index 8d0bb08..ea51967 100644
--- a/src/lib/python/isc/xfrin/diff.py
+++ b/src/lib/python/isc/xfrin/diff.py
@@ -584,16 +584,3 @@ class Diff:
if rr.get_name() == name:
new_rrsets.append(rr)
return result, new_rrsets, flags
-
- def get_rrset_collection(self):
- '''
- This first applies all changes to the data source. Then it creates
- and returns an RRsetCollection on top of the corresponding zone
- updater. Notice it might be impossible to apply more changes after
- that.
-
- This must not be called after a commit, or it'd throw ValueError.
- '''
- # Apply itself will check it is not yet commited.
- self.apply()
- return self.__updater.get_rrset_collection()
diff --git a/src/lib/python/isc/xfrin/tests/diff_tests.py b/src/lib/python/isc/xfrin/tests/diff_tests.py
index f013cd5..906406f 100644
--- a/src/lib/python/isc/xfrin/tests/diff_tests.py
+++ b/src/lib/python/isc/xfrin/tests/diff_tests.py
@@ -16,8 +16,7 @@
import isc.log
import unittest
from isc.datasrc import ZoneFinder
-from isc.dns import Name, RRset, RRClass, RRType, RRTTL, Rdata, \
- RRsetCollectionBase
+from isc.dns import Name, RRset, RRClass, RRType, RRTTL, Rdata
from isc.xfrin.diff import Diff, NoSuchZone
class TestError(Exception):
@@ -1088,52 +1087,6 @@ class DiffTest(unittest.TestCase):
self.__check_find_all_call(diff.find_all, self.__rrset3,
rcode)
- class Collection(isc.dns.RRsetCollectionBase):
- '''
- Our own mock RRsetCollection. We only pass it through, but we
- still define an (mostly empty) find method to satisfy the
- expectations.
- '''
- def __init__(self):
- '''
- Empty init. The base class's __init__ can't be called,
- so we need to provide our own to shadow it -- and make sure
- not to call the super().__init__().
- '''
- pass
-
- def find(self, name, rrclass, rrtype):
- '''
- Empty find method. Returns None to each query (pretends
- the collection is empty. Present mostly for completeness.
- '''
- return None
-
- def get_rrset_collection(self):
- '''
- Part of pretending to be the zone updater. This returns the rrset
- collection (a mock one, unuseable) for the updater.
- '''
- return self.Collection()
-
- def test_get_rrset_collection(self):
- '''
- Test the diff can return corresponding rrset collection. Test
- it applies the data first.
- '''
- diff = Diff(self, Name('example.org'), single_update_mode=True)
- diff.add_data(self.__rrset_soa)
- collection = diff.get_rrset_collection()
- # Check it is applied
- self.assertEqual(1, len(self.__data_operations))
- self.assertEqual('add', self.__data_operations[0][0])
- # Check the returned one is actually RRsetCollection
- self.assertTrue(isinstance(collection, self.Collection))
- # The collection is just the mock from above, so this doesn't do much
- # testing, but we check that the mock got through and didn't get hurt.
- self.assertIsNone(collection.find(Name('example.org'), RRClass.IN(),
- RRType.SOA()))
-
if __name__ == "__main__":
isc.log.init("bind10")
isc.log.resetUnitTestRootLogger()
diff --git a/src/lib/testutils/mockups.h b/src/lib/testutils/mockups.h
index fc8a2e0..8ba2287 100644
--- a/src/lib/testutils/mockups.h
+++ b/src/lib/testutils/mockups.h
@@ -48,7 +48,7 @@ public:
virtual void disconnect() {}
virtual int group_sendmsg(isc::data::ConstElementPtr msg, std::string group,
- std::string, std::string)
+ std::string, std::string, bool)
{
if (!send_ok_) {
isc_throw(isc::cc::SessionError,
diff --git a/tests/lettuce/configurations/xfrin/retransfer_master_nons.conf.orig b/tests/lettuce/configurations/xfrin/retransfer_master_nons.conf.orig
deleted file mode 100644
index 80cc3db..0000000
--- a/tests/lettuce/configurations/xfrin/retransfer_master_nons.conf.orig
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "version": 2,
- "Logging": {
- "loggers": [ {
- "debuglevel": 99,
- "severity": "DEBUG",
- "name": "*"
- } ]
- },
- "Auth": {
- "database_file": "data/example.org-nons.sqlite3",
- "listen_on": [ {
- "address": "::1",
- "port": 47807
- } ]
- },
- "data_sources": {
- "classes": {
- "IN": [{
- "type": "sqlite3",
- "params": {
- "database_file": "data/example.org-nons.sqlite3"
- }
- }]
- }
- },
- "Xfrout": {
- "zone_config": [ {
- "origin": "example.org"
- } ],
- "also_notify": [ {
- "address": "::1",
- "port": 47806
- } ]
- },
- "Stats": {
- "poll-interval": 1
- },
- "Boss": {
- "components": {
- "b10-auth": { "kind": "needed", "special": "auth" },
- "b10-xfrout": { "address": "Xfrout", "kind": "dispensable" },
- "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
- "b10-stats": { "address": "Stats", "kind": "dispensable" },
- "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
- }
- }
-}
diff --git a/tests/lettuce/data/example.org-nons.sqlite3 b/tests/lettuce/data/example.org-nons.sqlite3
deleted file mode 100644
index 40ddbf6..0000000
Binary files a/tests/lettuce/data/example.org-nons.sqlite3 and /dev/null differ
diff --git a/tests/lettuce/features/bindctl_commands.feature b/tests/lettuce/features/bindctl_commands.feature
index 57406c3..20a28fc 100644
--- a/tests/lettuce/features/bindctl_commands.feature
+++ b/tests/lettuce/features/bindctl_commands.feature
@@ -17,7 +17,7 @@ Feature: control with bindctl
And wait for bind10 stderr message XFRIN_STARTED
And wait for bind10 stderr message XFROUT_STARTED
And wait for bind10 stderr message STATS_STARTING
- And wait for bind10 stderr message STATSHTTPD_STARTED
+ And wait for bind10 stderr message STATHTTPD_STARTED
Then remove bind10 configuration Boss/components/NOSUCHMODULE
last bindctl output should contain Error
diff --git a/tests/lettuce/features/stats_httpd.feature b/tests/lettuce/features/stats_httpd.feature
deleted file mode 100644
index 50d5efa..0000000
--- a/tests/lettuce/features/stats_httpd.feature
+++ /dev/null
@@ -1,16 +0,0 @@
-Feature: b10-stats-httpd module
- Tests the stats httpd module
-
- Scenario: Check that the module logs and responds to requests
- Given I have bind10 running with configuration bindctl_commands.config
- And wait for bind10 stderr message STATSHTTPD_STARTED
-
- When I request the URL http://127.0.0.1:47811/
- # Should result in redirect, so two query logs
- And wait for new bind10 stderr message "GET / HTTP/1.0" 302 -
- And wait for new bind10 stderr message "GET /bind10/statistics/xml/ HTTP/1.0" 200 -
- The last http response status code should be 200
-
- When I request the URL http://127.0.0.1:47811/no_such_url
- And wait for new bind10 stderr message "GET /no_such_url HTTP/1.0" 404 -
- The last http response status code should be 404
diff --git a/tests/lettuce/features/terrain/http.py b/tests/lettuce/features/terrain/http.py
deleted file mode 100644
index f1f72f5..0000000
--- a/tests/lettuce/features/terrain/http.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2013 Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-from lettuce import *
-import urllib
-
-# Basic request
- at step('request the URL (.*)')
-def request_url(step, url):
- """
- Performs one basic HTTP GET request. The resulting HTTPResponse object
- will we placed in world.last_http_response
- Parameters:
- url: the full URL to query
- """
- world.last_http_response = urllib.urlopen(url)
-
- at step('last http response status code should be ([0-9]+)')
-def check_last_response_code(step, code):
- """
- Checks whether the last call to request_url resulted in a response
- with the given (numeric) status code
- Fails if it does not, or if there never was a complete request_url
- operation
- """
- assert world.last_http_response != None, "No HTTP request made yet"
- assert int(code) == world.last_http_response.getcode(),\
- code + " != " +\
- str(world.last_http_response.getcode())
diff --git a/tests/lettuce/features/terrain/steps.py b/tests/lettuce/features/terrain/steps.py
index e470acf..8df0bae 100644
--- a/tests/lettuce/features/terrain/steps.py
+++ b/tests/lettuce/features/terrain/steps.py
@@ -30,7 +30,7 @@ def stop_a_named_process(step, process_name):
"""
world.processes.stop_process(process_name)
- at step('wait (?:(\d+) times )?for (new )?(\w+) stderr message (\S+)(?: not (\S+))?')
+ at step('wait (?:(\d+) times )?for (new )?(\w+) stderr message (\w+)(?: not (\w+))?')
def wait_for_stderr_message(step, times, new, process_name, message, not_message):
"""
Block until the given message is printed to the given process's stderr
diff --git a/tests/lettuce/features/terrain/terrain.py b/tests/lettuce/features/terrain/terrain.py
index 4f48e3f..bc05341 100644
--- a/tests/lettuce/features/terrain/terrain.py
+++ b/tests/lettuce/features/terrain/terrain.py
@@ -1,4 +1,3 @@
-
# Copyright (C) 2011 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
@@ -64,8 +63,6 @@ copylist = [
"configurations/ddns/noddns.config"],
["configurations/xfrin/retransfer_master.conf.orig",
"configurations/xfrin/retransfer_master.conf"],
- ["configurations/xfrin/retransfer_master_nons.conf.orig",
- "configurations/xfrin/retransfer_master_nons.conf"],
["configurations/xfrin/retransfer_slave.conf.orig",
"configurations/xfrin/retransfer_slave.conf"],
["data/inmem-xfrin.sqlite3.orig",
@@ -383,9 +380,6 @@ def initialize(scenario):
# Convenience variable to access the last query result from querying.py
world.last_query_result = None
- # Convenience variable to access the last HTTP response from http.py
- world.last_http_response = None
-
# For slightly better errors, initialize a process_pids for the relevant
# steps
world.process_pids = None
diff --git a/tests/lettuce/features/xfrin_bind10.feature b/tests/lettuce/features/xfrin_bind10.feature
index cb1c33c..34674ca 100644
--- a/tests/lettuce/features/xfrin_bind10.feature
+++ b/tests/lettuce/features/xfrin_bind10.feature
@@ -25,13 +25,6 @@ Feature: Xfrin
A query for www.example.org to [::1]:47806 should have rcode REFUSED
When I send bind10 the command Xfrin retransfer example.org IN ::1 47807
- # The data we receive contain a NS RRset that refers to three names in the
- # example.org. zone. All these three are nonexistent in the data, producing
- # 3 separate warning messages in the log.
- And wait for new bind10 stderr message XFRIN_ZONE_WARN
- And wait for new bind10 stderr message XFRIN_ZONE_WARN
- And wait for new bind10 stderr message XFRIN_ZONE_WARN
- # But after complaining, the zone data should be accepted.
Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
A query for www.example.org to [::1]:47806 should have rcode NOERROR
@@ -45,20 +38,7 @@ Feature: Xfrin
When I do an AXFR transfer of example.org
Then transfer result should have 13 rrs
- # Now try to offer another update. However, the validation of
- # data should fail. The old version shoud still be available.
- When I send bind10 the following commands with cmdctl port 47804:
- """
- config set data_sources/classes/IN[0]/params/database_file data/example.org-nons.sqlite3
- config set Auth/database_file data/example.org-nons.sqlite3
- config commit
- """
- Then I send bind10 the command Xfrin retransfer example.org IN ::1 47807
- And wait for new bind10 stderr message XFRIN_ZONE_INVALID
- And wait for new bind10 stderr message XFRIN_INVALID_ZONE_DATA
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED
- A query for example.org type NS to [::1]:47806 should have rcode NOERROR
- And transfer result should have 13 rrs
+
Scenario: Transfer with TSIG
# Similar setup to the test above, but this time, we add TSIG configuration
@@ -106,41 +86,3 @@ Feature: Xfrin
# Transwer should succeed now
When I send bind10 the command Xfrin retransfer example.org
Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
-
- Scenario: Validation fails
- # In this test, the source data of the XFR is invalid (missing NS record
- # at the origin). We check it is rejected after the transfer.
- #
- # We use abuse the fact that we do not check data when we read it from
- # the sqlite3 database (unless we load into in-memory, which we don't
- # do here).
- The file data/test_nonexistent_db.sqlite3 should not exist
-
- Given I have bind10 running with configuration xfrin/retransfer_master_nons.conf with cmdctl port 47804 as master
- And wait for master stderr message BIND10_STARTED_CC
- And wait for master stderr message CMDCTL_STARTED
- And wait for master stderr message AUTH_SERVER_STARTED
- And wait for master stderr message XFROUT_STARTED
- And wait for master stderr message ZONEMGR_STARTED
-
- And I have bind10 running with configuration xfrin/retransfer_slave.conf
- And wait for bind10 stderr message BIND10_STARTED_CC
- And wait for bind10 stderr message CMDCTL_STARTED
- And wait for bind10 stderr message AUTH_SERVER_STARTED
- And wait for bind10 stderr message XFRIN_STARTED
- And wait for bind10 stderr message ZONEMGR_STARTED
-
- # Now we use the first step again to see if the file has been created
- The file data/test_nonexistent_db.sqlite3 should exist
-
- A query for www.example.org to [::1]:47806 should have rcode REFUSED
- When I send bind10 the command Xfrin retransfer example.org IN ::1 47807
- # It should complain once about invalid data, then again that the whole
- # zone is invalid and then reject it.
- And wait for new bind10 stderr message XFRIN_ZONE_INVALID
- And wait for new bind10 stderr message XFRIN_INVALID_ZONE_DATA
- Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_FAILED
- # The zone still doesn't exist as it is rejected.
- # FIXME: This step fails. Probably an empty zone is created in the data
- # source :-|. This should be REFUSED, not SERVFAIL.
- A query for www.example.org to [::1]:47806 should have rcode SERVFAIL
More information about the bind10-changes
mailing list