You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by da...@apache.org on 2018/10/23 00:05:52 UTC
[31/52] [abbrv] [partial] lucene-solr:jira/gradle: Add gradle support
for Solr
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0ae21ad0/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
deleted file mode 100644
index 83384fb..0000000
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ /dev/null
@@ -1,1874 +0,0 @@
-/*
- * 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 java.lang.invoke.MethodHandles;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import org.apache.http.auth.AuthSchemeProvider;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.config.Lookup;
-import org.apache.lucene.index.CorruptIndexException;
-import org.apache.lucene.store.Directory;
-import org.apache.solr.client.solrj.SolrClient;
-import org.apache.solr.client.solrj.cloud.SolrCloudManager;
-import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
-import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.impl.HttpClientUtil;
-import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
-import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder;
-import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder.AuthSchemeRegistryProvider;
-import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder.CredentialsProviderProvider;
-import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
-import org.apache.solr.cloud.CloudDescriptor;
-import org.apache.solr.cloud.Overseer;
-import org.apache.solr.cloud.ZkController;
-import org.apache.solr.cloud.autoscaling.AutoScalingHandler;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.cloud.DocCollection;
-import org.apache.solr.common.cloud.Replica;
-import org.apache.solr.common.cloud.Replica.State;
-import org.apache.solr.common.params.CollectionAdminParams;
-import org.apache.solr.common.util.ExecutorUtil;
-import org.apache.solr.common.util.IOUtils;
-import org.apache.solr.common.util.Utils;
-import org.apache.solr.core.DirectoryFactory.DirContext;
-import org.apache.solr.core.backup.repository.BackupRepository;
-import org.apache.solr.core.backup.repository.BackupRepositoryFactory;
-import org.apache.solr.handler.RequestHandlerBase;
-import org.apache.solr.handler.SnapShooter;
-import org.apache.solr.handler.admin.AutoscalingHistoryHandler;
-import org.apache.solr.handler.admin.CollectionsHandler;
-import org.apache.solr.handler.admin.ConfigSetsHandler;
-import org.apache.solr.handler.admin.CoreAdminHandler;
-import org.apache.solr.handler.admin.HealthCheckHandler;
-import org.apache.solr.handler.admin.InfoHandler;
-import org.apache.solr.handler.admin.MetricsCollectorHandler;
-import org.apache.solr.handler.admin.MetricsHandler;
-import org.apache.solr.handler.admin.MetricsHistoryHandler;
-import org.apache.solr.handler.admin.SecurityConfHandler;
-import org.apache.solr.handler.admin.SecurityConfHandlerLocal;
-import org.apache.solr.handler.admin.SecurityConfHandlerZk;
-import org.apache.solr.handler.admin.ZookeeperInfoHandler;
-import org.apache.solr.handler.admin.ZookeeperStatusHandler;
-import org.apache.solr.handler.component.ShardHandlerFactory;
-import org.apache.solr.logging.LogWatcher;
-import org.apache.solr.logging.MDCLoggingContext;
-import org.apache.solr.metrics.SolrCoreMetricManager;
-import org.apache.solr.metrics.SolrMetricManager;
-import org.apache.solr.metrics.SolrMetricProducer;
-import org.apache.solr.request.SolrRequestHandler;
-import org.apache.solr.search.SolrFieldCacheBean;
-import org.apache.solr.security.AuthenticationPlugin;
-import org.apache.solr.security.AuthorizationPlugin;
-import org.apache.solr.security.HttpClientBuilderPlugin;
-import org.apache.solr.security.PKIAuthenticationPlugin;
-import org.apache.solr.security.PublicKeyHandler;
-import org.apache.solr.security.SecurityPluginHolder;
-import org.apache.solr.update.SolrCoreState;
-import org.apache.solr.update.UpdateShardHandler;
-import org.apache.solr.util.DefaultSolrThreadFactory;
-import org.apache.solr.util.OrderedExecutor;
-import org.apache.solr.util.stats.MetricUtils;
-import org.apache.zookeeper.KeeperException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.solr.common.params.CommonParams.AUTHC_PATH;
-import static org.apache.solr.common.params.CommonParams.AUTHZ_PATH;
-import static org.apache.solr.common.params.CommonParams.AUTOSCALING_HISTORY_PATH;
-import static org.apache.solr.common.params.CommonParams.COLLECTIONS_HANDLER_PATH;
-import static org.apache.solr.common.params.CommonParams.CONFIGSETS_HANDLER_PATH;
-import static org.apache.solr.common.params.CommonParams.CORES_HANDLER_PATH;
-import static org.apache.solr.common.params.CommonParams.HEALTH_CHECK_HANDLER_PATH;
-import static org.apache.solr.common.params.CommonParams.INFO_HANDLER_PATH;
-import static org.apache.solr.common.params.CommonParams.METRICS_HISTORY_PATH;
-import static org.apache.solr.common.params.CommonParams.METRICS_PATH;
-import static org.apache.solr.common.params.CommonParams.ZK_PATH;
-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;
-
-/**
- *
- * @since solr 1.3
- */
-public class CoreContainer {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- final SolrCores solrCores = new SolrCores(this);
-
- public static class CoreLoadFailure {
-
- public final CoreDescriptor cd;
- public final Exception exception;
-
- public CoreLoadFailure(CoreDescriptor cd, Exception loadFailure) {
- this.cd = new CoreDescriptor(cd.getName(), cd);
- this.exception = loadFailure;
- }
- }
-
- protected final Map<String, CoreLoadFailure> coreInitFailures = new ConcurrentHashMap<>();
-
- protected CoreAdminHandler coreAdminHandler = null;
- protected CollectionsHandler collectionsHandler = null;
- protected HealthCheckHandler healthCheckHandler = null;
-
- private InfoHandler infoHandler;
- protected ConfigSetsHandler configSetsHandler = null;
-
- private PKIAuthenticationPlugin pkiAuthenticationPlugin;
-
- protected Properties containerProperties;
-
- private ConfigSetService coreConfigService;
-
- protected ZkContainer zkSys = new ZkContainer();
- protected ShardHandlerFactory shardHandlerFactory;
-
- private UpdateShardHandler updateShardHandler;
-
- private ExecutorService coreContainerWorkExecutor = ExecutorUtil.newMDCAwareCachedThreadPool(
- new DefaultSolrThreadFactory("coreContainerWorkExecutor") );
-
- private final OrderedExecutor replayUpdatesExecutor;
-
- protected LogWatcher logging = null;
-
- private CloserThread backgroundCloser = null;
- protected final NodeConfig cfg;
- protected final SolrResourceLoader loader;
-
- protected final String solrHome;
-
- protected final CoresLocator coresLocator;
-
- private String hostName;
-
- private final BlobRepository blobRepository = new BlobRepository(this);
-
- private PluginBag<SolrRequestHandler> containerHandlers = new PluginBag<>(SolrRequestHandler.class, null);
-
- private boolean asyncSolrCoreLoad;
-
- protected SecurityConfHandler securityConfHandler;
-
- private SecurityPluginHolder<AuthorizationPlugin> authorizationPlugin;
-
- private SecurityPluginHolder<AuthenticationPlugin> authenticationPlugin;
-
- private BackupRepositoryFactory backupRepoFactory;
-
- protected SolrMetricManager metricManager;
-
- protected String metricTag = Integer.toHexString(hashCode());
-
- protected MetricsHandler metricsHandler;
-
- protected MetricsHistoryHandler metricsHistoryHandler;
-
- protected MetricsCollectorHandler metricsCollectorHandler;
-
- protected AutoscalingHistoryHandler autoscalingHistoryHandler;
-
-
- // Bits for the state variable.
- public final static long LOAD_COMPLETE = 0x1L;
- public final static long CORE_DISCOVERY_COMPLETE = 0x2L;
- public final static long INITIAL_CORE_LOAD_COMPLETE = 0x4L;
- private volatile long status = 0L;
-
- protected AutoScalingHandler autoScalingHandler;
-
- private enum CoreInitFailedAction { fromleader, none }
-
- /**
- * This method instantiates a new instance of {@linkplain BackupRepository}.
- *
- * @param repositoryName The name of the backup repository (Optional).
- * If not specified, a default implementation is used.
- * @return a new instance of {@linkplain BackupRepository}.
- */
- public BackupRepository newBackupRepository(Optional<String> repositoryName) {
- BackupRepository repository;
- if (repositoryName.isPresent()) {
- repository = backupRepoFactory.newInstance(getResourceLoader(), repositoryName.get());
- } else {
- repository = backupRepoFactory.newInstance(getResourceLoader());
- }
- return repository;
- }
-
- public ExecutorService getCoreZkRegisterExecutorService() {
- return zkSys.getCoreZkRegisterExecutorService();
- }
-
- public SolrRequestHandler getRequestHandler(String path) {
- return RequestHandlerBase.getRequestHandler(path, containerHandlers);
- }
-
- public PluginBag<SolrRequestHandler> getRequestHandlers() {
- return this.containerHandlers;
- }
-
- {
- log.debug("New CoreContainer " + System.identityHashCode(this));
- }
-
- /**
- * Create a new CoreContainer using system properties to detect the solr home
- * directory. The container's cores are not loaded.
- * @see #load()
- */
- public CoreContainer() {
- this(new SolrResourceLoader(SolrResourceLoader.locateSolrHome()));
- }
-
- /**
- * Create a new CoreContainer using the given SolrResourceLoader. The container's
- * cores are not loaded.
- * @param loader the SolrResourceLoader
- * @see #load()
- */
- public CoreContainer(SolrResourceLoader loader) {
- this(SolrXmlConfig.fromSolrHome(loader, loader.getInstancePath()));
- }
-
- /**
- * Create a new CoreContainer using the given solr home directory. The container's
- * cores are not loaded.
- * @param solrHome a String containing the path to the solr home directory
- * @see #load()
- */
- public CoreContainer(String solrHome) {
- this(new SolrResourceLoader(Paths.get(solrHome)));
- }
-
- /**
- * Create a new CoreContainer using the given SolrResourceLoader,
- * configuration and CoresLocator. The container's cores are
- * not loaded.
- * @param config a ConfigSolr representation of this container's configuration
- * @see #load()
- */
- public CoreContainer(NodeConfig config) {
- this(config, new Properties());
- }
-
- public CoreContainer(NodeConfig config, Properties properties) {
- this(config, properties, new CorePropertiesLocator(config.getCoreRootDirectory()));
- }
-
- public CoreContainer(NodeConfig config, Properties properties, boolean asyncSolrCoreLoad) {
- this(config, properties, new CorePropertiesLocator(config.getCoreRootDirectory()), asyncSolrCoreLoad);
- }
-
- public CoreContainer(NodeConfig config, Properties properties, CoresLocator locator) {
- this(config, properties, locator, false);
- }
-
- public CoreContainer(NodeConfig config, Properties properties, CoresLocator locator, boolean asyncSolrCoreLoad) {
- this.loader = config.getSolrResourceLoader();
- this.solrHome = loader.getInstancePath().toString();
- containerHandlers.put(PublicKeyHandler.PATH, new PublicKeyHandler());
- this.cfg = requireNonNull(config);
- this.coresLocator = locator;
- this.containerProperties = new Properties(properties);
- this.asyncSolrCoreLoad = asyncSolrCoreLoad;
- this.replayUpdatesExecutor = new OrderedExecutor(
- cfg.getReplayUpdatesThreads(),
- ExecutorUtil.newMDCAwareCachedThreadPool(
- cfg.getReplayUpdatesThreads(),
- new DefaultSolrThreadFactory("replayUpdatesExecutor")));
- }
-
- private synchronized void initializeAuthorizationPlugin(Map<String, Object> authorizationConf) {
- authorizationConf = Utils.getDeepCopy(authorizationConf, 4);
- //Initialize the Authorization module
- SecurityPluginHolder<AuthorizationPlugin> old = authorizationPlugin;
- SecurityPluginHolder<AuthorizationPlugin> authorizationPlugin = null;
- if (authorizationConf != null) {
- String klas = (String) authorizationConf.get("class");
- if (klas == null) {
- throw new SolrException(ErrorCode.SERVER_ERROR, "class is required for authorization plugin");
- }
- if (old != null && old.getZnodeVersion() == readVersion(authorizationConf)) {
- return;
- }
- log.info("Initializing authorization plugin: " + klas);
- authorizationPlugin = new SecurityPluginHolder<>(readVersion(authorizationConf),
- getResourceLoader().newInstance(klas, AuthorizationPlugin.class));
-
- // Read and pass the authorization context to the plugin
- authorizationPlugin.plugin.init(authorizationConf);
- } else {
- log.debug("Security conf doesn't exist. Skipping setup for authorization module.");
- }
- this.authorizationPlugin = authorizationPlugin;
- if (old != null) {
- try {
- old.plugin.close();
- } catch (Exception e) {
- }
- }
- }
-
- private synchronized void initializeAuthenticationPlugin(Map<String, Object> authenticationConfig) {
- authenticationConfig = Utils.getDeepCopy(authenticationConfig, 4);
- String pluginClassName = null;
- if (authenticationConfig != null) {
- if (authenticationConfig.containsKey("class")) {
- pluginClassName = String.valueOf(authenticationConfig.get("class"));
- } else {
- throw new SolrException(ErrorCode.SERVER_ERROR, "No 'class' specified for authentication in ZK.");
- }
- }
-
- if (pluginClassName != null) {
- log.debug("Authentication plugin class obtained from security.json: "+pluginClassName);
- } else if (System.getProperty(AUTHENTICATION_PLUGIN_PROP) != null) {
- pluginClassName = System.getProperty(AUTHENTICATION_PLUGIN_PROP);
- log.debug("Authentication plugin class obtained from system property '" +
- AUTHENTICATION_PLUGIN_PROP + "': " + pluginClassName);
- } else {
- log.debug("No authentication plugin used.");
- }
- SecurityPluginHolder<AuthenticationPlugin> old = authenticationPlugin;
- SecurityPluginHolder<AuthenticationPlugin> authenticationPlugin = null;
-
- // Initialize the plugin
- if (pluginClassName != null) {
- log.info("Initializing authentication plugin: " + pluginClassName);
- authenticationPlugin = new SecurityPluginHolder<>(readVersion(authenticationConfig),
- getResourceLoader().newInstance(pluginClassName,
- AuthenticationPlugin.class,
- null,
- new Class[]{CoreContainer.class},
- new Object[]{this}));
- }
- if (authenticationPlugin != null) {
- authenticationPlugin.plugin.init(authenticationConfig);
- setupHttpClientForAuthPlugin(authenticationPlugin.plugin);
- }
- this.authenticationPlugin = authenticationPlugin;
- try {
- if (old != null) old.plugin.close();
- } catch (Exception e) {/*do nothing*/ }
-
- }
-
- private void setupHttpClientForAuthPlugin(Object authcPlugin) {
- if (authcPlugin instanceof HttpClientBuilderPlugin) {
- // Setup HttpClient for internode communication
- SolrHttpClientBuilder builder = ((HttpClientBuilderPlugin) authcPlugin).getHttpClientBuilder(HttpClientUtil.getHttpClientBuilder());
-
- // The default http client of the core container's shardHandlerFactory has already been created and
- // configured using the default httpclient configurer. We need to reconfigure it using the plugin's
- // http client configurer to set it up for internode communication.
- log.debug("Reconfiguring HttpClient settings.");
-
- SolrHttpClientContextBuilder httpClientBuilder = new SolrHttpClientContextBuilder();
- if (builder.getCredentialsProviderProvider() != null) {
- httpClientBuilder.setDefaultCredentialsProvider(new CredentialsProviderProvider() {
-
- @Override
- public CredentialsProvider getCredentialsProvider() {
- return builder.getCredentialsProviderProvider().getCredentialsProvider();
- }
- });
- }
- if (builder.getAuthSchemeRegistryProvider() != null) {
- httpClientBuilder.setAuthSchemeRegistryProvider(new AuthSchemeRegistryProvider() {
-
- @Override
- public Lookup<AuthSchemeProvider> getAuthSchemeRegistry() {
- return builder.getAuthSchemeRegistryProvider().getAuthSchemeRegistry();
- }
- });
- }
-
- HttpClientUtil.setHttpClientRequestContextBuilder(httpClientBuilder);
-
- } else {
- if (pkiAuthenticationPlugin != null) {
- //this happened due to an authc plugin reload. no need to register the pkiAuthc plugin again
- if(pkiAuthenticationPlugin.isInterceptorRegistered()) return;
- log.info("PKIAuthenticationPlugin is managing internode requests");
- setupHttpClientForAuthPlugin(pkiAuthenticationPlugin);
- pkiAuthenticationPlugin.setInterceptorRegistered();
- }
- }
- }
-
- private static int readVersion(Map<String, Object> conf) {
- if (conf == null) return -1;
- Map meta = (Map) conf.get("");
- if (meta == null) return -1;
- Number v = (Number) meta.get("v");
- return v == null ? -1 : v.intValue();
- }
-
- /**
- * This method allows subclasses to construct a CoreContainer
- * without any default init behavior.
- *
- * @param testConstructor pass (Object)null.
- * @lucene.experimental
- */
- protected CoreContainer(Object testConstructor) {
- solrHome = null;
- loader = null;
- coresLocator = null;
- cfg = null;
- containerProperties = null;
- replayUpdatesExecutor = null;
- }
-
- public static CoreContainer createAndLoad(Path solrHome) {
- return createAndLoad(solrHome, solrHome.resolve(SolrXmlConfig.SOLR_XML_FILE));
- }
-
- /**
- * Create a new CoreContainer and load its cores
- * @param solrHome the solr home directory
- * @param configFile the file containing this container's configuration
- * @return a loaded CoreContainer
- */
- public static CoreContainer createAndLoad(Path solrHome, Path configFile) {
- SolrResourceLoader loader = new SolrResourceLoader(solrHome);
- CoreContainer cc = new CoreContainer(SolrXmlConfig.fromFile(loader, configFile));
- try {
- cc.load();
- } catch (Exception e) {
- cc.shutdown();
- throw e;
- }
- return cc;
- }
-
- public Properties getContainerProperties() {
- return containerProperties;
- }
-
- public PKIAuthenticationPlugin getPkiAuthenticationPlugin() {
- return pkiAuthenticationPlugin;
- }
-
- public SolrMetricManager getMetricManager() {
- return metricManager;
- }
-
- public MetricsHandler getMetricsHandler() {
- return metricsHandler;
- }
-
- public MetricsHistoryHandler getMetricsHistoryHandler() {
- return metricsHistoryHandler;
- }
-
- public OrderedExecutor getReplayUpdatesExecutor() {
- return replayUpdatesExecutor;
- }
-
- //-------------------------------------------------------------------
- // Initialization / Cleanup
- //-------------------------------------------------------------------
-
- /**
- * Load the cores defined for this CoreContainer
- */
- public void load() {
- log.debug("Loading cores into CoreContainer [instanceDir={}]", loader.getInstancePath());
-
- // add the sharedLib to the shared resource loader before initializing cfg based plugins
- String libDir = cfg.getSharedLibDirectory();
- if (libDir != null) {
- Path libPath = loader.getInstancePath().resolve(libDir);
- try {
- loader.addToClassLoader(SolrResourceLoader.getURLs(libPath));
- loader.reloadLuceneSPI();
- } catch (IOException e) {
- if (!libDir.equals("lib")) { // Don't complain if default "lib" dir does not exist
- log.warn("Couldn't add files from {} to classpath: {}", libPath, e.getMessage());
- }
- }
- }
-
- metricManager = new SolrMetricManager(loader, cfg.getMetricsConfig());
-
- coreContainerWorkExecutor = MetricUtils.instrumentedExecutorService(
- coreContainerWorkExecutor, null,
- metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)),
- SolrMetricManager.mkName("coreContainerWorkExecutor", SolrInfoBean.Category.CONTAINER.toString(), "threadPool"));
-
- shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
- if (shardHandlerFactory instanceof SolrMetricProducer) {
- SolrMetricProducer metricProducer = (SolrMetricProducer) shardHandlerFactory;
- metricProducer.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, "httpShardHandler");
- }
-
- updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig());
- updateShardHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, "updateShardHandler");
-
- solrCores.load(loader);
-
-
- logging = LogWatcher.newRegisteredLogWatcher(cfg.getLogWatcherConfig(), loader);
-
- hostName = cfg.getNodeName();
-
- zkSys.initZooKeeper(this, solrHome, cfg.getCloudConfig());
- if(isZooKeeperAware()) pkiAuthenticationPlugin = new PKIAuthenticationPlugin(this, zkSys.getZkController().getNodeName(),
- (PublicKeyHandler) containerHandlers.get(PublicKeyHandler.PATH));
-
- MDCLoggingContext.setNode(this);
-
- securityConfHandler = isZooKeeperAware() ? new SecurityConfHandlerZk(this) : new SecurityConfHandlerLocal(this);
- reloadSecurityProperties();
- this.backupRepoFactory = new BackupRepositoryFactory(cfg.getBackupRepositoryPlugins());
-
- createHandler(ZK_PATH, ZookeeperInfoHandler.class.getName(), ZookeeperInfoHandler.class);
- createHandler(ZK_STATUS_PATH, ZookeeperStatusHandler.class.getName(), ZookeeperStatusHandler.class);
- collectionsHandler = createHandler(COLLECTIONS_HANDLER_PATH, cfg.getCollectionsHandlerClass(), CollectionsHandler.class);
- healthCheckHandler = createHandler(HEALTH_CHECK_HANDLER_PATH, cfg.getHealthCheckHandlerClass(), HealthCheckHandler.class);
- infoHandler = createHandler(INFO_HANDLER_PATH, cfg.getInfoHandlerClass(), InfoHandler.class);
- coreAdminHandler = createHandler(CORES_HANDLER_PATH, cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class);
- configSetsHandler = createHandler(CONFIGSETS_HANDLER_PATH, cfg.getConfigSetsHandlerClass(), ConfigSetsHandler.class);
-
- // metricsHistoryHandler uses metricsHandler, so create it first
- metricsHandler = new MetricsHandler(this);
- containerHandlers.put(METRICS_PATH, metricsHandler);
- metricsHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, METRICS_PATH);
-
- createMetricsHistoryHandler();
-
- autoscalingHistoryHandler = createHandler(AUTOSCALING_HISTORY_PATH, AutoscalingHistoryHandler.class.getName(), AutoscalingHistoryHandler.class);
- metricsCollectorHandler = createHandler(MetricsCollectorHandler.HANDLER_PATH, MetricsCollectorHandler.class.getName(), MetricsCollectorHandler.class);
- // may want to add some configuration here in the future
- metricsCollectorHandler.init(null);
-
- containerHandlers.put(AUTHZ_PATH, securityConfHandler);
- securityConfHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, AUTHZ_PATH);
- containerHandlers.put(AUTHC_PATH, securityConfHandler);
-
-
- PluginInfo[] metricReporters = cfg.getMetricsConfig().getMetricReporters();
- metricManager.loadReporters(metricReporters, loader, this, null, null, SolrInfoBean.Group.node);
- metricManager.loadReporters(metricReporters, loader, this, null, null, SolrInfoBean.Group.jvm);
- metricManager.loadReporters(metricReporters, loader, this, null, null, SolrInfoBean.Group.jetty);
-
- coreConfigService = ConfigSetService.createConfigSetService(cfg, loader, zkSys.zkController);
-
- containerProperties.putAll(cfg.getSolrProperties());
-
- // initialize gauges for reporting the number of cores and disk total/free
-
- String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.node);
- String metricTag = Integer.toHexString(hashCode());
- metricManager.registerGauge(null, registryName, () -> solrCores.getCores().size(),
- metricTag,true, "loaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
- metricManager.registerGauge(null, registryName, () -> solrCores.getLoadedCoreNames().size() - solrCores.getCores().size(),
- metricTag,true, "lazy", SolrInfoBean.Category.CONTAINER.toString(), "cores");
- metricManager.registerGauge(null, registryName, () -> solrCores.getAllCoreNames().size() - solrCores.getLoadedCoreNames().size(),
- metricTag,true, "unloaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
- Path dataHome = cfg.getSolrDataHome() != null ? cfg.getSolrDataHome() : cfg.getCoreRootDirectory();
- metricManager.registerGauge(null, registryName, () -> dataHome.toFile().getTotalSpace(),
- metricTag,true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
- metricManager.registerGauge(null, registryName, () -> dataHome.toFile().getUsableSpace(),
- metricTag,true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
- metricManager.registerGauge(null, registryName, () -> dataHome.toAbsolutePath().toString(),
- metricTag,true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs");
- metricManager.registerGauge(null, registryName, () -> {
- try {
- return org.apache.lucene.util.IOUtils.spins(dataHome.toAbsolutePath());
- } catch (IOException e) {
- // default to spinning
- return true;
- }
- },
- metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs");
- metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toFile().getTotalSpace(),
- metricTag,true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
- metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toFile().getUsableSpace(),
- metricTag,true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
- metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toAbsolutePath().toString(),
- metricTag,true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
- metricManager.registerGauge(null, registryName, () -> {
- try {
- return org.apache.lucene.util.IOUtils.spins(cfg.getCoreRootDirectory().toAbsolutePath());
- } catch (IOException e) {
- // default to spinning
- return true;
- }
- },
- metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
- // add version information
- metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getSpecificationVersion(),
- metricTag,true, "specification", SolrInfoBean.Category.CONTAINER.toString(), "version");
- metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getImplementationVersion(),
- metricTag,true, "implementation", SolrInfoBean.Category.CONTAINER.toString(), "version");
-
- SolrFieldCacheBean fieldCacheBean = new SolrFieldCacheBean();
- fieldCacheBean.initializeMetrics(metricManager, registryName, metricTag, null);
-
- if (isZooKeeperAware()) {
- metricManager.loadClusterReporters(metricReporters, this);
- }
-
- // setup executor to load cores in parallel
- ExecutorService coreLoadExecutor = MetricUtils.instrumentedExecutorService(
- ExecutorUtil.newMDCAwareFixedThreadPool(
- cfg.getCoreLoadThreadCount(isZooKeeperAware()),
- new DefaultSolrThreadFactory("coreLoadExecutor")), null,
- metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)),
- SolrMetricManager.mkName("coreLoadExecutor", SolrInfoBean.Category.CONTAINER.toString(), "threadPool"));
- final List<Future<SolrCore>> futures = new ArrayList<>();
- try {
- List<CoreDescriptor> cds = coresLocator.discover(this);
- if (isZooKeeperAware()) {
- //sort the cores if it is in SolrCloud. In standalone node the order does not matter
- CoreSorter coreComparator = new CoreSorter().init(this);
- cds = new ArrayList<>(cds);//make a copy
- Collections.sort(cds, coreComparator::compare);
- }
- checkForDuplicateCoreNames(cds);
- status |= CORE_DISCOVERY_COMPLETE;
-
- for (final CoreDescriptor cd : cds) {
- if (cd.isTransient() || !cd.isLoadOnStartup()) {
- solrCores.addCoreDescriptor(cd);
- } else if (asyncSolrCoreLoad) {
- solrCores.markCoreAsLoading(cd);
- }
- if (cd.isLoadOnStartup()) {
- futures.add(coreLoadExecutor.submit(() -> {
- SolrCore core;
- try {
- if (zkSys.getZkController() != null) {
- zkSys.getZkController().throwErrorIfReplicaReplaced(cd);
- }
- solrCores.waitAddPendingCoreOps(cd.getName());
- core = createFromDescriptor(cd, false, false);
- } finally {
- solrCores.removeFromPendingOps(cd.getName());
- if (asyncSolrCoreLoad) {
- solrCores.markCoreAsNotLoading(cd);
- }
- }
- try {
- zkSys.registerInZk(core, true, false);
- } catch (RuntimeException e) {
- SolrException.log(log, "Error registering SolrCore", e);
- }
- return core;
- }));
- }
- }
-
-
- // Start the background thread
- backgroundCloser = new CloserThread(this, solrCores, cfg);
- backgroundCloser.start();
-
- } finally {
- if (asyncSolrCoreLoad && futures != null) {
-
- coreContainerWorkExecutor.submit(() -> {
- try {
- for (Future<SolrCore> future : futures) {
- try {
- future.get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } catch (ExecutionException e) {
- log.error("Error waiting for SolrCore to be loaded on startup", e.getCause());
- }
- }
- } finally {
- ExecutorUtil.shutdownAndAwaitTermination(coreLoadExecutor);
- }
- });
- } else {
- ExecutorUtil.shutdownAndAwaitTermination(coreLoadExecutor);
- }
- }
-
- if (isZooKeeperAware()) {
- zkSys.getZkController().checkOverseerDesignate();
- // initialize this handler here when SolrCloudManager is ready
- autoScalingHandler = new AutoScalingHandler(getZkController().getSolrCloudManager(), loader);
- containerHandlers.put(AutoScalingHandler.HANDLER_PATH, autoScalingHandler);
- autoScalingHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, AutoScalingHandler.HANDLER_PATH);
- }
- // This is a bit redundant but these are two distinct concepts for all they're accomplished at the same time.
- status |= LOAD_COMPLETE | INITIAL_CORE_LOAD_COMPLETE;
- }
-
- // MetricsHistoryHandler supports both cloud and standalone configs
- private void createMetricsHistoryHandler() {
- PluginInfo plugin = cfg.getMetricsConfig().getHistoryHandler();
- Map<String, Object> initArgs;
- if (plugin != null && plugin.initArgs != null) {
- initArgs = plugin.initArgs.asMap(5);
- initArgs.put(MetricsHistoryHandler.ENABLE_PROP, plugin.isEnabled());
- } else {
- initArgs = new HashMap<>();
- }
- String name;
- SolrCloudManager cloudManager;
- SolrClient client;
- if (isZooKeeperAware()) {
- name = getZkController().getNodeName();
- cloudManager = getZkController().getSolrCloudManager();
- client = new CloudSolrClient.Builder(Collections.singletonList(getZkController().getZkServerAddress()), Optional.empty())
- .withHttpClient(updateShardHandler.getDefaultHttpClient()).build();
- } else {
- name = getNodeConfig().getNodeName();
- if (name == null || name.isEmpty()) {
- name = "localhost";
- }
- cloudManager = null;
- client = new EmbeddedSolrServer(this, CollectionAdminParams.SYSTEM_COLL) {
- @Override
- public void close() throws IOException {
- // do nothing - we close the container ourselves
- }
- };
- // enable local metrics unless specifically set otherwise
- if (!initArgs.containsKey(MetricsHistoryHandler.ENABLE_NODES_PROP)) {
- initArgs.put(MetricsHistoryHandler.ENABLE_NODES_PROP, true);
- }
- if (!initArgs.containsKey(MetricsHistoryHandler.ENABLE_REPLICAS_PROP)) {
- initArgs.put(MetricsHistoryHandler.ENABLE_REPLICAS_PROP, true);
- }
- }
- metricsHistoryHandler = new MetricsHistoryHandler(name, metricsHandler,
- client, cloudManager, initArgs);
- containerHandlers.put(METRICS_HISTORY_PATH, metricsHistoryHandler);
- metricsHistoryHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, METRICS_HISTORY_PATH);
- }
-
- public void securityNodeChanged() {
- log.info("Security node changed, reloading security.json");
- reloadSecurityProperties();
- }
-
- /**
- * Make sure securityConfHandler is initialized
- */
- private void reloadSecurityProperties() {
- SecurityConfHandler.SecurityConfig securityConfig = securityConfHandler.getSecurityConfig(false);
- initializeAuthorizationPlugin((Map<String, Object>) securityConfig.getData().get("authorization"));
- initializeAuthenticationPlugin((Map<String, Object>) securityConfig.getData().get("authentication"));
- }
-
- private static void checkForDuplicateCoreNames(List<CoreDescriptor> cds) {
- Map<String, Path> addedCores = Maps.newHashMap();
- for (CoreDescriptor cd : cds) {
- final String name = cd.getName();
- if (addedCores.containsKey(name))
- throw new SolrException(ErrorCode.SERVER_ERROR,
- String.format(Locale.ROOT, "Found multiple cores with the name [%s], with instancedirs [%s] and [%s]",
- name, addedCores.get(name), cd.getInstanceDir()));
- addedCores.put(name, cd.getInstanceDir());
- }
- }
-
- private volatile boolean isShutDown = false;
-
- public boolean isShutDown() {
- return isShutDown;
- }
-
- /**
- * Stops all cores.
- */
- public void shutdown() {
- log.info("Shutting down CoreContainer instance="
- + System.identityHashCode(this));
-
- isShutDown = true;
-
- ExecutorUtil.shutdownAndAwaitTermination(coreContainerWorkExecutor);
- replayUpdatesExecutor.shutdownAndAwaitTermination();
-
- if (metricsHistoryHandler != null) {
- IOUtils.closeQuietly(metricsHistoryHandler.getSolrClient());
- metricsHistoryHandler.close();
- }
-
- if (metricManager != null) {
- metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
- metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
- metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jetty));
-
- metricManager.unregisterGauges(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node), metricTag);
- metricManager.unregisterGauges(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm), metricTag);
- metricManager.unregisterGauges(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jetty), metricTag);
- }
-
- if (isZooKeeperAware()) {
- cancelCoreRecoveries();
- zkSys.zkController.publishNodeAsDown(zkSys.zkController.getNodeName());
- try {
- zkSys.zkController.removeEphemeralLiveNode();
- } catch (Exception e) {
- log.warn("Error removing live node. Continuing to close CoreContainer", e);
- }
- if (metricManager != null) {
- metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.cluster));
- }
- }
-
- try {
- if (coreAdminHandler != null) coreAdminHandler.shutdown();
- } catch (Exception e) {
- log.warn("Error shutting down CoreAdminHandler. Continuing to close CoreContainer.", e);
- }
-
- try {
- // First wake up the closer thread, it'll terminate almost immediately since it checks isShutDown.
- synchronized (solrCores.getModifyLock()) {
- solrCores.getModifyLock().notifyAll(); // wake up anyone waiting
- }
- if (backgroundCloser != null) { // Doesn't seem right, but tests get in here without initializing the core.
- try {
- while (true) {
- backgroundCloser.join(15000);
- if (backgroundCloser.isAlive()) {
- synchronized (solrCores.getModifyLock()) {
- solrCores.getModifyLock().notifyAll(); // there is a race we have to protect against
- }
- } else {
- break;
- }
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- if (log.isDebugEnabled()) {
- log.debug("backgroundCloser thread was interrupted before finishing");
- }
- }
- }
- // Now clear all the cores that are being operated upon.
- solrCores.close();
-
- // It's still possible that one of the pending dynamic load operation is waiting, so wake it up if so.
- // Since all the pending operations queues have been drained, there should be nothing to do.
- synchronized (solrCores.getModifyLock()) {
- solrCores.getModifyLock().notifyAll(); // wake up the thread
- }
-
- } finally {
- try {
- if (shardHandlerFactory != null) {
- shardHandlerFactory.close();
- }
- } finally {
- try {
- if (updateShardHandler != null) {
- updateShardHandler.close();
- }
- } finally {
- // we want to close zk stuff last
- zkSys.close();
- }
- }
- }
-
- // It should be safe to close the authorization plugin at this point.
- try {
- if(authorizationPlugin != null) {
- authorizationPlugin.plugin.close();
- }
- } catch (IOException e) {
- log.warn("Exception while closing authorization plugin.", e);
- }
-
- // It should be safe to close the authentication plugin at this point.
- try {
- if(authenticationPlugin != null) {
- authenticationPlugin.plugin.close();
- authenticationPlugin = null;
- }
- } catch (Exception e) {
- log.warn("Exception while closing authentication plugin.", e);
- }
-
- org.apache.lucene.util.IOUtils.closeWhileHandlingException(loader); // best effort
- }
-
- public void cancelCoreRecoveries() {
-
- List<SolrCore> cores = solrCores.getCores();
-
- // we must cancel without holding the cores sync
- // make sure we wait for any recoveries to stop
- for (SolrCore core : cores) {
- try {
- core.getSolrCoreState().cancelRecovery();
- } catch (Exception e) {
- SolrException.log(log, "Error canceling recovery for core", e);
- }
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if(!isShutDown){
- log.error("CoreContainer was not close prior to finalize(), indicates a bug -- POSSIBLE RESOURCE LEAK!!! instance=" + System.identityHashCode(this));
- }
- } finally {
- super.finalize();
- }
- }
-
- public CoresLocator getCoresLocator() {
- return coresLocator;
- }
-
- protected SolrCore registerCore(CoreDescriptor cd, SolrCore core, boolean registerInZk, boolean skipRecovery) {
- if( core == null ) {
- throw new RuntimeException( "Can not register a null core." );
- }
-
- if (isShutDown) {
- core.close();
- throw new IllegalStateException("This CoreContainer has been closed");
- }
- SolrCore old = solrCores.putCore(cd, core);
- /*
- * set both the name of the descriptor and the name of the
- * core, since the descriptors name is used for persisting.
- */
-
- core.setName(cd.getName());
-
- coreInitFailures.remove(cd.getName());
-
- if( old == null || old == core) {
- log.debug( "registering core: " + cd.getName() );
- if (registerInZk) {
- zkSys.registerInZk(core, false, skipRecovery);
- }
- return null;
- }
- else {
- log.debug( "replacing core: " + cd.getName() );
- old.close();
- if (registerInZk) {
- zkSys.registerInZk(core, false, skipRecovery);
- }
- return old;
- }
- }
-
- /**
- * Creates a new core, publishing the core state to the cluster
- * @param coreName the core name
- * @param parameters the core parameters
- * @return the newly created core
- */
- public SolrCore create(String coreName, Map<String, String> parameters) {
- return create(coreName, cfg.getCoreRootDirectory().resolve(coreName), parameters, false);
- }
-
- /**
- * Creates a new core in a specified instance directory, publishing the core state to the cluster
- * @param coreName the core name
- * @param instancePath the instance directory
- * @param parameters the core parameters
- * @return the newly created core
- */
- public SolrCore create(String coreName, Path instancePath, Map<String, String> parameters, boolean newCollection) {
-
- CoreDescriptor cd = new CoreDescriptor(coreName, instancePath, parameters, getContainerProperties(), isZooKeeperAware());
-
- // TODO: There's a race here, isn't there?
- // Since the core descriptor is removed when a core is unloaded, it should never be anywhere when a core is created.
- if (getAllCoreNames().contains(coreName)) {
- log.warn("Creating a core with existing name is not allowed");
- // TODO: Shouldn't this be a BAD_REQUEST?
- throw new SolrException(ErrorCode.SERVER_ERROR, "Core with name '" + coreName + "' already exists.");
- }
-
- boolean preExisitingZkEntry = false;
- try {
- if (getZkController() != null) {
- if (!Overseer.isLegacy(getZkController().getZkStateReader())) {
- if (cd.getCloudDescriptor().getCoreNodeName() == null) {
- throw new SolrException(ErrorCode.SERVER_ERROR, "non legacy mode coreNodeName missing " + parameters.toString());
-
- }
- }
- preExisitingZkEntry = getZkController().checkIfCoreNodeNameAlreadyExists(cd);
- }
-
- // Much of the logic in core handling pre-supposes that the core.properties file already exists, so create it
- // first and clean it up if there's an error.
- coresLocator.create(this, cd);
-
- SolrCore core = null;
- try {
- solrCores.waitAddPendingCoreOps(cd.getName());
- core = createFromDescriptor(cd, true, newCollection);
- coresLocator.persist(this, cd); // Write out the current core properties in case anything changed when the core was created
- } finally {
- solrCores.removeFromPendingOps(cd.getName());
- }
-
- return core;
- } catch (Exception ex) {
- // First clean up any core descriptor, there should never be an existing core.properties file for any core that
- // failed to be created on-the-fly.
- coresLocator.delete(this, cd);
- if (isZooKeeperAware() && !preExisitingZkEntry) {
- try {
- getZkController().unregister(coreName, cd);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- SolrException.log(log, null, e);
- } catch (KeeperException e) {
- SolrException.log(log, null, e);
- } catch (Exception e) {
- SolrException.log(log, null, e);
- }
- }
-
- Throwable tc = ex;
- Throwable c = null;
- do {
- tc = tc.getCause();
- if (tc != null) {
- c = tc;
- }
- } while (tc != null);
-
- String rootMsg = "";
- if (c != null) {
- rootMsg = " Caused by: " + c.getMessage();
- }
-
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
- "Error CREATEing SolrCore '" + coreName + "': " + ex.getMessage() + rootMsg, ex);
- }
- }
-
- /**
- * Creates a new core based on a CoreDescriptor.
- *
- * @param dcore a core descriptor
- * @param publishState publish core state to the cluster if true
- *
- * WARNING: Any call to this method should be surrounded by a try/finally block
- * that calls solrCores.waitAddPendingCoreOps(...) and solrCores.removeFromPendingOps(...)
- *
- * <pre>
- * <code>
- * try {
- * solrCores.waitAddPendingCoreOps(dcore.getName());
- * createFromDescriptor(...);
- * } finally {
- * solrCores.removeFromPendingOps(dcore.getName());
- * }
- * </code>
- * </pre>
- *
- * Trying to put the waitAddPending... in this method results in Bad Things Happening due to race conditions.
- * getCore() depends on getting the core returned _if_ it's in the pending list due to some other thread opening it.
- * If the core is not in the pending list and not loaded, then getCore() calls this method. Anything that called
- * to check if the core was loaded _or_ in pending ops and, based on the return called createFromDescriptor would
- * introduce a race condition, see getCore() for the place it would be a problem
- *
- * @return the newly created core
- */
- @SuppressWarnings("resource")
- private SolrCore createFromDescriptor(CoreDescriptor dcore, boolean publishState, boolean newCollection) {
-
- if (isShutDown) {
- throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Solr has been shutdown.");
- }
-
- SolrCore core = null;
- try {
- MDCLoggingContext.setCoreDescriptor(this, dcore);
- SolrIdentifierValidator.validateCoreName(dcore.getName());
- if (zkSys.getZkController() != null) {
- zkSys.getZkController().preRegister(dcore, publishState);
- }
-
- ConfigSet coreConfig = getConfigSet(dcore);
- dcore.setConfigSetTrusted(coreConfig.isTrusted());
- log.info("Creating SolrCore '{}' using configuration from {}, trusted={}", dcore.getName(), coreConfig.getName(), dcore.isConfigSetTrusted());
- try {
- core = new SolrCore(this, dcore, coreConfig);
- } catch (SolrException e) {
- core = processCoreCreateException(e, dcore, coreConfig);
- }
-
- // always kick off recovery if we are in non-Cloud mode
- if (!isZooKeeperAware() && core.getUpdateHandler().getUpdateLog() != null) {
- core.getUpdateHandler().getUpdateLog().recoverFromLog();
- }
-
- registerCore(dcore, core, publishState, newCollection);
-
- return core;
- } catch (Exception e) {
- coreInitFailures.put(dcore.getName(), new CoreLoadFailure(dcore, e));
- if (e instanceof ZkController.NotInClusterStateException && !newCollection) {
- // this mostly happen when the core is deleted when this node is down
- unload(dcore.getName(), true, true, true);
- throw e;
- }
- solrCores.removeCoreDescriptor(dcore);
- final SolrException solrException = new SolrException(ErrorCode.SERVER_ERROR, "Unable to create core [" + dcore.getName() + "]", e);
- if(core != null && !core.isClosed())
- IOUtils.closeQuietly(core);
- throw solrException;
- } catch (Throwable t) {
- SolrException e = new SolrException(ErrorCode.SERVER_ERROR, "JVM Error creating core [" + dcore.getName() + "]: " + t.getMessage(), t);
- coreInitFailures.put(dcore.getName(), new CoreLoadFailure(dcore, e));
- solrCores.removeCoreDescriptor(dcore);
- if(core != null && !core.isClosed())
- IOUtils.closeQuietly(core);
- throw t;
- } finally {
- MDCLoggingContext.clear();
- }
- }
-
- public boolean isSharedFs(CoreDescriptor cd) {
- try (SolrCore core = this.getCore(cd.getName())) {
- if (core != null) {
- return core.getDirectoryFactory().isSharedStorage();
- } else {
- ConfigSet configSet = getConfigSet(cd);
- return DirectoryFactory.loadDirectoryFactory(configSet.getSolrConfig(), this, null).isSharedStorage();
- }
- }
- }
-
- private ConfigSet getConfigSet(CoreDescriptor cd) {
- return coreConfigService.getConfig(cd);
- }
-
- /**
- * Take action when we failed to create a SolrCore. If error is due to corrupt index, try to recover. Various recovery
- * strategies can be specified via system properties "-DCoreInitFailedAction={fromleader, none}"
- *
- * @see CoreInitFailedAction
- *
- * @param original
- * the problem seen when loading the core the first time.
- * @param dcore
- * core descriptor for the core to create
- * @param coreConfig
- * core config for the core to create
- * @return if possible
- * @throws SolrException
- * rethrows the original exception if we will not attempt to recover, throws a new SolrException with the
- * original exception as a suppressed exception if there is a second problem creating the solr core.
- */
- private SolrCore processCoreCreateException(SolrException original, CoreDescriptor dcore, ConfigSet coreConfig) {
- // Traverse full chain since CIE may not be root exception
- Throwable cause = original;
- while ((cause = cause.getCause()) != null) {
- if (cause instanceof CorruptIndexException) {
- break;
- }
- }
-
- // If no CorruptIndexException, nothing we can try here
- if (cause == null) throw original;
-
- CoreInitFailedAction action = CoreInitFailedAction.valueOf(System.getProperty(CoreInitFailedAction.class.getSimpleName(), "none"));
- log.debug("CorruptIndexException while creating core, will attempt to repair via {}", action);
-
- switch (action) {
- case fromleader: // Recovery from leader on a CorruptedIndexException
- if (isZooKeeperAware()) {
- CloudDescriptor desc = dcore.getCloudDescriptor();
- try {
- Replica leader = getZkController().getClusterState()
- .getCollection(desc.getCollectionName())
- .getSlice(desc.getShardId())
- .getLeader();
- if (leader != null && leader.getState() == State.ACTIVE) {
- log.info("Found active leader, will attempt to create fresh core and recover.");
- resetIndexDirectory(dcore, coreConfig);
- // the index of this core is emptied, its term should be set to 0
- getZkController().getShardTerms(desc.getCollectionName(), desc.getShardId()).setTermToZero(desc.getCoreNodeName());
- return new SolrCore(this, dcore, coreConfig);
- }
- } catch (SolrException se) {
- se.addSuppressed(original);
- throw se;
- }
- }
- throw original;
- case none:
- throw original;
- default:
- log.warn("Failed to create core, and did not recognize specified 'CoreInitFailedAction': [{}]. Valid options are {}.",
- action, Arrays.asList(CoreInitFailedAction.values()));
- throw original;
- }
- }
-
- /**
- * Write a new index directory for the a SolrCore, but do so without loading it.
- */
- private void resetIndexDirectory(CoreDescriptor dcore, ConfigSet coreConfig) {
- SolrConfig config = coreConfig.getSolrConfig();
-
- String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, dcore.getName());
- DirectoryFactory df = DirectoryFactory.loadDirectoryFactory(config, this, registryName);
- String dataDir = SolrCore.findDataDir(df, null, config, dcore);
-
- String tmpIdxDirName = "index." + new SimpleDateFormat(SnapShooter.DATE_FMT, Locale.ROOT).format(new Date());
- SolrCore.modifyIndexProps(df, dataDir, config, tmpIdxDirName);
-
- // Free the directory object that we had to create for this
- Directory dir = null;
- try {
- dir = df.get(dataDir, DirContext.META_DATA, config.indexConfig.lockType);
- } catch (IOException e) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
- } finally {
- try {
- df.release(dir);
- df.doneWithDirectory(dir);
- } catch (IOException e) {
- SolrException.log(log, e);
- }
- }
- }
-
- /**
- * @return a Collection of registered SolrCores
- */
- public Collection<SolrCore> getCores() {
- return solrCores.getCores();
- }
-
- /**
- * Gets the cores that are currently loaded, i.e. cores that have
- * 1: loadOnStartup=true and are either not-transient or, if transient, have been loaded and have not been aged out
- * 2: loadOnStartup=false and have been loaded but are either non-transient or have not been aged out.
- *
- * Put another way, this will not return any names of cores that are lazily loaded but have not been called for yet
- * or are transient and either not loaded or have been swapped out.
- *
- */
- public Collection<String> getLoadedCoreNames() {
- return solrCores.getLoadedCoreNames();
- }
-
- /** This method is currently experimental.
- *
- * @return a Collection of the names that a specific core object is mapped to, there are more than one.
- */
- public Collection<String> getNamesForCore(SolrCore core) {
- return solrCores.getNamesForCore(core);
- }
-
- /**
- * get a list of all the cores that are currently known, whether currently loaded or not
- * @return a list of all the available core names in either permanent or transient cores
- *
- */
- public Collection<String> getAllCoreNames() {
- return solrCores.getAllCoreNames();
-
- }
-
- /**
- * Returns an immutable Map of Exceptions that occured when initializing
- * SolrCores (either at startup, or do to runtime requests to create cores)
- * keyed off of the name (String) of the SolrCore that had the Exception
- * during initialization.
- * <p>
- * While the Map returned by this method is immutable and will not change
- * once returned to the client, the source data used to generate this Map
- * can be changed as various SolrCore operations are performed:
- * </p>
- * <ul>
- * <li>Failed attempts to create new SolrCores will add new Exceptions.</li>
- * <li>Failed attempts to re-create a SolrCore using a name already contained in this Map will replace the Exception.</li>
- * <li>Failed attempts to reload a SolrCore will cause an Exception to be added to this list -- even though the existing SolrCore with that name will continue to be available.</li>
- * <li>Successful attempts to re-created a SolrCore using a name already contained in this Map will remove the Exception.</li>
- * <li>Registering an existing SolrCore with a name already contained in this Map (ie: ALIAS or SWAP) will remove the Exception.</li>
- * </ul>
- */
- public Map<String, CoreLoadFailure> getCoreInitFailures() {
- return ImmutableMap.copyOf(coreInitFailures);
- }
-
-
- // ---------------- Core name related methods ---------------
-
- private CoreDescriptor reloadCoreDescriptor(CoreDescriptor oldDesc) {
- if (oldDesc == null) {
- return null;
- }
-
- CorePropertiesLocator cpl = new CorePropertiesLocator(null);
- CoreDescriptor ret = cpl.buildCoreDescriptor(oldDesc.getInstanceDir().resolve(PROPERTIES_FILENAME), this);
-
- // Ok, this little jewel is all because we still create core descriptors on the fly from lists of properties
- // in tests particularly. Theoretically, there should be _no_ way to create a CoreDescriptor in the new world
- // of core discovery without writing the core.properties file out first.
- //
- // TODO: remove core.properties from the conf directory in test files, it's in a bad place there anyway.
- if (ret == null) {
- oldDesc.loadExtraProperties(); // there may be changes to extra properties that we need to pick up.
- return oldDesc;
-
- }
- // The CloudDescriptor bit here is created in a very convoluted way, requiring access to private methods
- // in ZkController. When reloading, this behavior is identical to what used to happen where a copy of the old
- // CoreDescriptor was just re-used.
-
- if (ret.getCloudDescriptor() != null) {
- ret.getCloudDescriptor().reload(oldDesc.getCloudDescriptor());
- }
-
- return ret;
- }
-
- /**
- * Recreates a SolrCore.
- * While the new core is loading, requests will continue to be dispatched to
- * and processed by the old core
- *
- * @param name the name of the SolrCore to reload
- */
- public void reload(String name) {
- SolrCore core = solrCores.getCoreFromAnyList(name, false);
- if (core != null) {
-
- // The underlying core properties files may have changed, we don't really know. So we have a (perhaps) stale
- // CoreDescriptor and we need to reload it from the disk files
- CoreDescriptor cd = reloadCoreDescriptor(core.getCoreDescriptor());
- solrCores.addCoreDescriptor(cd);
- 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);
- 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?
- getZkController().stopReplicationFromLeader(core.getName());
- if (!cd.getCloudDescriptor().isLeader()) {
- getZkController().startReplicationFromLeader(newCore.getName(), true);
- }
-
- } else if(replica.getType() == Replica.Type.PULL) {
- getZkController().stopReplicationFromLeader(core.getName());
- getZkController().startReplicationFromLeader(newCore.getName(), false);
- }
- }
- } catch (SolrCoreState.CoreIsClosedException e) {
- throw e;
- } catch (Exception e) {
- coreInitFailures.put(cd.getName(), new CoreLoadFailure(cd, e));
- throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to reload core [" + cd.getName() + "]", e);
- }
- finally {
- solrCores.removeFromPendingOps(cd.getName());
- }
- } else {
- CoreLoadFailure clf = coreInitFailures.get(name);
- if (clf != null) {
- try {
- solrCores.waitAddPendingCoreOps(clf.cd.getName());
- createFromDescriptor(clf.cd, true, false);
- } finally {
- solrCores.removeFromPendingOps(clf.cd.getName());
- }
- } else {
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name );
- }
- }
- }
-
- /**
- * Swaps two SolrCore descriptors.
- */
- public void swap(String n0, String n1) {
- if( n0 == null || n1 == null ) {
- throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Can not swap unnamed cores." );
- }
- solrCores.swap(n0, n1);
-
- coresLocator.swap(this, solrCores.getCoreDescriptor(n0), solrCores.getCoreDescriptor(n1));
-
- log.info("swapped: " + n0 + " with " + n1);
- }
-
- /**
- * Unload a core from this container, leaving all files on disk
- * @param name the name of the core to unload
- */
- public void unload(String name) {
- unload(name, false, false, false);
- }
-
- /**
- * Unload a core from this container, optionally removing the core's data and configuration
- *
- * @param name the name of the core to unload
- * @param deleteIndexDir if true, delete the core's index on close
- * @param deleteDataDir if true, delete the core's data directory on close
- * @param deleteInstanceDir if true, delete the core's instance directory on close
- */
- public void unload(String name, boolean deleteIndexDir, boolean deleteDataDir, boolean deleteInstanceDir) {
-
- CoreDescriptor cd = solrCores.getCoreDescriptor(name);
-
- if (name != null) {
- // check for core-init errors first
- CoreLoadFailure loadFailure = coreInitFailures.remove(name);
- if (loadFailure != null) {
- // getting the index directory requires opening a DirectoryFactory with a SolrConfig, etc,
- // which we may not be able to do because of the init error. So we just go with what we
- // can glean from the CoreDescriptor - datadir and instancedir
- SolrCore.deleteUnloadedCore(loadFailure.cd, deleteDataDir, deleteInstanceDir);
- // If last time around we didn't successfully load, make sure that all traces of the coreDescriptor are gone.
- if (cd != null) {
- solrCores.removeCoreDescriptor(cd);
- coresLocator.delete(this, cd);
- }
- return;
- }
- }
-
- if (cd == null) {
- throw new SolrException(ErrorCode.BAD_REQUEST, "Cannot unload non-existent core [" + name + "]");
- }
-
- boolean close = solrCores.isLoadedNotPendingClose(name);
- SolrCore core = solrCores.remove(name);
-
- solrCores.removeCoreDescriptor(cd);
- coresLocator.delete(this, cd);
- if (core == null) {
- // transient core
- SolrCore.deleteUnloadedCore(cd, deleteDataDir, deleteInstanceDir);
- return;
- }
-
- // delete metrics specific to this core
- metricManager.removeRegistry(core.getCoreMetricManager().getRegistryName());
-
- if (zkSys.getZkController() != null) {
- // cancel recovery in cloud mode
- core.getSolrCoreState().cancelRecovery();
- if (cd.getCloudDescriptor().getReplicaType() == Replica.Type.PULL
- || cd.getCloudDescriptor().getReplicaType() == Replica.Type.TLOG) {
- // Stop replication if this is part of a pull/tlog replica before closing the core
- zkSys.getZkController().stopReplicationFromLeader(name);
- }
- }
-
- core.unloadOnClose(cd, deleteIndexDir, deleteDataDir, deleteInstanceDir);
- if (close)
- core.closeAndWait();
-
- if (zkSys.getZkController() != null) {
- try {
- zkSys.getZkController().unregister(name, cd);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new SolrException(ErrorCode.SERVER_ERROR, "Interrupted while unregistering core [" + name + "] from cloud state");
- } catch (KeeperException e) {
- throw new SolrException(ErrorCode.SERVER_ERROR, "Error unregistering core [" + name + "] from cloud state", e);
- } catch (Exception e) {
- throw new SolrException(ErrorCode.SERVER_ERROR, "Error unregistering core [" + name + "] from cloud state", e);
- }
- }
- }
-
- public void rename(String name, String toName) {
- SolrIdentifierValidator.validateCoreName(toName);
- try (SolrCore core = getCore(name)) {
- if (core != null) {
- String oldRegistryName = core.getCoreMetricManager().getRegistryName();
- String newRegistryName = SolrCoreMetricManager.createRegistryName(core, toName);
- metricManager.swapRegistries(oldRegistryName, newRegistryName);
- // The old coreDescriptor is obsolete, so remove it. registerCore will put it back.
- CoreDescriptor cd = core.getCoreDescriptor();
- solrCores.removeCoreDescriptor(cd);
- cd.setProperty("name", toName);
- solrCores.addCoreDescriptor(cd);
- core.setName(toName);
- registerCore(cd, core, true, false);
- SolrCore old = solrCores.remove(name);
-
- coresLocator.rename(this, old.getCoreDescriptor(), core.getCoreDescriptor());
- }
- }
- }
-
- /**
- * Get the CoreDescriptors for all cores managed by this container
- * @return a List of CoreDescriptors
- */
- public List<CoreDescriptor> getCoreDescriptors() {
- return solrCores.getCoreDescriptors();
- }
-
- public CoreDescriptor getCoreDescriptor(String coreName) {
- return solrCores.getCoreDescriptor(coreName);
- }
-
- public Path getCoreRootDirectory() {
- return cfg.getCoreRootDirectory();
- }
-
- /**
- * Gets a core by name and increase its refcount.
- *
- * @see SolrCore#close()
- * @param name the core name
- * @return the core if found, null if a SolrCore by this name does not exist
- * @exception SolrCoreInitializationException if a SolrCore with this name failed to be initialized
- */
- public SolrCore getCore(String name) {
-
- // Do this in two phases since we don't want to lock access to the cores over a load.
- SolrCore core = solrCores.getCoreFromAnyList(name, true);
-
- // If a core is loaded, we're done just return it.
- if (core != null) {
- return core;
- }
-
- // If it's not yet loaded, we can check if it's had a core init failure and "do the right thing"
- CoreDescriptor desc = solrCores.getCoreDescriptor(name);
-
- // if there was an error initializing this core, throw a 500
- // error with the details for clients attempting to access it.
- CoreLoadFailure loadFailure = getCoreInitFailures().get(name);
- if (null != loadFailure) {
- throw new SolrCoreInitializationException(name, loadFailure.exception);
- }
- // This is a bit of awkwardness where SolrCloud and transient cores don't play nice together. For transient cores,
- // we have to allow them to be created at any time there hasn't been a core load failure (use reload to cure that).
- // But for TestConfigSetsAPI.testUploadWithScriptUpdateProcessor, this needs to _not_ try to load the core if
- // the core is null and there was an error. If you change this, be sure to run both TestConfiSetsAPI and
- // TestLazyCores
- if (desc == null || zkSys.getZkController() != null) return null;
-
- // This will put an entry in pending core ops if the core isn't loaded. Here's where moving the
- // waitAddPendingCoreOps to createFromDescriptor would introduce a race condition.
- core = solrCores.waitAddPendingCoreOps(name);
-
- if (isShutDown) return null; // We're quitting, so stop. This needs to be after the wait above since we may come off
- // the wait as a consequence of shutting down.
- try {
- if (core == null) {
- if (zkSys.getZkController() != null) {
- zkSys.getZkController().throwErrorIfReplicaReplaced(desc);
- }
- core = createFromDescriptor(desc, true, false); // This should throw an error if it fails.
- }
- core.open();
- }
- finally {
- solrCores.removeFromPendingOps(name);
- }
-
- return core;
- }
-
- public BlobRepository getBlobRepository(){
- return blobRepository;
- }
-
- /**
- * If using asyncSolrCoreLoad=true, calling this after {@link #load()} will
- * not return until all cores have finished loading.
- *
- * @param timeoutMs timeout, upon which method simply returns
- */
- public void waitForLoadingCoresToFinish(long timeoutMs) {
- solrCores.waitForLoadingCoresToFinish(timeoutMs);
- }
-
- public void waitForLoadingCore(String name, long timeoutMs) {
- solrCores.waitForLoadingCoreToFinish(name, timeoutMs);
- }
-
- // ---------------- CoreContainer request handlers --------------
-
- protected <T> T createHandler(String path, String handlerClass, Class<T> clazz) {
- T handler = loader.newInstance(handlerClass, clazz, null, new Class[] { CoreContainer.class }, new Object[] { this });
- if (handler instanceof SolrRequestHandler) {
- containerHandlers.put(path, (SolrRequestHandler)handler);
- }
- if (handler instanceof SolrMetricProducer) {
- ((SolrMetricProducer)handler).initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, path);
- }
- return handler;
- }
-
- public CoreAdminHandler getMultiCoreHandler() {
- return coreAdminHandler;
- }
-
- public CollectionsHandler getCollectionsHandler() {
- return collectionsHandler;
- }
-
- public HealthCheckHandler getHealthCheckHandler() { return healthCheckHandler; }
-
- public InfoHandler getInfoHandler() {
- return infoHandler;
- }
-
- public ConfigSetsHandler getConfigSetsHandler() {
- return configSetsHandler;
- }
-
- public String getHostName() {
- return this.hostName;
- }
-
- /**
- * Gets the alternate path for multicore handling:
- * This is used in case there is a registered unnamed core (aka name is "") to
- * declare an alternate way of accessing named cores.
- * This can also be used in a pseudo single-core environment so admins can prepare
- * a new version before swapping.
- */
- public String getManagementPath() {
- return cfg.getManagementPath();
- }
-
- public LogWatcher getLogging() {
- return logging;
- }
-
- /**
- * Determines whether the core is already loaded or not but does NOT load the core
- *
- */
- public boolean isLoaded(String name) {
- return solrCores.isLoaded(name);
- }
-
- public boolean isLoadedNotPendingClose(String name) {
- return solrCores.isLoadedNotPendingClose(name);
- }
-
- /**
- * Gets a solr core descriptor for a core that is not loaded. Note that if the caller calls this on a
- * loaded core, the unloaded descriptor will be returned.
- *
- * @param cname - name of the unloaded core descriptor to load. NOTE:
- * @return a coreDescriptor. May return null
- */
- public CoreDescriptor getUnloadedCoreDescriptor(String cname) {
- return solrCores.getUnloadedCoreDescriptor(cname);
- }
-
- public String getSolrHome() {
- return solrHome;
- }
-
- public boolean isZooKeeperAware() {
- return zkSys.getZkController() != null;
- }
-
- public ZkController getZkController() {
- return zkSys.getZkController();
- }
-
- public NodeConfig getConfig() {
- return cfg;
- }
-
- /** The default ShardHandlerFactory used to communicate with other solr instances */
- public ShardHandlerFactory getShardHandlerFactory() {
- return shardHandlerFactory;
- }
-
- public UpdateShardHandler getUpdateShardHandler() {
- return updateShardHandler;
- }
-
- public SolrResourceLoader getResourceLoader() {
- return loader;
- }
-
- public boolean isCoreLoading(String name) {
- return solrCores.isCoreLoading(name);
- }
-
- public AuthorizationPlugin getAuthorizationPlugin() {
- return authorizationPlugin == null ? null : authorizationPlugin.plugin;
- }
-
- public AuthenticationPlugin getAuthenticationPlugin() {
- return authenticationPlugin == null ? null : authenticationPlugin.plugin;
- }
-
- public NodeConfig getNodeConfig() {
- return cfg;
- }
-
- public long getStatus() {
- return status;
- }
-
- // Occasaionally we need to access the transient cache handler in places other than coreContainer.
- public TransientSolrCoreCache getTransientCache() {
- return solrCores.getTransientCacheHandler();
- }
-
-
- /**
- *
- * @param cd CoreDescriptor, presumably a deficient one
- * @param prop The property that needs to be repaired.
- * @return true if we were able to successfuly perisist the repaired coreDescriptor, false otherwise.
- *
- * See SOLR-11503, This can be removed when there's no chance we'll need to upgrade a
- * Solr installation created with legacyCloud=true from 6.6.1 through 7.1
- */
- public boolean repairCoreProperty(CoreDescriptor cd, String prop) {
- // So far, coreNodeName is the only property that we need to repair, this may get more complex as other properties
- // are added.
-
- if (CoreDescriptor.CORE_NODE_NAME.equals(prop) == false) {
- throw new SolrException(ErrorCode.SERVER_ERROR,
- String.format(Locale.ROOT,"The only supported property for repair is currently [%s]",
- CoreDescriptor.CORE_NODE_NAME));
- }
-
- // Try to read the coreNodeName from the cluster state.
-
- String coreName = cd.getName();
- DocCollection coll = getZkController().getZkStateReader().getClusterState().getCollection(cd.getCollectionName());
- for (Replica rep : coll.getReplicas()) {
- if (coreName.equals(rep.getCoreName())) {
- log.warn("Core properties file for node {} found with no coreNodeName, attempting to repair with value {}. See SOLR-11503. " +
- "This message should only appear if upgrading from collections created Solr 6.6.1 through 7.1.",
- rep.getCoreName(), rep.getName());
- cd.getCloudDescriptor().setCoreNodeName(rep.getName());
- coresLocator.persist(this, cd);
- return true;
- }
- }
- log.error("Could not repair coreNodeName in core.properties file for core {}", coreName);
- return false;
- }
-
- /**
- * @param solrCore te core against which we check if there has been a tragic exception
- * @return whether this solr core has tragic exception
- */
- public boolean checkTragicException(SolrCore solrCore) {
- Throwable tragicException;
- try {
- tragicException = solrCore.getSolrCoreState().getTragicException();
- } catch (IOException e) {
- // failed to open an indexWriter
- tragicException = e;
- }
-
- if (tragicException != null) {
- if (isZooKeeperAware()) {
- getZkController().giveupLeadership(solrCore.getCoreDescriptor(), tragicException);
- }
- }
-
- return tragicException != null;
- }
-
-}
-
-class CloserThread extends Thread {
- CoreContainer container;
- SolrCores solrCores;
- NodeConfig cfg;
-
-
- CloserThread(CoreContainer container, SolrCores solrCores, NodeConfig cfg) {
- this.container = container;
- this.solrCores = solrCores;
- this.cfg = cfg;
- }
-
- // It's important that this be the _only_ thread removing things from pendingDynamicCloses!
- // This is single-threaded, but I tried a multi-threaded approach and didn't see any performance gains, so
- // there's no good justification for the complexity. I suspect that the locking on things like DefaultSolrCoreState
- // essentially create a single-threaded process anyway.
- @Override
- public void run() {
- while (! container.isShutDown()) {
- synchronized (solrCores.getModifyLock()) { // need this so we can wait and be awoken.
- try {
- solrCores.getModifyLock().wait();
- } catch (InterruptedException e) {
- // Well, if we've been told to stop, we will. Otherwise, continue on and check to see if there are
- // any cores to close.
- }
- }
- for (SolrCore removeMe = solrCores.getCoreToClose();
- removeMe != null && !container.isShutDown();
- removeMe = solrCores.getCoreToClose()) {
- try {
- removeMe.close();
- } finally {
- solrCores.removeFromPendingOps(removeMe.getName());
- }
- }
- }
- }
-}