BIND 10 master, updated. 5baa7aa73ad8d8d5250990a9e330b9b746659452 Merge branch #1065
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Aug 23 19:47:16 UTC 2011
The branch, master has been updated
via 5baa7aa73ad8d8d5250990a9e330b9b746659452 (commit)
via 39a0a5c65d0802f40ab428474b1e6d981a91fbce (commit)
via 0c9db8bbeb7187218a5b47d82df18e38128d06a3 (commit)
via 9882d600d0bbbc115671b12646e690ccddbf5348 (commit)
via 59b545e90d30444a97c8e925569d240c819d42b4 (commit)
via 7e89c625c5d12b5816c857d0c0910922f8803f82 (commit)
from 872bd5756ba8b5daeeacedfcd4ec38bc50035ec8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5baa7aa73ad8d8d5250990a9e330b9b746659452
Merge: 872bd5756ba8b5daeeacedfcd4ec38bc50035ec8 39a0a5c65d0802f40ab428474b1e6d981a91fbce
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Tue Aug 23 21:40:52 2011 +0200
Merge branch #1065
Conflicts:
src/lib/datasrc/database.cc
src/lib/datasrc/database.h
src/lib/datasrc/sqlite3_accessor.cc
src/lib/datasrc/sqlite3_accessor.h
src/lib/datasrc/tests/database_unittest.cc
src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/database.cc | 16 +++++
src/lib/datasrc/database.h | 6 ++-
src/lib/datasrc/sqlite3_accessor.cc | 31 ++++-----
src/lib/datasrc/sqlite3_accessor.h | 4 +-
src/lib/datasrc/tests/database_unittest.cc | 69 ++++++++++++++++----
src/lib/datasrc/tests/sqlite3_accessor_unittest.cc | 10 +++
6 files changed, 103 insertions(+), 33 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index f0ac192..c2c0a4b 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -358,6 +358,22 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
result_rrset->getType() == isc::dns::RRType::CNAME()) {
result_status = CNAME;
}
+
+ if (!result_rrset && !records_found) {
+ // Request the context
+ DatabaseAccessor::IteratorContextPtr
+ context(database_->getRecords(name.toText(), zone_id_, true));
+ // It must not return NULL, that's a bug of the implementation
+ if (!context) {
+ isc_throw(isc::Unexpected, "Iterator context null at " +
+ name.toText());
+ }
+
+ std::string columns[DatabaseAccessor::COLUMN_COUNT];
+ if (context->getNext(columns)) {
+ records_found = true;
+ }
+ }
}
if (!result_rrset) {
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index d7785e6..16d742d 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -172,10 +172,14 @@ public:
*
* \param name The name to search for. This should be a FQDN.
* \param id The ID of the zone, returned from getZone().
+ * \param subdomains If set to true, match subdomains of name instead
+ * of name itself. It is used to find empty domains and match
+ * wildcards.
* \return Newly created iterator context. Must not be NULL.
*/
virtual IteratorContextPtr getRecords(const std::string& name,
- int id) const = 0;
+ int id,
+ bool subdomains = false) const = 0;
/**
* \brief Creates an iterator context for the whole zone.
diff --git a/src/lib/datasrc/sqlite3_accessor.cc b/src/lib/datasrc/sqlite3_accessor.cc
index e604cf9..092d919 100644
--- a/src/lib/datasrc/sqlite3_accessor.cc
+++ b/src/lib/datasrc/sqlite3_accessor.cc
@@ -28,23 +28,10 @@ struct SQLite3Parameters {
SQLite3Parameters() :
db_(NULL), version_(-1),
q_zone_(NULL)
- /*q_record_(NULL), q_addrs_(NULL), q_referral_(NULL),
- q_count_(NULL), q_previous_(NULL), q_nsec3_(NULL),
- q_prevnsec3_(NULL) */
{}
sqlite3* db_;
int version_;
sqlite3_stmt* q_zone_;
- /*
- TODO: Yet unneeded statements
- sqlite3_stmt* q_record_;
- sqlite3_stmt* q_addrs_;
- sqlite3_stmt* q_referral_;
- sqlite3_stmt* q_count_;
- sqlite3_stmt* q_previous_;
- sqlite3_stmt* q_nsec3_;
- sqlite3_stmt* q_prevnsec3_;
- */
};
SQLite3Database::SQLite3Database(const std::string& filename,
@@ -74,6 +61,8 @@ public:
if (params_.q_zone_ != NULL) {
sqlite3_finalize(params_.q_zone_);
}
+ // we do NOT finalize q_current_ - that is just a pointer to one of
+ // the other statements, not a separate one.
/*
if (params_.q_record_ != NULL) {
sqlite3_finalize(params_.q_record_);
@@ -139,6 +128,9 @@ const char* const q_zone_str = "SELECT id FROM zones WHERE name=?1 AND rdclass =
const char* const q_any_str = "SELECT rdtype, ttl, sigtype, rdata "
"FROM records WHERE zone_id=?1 AND name=?2";
+const char* const q_any_sub_str = "SELECT rdtype, ttl, sigtype, rdata "
+ "FROM records WHERE zone_id=?1 AND name LIKE (\"%.\" || ?2)";
+
// note that the order of the SELECT values is specifically chosen to match
// the enum values in RecordColumns
const char* const q_iterate_str = "SELECT rdtype, ttl, sigtype, rdata, name FROM records "
@@ -328,7 +320,6 @@ SQLite3Database::getZone(const isc::dns::Name& name) const {
return (std::pair<bool, int>(false, 0));
}
-
class SQLite3Database::Context : public DatabaseAccessor::IteratorContext {
public:
// Construct an iterator for all records. When constructed this
@@ -347,14 +338,15 @@ public:
// Construct an iterator for records with a specific name. When constructed
// this way, the getNext() call will copy all fields except name
Context(const boost::shared_ptr<const SQLite3Database>& database, int id,
- const std::string& name) :
+ const std::string& name, bool subdomains) :
iterator_type_(ITT_NAME),
database_(database),
statement_(NULL),
name_(name)
{
// We create the statement now and then just keep getting data from it
- statement_ = prepare(database->dbparameters_->db_, q_any_str);
+ statement_ = prepare(database->dbparameters_->db_,
+ subdomains ? q_any_sub_str : q_any_str);
bindZoneId(id);
bindName(name_);
}
@@ -459,8 +451,11 @@ private:
};
DatabaseAccessor::IteratorContextPtr
-SQLite3Database::getRecords(const std::string& name, int id) const {
- return (IteratorContextPtr(new Context(shared_from_this(), id, name)));
+SQLite3Database::getRecords(const std::string& name, int id,
+ bool subdomains) const
+{
+ return (IteratorContextPtr(new Context(shared_from_this(), id, name,
+ subdomains)));
}
DatabaseAccessor::IteratorContextPtr
diff --git a/src/lib/datasrc/sqlite3_accessor.h b/src/lib/datasrc/sqlite3_accessor.h
index 50b15e7..cc5c657 100644
--- a/src/lib/datasrc/sqlite3_accessor.h
+++ b/src/lib/datasrc/sqlite3_accessor.h
@@ -102,10 +102,12 @@ public:
*
* \param name the name to look up
* \param id the zone id, as returned by getZone()
+ * \param subdomains Match subdomains instead of the name.
* \return Iterator that contains all records with the given name
*/
virtual IteratorContextPtr getRecords(const std::string& name,
- int id) const;
+ int id,
+ bool subdomains = false) const;
/** \brief Look up all resource records for a zone
*
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index 8ff8c55..ac6cbf7 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -62,7 +62,9 @@ public:
return (database_name_);
}
- virtual IteratorContextPtr getRecords(const std::string&, int) const {
+ virtual IteratorContextPtr getRecords(const std::string&, int, bool)
+ const
+ {
isc_throw(isc::NotImplemented,
"This database datasource can't be iterated");
};
@@ -93,7 +95,7 @@ private:
class MockNameIteratorContext : public IteratorContext {
public:
MockNameIteratorContext(const MockAccessor& mock_accessor, int zone_id,
- const std::string& name) :
+ const std::string& name, bool subdomains) :
searched_name_(name), cur_record_(0)
{
// 'hardcoded' names to trigger exceptions
@@ -107,16 +109,32 @@ private:
throw std::exception();
}
- // we're not aiming for efficiency in this test, simply
- // copy the relevant vector from records
if (zone_id == 42) {
- if (mock_accessor.records.count(searched_name_) > 0) {
- cur_name = mock_accessor.records.find(searched_name_)->second;
- } else {
+ if (subdomains) {
cur_name.clear();
+ // Just walk everything and check if it is a subdomain.
+ // If it is, just copy all data from there.
+ for (Domains::const_iterator
+ i(mock_accessor.records.begin());
+ i != mock_accessor.records.end(); ++ i) {
+ Name local(i->first);
+ if (local.compare(isc::dns::Name(name)).
+ getRelation() ==
+ isc::dns::NameComparisonResult::SUBDOMAIN) {
+ cur_name.insert(cur_name.end(), i->second.begin(),
+ i->second.end());
+ }
+ }
+ } else {
+ // we're not aiming for efficiency in this test, simply
+ // copy the relevant vector from records
+ if (mock_accessor.records.count(searched_name_) > 0) {
+ cur_name = mock_accessor.records.find(searched_name_)->
+ second;
+ } else {
+ cur_name.clear();
+ }
}
- } else {
- cur_name.clear();
}
}
@@ -244,17 +262,27 @@ public:
}
}
- virtual IteratorContextPtr getRecords(const std::string& name, int id) const {
+ virtual IteratorContextPtr getRecords(const std::string& name, int id,
+ bool subdomains) const
+ {
if (id == 42) {
- return (IteratorContextPtr(new MockNameIteratorContext(*this, id, name)));
+ return (IteratorContextPtr(new MockNameIteratorContext(*this, id,
+ name, subdomains)));
} else {
isc_throw(isc::Unexpected, "Unknown zone ID");
}
}
private:
- std::map<std::string, std::vector< std::vector<std::string> > > records;
+ typedef std::map<std::string, std::vector< std::vector<std::string> > >
+ Domains;
+ // used as internal index for getNextRecord()
+ size_t cur_record;
// used as temporary storage during the building of the fake data
+ Domains records;
+ // used as temporary storage after searchForRecord() and during
+ // getNextRecord() calls, as well as during the building of the
+ // fake data
std::vector< std::vector<std::string> > cur_name;
// Adds one record to the current name in the database
@@ -428,12 +456,16 @@ private:
addRecord("RRSIG", "3600", "", "NS 5 3 3600 20000101000000 "
"20000201000000 12345 example.org. FAKEFAKEFAKE");
addCurName("example.org.");
+
+ // This is because of empty domain test
+ addRecord("A", "3600", "", "192.0.2.1");
+ addCurName("a.b.example.org.");
}
};
// This tests the default getRecords behaviour, throwing NotImplemented
TEST(DatabaseConnectionTest, getRecords) {
- EXPECT_THROW(NopAccessor().getRecords(".", 1),
+ EXPECT_THROW(NopAccessor().getRecords(".", 1, false),
isc::NotImplemented);
}
@@ -1103,6 +1135,17 @@ TEST_F(DatabaseClientTest, glueOK) {
ZoneFinder::FIND_GLUE_OK);
}
+TEST_F(DatabaseClientTest, empty) {
+ shared_ptr<DatabaseClient::Finder> finder(getFinder());
+
+ // Check empty domain
+ // This domain doesn't exist, but a subdomain of it does.
+ // Therefore we should pretend the domain is there, but contains no RRsets
+ doFindTest(finder, isc::dns::Name("b.example.org."), isc::dns::RRType::A(),
+ isc::dns::RRType::A(), isc::dns::RRTTL(3600),
+ ZoneFinder::NXRRSET, expected_rdatas_, expected_sig_rdatas_);
+}
+
TEST_F(DatabaseClientTest, getOrigin) {
DataSourceClient::FindResult zone(client_->findZone(Name("example.org")));
ASSERT_EQ(result::SUCCESS, zone.code);
diff --git a/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc b/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
index 5f7abaf..2526f98 100644
--- a/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
+++ b/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
@@ -327,6 +327,16 @@ TEST_F(SQLite3Access, getRecords) {
// check that another getNext does not cause problems
EXPECT_FALSE(context->getNext(columns));
+
+ // Try searching for subdomain
+ // There's foo.bar.example.com in the data
+ context = db->getRecords("bar.example.com.", zone_id, true);
+ ASSERT_TRUE(context->getNext(columns));
+ checkRecordRow(columns, "A", "3600", "", "192.0.2.1", "");
+ EXPECT_FALSE(context->getNext(columns));
+ // But we shouldn't match mix.example.com here
+ context = db->getRecords("ix.example.com.", zone_id, true);
+ EXPECT_FALSE(context->getNext(columns));
}
} // end anonymous namespace
More information about the bind10-changes
mailing list