Parcourir la source

Commit the latest change for recursor cache.

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

+ 1 - 1
src/lib/cache/Makefile.am

@@ -26,6 +26,6 @@ libcache_la_SOURCES  += message_cache.h message_cache.cc
 libcache_la_SOURCES  += message_entry.h message_entry.cc
 libcache_la_SOURCES  += rrset_cache.h rrset_cache.cc
 libcache_la_SOURCES  += rrset_entry.h rrset_entry.cc
-libcache_la_SOURCES  += cache_entry_key.h 
+libcache_la_SOURCES  += cache_entry_key.h cache_entry_key.cc
 
 CLEANFILES = *.gcno *.gcda

+ 22 - 17
src/lib/cache/cache_entry_key.h

@@ -14,30 +14,35 @@
 
 // $Id$
 
-#ifndef __CACHE_ENTRY_H
-#define __CACHE_ENTRY_H
+#ifndef __CACHE_ENTRY_KEY_H
+#define __CACHE_ENTRY_KEY_H
 
 #include <string>
-
+#include <dns/name.h>
+#include <dns/rrtype.h>
 
 namespace isc {
 namespace cache {
 
-class Name;
-class RRtype;
-
-std::pair<const char*, const uint32_t>
-genCacheEntryKey(const isc::dns::Name& qname,
-                 const isc::dns::RRType& qtype) 
-{
-    std::string keystr = qname.toText();
-    //TODO, use uint16_t rcode in case the text is too long?
-    keystr += qtype.toText(); 
-    return std::pair<const char*, const uint32_t>(keystr.c_str(), keystr.length());
-}
-    
+typedef std::pair<const char*, const uint32_t> CacheEntryKey;
+
+/// \brief Key Generation Functions
+/// Generate the hash key for message/rrset entries.
+/// The key is name(name of rrset) + type(16bits). 
+/// Note. the name is text string, not wire format.
+/// \return a pair(key_name, key_lenght) is returned
+CacheEntryKey
+genCacheEntryKey(const isc::dns::Name& name, 
+                 const isc::dns::RRType& type);
+   
+/// 
+/// \overload
+/// 
+CacheEntryKey
+genCacheEntryKey(const std::string& namestr, const uint16_t type);
+
 } // namespace cache
 } // namespace isc
 
-#endif // __CACHE_ENTRY_H
+#endif // __CACHE_ENTRY_KEY_H
 

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

@@ -43,7 +43,7 @@ MessageCache::lookup(const isc::dns::Name& qname,
                      const uint16_t query_header,
                      isc::dns::Message& response)
 {
-    std::pair<const char*, const uint32_t> keydata = genCacheEntryKey(qname, qtype);
+    CacheEntryKey keydata = genCacheEntryKey(qname, qtype);
 
     //TODO, HashKey need to be refactored, since we don't need query class
     // as the parameters.

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

@@ -18,8 +18,11 @@
 #include <nsas/nsas_entry.h>
 #include <nsas/fetchable.h>
 #include "message_entry.h"
+#include "rrset_entry.h"
 
 
+using namespace isc::dns;
+
 namespace isc {
 namespace cache {
 
@@ -39,9 +42,26 @@ MessageEntry::genMessage(const time_t&,
 }
 
 void
-MessageEntry::initMessageEntry(const isc::dns::Message&) {
-}
+MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
+    query_count_ = msg.getRRCount(Message::SECTION_QUESTION);
+    answer_count_ = msg.getRRCount(Message::SECTION_ANSWER);
+    authority_count_ = msg.getRRCount(Message::SECTION_AUTHORITY);
+    additional_count_ = msg.getRRCount(Message::SECTION_ADDITIONAL);
+
+    // 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);
 
+        // Add the rrset entry to rrset_cache or update the existed 
+        // rrset entry if the new one is more authoritative.
+    }
+
+}
 
 } // namespace cache
 } // namespace isc

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

@@ -75,12 +75,14 @@ private:
     uint16_t query_count_; // query count in query section.
     uint16_t answer_count_; // rrset count in answer section.
     uint16_t authority_count_; // rrset count in authority section.
-    uint16_t addition_count_; // rrset count in addition section.
+    uint16_t additional_count_; // rrset count in addition section.
 
     std::vector<boost::shared_ptr<RRsetEntry*> > rrsets_;
     boost::shared_ptr<RRsetCache> rrset_cache_;
 };
     
+typedef boost::shared_ptr<MessageEntry> MessageEntryPtr;
+
 } // namespace cache
 } // namespace isc
 

+ 37 - 9
src/lib/cache/rrset_cache.cc

@@ -21,6 +21,7 @@
 #include <nsas/hash_deleter.h>
 
 using namespace isc::nsas;
