Browse Source

Commit the latest code of recursor cache.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac449@4111 e5f2f494-b856-4b98-b285-d166d9295462
Likun Zhang 14 years ago
parent
commit
38e8504574

+ 21 - 9
src/lib/cache/message_cache.cc

@@ -33,7 +33,6 @@ MessageCache::MessageCache(boost::shared_ptr<RRsetCache> rrset_cache,
     message_table_(new NsasEntryCompare<MessageEntry>, cache_size),
     message_table_(new NsasEntryCompare<MessageEntry>, cache_size),
     message_lru_((3 * cache_size),
     message_lru_((3 * cache_size),
                   new HashDeleter<MessageEntry>(message_table_))
                   new HashDeleter<MessageEntry>(message_table_))
-
 {
 {
 }
 }
     
     
@@ -43,12 +42,8 @@ MessageCache::lookup(const isc::dns::Name& qname,
                      const uint16_t query_header,
                      const uint16_t query_header,
                      isc::dns::Message& response)
                      isc::dns::Message& response)
 {
 {
-    CacheEntryKey keydata = genCacheEntryKey(qname, qtype);
-
-    //TODO, HashKey need to be refactored, since we don't need query class
-    // as the parameters.
-    boost::shared_ptr<MessageEntry> msg_entry = message_table_.get(HashKey(
-                keydata.first, keydata.second, RRClass(message_class_)));
+    HashKey entry_key = getEntryHashKey(qname, qtype);
+    MessageEntryPtr msg_entry = message_table_.get(entry_key);
     if(msg_entry) {
     if(msg_entry) {
        return msg_entry->genMessage(time(NULL), query_header, response);
        return msg_entry->genMessage(time(NULL), query_header, response);
     }
     }
@@ -57,20 +52,37 @@ MessageCache::lookup(const isc::dns::Name& qname,
 }
 }
 
 
 bool
 bool
-MessageCache::update(const Message&) {
-    return true;
+MessageCache::update(const Message& msg) {
+    // The simplest way to update is removing the old message entry directly.
+    QuestionIterator iter = msg.beginQuestion();
+    HashKey entry_key = getEntryHashKey((*iter)->getName(),
+                                           (*iter)->getType());
+    message_table_.remove(entry_key);
+    MessageEntryPtr msg_entry(new MessageEntry(msg, rrset_cache_));
+    //TODO, lru list touch
+    return message_table_.add(msg_entry, entry_key, true);
+}
+
+HashKey
+MessageCache::getEntryHashKey(const Name& name, const RRType& type) const 
+{
+    CacheEntryKey keydata = genCacheEntryKey(name, type);
+    return HashKey(keydata.first, keydata.second, RRClass(message_class_));
 }
 }
 
 
 void
 void
 MessageCache::dump(const std::string&) {
 MessageCache::dump(const std::string&) {
+    //TODO
 }
 }
 
 
 void
 void
 MessageCache::load(const std::string&) {
 MessageCache::load(const std::string&) {
+    //TODO
 }
 }
 
 
 bool
 bool
 MessageCache::resize(uint32_t) {
 MessageCache::resize(uint32_t) {
+    //TODO
     return true;
     return true;
 }
 }
 
 

+ 8 - 0
src/lib/cache/message_cache.h

@@ -71,6 +71,14 @@ public:
     /// \brief Resize the size of message cache in runtime. 
     /// \brief Resize the size of message cache in runtime. 
     bool resize(uint32_t size);
     bool resize(uint32_t size);
 
 
+protected:
+    /// \brief Get the hash key for the message entry in the cache.
+    /// \param name query name of the message.
+    /// \param type query type of the message.
+    /// \return return the hash key.
+    HashKey getEntryHashKey(const isc::dns::Name& name, 
+                            const isc::dns::RRType& type) const;
+
 private:
 private:
     uint16_t message_class_; // The class of the message cache.
     uint16_t message_class_; // The class of the message cache.
     boost::shared_ptr<RRsetCache> rrset_cache_;
     boost::shared_ptr<RRsetCache> rrset_cache_;

+ 92 - 13
src/lib/cache/message_entry.cc

@@ -14,23 +14,28 @@
 
 
 // $Id$
 // $Id$
 
 
+#include <limits>
 #include <dns/message.h>
 #include <dns/message.h>
 #include <nsas/nsas_entry.h>
 #include <nsas/nsas_entry.h>
 #include <nsas/fetchable.h>
 #include <nsas/fetchable.h>
 #include "message_entry.h"
 #include "message_entry.h"
 #include "rrset_entry.h"
 #include "rrset_entry.h"
+#include "rrset_cache.h"
 
 
 
 
 using namespace isc::dns;
 using namespace isc::dns;
+using namespace std;
 
 
 namespace isc {
 namespace isc {
 namespace cache {
 namespace cache {
 
 
-MessageEntry::MessageEntry(const isc::dns::Message&,
+static uint32_t MAX_UINT32 = numeric_limits<uint32_t>::max();    
+
+MessageEntry::MessageEntry(const isc::dns::Message& msg,
                            boost::shared_ptr<RRsetCache> rrset_cache):
                            boost::shared_ptr<RRsetCache> rrset_cache):
     rrset_cache_(rrset_cache)
     rrset_cache_(rrset_cache)
 {
 {
-
+    initMessageEntry(msg);
 }
 }
     
     
 bool
 bool
@@ -41,26 +46,100 @@ MessageEntry::genMessage(const time_t&,
     return true;
     return true;
 }
 }
 
 
+RRsetTrustLevel
+MessageEntry::getRRsetTrustLevel(const Message& message,
+                   const RRset&,
+                   const Message::Section& section) 
+{
+    bool aa = message.getHeaderFlag(Message::HEADERFLAG_AA);
+    switch(section) {
+        case Message::SECTION_ANSWER: {
+            if (aa) {
+                //TODO, according RFC2181 section 5.4.1, only the record 
+                // describing that ailas is necessarily authoritative.
+                return RRSET_TRUST_ANSWER_AA;
+            } else {
+                return RRSET_TRUST_ANSWER_NONAA;
+            }
+            break;
+        }
+        
+        case Message::SECTION_AUTHORITY: {
+            if (aa) {
+                return RRSET_TRUST_AUTHORITY_AA;
+            } else {
+                return RRSET_TRUST_AUTHORITY_NONAA;
+            }
+            break;
+        }
+
+        case Message::SECTION_ADDITIONAL: {
+            if (aa) {
+                return RRSET_TRUST_ADDITIONAL_AA;
+            } else {
+                return RRSET_TRUST_ADDITIONAL_NONAA;
+            }
+            break;
+        }
+
+        default:
+            return RRSET_TRUST_DEFAULT;
+    }
+}
+
+void
+MessageEntry::parseSection(const isc::dns::Message& msg,
+                           const Message::Section& section,
+                           uint32_t& smaller_ttl)
+{
+    RRsetIterator iter;
+    for (iter = msg.beginSection(section);
+         iter != msg.endSection(section);
+         ++iter) {
+        // Add the rrset entry to rrset_cache or update the existed 
+        // rrset entry if the new one is more authoritative.
+        //TODO set proper rrset trust level.
+        RRsetPtr rrset_ptr = *iter;
+        RRsetTrustLevel level = getRRsetTrustLevel(msg, *rrset_ptr, section);
+        RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
+        rrsets_.push_back(rrset_entry);
+        
+        uint32_t rrset_ttl = rrset_entry->getTTL();
+        if (smaller_ttl > rrset_ttl) {
+            smaller_ttl = rrset_ttl;
+        }
+    }
+}
+
 void
 void
 MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
 MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
     query_count_ = msg.getRRCount(Message::SECTION_QUESTION);
     query_count_ = msg.getRRCount(Message::SECTION_QUESTION);
     answer_count_ = msg.getRRCount(Message::SECTION_ANSWER);
     answer_count_ = msg.getRRCount(Message::SECTION_ANSWER);
     authority_count_ = msg.getRRCount(Message::SECTION_AUTHORITY);
     authority_count_ = msg.getRRCount(Message::SECTION_AUTHORITY);
     additional_count_ = msg.getRRCount(Message::SECTION_ADDITIONAL);
     additional_count_ = msg.getRRCount(Message::SECTION_ADDITIONAL);
+    
+    //TODO how to cache the header?
+    // query_header 
 
 
-    // query_header \\TODO how to cache the header?
-    RRsetIterator iter;
-    for (iter = msg.beginSection(Message::SECTION_ANSWER);
-         iter != msg.endSection(Message::SECTION_ANSWER);
-         ++iter) {
-        //*rit is one pointer to RRset.
-        //boost::shared_ptr<RRsetEntry> entry_ptr = new RRsetEntry(*(*iter);
-        //rrsets_.append(entry_ptr);
+    // We only cache the first question in question section.
+    // TODO, do we need to support muptiple questions?
+    QuestionIterator iter = msg.beginQuestion();
+    query_name_ = (*iter)->getName().toText();
+    query_type_ = (*iter)->getType().getCode();
+    query_class_ = (*iter)->getClass().getCode();
+    
+    uint32_t min_ttl = MAX_UINT32;
+    parseSection(msg, Message::SECTION_ANSWER, min_ttl);
+    parseSection(msg, Message::SECTION_AUTHORITY, min_ttl);
+    parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl);
 
 
-        // Add the rrset entry to rrset_cache or update the existed 
-        // rrset entry if the new one is more authoritative.
-    }
+    expire_time_ = time(NULL) + min_ttl;
+}
 
 
+HashKey
+MessageEntry::hashKey() const {
+    CacheEntryKey keydata = genCacheEntryKey(query_name_, query_type_);
+    return HashKey(keydata.first, keydata.second, RRClass(query_class_));
 }
 }
 
 
 } // namespace cache
 } // namespace cache

