[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