+using namespace isc::dns;
 
 namespace isc {
 namespace cache {
@@ -33,18 +34,45 @@ RRsetCache::RRsetCache(uint32_t cache_size):
 {
 }
     
-bool
-RRsetCache::lookUp(const isc::dns::Name&,
-       const isc::dns::RRType&,
-       const isc::dns::RRClass&,
-       RRsetEntry& )
+RRsetEntryPtr
+RRsetCache::lookup(const isc::dns::Name& qname,
+                   const isc::dns::RRType& qtype)
 {
-    return true;
+    CacheEntryKey keydata = genCacheEntryKey(qname, qtype);
+    //TODO, HashKey need to be refactored, since we don't need query class
+    // as the parameters.
+    return rrset_table_.get(HashKey(
+           keydata.first, keydata.second, RRClass(class_)));
 }
 
-bool
-RRsetCache::update(const isc::dns::RRset&) {
-    return true;
+RRsetEntryPtr
+RRsetCache::update(const isc::dns::RRset& rrset, const RRsetTrustLevel& level) {
+    // lookup first
+    RRsetEntryPtr entry_ptr = lookup(rrset.getName(), rrset.getType());
+    if(!entry_ptr) {
+        // rrset entry doesn't exist, create one rrset entry for the rrset
+        // and add it directly.
+        entry_ptr.reset(new RRsetEntry(rrset, level));
+        rrset_table_.add(entry_ptr, entry_ptr->hashKey());
+        //TODO , lru list touch.
+        return entry_ptr;
+    } else {
+        // there is one rrset entry in the cache, need to check whether
+        // the new rrset is more authoritative.
+        if (entry_ptr->getTrustLevel() > level) {
+            // existed rrset entry is more authoritative, do nothing,
+            // just return it.
+            //TODO, lru list touch
+            return entry_ptr;
+        } else {
+            HashKey key = entry_ptr->hashKey();
+            rrset_table_.remove(key);
+            entry_ptr.reset(new RRsetEntry(rrset, level));
+            //TODO, lru list touch.
+            rrset_table_.add(entry_ptr, key);
+            return entry_ptr;
+        }
+    }
 }
 
 void

+ 16 - 12
src/lib/cache/rrset_cache.h

@@ -36,19 +36,23 @@ public:
     RRsetCache(uint32_t cache_size);
     
     /// \brief Look up rrset in cache.
-    /// \param msg_entry
-    /// \return return true if the message can be found in cache, or else,
-    /// return false.
-    bool lookUp(const isc::dns::Name& qname,
-                const isc::dns::RRType& qtype,
-                const isc::dns::RRClass& qclass,
-                RRsetEntry& rrset_entry);
+    /// \return return the shared_ptr of rrset entry if it can 
+    /// found in the cache, or else, return NULL.
+    RRsetEntryPtr lookup(const isc::dns::Name& qname,
+                         const isc::dns::RRType& qtype);
 
-    /// \brief Update the rrset in the cache with the new one.
-    /// If the rrset doesn't exist in the cache, it will be added
-    /// directly. It may be ingored if the new rrset is not more
-    /// authoritative than the old rrset in cache.
-    bool update(const isc::dns::RRset& rrset);
+    /// \brief Update RRset Cache
+    /// Update the rrset entry in the cache with the new one.
+    /// If the rrset has expired or doesn't exist in the cache, 
+    /// it will be added directly. It may be ingored if the new 
+    /// rrset is not more authoritative than the old rrset in cache.
+    /// 
+    /// \param rrset The new rrset used to update cache.
+    /// \param level trustworthiness of the rrset.
+    /// \return return the rrset entry in the cache, it may be the 
+    /// new added rrset entry or existed one if it is not replaced.
+    RRsetEntryPtr update(const isc::dns::RRset& rrset,
+                         const RRsetTrustLevel& level);
 
     /// \brief Dump the rrset cache to specified file.
     /// \todo It should can be dumped to one configured database.

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

@@ -19,11 +19,14 @@
 #include <nsas/fetchable.h>
 #include "rrset_entry.h"
 
+using namespace isc::dns;
 
 namespace isc {
 namespace cache {
 
-RRsetEntry::RRsetEntry() {
+RRsetEntry::RRsetEntry(const isc::dns::RRset&, 
+    const RRsetTrustLevel& level):trust_level_(level)
+{
 }
 
 void
@@ -35,6 +38,13 @@ RRsetEntry::getExpirationTime() const {
     return expire_time_;
 }
 
+HashKey
+RRsetEntry::hashKey() const {
+    CacheEntryKey keydata = genCacheEntryKey(name_, type_);
+    // as the parameters.
+    return HashKey(keydata.first, keydata.second, RRClass(class_));
+}
+
 } // namespace cache
 } // namespace isc
 

+ 53 - 6
src/lib/cache/rrset_entry.h

@@ -20,18 +20,51 @@
 #include <dns/message.h>
 #include <nsas/nsas_entry.h>
 #include <nsas/fetchable.h>
-
+#include "cache_entry_key.h"
 
 using namespace isc::nsas;
 
 namespace isc {
 namespace cache {
 
+/// \brief RRset Trustworthiness
+/// For detail of rrset trustworthiness, please refer to
+/// RFC2181 section5.4.1.
+/// Bigger value is more trustworthy.
+enum RRsetTrustLevel {
+    // Default trust for rrset. 
+    RRSET_TRUST_DEFAULT = 0,
+    // Additional information from non-authoritative answer.
+    RRSET_TRUST_ADDITIONAL_NONAA,
+    // Data from the authority section of a non-authoritative answer
+    RRSET_TRUST_AUTHORITY_NONAA,
+    // Additional information from an authoritative answer.
+    RRSET_TRUST_ADDITIONAL_AA,
+    // Non-authoritative data from the answer section of authoritative
+    // answers
+    RRSET_TRUST_NONAUTH_ANSWER_AA,
+    // Data from the answer section of a non-authoritative answer.
+    RRSET_TRUST_ANSWER_NONAA,
+    // 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
+};
+
+/// \brief RRset Entry
+/// The object of RRsetEntry represents one cached rrset.
+/// Each rrset entry may be refered using shared_ptr by several message 
+/// entries.
 class RRsetEntry : public NsasEntry<RRsetEntry>, 
                    public Fetchable 
 {
 public:
-    RRsetEntry();
+    /// \param rrset The rrset used to initialize the rrset entry.
+    /// \param level trustworthiness of the rrset.
+    RRsetEntry(const isc::dns::RRset& rrset, const RRsetTrustLevel& level);
 
     /// \brief Generate one rrset according the entry information.
     void generateRRset(isc::dns::RRset& rrset) const;
@@ -39,16 +72,30 @@ public:
     /// \brief Get the expiration time of the rrset.
     time_t getExpirationTime() const;
 
+    /// \return return hash key
+    virtual HashKey hashKey() const;
+
+    /// \brief get rrset trustworthiness
+    RRsetTrustLevel getTrustLevel() const {
+        return trust_level_;
+    }
+
 private:
-    time_t expire_time_; // Expiration time of rrset.
-    uint32_t ttl_;
-    uint16_t class_;
+    std::string name_; // rrset name.
+    uint16_t type_; // rrset type.
+    uint16_t class_; // rrset class.
+
+    uint32_t ttl_; // ttl of rrset
     uint32_t rr_count;
     uint32_t rrsig_count;
+
+    time_t expire_time_; // Expiration time of rrset.
+    RRsetTrustLevel trust_level_; // rrset trustworthiness.
     // sec_status;
-    // trust_level; trust or not.
 };
     
+typedef boost::shared_ptr<RRsetEntry> RRsetEntryPtr;    
+
 } // namespace cache
 } // namespace isc
 

+ 1 - 0
src/lib/cache/tests/Makefile.am

@@ -28,6 +28,7 @@ TESTS =
 if HAVE_GTEST
 TESTS += run_unittests
 run_unittests_SOURCES  = run_unittests.cc
+run_unittests_SOURCES  += rrset_entry_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)

+ 49 - 0
src/lib/cache/tests/rrset_entry_unittest.cc

@@ -0,0 +1,49 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+#include <config.h>
+#include <string>
+#include <gtest/gtest.h>
+#include "../cache_entry_key.h"
+
+using namespace isc::cache;
+using namespace isc::dns;
+using namespace std;
+
+namespace {
+class GenCacheKeyTest: public testing::Test {
+};
+
+TEST_F(GenCacheKeyTest, genCacheEntryKey1) {
+    string name = "example.com.";
+    uint16_t type = 12;
+    string name_type = "example.com.12";
+
+    pair<const char*, const int32_t> key =  genCacheEntryKey(name, type);
+    EXPECT_EQ(name_type, string(key.first));
+    EXPECT_EQ(name_type.length(), key.second);
+}
+
+TEST_F(GenCacheKeyTest, genCacheEntryKey2) {
+    Name name("example.com");
+    RRType type(1234);
+    string keystr = "example.com.1234";
+    pair<const char*, const int32_t> key = genCacheEntryKey(name, type);
+    EXPECT_EQ(keystr, string(key.first));
+    EXPECT_EQ(keystr.length(), key.second);
+}
+
+}   // namespace
+