+ 31 - 4
src/lib/cache/message_entry.h

@@ -21,6 +21,7 @@
 #include <dns/message.h>
 #include <dns/message.h>
 #include <nsas/nsas_entry.h>
 #include <nsas/nsas_entry.h>
 #include <nsas/fetchable.h>
 #include <nsas/fetchable.h>
+#include "rrset_entry.h"
 
 
 
 
 using namespace isc::nsas;
 using namespace isc::nsas;
@@ -43,8 +44,9 @@ public:
     /// message.
     /// message.
     /// \param message The message used to initialize MessageEntry.
     /// \param message The message used to initialize MessageEntry.
     /// \param rrset_cache the pointer of RRsetCache. When one message
     /// \param rrset_cache the pointer of RRsetCache. When one message
-    /// entry is created, some new rrset entries may be created/updated
-    /// if they doesn't exist in the rrset cache.
+    /// entry is created, rrset cache needs to be updated, since some
+    /// new rrset entries may be inserted into the rrset cache, or the
+    /// existed rrset entries need to be updated.
     MessageEntry(const isc::dns::Message& message,
     MessageEntry(const isc::dns::Message& message,
                  boost::shared_ptr<RRsetCache> rrset_cache);
                  boost::shared_ptr<RRsetCache> rrset_cache);
 
 
