diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index a01c16e7ab1..9e3f3513b11 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -167,7 +167,9 @@ Bug Fixes * SOLR-12933: Fix SolrCloud distributed commit. (Mark Miller) -* SOLR-13014: URI Too Long with large streaming expressions in SolrJ (janhoy) +* SOLR-13014: URI Too Long with large streaming expressions in SolrJ (janhoy) + +* SOLR-13066: A failure while reloading a SolrCore can result in the SolrCore not being closed. (Mark Miller) Improvements ---------------------- diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java index 3051dbfef55..357949000f0 100644 --- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java +++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java @@ -32,6 +32,7 @@ import static org.apache.solr.common.params.CommonParams.ZK_STATUS_PATH; import static org.apache.solr.core.CorePropertiesLocator.PROPERTIES_FILENAME; import static org.apache.solr.security.AuthenticationPlugin.AUTHENTICATION_PLUGIN_PROP; +import java.io.Closeable; import java.io.IOException; import java.lang.invoke.MethodHandles; import java.nio.file.Path; @@ -1432,6 +1433,7 @@ public class CoreContainer { if (isShutDown) { throw new AlreadyClosedException(); } + SolrCore newCore = null; SolrCore core = solrCores.getCoreFromAnyList(name, false); if (core != null) { @@ -1439,34 +1441,41 @@ public class CoreContainer { // CoreDescriptor and we need to reload it from the disk files CoreDescriptor cd = reloadCoreDescriptor(core.getCoreDescriptor()); solrCores.addCoreDescriptor(cd); + Closeable oldCore = null; + boolean success = false; try { solrCores.waitAddPendingCoreOps(cd.getName()); ConfigSet coreConfig = coreConfigService.getConfig(cd); log.info("Reloading SolrCore '{}' using configuration from {}", cd.getName(), coreConfig.getName()); - SolrCore newCore = core.reload(coreConfig); + newCore = core.reload(coreConfig); + registerCore(cd, newCore, false, false); + if (getZkController() != null) { DocCollection docCollection = getZkController().getClusterState().getCollection(cd.getCollectionName()); Replica replica = docCollection.getReplica(cd.getCloudDescriptor().getCoreNodeName()); assert replica != null; - if (replica.getType() == Replica.Type.TLOG) { //TODO: needed here? + if (replica.getType() == Replica.Type.TLOG) { // TODO: needed here? getZkController().stopReplicationFromLeader(core.getName()); if (!cd.getCloudDescriptor().isLeader()) { getZkController().startReplicationFromLeader(newCore.getName(), true); } - } else if(replica.getType() == Replica.Type.PULL) { + } else if (replica.getType() == Replica.Type.PULL) { getZkController().stopReplicationFromLeader(core.getName()); getZkController().startReplicationFromLeader(newCore.getName(), false); } } + success = true; } catch (SolrCoreState.CoreIsClosedException e) { throw e; } catch (Exception e) { - coreInitFailures.put(cd.getName(), new CoreLoadFailure(cd, e)); + coreInitFailures.put(cd.getName(), new CoreLoadFailure(cd, (Exception) e)); throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to reload core [" + cd.getName() + "]", e); - } - finally { + } finally { + if (!success && newCore != null && newCore.getOpenCount() > 0) { + IOUtils.closeQuietly(newCore); + } solrCores.removeFromPendingOps(cd.getName()); } } else { @@ -1479,7 +1488,7 @@ public class CoreContainer { solrCores.removeFromPendingOps(clf.cd.getName()); } } else { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name ); + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name); } } } 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 e66ca89f110..b64a6c65a66 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -674,7 +674,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab return core; } finally { // close the new core on any errors that have occurred. - if (!success) { + if (!success && core != null && core.getOpenCount() > 0) { IOUtils.closeQuietly(core); } } @@ -896,64 +896,64 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab public SolrCore(CoreContainer coreContainer, String name, String dataDir, SolrConfig config, IndexSchema schema, NamedList configSetProperties, CoreDescriptor coreDescriptor, UpdateHandler updateHandler, - IndexDeletionPolicyWrapper delPolicy, SolrCore prev, boolean reload) { + IndexDeletionPolicyWrapper delPolicy, SolrCore prev, boolean reload) { - this.coreContainer = coreContainer; - assert ObjectReleaseTracker.track(searcherExecutor); // ensure that in unclean shutdown tests we still close this - CoreDescriptor cd = Objects.requireNonNull(coreDescriptor, "coreDescriptor cannot be null"); - coreContainer.solrCores.addCoreDescriptor(cd); - - setName(name); - MDCLoggingContext.setCore(this); - - resourceLoader = config.getResourceLoader(); - this.solrConfig = config; - this.configSetProperties = configSetProperties; - // Initialize the metrics manager - this.coreMetricManager = initCoreMetricManager(config); - this.coreMetricManager.loadReporters(); - - if (updateHandler == null) { - directoryFactory = initDirectoryFactory(); - recoveryStrategyBuilder = initRecoveryStrategyBuilder(); - solrCoreState = new DefaultSolrCoreState(directoryFactory, recoveryStrategyBuilder); - } else { - solrCoreState = updateHandler.getSolrCoreState(); - directoryFactory = solrCoreState.getDirectoryFactory(); - recoveryStrategyBuilder = solrCoreState.getRecoveryStrategyBuilder(); - isReloaded = true; - } - - this.dataDir = initDataDir(dataDir, config, coreDescriptor); - this.ulogDir = initUpdateLogDir(coreDescriptor); - - log.info("[{}] Opening new SolrCore at [{}], dataDir=[{}]", logid, resourceLoader.getInstancePath(), this.dataDir); - - checkVersionFieldExistsInSchema(schema, coreDescriptor); - - SolrMetricManager metricManager = coreContainer.getMetricManager(); - - // initialize searcher-related metrics - initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, null); - - SolrFieldCacheBean solrFieldCacheBean = new SolrFieldCacheBean(); - // this is registered at the CONTAINER level because it's not core-specific - for now we - // also register it here for back-compat - solrFieldCacheBean.initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, "core"); - infoRegistry.put("fieldCache", solrFieldCacheBean); - - - initSchema(config, schema); - - this.maxWarmingSearchers = config.maxWarmingSearchers; - this.slowQueryThresholdMillis = config.slowQueryThresholdMillis; + this.coreContainer = coreContainer; final CountDownLatch latch = new CountDownLatch(1); try { + CoreDescriptor cd = Objects.requireNonNull(coreDescriptor, "coreDescriptor cannot be null"); + coreContainer.solrCores.addCoreDescriptor(cd); + + setName(name); + MDCLoggingContext.setCore(this); + + resourceLoader = config.getResourceLoader(); + this.solrConfig = config; + this.configSetProperties = configSetProperties; + // Initialize the metrics manager + this.coreMetricManager = initCoreMetricManager(config); + this.coreMetricManager.loadReporters(); + + if (updateHandler == null) { + directoryFactory = initDirectoryFactory(); + recoveryStrategyBuilder = initRecoveryStrategyBuilder(); + solrCoreState = new DefaultSolrCoreState(directoryFactory, recoveryStrategyBuilder); + } else { + solrCoreState = updateHandler.getSolrCoreState(); + directoryFactory = solrCoreState.getDirectoryFactory(); + recoveryStrategyBuilder = solrCoreState.getRecoveryStrategyBuilder(); + isReloaded = true; + } + + this.dataDir = initDataDir(dataDir, config, coreDescriptor); + this.ulogDir = initUpdateLogDir(coreDescriptor); + + log.info("[{}] Opening new SolrCore at [{}], dataDir=[{}]", logid, resourceLoader.getInstancePath(), + this.dataDir); + + checkVersionFieldExistsInSchema(schema, coreDescriptor); + + SolrMetricManager metricManager = coreContainer.getMetricManager(); + + // initialize searcher-related metrics + initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, null); + + SolrFieldCacheBean solrFieldCacheBean = new SolrFieldCacheBean(); + // this is registered at the CONTAINER level because it's not core-specific - for now we + // also register it here for back-compat + solrFieldCacheBean.initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, "core"); + infoRegistry.put("fieldCache", solrFieldCacheBean); + + initSchema(config, schema); + + this.maxWarmingSearchers = config.maxWarmingSearchers; + this.slowQueryThresholdMillis = config.slowQueryThresholdMillis; + initListeners(); this.snapshotMgr = initSnapshotMetaDataManager(); @@ -961,7 +961,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab this.codec = initCodec(solrConfig, this.schema); - memClassLoader = new MemClassLoader(PluginBag.RuntimeLib.getLibObjects(this, solrConfig.getPluginInfos(PluginBag.RuntimeLib.class.getName())), getResourceLoader()); + memClassLoader = new MemClassLoader( + PluginBag.RuntimeLib.getLibObjects(this, solrConfig.getPluginInfos(PluginBag.RuntimeLib.class.getName())), + getResourceLoader()); initIndex(prev != null, reload); initWriters(); @@ -987,7 +989,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab }); this.updateHandler = initUpdateHandler(updateHandler); - + initSearcher(prev); // Initialize the RestManager @@ -997,7 +999,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab resourceLoader.inform(resourceLoader); resourceLoader.inform(this); // last call before the latch is released. this.updateHandler.informEventListeners(this); - + infoRegistry.put("core", this); // register any SolrInfoMBeans SolrResourceLoader initialized @@ -1029,13 +1031,13 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // should be fine, since counting down on a latch of 0 is still fine latch.countDown(); if (e instanceof OutOfMemoryError) { - throw (OutOfMemoryError)e; + throw (OutOfMemoryError) e; } try { // close down the searcher and any other resources, if it exists, as this // is not recoverable - close(); + close(); } catch (Throwable t) { if (t instanceof OutOfMemoryError) { throw (OutOfMemoryError) t; @@ -1048,7 +1050,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // allow firstSearcher events to fire and make sure it is released latch.countDown(); } - + assert ObjectReleaseTracker.track(this); }