Browse Source

[2851] avoid loading/reloading read only cache

JINMEI Tatuya 12 years ago
parent
commit
48c33c6c5a

+ 6 - 0
src/bin/auth/datasrc_clients_mgr.h

@@ -639,6 +639,12 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::getZoneWriter(
                   AUTH_DATASRC_CLIENTS_BUILDER_LOAD_ZONE_NOCACHE)
             .arg(origin).arg(rrclass);
         break;                  // return NULL below
+    case datasrc::ConfigurableClientList::CACHE_NOT_WRITABLE:
+        // This is an internal error. Auth server should skip reloading zones
+        // on non writable caches.
+        isc_throw(InternalCommandError, "failed to load zone " << origin
+                  << "/" << rrclass << ": internal failure, in-memory cache "
+                  "is not writable");
     case datasrc::ConfigurableClientList::CACHE_DISABLED:
         // This is an internal error. Auth server must have the cache
         // enabled.

+ 24 - 0
src/bin/auth/tests/datasrc_clients_builder_unittest.cc

@@ -532,4 +532,28 @@ TEST_F(DataSrcClientsBuilderTest, loadZoneInvalidParams) {
                  isc::data::TypeError);
 }
 
+// This works only if mapped memory segment is compiled.
+// Note also that this test case may fail as we make b10-auth more aware
+// of shared-memory cache.
+TEST_F(DataSrcClientsBuilderTest, loadInNonWritableCache) {
+    const ConstElementPtr config = Element::fromJSON(
+        "{"
+        "\"IN\": [{"
+        "   \"type\": \"MasterFiles\","
+        "   \"params\": {"
+        "       \"test1.example\": \"" +
+        std::string(TEST_DATA_BUILDDIR "/test1.zone.copied") + "\"},"
+        "   \"cache-enable\": true,"
+        "   \"cache-type\": \"mapped\""
+        "}]}");
+    clients_map = configureDataSource(config);
+
+    EXPECT_THROW(builder.handleCommand(
+                     Command(LOADZONE,
+                             Element::fromJSON(
+                                 "{\"origin\": \"test1.example\","
+                                 " \"class\": \"IN\"}"))),
+                 TestDataSrcClientsBuilder::InternalCommandError);
+}
+
 } // unnamed namespace

+ 17 - 5
src/lib/datasrc/client_list.cc

@@ -132,11 +132,20 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
                                                       cache_conf, rrclass_,
                                                       datasrc_name));
 
-            // If cache is disabled we are done for this data source.
+            // If cache is disabled, or the zone table segment is not (yet)
+            // writable,  we are done for this data source.
             // Otherwise load zones into the in-memory cache.
             if (!cache_conf->isEnabled()) {
                 continue;
             }
+            memory::ZoneTableSegment& zt_segment =
+                *new_data_sources.back().ztable_segment_;
+            if (!zt_segment.isWritable()) {
+                LOG_DEBUG(logger, DBGLVL_TRACE_BASIC,
+                          DATASRC_LIST_CACHE_PENDING).arg(datasrc_name);
+                continue;
+            }
+
             internal::CacheConfig::ConstZoneIterator end_of_zones =
                 cache_conf->end();
             for (internal::CacheConfig::ConstZoneIterator zone_it =
@@ -150,8 +159,7 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
                         cache_conf->getLoadAction(rrclass_, zname);
                     // in this loop this should be always true
                     assert(load_action);
-                    memory::ZoneWriter writer(
-                        *new_data_sources.back().ztable_segment_,
+                    memory::ZoneWriter writer(zt_segment,
                         load_action, zname, rrclass_);
                     writer.load();
                     writer.install();
@@ -318,13 +326,17 @@ ConfigurableClientList::getCachedZoneWriter(const Name& name) {
     // Find the data source from which the zone to be loaded into memory.
     // Then get the appropriate load action and create a zone writer.
     BOOST_FOREACH(const DataSourceInfo& info, data_sources_) {
-        // If there's a underlying "real" data source and it doesn't contain
+        // If there's an underlying "real" data source and it doesn't contain
         // the given name, obviously we cannot load it.
         if (info.data_src_client_ &&
             info.data_src_client_->findZone(name).code != result::SUCCESS) {
             continue;
         }
-
+        // If the corresponding zone table segment is not (yet) writable,
+        // we cannot load at this time.
+        if (info.ztable_segment_ && !info.ztable_segment_->isWritable()) {
+            return (ZoneWriterPair(CACHE_NOT_WRITABLE, ZoneWriterPtr()));
+        }
         // Note that getCacheConfig() must return non NULL in this module
         // (only tests could set it to a bogus value).
         const memory::LoadAction load_action =

+ 2 - 0
src/lib/datasrc/client_list.h

@@ -352,6 +352,8 @@ public:
                             ///  where caching is disabled for the specific
                             ///  data source).
         ZONE_NOT_FOUND,     ///< Zone does not exist in this list.
+        CACHE_NOT_WRITABLE, ///< The cache is not (yet) writable (and zones
+                            ///  zones can't be loaded)
         ZONE_SUCCESS        ///< Zone to be cached is successfully found and
                             ///  is ready to be loaded
     };

+ 7 - 0
src/lib/datasrc/datasrc_messages.mes

@@ -356,6 +356,13 @@ not contain RRs the requested type.  AN NXRRSET indication is returned.
 A debug message indicating that a query for the given name and RR type is being
 processed.
 
+% DATASRC_LIST_CACHE_PENDING in-memory cache for data source '%1' is not yet writable, pending load
+While (re)configuring data source clients, zone data of the shown data
+source cannot be loaded to in-memory cache at that point because the
+cache is not yet ready for writing.  This can happen for shared-memory
+type of cache, in which case the cache will be reset later, either
+by a higher level application or by a command from other module.
+
 % DATASRC_LIST_NOT_CACHED zones in data source %1 for class %2 not cached, cache disabled globally. Will not be available.
 The process disabled caching of RR data completely. However, this data source
 is provided from a master file and it can be served from memory cache only.

+ 20 - 0
src/lib/datasrc/tests/client_list_unittest.cc

@@ -714,6 +714,26 @@ TEST_F(ListTest, badCache) {
     checkDS(0, "test_type", "[\"example.org\"]", true);
 }
 
+TEST_F(ListTest, cacheInReadOnlySegment) {
+    // Initializing data source with read-only zone table memory segment
+    // is possible.  Loading is just postponed
+    const ConstElementPtr elem(Element::fromJSON("["
+        "{"
+        "   \"type\": \"test_type\","
+        "   \"cache-enable\": true,"
+        "   \"cache-type\": \"mapped\","
+        "   \"cache-zones\": [\"example.org\"],"
+        "   \"params\": [\"example.org\"]"
+        "}]"));
+    list_->configure(elem, true); // no disruption
+    checkDS(0, "test_type", "[\"example.org\"]", true);
+    const shared_ptr<InMemoryClient> cache(list_->getDataSources()[0].cache_);
+
+    // Likewise, reload attempt will fail.
+    EXPECT_EQ(ConfigurableClientList::CACHE_NOT_WRITABLE,
+              doReload(Name("example.org")));
+}
+
 TEST_F(ListTest, masterFiles) {
     const ConstElementPtr elem(Element::fromJSON("["
         "{"