[svn] commit: r4057 - in /trunk: ./ src/bin/auth/ src/bin/auth/tests/ src/bin/auth/tests/testdata/ src/bin/bind10/ src/bin/recurse/tests/ src/lib/asiolink/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/datasrc/tests/testdata/ src/lib/log/ src/lib/python/isc/utils/ src/lib/testutils/ src/lib/testutils/testdata/
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Dec 28 20:50:26 UTC 2010
Author: vorner
Date: Tue Dec 28 20:50:26 2010
New Revision: 4057
Log:
Merge #451 (MemoryZone::load)
Added:
trunk/src/lib/datasrc/tests/testdata/duplicate_rrset.zone
- copied unchanged from r4053, branches/trac451/src/lib/datasrc/tests/testdata/duplicate_rrset.zone
trunk/src/lib/testutils/testdata/example.com.zone
- copied unchanged from r4053, branches/trac451/src/lib/testutils/testdata/example.com.zone
trunk/src/lib/testutils/testdata/example.net.zone
- copied unchanged from r4053, branches/trac451/src/lib/testutils/testdata/example.net.zone
trunk/src/lib/testutils/testdata/example.org.zone
- copied unchanged from r4053, branches/trac451/src/lib/testutils/testdata/example.org.zone
trunk/src/lib/testutils/testdata/example.zone
- copied unchanged from r4053, branches/trac451/src/lib/testutils/testdata/example.zone
Modified:
trunk/ (props changed)
trunk/src/bin/auth/config.cc
trunk/src/bin/auth/tests/config_unittest.cc
trunk/src/bin/auth/tests/testdata/ (props changed)
trunk/src/bin/bind10/bind10.py.in (props changed)
trunk/src/bin/recurse/tests/ (props changed)
trunk/src/lib/asiolink/ (props changed)
trunk/src/lib/datasrc/memory_datasrc.cc
trunk/src/lib/datasrc/memory_datasrc.h
trunk/src/lib/datasrc/rbtree.h
trunk/src/lib/datasrc/tests/memory_datasrc_unittest.cc
trunk/src/lib/datasrc/tests/rbtree_unittest.cc
trunk/src/lib/log/ (props changed)
trunk/src/lib/python/isc/utils/ (props changed)
trunk/src/lib/testutils/ (props changed)
trunk/src/lib/testutils/testdata/Makefile.am
Modified: trunk/src/bin/auth/config.cc
==============================================================================
--- trunk/src/bin/auth/config.cc (original)
+++ trunk/src/bin/auth/config.cc Tue Dec 28 20:50:26 2010
@@ -151,16 +151,21 @@
isc_throw(AuthConfigError, "Missing zone file for zone: "
<< origin->str());
}
- const result::Result result = memory_datasrc_->addZone(
- ZonePtr(new MemoryZone(rrclass_, Name(origin->stringValue()))));
+ shared_ptr<MemoryZone> new_zone(new MemoryZone(rrclass_,
+ Name(origin->stringValue())));
+ const result::Result result = memory_datasrc_->addZone(new_zone);
if (result == result::EXIST) {
isc_throw(AuthConfigError, "zone "<< origin->str()
<< " already exists");
}
- // TODO
- // then load the zone from 'file', which is currently not implemented.
- //
+ /*
+ * TODO: Once we have better reloading of configuration (something
+ * else than throwing everything away and loading it again), we will
+ * need the load method to be split into some kind of build and
+ * commit/abort parts.
+ */
+ new_zone->load(file->stringValue());
}
}
Modified: trunk/src/bin/auth/tests/config_unittest.cc
==============================================================================
--- trunk/src/bin/auth/tests/config_unittest.cc (original)
+++ trunk/src/bin/auth/tests/config_unittest.cc Tue Dec 28 20:50:26 2010
@@ -17,6 +17,7 @@
#include <exceptions/exceptions.h>
#include <dns/rrclass.h>
+#include <dns/masterload.h>
#include <cc/data.h>
@@ -143,33 +144,42 @@
}
TEST_F(MemoryDatasrcConfigTest, addOneZone) {
- parser->build(Element::fromJSON(
- "[{\"type\": \"memory\","
- " \"zones\": [{\"origin\": \"example.com\","
- " \"file\": \"example.zone\"}]}]"));
- parser->commit();
- EXPECT_EQ(1, server.getMemoryDataSrc(rrclass)->getZoneCount());
+ EXPECT_NO_THROW(parser->build(Element::fromJSON(
+ "[{\"type\": \"memory\","
+ " \"zones\": [{\"origin\": \"example.com\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.zone\"}]}]")));
+ EXPECT_NO_THROW(parser->commit());
+ EXPECT_EQ(1, server.getMemoryDataSrc(rrclass)->getZoneCount());
+ // Check it actually loaded something
+ EXPECT_EQ(Zone::SUCCESS, server.getMemoryDataSrc(rrclass)->findZone(
+ Name("ns.example.com.")).zone->find(Name("ns.example.com."),
+ RRType::A()).code);
}
TEST_F(MemoryDatasrcConfigTest, addMultiZones) {
- parser->build(Element::fromJSON(
- "[{\"type\": \"memory\","
- " \"zones\": [{\"origin\": \"example.com\","
- " \"file\": \"example.zone\"},"
+ EXPECT_NO_THROW(parser->build(Element::fromJSON(
+ "[{\"type\": \"memory\","
+ " \"zones\": [{\"origin\": \"example.com\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.zone\"},"
" {\"origin\": \"example.org\","
- " \"file\": \"example.org.zone\"},"
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.org.zone\"},"
" {\"origin\": \"example.net\","
- " \"file\": \"example.net.zone\"}]}]"));
- parser->commit();
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.net.zone\"}]}]")));
+ EXPECT_NO_THROW(parser->commit());
EXPECT_EQ(3, server.getMemoryDataSrc(rrclass)->getZoneCount());
}
TEST_F(MemoryDatasrcConfigTest, replace) {
- parser->build(Element::fromJSON(
- "[{\"type\": \"memory\","
- " \"zones\": [{\"origin\": \"example.com\","
- " \"file\": \"example.zone\"}]}]"));
- parser->commit();
+ EXPECT_NO_THROW(parser->build(Element::fromJSON(
+ "[{\"type\": \"memory\","
+ " \"zones\": [{\"origin\": \"example.com\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.zone\"}]}]")));
+ EXPECT_NO_THROW(parser->commit());
EXPECT_EQ(1, server.getMemoryDataSrc(rrclass)->getZoneCount());
EXPECT_EQ(isc::datasrc::result::SUCCESS,
server.getMemoryDataSrc(rrclass)->findZone(
@@ -179,31 +189,69 @@
// should replace the old one.
delete parser;
parser = createAuthConfigParser(server, "datasources");
- parser->build(Element::fromJSON(
+ EXPECT_NO_THROW(parser->build(Element::fromJSON(
"[{\"type\": \"memory\","
" \"zones\": [{\"origin\": \"example.org\","
- " \"file\": \"example.org.zone\"},"
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.org.zone\"},"
" {\"origin\": \"example.net\","
- " \"file\": \"example.net.zone\"}]}]"));
- parser->commit();
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.net.zone\"}]}]")));
+ EXPECT_NO_THROW(parser->commit());
EXPECT_EQ(2, server.getMemoryDataSrc(rrclass)->getZoneCount());
EXPECT_EQ(isc::datasrc::result::NOTFOUND,
server.getMemoryDataSrc(rrclass)->findZone(
Name("example.com")).code);
}
+TEST_F(MemoryDatasrcConfigTest, exception) {
+ // Load a zone
+ EXPECT_NO_THROW(parser->build(Element::fromJSON(
+ "[{\"type\": \"memory\","
+ " \"zones\": [{\"origin\": \"example.com\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.zone\"}]}]")));
+ EXPECT_NO_THROW(parser->commit());
+ EXPECT_EQ(1, server.getMemoryDataSrc(rrclass)->getZoneCount());
+ EXPECT_EQ(isc::datasrc::result::SUCCESS,
+ server.getMemoryDataSrc(rrclass)->findZone(
+ Name("example.com")).code);
+
+ // create a new parser, and try to load something. It will throw,
+ // the given master file should not exist
+ delete parser;
+ parser = createAuthConfigParser(server, "datasources");
+ EXPECT_THROW(parser->build(Element::fromJSON(
+ "[{\"type\": \"memory\","
+ " \"zones\": [{\"origin\": \"example.org\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.org.zone\"},"
+ " {\"origin\": \"example.net\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/nonexistent.zone\"}]}]")), isc::dns::MasterLoadError);
+ // As that one throwed exception, it is not expected from us to
+ // commit it
+
+ // The original should be untouched
+ EXPECT_EQ(1, server.getMemoryDataSrc(rrclass)->getZoneCount());
+ EXPECT_EQ(isc::datasrc::result::SUCCESS,
+ server.getMemoryDataSrc(rrclass)->findZone(
+ Name("example.com")).code);
+}
+
TEST_F(MemoryDatasrcConfigTest, remove) {
- parser->build(Element::fromJSON(
- "[{\"type\": \"memory\","
- " \"zones\": [{\"origin\": \"example.com\","
- " \"file\": \"example.zone\"}]}]"));
- parser->commit();
+ EXPECT_NO_THROW(parser->build(Element::fromJSON(
+ "[{\"type\": \"memory\","
+ " \"zones\": [{\"origin\": \"example.com\","
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.zone\"}]}]")));
+ EXPECT_NO_THROW(parser->commit());
EXPECT_EQ(1, server.getMemoryDataSrc(rrclass)->getZoneCount());
delete parser;
parser = createAuthConfigParser(server, "datasources");
- parser->build(Element::fromJSON("[]"));
- parser->commit();
+ EXPECT_NO_THROW(parser->build(Element::fromJSON("[]")));
+ EXPECT_NO_THROW(parser->commit());
EXPECT_EQ(AuthSrv::MemoryDataSrcPtr(), server.getMemoryDataSrc(rrclass));
}
@@ -212,9 +260,11 @@
Element::fromJSON(
"[{\"type\": \"memory\","
" \"zones\": [{\"origin\": \"example.com\","
- " \"file\": \"example.zone\"},"
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.zone\"},"
" {\"origin\": \"example.com\","
- " \"file\": \"example.com.zone\"}]}]")),
+ " \"file\": \"" TEST_DATA_DIR
+ "/example.com.zone\"}]}]")),
AuthConfigError);
}
Modified: trunk/src/lib/datasrc/memory_datasrc.cc
==============================================================================
--- trunk/src/lib/datasrc/memory_datasrc.cc (original)
+++ trunk/src/lib/datasrc/memory_datasrc.cc Tue Dec 28 20:50:26 2010
@@ -15,9 +15,11 @@
#include <map>
#include <cassert>
#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
#include <dns/name.h>
#include <dns/rrclass.h>
+#include <dns/masterload.h>
#include <datasrc/memory_datasrc.h>
#include <datasrc/rbtree.h>
@@ -65,7 +67,7 @@
* access is without the impl_-> and it will get inlined anyway.
*/
// Implementation of MemoryZone::add
- result::Result add(const ConstRRsetPtr& rrset) {
+ result::Result add(const ConstRRsetPtr& rrset, DomainTree* domains) {
// Sanitize input
if (!rrset) {
isc_throw(NullRRset, "The rrset provided is NULL");
@@ -80,7 +82,7 @@
}
// Get the node
DomainNode* node;
- switch (domains_.insert(name, &node)) {
+ switch (domains->insert(name, &node)) {
// Just check it returns reasonable results
case DomainTree::SUCCEED:
case DomainTree::ALREADYEXIST:
@@ -109,6 +111,22 @@
// The RRSet of given type was already there
return (result::EXIST);
}
+ }
+
+ /*
+ * Same as above, but it checks the return value and if it already exists,
+ * it throws.
+ */
+ void addFromLoad(const ConstRRsetPtr& set, DomainTree* domains) {
+ switch (add(set, domains)) {
+ case result::EXIST:
+ isc_throw(dns::MasterLoadError, "Duplicate rrset: " <<
+ set->toText());
+ case result::SUCCESS:
+ return;
+ default:
+ assert(0);
+ }
}
// Implementation of MemoryZone::find
@@ -172,7 +190,19 @@
result::Result
MemoryZone::add(const ConstRRsetPtr& rrset) {
- return (impl_->add(rrset));
+ return (impl_->add(rrset, &impl_->domains_));
+}
+
+
+void
+MemoryZone::load(const string& filename) {
+ // Load it into a temporary tree
+ MemoryZoneImpl::DomainTree tmp;
+ masterLoad(filename.c_str(), getOrigin(), getClass(),
+ boost::bind(&MemoryZoneImpl::addFromLoad, impl_, _1, &tmp));
+ // If it went well, put it inside
+ tmp.swap(impl_->domains_);
+ // And let the old data die with tmp
}
/// Implementation details for \c MemoryDataSrc hidden from the public
Modified: trunk/src/lib/datasrc/memory_datasrc.h
==============================================================================
--- trunk/src/lib/datasrc/memory_datasrc.h (original)
+++ trunk/src/lib/datasrc/memory_datasrc.h Tue Dec 28 20:50:26 2010
@@ -97,6 +97,30 @@
{ }
};
+ /// \brief Load zone from masterfile.
+ ///
+ /// This loads data from masterfile specified by filename. It replaces
+ /// current content. The masterfile parsing ability is kind of limited,
+ /// see isc::dns::masterLoad.
+ ///
+ /// This throws isc::dns::MasterLoadError if there is problem with loading
+ /// (missing file, malformed, it contains different zone, etc - see
+ /// isc::dns::masterLoad for details).
+ ///
+ /// In case of internal problems, OutOfZone, NullRRset or AssertError could
+ /// be thrown, but they should not be expected. Exceptions caused by
+ /// allocation may be thrown as well.
+ ///
+ /// If anything is thrown, the previous content is preserved (so it can
+ /// be used to update the data, but if user makes a typo, the old one
+ /// is kept).
+ ///
+ /// \param filename The master file to load.
+ ///
+ /// \todo We may need to split it to some kind of build and commit/abort.
+ /// This will probably be needed when a better implementation of
+ /// configuration reloading is written.
+ void load(const std::string& filename);
private:
/// \name Hidden private data
//@{
Modified: trunk/src/lib/datasrc/rbtree.h
==============================================================================
--- trunk/src/lib/datasrc/rbtree.h (original)
+++ trunk/src/lib/datasrc/rbtree.h Tue Dec 28 20:50:26 2010
@@ -293,6 +293,16 @@
/// \code find() \endcode, in case the name isn't exist and needs to insert again
Result insert(const isc::dns::Name& name, RBNode<T>** inserted_node);
//@}
+
+ /// \brief Swaps two tree's contents.
+ ///
+ /// This acts the same as many std::*.swap functions, exchanges the
+ /// contents. This doesn't throw anything.
+ void swap(RBTree<T>& other) {
+ std::swap(root_, other.root_);
+ std::swap(NULLNODE, other.NULLNODE);
+ std::swap(node_count_, other.node_count_);
+ }
private:
/// \name RBTree balance functions
Modified: trunk/src/lib/datasrc/tests/memory_datasrc_unittest.cc
==============================================================================
--- trunk/src/lib/datasrc/tests/memory_datasrc_unittest.cc (original)
+++ trunk/src/lib/datasrc/tests/memory_datasrc_unittest.cc Tue Dec 28 20:50:26 2010
@@ -17,6 +17,7 @@
#include <dns/name.h>
#include <dns/rrclass.h>
#include <dns/rrttl.h>
+#include <dns/masterload.h>
#include <datasrc/memory_datasrc.h>
@@ -181,18 +182,28 @@
* \param name The name to ask for.
* \param rrtype The RRType to ask of.
* \param result The expected code of the result.
+ * \param check_answer Should a check against equality of the answer be
+ * done?
* \param answer The expected rrset, if any should be returned.
+ * \param zone Check different MemoryZone object than zone_ (if NULL,
+ * uses zone_)
*/
void findTest(const Name& name, const RRType& rrtype, Zone::Result result,
- const ConstRRsetPtr& answer = ConstRRsetPtr())
+ bool check_answer = true,
+ const ConstRRsetPtr& answer = ConstRRsetPtr(), MemoryZone *zone = NULL)
{
+ if (!zone) {
+ zone = &zone_;
+ }
// The whole block is inside, because we need to check the result and
// we can't assign to FindResult
EXPECT_NO_THROW({
- Zone::FindResult find_result(zone_.find(name, rrtype));
+ Zone::FindResult find_result(zone->find(name, rrtype));
// Check it returns correct answers
EXPECT_EQ(result, find_result.code);
- EXPECT_EQ(answer, find_result.rrset);
+ if (check_answer) {
+ EXPECT_EQ(answer, find_result.rrset);
+ }
});
}
};
@@ -248,8 +259,8 @@
EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_a_)));
// These two should be successful
- findTest(origin_, RRType::NS(), Zone::SUCCESS, rr_ns_);
- findTest(ns_name_, RRType::A(), Zone::SUCCESS, rr_ns_a_);
+ findTest(origin_, RRType::NS(), Zone::SUCCESS, true, rr_ns_);
+ findTest(ns_name_, RRType::A(), Zone::SUCCESS, true, rr_ns_a_);
// These domain exist but don't have the provided RRType
findTest(origin_, RRType::AAAA(), Zone::NXRRSET);
@@ -260,4 +271,34 @@
findTest(Name("example.net"), RRType::A(), Zone::NXDOMAIN);
}
-}
+TEST_F(MemoryZoneTest, load) {
+ // Put some data inside the zone
+ EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_.add(rr_ns_)));
+ // Loading with different origin should fail
+ EXPECT_THROW(zone_.load(TEST_DATA_DIR "/root.zone"), MasterLoadError);
+ // See the original data is still there, survived the exception
+ findTest(origin_, RRType::NS(), Zone::SUCCESS, true, rr_ns_);
+ // Create correct zone
+ MemoryZone rootzone(class_, Name("."));
+ // Try putting something inside
+ EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, rootzone.add(rr_ns_aaaa_)));
+ // Load the zone. It should overwrite/remove the above RRset
+ EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
+
+ // Now see there are some rrsets (we don't look inside, though)
+ findTest(Name("."), RRType::SOA(), Zone::SUCCESS, false, ConstRRsetPtr(),
+ &rootzone);
+ findTest(Name("."), RRType::NS(), Zone::SUCCESS, false, ConstRRsetPtr(),
+ &rootzone);
+ findTest(Name("a.root-servers.net."), RRType::A(), Zone::SUCCESS, false,
+ ConstRRsetPtr(), &rootzone);
+ // But this should no longer be here
+ findTest(ns_name_, RRType::AAAA(), Zone::NXDOMAIN, true, ConstRRsetPtr(),
+ &rootzone);
+
+ // Try loading zone that is wrong in a different way
+ EXPECT_THROW(zone_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
+ MasterLoadError);
+}
+
+}
Modified: trunk/src/lib/datasrc/tests/rbtree_unittest.cc
==============================================================================
--- trunk/src/lib/datasrc/tests/rbtree_unittest.cc (original)
+++ trunk/src/lib/datasrc/tests/rbtree_unittest.cc Tue Dec 28 20:50:26 2010
@@ -176,4 +176,34 @@
str2 << "tree has 13 node(s)\nb. (black)\n a. (black)\n NULL\n NULL\n d.e.f. (black)[invisible] \n begin down from d.e.f.\n w.y. (black)[invisible] \n begin down from w.y.\n p. (black)\n o. (red)\n NULL\n NULL\n q. (red)\n NULL\n NULL\n end down from w.y.\n x. (red)\n NULL\n NULL\n z. (red)\n begin down from z.\n j. (black)\n NULL\n NULL\n end down from z.\n NULL\n NULL\n end down from d.e.f.\n c. (red)\n NULL\n NULL\n g.h. (red)\n begin down from g.h.\n i. (black)\n
NULL\n NULL\n end down from g.h.\n NULL\n NULL\n";
EXPECT_EQ(str.str(), str2.str());
}
-}
+
+TEST_F(RBTreeTest, swap) {
+ // Store info about the first tree
+ std::ostringstream str1;
+ rbtree.dumpTree(str1);
+ size_t count1(rbtree.getNodeCount());
+
+ // Create second one and store state
+ RBTree<int> tree2;
+ RBNode<int>* node;
+ tree2.insert(Name("second"), &node);
+ std::ostringstream str2;
+ tree2.dumpTree(str2);
+
+ // Swap them
+ ASSERT_NO_THROW(tree2.swap(rbtree));
+
+ // Check their sizes
+ ASSERT_EQ(1, rbtree.getNodeCount());
+ ASSERT_EQ(count1, tree2.getNodeCount());
+
+ // And content
+ std::ostringstream out;
+ rbtree.dumpTree(out);
+ ASSERT_EQ(str2.str(), out.str());
+ out.str("");
+ tree2.dumpTree(out);
+ ASSERT_EQ(str1.str(), out.str());
+}
+
+}
Modified: trunk/src/lib/testutils/testdata/Makefile.am
==============================================================================
--- trunk/src/lib/testutils/testdata/Makefile.am (original)
+++ trunk/src/lib/testutils/testdata/Makefile.am Tue Dec 28 20:50:26 2010
@@ -18,6 +18,7 @@
EXTRA_DIST += shortresponse_fromWire
EXTRA_DIST += simplequery_fromWire.spec
EXTRA_DIST += simpleresponse_fromWire.spec
+EXTRA_DIST += example.com.zone example.net.zone example.org.zone example.zone
EXTRA_DIST += example.com
EXTRA_DIST += example.sqlite3
More information about the bind10-changes
mailing list