/** * 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) throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name); CoreDescriptor cd = core.getCoreDescriptor(); try { solrCores.waitAddPendingCoreOps(name); ConfigSet coreConfig = coreConfigService.getConfig(cd); log.info( "Reloading SolrCore '{}' using configuration from {}", cd.getName(), coreConfig.getName()); SolrCore newCore = core.reload(coreConfig); registerCore(name, newCore, 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(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, 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) { 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); return; } } CoreDescriptor cd = solrCores.getCoreDescriptor(name); 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); coresLocator.delete(this, cd); if (core == null) { // transient core SolrCore.deleteUnloadedCore(cd, deleteDataDir, deleteInstanceDir); return; } if (zkSys.getZkController() != null) { // cancel recovery in cloud mode core.getSolrCoreState().cancelRecovery(); } core.unloadOnClose(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); } } }
/** * 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 SolrException 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 (core != null) { return core; } // OK, it's not presently in any list, is it in the list of dynamic cores but not loaded yet? If // so, load it. CoreDescriptor desc = solrCores.getDynamicDescriptor(name); if (desc == null) { // Nope, no transient core with this 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 SolrException( ErrorCode.SERVER_ERROR, "SolrCore '" + name + "' is not available due to init failure: " + loadFailure.exception.getMessage(), loadFailure.exception); } // otherwise the user is simply asking for something that doesn't exist. return null; } // This will put an entry in pending core ops if the core isn't loaded 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 = create(desc, true); // This should throw an error if it fails. } core.open(); } finally { solrCores.removeFromPendingOps(name); } return core; }
protected SolrCore registerCore(String name, SolrCore core, boolean registerInZk) { if (core == null) { throw new RuntimeException("Can not register a null core."); } // We can register a core when creating them via the admin UI, so we need to ensure that the // dynamic descriptors // are up to date CoreDescriptor cd = core.getCoreDescriptor(); if ((cd.isTransient() || !cd.isLoadOnStartup()) && solrCores.getDynamicDescriptor(name) == null) { // Store it away for later use. includes non-transient but not // loaded at startup cores. solrCores.putDynamicDescriptor(name, cd); } SolrCore old; if (isShutDown) { core.close(); throw new IllegalStateException("This CoreContainer has been closed"); } if (cd.isTransient()) { old = solrCores.putTransientCore(cfg, name, core, loader); } else { old = solrCores.putCore(name, core); } /* * set both the name of the descriptor and the name of the * core, since the descriptors name is used for persisting. */ core.setName(name); coreInitFailures.remove(name); if (old == null || old == core) { log.info("registering core: " + name); if (registerInZk) { zkSys.registerInZk(core, false); } return null; } else { log.info("replacing core: " + name); old.close(); if (registerInZk) { zkSys.registerInZk(core, false); } return old; } }
public void rename(String name, String toName) { SolrIdentifierValidator.validateCoreName(toName); try (SolrCore core = getCore(name)) { if (core != null) { registerCore(toName, core, true); SolrCore old = solrCores.remove(name); coresLocator.rename(this, old.getCoreDescriptor(), core.getCoreDescriptor()); } } }
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); } } }
// 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()); } } } }
/** Stops all cores. */ public void shutdown() { log.info("Shutting down CoreContainer instance=" + System.identityHashCode(this)); isShutDown = true; ExecutorUtil.shutdownAndAwaitTermination(coreContainerWorkExecutor); if (isZooKeeperAware()) { cancelCoreRecoveries(); zkSys.zkController.publishNodeAsDown(zkSys.zkController.getNodeName()); } 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 { backgroundCloser.join(); } 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 }
/** Load the cores defined for this CoreContainer */ public void load() { log.info("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) { log.warn("Couldn't add files from {} to classpath: {}", libPath, e.getMessage()); } } shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader); updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig()); solrCores.allocateLazyCores(cfg.getTransientCacheSize(), 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()); ZkStateReader.ConfigData securityConfig = isZooKeeperAware() ? getZkController().getZkStateReader().getSecurityProps(false) : new ZkStateReader.ConfigData(EMPTY_MAP, -1); initializeAuthorizationPlugin((Map<String, Object>) securityConfig.data.get("authorization")); initializeAuthenticationPlugin((Map<String, Object>) securityConfig.data.get("authentication")); this.backupRepoFactory = new BackupRepositoryFactory(cfg.getBackupRepositoryPlugins()); containerHandlers.put(ZK_PATH, new ZookeeperInfoHandler(this)); securityConfHandler = new SecurityConfHandler(this); collectionsHandler = createHandler(cfg.getCollectionsHandlerClass(), CollectionsHandler.class); containerHandlers.put(COLLECTIONS_HANDLER_PATH, collectionsHandler); infoHandler = createHandler(cfg.getInfoHandlerClass(), InfoHandler.class); containerHandlers.put(INFO_HANDLER_PATH, infoHandler); coreAdminHandler = createHandler(cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class); containerHandlers.put(CORES_HANDLER_PATH, coreAdminHandler); configSetsHandler = createHandler(cfg.getConfigSetsHandlerClass(), ConfigSetsHandler.class); containerHandlers.put(CONFIGSETS_HANDLER_PATH, configSetsHandler); containerHandlers.put(AUTHZ_PATH, securityConfHandler); containerHandlers.put(AUTHC_PATH, securityConfHandler); if (pkiAuthenticationPlugin != null) containerHandlers.put( PKIAuthenticationPlugin.PATH, pkiAuthenticationPlugin.getRequestHandler()); coreConfigService = ConfigSetService.createConfigSetService(cfg, loader, zkSys.zkController); containerProperties.putAll(cfg.getSolrProperties()); // setup executor to load cores in parallel ExecutorService coreLoadExecutor = ExecutorUtil.newMDCAwareFixedThreadPool( cfg.getCoreLoadThreadCount( isZooKeeperAware() ? DEFAULT_CORE_LOAD_THREADS_IN_CLOUD : DEFAULT_CORE_LOAD_THREADS), new DefaultSolrThreadFactory("coreLoadExecutor")); 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); for (final CoreDescriptor cd : cds) { if (cd.isTransient() || !cd.isLoadOnStartup()) { solrCores.putDynamicDescriptor(cd.getName(), 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); } core = create(cd, false); } finally { if (asyncSolrCoreLoad) { solrCores.markCoreAsNotLoading(cd); } } try { zkSys.registerInZk(core, true); } 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( (Runnable) () -> { 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 created", e); } } } finally { ExecutorUtil.shutdownAndAwaitTermination(coreLoadExecutor); } }); } else { ExecutorUtil.shutdownAndAwaitTermination(coreLoadExecutor); } } if (isZooKeeperAware()) { zkSys.getZkController().checkOverseerDesignate(); } }
public boolean isCoreLoading(String name) { return solrCores.isCoreLoading(name); }
/** * This method is currently experimental. * * @return a Collection of the names that a specific core is mapped to. */ public Collection<String> getCoreNames(SolrCore core) { return solrCores.getCoreNames(core); }
/** 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 void waitForLoadingCore(String name, long timeoutMs) { solrCores.waitForLoadingCoreToFinish(name, timeoutMs); }
/** * 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); }
/** * Get the CoreDescriptors for all cores managed by this container * * @return a List of CoreDescriptors */ public List<CoreDescriptor> getCoreDescriptors() { return solrCores.getCoreDescriptors(); }
/** @return a Collection of registered SolrCores */ public Collection<SolrCore> getCores() { return solrCores.getCores(); }
public boolean isLoadedNotPendingClose(String name) { return solrCores.isLoadedNotPendingClose(name); }
/** * get a list of all the cores that are currently loaded * * @return a list of al lthe available core names in either permanent or transient core lists. */ public Collection<String> getAllCoreNames() { return solrCores.getAllCoreNames(); }
/** * 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); }