Browse Source

[2044] Load zones into the cache

Only the ones that are requested.

This needs a lot of error handling added.
Michal 'vorner' Vaner 13 years ago
parent
commit
42b565e069
2 changed files with 86 additions and 2 deletions
  1. 21 0
      src/lib/datasrc/client_list.cc
  2. 65 2
      src/lib/datasrc/tests/client_list_unittest.cc

+ 21 - 0
src/lib/datasrc/client_list.cc

@@ -21,7 +21,9 @@
 #include <boost/foreach.hpp>
 
 using namespace isc::data;
+using namespace isc::dns;
 using namespace std;
+using namespace boost;
 
 namespace isc {
 namespace datasrc {
@@ -66,6 +68,25 @@ ConfigurableClientList::configure(const Element& config, bool allowCache) {
             // And put it into the vector
             new_data_sources.push_back(DataSourceInfo(ds.first, ds.second,
                                                       wantCache));
+            if (wantCache) {
+                const ConstElementPtr zones(dconf->get("cache-zones"));
+                const shared_ptr<InMemoryClient>
+                    cache(new_data_sources.back().cache_);
+                const DataSourceClient* const
+                    client(new_data_sources.back().data_src_client_);
+                for (size_t i(0); i < zones->size(); ++i) {
+                    const Name origin(zones->get(i)->stringValue());
+                    const DataSourceClient::FindResult
+                        zone(client->findZone(origin));
+                    // TODO check it is SUCCESS
+                    shared_ptr<InMemoryZoneFinder>
+                        finder(new
+                            InMemoryZoneFinder(zone.zone_finder->getClass(),
+                                               origin));
+                    finder->load(*client->getIterator(origin));
+                    cache->addZone(finder);
+                }
+            }
         }
         // If everything is OK up until now, we have the new configuration
         // ready. So just put it there and let the old one die when we exit

+ 65 - 2
src/lib/datasrc/tests/client_list_unittest.cc

@@ -14,9 +14,13 @@
 
 #include <datasrc/client_list.h>
 #include <datasrc/client.h>
+#include <datasrc/iterator.h>
 #include <datasrc/data_source.h>
+#include <datasrc/memory_datasrc.h>
 
 #include <dns/rrclass.h>
+#include <dns/rrttl.h>
+#include <dns/rdataclass.h>
 
 #include <gtest/gtest.h>
 
@@ -41,7 +45,7 @@ public:
         Name getOrigin() const { return (origin_); }
         // The rest is not to be called, so just have them
         RRClass getClass() const {
-            isc_throw(isc::NotImplemented, "Not implemented");
+            return (RRClass::IN());
         }
         shared_ptr<Context> find(const Name&, const RRType&,
                                  const FindOptions)
@@ -60,6 +64,35 @@ public:
     private:
         Name origin_;
     };
+    class Iterator : public ZoneIterator {
+    public:
+        Iterator(const Name& origin) :
+            origin_(origin),
+            finished_(false),
+            soa_(new RRset(origin_, RRClass::IN(), RRType::SOA(), RRTTL(3600)))
+        {
+            // The RData here is bogus, but it is not used to anything. There
+            // just needs to be some.
+            soa_->addRdata(rdata::generic::SOA(Name::ROOT_NAME(),
+                                               Name::ROOT_NAME(),
+                                               0, 0, 0, 0, 0));
+        }
+        virtual isc::dns::ConstRRsetPtr getNextRRset() {
+            if (finished_) {
+                return (ConstRRsetPtr());
+            } else {
+                finished_ = true;
+                return (soa_);
+            }
+        }
+        virtual isc::dns::ConstRRsetPtr getSOA() const {
+            return (soa_);
+        }
+    private:
+        const Name origin_;
+        bool finished_;
+        const isc::dns::RRsetPtr soa_;
+    };
     // Constructor from a list of zones.
     MockDataSourceClient(const char* zone_names[]) {
         for (const char** zone(zone_names); *zone; ++zone) {
@@ -72,7 +105,13 @@ public:
                          const ConstElementPtr& configuration) :
         type_(type),
         configuration_(configuration)
-    {}
+    {
+        if (configuration_->getType() == Element::list) {
+            for (size_t i(0); i < configuration_->size(); ++i) {
+                zones.insert(Name(configuration_->get(i)->stringValue()));
+            }
+        }
+    }
     virtual FindResult findZone(const Name& name) const {
         if (zones.empty()) {
             return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
@@ -103,6 +142,9 @@ public:
     {
         isc_throw(isc::NotImplemented, "Not implemented");
     }
+    virtual ZoneIteratorPtr getIterator(const Name& name, bool) const {
+        return (ZoneIteratorPtr(new Iterator(name)));
+    }
     const string type_;
     const ConstElementPtr configuration_;
 private:
@@ -515,4 +557,25 @@ TEST_F(ListTest, configureCacheDisabled) {
     checkDS(1, "type2", "{}", false);
 }
 
+// Put some zones into the cache
+TEST_F(ListTest, cacheZones) {
+    ConstElementPtr elem(Element::fromJSON("["
+        "{"
+        "   \"type\": \"type1\","
+        "   \"cache-enable\": true,"
+        "   \"cache-zones\": [\"example.org\", \"example.com\"],"
+        "   \"params\": [\"example.org\", \"example.com\", \"exmaple.cz\"]"
+        "}]"));
+    list_->configure(*elem, true);
+    checkDS(0, "type1", "[\"example.org\", \"example.com\", \"exmaple.cz\"]",
+            true);
+
+    const shared_ptr<InMemoryClient> cache(list_->getDataSources()[0].cache_);
+    EXPECT_EQ(2, cache->getZoneCount());
+
+    EXPECT_EQ(result::SUCCESS, cache->findZone(Name("example.org")).code);
+    EXPECT_EQ(result::SUCCESS, cache->findZone(Name("example.com")).code);
+    EXPECT_EQ(result::NOTFOUND, cache->findZone(Name("example.cz")).code);
+}
+
 }