[svn] commit: r1975 - in /branches/trac192/src/lib/datasrc: TODO cache.cc cache.h data_source.cc tests/cache_unittest.cc
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat May 29 02:56:15 UTC 2010
Author: each
Date: Sat May 29 02:56:15 2010
New Revision: 1975
Log:
checkpoint: added negative caching
Modified:
branches/trac192/src/lib/datasrc/TODO
branches/trac192/src/lib/datasrc/cache.cc
branches/trac192/src/lib/datasrc/cache.h
branches/trac192/src/lib/datasrc/data_source.cc
branches/trac192/src/lib/datasrc/tests/cache_unittest.cc
Modified: branches/trac192/src/lib/datasrc/TODO
==============================================================================
--- branches/trac192/src/lib/datasrc/TODO (original)
+++ branches/trac192/src/lib/datasrc/TODO Sat May 29 02:56:15 2010
@@ -1,1 +1,19 @@
- store rdata in the database as binary blobs instead of text
+
+
+hot cache:
+- in doQueryTask() (or helper routines), for each task
+ consult the cache first before calling low-level find()
+ routines.
+
+ SIMPLE_QUERY: check for qname/qclass/qtype
+ AUTH_QUERY: check for qname/qclass/{qtype|CNAME}
+ GLUE_QUERY: check for qname/qclass/{A|AAAA}
+ REF_QUERY: check for qname/qclass/{NS|DS|DNAME}
+
+ if any of the checked types returns a cache miss, discard all
+ of them from the cache and perform a database query, caching the
+ results.
+
+- add a fast lookup method (using a hash table or a std::map)
+ to HotCache so retrieval isn't linear.
Modified: branches/trac192/src/lib/datasrc/cache.cc
==============================================================================
--- branches/trac192/src/lib/datasrc/cache.cc (original)
+++ branches/trac192/src/lib/datasrc/cache.cc Sat May 29 02:56:15 2010
@@ -24,7 +24,7 @@
namespace isc {
namespace datasrc {
-// CacheNode constructor
+// CacheNode constructors
CacheNode::CacheNode(const isc::dns::RRsetPtr rrset, time_t interval) :
qname(rrset->getName()), qclass(rrset->getClass()),
qtype(rrset->getType()), rrset_(rrset)
@@ -36,11 +36,23 @@
next = CacheNodePtr();
}
+CacheNode::CacheNode(const isc::dns::Name& name,
+ const isc::dns::RRClass& rrclass,
+ const isc::dns::RRType& rrtype, const time_t interval) :
+ qname(name), qclass(rrclass), qtype(rrtype), rrset_(RRsetPtr())
+{
+ time_t now = time(NULL);
+ expiry_ = now + interval;
+
+ prev = CacheNodePtr();
+ next = CacheNodePtr();
+}
+
// CacheNode destructor
CacheNode::~CacheNode() {}
bool
-CacheNode::isValid() {
+CacheNode::isValid() const {
time_t now = time(NULL);
return (now < expiry_);
}
@@ -80,20 +92,13 @@
promote(node);
return (node->getRRset());
} else {
-cout << "invalid node, removing it" << endl;
remove(node);
return (RRsetPtr());
}
}
-void
-HotCache::insert(RRsetPtr rrset, time_t interval) {
- if (!rrset) {
- return;
- }
-
- CacheNodePtr node(new CacheNode(rrset, interval));
-
+inline void
+HotCache::insert(const CacheNodePtr node) {
if (head) {
node->next = head;
head->prev = node;
@@ -107,9 +112,21 @@
++count_;
while (slots_ != 0 && count_ > slots_ && tail) {
-cout << "slots " << slots_ << ", count " << count_ << ", over limit, purging" << endl;
remove(tail);
}
+}
+
+void
+HotCache::cache(RRsetPtr rrset, const time_t interval) {
+ CacheNodePtr node(new CacheNode(rrset, interval));
+ this->insert(node);
+}
+
+void
+HotCache::ncache(const Name& name, const RRClass &rrclass,
+ const RRType& rrtype, const time_t interval) {
+ CacheNodePtr node(new CacheNode(name, rrclass, rrtype, interval));
+ this->insert(node);
}
void
@@ -117,19 +134,18 @@
slots_ = slots;
while (slots_ != 0 && count_ > slots_ && tail) {
-cout << "slots lowered? purging" << endl;
remove(tail);
}
}
int
-HotCache::getSlots()
+HotCache::getSlots() const
{
return (slots_);
}
int
-HotCache::getCount()
+HotCache::getCount() const
{
return (count_);
}
@@ -162,31 +178,23 @@
void
HotCache::remove(CacheNodePtr node) {
if (!node) {
-cout << "null node!?" << endl;
return;
}
-cout << "removing node " << node.get() << endl;
-cout << "(next " << node->next.get() << " prev " << node->prev.get() << ")" << endl;
if (node == head) {
-cout << "node was head; now head is " << head.get() << endl;
head = node->next;
-cout << "node was head; now head is " << head.get() << endl;
}
if (node == tail) {
tail = node->prev;
-cout << "node was tail; now tail is " << tail.get() << endl;
}
if (node->next) {
node->next->prev = node->prev;
-cout << "next node's prev is now " << node->next->prev.get() << endl;
}
if (node->prev) {
node->prev->next = node->next;
-cout << "prev node's next is now " << node->prev->next.get() << endl;
}
--count_;
Modified: branches/trac192/src/lib/datasrc/cache.h
==============================================================================
--- branches/trac192/src/lib/datasrc/cache.h (original)
+++ branches/trac192/src/lib/datasrc/cache.h Sat May 29 02:56:15 2010
@@ -40,13 +40,15 @@
public:
// Constructors
CacheNode(const isc::dns::RRsetPtr rrset, time_t interval);
+ CacheNode(const isc::dns::Name& name, const isc::dns::RRClass& rrclass,
+ const isc::dns::RRType& rrtype, const time_t interval);
// Destructor
~CacheNode();
- isc::dns::RRsetPtr getRRset() { return (rrset_); }
+ isc::dns::RRsetPtr getRRset() const { return (rrset_); }
- bool isValid();
+ bool isValid() const;
// List pointers
CacheNodePtr prev;
@@ -75,15 +77,21 @@
// Destructor
~HotCache();
+ // Retrieve a record from the cache
isc::dns::RRsetPtr retrieve(isc::dns::Name qname,
isc::dns::RRClass qclass,
isc::dns::RRType qtype);
- void insert(isc::dns::RRsetPtr rrset, time_t interval);
+ // Positively cache an RRset
+ void cache(isc::dns::RRsetPtr rrset, const time_t interval);
+
+ // Negatively cache a name/class/type tuple
+ void ncache(const isc::dns::Name& name, const isc::dns::RRClass& rrclass,
+ const isc::dns::RRType& rrtype, const time_t interval);
void setSlots(int slots);
- int getSlots();
- int getCount();
+ int getSlots() const;
+ int getCount() const;
// Pointers to the doubly-linked list of cache nodes
CacheNodePtr head;
@@ -96,6 +104,9 @@
// Move a node to the front of the LRU queue.
void promote(CacheNodePtr node);
void remove(CacheNodePtr node);
+
+ // Insert a node (used by both cache() and ncache())
+ inline void insert(const CacheNodePtr node);
};
Modified: branches/trac192/src/lib/datasrc/data_source.cc
==============================================================================
--- branches/trac192/src/lib/datasrc/data_source.cc (original)
+++ branches/trac192/src/lib/datasrc/data_source.cc Sat May 29 02:56:15 2010
@@ -544,26 +544,26 @@
task->qname.split(1, task->qname.getLabelCount() - 1) :
task->qname);
findClosestEnclosure(match, task->qclass);
- const DataSrc* datasource = match.bestDataSrc();
+ const DataSrc* datasrc = match.bestDataSrc();
const Name* zonename = match.closestName();
- assert((datasource == NULL && zonename == NULL) ||
- (datasource != NULL && zonename != NULL));
+ assert((datasrc == NULL && zonename == NULL) ||
+ (datasrc != NULL && zonename != NULL));
RRsetList data;
Result result = SUCCESS;
- if (datasource) {
+ if (datasrc) {
// For these query task types, if there is more than
// one level between the zone name and qname, we need to
// check the intermediate nodes for referrals.
if ((task->op == QueryTask::AUTH_QUERY ||
task->op == QueryTask::NOGLUE_QUERY) &&
- hasDelegation(datasource, zonename, q, task)) {
+ hasDelegation(datasrc, zonename, q, task)) {
continue;
}
- result = doQueryTask(datasource, zonename, *task, data);
+ result = doQueryTask(datasrc, zonename, *task, data);
if (result != SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
@@ -614,7 +614,7 @@
// Add the NS records for the enclosing zone to
// the authority section.
RRsetList auth;
- if (!refQuery(*zonename, q.qclass(), datasource, zonename,
+ if (!refQuery(*zonename, q.qclass(), datasrc, zonename,
auth)) {
m.setRcode(Rcode::SERVFAIL());
return;
@@ -658,7 +658,7 @@
if (task->state == QueryTask::GETANSWER) {
RRsetList auth;
m.clearHeaderFlag(MessageFlag::AA());
- if (!refQuery(task->qname, q.qclass(), datasource, zonename,
+ if (!refQuery(task->qname, q.qclass(), datasrc, zonename,
auth)) {
m.setRcode(Rcode::SERVFAIL());
return;
@@ -682,7 +682,7 @@
// and the name was not found, we need to find out whether
// there are any relevant wildcards.
bool wildcard_found = false;
- result = tryWildcard(q, task, datasource, zonename, wildcard_found);
+ result = tryWildcard(q, task, datasrc, zonename, wildcard_found);
if (result != SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
@@ -704,7 +704,7 @@
m.setRcode(Rcode::NXDOMAIN());
}
- result = addSOA(q, zonename, datasource);
+ result = addSOA(q, zonename, datasrc);
if (result != SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
@@ -713,11 +713,11 @@
Name nsecname(task->qname);
if ((task->flags & NAME_NOT_FOUND) != 0) {
- datasource->findPreviousName(task->qname, nsecname, zonename);
+ datasrc->findPreviousName(task->qname, nsecname, zonename);
}
if (q.wantDnssec()) {
- result = proveNX(q, task, datasource, *zonename, false);
+ result = proveNX(q, task, datasrc, *zonename, false);
if (result != DataSrc::SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
Modified: branches/trac192/src/lib/datasrc/tests/cache_unittest.cc
==============================================================================
--- branches/trac192/src/lib/datasrc/tests/cache_unittest.cc (original)
+++ branches/trac192/src/lib/datasrc/tests/cache_unittest.cc Sat May 29 02:56:15 2010
@@ -57,9 +57,9 @@
cache.setSlots(5);
- cache.insert(a, 30);
- cache.insert(b, 30);
- cache.insert(c, 30);
+ cache.cache(a, 30);
+ cache.cache(b, 30);
+ cache.cache(c, 30);
}
Name test_name;
@@ -79,7 +79,7 @@
RRsetPtr aaaa(new RRset(Name("foo"), RRClass::IN(), RRType::AAAA(),
RRTTL(0)));
aaaa->addRdata(in::AAAA("001:4f8:3:bb::5"));
- cache.insert(aaaa, (time_t) 4);
+ cache.cache(aaaa, (time_t) 4);
EXPECT_EQ(4, cache.getCount());
@@ -151,7 +151,7 @@
RRsetPtr aaaa(new RRset(Name("foo"), RRClass::IN(), RRType::AAAA(),
RRTTL(0)));
aaaa->addRdata(in::AAAA("001:4f8:3:bb::5"));
- cache.insert(aaaa, (time_t) 2);
+ cache.cache(aaaa, (time_t) 2);
sleep(3);
RRsetPtr r = cache.retrieve(Name("foo"), RRClass::IN(), RRType::AAAA());
@@ -160,7 +160,7 @@
TEST_F(CacheTest, LRU)
{
- // Retrieve a record, insert four new records; with five slots
+ // Retrieve a record, cache four new records; with five slots
// in the LRU queue this should remove all the previous records
// except the last one retreived.
RRsetPtr r = cache.retrieve(test_nsname, RRClass::IN(), RRType::NS());
@@ -169,25 +169,25 @@
RRsetPtr one(new RRset(Name("one"), RRClass::IN(), RRType::TXT(),
RRTTL(0)));
one->addRdata(generic::TXT("one"));
- cache.insert(one, (time_t) 30);
+ cache.cache(one, (time_t) 30);
EXPECT_EQ(4, cache.getCount());
RRsetPtr two(new RRset(Name("two"), RRClass::IN(), RRType::TXT(),
RRTTL(0)));
two->addRdata(generic::TXT("two"));
- cache.insert(two, (time_t) 30);
+ cache.cache(two, (time_t) 30);
EXPECT_EQ(5, cache.getCount());
RRsetPtr three(new RRset(Name("three"), RRClass::IN(), RRType::TXT(),
RRTTL(0)));
three->addRdata(generic::TXT("three"));
- cache.insert(three, (time_t) 30);
+ cache.cache(three, (time_t) 30);
EXPECT_EQ(5, cache.getCount());
RRsetPtr four(new RRset(Name("four"), RRClass::IN(), RRType::TXT(),
RRTTL(0)));
four->addRdata(generic::TXT("four"));
- cache.insert(four, (time_t) 30);
+ cache.cache(four, (time_t) 30);
EXPECT_EQ(5, cache.getCount());
r = cache.retrieve(test_name, RRClass::IN(), RRType::A());
More information about the bind10-changes
mailing list