@@ -60,10 +62,35 @@ public:
     bool genMessage(const time_t& time_now,
     bool genMessage(const time_t& time_now,
                     const uint16_t query_header,
                     const uint16_t query_header,
                     isc::dns::Message& response);
                     isc::dns::Message& response);
+    
+    /// \brief Get the hash key of the message entry.
+    /// \return return hash key
+    virtual HashKey hashKey() const;
+
 protected:
 protected:
-    // Initialize the message entry with dns message.
+    /// \brief Initialize the message entry with dns message.
     void initMessageEntry(const isc::dns::Message& message);
     void initMessageEntry(const isc::dns::Message& message);
 
 
+    /// \brief These two functions should be static functions
+    /// placed in cc file. Put them here just for easy unit 
+    /// test.
+    //@{
+    /// \brief Parse the rrsets in specified section.
+    /// \param smaller_ttl Get the smallest ttl of rrsets in 
+    /// specified section, if it's smaller than the given value.
+    void parseSection(const isc::dns::Message& msg,
+                      const isc::dns::Message::Section& section,
+                      uint32_t& smaller_ttl);
+
+    /// \brief Get RRset Trust worthiness
+    /// only the rrset can be updated by the rrsets 
+    /// with higher trust level.
+    ///
+    /// \return return rrset trust level.
+    RRsetTrustLevel getRRsetTrustLevel(const isc::dns::Message& message,
+                               const isc::dns::RRset& rrset,
+                               const isc::dns::Message::Section& section);
+    //@}
 private:
 private:
     time_t expire_time_;  // Expiration time of the message.
     time_t expire_time_;  // Expiration time of the message.
 
 
