diff --git a/solr/core/src/java/org/apache/solr/core/BlobRepository.java b/solr/core/src/java/org/apache/solr/core/BlobRepository.java index b9a1e731a38..24bb88e0807 100644 --- a/solr/core/src/java/org/apache/solr/core/BlobRepository.java +++ b/solr/core/src/java/org/apache/solr/core/BlobRepository.java @@ -60,7 +60,7 @@ import static org.apache.solr.common.cloud.ZkStateReader.BASE_URL_PROP; * The purpose of this class is to store the Jars loaded in memory and to keep only one copy of the Jar in a single node. */ public class BlobRepository { - private static final long MAX_JAR_SIZE = Long.parseLong(System.getProperty("runtme.lib.size", String.valueOf(5* 1024*1024))); + private static final long MAX_JAR_SIZE = Long.parseLong(System.getProperty("runtme.lib.size", String.valueOf(5 * 1024 * 1024))); private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); static final Random RANDOM; static final Pattern BLOB_KEY_PATTERN_CHECKER = Pattern.compile(".*/\\d+"); @@ -89,8 +89,9 @@ public class BlobRepository { } // I wanted to {@link SolrCore#loadDecodeAndCacheBlob(String, Decoder)} below but precommit complains + /** - * Returns the contents of a blob containing a ByteBuffer and increments a reference count. Please return the + * Returns the contents of a blob containing a ByteBuffer and increments a reference count. Please return the * same object to decrease the refcount. This is normally used for storing jar files, and binary raw data. * If you are caching Java Objects you want to use {@code SolrCore#loadDecodeAndCacheBlob(String, Decoder)} * @@ -98,27 +99,27 @@ public class BlobRepository { * @return The reference of a blob */ public BlobContentRef getBlobIncRef(String key) { - return getBlobIncRef(key, () -> addBlob(key)); + return getBlobIncRef(key, () -> addBlob(key)); } - + /** - * Internal method that returns the contents of a blob and increments a reference count. Please return the same - * object to decrease the refcount. Only the decoded content will be cached when this method is used. Component - * authors attempting to share objects across cores should use + * Internal method that returns the contents of a blob and increments a reference count. Please return the same + * object to decrease the refcount. Only the decoded content will be cached when this method is used. Component + * authors attempting to share objects across cores should use * {@code SolrCore#loadDecodeAndCacheBlob(String, Decoder)} which ensures that a proper close hook is also created. * - * @param key it is a combination of blob name and version like blobName/version + * @param key it is a combination of blob name and version like blobName/version * @param decoder a decoder that knows how to interpret the bytes from the blob * @return The reference of a blob */ BlobContentRef getBlobIncRef(String key, Decoder decoder) { - return getBlobIncRef(key.concat(decoder.getName()), () -> addBlob(key,decoder)); + return getBlobIncRef(key.concat(decoder.getName()), () -> addBlob(key, decoder)); } BlobContentRef getBlobIncRef(String key, Decoder decoder, String url, String sha512) { StringBuffer keyBuilder = new StringBuffer(key); - if (decoder != null) keyBuilder .append( decoder.getName()); - keyBuilder.append("/").append( sha512); + if (decoder != null) keyBuilder.append(decoder.getName()); + keyBuilder.append("/").append(sha512); return getBlobIncRef(keyBuilder.toString(), () -> new BlobContent<>(key, fetchBlobAndVerify(key, url, sha512), decoder)); } @@ -133,7 +134,7 @@ public class BlobRepository { try { aBlob = blobCreator.call(); } catch (Exception e) { - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Blob loading failed: "+e.getMessage(), e); + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Blob loading failed: " + e.getMessage(), e); } } } @@ -151,7 +152,7 @@ public class BlobRepository { // For use cases sharing raw bytes private BlobContent addBlob(String key) { ByteBuffer b = fetchBlob(key); - BlobContent aBlob = new BlobContent<>(key, b); + BlobContent aBlob = new BlobContent<>(key, b); blobs.put(key, aBlob); return aBlob; } @@ -159,11 +160,12 @@ public class BlobRepository { // for use cases sharing java objects private BlobContent addBlob(String key, Decoder decoder) { ByteBuffer b = fetchBlob(key); - String keyPlusName = key + decoder.getName(); + String keyPlusName = key + decoder.getName(); BlobContent aBlob = new BlobContent<>(keyPlusName, b, decoder); blobs.put(keyPlusName, aBlob); return aBlob; } + static String INVALID_JAR_MSG = "Invalid jar from {0} , expected sha512 hash : {1} , actual : {2}"; private ByteBuffer fetchBlobAndVerify(String key, String url, String sha512) { @@ -193,7 +195,7 @@ public class BlobRepository { /** - * Package local for unit tests only please do not use elsewhere + * Package local for unit tests only please do not use elsewhere */ ByteBuffer fetchBlob(String key) { Replica replica = getSystemCollReplica(); @@ -234,9 +236,11 @@ public class BlobRepository { ZkStateReader zkStateReader = this.coreContainer.getZkController().getZkStateReader(); ClusterState cs = zkStateReader.getClusterState(); DocCollection coll = cs.getCollectionOrNull(CollectionAdminParams.SYSTEM_COLL); - if (coll == null) throw new SolrException(SERVICE_UNAVAILABLE, CollectionAdminParams.SYSTEM_COLL + " collection not available"); + if (coll == null) + throw new SolrException(SERVICE_UNAVAILABLE, CollectionAdminParams.SYSTEM_COLL + " collection not available"); ArrayList slices = new ArrayList<>(coll.getActiveSlices()); - if (slices.isEmpty()) throw new SolrException(SERVICE_UNAVAILABLE, "No active slices for " + CollectionAdminParams.SYSTEM_COLL + " collection"); + if (slices.isEmpty()) + throw new SolrException(SERVICE_UNAVAILABLE, "No active slices for " + CollectionAdminParams.SYSTEM_COLL + " collection"); Collections.shuffle(slices, RANDOM); //do load balancing Replica replica = null; @@ -245,7 +249,7 @@ public class BlobRepository { Collections.shuffle(replicas, RANDOM); for (Replica r : replicas) { if (r.getState() == Replica.State.ACTIVE) { - if(zkStateReader.getClusterState().getLiveNodes().contains(r.get(ZkStateReader.NODE_NAME_PROP))){ + if (zkStateReader.getClusterState().getLiveNodes().contains(r.get(ZkStateReader.NODE_NAME_PROP))) { replica = r; break; } else { @@ -291,12 +295,12 @@ public class BlobRepository { @SuppressWarnings("unchecked") public BlobContent(String key, ByteBuffer buffer) { this.key = key; - this.content = (T) buffer; + this.content = (T) buffer; } /** - * Get the cached object. - * + * Get the cached object. + * * @return the object representing the content that is cached. */ public T get() { @@ -310,14 +314,16 @@ public class BlobRepository { /** * A name by which to distinguish this decoding. This only needs to be implemented if you want to support * decoding the same blob content with more than one decoder. - * + * * @return The name of the decoding, defaults to empty string. */ - default String getName() { return ""; } + default String getName() { + return ""; + } /** * A routine that knows how to convert the stream of bytes from the blob into a Java object. - * + * * @param inputStream the bytes from a blob * @return A Java object of the specified type. */ diff --git a/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java index 8b8c740523b..24f5a23452a 100644 --- a/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java +++ b/solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java @@ -44,9 +44,8 @@ import org.slf4j.LoggerFactory; * A {@link DirectoryFactory} impl base class for caching Directory instances * per path. Most DirectoryFactory implementations will want to extend this * class and simply implement {@link DirectoryFactory#create(String, LockFactory, DirContext)}. - * + *

