From d9c3c7e6f0692319ae7ef5e52bc47e76360d17d9 Mon Sep 17 00:00:00 2001 From: markrmiller Date: Fri, 1 Apr 2016 15:51:27 -0400 Subject: [PATCH] SOLR-8855: The HDFS BlockDirectory should not clean up it's cache on shutdown. --- solr/CHANGES.txt | 2 ++ .../solr/core/CachingDirectoryFactory.java | 20 +++++-------- .../apache/solr/core/DirectoryFactory.java | 6 ++++ .../solr/core/HdfsDirectoryFactory.java | 1 + .../solr/core/ShutdownAwareDirectory.java | 30 +++++++++++++++++++ .../java/org/apache/solr/core/SolrCore.java | 4 +++ .../solr/store/blockcache/BlockDirectory.java | 10 ++++++- 7 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/core/ShutdownAwareDirectory.java diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 2aba27db6f7..17e949a9357 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -70,6 +70,8 @@ Bug Fixes * SOLR-8902: Make sure ReturnFields only returns the requested fields from (fl=) evn when DocumentTransformers ask for getExtraRequestFields() (ryan) +* SOLR-8855: The HDFS BlockDirectory should not clean up it's cache on shutdown. (Mark Miller) + Optimizations ---------------------- * SOLR-8722: Don't force a full ZkStateReader refresh on every Overseer operation. diff --git a/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java index f7877c47c39..11cf479fc9d 100644 --- a/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java +++ b/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java @@ -25,27 +25,17 @@ import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.store.Directory; -import org.apache.lucene.store.IOContext.Context; import org.apache.lucene.store.LockFactory; -import org.apache.lucene.store.NRTCachingDirectory; -import org.apache.lucene.store.NativeFSLockFactory; -import org.apache.lucene.store.NoLockFactory; -import org.apache.lucene.store.SimpleFSLockFactory; -import org.apache.lucene.store.SingleInstanceLockFactory; import org.apache.lucene.util.IOUtils; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.ObjectReleaseTracker; -import org.apache.solr.store.blockcache.BlockDirectory; -import org.apache.solr.store.hdfs.HdfsDirectory; -import org.apache.solr.store.hdfs.HdfsLockFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -302,9 +292,15 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { } private void close(CacheValue val) { + log.info("Closing directory, CoreContainer#isShutdown={}", coreContainer != null ? coreContainer.isShutDown() : "null"); try { - log.info("Closing directory: " + val.path); - val.directory.close(); + if (coreContainer != null && coreContainer.isShutDown() && val.directory instanceof ShutdownAwareDirectory) { + log.info("Closing directory on shutdown: " + val.path); + ((ShutdownAwareDirectory) val.directory).closeOnShutdown(); + } else { + log.info("Closing directory: " + val.path); + val.directory.close(); + } assert ObjectReleaseTracker.release(val.directory); } catch (Exception e) { SolrException.log(log, "Error closing directory", e); diff --git a/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java index 99c35832ea7..8cc9e7d2073 100644 --- a/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java +++ b/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java @@ -60,6 +60,8 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin, public final static String LOCK_TYPE_SINGLE = "single"; public final static String LOCK_TYPE_NONE = "none"; public final static String LOCK_TYPE_HDFS = "hdfs"; + + protected volatile CoreContainer coreContainer; /** * Indicates a Directory will no longer be used, and when its ref count @@ -325,4 +327,8 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin, FileUtils.deleteDirectory(dirToRm); return !dirToRm.isDirectory(); } + + public void initCoreContainer(CoreContainer cc) { + this.coreContainer = cc; + } } diff --git a/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java index d22cbe3060b..9d6797a4fb8 100644 --- a/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java +++ b/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java @@ -143,6 +143,7 @@ public class HdfsDirectoryFactory extends CachingDirectoryFactory implements Sol @Override public void init(NamedList args) { + super.init(args); params = SolrParams.toSolrParams(args); this.hdfsDataDir = getConfig(HDFS_HOME, null); if (this.hdfsDataDir != null && this.hdfsDataDir.length() == 0) { diff --git a/solr/core/src/java/org/apache/solr/core/ShutdownAwareDirectory.java b/solr/core/src/java/org/apache/solr/core/ShutdownAwareDirectory.java new file mode 100644 index 00000000000..effe6775ada --- /dev/null +++ b/solr/core/src/java/org/apache/solr/core/ShutdownAwareDirectory.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.core; + +import java.io.IOException; + +import org.apache.lucene.store.Directory; + +/** + * {@link CachingDirectoryFactory} will call this method + * rather than {@link Directory#close()} on shutdown if + * a Directory implements this interface. + */ +public interface ShutdownAwareDirectory { + public void closeOnShutdown() throws IOException; +} diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index c5e54d21a0d..e511de054c8 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -125,6 +125,7 @@ import static org.apache.solr.common.params.CommonParams.PATH; * */ public final class SolrCore implements SolrInfoMBean, Closeable { + public static final String version="1.0"; private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -480,10 +481,13 @@ public final class SolrCore implements SolrInfoMBean, Closeable { if (info != null) { log.info(info.className); dirFactory = getResourceLoader().newInstance(info.className, DirectoryFactory.class); + // allow DirectoryFactory instances to access the CoreContainer + dirFactory.initCoreContainer(getCoreDescriptor().getCoreContainer()); dirFactory.init(info.initArgs); } else { log.info("solr.NRTCachingDirectoryFactory"); dirFactory = new NRTCachingDirectoryFactory(); + dirFactory.initCoreContainer(getCoreDescriptor().getCoreContainer()); } return dirFactory; } diff --git a/solr/core/src/java/org/apache/solr/store/blockcache/BlockDirectory.java b/solr/core/src/java/org/apache/solr/store/blockcache/BlockDirectory.java index d26bc44a8e4..209d6d157ae 100644 --- a/solr/core/src/java/org/apache/solr/store/blockcache/BlockDirectory.java +++ b/solr/core/src/java/org/apache/solr/store/blockcache/BlockDirectory.java @@ -29,6 +29,7 @@ import org.apache.lucene.store.FilterDirectory; import org.apache.lucene.store.IOContext; import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; +import org.apache.solr.core.ShutdownAwareDirectory; import org.apache.solr.store.hdfs.HdfsDirectory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +37,7 @@ import org.slf4j.LoggerFactory; /** * @lucene.experimental */ -public class BlockDirectory extends FilterDirectory { +public class BlockDirectory extends FilterDirectory implements ShutdownAwareDirectory { private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); public static final long BLOCK_SHIFT = 13; // 2^13 = 8,192 bytes per block @@ -234,6 +235,13 @@ public class BlockDirectory extends FilterDirectory { } } + @Override + public void closeOnShutdown() throws IOException { + LOG.info("BlockDirectory closing on shutdown"); + // we are shutting down, no need to clean up cache + super.close(); + } + @Override public void close() throws IOException { try {