@@ -77,7 +104,7 @@ private:
     uint16_t authority_count_; // rrset count in authority section.
     uint16_t authority_count_; // rrset count in authority section.
     uint16_t additional_count_; // rrset count in addition section.
     uint16_t additional_count_; // rrset count in addition section.
 
 
-    std::vector<boost::shared_ptr<RRsetEntry*> > rrsets_;
+    std::vector<boost::shared_ptr<RRsetEntry> > rrsets_;
     boost::shared_ptr<RRsetCache> rrset_cache_;
     boost::shared_ptr<RRsetCache> rrset_cache_;
 };
 };
     
     

+ 22 - 4
src/lib/cache/rrset_cache.cc

@@ -33,7 +33,7 @@ RRsetCache::RRsetCache(uint32_t cache_size):
 
 
 {
 {
 }
 }
-    
+
 RRsetEntryPtr
 RRsetEntryPtr
 RRsetCache::lookup(const isc::dns::Name& qname,
 RRsetCache::lookup(const isc::dns::Name& qname,
                    const isc::dns::RRType& qtype)
                    const isc::dns::RRType& qtype)
@@ -41,8 +41,14 @@ RRsetCache::lookup(const isc::dns::Name& qname,
     CacheEntryKey keydata = genCacheEntryKey(qname, qtype);
     CacheEntryKey keydata = genCacheEntryKey(qname, qtype);
     //TODO, HashKey need to be refactored, since we don't need query class
     //TODO, HashKey need to be refactored, since we don't need query class
     // as the parameters.
     // as the parameters.
-    return rrset_table_.get(HashKey(
+    RRsetEntryPtr entry_ptr = rrset_table_.get(HashKey(
            keydata.first, keydata.second, RRClass(class_)));
            keydata.first, keydata.second, RRClass(class_)));
+
+    //If the rrset entry has expired, return NULL.
+    if(time(NULL) > entry_ptr->getExpireTime()) {
+        return RRsetEntryPtr();
+    }
+    return entry_ptr;
 }
 }
 
 
 RRsetEntryPtr
 RRsetEntryPtr
@@ -53,7 +59,8 @@ RRsetCache::update(const isc::dns::RRset& rrset, const RRsetTrustLevel& level) {
         // rrset entry doesn't exist, create one rrset entry for the rrset
         // rrset entry doesn't exist, create one rrset entry for the rrset
         // and add it directly.
         // and add it directly.
         entry_ptr.reset(new RRsetEntry(rrset, level));
         entry_ptr.reset(new RRsetEntry(rrset, level));
-        rrset_table_.add(entry_ptr, entry_ptr->hashKey());
+        // Replace the expired rrset entry if it exists.
+        rrset_table_.add(entry_ptr, entry_ptr->hashKey(), true);
         //TODO , lru list touch.
         //TODO , lru list touch.
         return entry_ptr;
         return entry_ptr;
     } else {
     } else {
@@ -69,22 +76,33 @@ RRsetCache::update(const isc::dns::RRset& rrset, const RRsetTrustLevel& level) {
             rrset_table_.remove(key);
             rrset_table_.remove(key);
             entry_ptr.reset(new RRsetEntry(rrset, level));
             entry_ptr.reset(new RRsetEntry(rrset, level));
             //TODO, lru list touch.
             //TODO, lru list touch.
-            rrset_table_.add(entry_ptr, key);
+            // Replace the expired rrset entry if it exists.
+            rrset_table_.add(entry_ptr, key, true);
             return entry_ptr;
             return entry_ptr;
         }
         }
     }
     }
 }
 }
 
 