* This is an expert class and these API's are subject to change. - * */ public abstract class CachingDirectoryFactory extends DirectoryFactory { protected static class CacheValue { @@ -56,7 +55,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { //final Exception originTrace; // use the setter! private boolean deleteOnClose = false; - + public CacheValue(String path, Directory directory) { this.path = path; this.directory = directory; @@ -64,6 +63,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { // for debug // this.originTrace = new RuntimeException("Originated from:"); } + public int refCnt = 1; // has doneWithDirectory(Directory) been called on this? public boolean closeCacheValueCalled = false; @@ -79,21 +79,21 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { this.deleteOnClose = deleteOnClose; this.deleteAfterCoreClose = deleteAfterCoreClose; } - + @Override public String toString() { return "CachedDir<<" + "refCount=" + refCnt + ";path=" + path + ";done=" + doneWithDir + ">>"; } } - + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - protected Map byPathCache = new HashMap<>(); - - protected Map byDirectoryCache = new IdentityHashMap<>(); - - protected Map> closeListeners = new HashMap<>(); - + + protected Map byPathCache = new HashMap<>(); + + protected Map byDirectoryCache = new IdentityHashMap<>(); + + protected Map> closeListeners = new HashMap<>(); + protected Set removeEntries = new HashSet<>(); private Double maxWriteMBPerSecFlush; @@ -105,13 +105,13 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { private Double maxWriteMBPerSecDefault; private boolean closed; - + public interface CloseListener { public void postClose(); public void preClose(); } - + @Override public void addCloseListener(Directory dir, CloseListener closeListener) { synchronized (this) { @@ -125,11 +125,11 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { closeListeners.put(dir, listeners); } listeners.add(closeListener); - + closeListeners.put(dir, listeners); } } - + @Override public void doneWithDirectory(Directory directory) throws IOException { synchronized (this) { @@ -148,10 +148,10 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { } } } - + /* * (non-Javadoc) - * + * * @see org.apache.solr.core.DirectoryFactory#close() */ @Override @@ -161,15 +161,15 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { this.closed = true; Collection values = byDirectoryCache.values(); for (CacheValue val : values) { - log.debug("Closing {} - currently tracking: {}", - this.getClass().getSimpleName(), val); + log.debug("Closing {} - currently tracking: {}", + this.getClass().getSimpleName(), val); try { // if there are still refs out, we have to wait for them assert val.refCnt > -1 : val.refCnt; int cnt = 0; - while(val.refCnt != 0) { + while (val.refCnt != 0) { wait(100); - + if (cnt++ >= 120) { String msg = "Timeout waiting for all directory ref counts to be released - gave up waiting on " + val; log.error(msg); @@ -183,7 +183,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { SolrException.log(log, "Error closing directory", e); } } - + values = byDirectoryCache.values(); Set closedDirs = new HashSet<>(); for (CacheValue val : values) { @@ -209,7 +209,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { SolrException.log(log, "Error removing directory", e); } } - + for (CacheValue v : closedDirs) { removeFromCache(v); } @@ -240,7 +240,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { if (cacheValue.deleteOnClose) { // see if we are a subpath Collection values = byPathCache.values(); - + Collection cacheValues = new ArrayList<>(values); cacheValues.remove(cacheValue); for (CacheValue otherCacheValue : cacheValues) { @@ -279,7 +279,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { removeEntries.add(val); } } - + if (listeners != null) { for (CloseListener listener : listeners) { try { @@ -311,38 +311,38 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { private boolean isSubPath(CacheValue cacheValue, CacheValue otherCacheValue) { int one = cacheValue.path.lastIndexOf('/'); int two = otherCacheValue.path.lastIndexOf('/'); - + return otherCacheValue.path.startsWith(cacheValue.path + "/") && two > one; } - + @Override public boolean exists(String path) throws IOException { // back compat behavior File dirFile = new File(path); return dirFile.canRead() && dirFile.list().length > 0; } - + /* * (non-Javadoc) - * + * * @see org.apache.solr.core.DirectoryFactory#get(java.lang.String, * java.lang.String, boolean) */ @Override - public final Directory get(String path, DirContext dirContext, String rawLockType) + public final Directory get(String path, DirContext dirContext, String rawLockType) throws IOException { String fullPath = normalize(path); synchronized (this) { if (closed) { throw new AlreadyClosedException("Already closed"); } - + final CacheValue cacheValue = byPathCache.get(fullPath); Directory directory = null; if (cacheValue != null) { directory = cacheValue.directory; } - + if (directory == null) { directory = create(fullPath, createLockFactory(rawLockType), dirContext); assert ObjectReleaseTracker.track(directory); @@ -362,14 +362,14 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { cacheValue.refCnt++; log.debug("Reusing cached directory: {}", cacheValue); } - + return directory; } } /* * (non-Javadoc) - * + * * @see * org.apache.solr.core.DirectoryFactory#incRef(org.apache.lucene.store.Directory * ) @@ -384,12 +384,12 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { if (cacheValue == null) { throw new IllegalArgumentException("Unknown directory: " + directory); } - + cacheValue.refCnt++; log.debug("incRef'ed: {}", cacheValue); } } - + @Override public void init(NamedList args) { maxWriteMBPerSecFlush = (Double) args.get("maxWriteMBPerSecFlush"); @@ -405,10 +405,10 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { log.info(SolrXmlConfig.SOLR_DATA_HOME + "=" + dataHomePath); } } - + /* * (non-Javadoc) - * + * * @see * org.apache.solr.core.DirectoryFactory#release(org.apache.lucene.store.Directory * ) @@ -421,7 +421,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { synchronized (this) { // don't check if already closed here - we need to able to release // while #close() waits. - + CacheValue cacheValue = byDirectoryCache.get(directory); if (cacheValue == null) { throw new IllegalArgumentException("Unknown directory: " + directory @@ -430,7 +430,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { log.debug("Releasing directory: " + cacheValue.path + " " + (cacheValue.refCnt - 1) + " " + cacheValue.doneWithDir); cacheValue.refCnt--; - + assert cacheValue.refCnt >= 0 : cacheValue.refCnt; if (cacheValue.refCnt == 0 && cacheValue.doneWithDir && !closed) { @@ -441,17 +441,17 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { } } } - + @Override public void remove(String path) throws IOException { remove(path, false); } - + @Override public void remove(Directory dir) throws IOException { remove(dir, false); } - + @Override public void remove(String path, boolean deleteAfterCoreClose) throws IOException { synchronized (this) { @@ -462,7 +462,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { val.setDeleteOnClose(true, deleteAfterCoreClose); } } - + @Override public void remove(Directory dir, boolean deleteAfterCoreClose) throws IOException { synchronized (this) { @@ -473,28 +473,28 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { val.setDeleteOnClose(true, deleteAfterCoreClose); } } - + protected synchronized void removeDirectory(CacheValue cacheValue) throws IOException { - // this page intentionally left blank + // this page intentionally left blank } - + @Override public String normalize(String path) throws IOException { path = stripTrailingSlash(path); return path; } - + protected String stripTrailingSlash(String path) { if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); } return path; } - + /** * Method for inspecting the cache - * @return paths in the cache which have not been marked "done" * + * @return paths in the cache which have not been marked "done" * @see #doneWithDirectory */ public synchronized Set getLivePaths() { @@ -506,7 +506,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { } return livePaths; } - + @Override protected boolean deleteOldIndexDirectory(String oldDirPath) throws IOException { Set livePaths = getLivePaths(); @@ -517,7 +517,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory { return super.deleteOldIndexDirectory(oldDirPath); } - + protected synchronized String getPath(Directory directory) { return byDirectoryCache.get(directory).path; } diff --git a/solr/core/src/java/org/apache/solr/core/CloudConfig.java b/solr/core/src/java/org/apache/solr/core/CloudConfig.java index 15ccf3c1310..4d0f41097b8 100644 --- a/solr/core/src/java/org/apache/solr/core/CloudConfig.java +++ b/solr/core/src/java/org/apache/solr/core/CloudConfig.java @@ -41,12 +41,12 @@ public class CloudConfig { private final String zkCredentialsProviderClass; private final String zkACLProviderClass; - + private final int createCollectionWaitTimeTillActive; - + private final boolean createCollectionCheckLeaderActive; - CloudConfig(String zkHost, int zkClientTimeout, int hostPort, String hostName, String hostContext, boolean useGenericCoreNames, + CloudConfig(String zkHost, int zkClientTimeout, int hostPort, String hostName, String hostContext, boolean useGenericCoreNames, int leaderVoteWait, int leaderConflictResolveWait, int autoReplicaFailoverWaitAfterExpiration, String zkCredentialsProviderClass, String zkACLProviderClass, int createCollectionWaitTimeTillActive, boolean createCollectionCheckLeaderActive) { @@ -128,8 +128,8 @@ public class CloudConfig { private static final int DEFAULT_LEADER_VOTE_WAIT = 180000; // 3 minutes private static final int DEFAULT_LEADER_CONFLICT_RESOLVE_WAIT = 180000; private static final int DEFAULT_CREATE_COLLECTION_ACTIVE_WAIT = 45; // 45 seconds - private static final boolean DEFAULT_CREATE_COLLECTION_CHECK_LEADER_ACTIVE = false; - + private static final boolean DEFAULT_CREATE_COLLECTION_CHECK_LEADER_ACTIVE = false; + private static final int DEFAULT_AUTO_REPLICA_FAILOVER_WAIT_AFTER_EXPIRATION = 120000; private String zkHost = System.getProperty("zkHost"); @@ -200,16 +200,16 @@ public class CloudConfig { this.createCollectionWaitTimeTillActive = createCollectionWaitTimeTillActive; return this; } - + public CloudConfigBuilder setCreateCollectionCheckLeaderActive(boolean createCollectionCheckLeaderActive) { this.createCollectionCheckLeaderActive = createCollectionCheckLeaderActive; return this; } - + public CloudConfig build() { - return new CloudConfig(zkHost, zkClientTimeout, hostPort, hostName, hostContext, useGenericCoreNames, leaderVoteWait, - leaderConflictResolveWait, autoReplicaFailoverWaitAfterExpiration, zkCredentialsProviderClass, zkACLProviderClass, createCollectionWaitTimeTillActive, - createCollectionCheckLeaderActive); + return new CloudConfig(zkHost, zkClientTimeout, hostPort, hostName, hostContext, useGenericCoreNames, leaderVoteWait, + leaderConflictResolveWait, autoReplicaFailoverWaitAfterExpiration, zkCredentialsProviderClass, zkACLProviderClass, createCollectionWaitTimeTillActive, + createCollectionCheckLeaderActive); } } } diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetProperties.java b/solr/core/src/java/org/apache/solr/core/ConfigSetProperties.java index 3ecffe12fb3..703fc09722d 100644 --- a/solr/core/src/java/org/apache/solr/core/ConfigSetProperties.java +++ b/solr/core/src/java/org/apache/solr/core/ConfigSetProperties.java @@ -42,7 +42,7 @@ public class ConfigSetProperties { * Return the properties associated with the ConfigSet (e.g. immutable) * * @param loader the resource loader - * @param name the name of the config set properties file + * @param name the name of the config set properties file * @return the properties in a NamedList */ public static NamedList readFromResourceLoader(SolrResourceLoader loader, String name) { @@ -70,7 +70,7 @@ public class ConfigSetProperties { final String objectClass = object == null ? "null" : object.getClass().getName(); throw new SolrException(ErrorCode.SERVER_ERROR, "Invalid JSON type " + objectClass + ", expected Map"); } - return new NamedList((Map)object); + return new NamedList((Map) object); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to load ConfigSet properties", ex); } finally { 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 625fbac2bd7..35523433110 100644 --- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java +++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java @@ -134,7 +134,6 @@ 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 { @@ -175,7 +174,7 @@ public class CoreContainer { private volatile UpdateShardHandler updateShardHandler; private volatile ExecutorService coreContainerWorkExecutor = ExecutorUtil.newMDCAwareCachedThreadPool( - new DefaultSolrThreadFactory("coreContainerWorkExecutor") ); + new DefaultSolrThreadFactory("coreContainerWorkExecutor")); private final OrderedExecutor replayUpdatesExecutor; @@ -204,7 +203,7 @@ public class CoreContainer { private volatile SecurityPluginHolder authenticationPlugin; private SecurityPluginHolder auditloggerPlugin; - + private volatile BackupRepositoryFactory backupRepoFactory; protected volatile SolrMetricManager metricManager; @@ -230,7 +229,7 @@ public class CoreContainer { private ExecutorService coreContainerAsyncTaskExecutor = ExecutorUtil.newMDCAwareCachedThreadPool("Core Container Async Task"); - private enum CoreInitFailedAction { fromleader, none } + private enum CoreInitFailedAction {fromleader, none} /** * This method instantiates a new instance of {@linkplain BackupRepository}. @@ -268,6 +267,7 @@ public class CoreContainer { /** * Create a new CoreContainer using system properties to detect the solr home * directory. The container's cores are not loaded. + * * @see #load() */ public CoreContainer() { @@ -277,6 +277,7 @@ public class CoreContainer { /** * Create a new CoreContainer using the given SolrResourceLoader. The container's * cores are not loaded. + * * @param loader the SolrResourceLoader * @see #load() */ @@ -287,6 +288,7 @@ public class CoreContainer { /** * 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() */ @@ -298,6 +300,7 @@ public class CoreContainer { * 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() */ @@ -399,10 +402,10 @@ public class CoreContainer { } catch (Exception e) { log.error("Exception while attempting to close old auditlogger plugin", e); } - } + } } - + private synchronized void initializeAuthenticationPlugin(Map authenticationConfig) { authenticationConfig = Utils.getDeepCopy(authenticationConfig, 4); int newVersion = readVersion(authenticationConfig); @@ -416,7 +419,7 @@ public class CoreContainer { } if (pluginClassName != null) { - log.debug("Authentication plugin class obtained from security.json: "+pluginClassName); + 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 '" + @@ -529,7 +532,8 @@ public class CoreContainer { /** * Create a new CoreContainer and load its cores - * @param solrHome the solr home directory + * + * @param solrHome the solr home directory * @param configFile the file containing this container's configuration * @return a loaded CoreContainer */ @@ -576,7 +580,7 @@ public class CoreContainer { /** * Load the cores defined for this CoreContainer */ - public void load() { + 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 @@ -617,7 +621,7 @@ public class CoreContainer { hostName = cfg.getNodeName(); zkSys.initZooKeeper(this, solrHome, cfg.getCloudConfig()); - if(isZooKeeperAware()) { + if (isZooKeeperAware()) { pkiAuthenticationPlugin = new PKIAuthenticationPlugin(this, zkSys.getZkController().getNodeName(), (PublicKeyHandler) containerHandlers.get(PublicKeyHandler.PATH)); TracerConfigurator.loadTracer(loader, cfg.getTracerConfiguratorPluginInfo(), getZkController().getZkStateReader()); @@ -632,8 +636,8 @@ public class CoreContainer { 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); - infoHandler = createHandler(INFO_HANDLER_PATH, cfg.getInfoHandlerClass(), InfoHandler.class); - coreAdminHandler = createHandler(CORES_HANDLER_PATH, cfg.getCoreAdminHandlerClass(), CoreAdminHandler.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 @@ -667,18 +671,18 @@ public class CoreContainer { 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"); + 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"); + 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"); + 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"); + metricTag, true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs"); metricManager.registerGauge(null, registryName, () -> dataHome.toFile().getUsableSpace(), - metricTag,true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs"); + metricTag, true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs"); metricManager.registerGauge(null, registryName, () -> dataHome.toAbsolutePath().toString(), - metricTag,true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs"); + metricTag, true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs"); metricManager.registerGauge(null, registryName, () -> { try { return org.apache.lucene.util.IOUtils.spins(dataHome.toAbsolutePath()); @@ -687,13 +691,13 @@ public class CoreContainer { return true; } }, - metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs"); + 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"); + 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"); + 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"); + metricTag, true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot"); metricManager.registerGauge(null, registryName, () -> { try { return org.apache.lucene.util.IOUtils.spins(cfg.getCoreRootDirectory().toAbsolutePath()); @@ -702,12 +706,12 @@ public class CoreContainer { return true; } }, - metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot"); + 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"); + metricTag, true, "specification", SolrInfoBean.Category.CONTAINER.toString(), "version"); metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getImplementationVersion(), - metricTag,true, "implementation", SolrInfoBean.Category.CONTAINER.toString(), "version"); + metricTag, true, "implementation", SolrInfoBean.Category.CONTAINER.toString(), "version"); SolrFieldCacheBean fieldCacheBean = new SolrFieldCacheBean(); fieldCacheBean.initializeMetrics(metricManager, registryName, metricTag, null); @@ -1054,8 +1058,8 @@ public class CoreContainer { } protected SolrCore registerCore(CoreDescriptor cd, SolrCore core, boolean registerInZk, boolean skipRecovery) { - if( core == null ) { - throw new RuntimeException( "Can not register a null core." ); + if (core == null) { + throw new RuntimeException("Can not register a null core."); } if (isShutDown) { @@ -1063,24 +1067,23 @@ public class CoreContainer { 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. - */ + /* + * 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 (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() ); + } else { + log.debug("replacing core: " + cd.getName()); old.close(); if (registerInZk) { zkSys.registerInZk(core, false, skipRecovery); @@ -1091,7 +1094,8 @@ public class CoreContainer { /** * Creates a new core, publishing the core state to the cluster - * @param coreName the core name + * + * @param coreName the core name * @param parameters the core parameters * @return the newly created core */ @@ -1101,9 +1105,10 @@ public class CoreContainer { /** * Creates a new core in a specified instance directory, publishing the core state to the cluster - * @param coreName the core name + * + * @param coreName the core name * @param instancePath the instance directory - * @param parameters the core parameters + * @param parameters the core parameters * @return the newly created core */ public SolrCore create(String coreName, Path instancePath, Map parameters, boolean newCollection) { @@ -1185,27 +1190,26 @@ public class CoreContainer { * * @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(...) * - * WARNING: Any call to this method should be surrounded by a try/finally block - * that calls solrCores.waitAddPendingCoreOps(...) and solrCores.removeFromPendingOps(...) - * - *

-   *   
-   *   try {
-   *      solrCores.waitAddPendingCoreOps(dcore.getName());
-   *      createFromDescriptor(...);
-   *   } finally {
-   *      solrCores.removeFromPendingOps(dcore.getName());
-   *   }
-   *   
-   * 
- * - * 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 - * + *
+   *                                           
+   *                                           try {
+   *                                              solrCores.waitAddPendingCoreOps(dcore.getName());
+   *                                              createFromDescriptor(...);
+   *                                           } finally {
+   *                                              solrCores.removeFromPendingOps(dcore.getName());
+   *                                           }
+   *                                           
+   *                                         
+ *

+ * 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") @@ -1249,14 +1253,14 @@ public class CoreContainer { } solrCores.removeCoreDescriptor(dcore); final SolrException solrException = new SolrException(ErrorCode.SERVER_ERROR, "Unable to create core [" + dcore.getName() + "]", e); - if(core != null && !core.isClosed()) + 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()) + if (core != null && !core.isClosed()) IOUtils.closeQuietly(core); throw t; } finally { @@ -1283,18 +1287,13 @@ public class CoreContainer { * 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 + * @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. + * @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. + * @see CoreInitFailedAction */ private SolrCore processCoreCreateException(SolrException original, CoreDescriptor dcore, ConfigSet coreConfig) { // Traverse full chain since CIE may not be root exception @@ -1382,16 +1381,16 @@ public class CoreContainer { * 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 getLoadedCoreNames() { return solrCores.getLoadedCoreNames(); } - /** This method is currently experimental. + /** + * This method is currently experimental. * * @return a Collection of the names that a specific core object is mapped to, there are more than one. */ @@ -1401,8 +1400,8 @@ public class CoreContainer { /** * 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 * + * @return a list of all the available core names in either permanent or transient cores */ public Collection getAllCoreNames() { return solrCores.getAllCoreNames(); @@ -1420,11 +1419,11 @@ public class CoreContainer { * can be changed as various SolrCore operations are performed: *

*
    - *
  • Failed attempts to create new SolrCores will add new Exceptions.
  • - *
  • Failed attempts to re-create a SolrCore using a name already contained in this Map will replace the Exception.
  • - *
  • 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.
  • - *
  • Successful attempts to re-created a SolrCore using a name already contained in this Map will remove the Exception.
  • - *
  • Registering an existing SolrCore with a name already contained in this Map (ie: ALIAS or SWAP) will remove the Exception.
  • + *
  • Failed attempts to create new SolrCores will add new Exceptions.
  • + *
  • Failed attempts to re-create a SolrCore using a name already contained in this Map will replace the Exception.
  • + *
  • 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.
  • + *
  • Successful attempts to re-created a SolrCore using a name already contained in this Map will remove the Exception.
  • + *
  • Registering an existing SolrCore with a name already contained in this Map (ie: ALIAS or SWAP) will remove the Exception.
  • *
*/ public Map getCoreInitFailures() { @@ -1564,8 +1563,8 @@ public class CoreContainer { * 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." ); + if (n0 == null || n1 == null) { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can not swap unnamed cores."); } solrCores.swap(n0, n1); @@ -1576,6 +1575,7 @@ public class CoreContainer { /** * 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) { @@ -1585,9 +1585,9 @@ public class CoreContainer { /** * 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 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) { @@ -1680,6 +1680,7 @@ public class CoreContainer { /** * Get the CoreDescriptors for all cores managed by this container + * * @return a List of CoreDescriptors */ public List getCoreDescriptors() { @@ -1697,10 +1698,10 @@ public class CoreContainer { /** * 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 + * @throws SolrCoreInitializationException if a SolrCore with this name failed to be initialized + * @see SolrCore#close() */ public SolrCore getCore(String name) { @@ -1742,15 +1743,14 @@ public class CoreContainer { core = createFromDescriptor(desc, true, false); // This should throw an error if it fails. } core.open(); - } - finally { + } finally { solrCores.removeFromPendingOps(name); } return core; } - public BlobRepository getBlobRepository(){ + public BlobRepository getBlobRepository() { return blobRepository; } @@ -1771,12 +1771,12 @@ public class CoreContainer { // ---------------- CoreContainer request handlers -------------- protected T createHandler(String path, String handlerClass, Class clazz) { - T handler = loader.newInstance(handlerClass, clazz, null, new Class[] { CoreContainer.class }, new Object[] { this }); + T handler = loader.newInstance(handlerClass, clazz, null, new Class[]{CoreContainer.class}, new Object[]{this}); if (handler instanceof SolrRequestHandler) { - containerHandlers.put(path, (SolrRequestHandler)handler); + containerHandlers.put(path, (SolrRequestHandler) handler); } if (handler instanceof SolrMetricProducer) { - ((SolrMetricProducer)handler).initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, path); + ((SolrMetricProducer) handler).initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, path); } return handler; } @@ -1789,7 +1789,9 @@ public class CoreContainer { return collectionsHandler; } - public HealthCheckHandler getHealthCheckHandler() { return healthCheckHandler; } + public HealthCheckHandler getHealthCheckHandler() { + return healthCheckHandler; + } public InfoHandler getInfoHandler() { return infoHandler; @@ -1820,7 +1822,6 @@ public class CoreContainer { /** * Determines whether the core is already loaded or not but does NOT load the core - * */ public boolean isLoaded(String name) { return solrCores.isLoaded(name); @@ -1834,6 +1835,7 @@ public class CoreContainer { public void queueCoreToClose(SolrCore coreToClose) { solrCores.queueCoreToClose(coreToClose); } + /** * 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. @@ -1861,7 +1863,9 @@ public class CoreContainer { return cfg; } - /** The default ShardHandlerFactory used to communicate with other solr instances */ + /** + * The default ShardHandlerFactory used to communicate with other solr instances + */ public ShardHandlerFactory getShardHandlerFactory() { return shardHandlerFactory; } @@ -1905,11 +1909,10 @@ public class CoreContainer { /** - * - * @param cd CoreDescriptor, presumably a deficient one + * @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 */ @@ -1919,7 +1922,7 @@ public class CoreContainer { 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]", + String.format(Locale.ROOT, "The only supported property for repair is currently [%s]", CoreDescriptor.CORE_NODE_NAME)); } @@ -1930,7 +1933,7 @@ public class CoreContainer { 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.", + "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); @@ -2012,7 +2015,7 @@ class CloserThread extends Thread { // essentially create a single-threaded process anyway. @Override public void run() { - while (! container.isShutDown()) { + while (!container.isShutDown()) { synchronized (solrCores.getModifyLock()) { // need this so we can wait and be awoken. try { solrCores.getModifyLock().wait(); 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 d314fc54153..b730f3e14ef 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -182,7 +182,7 @@ import static org.apache.solr.common.params.CommonParams.PATH; */ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeable { - public static final String version="1.0"; + public static final String version = "1.0"; private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final Logger requestLog = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass().getName() + ".Request"); @@ -209,7 +209,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab private final RequestHandlers reqHandlers; private final PluginBag searchComponents = new PluginBag<>(SearchComponent.class, this); private final PluginBag updateProcessors = new PluginBag<>(UpdateRequestProcessorFactory.class, this, true); - private final Map updateProcessorChains; + private final Map updateProcessorChains; private final SolrCoreMetricManager coreMetricManager; private final Map infoRegistry = new ConcurrentHashMap<>(); private final IndexDeletionPolicyWrapper solrDelPolicy; @@ -243,7 +243,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab return metricNames; } - public Date getStartTimeStamp() { return startTime; } + public Date getStartTimeStamp() { + return startTime; + } private final Map perSegmentFingerprintCache = new MapMaker().weakKeys().makeMap(); @@ -267,6 +269,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * The SolrResourceLoader used to load all resources for this core. + * * @since solr 1.3 */ public SolrResourceLoader getResourceLoader() { @@ -275,6 +278,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Gets the configuration resource name used by this core instance. + * * @since solr 1.3 */ public String getConfigResource() { @@ -290,25 +294,27 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Gets the schema resource name used by this core instance. + * * @since solr 1.3 */ public String getSchemaResource() { return getLatestSchema().getResourceName(); } - - /** - * @return the latest snapshot of the schema used by this core instance. - * @see #setLatestSchema + + /** + * @return the latest snapshot of the schema used by this core instance. + * @see #setLatestSchema */ public IndexSchema getLatestSchema() { return schema; } - - /** - * Sets the latest schema snapshot to be used by this core instance. - * If the specified replacementSchema uses a {@link SimilarityFactory} which is - * {@link SolrCoreAware} then this method will {@link SolrCoreAware#inform} that factory about + + /** + * Sets the latest schema snapshot to be used by this core instance. + * If the specified replacementSchema uses a {@link SimilarityFactory} which is + * {@link SolrCoreAware} then this method will {@link SolrCoreAware#inform} that factory about * this SolrCore prior to using the replacementSchema + * * @see #getLatestSchema */ public void setLatestSchema(IndexSchema replacementSchema) { @@ -325,7 +331,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } this.schema = replacementSchema; } - + public NamedList getConfigSetProperties() { return configSetProperties; } @@ -355,7 +361,6 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * and indexwriters. Use the getIndexDir() method to know the active index directory * * @return the indexdir as given in index.properties - * * @throws SolrException if for any reason the a reasonable index directory cannot be determined. */ public String getNewIndexDir() { @@ -430,7 +435,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab public IndexReaderFactory getIndexReaderFactory() { return indexReaderFactory; } - + public long getIndexSize() { Directory dir; long size = 0; @@ -456,14 +461,13 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab public void setName(String v) { this.name = v; - this.logid = (v==null)?"":("["+v+"] "); + this.logid = (v == null) ? "" : ("[" + v + "] "); if (coreMetricManager != null) { coreMetricManager.afterCoreSetName(); } } - public String getLogId() - { + public String getLogId() { return this.logid; } @@ -492,7 +496,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab if (delPolicyWrapper != null) { return delPolicyWrapper; } - + final PluginInfo info = solrConfig.getPluginInfo(IndexDeletionPolicy.class.getName()); final IndexDeletionPolicy delPolicy; if (info != null) { @@ -511,7 +515,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab try { String dirName = getDataDir() + SolrSnapshotMetaDataManager.SNAPSHOT_METADATA_DIR + "/"; Directory snapshotDir = directoryFactory.get(dirName, DirContext.DEFAULT, - getSolrConfig().indexConfig.lockType); + getSolrConfig().indexConfig.lockType); return new SolrSnapshotMetaDataManager(this, snapshotDir); } catch (IOException e) { throw new IllegalStateException(e); @@ -622,9 +626,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * * @see SolrCoreAware */ - public void registerFirstSearcherListener( SolrEventListener listener ) - { - firstSearcherListeners.add( listener ); + public void registerFirstSearcherListener(SolrEventListener listener) { + firstSearcherListeners.add(listener); } /** @@ -634,9 +637,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * * @see SolrCoreAware */ - public void registerNewSearcherListener( SolrEventListener listener ) - { - newSearcherListeners.add( listener ); + public void registerNewSearcherListener(SolrEventListener listener) { + newSearcherListeners.add(listener); } /** @@ -646,7 +648,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * * @see SolrCoreAware */ - public QueryResponseWriter registerResponseWriter( String name, QueryResponseWriter responseWriter ){ + public QueryResponseWriter registerResponseWriter(String name, QueryResponseWriter responseWriter) { return responseWriters.put(name, responseWriter); } @@ -670,10 +672,10 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab core = new SolrCore(coreContainer, getName(), getDataDir(), coreConfig.getSolrConfig(), coreConfig.getIndexSchema(), coreConfig.getProperties(), cd, updateHandler, solrDelPolicy, currentCore, true); - + // we open a new IndexWriter to pick up the latest config core.getUpdateHandler().getSolrCoreState().newIndexWriter(core, false); - + core.getSearcher(true, false, null, true); success = true; return core; @@ -724,10 +726,11 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Returns true iff the index in the named directory is * currently locked. + * * @param directory the directory to check for a lock * @throws IOException if there is a low-level IO error * @deprecated Use of this method can only lead to race conditions. Try - * to actually obtain a lock instead. + * to actually obtain a lock instead. */ @Deprecated private static boolean isWriterLocked(Directory directory) throws IOException { @@ -772,12 +775,12 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab log.debug("{}Solr index directory '{}' doesn't exist. Creating new index...", logid, indexDir); SolrIndexWriter writer = null; try { - writer = SolrIndexWriter.create(this, "SolrCore.initIndex", indexDir, getDirectoryFactory(), true, - getLatestSchema(), solrConfig.indexConfig, solrDelPolicy, codec); + writer = SolrIndexWriter.create(this, "SolrCore.initIndex", indexDir, getDirectoryFactory(), true, + getLatestSchema(), solrConfig.indexConfig, solrDelPolicy, codec); } finally { IOUtils.closeQuietly(writer); } - + } cleanupOldIndexDirectories(reload); @@ -828,17 +831,17 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab Class clazz = null; if (msg == null) msg = "SolrCore Object"; try { - clazz = getResourceLoader().findClass(className, UpdateHandler.class); - //most of the classes do not have constructors which takes SolrCore argument. It is recommended to obtain SolrCore by implementing SolrCoreAware. - // So invariably always it will cause a NoSuchMethodException. So iterate though the list of available constructors - Constructor[] cons = clazz.getConstructors(); - for (Constructor con : cons) { - Class[] types = con.getParameterTypes(); - if(types.length == 2 && types[0] == SolrCore.class && types[1] == UpdateHandler.class){ - return UpdateHandler.class.cast(con.newInstance(this, updateHandler)); - } + clazz = getResourceLoader().findClass(className, UpdateHandler.class); + //most of the classes do not have constructors which takes SolrCore argument. It is recommended to obtain SolrCore by implementing SolrCoreAware. + // So invariably always it will cause a NoSuchMethodException. So iterate though the list of available constructors + Constructor[] cons = clazz.getConstructors(); + for (Constructor con : cons) { + Class[] types = con.getParameterTypes(); + if (types.length == 2 && types[0] == SolrCore.class && types[1] == UpdateHandler.class) { + return UpdateHandler.class.cast(con.newInstance(this, updateHandler)); } - throw new SolrException(ErrorCode.SERVER_ERROR,"Error Instantiating "+msg+", "+className+ " could not find proper constructor for " + UpdateHandler.class.getName()); + } + throw new SolrException(ErrorCode.SERVER_ERROR, "Error Instantiating " + msg + ", " + className + " could not find proper constructor for " + UpdateHandler.class.getName()); } catch (SolrException e) { throw e; } catch (Exception e) { @@ -849,19 +852,19 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab throw inner; } - throw new SolrException(ErrorCode.SERVER_ERROR,"Error Instantiating "+msg+", "+className+ " failed to instantiate " + UpdateHandler.class.getName(), e); + throw new SolrException(ErrorCode.SERVER_ERROR, "Error Instantiating " + msg + ", " + className + " failed to instantiate " + UpdateHandler.class.getName(), e); } } - public T createInitInstance(PluginInfo info,Class cast, String msg, String defClassName){ - if(info == null) return null; - T o = createInstance(info.className == null ? defClassName : info.className ,cast, msg,this, getResourceLoader()); + public T createInitInstance(PluginInfo info, Class cast, String msg, String defClassName) { + if (info == null) return null; + T o = createInstance(info.className == null ? defClassName : info.className, cast, msg, this, getResourceLoader()); if (o instanceof PluginInfoInitialized) { ((PluginInfoInitialized) o).init(info); } else if (o instanceof NamedListInitializedPlugin) { ((NamedListInitializedPlugin) o).init(info.initArgs); } - if(o instanceof SearchComponent) { + if (o instanceof SearchComponent) { ((SearchComponent) o).setName(info.name); } return o; @@ -889,19 +892,15 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * Creates a new core and register it in the list of cores. If a core with the * same name already exists, it will be stopped and replaced by this one. * - * @param dataDir - * the index directory - * @param config - * a solr config instance - * @param schema - * a solr schema instance - * + * @param dataDir the index directory + * @param config a solr config instance + * @param schema a solr schema instance * @since solr 1.3 */ 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) { assert ObjectReleaseTracker.track(searcherExecutor); // ensure that in unclean shutdown tests we still close this @@ -1078,9 +1077,11 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } - /** Set UpdateLog to buffer updates if the slice is in construction. */ + /** + * Set UpdateLog to buffer updates if the slice is in construction. + */ private void bufferUpdatesIfConstructing(CoreDescriptor coreDescriptor) { - + if (coreContainer != null && coreContainer.isZooKeeperAware()) { if (reqHandlers.get("/get") == null) { log.warn("WARNING: RealTimeGetHandler is not registered at /get. " + @@ -1133,15 +1134,16 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab newUpdateHandler = createUpdateHandler(updateHandlerClass, updateHandler); } if (newUpdateHandler instanceof SolrMetricProducer) { - coreMetricManager.registerMetricProducer("updateHandler", (SolrMetricProducer)newUpdateHandler); + coreMetricManager.registerMetricProducer("updateHandler", (SolrMetricProducer) newUpdateHandler); } infoRegistry.put("updateHandler", newUpdateHandler); return newUpdateHandler; } - + /** - * Initializes the "Latest Schema" for this SolrCore using either the provided schema + * Initializes the "Latest Schema" for this SolrCore using either the provided schema * if non-null, or a new instance build via the factory identified in the specified config + * * @see IndexSchemaFactory * @see #setLatestSchema */ @@ -1235,8 +1237,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab VersionInfo.getAndCheckVersionField(schema); } catch (SolrException e) { throw new SolrException(ErrorCode.SERVER_ERROR, - "Schema will not work with SolrCloud mode: " + - e.getMessage(), e); + "Schema will not work with SolrCloud mode: " + + e.getMessage(), e); } } } @@ -1248,18 +1250,13 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Locate the data directory for a given config and core descriptor. * - * @param directoryFactory - * The directory factory to use if necessary to calculate an absolute path. Should be the same as what will - * be used to open the data directory later. - * @param dataDir - * An optional hint to the data directory location. Will be normalized and used if not null. - * @param config - * A solr config to retrieve the default data directory location, if used. - * @param coreDescriptor - * descriptor to load the actual data dir from, if not using the defualt. + * @param directoryFactory The directory factory to use if necessary to calculate an absolute path. Should be the same as what will + * be used to open the data directory later. + * @param dataDir An optional hint to the data directory location. Will be normalized and used if not null. + * @param config A solr config to retrieve the default data directory location, if used. + * @param coreDescriptor descriptor to load the actual data dir from, if not using the defualt. * @return a normalized data directory name - * @throws SolrException - * if the data directory cannot be loaded from the core descriptor + * @throws SolrException if the data directory cannot be loaded from the core descriptor */ static String findDataDir(DirectoryFactory directoryFactory, String dataDir, SolrConfig config, CoreDescriptor coreDescriptor) { if (dataDir == null) { @@ -1284,7 +1281,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab public boolean modifyIndexProps(String tmpIdxDirName) { return SolrCore.modifyIndexProps(getDirectoryFactory(), getDataDir(), getSolrConfig(), tmpIdxDirName); } - + /** * Update the index.properties file with the new index sub directory name */ @@ -1310,11 +1307,12 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } } - + /** * Write the index.properties file with the new index sub directory name - * @param dir a data directory (containing an index.properties file) - * @param tmpFileName the file name to write the new index.properties to + * + * @param dir a data directory (containing an index.properties file) + * @param tmpFileName the file name to write the new index.properties to * @param tmpIdxDirName new index directory name */ private static void writeNewIndexProps(Directory dir, String tmpFileName, String tmpIdxDirName) { @@ -1322,7 +1320,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab tmpFileName = IndexFetcher.INDEX_PROPERTIES; } final Properties p = new Properties(); - + // Read existing properties try { final IndexInput input = dir.openInput(IndexFetcher.INDEX_PROPERTIES, DirectoryFactory.IOCONTEXT_NO_CACHE); @@ -1337,7 +1335,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } catch (IOException e) { // ignore; file does not exist } - + p.put("index", tmpIdxDirName); // Write new properties @@ -1364,8 +1362,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Close the core, if it is still in use waits until is no longer in use. - * @see #close() - * @see #isClosed() + * + * @see #close() + * @see #isClosed() */ public void closeAndWait() { close(); @@ -1382,7 +1381,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } } - + private Codec initCodec(SolrConfig solrConfig, final IndexSchema schema) { final PluginInfo info = solrConfig.getPluginInfo(CodecFactory.class.getName()); final CodecFactory factory; @@ -1400,7 +1399,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab if (factory instanceof SolrCoreAware) { // CodecFactory needs SolrCore before inform() is called on all registered // SolrCoreAware listeners, at the end of the SolrCore constructor - ((SolrCoreAware)factory).inform(this); + ((SolrCoreAware) factory).inform(this); } else { for (FieldType ft : schema.getFieldTypes().values()) { if (null != ft.getPostingsFormat()) { @@ -1442,19 +1441,19 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Load the request processors */ - private Map loadUpdateProcessorChains() { + private Map loadUpdateProcessorChains() { Map map = new HashMap<>(); - UpdateRequestProcessorChain def = initPlugins(map,UpdateRequestProcessorChain.class, UpdateRequestProcessorChain.class.getName()); - if(def == null){ + UpdateRequestProcessorChain def = initPlugins(map, UpdateRequestProcessorChain.class, UpdateRequestProcessorChain.class.getName()); + if (def == null) { def = map.get(null); } if (def == null) { log.debug("no updateRequestProcessorChain defined as default, creating implicit default"); // construct the default chain UpdateRequestProcessorFactory[] factories = new UpdateRequestProcessorFactory[]{ - new LogUpdateProcessorFactory(), - new DistributedUpdateProcessorFactory(), - new RunUpdateProcessorFactory() + new LogUpdateProcessorFactory(), + new DistributedUpdateProcessorFactory(), + new RunUpdateProcessorFactory() }; def = new UpdateRequestProcessorChain(Arrays.asList(factories), this); } @@ -1474,12 +1473,11 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * @return an update processor registered to the given name. Throw an exception if this chain is undefined */ - public UpdateRequestProcessorChain getUpdateProcessingChain( final String name ) - { - UpdateRequestProcessorChain chain = updateProcessorChains.get( name ); - if( chain == null ) { - throw new SolrException( ErrorCode.BAD_REQUEST, - "unknown UpdateRequestProcessorChain: "+name ); + public UpdateRequestProcessorChain getUpdateProcessingChain(final String name) { + UpdateRequestProcessorChain chain = updateProcessorChains.get(name); + if (chain == null) { + throw new SolrException(ErrorCode.BAD_REQUEST, + "unknown UpdateRequestProcessorChain: " + name); } return chain; } @@ -1499,7 +1497,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // this core current usage count private final AtomicInteger refCount = new AtomicInteger(1); - /** expert: increments the core reference count */ + /** + * expert: increments the core reference count + */ public void open() { refCount.incrementAndGet(); } @@ -1507,25 +1507,26 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Close all resources allocated by the core if it is no longer in use... *

    - *
  • searcher
  • - *
  • updateHandler
  • - *
  • all CloseHooks will be notified
  • - *
  • All MBeans will be unregistered from MBeanServer if JMX was enabled - *
  • + *
  • searcher
  • + *
  • updateHandler
  • + *
  • all CloseHooks will be notified
  • + *
  • All MBeans will be unregistered from MBeanServer if JMX was enabled + *
  • *
*

* The behavior of this method is determined by the result of decrementing * the core's reference count (A core is created with a reference count of 1)... *

*
    - *
  • If reference count is > 0, the usage count is decreased by 1 and no - * resources are released. - *
  • - *
  • If reference count is == 0, the resources are released. - *
  • If reference count is < 0, and error is logged and no further action - * is taken. - *
  • + *
  • If reference count is > 0, the usage count is decreased by 1 and no + * resources are released. + *
  • + *
  • If reference count is == 0, the resources are released. + *
  • If reference count is < 0, and error is logged and no further action + * is taken. + *
  • *
+ * * @see #isClosed() */ @Override @@ -1533,7 +1534,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab int count = refCount.decrementAndGet(); if (count > 0) return; // close is called often, and only actually closes if nothing is using it. if (count < 0) { - log.error("Too many close [count:{}] on {}. Please report this exception to solr-user@lucene.apache.org", count, this ); + log.error("Too many close [count:{}] on {}. Please report this exception to solr-user@lucene.apache.org", count, this); assert false : "Too many closes on SolrCore"; return; } @@ -1546,25 +1547,25 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab coreMetricManager.close(); } catch (Throwable e) { SolrException.log(log, e); - if (e instanceof Error) { + if (e instanceof Error) { throw (Error) e; } } - if( closeHooks != null ) { - for( CloseHook hook : closeHooks ) { - try { - hook.preClose( this ); - } catch (Throwable e) { - SolrException.log(log, e); - if (e instanceof Error) { - throw (Error) e; - } - } + if (closeHooks != null) { + for (CloseHook hook : closeHooks) { + try { + hook.preClose(this); + } catch (Throwable e) { + SolrException.log(log, e); + if (e instanceof Error) { + throw (Error) e; + } + } } } - if(reqHandlers != null) reqHandlers.close(); + if (reqHandlers != null) reqHandlers.close(); responseWriters.close(); searchComponents.close(); qParserPlugins.close(); @@ -1584,7 +1585,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab updateHandler.close(); } } catch (Throwable e) { - SolrException.log(log,e); + SolrException.log(log, e); if (e instanceof Error) { throw (Error) e; } @@ -1626,12 +1627,12 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // tries to use it, and the exception handling code should close it. closeSearcher(); } catch (Throwable e) { - SolrException.log(log,e); + SolrException.log(log, e); if (e instanceof Error) { throw (Error) e; } } - + if (coreStateClosed) { try { cleanupOldIndexDirectories(false); @@ -1653,15 +1654,15 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab Directory snapshotsDir = snapshotMgr.getSnapshotsDir(); try { this.directoryFactory.release(snapshotsDir); - } catch (Throwable e) { - SolrException.log(log,e); + } catch (Throwable e) { + SolrException.log(log, e); if (e instanceof Error) { throw (Error) e; } } if (coreStateClosed) { - + try { directoryFactory.close(); } catch (Throwable e) { @@ -1672,48 +1673,53 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } - if( closeHooks != null ) { - for( CloseHook hook : closeHooks ) { - try { - hook.postClose( this ); - } catch (Throwable e) { - SolrException.log(log, e); - if (e instanceof Error) { - throw (Error) e; - } - } + if (closeHooks != null) { + for (CloseHook hook : closeHooks) { + try { + hook.postClose(this); + } catch (Throwable e) { + SolrException.log(log, e); + if (e instanceof Error) { + throw (Error) e; + } + } } } - + assert ObjectReleaseTracker.release(this); } - /** Current core usage count. */ + /** + * Current core usage count. + */ public int getOpenCount() { return refCount.get(); } - /** Whether this core is closed. */ + /** + * Whether this core is closed. + */ public boolean isClosed() { - return refCount.get() <= 0; + return refCount.get() <= 0; } private Collection closeHooks = null; - /** - * Add a close callback hook - */ - public void addCloseHook( CloseHook hook ) - { - if( closeHooks == null ) { - closeHooks = new ArrayList<>(); - } - closeHooks.add( hook ); - } + /** + * Add a close callback hook + */ + public void addCloseHook(CloseHook hook) { + if (closeHooks == null) { + closeHooks = new ArrayList<>(); + } + closeHooks.add(hook); + } + + /** + * @lucene.internal Debugging aid only. No non-test code should be released with uncommented verbose() calls. + */ + public static boolean VERBOSE = Boolean.parseBoolean(System.getProperty("tests.verbose", "false")); - /** @lucene.internal - * Debugging aid only. No non-test code should be released with uncommented verbose() calls. */ - public static boolean VERBOSE = Boolean.parseBoolean(System.getProperty("tests.verbose","false")); public static void verbose(Object... args) { if (!VERBOSE) return; StringBuilder sb = new StringBuilder("VERBOSE:"); @@ -1721,7 +1727,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // sb.append(':'); for (Object o : args) { sb.append(' '); - sb.append(o==null ? "(null)" : o.toString()); + sb.append(o == null ? "(null)" : o.toString()); } // System.out.println(sb.toString()); log.info(sb.toString()); @@ -1734,7 +1740,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Get the request handler registered to a given name. - * + *

* This function is thread safe. */ public SolrRequestHandler getRequestHandler(String handlerName) { @@ -1752,30 +1758,29 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Registers a handler at the specified location. If one exists there, it will be replaced. * To remove a handler, register null at its path - * + *

* Once registered the handler can be accessed through: *

    *   http://${host}:${port}/${context}/${handlerName}
    * or:
    *   http://${host}:${port}/${context}/select?qt=${handlerName}
    * 
- * + *

* Handlers must be initialized before getting registered. Registered * handlers can immediately accept requests. - * + *

* This call is thread safe. * * @return the previous SolrRequestHandler registered to this name null if none. */ public SolrRequestHandler registerRequestHandler(String handlerName, SolrRequestHandler handler) { - return reqHandlers.register(handlerName,handler); + return reqHandlers.register(handlerName, handler); } /** * Register the default search components */ - private void loadSearchComponents() - { + private void loadSearchComponents() { Map instances = createInstances(SearchComponent.standard_components); for (Map.Entry e : instances.entrySet()) e.getValue().setName(e.getKey()); searchComponents.init(instances, this); @@ -1789,6 +1794,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } } + /** * @return a Search Component registered to a given name. Throw an exception if the component is undefined */ @@ -1798,6 +1804,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab /** * Accessor for all the Search Components + * * @return An unmodifiable Map of Search Components */ public PluginBag getSearchComponents() { @@ -1864,14 +1871,15 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * {@link org.apache.solr.request.SolrQueryRequest#getSearcher()} instead. * If you still think you need to call this, consider {@link #withSearcher(IOFunction)} instead which is easier to * use. + * * @see SolrQueryRequest#getSearcher() * @see #withSearcher(IOFunction) */ public RefCounted getSearcher() { - if ( searchEnabled ) { - return getSearcher(false,true,null); + if (searchEnabled) { + return getSearcher(false, true, null); } - throw new SolrException( SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Search is temporarily disabled"); + throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Search is temporarily disabled"); } /** @@ -1885,7 +1893,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * be closed soon after this method returns; it really depends. */ @SuppressWarnings("unchecked") - public R withSearcher(IOFunction lambda) throws IOException { + public R withSearcher(IOFunction lambda) throws IOException { final RefCounted refCounted = getSearcher(); try { return lambda.apply(refCounted.get()); @@ -1912,7 +1920,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab log.debug("Cannot cache IndexFingerprint as reader does not support caching. searcher:{} reader:{} readerHash:{} maxVersion:{}", searcher, ctx.reader(), ctx.reader().hashCode(), maxVersion); return IndexFingerprint.getFingerprint(searcher, ctx, maxVersion); } - + IndexFingerprint f = null; f = perSegmentFingerprintCache.get(cacheHelper.getKey()); // fingerprint is either not cached or @@ -1936,8 +1944,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } /** - * Returns the current registered searcher with its reference count incremented, or null if none are registered. - */ + * Returns the current registered searcher with its reference count incremented, or null if none are registered. + */ public RefCounted getRegisteredSearcher() { synchronized (searcherLock) { if (_searcher != null) { @@ -1965,7 +1973,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab return openNew ? getRealtimeSearcher() : null; } - /** Gets the latest real-time searcher w/o forcing open a new searcher if one already exists. + /** + * Gets the latest real-time searcher w/o forcing open a new searcher if one already exists. * The reference count will be incremented. */ public RefCounted getRealtimeSearcher() { @@ -2001,18 +2010,19 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } - /** Opens a new searcher and returns a RefCounted<SolrIndexSearcher> with its reference incremented. - * + /** + * Opens a new searcher and returns a RefCounted<SolrIndexSearcher> with its reference incremented. + *

* "realtime" means that we need to open quickly for a realtime view of the index, hence don't do any * autowarming and add to the _realtimeSearchers queue rather than the _searchers queue (so it won't * be used for autowarming by a future normal searcher). A "realtime" searcher will currently never * become "registered" (since it currently lacks caching). - * + *

* realtimeSearcher is updated to the latest opened searcher, regardless of the value of "realtime". - * + *

* This method acquires openSearcherLock - do not call with searchLock held! */ - public RefCounted openNewSearcher(boolean updateHandlerReopens, boolean realtime) { + public RefCounted openNewSearcher(boolean updateHandlerReopens, boolean realtime) { if (isClosed()) { // catch some errors quicker throw new SolrCoreState.CoreIsClosedException(); } @@ -2088,7 +2098,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab final boolean useCaches = !realtime; final String newName = realtime ? "realtime" : "main"; tmp = new SolrIndexSearcher(this, newIndexDir, getLatestSchema(), newName, - newReader, true, useCaches, true, directoryFactory); + newReader, true, useCaches, true, directoryFactory); } else { // newestSearcher == null at this point @@ -2099,8 +2109,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // in time on a core reload DirectoryReader newReader = newReaderCreator.call(); tmp = new SolrIndexSearcher(this, newIndexDir, getLatestSchema(), - (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory); - } else { + (realtime ? "realtime" : "main"), newReader, true, !realtime, true, directoryFactory); + } else { RefCounted writer = getSolrCoreState().getIndexWriter(this); DirectoryReader newReader = null; try { @@ -2109,7 +2119,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab writer.decref(); } tmp = new SolrIndexSearcher(this, newIndexDir, getLatestSchema(), - (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory); + (realtime ? "realtime" : "main"), newReader, true, !realtime, true, directoryFactory); } } @@ -2141,8 +2151,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } catch (Exception e) { throw new SolrException(ErrorCode.SERVER_ERROR, "Error opening new searcher", e); - } - finally { + } finally { openSearcherLock.unlock(); if (newestSearcher != null) { newestSearcher.decref(); @@ -2165,14 +2174,14 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * *

* If forceNew==true then - * A new searcher will be opened and registered regardless of whether there is already - * a registered searcher or other searchers in the process of being created. + * A new searcher will be opened and registered regardless of whether there is already + * a registered searcher or other searchers in the process of being created. *

* If forceNew==false then:

    - *
  • If a searcher is already registered, that searcher will be returned
  • - *
  • If no searcher is currently registered, but at least one is in the process of being created, then + *
  • If a searcher is already registered, that searcher will be returned
  • + *
  • If no searcher is currently registered, but at least one is in the process of being created, then * this call will block until the first searcher is registered
  • - *
  • If no searcher is currently registered, and no searchers in the process of being registered, a new + *
  • If no searcher is currently registered, and no searchers in the process of being registered, a new * searcher will be created.
  • *
*

@@ -2184,6 +2193,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab * null in which case the SolrIndexSearcher created has already been registered at the time * this method returned. *

+ * * @param forceNew if true, force the open of a new index searcher regardless if there is already one open. * @param returnSearcher if true, returns a {@link SolrIndexSearcher} holder with the refcount already incremented. * @param waitSearcher if non-null, will be filled in with a {@link Future} that will return after the new searcher is registered. @@ -2195,7 +2205,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // if it isn't necessary. synchronized (searcherLock) { - for(;;) { // this loop is so w can retry in the event that we exceed maxWarmingSearchers + for (; ; ) { // this loop is so w can retry in the event that we exceed maxWarmingSearchers // see if we can return the current searcher if (_searcher != null && !forceNew) { if (returnSearcher) { @@ -2252,7 +2262,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } // a signal to decrement onDeckSearchers if something goes wrong. - final boolean[] decrementOnDeckCount=new boolean[]{true}; + final boolean[] decrementOnDeckCount = new boolean[]{true}; RefCounted currSearcherHolder = null; // searcher we are autowarming from RefCounted searchHolder = null; boolean success = false; @@ -2261,8 +2271,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab Timer.Context timerContext = newSearcherTimer.time(); try { searchHolder = openNewSearcher(updateHandlerReopens, false); - // the searchHolder will be incremented once already (and it will eventually be assigned to _searcher when registered) - // increment it again if we are going to return it to the caller. + // the searchHolder will be incremented once already (and it will eventually be assigned to _searcher when registered) + // increment it again if we are going to return it to the caller. if (returnSearcher) { searchHolder.incref(); } @@ -2279,20 +2289,20 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // want to register this one before warming is complete instead of waiting. if (solrConfig.useColdSearcher) { registerSearcher(newSearchHolder); - decrementOnDeckCount[0]=false; - alreadyRegistered=true; + decrementOnDeckCount[0] = false; + alreadyRegistered = true; } } else { // get a reference to the current searcher for purposes of autowarming. - currSearcherHolder=_searcher; + currSearcherHolder = _searcher; currSearcherHolder.incref(); } } - final SolrIndexSearcher currSearcher = currSearcherHolder==null ? null : currSearcherHolder.get(); + final SolrIndexSearcher currSearcher = currSearcherHolder == null ? null : currSearcherHolder.get(); - Future future=null; + Future future = null; // if the underlying searcher has not changed, no warming is needed if (newSearcher != currSearcher) { @@ -2369,7 +2379,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } finally { // we are all done with the old searcher we used // for warming... - if (currSearcherHolderF!=null) currSearcherHolderF.decref(); + if (currSearcherHolderF != null) currSearcherHolderF.decref(); } return null; } @@ -2387,21 +2397,22 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab return returnSearcher ? newSearchHolder : null; } catch (Exception e) { - if (e instanceof RuntimeException) throw (RuntimeException)e; + if (e instanceof RuntimeException) throw (RuntimeException) e; throw new SolrException(ErrorCode.SERVER_ERROR, e); } finally { timerContext.close(); if (!success) { - newSearcherOtherErrorsCounter.inc();; + newSearcherOtherErrorsCounter.inc(); + ; synchronized (searcherLock) { onDeckSearchers--; if (onDeckSearchers < 0) { // sanity check... should never happen log.error("{}ERROR!!! onDeckSearchers after decrement={}", logid, onDeckSearchers); - onDeckSearchers=0; // try and recover + onDeckSearchers = 0; // try and recover } // if we failed, we need to wake up at least one waiter to continue the process searcherLock.notify(); @@ -2433,7 +2444,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab @Override public void close() { try { - synchronized(searcherLock) { + synchronized (searcherLock) { // it's possible for someone to get a reference via the _searchers queue // and increment the refcount while RefCounted.close() is being called. // we check the refcount again to see if this has happened and abort the close. @@ -2477,23 +2488,23 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab if (_searcher != null) { _searcher.decref(); // dec refcount for this._searcher - _searcher=null; + _searcher = null; } _searcher = newSearcherHolder; SolrIndexSearcher newSearcher = newSearcherHolder.get(); /*** - // a searcher may have been warming asynchronously while the core was being closed. - // if this happens, just close the searcher. - if (isClosed()) { - // NOTE: this should not happen now - see close() for details. - // *BUT* if we left it enabled, this could still happen before - // close() stopped the executor - so disable this test for now. - log.error("Ignoring searcher register on closed core:" + newSearcher); - _searcher.decref(); - } - ***/ + // a searcher may have been warming asynchronously while the core was being closed. + // if this happens, just close the searcher. + if (isClosed()) { + // NOTE: this should not happen now - see close() for details. + // *BUT* if we left it enabled, this could still happen before + // close() stopped the executor - so disable this test for now. + log.error("Ignoring searcher register on closed core:" + newSearcher); + _searcher.decref(); + } + ***/ newSearcher.register(); // register subitems (caches) log.info("{}Registered new searcher {}", logid, newSearcher); @@ -2512,7 +2523,6 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } - public void closeSearcher() { log.debug("{}Closing main searcher on request.", logid); synchronized (searcherLock) { @@ -2528,9 +2538,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } public void execute(SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) { - if (handler==null) { + if (handler == null) { String msg = "Null Request Handler '" + - req.getParams().get(CommonParams.QT) + "'"; + req.getParams().get(CommonParams.QT) + "'"; log.warn("{}{}:{}", logid, msg, req); @@ -2554,7 +2564,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab // if (req.getParams().getBool(ShardParams.IS_SHARD,false) && !(handler instanceof SearchHandler)) // throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"isShard is only acceptable with search handlers"); - handler.handleRequest(req,rsp); + handler.handleRequest(req, rsp); postDecorateResponse(handler, req, rsp); if (rsp.getToLog().size() > 0) { @@ -2616,51 +2626,53 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } - /** Put status, QTime, and possibly request handler and params, in the response header */ + /** + * Put status, QTime, and possibly request handler and params, in the response header + */ public static void postDecorateResponse - (SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) { + (SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) { // TODO should check that responseHeader has not been replaced by handler NamedList responseHeader = rsp.getResponseHeader(); - final int qtime=(int)(req.getRequestTimer().getTime()); + final int qtime = (int) (req.getRequestTimer().getTime()); int status = 0; Exception exception = rsp.getException(); - if( exception != null ){ - if( exception instanceof SolrException ) - status = ((SolrException)exception).code(); + if (exception != null) { + if (exception instanceof SolrException) + status = ((SolrException) exception).code(); else status = 500; } - responseHeader.add("status",status); - responseHeader.add("QTime",qtime); + responseHeader.add("status", status); + responseHeader.add("QTime", qtime); if (rsp.getToLog().size() > 0) { - rsp.getToLog().add("status",status); - rsp.getToLog().add("QTime",qtime); + rsp.getToLog().add("status", status); + rsp.getToLog().add("QTime", qtime); } SolrParams params = req.getParams(); - if( null != handler && params.getBool(CommonParams.HEADER_ECHO_HANDLER, false) ) { - responseHeader.add("handler", handler.getName() ); + if (null != handler && params.getBool(CommonParams.HEADER_ECHO_HANDLER, false)) { + responseHeader.add("handler", handler.getName()); } // Values for echoParams... false/true/all or false/explicit/all ??? - String ep = params.get( CommonParams.HEADER_ECHO_PARAMS, null ); - if( ep != null ) { - EchoParamStyle echoParams = EchoParamStyle.get( ep ); - if( echoParams == null ) { + String ep = params.get(CommonParams.HEADER_ECHO_PARAMS, null); + if (ep != null) { + EchoParamStyle echoParams = EchoParamStyle.get(ep); + if (echoParams == null) { throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid value '" + ep + "' for " + CommonParams.HEADER_ECHO_PARAMS - + " parameter, use '" + EchoParamStyle.EXPLICIT + "' or '" + EchoParamStyle.ALL + "'" ); + + " parameter, use '" + EchoParamStyle.EXPLICIT + "' or '" + EchoParamStyle.ALL + "'"); } - if( echoParams == EchoParamStyle.EXPLICIT ) { + if (echoParams == EchoParamStyle.EXPLICIT) { responseHeader.add("params", req.getOriginalParams().toNamedList()); - } else if( echoParams == EchoParamStyle.ALL ) { + } else if (echoParams == EchoParamStyle.ALL) { responseHeader.add("params", req.getParams().toNamedList()); } } } final public static void log(Throwable e) { - SolrException.log(log,null,e); + SolrException.log(log, null, e); } public PluginBag getResponseWriters() { @@ -2668,9 +2680,10 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } private final PluginBag responseWriters = new PluginBag<>(QueryResponseWriter.class, this); - public static final Map DEFAULT_RESPONSE_WRITERS ; - static{ - HashMap m= new HashMap<>(15, 1); + public static final Map DEFAULT_RESPONSE_WRITERS; + + static { + HashMap m = new HashMap<>(15, 1); m.put("xml", new XMLResponseWriter()); m.put(CommonParams.JSON, new JSONResponseWriter()); m.put("standard", m.get(CommonParams.JSON)); @@ -2696,7 +2709,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } private static BinaryResponseWriter getFileStreamWriter() { - return new BinaryResponseWriter(){ + return new BinaryResponseWriter() { @Override public void write(OutputStream out, SolrQueryRequest req, SolrQueryResponse response) throws IOException { RawWriter rawWriter = (RawWriter) response.getValues().get(ReplicationHandler.FILE_STREAM); @@ -2727,11 +2740,14 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab default String getContentType() { return BinaryResponseParser.BINARY_CONTENT_TYPE; } - void write(OutputStream os) throws IOException ; + + void write(OutputStream os) throws IOException; } - /** Configure the query response writers. There will always be a default writer; additional - * writers may also be configured. */ + /** + * Configure the query response writers. There will always be a default writer; additional + * writers may also be configured. + */ private void initWriters() { responseWriters.init(DEFAULT_RESPONSE_WRITERS, this); // configure the default response writer; this one should never be null @@ -2739,12 +2755,15 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } - /** Finds a writer by name, or returns the default writer if not found. */ + /** + * Finds a writer by name, or returns the default writer if not found. + */ public final QueryResponseWriter getQueryResponseWriter(String writerName) { return responseWriters.get(writerName, true); } - /** Returns the appropriate writer for a request. If the request specifies a writer via the + /** + * Returns the appropriate writer for a request. If the request specifies a writer via the * 'wt' parameter, attempts to find that one; otherwise return the default writer. */ public final QueryResponseWriter getQueryResponseWriter(SolrQueryRequest request) { @@ -2780,14 +2799,14 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab return transformerFactories.get(name); } - public void addTransformerFactory(String name, TransformerFactory factory){ + public void addTransformerFactory(String name, TransformerFactory factory) { transformerFactories.put(name, factory); } /** - * @param registry The map to which the instance should be added to. The key is the name attribute - * @param type the class or interface that the instance should extend or implement. + * @param registry The map to which the instance should be added to. The key is the name attribute + * @param type the class or interface that the instance should extend or implement. * @param defClassName If PluginInfo does not have a classname, use this as the classname * @return The default instance . The one with (default=true) */ @@ -2798,12 +2817,12 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab public T initPlugins(List pluginInfos, Map registry, Class type, String defClassName) { T def = null; for (PluginInfo info : pluginInfos) { - T o = createInitInstance(info,type, type.getSimpleName(), defClassName); + T o = createInitInstance(info, type, type.getSimpleName(), defClassName); registry.put(info.name, o); if (o instanceof SolrMetricProducer) { - coreMetricManager.registerMetricProducer(type.getSimpleName() + "." + info.name, (SolrMetricProducer)o); + coreMetricManager.registerMetricProducer(type.getSimpleName() + "." + info.name, (SolrMetricProducer) o); } - if(info.isDefault()){ + if (info.isDefault()) { def = o; } } @@ -2812,26 +2831,27 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab public void initDefaultPlugin(Object plugin, Class type) { if (plugin instanceof SolrMetricProducer) { - coreMetricManager.registerMetricProducer(type.getSimpleName() + ".default", (SolrMetricProducer)plugin); + coreMetricManager.registerMetricProducer(type.getSimpleName() + ".default", (SolrMetricProducer) plugin); } } - /**For a given List of PluginInfo return the instances as a List + /** + * For a given List of PluginInfo return the instances as a List + * * @param defClassName The default classname if PluginInfo#className == null * @return The instances initialized */ public List initPlugins(List pluginInfos, Class type, String defClassName) { - if(pluginInfos.isEmpty()) return Collections.emptyList(); + if (pluginInfos.isEmpty()) return Collections.emptyList(); List result = new ArrayList<>(pluginInfos.size()); - for (PluginInfo info : pluginInfos) result.add(createInitInstance(info,type, type.getSimpleName(), defClassName)); + for (PluginInfo info : pluginInfos) result.add(createInitInstance(info, type, type.getSimpleName(), defClassName)); return result; } /** - * * @param registry The map to which the instance should be added to. The key is the name attribute - * @param type The type of the Plugin. These should be standard ones registered by type.getName() in SolrConfig - * @return The default if any + * @param type The type of the Plugin. These should be standard ones registered by type.getName() in SolrConfig + * @return The default if any */ public T initPlugins(Map registry, Class type) { return initPlugins(registry, type, null); @@ -2882,13 +2902,13 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab return coreContainer.getCoreDescriptor(name); } - public IndexDeletionPolicyWrapper getDeletionPolicy(){ + public IndexDeletionPolicyWrapper getDeletionPolicy() { return solrDelPolicy; } /** * @return A reference of {@linkplain SolrSnapshotMetaDataManager} - * managing the persistent snapshots for this Solr core. + * managing the persistent snapshots for this Solr core. */ public SolrSnapshotMetaDataManager getSnapshotMetaDataManager() { return snapshotMgr; @@ -2977,7 +2997,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } - /**Register to notify for any file change in the conf directory. + /** + * Register to notify for any file change in the conf directory. * If the file change results in a core reload , then the listener * is not fired */ @@ -2985,13 +3006,15 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab confListeners.add(runnable); } - /**Remove a listener - * */ + /** + * Remove a listener + */ public boolean removeConfListener(Runnable runnable) { return confListeners.remove(runnable); } - /**This registers one listener for the entire conf directory. In zookeeper + /** + * This registers one listener for the entire conf directory. In zookeeper * there is no event fired when children are modified. So , we expect everyone * to 'touch' the /conf directory by setting some data so that events are triggered. */ @@ -3040,9 +3063,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab checkStale(zkClient, solrConfigPath, overlayVersion) || checkStale(zkClient, managedSchmaResourcePath, managedSchemaVersion)) { log.info("core reload {}", coreName); - SolrConfigHandler configHandler = ((SolrConfigHandler)core.getRequestHandler("/config")); - if (configHandler.getReloadLock().tryLock()){ - + SolrConfigHandler configHandler = ((SolrConfigHandler) core.getRequestHandler("/config")); + if (configHandler.getReloadLock().tryLock()) { + try { cc.reload(coreName); } catch (SolrCoreState.CoreIsClosedException e) { @@ -3050,7 +3073,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } finally { configHandler.getReloadLock().unlock(); } - + } else { log.info("Another reload is in progress. Not doing anything."); } @@ -3080,20 +3103,20 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } } - private static boolean checkStale(SolrZkClient zkClient, String zkPath, int currentVersion) { - if(zkPath == null) return false; + private static boolean checkStale(SolrZkClient zkClient, String zkPath, int currentVersion) { + if (zkPath == null) return false; try { Stat stat = zkClient.exists(zkPath, null, true); - if(stat == null){ - if(currentVersion > -1) return true; + if (stat == null) { + if (currentVersion > -1) return true; return false; } - if (stat.getVersion() > currentVersion) { - log.debug("{} is stale will need an update from {} to {}", zkPath, currentVersion,stat.getVersion()); + if (stat.getVersion() > currentVersion) { + log.debug("{} is stale will need an update from {} to {}", zkPath, currentVersion, stat.getVersion()); return true; } return false; - } catch (KeeperException.NoNodeException nne){ + } catch (KeeperException.NoNodeException nne) { //no problem } catch (KeeperException e) { log.error("error refreshing solrconfig ", e); @@ -3116,7 +3139,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } catch (Exception exc) { log.error("Failed to cleanup old index directories for core {}", coreName, exc); } - }, "OldIndexDirectoryCleanupThreadForCore-"+coreName); + }, "OldIndexDirectoryCleanupThreadForCore-" + coreName); cleanupThread.setDaemon(true); cleanupThread.start(); } @@ -3137,14 +3160,14 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab } /** - * Convenience method to load a blob. This method minimizes the degree to which component and other code needs - * to depend on the structure of solr's object graph and ensures that a proper close hook is registered. This method + * Convenience method to load a blob. This method minimizes the degree to which component and other code needs + * to depend on the structure of solr's object graph and ensures that a proper close hook is registered. This method * should normally be called in {@link SolrCoreAware#inform(SolrCore)}, and should never be called during request - * processing. The Decoder will only run on the first invocations, subsequent invocations will return the - * cached object. - * - * @param key A key in the format of name/version for a blob stored in the - * {@link CollectionAdminParams#SYSTEM_COLL} blob store via the Blob Store API + * processing. The Decoder will only run on the first invocations, subsequent invocations will return the + * cached object. + * + * @param key A key in the format of name/version for a blob stored in the + * {@link CollectionAdminParams#SYSTEM_COLL} blob store via the Blob Store API * @param decoder a decoder with which to convert the blob into a Java Object representation (first time only) * @return a reference to the blob that has already cached the decoded version. */ diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java index 2306916d488..c3bfda25130 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java @@ -168,7 +168,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); protected final CoreContainer coreContainer; - private final CollectionHandlerApi v2Handler ; + private final CollectionHandlerApi v2Handler; public CollectionsHandler() { super(); @@ -228,11 +228,11 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission CoreContainer cores = getCoreContainer(); if (cores == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, - "Core container instance missing"); + "Core container instance missing"); } // Make sure that the core is ZKAware - if(!cores.isZooKeeperAware()) { + if (!cores.isZooKeeperAware()) { throw new SolrException(ErrorCode.BAD_REQUEST, "Solr instance is not running in SolrCloud mode."); } @@ -306,7 +306,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission */ private static final boolean CHECK_ASYNC_ID_BACK_COMPAT_LOCATIONS = true; - public static long DEFAULT_COLLECTION_OP_TIMEOUT = 180*1000; + public static long DEFAULT_COLLECTION_OP_TIMEOUT = 180 * 1000; public SolrResponse sendToOCPQueue(ZkNodeProps m) throws KeeperException, InterruptedException { return sendToOCPQueue(m, DEFAULT_COLLECTION_OP_TIMEOUT); @@ -319,44 +319,44 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission } if (m.get(ASYNC) != null) { - String asyncId = m.getStr(ASYNC); + String asyncId = m.getStr(ASYNC); - if (asyncId.equals("-1")) { - throw new SolrException(ErrorCode.BAD_REQUEST, "requestid can not be -1. It is reserved for cleanup purposes."); - } + if (asyncId.equals("-1")) { + throw new SolrException(ErrorCode.BAD_REQUEST, "requestid can not be -1. It is reserved for cleanup purposes."); + } - NamedList r = new NamedList<>(); + NamedList r = new NamedList<>(); - if (CHECK_ASYNC_ID_BACK_COMPAT_LOCATIONS && ( - coreContainer.getZkController().getOverseerCompletedMap().contains(asyncId) || - coreContainer.getZkController().getOverseerFailureMap().contains(asyncId) || - coreContainer.getZkController().getOverseerRunningMap().contains(asyncId) || - overseerCollectionQueueContains(asyncId))) { - // for back compatibility, check in the old places. This can be removed in Solr 9 - r.add("error", "Task with the same requestid already exists."); - } else { - if (coreContainer.getZkController().claimAsyncId(asyncId)) { - boolean success = false; - try { - coreContainer.getZkController().getOverseerCollectionQueue() - .offer(Utils.toJSON(m)); - success = true; - } finally { - if (!success) { - try { - coreContainer.getZkController().clearAsyncId(asyncId); - } catch (Exception e) { - // let the original exception bubble up - log.error("Unable to release async ID={}", asyncId, e); - SolrZkClient.checkInterrupted(e); - } - } - } - } else { - r.add("error", "Task with the same requestid already exists."); - } - } - r.add(CoreAdminParams.REQUESTID, (String) m.get(ASYNC)); + if (CHECK_ASYNC_ID_BACK_COMPAT_LOCATIONS && ( + coreContainer.getZkController().getOverseerCompletedMap().contains(asyncId) || + coreContainer.getZkController().getOverseerFailureMap().contains(asyncId) || + coreContainer.getZkController().getOverseerRunningMap().contains(asyncId) || + overseerCollectionQueueContains(asyncId))) { + // for back compatibility, check in the old places. This can be removed in Solr 9 + r.add("error", "Task with the same requestid already exists."); + } else { + if (coreContainer.getZkController().claimAsyncId(asyncId)) { + boolean success = false; + try { + coreContainer.getZkController().getOverseerCollectionQueue() + .offer(Utils.toJSON(m)); + success = true; + } finally { + if (!success) { + try { + coreContainer.getZkController().clearAsyncId(asyncId); + } catch (Exception e) { + // let the original exception bubble up + log.error("Unable to release async ID={}", asyncId, e); + SolrZkClient.checkInterrupted(e); + } + } + } + } else { + r.add("error", "Task with the same requestid already exists."); + } + } + r.add(CoreAdminParams.REQUESTID, (String) m.get(ASYNC)); return new OverseerSolrResponse(r); } @@ -393,12 +393,12 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission * Copy prefixed params into a map. There must only be one value for these parameters. * * @param params The source of params from which copies should be made - * @param props The map into which param names and values should be copied as keys and values respectively + * @param props The map into which param names and values should be copied as keys and values respectively * @param prefix The prefix to select. * @return the map supplied in the props parameter, modified to contain the prefixed params. */ private static Map copyPropertiesWithPrefix(SolrParams params, Map props, String prefix) { - Iterator iter = params.getParameterNamesIterator(); + Iterator iter = params.getParameterNamesIterator(); while (iter.hasNext()) { String param = iter.next(); if (param.startsWith(prefix)) { @@ -665,7 +665,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission } if (createCollParams.get(COLL_CONF) == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, - "We require an explicit " + COLL_CONF ); + "We require an explicit " + COLL_CONF); } // note: could insist on a config name here as well.... or wait to throw at overseer createCollParams.add(NAME, "TMP_name_TMP_name_TMP"); // just to pass validation @@ -699,7 +699,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission // the aliases themselves... rsp.getValues().add("aliases", aliases.getCollectionAliasMap()); // Any properties for the above aliases. - Map> meta = new LinkedHashMap<>(); + Map> meta = new LinkedHashMap<>(); for (String alias : aliases.getCollectionAliasListMap().keySet()) { Map collectionAliasProperties = aliases.getCollectionAliasProperties(alias); if (!collectionAliasProperties.isEmpty()) { @@ -792,8 +792,8 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission DELETE_DATA_DIR, DELETE_INSTANCE_DIR, DELETE_METRICS_HISTORY, - COUNT_PROP, REPLICA_PROP, - SHARD_ID_PROP, + COUNT_PROP, REPLICA_PROP, + SHARD_ID_PROP, ONLY_IF_DOWN); }), MIGRATE_OP(MIGRATE, (req, rsp, h) -> { @@ -877,11 +877,11 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission if (flush) { Collection completed = zkController.getOverseerCompletedMap().keys(); Collection failed = zkController.getOverseerFailureMap().keys(); - for (String asyncId:completed) { + for (String asyncId : completed) { zkController.getOverseerCompletedMap().remove(asyncId); zkController.clearAsyncId(asyncId); } - for (String asyncId:failed) { + for (String asyncId : failed) { zkController.getOverseerFailureMap().remove(asyncId); zkController.clearAsyncId(asyncId); } @@ -1013,7 +1013,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission MODIFYCOLLECTION_OP(MODIFYCOLLECTION, (req, rsp, h) -> { Map m = copy(req.getParams(), null, CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES); copyPropertiesWithPrefix(req.getParams(), m, COLL_PROP_PREFIX); - if (m.isEmpty()) { + if (m.isEmpty()) { throw new SolrException(ErrorCode.BAD_REQUEST, formatString("no supported values provided {0}", CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES.toString())); } @@ -1021,7 +1021,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission addMapObject(m, RULE); addMapObject(m, SNITCH); for (String prop : m.keySet()) { - if ("".equals(m.get(prop))) { + if ("".equals(m.get(prop))) { // set to an empty string is equivalent to removing the property, see SOLR-12507 m.put(prop, null); } @@ -1224,17 +1224,17 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission * all prefixed properties as the value. The sub-map keys have the prefix removed. * * @param params The solr params from which to extract prefixed properties. - * @param sink The map to add the properties too. + * @param sink The map to add the properties too. * @param prefix The prefix to identify properties to be extracted * @return The sink map, or a new map if the sink map was null */ private static Map convertPrefixToMap(SolrParams params, Map sink, String prefix) { - Map result = new LinkedHashMap<>(); - Iterator iter = params.getParameterNamesIterator(); + Map result = new LinkedHashMap<>(); + Iterator iter = params.getParameterNamesIterator(); while (iter.hasNext()) { String param = iter.next(); if (param.startsWith(prefix)) { - result.put(param.substring(prefix.length()+1), params.get(param)); + result.put(param.substring(prefix.length() + 1), params.get(param)); } } if (sink == null) { @@ -1396,7 +1396,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission }); } catch (TimeoutException | InterruptedException e) { - String error = "Timeout waiting for active collection " + collectionName + " with timeout=" + seconds; + String error = "Timeout waiting for active collection " + collectionName + " with timeout=" + seconds; throw new NotInClusterStateException(ErrorCode.SERVER_ERROR, error); } @@ -1462,7 +1462,9 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission // These "copy" methods were once SolrParams.getAll but were moved here as there is no universal way that // a SolrParams can be represented in a Map; there are various choices. - /**Copy all params to the given map or if the given map is null create a new one */ + /** + * Copy all params to the given map or if the given map is null create a new one + */ static Map copy(SolrParams source, Map sink, Collection paramNames) { if (sink == null) sink = new LinkedHashMap<>(); for (String param : paramNames) { @@ -1478,8 +1480,10 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission return sink; } - /**Copy all params to the given map or if the given map is null create a new one */ - static Map copy(SolrParams source, Map sink, String... paramNames){ + /** + * Copy all params to the given map or if the given map is null create a new one + */ + static Map copy(SolrParams source, Map sink, String... paramNames) { return copy(source, sink, paramNames == null ? Collections.emptyList() : Arrays.asList(paramNames)); } diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java index cd72203eacb..88b67ff4045 100644 --- a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java +++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java @@ -87,7 +87,9 @@ public class ZkStateReader implements SolrCloseable { public static final String STATE_PROP = "state"; // if this flag equals to false and the replica does not exist in cluster state, set state op become no op (default is true) public static final String FORCE_SET_STATE_PROP = "force_set_state"; - /** SolrCore name. */ + /** + * SolrCore name. + */ public static final String CORE_NAME_PROP = "core"; public static final String COLLECTION_PROP = "collection"; public static final String ELECTION_NODE_PROP = "election_node"; @@ -132,7 +134,7 @@ public class ZkStateReader implements SolrCloseable { public static final String ROLES = "/roles.json"; public static final String CONFIGS_ZKNODE = "/configs"; - public final static String CONFIGNAME_PROP="configName"; + public final static String CONFIGNAME_PROP = "configName"; public static final String LEGACY_CLOUD = "legacyCloud"; public static final String SAMPLE_PERCENTAGE = "samplePercentage"; @@ -147,33 +149,48 @@ public class ZkStateReader implements SolrCloseable { public static final String REPLICA_TYPE = "type"; - /** A view of the current state of all collections; combines all the different state sources into a single view. */ + /** + * A view of the current state of all collections; combines all the different state sources into a single view. + */ protected volatile ClusterState clusterState; private static final int GET_LEADER_RETRY_INTERVAL_MS = 50; - private static final int GET_LEADER_RETRY_DEFAULT_TIMEOUT = Integer.parseInt(System.getProperty("zkReaderGetLeaderRetryTimeoutMs", "4000"));; + private static final int GET_LEADER_RETRY_DEFAULT_TIMEOUT = Integer.parseInt(System.getProperty("zkReaderGetLeaderRetryTimeoutMs", "4000")); + ; public static final String LEADER_ELECT_ZKNODE = "leader_elect"; public static final String SHARD_LEADERS_ZKNODE = "leaders"; public static final String ELECTION_NODE = "election"; - /** Collections tracked in the legacy (shared) state format, reflects the contents of clusterstate.json. */ + /** + * Collections tracked in the legacy (shared) state format, reflects the contents of clusterstate.json. + */ private Map legacyCollectionStates = emptyMap(); - /** Last seen ZK version of clusterstate.json. */ + /** + * Last seen ZK version of clusterstate.json. + */ private int legacyClusterStateVersion = 0; - /** Collections with format2 state.json, "interesting" and actively watched. */ + /** + * Collections with format2 state.json, "interesting" and actively watched. + */ private final ConcurrentHashMap watchedCollectionStates = new ConcurrentHashMap<>(); - /** Collections with format2 state.json, not "interesting" and not actively watched. */ + /** + * Collections with format2 state.json, not "interesting" and not actively watched. + */ private final ConcurrentHashMap lazyCollectionStates = new ConcurrentHashMap<>(); - /** Collection properties being actively watched */ + /** + * Collection properties being actively watched + */ private final ConcurrentHashMap watchedCollectionProps = new ConcurrentHashMap<>(); - /** Collection properties being actively watched */ + /** + * Collection properties being actively watched + */ private final ConcurrentHashMap collectionPropsWatchers = new ConcurrentHashMap<>(); private volatile SortedSet liveNodes = emptySortedSet(); @@ -199,7 +216,9 @@ public class ZkStateReader implements SolrCloseable { private Set clusterPropertiesListeners = ConcurrentHashMap.newKeySet(); - /** Used to submit notifications to Collection Properties watchers in order **/ + /** + * Used to submit notifications to Collection Properties watchers in order + **/ private final ExecutorService collectionPropsNotifications = ExecutorUtil.newMDCAwareSingleThreadExecutor(new SolrjNamedThreadFactory("collectionPropsNotifications")); private static final long LAZY_CACHE_TIME = TimeUnit.NANOSECONDS.convert(STATE_UPDATE_DELAY, TimeUnit.MILLISECONDS); @@ -208,6 +227,7 @@ public class ZkStateReader implements SolrCloseable { /** * Get current {@link AutoScalingConfig}. + * * @return current configuration from autoscaling.json. NOTE: * this data is retrieved from ZK on each call. */ @@ -217,6 +237,7 @@ public class ZkStateReader implements SolrCloseable { /** * Get current {@link AutoScalingConfig}. + * * @param watcher optional {@link Watcher} to set on a znode to watch for config changes. * @return current configuration from autoscaling.json. NOTE: * this data is retrieved from ZK on each call. @@ -237,7 +258,7 @@ public class ZkStateReader implements SolrCloseable { return new AutoScalingConfig(map); } - private static class CollectionWatch { + private static class CollectionWatch { int coreRefCount = 0; Set stateWatchers = ConcurrentHashMap.newKeySet(); @@ -359,7 +380,7 @@ public class ZkStateReader implements SolrCloseable { /** * Forcibly refresh cluster state from ZK. Do this only to avoid race conditions because it's expensive. - * + *

* It is cheaper to call {@link #forceUpdateCollection(String)} on a single collection if you must. * * @lucene.internal @@ -438,7 +459,9 @@ public class ZkStateReader implements SolrCloseable { } - /** Refresh the set of live nodes. */ + /** + * Refresh the set of live nodes. + */ public void updateLiveNodes() throws KeeperException, InterruptedException { refreshLiveNodes(null); } @@ -449,7 +472,7 @@ public class ZkStateReader implements SolrCloseable { if (collection.getZNodeVersion() < version) { log.debug("Server older than client {}<{}", collection.getZNodeVersion(), version); DocCollection nu = getCollectionLive(this, coll); - if (nu == null) return -1 ; + if (nu == null) return -1; if (nu.getZNodeVersion() > collection.getZNodeVersion()) { if (updateWatchedCollection(coll, nu)) { synchronized (getUpdateLock()) { @@ -478,7 +501,7 @@ public class ZkStateReader implements SolrCloseable { // Sanity check ZK structure. if (!zkClient.exists(CLUSTER_STATE, true)) { throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, - "Cannot connect to cluster at " + zkClient.getZkServerAddress() + ": cluster not found/not ready"); + "Cannot connect to cluster at " + zkClient.getZkServerAddress() + ": cluster not found/not ready"); } // on reconnect of SolrZkClient force refresh and re-add watches. @@ -652,7 +675,7 @@ public class ZkStateReader implements SolrCloseable { /** * Search for any lazy-loadable state format2 collections. - * + *

* A stateFormat=1 collection which is not interesting to us can also * be put into the {@link #lazyCollectionStates} map here. But that is okay * because {@link #constructState(Set)} will give priority to collections in the @@ -761,7 +784,8 @@ public class ZkStateReader implements SolrCloseable { Stat exists = null; try { exists = zkClient.exists(getCollectionPath(collName), null, true); - } catch (Exception e) {} + } catch (Exception e) { + } if (exists != null && exists.getVersion() == cachedDocCollection.getZNodeVersion()) { shouldFetch = false; } @@ -873,11 +897,13 @@ public class ZkStateReader implements SolrCloseable { } public void close() { - this.closed = true; + this.closed = true; notifications.shutdownNow(); - waitLatches.parallelStream().forEach(c -> { c.countDown(); }); + waitLatches.parallelStream().forEach(c -> { + c.countDown(); + }); ExecutorUtil.shutdownAndAwaitTermination(notifications); ExecutorUtil.shutdownAndAwaitTermination(collectionPropsNotifications); @@ -904,6 +930,7 @@ public class ZkStateReader implements SolrCloseable { } return null; } + public Replica getLeader(String collection, String shard) { if (clusterState != null) { DocCollection docCollection = clusterState.getCollectionOrNull(collection); @@ -961,7 +988,7 @@ public class ZkStateReader implements SolrCloseable { */ public static String getShardLeadersElectPath(String collection, String shardId) { return COLLECTIONS_ZKNODE + "/" + collection + "/" - + LEADER_ELECT_ZKNODE + (shardId != null ? ("/" + shardId + "/" + ELECTION_NODE) + + LEADER_ELECT_ZKNODE + (shardId != null ? ("/" + shardId + "/" + ELECTION_NODE) : ""); } @@ -971,18 +998,18 @@ public class ZkStateReader implements SolrCloseable { } public List getReplicaProps(String collection, String shardId, String thisCoreNodeName, - Replica.State mustMatchStateFilter) { + Replica.State mustMatchStateFilter) { return getReplicaProps(collection, shardId, thisCoreNodeName, mustMatchStateFilter, null); } public List getReplicaProps(String collection, String shardId, String thisCoreNodeName, - Replica.State mustMatchStateFilter, Replica.State mustNotMatchStateFilter) { + Replica.State mustMatchStateFilter, Replica.State mustNotMatchStateFilter) { //TODO: We don't need all these getReplicaProps method overloading. Also, it's odd that the default is to return replicas of type TLOG and NRT only - return getReplicaProps(collection, shardId, thisCoreNodeName, mustMatchStateFilter, null, EnumSet.of(Replica.Type.TLOG, Replica.Type.NRT)); + return getReplicaProps(collection, shardId, thisCoreNodeName, mustMatchStateFilter, null, EnumSet.of(Replica.Type.TLOG, Replica.Type.NRT)); } public List getReplicaProps(String collection, String shardId, String thisCoreNodeName, - Replica.State mustMatchStateFilter, Replica.State mustNotMatchStateFilter, final EnumSet acceptReplicaType) { + Replica.State mustMatchStateFilter, Replica.State mustNotMatchStateFilter, final EnumSet acceptReplicaType) { assert thisCoreNodeName != null; ClusterState clusterState = this.clusterState; if (clusterState == null) { @@ -994,15 +1021,15 @@ public class ZkStateReader implements SolrCloseable { "Could not find collection in zk: " + collection); } - Map slices = docCollection.getSlicesMap(); + Map slices = docCollection.getSlicesMap(); Slice replicas = slices.get(shardId); if (replicas == null) { throw new ZooKeeperException(ErrorCode.BAD_REQUEST, "Could not find shardId in zk: " + shardId); } - Map shardMap = replicas.getReplicasMap(); + Map shardMap = replicas.getReplicasMap(); List nodes = new ArrayList<>(shardMap.size()); - for (Entry entry : shardMap.entrySet().stream().filter((e)->acceptReplicaType.contains(e.getValue().getType())).collect(Collectors.toList())) { + for (Entry entry : shardMap.entrySet().stream().filter((e) -> acceptReplicaType.contains(e.getValue().getType())).collect(Collectors.toList())) { ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(entry.getValue()); String coreNodeName = entry.getValue().getName(); @@ -1029,32 +1056,33 @@ public class ZkStateReader implements SolrCloseable { /** * Get a cluster property - * + *

* N.B. Cluster properties are updated via ZK watchers, and so may not necessarily * be completely up-to-date. If you need to get the latest version, then use a * {@link ClusterProperties} instance. * - * @param key the property to read - * @param defaultValue a default value to use if no such property exists - * @param the type of the property + * @param key the property to read + * @param defaultValue a default value to use if no such property exists + * @param the type of the property * @return the cluster property, or a default if the property is not set */ @SuppressWarnings("unchecked") public T getClusterProperty(String key, T defaultValue) { - T value = (T) Utils.getObjectByPath( clusterProperties, false, key); + T value = (T) Utils.getObjectByPath(clusterProperties, false, key); if (value == null) return defaultValue; return value; } - /**Same as the above but allows a full json path as a list of parts + /** + * Same as the above but allows a full json path as a list of parts * - * @param keyPath path to the property example ["collectionDefauls", "numShards"] + * @param keyPath path to the property example ["collectionDefauls", "numShards"] * @param defaultValue a default value to use if no such property exists * @return the cluster property, or a default if the property is not set */ public T getClusterProperty(List keyPath, T defaultValue) { - T value = (T) Utils.getObjectByPath( clusterProperties, false, keyPath); + T value = (T) Utils.getObjectByPath(clusterProperties, false, keyPath); if (value == null) return defaultValue; return value; @@ -1062,7 +1090,7 @@ public class ZkStateReader implements SolrCloseable { /** * Get all cluster properties for this cluster - * + *

* N.B. Cluster properties are updated via ZK watchers, and so may not necessarily * be completely up-to-date. If you need to get the latest version, then use a * {@link ClusterProperties} instance. @@ -1090,7 +1118,7 @@ public class ZkStateReader implements SolrCloseable { this.clusterProperties = ClusterProperties.convertCollectionDefaultsToNestedFormat((Map) Utils.fromJSON(data)); log.debug("Loaded cluster properties: {}", this.clusterProperties); - for (ClusterPropertiesListener listener: clusterPropertiesListeners) { + for (ClusterPropertiesListener listener : clusterPropertiesListeners) { listener.onChange(getClusterProperties()); } return; @@ -1116,7 +1144,7 @@ public class ZkStateReader implements SolrCloseable { * @return a map representing the key/value properties for the collection. */ public Map getCollectionProperties(final String collection) { - return getCollectionProperties(collection,0); + return getCollectionProperties(collection, 0); } /** @@ -1126,7 +1154,7 @@ public class ZkStateReader implements SolrCloseable { * This version of {@code getCollectionProperties} should be used when properties need to be consulted * frequently in the absence of an active {@link CollectionPropsWatcher}. * - * @param collection The collection for which properties are desired + * @param collection The collection for which properties are desired * @param cacheForMillis The minimum number of milliseconds to maintain a cache for the specified collection's * properties. Setting a {@code CollectionPropsWatcher} will override this value and retain * the cache for the life of the watcher. A lack of changes in zookeeper may allow the @@ -1156,7 +1184,7 @@ public class ZkStateReader implements SolrCloseable { properties = vcp.props; if (cacheForMillis > 0) { vcp.cacheUntilNs = untilNs; - watchedCollectionProps.put(collection,vcp); + watchedCollectionProps.put(collection, vcp); } else { // we're synchronized on watchedCollectionProps and we can only get here if we have found an expired // vprops above, so it is safe to remove the cached value and let the GC free up some mem a bit sooner. @@ -1174,7 +1202,7 @@ public class ZkStateReader implements SolrCloseable { private class VersionedCollectionProps { int zkVersion; - Map props; + Map props; long cacheUntilNs = 0; VersionedCollectionProps(int zkVersion, Map props) { @@ -1202,7 +1230,7 @@ public class ZkStateReader implements SolrCloseable { try { Stat stat = new Stat(); byte[] data = zkClient.getData(znodePath, watcher, stat, true); - return new VersionedCollectionProps(stat.getVersion(),(Map) Utils.fromJSON(data)); + return new VersionedCollectionProps(stat.getVersion(), (Map) Utils.fromJSON(data)); } catch (ClassCastException e) { throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to parse collection properties for collection " + collection, e); } catch (KeeperException.NoNodeException e) { @@ -1226,12 +1254,12 @@ public class ZkStateReader implements SolrCloseable { */ public ConfigData getSecurityProps(boolean getFresh) { if (!getFresh) { - if (securityData == null) return new ConfigData(EMPTY_MAP,-1); + if (securityData == null) return new ConfigData(EMPTY_MAP, -1); return new ConfigData(securityData.data, securityData.version); } try { Stat stat = new Stat(); - if(getZkClient().exists(SOLR_SECURITY_CONF_PATH, true)) { + if (getZkClient().exists(SOLR_SECURITY_CONF_PATH, true)) { final byte[] data = getZkClient().getData(ZkStateReader.SOLR_SECURITY_CONF_PATH, null, stat, true); return data != null && data.length > 0 ? new ConfigData((Map) Utils.fromJSON(data), stat.getVersion()) : @@ -1239,9 +1267,9 @@ public class ZkStateReader implements SolrCloseable { } } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new SolrException(ErrorCode.SERVER_ERROR,"Error reading security properties", e) ; + throw new SolrException(ErrorCode.SERVER_ERROR, "Error reading security properties", e); } catch (KeeperException e) { - throw new SolrException(ErrorCode.SERVER_ERROR,"Error reading security properties", e) ; + throw new SolrException(ErrorCode.SERVER_ERROR, "Error reading security properties", e); } return null; } @@ -1250,13 +1278,16 @@ public class ZkStateReader implements SolrCloseable { * Returns the baseURL corresponding to a given node's nodeName -- * NOTE: does not (currently) imply that the nodeName (or resulting * baseURL) exists in the cluster. + * * @lucene.experimental */ public String getBaseUrlForNodeName(final String nodeName) { return Utils.getBaseUrlForNodeName(nodeName, getClusterProperty(URL_SCHEME, "http")); } - /** Watches a single collection's format2 state.json. */ + /** + * Watches a single collection's format2 state.json. + */ class StateWatcher implements Watcher { private final String coll; @@ -1279,7 +1310,7 @@ public class ZkStateReader implements SolrCloseable { Set liveNodes = ZkStateReader.this.liveNodes; log.info("A cluster state change: [{}] for collection [{}] has occurred - updating... (live nodes size: [{}])", - event, coll, liveNodes.size()); + event, coll, liveNodes.size()); refreshAndWatch(); @@ -1310,7 +1341,9 @@ public class ZkStateReader implements SolrCloseable { } } - /** Watches the legacy clusterstate.json. */ + /** + * Watches the legacy clusterstate.json. + */ class LegacyClusterStateWatcher implements Watcher { @Override @@ -1324,13 +1357,15 @@ public class ZkStateReader implements SolrCloseable { refreshAndWatch(); } - /** Must hold {@link #getUpdateLock()} before calling this method. */ + /** + * Must hold {@link #getUpdateLock()} before calling this method. + */ public void refreshAndWatch() { try { refreshLegacyClusterState(this); } catch (KeeperException.NoNodeException e) { throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, - "Cannot connect to cluster at " + zkClient.getZkServerAddress() + ": cluster not found/not ready"); + "Cannot connect to cluster at " + zkClient.getZkServerAddress() + ": cluster not found/not ready"); } catch (KeeperException.SessionExpiredException | KeeperException.ConnectionLossException e) { log.warn("ZooKeeper watch triggered, but Solr cannot talk to ZK: [{}]", e.getMessage()); } catch (KeeperException e) { @@ -1344,7 +1379,9 @@ public class ZkStateReader implements SolrCloseable { } } - /** Watches collection properties */ + /** + * Watches collection properties + */ class PropsWatcher implements Watcher { private final String coll; private long watchUntilNs; @@ -1356,11 +1393,11 @@ public class ZkStateReader implements SolrCloseable { PropsWatcher(String coll, long forMillis) { this.coll = coll; - watchUntilNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(forMillis,TimeUnit.MILLISECONDS); + watchUntilNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(forMillis, TimeUnit.MILLISECONDS); } public PropsWatcher renew(long forMillis) { - watchUntilNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(forMillis,TimeUnit.MILLISECONDS); + watchUntilNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(forMillis, TimeUnit.MILLISECONDS); return this; } @@ -1428,7 +1465,9 @@ public class ZkStateReader implements SolrCloseable { } } - /** Watches /collections children . */ + /** + * Watches /collections children . + */ class CollectionsChildWatcher implements Watcher { @Override @@ -1448,7 +1487,9 @@ public class ZkStateReader implements SolrCloseable { } } - /** Must hold {@link #getUpdateLock()} before calling this method. */ + /** + * Must hold {@link #getUpdateLock()} before calling this method. + */ public void refreshAndWatch() { try { refreshCollectionList(this); @@ -1465,7 +1506,9 @@ public class ZkStateReader implements SolrCloseable { } } - /** Watches the live_nodes and syncs changes. */ + /** + * Watches the live_nodes and syncs changes. + */ class LiveNodeWatcher implements Watcher { @Override @@ -1531,7 +1574,7 @@ public class ZkStateReader implements SolrCloseable { } public static String getCollectionPathRoot(String coll) { - return COLLECTIONS_ZKNODE+"/"+coll; + return COLLECTIONS_ZKNODE + "/" + coll; } public static String getCollectionPath(String coll) { @@ -1541,14 +1584,13 @@ public class ZkStateReader implements SolrCloseable { /** * Notify this reader that a local Core is a member of a collection, and so that collection * state should be watched. - * + *

* Not a public API. This method should only be called from ZkController. - * + *

* The number of cores per-collection is tracked, and adding multiple cores from the same * collection does not increase the number of watches. * * @param collection the collection that the core is a member of - * * @see ZkStateReader#unregisterCore(String) */ public void registerCore(String collection) { @@ -1568,9 +1610,9 @@ public class ZkStateReader implements SolrCloseable { /** * Notify this reader that a local core that is a member of a collection has been closed. - * + *

* Not a public API. This method should only be called from ZkController. - * + *

* If no cores are registered for a collection, and there are no {@link CollectionStateWatcher}s * for that collection either, the collection watch will be removed. * @@ -1599,18 +1641,18 @@ public class ZkStateReader implements SolrCloseable { } /** - * Register a CollectionStateWatcher to be called when the state of a collection changes + * Register a CollectionStateWatcher to be called when the state of a collection changes * or the set of live nodes changes. * *

- * The Watcher will automatically be removed when it's + * The Watcher will automatically be removed when it's * onStateChanged returns true *

* *

- * This is method is just syntactic sugar for registering both a {@link DocCollectionWatcher} and - * a {@link LiveNodesListener}. Callers that only care about one or the other (but not both) are - * encouraged to use the more specific methods register methods as it may reduce the number of + * This is method is just syntactic sugar for registering both a {@link DocCollectionWatcher} and + * a {@link LiveNodesListener}. Callers that only care about one or the other (but not both) are + * encouraged to use the more specific methods register methods as it may reduce the number of * ZooKeeper watchers needed, and reduce the amount of network/cpu used. *

* @@ -1619,8 +1661,8 @@ public class ZkStateReader implements SolrCloseable { */ public void registerCollectionStateWatcher(String collection, CollectionStateWatcher stateWatcher) { final DocCollectionAndLiveNodesWatcherWrapper wrapper - = new DocCollectionAndLiveNodesWatcherWrapper(collection, stateWatcher); - + = new DocCollectionAndLiveNodesWatcherWrapper(collection, stateWatcher); + registerDocCollectionWatcher(collection, wrapper); registerLiveNodesListener(wrapper); @@ -1634,7 +1676,7 @@ public class ZkStateReader implements SolrCloseable { * Register a DocCollectionWatcher to be called when the state of a collection changes * *

- * The Watcher will automatically be removed when it's + * The Watcher will automatically be removed when it's * onStateChanged returns true *

*/ @@ -1668,19 +1710,19 @@ public class ZkStateReader implements SolrCloseable { *

* *

- * This implementation utilizes {@link CollectionStateWatcher} internally. - * Callers that don't care about liveNodes are encouraged to use a {@link DocCollection} {@link Predicate} + * This implementation utilizes {@link CollectionStateWatcher} internally. + * Callers that don't care about liveNodes are encouraged to use a {@link DocCollection} {@link Predicate} * instead *

- * - * @see #waitForState(String, long, TimeUnit, Predicate) - * @see #registerCollectionStateWatcher + * * @param collection the collection to watch * @param wait how long to wait * @param unit the units of the wait parameter * @param predicate the predicate to call on state changes * @throws InterruptedException on interrupt - * @throws TimeoutException on timeout + * @throws TimeoutException on timeout + * @see #waitForState(String, long, TimeUnit, Predicate) + * @see #registerCollectionStateWatcher */ public void waitForState(final String collection, long wait, TimeUnit unit, CollectionStatePredicate predicate) throws InterruptedException, TimeoutException { @@ -1707,13 +1749,12 @@ public class ZkStateReader implements SolrCloseable { if (!latch.await(wait, unit)) throw new TimeoutException("Timeout waiting to see state for collection=" + collection + " :" + docCollection.get()); - } - finally { + } finally { removeCollectionStateWatcher(collection, watcher); waitLatches.remove(latch); } } - + /** * Block until a Predicate returns true, or the wait times out * @@ -1727,7 +1768,7 @@ public class ZkStateReader implements SolrCloseable { * @param unit the units of the wait parameter * @param predicate the predicate to call on state changes * @throws InterruptedException on interrupt - * @throws TimeoutException on timeout + * @throws TimeoutException on timeout */ public void waitForState(final String collection, long wait, TimeUnit unit, Predicate predicate) throws InterruptedException, TimeoutException { @@ -1754,8 +1795,7 @@ public class ZkStateReader implements SolrCloseable { if (!latch.await(wait, unit)) throw new TimeoutException("Timeout waiting to see state for collection=" + collection + " :" + docCollection.get()); - } - finally { + } finally { removeDocCollectionWatcher(collection, watcher); waitLatches.remove(latch); } @@ -1767,11 +1807,12 @@ public class ZkStateReader implements SolrCloseable { * Note that the predicate may be called again even after it has returned true, so * implementors should avoid changing state within the predicate call itself. *

- * @param wait how long to wait - * @param unit the units of the wait parameter - * @param predicate the predicate to call on state changes + * + * @param wait how long to wait + * @param unit the units of the wait parameter + * @param predicate the predicate to call on state changes * @throws InterruptedException on interrupt - * @throws TimeoutException on timeout + * @throws TimeoutException on timeout */ public void waitForLiveNodes(long wait, TimeUnit unit, LiveNodesPredicate predicate) throws InterruptedException, TimeoutException { @@ -1798,8 +1839,7 @@ public class ZkStateReader implements SolrCloseable { if (!latch.await(wait, unit)) throw new TimeoutException("Timeout waiting for live nodes, currently they are: " + getClusterState().getLiveNodes()); - } - finally { + } finally { removeLiveNodesListener(listener); waitLatches.remove(latch); } @@ -1813,18 +1853,18 @@ public class ZkStateReader implements SolrCloseable { * collection. *

* - * @see #registerCollectionStateWatcher * @param collection the collection * @param watcher the watcher + * @see #registerCollectionStateWatcher */ public void removeCollectionStateWatcher(String collection, CollectionStateWatcher watcher) { final DocCollectionAndLiveNodesWatcherWrapper wrapper - = new DocCollectionAndLiveNodesWatcherWrapper(collection, watcher); + = new DocCollectionAndLiveNodesWatcherWrapper(collection, watcher); removeDocCollectionWatcher(collection, wrapper); removeLiveNodesListener(wrapper); } - + /** * Remove a watcher from a collection's watch list. *

@@ -1832,9 +1872,9 @@ public class ZkStateReader implements SolrCloseable { * collection. *

* - * @see #registerDocCollectionWatcher * @param collection the collection * @param watcher the watcher + * @see #registerDocCollectionWatcher */ public void removeDocCollectionWatcher(String collection, DocCollectionWatcher watcher) { AtomicBoolean reconstructState = new AtomicBoolean(false); @@ -1967,8 +2007,7 @@ public class ZkStateReader implements SolrCloseable { } try { notifications.submit(new Notification(collection, collectionState)); - } - catch (RejectedExecutionException e) { + } catch (RejectedExecutionException e) { if (closed == false) { log.error("Couldn't run collection notifications for {}", collection, e); } @@ -2011,7 +2050,9 @@ public class ZkStateReader implements SolrCloseable { // Aliases related // - /** Access to the {@link Aliases}. */ + /** + * Access to the {@link Aliases}. + */ public final AliasesManager aliasesManager = new AliasesManager(); /** @@ -2039,7 +2080,7 @@ public class ZkStateReader implements SolrCloseable { * per instance of ZkStateReader. Normally it will not be useful to create a new instance since * this watcher automatically re-registers itself every time it is updated. */ - public class AliasesManager implements Watcher { // the holder is a Zk watcher + public class AliasesManager implements Watcher { // the holder is a Zk watcher // note: as of this writing, this class if very generic. Is it useful to use for other ZK managed things? private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -2232,8 +2273,8 @@ public class ZkStateReader implements SolrCloseable { } } - /** - * Helper class that acts as both a {@link DocCollectionWatcher} and a {@link LiveNodesListener} + /** + * Helper class that acts as both a {@link DocCollectionWatcher} and a {@link LiveNodesListener} * while wraping and delegating to a {@link CollectionStateWatcher} */ private final class DocCollectionAndLiveNodesWatcherWrapper implements DocCollectionWatcher, LiveNodesListener { @@ -2243,34 +2284,34 @@ public class ZkStateReader implements SolrCloseable { public int hashCode() { return collectionName.hashCode() * delegate.hashCode(); } - + public boolean equals(Object other) { if (other instanceof DocCollectionAndLiveNodesWatcherWrapper) { DocCollectionAndLiveNodesWatcherWrapper that - = (DocCollectionAndLiveNodesWatcherWrapper) other; + = (DocCollectionAndLiveNodesWatcherWrapper) other; return this.collectionName.equals(that.collectionName) - && this.delegate.equals(that.delegate); + && this.delegate.equals(that.delegate); } return false; } - + public DocCollectionAndLiveNodesWatcherWrapper(final String collectionName, final CollectionStateWatcher delegate) { this.collectionName = collectionName; this.delegate = delegate; } - + @Override public boolean onStateChanged(DocCollection collectionState) { final boolean result = delegate.onStateChanged(ZkStateReader.this.liveNodes, - collectionState); + collectionState); if (result) { // it might be a while before live nodes changes, so proactively remove ourselves removeLiveNodesListener(this); } return result; } - + @Override public boolean onChange(SortedSet oldLiveNodes, SortedSet newLiveNodes) { final DocCollection collection = ZkStateReader.this.clusterState.getCollectionOrNull(collectionName);