Parcourir la source

Add first part of the main NameserverAddressStore class.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac356@3420 e5f2f494-b856-4b98-b285-d166d9295462
Stephen Morris il y a 14 ans
Parent
commit
d332e57dd2

+ 4 - 1
src/lib/nsas/Makefile.am

@@ -8,13 +8,16 @@ AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 lib_LTLIBRARIES = libnsas.la
 libnsas_la_SOURCES  = address_entry.h address_entry.cc
+libnsas_la_SOURCES += asiolink.h
 libnsas_la_SOURCES += hash.cc hash.h
 libnsas_la_SOURCES += hash_deleter.h
 libnsas_la_SOURCES += hash_key.cc hash_key.h
 libnsas_la_SOURCES += hash_table.h
 libnsas_la_SOURCES += lru_list.h
+libnsas_la_SOURCES += nameserver_address_store.cc nameserver_address_store.h
 libnsas_la_SOURCES += nameserver_entry.cc nameserver_entry.h
+libnsas_la_SOURCES += nsas_entry_compare.h
 libnsas_la_SOURCES += nsas_entry.h
-libnsas_la_SOURCES += asiolink.h
+libnsas_la_SOURCES += zone_entry.h
 
 CLEANFILES = *.gcno *.gcda

+ 3 - 2
src/lib/nsas/hash_deleter.h

@@ -19,6 +19,7 @@
 
 #include <boost/shared_ptr.hpp>
 #include "hash_table.h"
