Commit 76f00404 authored by Michal Vaner's avatar Michal Vaner

NSAS answers at last some queries

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac408@3540 e5f2f494-b856-4b98-b285-d166d9295462
parent e6d8478c
......@@ -14,8 +14,10 @@
// $Id$
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <boost/random.hpp>
#include <config.h>
#include <dns/rdataclass.h>
......@@ -45,7 +47,8 @@ NameserverAddressStore::NameserverAddressStore(ResolverInterface& resolver,
zone_lru_((3 * zonehashsize), new HashDeleter<ZoneEntry>(zone_hash_)),
nameserver_lru_((3 * nshashsize), new HashDeleter<NameserverEntry>(
nameserver_hash_)),
resolver_(resolver)
resolver_(resolver),
callback_(*this)
{
}
......@@ -89,7 +92,7 @@ newZone(const std::string* zone, uint16_t class_code,
if (authority->getName() != Name(*zone)) {
isc_throw(InconsistentZone,
"Authority section is for different zone, expected: " <<
zone << ", got: " << authority->getName().toText());
*zone << ", got: " << authority->getName().toText());
}
if (authority->getType() != RRType::NS()) {
isc_throw(NotNS, "Authority section with non-NS RR type: " <<
......@@ -141,6 +144,21 @@ NameserverAddressStore::lookup(const std::string& zone, uint16_t class_code,
namespace {
mutex randMutex;
size_t
randIndex(size_t count) {
// We need to lock the global generator
// TODO If there's contention locking, we might want a generator
// for each thread?
mutex::scoped_lock lock(randMutex);
// This seems to be enough to use pseudo-random generator and according
// to boost docs, this one is fast.
static rand48 generator;
return variate_generator<rand48&, uniform_int<size_t> >(generator,
uniform_int<size_t>(0, count - 1))();
}
asiolink::IOAddress
chooseAddress(const NameserverEntry::AddressVector& addresses) {
// TODO Something little bit more inteligent than just picking the first
......@@ -184,6 +202,7 @@ void NameserverAddressStore::processZone(ZonePtr zone) {
break;
case Fetchable::IN_PROGRESS:
pending = true;
ns->ensureHasCallback(zone, callback_);
break;
case Fetchable::UNREACHABLE:
// Nothing. We do not care about it.
......@@ -200,7 +219,15 @@ void NameserverAddressStore::processZone(ZonePtr zone) {
zone->setState(Fetchable::UNREACHABLE);
}
// TODO Pick up to two not_asked ones and ask them
// Pick up to two nameservers and try to resolve them
// TODO Any better way to choose one?
for (int i(0); i < 2 && !not_asked.empty(); ++ i) {
size_t index(randIndex(not_asked.size()));
not_asked[index]->askIP(resolver_, zone, callback_,
not_asked[index]);
// Remove from the vector so we do not choose it again
not_asked.erase(not_asked.begin() + index);
}
state = zone->getState();
} // Release the lock (and some other resources as a bonus)
......
......@@ -141,6 +141,19 @@ private:
* \todo Pass some of the referral stuff there?
*/
void processZone(boost::shared_ptr<ZoneEntry> zone);
/// \short Callback from nameserver entry to process zone.
class Callback : public NameserverEntry::Callback {
public:
Callback(NameserverAddressStore& store) :
store_(store)
{ }
virtual void operator()(boost::shared_ptr<ZoneEntry> zone) {
store_.processZone(zone);
}
private:
NameserverAddressStore& store_;
} callback_;
friend class Callback;
};
} // namespace nsas
......
......@@ -211,7 +211,7 @@ TEST_F(NameserverAddressStoreTest, emptyLookup) {
vector<AbstractRRset>(), getCallback());
// It should ask for IP addresses for example.com.
ASSERT_EQ(2, defaultTestResolver.requests.size());
defaultTestResolver.asksIPs(Name("example.com."), 0, 1);
defaultTestResolver.asksIPs(Name("ns.example.com."), 0, 1);
// Ask another question for the same zone
nsas.lookup("example.net.", RRClass::IN().getCode(), *authority_,
......@@ -274,7 +274,7 @@ TEST_F(NameserverAddressStoreTest, unreachableNS) {
vector<AbstractRRset>(), getCallback());
// It should ask for IP addresses for example.com.
ASSERT_EQ(2, defaultTestResolver.requests.size());
defaultTestResolver.asksIPs(Name("example.com."), 0, 1);
defaultTestResolver.asksIPs(Name("ns.example.com."), 0, 1);
// Ask another question with different zone but the same nameserver
authority_->setName(Name("example.com."));
......@@ -291,8 +291,10 @@ TEST_F(NameserverAddressStoreTest, unreachableNS) {
EXPECT_EQ(2, NSASCallback::results.size());
// When we ask one same and one other zone with the same nameserver,
// it should generate no questions and answer right away
authority_->setName(Name("example.net."));
nsas.lookup("example.net.", RRClass::IN().getCode(), *authority_,
vector<AbstractRRset>(), getCallback());
authority_->setName(Name("example.org."));
nsas.lookup("example.org.", RRClass::IN().getCode(), *authority_,
vector<AbstractRRset>(), getCallback());
// There should be 4 negative answers now
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment