Browse Source

Merge branch 'trac2907'

Paul Selkirk 12 years ago
parent
commit
7e575b706d

+ 6 - 0
src/bin/auth/tests/query_unittest.cc

@@ -80,6 +80,12 @@ public:
                 return (FindResult());
         }
     }
+    virtual ConstZoneTableAccessorPtr
+    getZoneTableAccessor(const std::string&, bool) const {
+        isc_throw(isc::NotImplemented,
+                  "getZoneTableAccessor not implemented for SingletonList");
+    }
+
 private:
     DataSourceClient& client_;
 };

+ 27 - 1
src/lib/datasrc/client_list.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013  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
@@ -24,6 +24,7 @@
 #include <datasrc/memory/zone_data_loader.h>
 #include <datasrc/memory/zone_data_updater.h>
 #include <datasrc/logger.h>
+#include <datasrc/zone_table_accessor_cache.h>
 #include <dns/masterload.h>
 #include <util/memory_segment_local.h>
 
@@ -403,5 +404,30 @@ ConfigurableClientList::getStatus() const {
     return (result);
 }
 
+ConstZoneTableAccessorPtr
+ConfigurableClientList::getZoneTableAccessor(const std::string& datasrc_name,
+                                             bool use_cache) const
+{
+    if (!use_cache) {
+        isc_throw(isc::NotImplemented,
+              "getZoneTableAccessor only implemented for cache");
+    }
+
+    // Find the matching data source
+    BOOST_FOREACH(const DataSourceInfo& info, data_sources_) {
+        if (!datasrc_name.empty() && datasrc_name != info.name_) {
+            continue;
+        }
+
+        const internal::CacheConfig* config(info.getCacheConfig());
+        // If caching is disabled for the named data source, this will
+        // return an accessor to an effectivley empty table.
+        return (ConstZoneTableAccessorPtr
+                (new internal::ZoneTableAccessorCache(*config)));
+    }
+
+    return (ConstZoneTableAccessorPtr());
+}
+
 }
 }

+ 35 - 3
src/lib/datasrc/client_list.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013  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
@@ -22,6 +22,7 @@
 #include <cc/data.h>
 #include <exceptions/exceptions.h>
 #include "memory/zone_table_segment.h"
+#include <datasrc/zone_table_accessor.h>
 
 #include <vector>
 #include <boost/shared_ptr.hpp>
@@ -120,6 +121,8 @@ private:
     MemorySegmentState state_;
 };
 
+typedef boost::shared_ptr<const ZoneTableAccessor> ConstZoneTableAccessorPtr;
+
 /// \brief The list of data source clients.
 ///
 /// The purpose of this class is to hold several data source clients and search
@@ -281,6 +284,19 @@ public:
     virtual FindResult find(const dns::Name& zone,
                             bool want_exact_match = false,
                             bool want_finder = true) const = 0;
+
+    /// \brief Creates a ZoneTableAccessor object for the specified data
+    /// source.
+    ///
+    /// \param datasrc_name If not empty, the name of the data source.
+    /// \param use_cache If true, create a zone table for in-memory cache.
+    /// \throw NotImplemented if this method is not implemented.
+    /// \return A pointer to the accessor, or NULL if the requested data
+    /// source is not found.
+    virtual ConstZoneTableAccessorPtr
+    getZoneTableAccessor(const std::string& datasrc_name,
+                         bool use_cache) const = 0;
+
 };
 
 /// \brief Shared pointer to the list.
@@ -288,8 +304,8 @@ typedef boost::shared_ptr<ClientList> ClientListPtr;
 /// \brief Shared const pointer to the list.
 typedef boost::shared_ptr<const ClientList> ConstClientListPtr;
 
-/// \Concrete implementation of the ClientList, which is constructed based on
-///     configuration.
+/// \brief Concrete implementation of the ClientList, which is constructed
+/// based on configuration.
 ///
 /// This is the implementation which is expected to be used in the servers.
 /// However, it is expected most of the code will use it as the ClientList,
@@ -490,6 +506,22 @@ public:
     /// it might be, so it is just made public (there's no real reason to
     /// hide it).
     const DataSources& getDataSources() const { return (data_sources_); }
+
+    /// \brief Creates a ZoneTableAccessor object for the specified data
+    /// source.
+    ///
+    /// \param datasrc_name If not empty, the name of the data source
+    /// \param use_cache If true, create a zone table for in-memory cache.
+    /// \note At present, the only concrete implementation of
+    /// ZoneTableAccessor is ZoneTableAccessorCache, so \c use_cache must be
+    /// true.
+    /// \throw NotImplemented if \c use_cache is false.
+    /// \return A pointer to the accessor, or NULL if the requested data
+    /// source is not found.
+    ConstZoneTableAccessorPtr
+    getZoneTableAccessor(const std::string& datasrc_name,
+                         bool use_cache) const;
+
 private:
     struct MutableResult;
     /// \brief Internal implementation of find.