+#include "lru_list.h"
 
 namespace isc {
 namespace nsas {
@@ -53,7 +54,7 @@ public:
     /// Performs the deletion of the zone entry from the hash table.
     ///
     /// \param element Element to be deleted
-    virtual void operator()(boost::shared_ptr<T>& element);
+    virtual void operator()(T* element) const;
 
 private:
     HashTable<T>& hashtable_;         ///< Hash table to access element
@@ -61,7 +62,7 @@ private:
 
 // delete the object from the relevant hash table
 template <class T>
-void HashDeleter<T>::operator()(boost::shared_ptr<T>& element) {
+void HashDeleter<T>::operator()(T* element) const {
     hashtable_.remove(element->hashKey());
 }
 

+ 2 - 2
src/lib/nsas/lru_list.h

@@ -66,7 +66,7 @@ public:
         /// LRU list.
         ///
         /// \param drop Object being dropped.
-        virtual void operator()(boost::shared_ptr<T>& drop) = 0;
+        virtual void operator()(T* drop) const = 0;
     };
 
     /// \brief Constructor
@@ -171,7 +171,7 @@ void LruList<T>::add(boost::shared_ptr<T>& element) {
 
             // to-be-dropped object.
             if (dropped_) {
-                (*dropped_)(*lru_.begin());
+                (*dropped_)(lru_.begin()->get());
             }
 
             // ... and get rid of it from the list

+ 45 - 0
src/lib/nsas/nameserver_address_store.cc

@@ -0,0 +1,45 @@
+// 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 <boost/shared_ptr.hpp>
+
+#include "config.h"
+
+#include "hash_deleter.h"
+#include "nsas_entry_compare.h"
+#include "nameserver_entry.h"
+#include "nameserver_address_store.h"
+#include "zone_entry.h"
+
+namespace isc {
+namespace nsas {
+
+// Constructor.
+//
+// The LRU lists are set equal to three times the size of the respective
+// hash table, on the assumption that three elements is the longest linear
+// search we want to do when looking up names in the hash table.
+NameserverAddressStore::NameserverAddressStore(uint32_t zonehashsize,
+    uint32_t nshashsize) :
+    zone_hash_(new NsasEntryCompare<ZoneEntry>, zonehashsize),
+    nameserver_hash_(new NsasEntryCompare<NameserverEntry>, nshashsize),
+    zone_lru_((3 * zonehashsize), new HashDeleter<ZoneEntry>(zone_hash_)),
+    nameserver_lru_((3 * nshashsize), new HashDeleter<NameserverEntry>(nameserver_hash_))
+{
+}
+
+} // namespace nsas
+} // namespace isc

+ 106 - 0
src/lib/nsas/nameserver_address_store.h

@@ -0,0 +1,106 @@
+// 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$
+
+#ifndef __NAMESERVER_ADDRESS_STORE_H
+#define __NAMESERVER_ADDRESS_STORE_H
+
+#include <string>
+#include <vector>
+
+#include "rrset.h"
+
+#include "address_request_callback.h"
+#include "hash_table.h"
+#include "nameserver_entry.h"
+#include "lru_list.h"
+#include "zone_entry.h"
+
+namespace isc {
+namespace nsas {
+
+/// \brief Nameserver Address Store
+///
+/// This class implements the bare bones of the nameserver address store - the
+/// storage of nameserver information.  An additional layer above it implements
+/// the logic for sending queries for the nameserver addresses if they are not
+/// in the store.
+
+class NameserverAddressStore {
+public:
+
+    /// \brief Constructor
+    ///
+    /// The constructor sizes all the tables.  As there are various
+    /// relationships between the table sizes, and as some values are best as
+    /// prime numbers, the table sizes are determined by compile-time values.
+    /// 
+    /// \param zonehashsize Size of the zone hash table.  The default value of
+    /// 1009 is the first prime number above 1000.
+    /// \param nshash size Size of the nameserver hash table.  The default
+    /// value of 2003 is the first prime number over 2000, and by implication,
+    /// there is an assumption that there will be more nameservers than zones
+    /// in the store.
+    NameserverAddressStore(uint32_t zonehashsize = 1009,
+        uint32_t nshashsize = 3001);
+
+    /// \brief Destructor
+    ///
+    /// Empty virtual destructor.
+    virtual ~NameserverAddressStore()
+    {}
+
+    /// \brief Lookup Address for a Zone
+    ///
+    /// Looks up the address of a nameserver in the zone.
+    ///
+    /// \param zone Name of zone for which an address is required.
+    /// \param authority Authority RRset from the referral containing the
+    /// nameservers that serve the zone.
+    /// \param additional Additional RRset(s) for authority information.  These
+    /// are taken from the referral.
+    /// \param callback Callback object used to pass the result back to the
+    /// caller.
+    /* void lookup(const std::string& zone, isc::dns::AbstractRRset& authority,
+        const std::vector<isc::dns::AbstractRRset>& additional
+        boost::shared_ptr<isc::dns::AddressRequestCallback> callback ); */
+
+    /// \brief Protected Members
+    ///
+    /// These members should be private.  However, with so few public methods
+    /// and with a lot of internal processing, the testing of this class is
+    /// problematical.
+    ///
+    /// To get round this, a number of elements are declared protected.  This
+    /// means that tests can be carried out by testing a subclass.  The subclass
+    /// does not override the main class methods, but does contain additional
+    /// methods to set up data and examine the internal state of the class.
+    //@{
+protected:
+    // Zone and nameserver hash tables
+    HashTable<ZoneEntry>        zone_hash_;
+    HashTable<NameserverEntry>  nameserver_hash_;
+
+    // ... and the LRU lists
+    LruList<ZoneEntry>          zone_lru_;
+    LruList<NameserverEntry>    nameserver_lru_;
+    //}@
+};
+
+} // namespace nsas
+} // namespace isc
+
+
+#endif // __NAMESERVER_ADDRESS_STORE_H

+ 3 - 3
src/lib/nsas/nameserver_entry.h

@@ -87,9 +87,9 @@ public:
     /// \brief Constructor where no A records are supplied.
     ///
     /// \param name Name of the nameserver,
-    /// \param classCode class of the nameserver
-    NameserverEntry(const std::string& name, uint16_t classCode) :
-        name_(name), classCode_(classCode)
+    /// \param class_code class of the nameserver
+    NameserverEntry(const std::string& name, uint16_t class_code) :
+        name_(name), classCode_(class_code)
     {}
 
     /// Constructor where one or more RRsets of A/AAAA records are supplied.

+ 2 - 0
src/lib/nsas/tests/Makefile.am

@@ -23,9 +23,11 @@ run_unittests_SOURCES += hash_key_unittest.cc
 run_unittests_SOURCES += hash_table_unittest.cc
 run_unittests_SOURCES += hash_unittest.cc
 run_unittests_SOURCES += lru_list_unittest.cc
+run_unittests_SOURCES += nameserver_address_store_unittest.cc
 run_unittests_SOURCES += nameserver_entry_unittest.cc
 run_unittests_SOURCES += nsas_entry_compare_unittest.cc
 run_unittests_SOURCES += nsas_test_utilities.h 
+run_unittests_SOURCES += zone_entry_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)

+ 1 - 1
src/lib/nsas/tests/lru_list_unittest.cc

@@ -39,7 +39,7 @@ namespace nsas {
 /// MS bit on the 16-bit class value.
 class Dropped : public LruList<TestEntry>::Dropped {
 public:
-    virtual void operator()(boost::shared_ptr<TestEntry>& entry) {
+    virtual void operator()(TestEntry* entry) const {
         entry->setClass(entry->getClass() | 0x8000);
     }
 };

+ 160 - 0
src/lib/nsas/tests/nameserver_address_store_unittest.cc

@@ -0,0 +1,160 @@
+// 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$
+
+/// \brief Test Deleter Objects
+///
+/// This file contains tests for the "deleter" classes within the nameserver
+/// address store.  These act to delete zones from the zone hash table when
+/// the element reaches the top of the LRU list.
+
+#include <gtest/gtest.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <string.h>
+#include <vector>
+
+#include "nameserver_address_store.h"
+#include "nsas_entry_compare.h"
+#include "nameserver_entry.h"
+#include "zone_entry.h"
+#include "nsas_test.h"
+
+namespace isc {
+namespace nsas {
+
+
+/// \brief NSAS Store
+///
+/// This is a subclass of the NameserverAddressStore class, with methods to
+/// access the internal members to check that the deleter objects are working.
+class DerivedNsas : public NameserverAddressStore {
+public:
+    /// \brief Constructor
+    ///
+    /// \param hashsize Size of the zone hash table
+    /// \param lrusize Size of the zone hash table
+    DerivedNsas(uint32_t hashsize, uint32_t lrusize) :
+        NameserverAddressStore(hashsize, lrusize)
+    {}
+
+    /// \brief Virtual Destructor
+    virtual ~DerivedNsas()
+    {}
+
+    /// \brief Add Nameserver Entry to Hash and LRU Tables
+    void AddNameserverEntry(boost::shared_ptr<NameserverEntry>& entry) {
+        HashKey h = entry->hashKey();
+        nameserver_hash_.add(entry, h);
+        nameserver_lru_.add(entry);
+    }
+
+    /// \brief Add Zone Entry to Hash and LRU Tables
+    void AddZoneEntry(boost::shared_ptr<ZoneEntry>& entry) {
+        HashKey h = entry->hashKey();
+        zone_hash_.add(entry, h);
+        zone_lru_.add(entry);
+    }
+};
+
+
+
+/// \brief Text Fixture Class
+class NameserverAddressStoreTest : public ::testing::Test {
+protected:
+
+    // Constructor - initialize a set of nameserver and zone objects.  For convenience,
+    // these are stored in vectors.
+    NameserverAddressStoreTest()
+    {
+        for (int i = 1; i <= 9; ++i) {
+            std::string name = "nameserver" + boost::lexical_cast<std::string>(i);
+            nameservers_.push_back(boost::shared_ptr<NameserverEntry>(new NameserverEntry(name, (40 + i))));
+        }
+
+        for (int i = 1; i <= 9; ++i) {
+            std::string name = "zone" + boost::lexical_cast<std::string>(i);
+            zones_.push_back(boost::shared_ptr<ZoneEntry>(new ZoneEntry(name, (40 + i))));
+        }
+    }
+
+    // Vector of pointers to nameserver and zone entries.
+    std::vector<boost::shared_ptr<NameserverEntry> > nameservers_;
+    std::vector<boost::shared_ptr<ZoneEntry> >       zones_;
+};
+
+
+/// \brief Remove Zone Entry from Hash Table
+///
+/// Check that when an entry reaches the top of the zone LRU list, it is removed from the
+/// hash table as well.
+TEST_F(NameserverAddressStoreTest, ZoneDeletionCheck) {
+
+    // Create a NSAS with a hash size of three and a LRU size of 9 (both zone and
+    // nameserver tables).
+    DerivedNsas nsas(2, 2);
+
+    // Add six entries to the tables.  After addition the reference count of each element
+    // should be 3 - one for the entry in the zones_ vector, and one each for the entries
+    // in the LRU list and hash table.
+    for (int i = 1; i <= 6; ++i) {
+        EXPECT_EQ(1, zones_[i].use_count());
+        nsas.AddZoneEntry(zones_[i]);
+        EXPECT_EQ(3, zones_[i].use_count());
+    }
+
+    // Adding another entry should cause the first one to drop off the LRU list, which
+    // should also trigger the deletion of the entry from the hash table.  This should
+    // reduce its use count to 1.
+    EXPECT_EQ(1, zones_[7].use_count());
+    nsas.AddZoneEntry(zones_[7]);
+    EXPECT_EQ(3, zones_[7].use_count());
+
+    EXPECT_EQ(1, zones_[1].use_count());
+}
+
+
+/// \brief Remove Entry from Hash Table
+///
+/// Check that when an entry reaches the top of the LRU list, it is removed from the
+/// hash table as well.
+TEST_F(NameserverAddressStoreTest, NameserverDeletionCheck) {
+
+    // Create a NSAS with a hash size of three and a LRU size of 9 (both zone and
+    // nameserver tables).
+    DerivedNsas nsas(2, 2);
+
+    // Add six entries to the tables.  After addition the reference count of each element
+    // should be 3 - one for the entry in the nameservers_ vector, and one each for the entries
+    // in the LRU list and hash table.
+    for (int i = 1; i <= 6; ++i) {
+        EXPECT_EQ(1, nameservers_[i].use_count());
+        nsas.AddNameserverEntry(nameservers_[i]);
+        EXPECT_EQ(3, nameservers_[i].use_count());
+    }
+
+    // Adding another entry should cause the first one to drop off the LRU list, which
+    // should also trigger the deletion of the entry from the hash table.  This should
+    // reduce its use count to 1.
+    EXPECT_EQ(1, nameservers_[7].use_count());
+    nsas.AddNameserverEntry(nameservers_[7]);
+    EXPECT_EQ(3, nameservers_[7].use_count());
+
+    EXPECT_EQ(1, nameservers_[1].use_count());
+}
+
+} // namespace nsas
+} // namespace isc

+ 52 - 0
src/lib/nsas/tests/zone_entry_unittest.cc

@@ -0,0 +1,52 @@
+// 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 <gtest/gtest.h>
+
+#include "rrclass.h"
+
+#include "asiolink.h"
+#include "zone_entry.h"
+
+#include "nsas_test.h"
+
+using namespace asiolink;
+using namespace std;
+using namespace isc::dns;
+
+namespace isc {
+namespace nsas {
+
+// String constants.  These should end in a dot.
+static const std::string EXAMPLE_CO_UK("example.co.uk.");
+
+/// \brief Test Fixture Class
+class ZoneEntryTest : public ::testing::Test {
+protected:
+
+};
+
+/// Tests of the default constructor
+TEST_F(ZoneEntryTest, DefaultConstructor) {
+
+    // Default constructor should not create any RRsets
+    ZoneEntry alpha(EXAMPLE_CO_UK, RRClass::IN().getCode());
+    EXPECT_EQ(EXAMPLE_CO_UK, alpha.getName());
+    EXPECT_EQ(RRClass::IN().getCode(), alpha.getClass());
+}
+
+}   // namespace nsas
+}   // namespace isc

+ 43 - 9
src/lib/nsas/zone_entry.h

@@ -19,12 +19,18 @@
 
 #include <string>
 #include <vector>
-#include <boost/thread.h>
-#include <boost/shared_ptr.h>
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
 
+#include "rrset.h"
+
+#include "hash_key.h"
 #include "nsas_entry.h"
 #include "asiolink.h"
 
+namespace isc {
+namespace nsas {
+
 class NameserverEntry;
 
 /// \brief Zone Entry
@@ -39,27 +45,55 @@ class NameserverEntry;
 class ZoneEntry : public NsasEntry<ZoneEntry> {
 public:
 
+    /// \brief Constructor where no NS records are supplied
+    ///
+    /// \param name Name of the zone
+    /// \param class_code Class of this zone (zones of different classes have
+    /// different objects.
+    ZoneEntry(const std::string& name, uint16_t class_code) :
+        name_(name), classCode_(class_code)
+    {}
+
     /// \brief Constructor
     ///
     /// Creates a zone entry object with an RRset representing the nameservers,
     /// plus possibly additional RRsets holding address information.
-    ZoneEntry(AbstractRRset* nsrrset,
-            const std::vector<AbstractRRSet*>& additional);
+    //ZoneEntry(isc::dns::AbstractRRset* nsrrset,
+    //       const std::vector<isc::dns::AbstractRRset*>& additional);
+
+    /// \brief Destructor
+    virtual ~ZoneEntry()
+    {}
+
+    /// \return Name of the zone
+    virtual std::string getName() const {
+        return name_;
+    }
+
+    /// \return Class of zone
+    virtual short getClass() const {
+        return classCode_;
+    }
+
+    /// \return Return Hash Key
+    virtual HashKey hashKey() const {
+        return HashKey(name_, classCode_);
+    }
 
     /// \brief Lookup Address
     ///
     /// Returns the address with the lowest RTT.
-    asiolink::IOAddress getAddress() const;
-
-public:
-    void updateNS
+    //virtual asiolink::IOAddress getAddress() const;
 
 private:
     boost::mutex    mutex_;     ///< Mutex protecting this zone entry
     std::string     name_;      ///< Canonical zone name
-    short           classCode_; ///< Class code
+    uint16_t        classCode_; ///< Class code
     std::vector<boost::shared_ptr<NameserverEntry> > nameservers_; ///< Nameservers
     time_t          expiry_;    ///< Expiry time of this entry
 };
+
+} // namespace nsas
+} // namespace isc
  
 #endif // __ZONE_ENTRY_H