+HashKey
+RRsetCache::getEntryHashKey(const Name& name, const RRType& type) const 
+{
+    CacheEntryKey keydata = genCacheEntryKey(name, type);
+    return HashKey(keydata.first, keydata.second, RRClass(class_));
+}
+
 void
 void
 RRsetCache::dump(const std::string&) {
 RRsetCache::dump(const std::string&) {
+    //TODO
 }
 }
 
 
 void
 void
 RRsetCache::load(const std::string&) {
 RRsetCache::load(const std::string&) {
+    //TODO
 }
 }
 
 
 bool
 bool
 RRsetCache::resize(uint32_t) {
 RRsetCache::resize(uint32_t) {
+    //TODO
     return true;
     return true;
 }
 }
 
 

+ 8 - 0
src/lib/cache/rrset_cache.h

@@ -65,6 +65,14 @@ public:
     /// \brief Resize the size of rrset cache in runtime. 
     /// \brief Resize the size of rrset cache in runtime. 
     bool resize(uint32_t size);
     bool resize(uint32_t size);
 
 
+protected:
+    /// \brief Get the hash key for the rrset entry in the cache.
+    /// \param name name of the rrset.
+    /// \param type type of the rrset.
+    /// \return return the hash key.
+    HashKey getEntryHashKey(const isc::dns::Name& name, 
+                            const isc::dns::RRType& type) const;
+
 private:
 private:
     uint16_t class_; // The class of the rrset cache.
     uint16_t class_; // The class of the rrset cache.
     isc::nsas::HashTable<RRsetEntry> rrset_table_;
     isc::nsas::HashTable<RRsetEntry> rrset_table_;

+ 2 - 3
src/lib/cache/rrset_entry.cc

@@ -30,18 +30,17 @@ RRsetEntry::RRsetEntry(const isc::dns::RRset&,
 }
 }
 
 
 void
 void
-RRsetEntry::generateRRset(isc::dns::RRset&) const {
+RRsetEntry::genRRset(isc::dns::RRset&) const {
 }
 }
 
 
 time_t
 time_t
-RRsetEntry::getExpirationTime() const {
+RRsetEntry::getExpireTime() const {
     return expire_time_;
     return expire_time_;
 }
 }
 
 
 HashKey
 HashKey
 RRsetEntry::hashKey() const {
 RRsetEntry::hashKey() const {
     CacheEntryKey keydata = genCacheEntryKey(name_, type_);
     CacheEntryKey keydata = genCacheEntryKey(name_, type_);
-    // as the parameters.
     return HashKey(keydata.first, keydata.second, RRClass(class_));
     return HashKey(keydata.first, keydata.second, RRClass(class_));
 }
 }
 
 

+ 8 - 3
src/lib/cache/rrset_entry.h

@@ -27,7 +27,7 @@ using namespace isc::nsas;
 namespace isc {
 namespace isc {
 namespace cache {
 namespace cache {
 
 
-/// \brief RRset Trustworthiness
+/// \enum RRset Trustworthiness
 /// For detail of rrset trustworthiness, please refer to
 /// For detail of rrset trustworthiness, please refer to
 /// RFC2181 section5.4.1.
 /// RFC2181 section5.4.1.
 /// Bigger value is more trustworthy.
 /// Bigger value is more trustworthy.
@@ -67,10 +67,15 @@ public:
     RRsetEntry(const isc::dns::RRset& rrset, const RRsetTrustLevel& level);
     RRsetEntry(const isc::dns::RRset& rrset, const RRsetTrustLevel& level);
 
 
     /// \brief Generate one rrset according the entry information.
     /// \brief Generate one rrset according the entry information.
-    void generateRRset(isc::dns::RRset& rrset) const;
+    void genRRset(isc::dns::RRset& rrset) const;
     
     
     /// \brief Get the expiration time of the rrset.
     /// \brief Get the expiration time of the rrset.
-    time_t getExpirationTime() const;
+    time_t getExpireTime() const;
+
+    /// \brief Get the ttl of the rrset.
+    uint32_t getTTL() const {
+        return ttl_;
+    }
 
 
     /// \return return hash key
     /// \return return hash key
     virtual HashKey hashKey() const;
     virtual HashKey hashKey() const;