+ 90 - 1
src/lib/datasrc/tests/client_list_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013  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
@@ -266,6 +266,8 @@ public:
     }
     ConfigurableClientList::CacheStatus doReload(
         const Name& origin, const string& datasrc_name = "");
+    void accessorIterate(const ConstZoneTableAccessorPtr& accessor,
+        int numZones, const string& zoneName);
 
     const RRClass rrclass_;
     shared_ptr<TestedList> list_;
@@ -1147,6 +1149,93 @@ TEST_F(ListTest, reloadByDataSourceName) {
               doReload(Name("example.org"), "test_type4"));
 }
 
+// This takes the accessor provided by getZoneTableAccessor(), iterates
+// through the table, and verifies that the expected number of zones are
+// present, as well as the named zone.
+void
+ListTest::accessorIterate(const ConstZoneTableAccessorPtr& accessor,
+                          int numZones, const string& zoneName="")
+{
+    // Confirm basic iterator behavior.
+    ASSERT_TRUE(accessor);
+    ZoneTableAccessor::IteratorPtr it = accessor->getIterator();
+    ASSERT_TRUE(it);
+    // Iterator does not guarantee ordering, so we look for the target
+    // name anywhere in the table.
+    bool found = false;
+    int i;
+    for (i = 0; !it->isLast(); ++i, it->next()) {
+	if (Name(zoneName) == it->getCurrent().origin) {
+	    found = true;
+	}
+    }
+    EXPECT_EQ(i, numZones);
+    if (numZones > 0) {
+        EXPECT_TRUE(found);
+    }
+}
+
+TEST_F(ListTest, zoneTableAccessor) {
+    // empty configuration
+    const ConstElementPtr elem(new ListElement);
+    list_->configure(elem, true);
+    // null pointer treated as false
+    EXPECT_FALSE(list_->getZoneTableAccessor("", true));
+
+    // empty list; expect it to return an empty list
+    list_->configure(config_elem_, true);
+    ConstZoneTableAccessorPtr z(list_->getZoneTableAccessor("", true));
+    accessorIterate(z, 0);
+
+    const ConstElementPtr elem2(Element::fromJSON("["
+        "{"
+        "   \"type\": \"type1\","
+        "   \"cache-enable\": true,"
+        "   \"cache-zones\": [\"example.com\"],"
+        "   \"params\": [\"example.com\"]"
+        "},"
+        "{"
+        "   \"type\": \"type2\","
+        "   \"cache-enable\": false,"
+        "   \"params\": [\"example.org\"]"
+        "},"
+        "{"
+        "   \"type\": \"type3\","
+        "   \"cache-enable\": true,"
+        "   \"cache-zones\": [\"example.net\", \"example.info\"],"
+        "   \"params\": [\"example.net\", \"example.info\"]"
+        "}]"));
+
+    // allow_cache = false
+    // ask for a non-existent zone table, expect null
+    list_->configure(elem2, false);
+    EXPECT_FALSE(list_->getZoneTableAccessor("bogus", true));
+    // ask for any zone table, expect an empty list
+    z = list_->getZoneTableAccessor("", true);
+    accessorIterate(z, 0);
+
+    // allow_cache = true, use_cache = false
+    list_->configure(elem2, true);
+    EXPECT_THROW(list_->getZoneTableAccessor("", false), isc::NotImplemented);
+    EXPECT_THROW(list_->getZoneTableAccessor("type1", false),
+                 isc::NotImplemented);
+
+    // datasrc not found, returns NULL pointer
+    EXPECT_FALSE(list_->getZoneTableAccessor("bogus", true));
+
+    // return first datasrc
+    z = list_->getZoneTableAccessor("", true);
+    accessorIterate(z, 1, "example.com");
+
+    // datasrc has cache disabled, returns accessor to empty list
+    z = list_->getZoneTableAccessor("type2", true);
+    accessorIterate(z, 0);
+
+    // search by name
+    z = list_->getZoneTableAccessor("type3", true);
+    accessorIterate(z, 2, "example.net");
+}
+
 // Check the status holds data
 TEST(DataSourceStatus, status) {
     const DataSourceStatus status("Test", SEGMENT_INUSE, "local");