Parcourir la source

Add the implementaion for class recursor cache

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac449@4157 e5f2f494-b856-4b98-b285-d166d9295462
Likun Zhang il y a 14 ans
Parent
commit
886b10843e

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

@@ -43,13 +43,14 @@ MessageEntry::genMessage(const time_t&,
                          const uint16_t,
                          isc::dns::Message&)
 {
+    //TODO
     return true;
 }
 
 RRsetTrustLevel
 MessageEntry::getRRsetTrustLevel(const Message& message,
-                   const RRset&,
-                   const Message::Section& section) 
+                   const isc::dns::RRset&,
+                   const isc::dns::Message::Section& section) 
 {
     bool aa = message.getHeaderFlag(Message::HEADERFLAG_AA);
     switch(section) {

+ 115 - 31
src/lib/cache/recursor_cache.cc

@@ -15,64 +15,148 @@
 // $Id$
 
 #include "recursor_cache.h"
+#include "dns/message.h"
+#include "rrset_cache.h"
+#include <string>
 
+using namespace isc::dns;
+using namespace std; 
 
 namespace isc {
 namespace cache {
 
-RecursorCache::RecursorCache() {
+RecursorCache::RecursorCache(std::vector<uint16_t> dns_classes) {
+    uint32_t index = 0;
+    uint32_t size = dns_classes.size();
+    for (; index < size; index++) {
+        uint16_t klass = dns_classes[index];
+        rrsets_cache1_[klass] = RRsetCachePtr(new 
+                                RRsetCache(RRSET_CACHE1_DEFAULT_SIZE, klass));
+        rrsets_cache2_[klass] = RRsetCachePtr(new 
+                                RRsetCache(RRSET_CACHE2_DEFAULT_SIZE, klass));
+        messages_cache_[klass] = MessageCachePtr(new MessageCache(rrsets_cache2_[klass], 
+                                                      MESSAGE_CACHE_DEFAULT_SIZE, 
+                                                      klass));
+    }
 }
 
 bool
-RecursorCache::lookUp(const isc::dns::Name& qname, 
+RecursorCache::lookup(const isc::dns::Name& qname, 
                const isc::dns::RRType& qtype,
                const isc::dns::RRClass& qclass,
-               isc::dns::Message& response)
+               const uint16_t query_header,
+               isc::dns::Message& response) const
 {
-    //TODO, temp code begin
-    qname.toText();
-    qtype.toText();
-    qclass.toText();
-    response.toText();
-    //TODO, temp code end 
-    return true;
+    // First, query in rrsets_cache1_, if the rrset(qname, qtype, qclass) can be 
+    // found in rrsets_cache1_, generated reply message with only the rrset in 
+    // answer section.
+    RRsetCacheMap::const_iterator cache_iter = rrsets_cache1_.find(qclass.getCode());
+    if (cache_iter != rrsets_cache1_.end()) {
+        RRsetEntryPtr rrset_entry = cache_iter->second->lookup(qname, qtype);
+        if (rrset_entry) {
+            boost::shared_ptr<isc::dns::RRset> rrset_ptr = rrset_entry->genRRset();
+            response.addRRset(Message::SECTION_ANSWER, rrset_ptr);
+        }
+    }
+
+    // Search in class-specific message cache.
+    MessageCacheMap::const_iterator iter = messages_cache_.find(qclass.getCode());
+    if (iter == messages_cache_.end()) {
+        // Can't find the class-specific message cache, return false.
+        return false;
+    } else {
+        return iter->second->lookup(qname, qtype, query_header, response);
+    }
 }
 
-bool
-RecursorCache::lookUp(const isc::dns::Name& qname, 
+isc::dns::RRsetPtr
+RecursorCache::lookup_in_rrset_cache(const isc::dns::Name& qname, 
+                      const isc::dns::RRType& qtype,
+                      const isc::dns::RRClass& qclass,
+                      const RRsetCacheMap& rrsets_cache) const
+{
+    RRsetCacheMap::const_iterator cache_iter = rrsets_cache.find(qclass.getCode());
+    if (cache_iter != rrsets_cache.end()) {
+        RRsetEntryPtr rrset_entry = cache_iter->second->lookup(qname, qtype);
+        if (rrset_entry) {
+            return rrset_entry->genRRset();
+        }
+    }
+
+    // Can't find the rrset in specified rrset cache, return NULL.
+    return RRsetPtr();
+}
+
+isc::dns::RRsetPtr
+RecursorCache::lookup(const isc::dns::Name& qname, 
                const isc::dns::RRType& qtype,
-               const isc::dns::RRClass& qclass,
-               isc::dns::RRset& rrset)
+               const isc::dns::RRClass& qclass) const
 {
-    //TODO, temp code begin
-    qname.toText();
-    qtype.toText();
-    qclass.toText();
-    rrset.toText();
-    //TODO, temp code end 
-    return true;
+    // Algorithm:
+    // 1. Search in rrsets_cache1_ first, 
+    // 2. Then do search in rrsets_cache2_.
+    RRsetPtr rrset_ptr = lookup_in_rrset_cache(qname, qtype, qclass, rrsets_cache1_);
+    if (rrset_ptr) {
+        return rrset_ptr;
+    } else {
+        rrset_ptr = lookup_in_rrset_cache(qname, qtype, qclass, rrsets_cache2_);
+    }
+
+    return rrset_ptr;
 }
 
-void
+bool
 RecursorCache::update(const isc::dns::Message& msg) {
-    msg.toText();
-    return;
+    QuestionIterator iter = msg.beginQuestion();
+    MessageCacheMap::iterator cache_iter = messages_cache_.find((*iter)->getClass().getCode());
+    if (cache_iter == messages_cache_.end()) {
+        // The message is not allowed to cached.
+        return false;
+    } else {
+        return cache_iter->second->update(msg);
+    }
 }
 
-void
+bool
+RecursorCache::updateRRsetCache(const isc::dns::RRset& rrset,
+                                RRsetCacheMap& rrset_cache_map) 
+{
+    uint16_t klass = rrset.getClass().getCode();
+    RRsetCacheMap::iterator cache_iter = rrset_cache_map.find(klass);
+    if (cache_iter == rrset_cache_map.end()) {
+        // The rrset is not allowed to be cached.
+        return false;
+    } else {
+        RRsetTrustLevel level;
+        string typestr = rrset.getType().toText();
+        if (typestr == "A" || typestr == "AAAA") {
+            level = RRSET_TRUST_PRIM_GLUE;
+        } else {
+            level = RRSET_TRUST_PRIM_ZONE_NONGLUE;
+        }
+
+        cache_iter->second->update(rrset, level);
+    }
+    return true;
+}
+
+bool
 RecursorCache::update(const isc::dns::RRset& rrset) {
-    rrset.toText();
-    return;
+    if (!updateRRsetCache(rrset, rrsets_cache1_)) {
+        return false;
+    }
+
+    return updateRRsetCache(rrset, rrsets_cache2_);
 }
 
 void
-RecursorCache::dump(const std::string& file_name) {
-    std::cout << file_name;
+RecursorCache::dump(const std::string&) {
+    //TODO
 }
 
 void
-RecursorCache::load(const std::string& file_name) {
-    std::cout << file_name;
+RecursorCache::load(const std::string&) {
+    //TODO
 }
 
 } // namespace cache

+ 55 - 17
src/lib/cache/recursor_cache.h

@@ -23,11 +23,20 @@
 #include <dns/message.h>
 #include "message_cache.h"
 
-
 namespace isc {
 namespace cache {
 class RRsetCache;
 
+typedef boost::shared_ptr<MessageCache> MessageCachePtr;
+typedef boost::shared_ptr<RRsetCache> RRsetCachePtr;
+typedef std::map<uint16_t, MessageCachePtr> MessageCacheMap;
+typedef std::map<uint16_t, RRsetCachePtr> RRsetCacheMap;
+
+//TODO a better proper default cache size
+#define MESSAGE_CACHE_DEFAULT_SIZE 1000000 
+#define RRSET_CACHE1_DEFAULT_SIZE  1000
+#define RRSET_CACHE2_DEFAULT_SIZE  10000
+
 ///    
 /// \brief Recursor Cache
 /// The object of RecursorCache represents the cache of the recursor. It holds
@@ -35,7 +44,9 @@ class RRsetCache;
 ///
 class RecursorCache {
 public:
-    RecursorCache();
+    /// \brief Construct Function
+    /// \param dns_classes cache the messages/rrsets for these classes.
+    RecursorCache(std::vector<uint16_t> dns_classes);
 
     /// \name Lookup Interfaces
     //@{
@@ -43,35 +54,42 @@ public:
     ///
     /// \param response generated response message if the message can be found 
     ///  in cache.
+    /// \param query_header the 16bit query header.
     ///
     /// \return return true if the message can be found, or else, return false.
-    bool lookUp(const isc::dns::Name& qname, 
+    bool lookup(const isc::dns::Name& qname, 
                 const isc::dns::RRType& qtype,
                 const isc::dns::RRClass& qclass,
-                isc::dns::Message& response);
+                const uint16_t query_header,
+                isc::dns::Message& response) const;
 
     /// \brief Look up rrset in cache.
-    /// \param rrset generated rrset if it can be found in the cache.
-    /// \return return true if the rrset can be found, or else, return false.
+    /// \return return the shared_ptr of rrset if it can be found, 
+    /// or else, return NULL. When looking up, cache1(localzone) will 
+    /// be searched first, if not found, then search in cache2.
     ///
     /// \overload
     ///
-    bool lookUp(const isc::dns::Name& qname, 
-                const isc::dns::RRType& qtype,
-                const isc::dns::RRClass& qclass,
-                isc::dns::RRset& rrset);
+    isc::dns::RRsetPtr lookup(const isc::dns::Name& qname, 
+                              const isc::dns::RRType& qtype,
+                              const isc::dns::RRClass& qclass) const;
     //@}
 
     /// \brief Update the message in the cache with the new one.
-    void update(const isc::dns::Message& msg);
+    /// \return return true if the message is updated into the cache,
+    /// or else, return false.
+    bool update(const isc::dns::Message& msg);
 
     /// \brief Update the rrset in the cache with the new one.
-    /// rrset_cache1_ and rrset_cache2_ should be updated together
-    /// if the rrset exists in both of them.
+    /// rrset_cache1_ and rrset_cache2_ should be updated together.
+    /// If the rrset doesn't exist in both of them, then the rrset
+    /// will be added into both of them.
+    /// \return return false, if the class of the parameter rrset is
+    /// allowed to be cached.
     ///
     /// \overload 
     ///
-    void update(const isc::dns::RRset& rrset);
+    bool update(const isc::dns::RRset& rrset);
 
     /// \name Cache Serialization
     //@{
@@ -84,21 +102,41 @@ public:
     void load(const std::string& file_name);
     //@}
 
+protected:    
+    /// \brief Look up rrset in one specified rrset cache.
+    /// This function is used internally by lookup()
+    /// \param rrsets_cache the cache for looking up rrset.
+    /// \return return the shared_ptr of the rrset if it can be
+    /// found in the cache.
+    isc::dns::RRsetPtr lookup_in_rrset_cache(const isc::dns::Name& qname, 
+                      const isc::dns::RRType& qtype,
+                      const isc::dns::RRClass& qclass,
+                      const RRsetCacheMap& rrsets_cache) const;
+
+    /// \brief Update the rrset in one rrset cache.
+    /// \return return true if the rrset is updated in the rrset cache,
+    /// or else return false.
+    /// \param rrset_cache_map the map of rrset cache, the rrset cache needs
+    /// to be updated should be found first according the class of the rrset.
+    /// If the class-specific rrset cache can't be found in the map, it returns
+    /// false.
+    bool updateRRsetCache(const isc::dns::RRset& rrset,
+                          RRsetCacheMap& rrset_cache_map);
 protected:
 
     /// \brief the list of message cache for configured classes(message cache
     /// is class-specific)
-    std::map<uint16_t, MessageCache*> messages_cache_;
+    MessageCacheMap messages_cache_;
     
     /// \name rrset caches
     //@{
     /// \brief the list of rrset cache for configured classes.
     /// rrsets_cache1_ is used to cache the configured rrsets in localzone, rrsets 
     /// in it will never expire.
-    std::map<uint16_t, RRsetCache*> rrsets_cache1_;
+    RRsetCacheMap rrsets_cache1_;
 
     /// \brief cache the rrsets parsed from the received message.
-    std::map<uint16_t, RRsetCache*> rrsets_cache2_;
+    RRsetCacheMap rrsets_cache2_;
     //@}
 };
 

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

@@ -26,11 +26,12 @@ using namespace isc::dns;
 namespace isc {
 namespace cache {
 
-RRsetCache::RRsetCache(uint32_t cache_size):
+RRsetCache::RRsetCache(uint32_t cache_size,
+                       uint16_t rrset_class):
+    class_(rrset_class),
     rrset_table_(new NsasEntryCompare<RRsetEntry>, cache_size),
     rrset_lru_((3 * cache_size),
                   new HashDeleter<RRsetEntry>(rrset_table_))
-
 {
 }
 

+ 3 - 1
src/lib/cache/rrset_cache.h

@@ -33,7 +33,9 @@ class RRsetEntry;
 /// RRsets.
 class RRsetCache{
 public:
-    RRsetCache(uint32_t cache_size);
+    /// \param cache_size the size of rrset cache.
+    /// \param rrset_class the class of rrset cache.
+    RRsetCache(uint32_t cache_size, uint16_t rrset_class);
     
     /// \brief Look up rrset in cache.
     /// \return return the shared_ptr of rrset entry if it can 

+ 1 - 1
src/lib/cache/rrset_entry.cc

@@ -29,7 +29,7 @@ RRsetEntry::RRsetEntry(const isc::dns::RRset&,
 {
 }
 
-boost::shared_ptr<isc::dns::RRset>
+isc::dns::RRsetPtr
 RRsetEntry::genRRset() const {
     return boost::shared_ptr<isc::dns::RRset> ();
 }

+ 4 - 2
src/lib/cache/rrset_entry.h

@@ -47,13 +47,15 @@ enum RRsetTrustLevel {
     RRSET_TRUST_NONAUTH_ANSWER_AA,
     // Data from the answer section of a non-authoritative answer.
     RRSET_TRUST_ANSWER_NONAA,
+    // Glue from a primary zone, or glue from a zone transfer.
+    RRSET_TRUST_PRIM_GLUE,
     // Data from the authority section of an authoritative answer.
     RRSET_TRUST_AUTHORITY_AA, 
     // Authoritative data included in the answer section of 
     // an authoritative reply.
     RRSET_TRUST_ANSWER_AA,
     // Data from a primary zone file, other than glue data.
-    RRSET_TRUST_PRIM_ZONE_NONGLUE, ///< RRSET_TRUST_DEFAULT
+    RRSET_TRUST_PRIM_ZONE_NONGLUE
 };
 
 /// \brief RRset Entry
@@ -69,7 +71,7 @@ public:
     RRsetEntry(const isc::dns::RRset& rrset, const RRsetTrustLevel& level);
 
     /// \brief Generate one rrset according the entry information.
-    boost::shared_ptr<isc::dns::RRset> genRRset() const;
+    isc::dns::RRsetPtr genRRset() const;
     
     /// \brief Get the expiration time of the rrset.
     time_t getExpireTime() const;