mirror of https://github.com/apache/lucene.git
reformatting
This commit is contained in:
parent
4589bbe47b
commit
742c80550c
|
@ -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.
|
* 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 {
|
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());
|
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
static final Random RANDOM;
|
static final Random RANDOM;
|
||||||
static final Pattern BLOB_KEY_PATTERN_CHECKER = Pattern.compile(".*/\\d+");
|
static final Pattern BLOB_KEY_PATTERN_CHECKER = Pattern.compile(".*/\\d+");
|
||||||
|
@ -89,6 +89,7 @@ public class BlobRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
// I wanted to {@link SolrCore#loadDecodeAndCacheBlob(String, Decoder)} below but precommit complains
|
// 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.
|
* same object to decrease the refcount. This is normally used for storing jar files, and binary raw data.
|
||||||
|
@ -98,7 +99,7 @@ public class BlobRepository {
|
||||||
* @return The reference of a blob
|
* @return The reference of a blob
|
||||||
*/
|
*/
|
||||||
public BlobContentRef<ByteBuffer> getBlobIncRef(String key) {
|
public BlobContentRef<ByteBuffer> getBlobIncRef(String key) {
|
||||||
return getBlobIncRef(key, () -> addBlob(key));
|
return getBlobIncRef(key, () -> addBlob(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,18 +108,18 @@ public class BlobRepository {
|
||||||
* authors attempting to share objects across cores should use
|
* authors attempting to share objects across cores should use
|
||||||
* {@code SolrCore#loadDecodeAndCacheBlob(String, Decoder)} which ensures that a proper close hook is also created.
|
* {@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
|
* @param decoder a decoder that knows how to interpret the bytes from the blob
|
||||||
* @return The reference of a blob
|
* @return The reference of a blob
|
||||||
*/
|
*/
|
||||||
BlobContentRef<Object> getBlobIncRef(String key, Decoder<Object> decoder) {
|
BlobContentRef<Object> getBlobIncRef(String key, Decoder<Object> 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) {
|
BlobContentRef getBlobIncRef(String key, Decoder decoder, String url, String sha512) {
|
||||||
StringBuffer keyBuilder = new StringBuffer(key);
|
StringBuffer keyBuilder = new StringBuffer(key);
|
||||||
if (decoder != null) keyBuilder .append( decoder.getName());
|
if (decoder != null) keyBuilder.append(decoder.getName());
|
||||||
keyBuilder.append("/").append( sha512);
|
keyBuilder.append("/").append(sha512);
|
||||||
|
|
||||||
return getBlobIncRef(keyBuilder.toString(), () -> new BlobContent<>(key, fetchBlobAndVerify(key, url, sha512), decoder));
|
return getBlobIncRef(keyBuilder.toString(), () -> new BlobContent<>(key, fetchBlobAndVerify(key, url, sha512), decoder));
|
||||||
}
|
}
|
||||||
|
@ -133,7 +134,7 @@ public class BlobRepository {
|
||||||
try {
|
try {
|
||||||
aBlob = blobCreator.call();
|
aBlob = blobCreator.call();
|
||||||
} catch (Exception e) {
|
} 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
|
// For use cases sharing raw bytes
|
||||||
private BlobContent<ByteBuffer> addBlob(String key) {
|
private BlobContent<ByteBuffer> addBlob(String key) {
|
||||||
ByteBuffer b = fetchBlob(key);
|
ByteBuffer b = fetchBlob(key);
|
||||||
BlobContent<ByteBuffer> aBlob = new BlobContent<>(key, b);
|
BlobContent<ByteBuffer> aBlob = new BlobContent<>(key, b);
|
||||||
blobs.put(key, aBlob);
|
blobs.put(key, aBlob);
|
||||||
return aBlob;
|
return aBlob;
|
||||||
}
|
}
|
||||||
|
@ -159,11 +160,12 @@ public class BlobRepository {
|
||||||
// for use cases sharing java objects
|
// for use cases sharing java objects
|
||||||
private BlobContent<Object> addBlob(String key, Decoder<Object> decoder) {
|
private BlobContent<Object> addBlob(String key, Decoder<Object> decoder) {
|
||||||
ByteBuffer b = fetchBlob(key);
|
ByteBuffer b = fetchBlob(key);
|
||||||
String keyPlusName = key + decoder.getName();
|
String keyPlusName = key + decoder.getName();
|
||||||
BlobContent<Object> aBlob = new BlobContent<>(keyPlusName, b, decoder);
|
BlobContent<Object> aBlob = new BlobContent<>(keyPlusName, b, decoder);
|
||||||
blobs.put(keyPlusName, aBlob);
|
blobs.put(keyPlusName, aBlob);
|
||||||
return aBlob;
|
return aBlob;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String INVALID_JAR_MSG = "Invalid jar from {0} , expected sha512 hash : {1} , actual : {2}";
|
static String INVALID_JAR_MSG = "Invalid jar from {0} , expected sha512 hash : {1} , actual : {2}";
|
||||||
|
|
||||||
private ByteBuffer fetchBlobAndVerify(String key, String url, String sha512) {
|
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) {
|
ByteBuffer fetchBlob(String key) {
|
||||||
Replica replica = getSystemCollReplica();
|
Replica replica = getSystemCollReplica();
|
||||||
|
@ -234,9 +236,11 @@ public class BlobRepository {
|
||||||
ZkStateReader zkStateReader = this.coreContainer.getZkController().getZkStateReader();
|
ZkStateReader zkStateReader = this.coreContainer.getZkController().getZkStateReader();
|
||||||
ClusterState cs = zkStateReader.getClusterState();
|
ClusterState cs = zkStateReader.getClusterState();
|
||||||
DocCollection coll = cs.getCollectionOrNull(CollectionAdminParams.SYSTEM_COLL);
|
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<Slice> slices = new ArrayList<>(coll.getActiveSlices());
|
ArrayList<Slice> 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
|
Collections.shuffle(slices, RANDOM); //do load balancing
|
||||||
|
|
||||||
Replica replica = null;
|
Replica replica = null;
|
||||||
|
@ -245,7 +249,7 @@ public class BlobRepository {
|
||||||
Collections.shuffle(replicas, RANDOM);
|
Collections.shuffle(replicas, RANDOM);
|
||||||
for (Replica r : replicas) {
|
for (Replica r : replicas) {
|
||||||
if (r.getState() == Replica.State.ACTIVE) {
|
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;
|
replica = r;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -313,7 +317,9 @@ public class BlobRepository {
|
||||||
*
|
*
|
||||||
* @return The name of the decoding, defaults to empty string.
|
* @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.
|
* A routine that knows how to convert the stream of bytes from the blob into a Java object.
|
||||||
|
|
|
@ -44,9 +44,8 @@ import org.slf4j.LoggerFactory;
|
||||||
* A {@link DirectoryFactory} impl base class for caching Directory instances
|
* A {@link DirectoryFactory} impl base class for caching Directory instances
|
||||||
* per path. Most DirectoryFactory implementations will want to extend this
|
* per path. Most DirectoryFactory implementations will want to extend this
|
||||||
* class and simply implement {@link DirectoryFactory#create(String, LockFactory, DirContext)}.
|
* class and simply implement {@link DirectoryFactory#create(String, LockFactory, DirContext)}.
|
||||||
*
|
* <p>
|
||||||
* This is an expert class and these API's are subject to change.
|
* This is an expert class and these API's are subject to change.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
protected static class CacheValue {
|
protected static class CacheValue {
|
||||||
|
@ -64,6 +63,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
// for debug
|
// for debug
|
||||||
// this.originTrace = new RuntimeException("Originated from:");
|
// this.originTrace = new RuntimeException("Originated from:");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int refCnt = 1;
|
public int refCnt = 1;
|
||||||
// has doneWithDirectory(Directory) been called on this?
|
// has doneWithDirectory(Directory) been called on this?
|
||||||
public boolean closeCacheValueCalled = false;
|
public boolean closeCacheValueCalled = false;
|
||||||
|
@ -88,11 +88,11 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
protected Map<String,CacheValue> byPathCache = new HashMap<>();
|
protected Map<String, CacheValue> byPathCache = new HashMap<>();
|
||||||
|
|
||||||
protected Map<Directory,CacheValue> byDirectoryCache = new IdentityHashMap<>();
|
protected Map<Directory, CacheValue> byDirectoryCache = new IdentityHashMap<>();
|
||||||
|
|
||||||
protected Map<Directory,List<CloseListener>> closeListeners = new HashMap<>();
|
protected Map<Directory, List<CloseListener>> closeListeners = new HashMap<>();
|
||||||
|
|
||||||
protected Set<CacheValue> removeEntries = new HashSet<>();
|
protected Set<CacheValue> removeEntries = new HashSet<>();
|
||||||
|
|
||||||
|
@ -162,12 +162,12 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
Collection<CacheValue> values = byDirectoryCache.values();
|
Collection<CacheValue> values = byDirectoryCache.values();
|
||||||
for (CacheValue val : values) {
|
for (CacheValue val : values) {
|
||||||
log.debug("Closing {} - currently tracking: {}",
|
log.debug("Closing {} - currently tracking: {}",
|
||||||
this.getClass().getSimpleName(), val);
|
this.getClass().getSimpleName(), val);
|
||||||
try {
|
try {
|
||||||
// if there are still refs out, we have to wait for them
|
// if there are still refs out, we have to wait for them
|
||||||
assert val.refCnt > -1 : val.refCnt;
|
assert val.refCnt > -1 : val.refCnt;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while(val.refCnt != 0) {
|
while (val.refCnt != 0) {
|
||||||
wait(100);
|
wait(100);
|
||||||
|
|
||||||
if (cnt++ >= 120) {
|
if (cnt++ >= 120) {
|
||||||
|
@ -329,7 +329,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
* java.lang.String, boolean)
|
* java.lang.String, boolean)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final Directory get(String path, DirContext dirContext, String rawLockType)
|
public final Directory get(String path, DirContext dirContext, String rawLockType)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String fullPath = normalize(path);
|
String fullPath = normalize(path);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
@ -475,7 +475,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void removeDirectory(CacheValue cacheValue) throws IOException {
|
protected synchronized void removeDirectory(CacheValue cacheValue) throws IOException {
|
||||||
// this page intentionally left blank
|
// this page intentionally left blank
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -493,8 +493,8 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for inspecting the cache
|
* 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
|
* @see #doneWithDirectory
|
||||||
*/
|
*/
|
||||||
public synchronized Set<String> getLivePaths() {
|
public synchronized Set<String> getLivePaths() {
|
||||||
|
|
|
@ -208,8 +208,8 @@ public class CloudConfig {
|
||||||
|
|
||||||
public CloudConfig build() {
|
public CloudConfig build() {
|
||||||
return new CloudConfig(zkHost, zkClientTimeout, hostPort, hostName, hostContext, useGenericCoreNames, leaderVoteWait,
|
return new CloudConfig(zkHost, zkClientTimeout, hostPort, hostName, hostContext, useGenericCoreNames, leaderVoteWait,
|
||||||
leaderConflictResolveWait, autoReplicaFailoverWaitAfterExpiration, zkCredentialsProviderClass, zkACLProviderClass, createCollectionWaitTimeTillActive,
|
leaderConflictResolveWait, autoReplicaFailoverWaitAfterExpiration, zkCredentialsProviderClass, zkACLProviderClass, createCollectionWaitTimeTillActive,
|
||||||
createCollectionCheckLeaderActive);
|
createCollectionCheckLeaderActive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class ConfigSetProperties {
|
||||||
* Return the properties associated with the ConfigSet (e.g. immutable)
|
* Return the properties associated with the ConfigSet (e.g. immutable)
|
||||||
*
|
*
|
||||||
* @param loader the resource loader
|
* @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
|
* @return the properties in a NamedList
|
||||||
*/
|
*/
|
||||||
public static NamedList readFromResourceLoader(SolrResourceLoader loader, String name) {
|
public static NamedList readFromResourceLoader(SolrResourceLoader loader, String name) {
|
||||||
|
@ -70,7 +70,7 @@ public class ConfigSetProperties {
|
||||||
final String objectClass = object == null ? "null" : object.getClass().getName();
|
final String objectClass = object == null ? "null" : object.getClass().getName();
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Invalid JSON type " + objectClass + ", expected Map");
|
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) {
|
} catch (Exception ex) {
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to load ConfigSet properties", ex);
|
throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to load ConfigSet properties", ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -134,7 +134,6 @@ import static org.apache.solr.core.CorePropertiesLocator.PROPERTIES_FILENAME;
|
||||||
import static org.apache.solr.security.AuthenticationPlugin.AUTHENTICATION_PLUGIN_PROP;
|
import static org.apache.solr.security.AuthenticationPlugin.AUTHENTICATION_PLUGIN_PROP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @since solr 1.3
|
* @since solr 1.3
|
||||||
*/
|
*/
|
||||||
public class CoreContainer {
|
public class CoreContainer {
|
||||||
|
@ -175,7 +174,7 @@ public class CoreContainer {
|
||||||
private volatile UpdateShardHandler updateShardHandler;
|
private volatile UpdateShardHandler updateShardHandler;
|
||||||
|
|
||||||
private volatile ExecutorService coreContainerWorkExecutor = ExecutorUtil.newMDCAwareCachedThreadPool(
|
private volatile ExecutorService coreContainerWorkExecutor = ExecutorUtil.newMDCAwareCachedThreadPool(
|
||||||
new DefaultSolrThreadFactory("coreContainerWorkExecutor") );
|
new DefaultSolrThreadFactory("coreContainerWorkExecutor"));
|
||||||
|
|
||||||
private final OrderedExecutor replayUpdatesExecutor;
|
private final OrderedExecutor replayUpdatesExecutor;
|
||||||
|
|
||||||
|
@ -230,7 +229,7 @@ public class CoreContainer {
|
||||||
|
|
||||||
private ExecutorService coreContainerAsyncTaskExecutor = ExecutorUtil.newMDCAwareCachedThreadPool("Core Container Async Task");
|
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}.
|
* 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
|
* Create a new CoreContainer using system properties to detect the solr home
|
||||||
* directory. The container's cores are not loaded.
|
* directory. The container's cores are not loaded.
|
||||||
|
*
|
||||||
* @see #load()
|
* @see #load()
|
||||||
*/
|
*/
|
||||||
public CoreContainer() {
|
public CoreContainer() {
|
||||||
|
@ -277,6 +277,7 @@ public class CoreContainer {
|
||||||
/**
|
/**
|
||||||
* Create a new CoreContainer using the given SolrResourceLoader. The container's
|
* Create a new CoreContainer using the given SolrResourceLoader. The container's
|
||||||
* cores are not loaded.
|
* cores are not loaded.
|
||||||
|
*
|
||||||
* @param loader the SolrResourceLoader
|
* @param loader the SolrResourceLoader
|
||||||
* @see #load()
|
* @see #load()
|
||||||
*/
|
*/
|
||||||
|
@ -287,6 +288,7 @@ public class CoreContainer {
|
||||||
/**
|
/**
|
||||||
* Create a new CoreContainer using the given solr home directory. The container's
|
* Create a new CoreContainer using the given solr home directory. The container's
|
||||||
* cores are not loaded.
|
* cores are not loaded.
|
||||||
|
*
|
||||||
* @param solrHome a String containing the path to the solr home directory
|
* @param solrHome a String containing the path to the solr home directory
|
||||||
* @see #load()
|
* @see #load()
|
||||||
*/
|
*/
|
||||||
|
@ -298,6 +300,7 @@ public class CoreContainer {
|
||||||
* Create a new CoreContainer using the given SolrResourceLoader,
|
* Create a new CoreContainer using the given SolrResourceLoader,
|
||||||
* configuration and CoresLocator. The container's cores are
|
* configuration and CoresLocator. The container's cores are
|
||||||
* not loaded.
|
* not loaded.
|
||||||
|
*
|
||||||
* @param config a ConfigSolr representation of this container's configuration
|
* @param config a ConfigSolr representation of this container's configuration
|
||||||
* @see #load()
|
* @see #load()
|
||||||
*/
|
*/
|
||||||
|
@ -416,7 +419,7 @@ public class CoreContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginClassName != null) {
|
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) {
|
} else if (System.getProperty(AUTHENTICATION_PLUGIN_PROP) != null) {
|
||||||
pluginClassName = System.getProperty(AUTHENTICATION_PLUGIN_PROP);
|
pluginClassName = System.getProperty(AUTHENTICATION_PLUGIN_PROP);
|
||||||
log.debug("Authentication plugin class obtained from system property '" +
|
log.debug("Authentication plugin class obtained from system property '" +
|
||||||
|
@ -529,7 +532,8 @@ public class CoreContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new CoreContainer and load its cores
|
* 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
|
* @param configFile the file containing this container's configuration
|
||||||
* @return a loaded CoreContainer
|
* @return a loaded CoreContainer
|
||||||
*/
|
*/
|
||||||
|
@ -576,7 +580,7 @@ public class CoreContainer {
|
||||||
/**
|
/**
|
||||||
* Load the cores defined for this CoreContainer
|
* Load the cores defined for this CoreContainer
|
||||||
*/
|
*/
|
||||||
public void load() {
|
public void load() {
|
||||||
log.debug("Loading cores into CoreContainer [instanceDir={}]", loader.getInstancePath());
|
log.debug("Loading cores into CoreContainer [instanceDir={}]", loader.getInstancePath());
|
||||||
|
|
||||||
// add the sharedLib to the shared resource loader before initializing cfg based plugins
|
// add the sharedLib to the shared resource loader before initializing cfg based plugins
|
||||||
|
@ -617,7 +621,7 @@ public class CoreContainer {
|
||||||
hostName = cfg.getNodeName();
|
hostName = cfg.getNodeName();
|
||||||
|
|
||||||
zkSys.initZooKeeper(this, solrHome, cfg.getCloudConfig());
|
zkSys.initZooKeeper(this, solrHome, cfg.getCloudConfig());
|
||||||
if(isZooKeeperAware()) {
|
if (isZooKeeperAware()) {
|
||||||
pkiAuthenticationPlugin = new PKIAuthenticationPlugin(this, zkSys.getZkController().getNodeName(),
|
pkiAuthenticationPlugin = new PKIAuthenticationPlugin(this, zkSys.getZkController().getNodeName(),
|
||||||
(PublicKeyHandler) containerHandlers.get(PublicKeyHandler.PATH));
|
(PublicKeyHandler) containerHandlers.get(PublicKeyHandler.PATH));
|
||||||
TracerConfigurator.loadTracer(loader, cfg.getTracerConfiguratorPluginInfo(), getZkController().getZkStateReader());
|
TracerConfigurator.loadTracer(loader, cfg.getTracerConfiguratorPluginInfo(), getZkController().getZkStateReader());
|
||||||
|
@ -632,8 +636,8 @@ public class CoreContainer {
|
||||||
createHandler(ZK_PATH, ZookeeperInfoHandler.class.getName(), ZookeeperInfoHandler.class);
|
createHandler(ZK_PATH, ZookeeperInfoHandler.class.getName(), ZookeeperInfoHandler.class);
|
||||||
createHandler(ZK_STATUS_PATH, ZookeeperStatusHandler.class.getName(), ZookeeperStatusHandler.class);
|
createHandler(ZK_STATUS_PATH, ZookeeperStatusHandler.class.getName(), ZookeeperStatusHandler.class);
|
||||||
collectionsHandler = createHandler(COLLECTIONS_HANDLER_PATH, cfg.getCollectionsHandlerClass(), CollectionsHandler.class);
|
collectionsHandler = createHandler(COLLECTIONS_HANDLER_PATH, cfg.getCollectionsHandlerClass(), CollectionsHandler.class);
|
||||||
infoHandler = createHandler(INFO_HANDLER_PATH, cfg.getInfoHandlerClass(), InfoHandler.class);
|
infoHandler = createHandler(INFO_HANDLER_PATH, cfg.getInfoHandlerClass(), InfoHandler.class);
|
||||||
coreAdminHandler = createHandler(CORES_HANDLER_PATH, cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class);
|
coreAdminHandler = createHandler(CORES_HANDLER_PATH, cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class);
|
||||||
configSetsHandler = createHandler(CONFIGSETS_HANDLER_PATH, cfg.getConfigSetsHandlerClass(), ConfigSetsHandler.class);
|
configSetsHandler = createHandler(CONFIGSETS_HANDLER_PATH, cfg.getConfigSetsHandlerClass(), ConfigSetsHandler.class);
|
||||||
|
|
||||||
// metricsHistoryHandler uses metricsHandler, so create it first
|
// metricsHistoryHandler uses metricsHandler, so create it first
|
||||||
|
@ -667,18 +671,18 @@ public class CoreContainer {
|
||||||
String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.node);
|
String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.node);
|
||||||
String metricTag = Integer.toHexString(hashCode());
|
String metricTag = Integer.toHexString(hashCode());
|
||||||
metricManager.registerGauge(null, registryName, () -> solrCores.getCores().size(),
|
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(),
|
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(),
|
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();
|
Path dataHome = cfg.getSolrDataHome() != null ? cfg.getSolrDataHome() : cfg.getCoreRootDirectory();
|
||||||
metricManager.registerGauge(null, registryName, () -> dataHome.toFile().getTotalSpace(),
|
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(),
|
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(),
|
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, () -> {
|
metricManager.registerGauge(null, registryName, () -> {
|
||||||
try {
|
try {
|
||||||
return org.apache.lucene.util.IOUtils.spins(dataHome.toAbsolutePath());
|
return org.apache.lucene.util.IOUtils.spins(dataHome.toAbsolutePath());
|
||||||
|
@ -687,13 +691,13 @@ public class CoreContainer {
|
||||||
return true;
|
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(),
|
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(),
|
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(),
|
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, () -> {
|
metricManager.registerGauge(null, registryName, () -> {
|
||||||
try {
|
try {
|
||||||
return org.apache.lucene.util.IOUtils.spins(cfg.getCoreRootDirectory().toAbsolutePath());
|
return org.apache.lucene.util.IOUtils.spins(cfg.getCoreRootDirectory().toAbsolutePath());
|
||||||
|
@ -702,12 +706,12 @@ public class CoreContainer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
|
metricTag, true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
|
||||||
// add version information
|
// add version information
|
||||||
metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getSpecificationVersion(),
|
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(),
|
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();
|
SolrFieldCacheBean fieldCacheBean = new SolrFieldCacheBean();
|
||||||
fieldCacheBean.initializeMetrics(metricManager, registryName, metricTag, null);
|
fieldCacheBean.initializeMetrics(metricManager, registryName, metricTag, null);
|
||||||
|
@ -1054,8 +1058,8 @@ public class CoreContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SolrCore registerCore(CoreDescriptor cd, SolrCore core, boolean registerInZk, boolean skipRecovery) {
|
protected SolrCore registerCore(CoreDescriptor cd, SolrCore core, boolean registerInZk, boolean skipRecovery) {
|
||||||
if( core == null ) {
|
if (core == null) {
|
||||||
throw new RuntimeException( "Can not register a null core." );
|
throw new RuntimeException("Can not register a null core.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isShutDown) {
|
if (isShutDown) {
|
||||||
|
@ -1063,24 +1067,23 @@ public class CoreContainer {
|
||||||
throw new IllegalStateException("This CoreContainer has been closed");
|
throw new IllegalStateException("This CoreContainer has been closed");
|
||||||
}
|
}
|
||||||
SolrCore old = solrCores.putCore(cd, core);
|
SolrCore old = solrCores.putCore(cd, core);
|
||||||
/*
|
/*
|
||||||
* set both the name of the descriptor and the name of the
|
* set both the name of the descriptor and the name of the
|
||||||
* core, since the descriptors name is used for persisting.
|
* core, since the descriptors name is used for persisting.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
core.setName(cd.getName());
|
core.setName(cd.getName());
|
||||||
|
|
||||||
coreInitFailures.remove(cd.getName());
|
coreInitFailures.remove(cd.getName());
|
||||||
|
|
||||||
if( old == null || old == core) {
|
if (old == null || old == core) {
|
||||||
log.debug( "registering core: " + cd.getName() );
|
log.debug("registering core: " + cd.getName());
|
||||||
if (registerInZk) {
|
if (registerInZk) {
|
||||||
zkSys.registerInZk(core, false, skipRecovery);
|
zkSys.registerInZk(core, false, skipRecovery);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
} else {
|
||||||
else {
|
log.debug("replacing core: " + cd.getName());
|
||||||
log.debug( "replacing core: " + cd.getName() );
|
|
||||||
old.close();
|
old.close();
|
||||||
if (registerInZk) {
|
if (registerInZk) {
|
||||||
zkSys.registerInZk(core, false, skipRecovery);
|
zkSys.registerInZk(core, false, skipRecovery);
|
||||||
|
@ -1091,7 +1094,8 @@ public class CoreContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new core, publishing the core state to the cluster
|
* 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
|
* @param parameters the core parameters
|
||||||
* @return the newly created core
|
* @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
|
* 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 instancePath the instance directory
|
||||||
* @param parameters the core parameters
|
* @param parameters the core parameters
|
||||||
* @return the newly created core
|
* @return the newly created core
|
||||||
*/
|
*/
|
||||||
public SolrCore create(String coreName, Path instancePath, Map<String, String> parameters, boolean newCollection) {
|
public SolrCore create(String coreName, Path instancePath, Map<String, String> parameters, boolean newCollection) {
|
||||||
|
@ -1185,27 +1190,26 @@ public class CoreContainer {
|
||||||
*
|
*
|
||||||
* @param dcore a core descriptor
|
* @param dcore a core descriptor
|
||||||
* @param publishState publish core state to the cluster if true
|
* @param publishState publish core state to the cluster if true
|
||||||
|
* <p>
|
||||||
|
* 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
|
* <pre>
|
||||||
* that calls solrCores.waitAddPendingCoreOps(...) and solrCores.removeFromPendingOps(...)
|
* <code>
|
||||||
*
|
* try {
|
||||||
* <pre>
|
* solrCores.waitAddPendingCoreOps(dcore.getName());
|
||||||
* <code>
|
* createFromDescriptor(...);
|
||||||
* try {
|
* } finally {
|
||||||
* solrCores.waitAddPendingCoreOps(dcore.getName());
|
* solrCores.removeFromPendingOps(dcore.getName());
|
||||||
* createFromDescriptor(...);
|
* }
|
||||||
* } finally {
|
* </code>
|
||||||
* solrCores.removeFromPendingOps(dcore.getName());
|
* </pre>
|
||||||
* }
|
* <p>
|
||||||
* </code>
|
* Trying to put the waitAddPending... in this method results in Bad Things Happening due to race conditions.
|
||||||
* </pre>
|
* 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
|
||||||
* Trying to put the waitAddPending... in this method results in Bad Things Happening due to race conditions.
|
* to check if the core was loaded _or_ in pending ops and, based on the return called createFromDescriptor would
|
||||||
* getCore() depends on getting the core returned _if_ it's in the pending list due to some other thread opening it.
|
* introduce a race condition, see getCore() for the place it would be a problem
|
||||||
* 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
|
* @return the newly created core
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
|
@ -1249,14 +1253,14 @@ public class CoreContainer {
|
||||||
}
|
}
|
||||||
solrCores.removeCoreDescriptor(dcore);
|
solrCores.removeCoreDescriptor(dcore);
|
||||||
final SolrException solrException = new SolrException(ErrorCode.SERVER_ERROR, "Unable to create core [" + dcore.getName() + "]", e);
|
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);
|
IOUtils.closeQuietly(core);
|
||||||
throw solrException;
|
throw solrException;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
SolrException e = new SolrException(ErrorCode.SERVER_ERROR, "JVM Error creating core [" + dcore.getName() + "]: " + t.getMessage(), 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));
|
coreInitFailures.put(dcore.getName(), new CoreLoadFailure(dcore, e));
|
||||||
solrCores.removeCoreDescriptor(dcore);
|
solrCores.removeCoreDescriptor(dcore);
|
||||||
if(core != null && !core.isClosed())
|
if (core != null && !core.isClosed())
|
||||||
IOUtils.closeQuietly(core);
|
IOUtils.closeQuietly(core);
|
||||||
throw t;
|
throw t;
|
||||||
} finally {
|
} 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
|
* 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}"
|
* 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 original
|
* @param coreConfig core config for the core to create
|
||||||
* 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
|
* @return if possible
|
||||||
* @throws SolrException
|
* @throws SolrException rethrows the original exception if we will not attempt to recover, throws a new SolrException with the
|
||||||
* 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.
|
||||||
* 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) {
|
private SolrCore processCoreCreateException(SolrException original, CoreDescriptor dcore, ConfigSet coreConfig) {
|
||||||
// Traverse full chain since CIE may not be root exception
|
// 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
|
* 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
|
* 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.
|
* 2: loadOnStartup=false and have been loaded but are either non-transient or have not been aged out.
|
||||||
*
|
* <p>
|
||||||
* Put another way, this will not return any names of cores that are lazily loaded but have not been called for yet
|
* 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.
|
* or are transient and either not loaded or have been swapped out.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public Collection<String> getLoadedCoreNames() {
|
public Collection<String> getLoadedCoreNames() {
|
||||||
return solrCores.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.
|
* @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
|
* 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<String> getAllCoreNames() {
|
public Collection<String> getAllCoreNames() {
|
||||||
return solrCores.getAllCoreNames();
|
return solrCores.getAllCoreNames();
|
||||||
|
@ -1420,11 +1419,11 @@ public class CoreContainer {
|
||||||
* can be changed as various SolrCore operations are performed:
|
* can be changed as various SolrCore operations are performed:
|
||||||
* </p>
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Failed attempts to create new SolrCores will add new Exceptions.</li>
|
* <li>Failed attempts to create new SolrCores will add new Exceptions.</li>
|
||||||
* <li>Failed attempts to re-create a SolrCore using a name already contained in this Map will replace the Exception.</li>
|
* <li>Failed attempts to re-create a SolrCore using a name already contained in this Map will replace the Exception.</li>
|
||||||
* <li>Failed attempts to reload a SolrCore will cause an Exception to be added to this list -- even though the existing SolrCore with that name will continue to be available.</li>
|
* <li>Failed attempts to reload a SolrCore will cause an Exception to be added to this list -- even though the existing SolrCore with that name will continue to be available.</li>
|
||||||
* <li>Successful attempts to re-created a SolrCore using a name already contained in this Map will remove the Exception.</li>
|
* <li>Successful attempts to re-created a SolrCore using a name already contained in this Map will remove the Exception.</li>
|
||||||
* <li>Registering an existing SolrCore with a name already contained in this Map (ie: ALIAS or SWAP) will remove the Exception.</li>
|
* <li>Registering an existing SolrCore with a name already contained in this Map (ie: ALIAS or SWAP) will remove the Exception.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public Map<String, CoreLoadFailure> getCoreInitFailures() {
|
public Map<String, CoreLoadFailure> getCoreInitFailures() {
|
||||||
|
@ -1564,8 +1563,8 @@ public class CoreContainer {
|
||||||
* Swaps two SolrCore descriptors.
|
* Swaps two SolrCore descriptors.
|
||||||
*/
|
*/
|
||||||
public void swap(String n0, String n1) {
|
public void swap(String n0, String n1) {
|
||||||
if( n0 == null || n1 == null ) {
|
if (n0 == null || n1 == null) {
|
||||||
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Can not swap unnamed cores." );
|
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can not swap unnamed cores.");
|
||||||
}
|
}
|
||||||
solrCores.swap(n0, n1);
|
solrCores.swap(n0, n1);
|
||||||
|
|
||||||
|
@ -1576,6 +1575,7 @@ public class CoreContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unload a core from this container, leaving all files on disk
|
* Unload a core from this container, leaving all files on disk
|
||||||
|
*
|
||||||
* @param name the name of the core to unload
|
* @param name the name of the core to unload
|
||||||
*/
|
*/
|
||||||
public void unload(String name) {
|
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
|
* Unload a core from this container, optionally removing the core's data and configuration
|
||||||
*
|
*
|
||||||
* @param name the name of the core to unload
|
* @param name the name of the core to unload
|
||||||
* @param deleteIndexDir if true, delete the core's index on close
|
* @param deleteIndexDir if true, delete the core's index on close
|
||||||
* @param deleteDataDir if true, delete the core's data directory 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
|
* @param deleteInstanceDir if true, delete the core's instance directory on close
|
||||||
*/
|
*/
|
||||||
public void unload(String name, boolean deleteIndexDir, boolean deleteDataDir, boolean deleteInstanceDir) {
|
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
|
* Get the CoreDescriptors for all cores managed by this container
|
||||||
|
*
|
||||||
* @return a List of CoreDescriptors
|
* @return a List of CoreDescriptors
|
||||||
*/
|
*/
|
||||||
public List<CoreDescriptor> getCoreDescriptors() {
|
public List<CoreDescriptor> getCoreDescriptors() {
|
||||||
|
@ -1697,10 +1698,10 @@ public class CoreContainer {
|
||||||
/**
|
/**
|
||||||
* Gets a core by name and increase its refcount.
|
* Gets a core by name and increase its refcount.
|
||||||
*
|
*
|
||||||
* @see SolrCore#close()
|
|
||||||
* @param name the core name
|
* @param name the core name
|
||||||
* @return the core if found, null if a SolrCore by this name does not exist
|
* @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) {
|
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 = createFromDescriptor(desc, true, false); // This should throw an error if it fails.
|
||||||
}
|
}
|
||||||
core.open();
|
core.open();
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
solrCores.removeFromPendingOps(name);
|
solrCores.removeFromPendingOps(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return core;
|
return core;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlobRepository getBlobRepository(){
|
public BlobRepository getBlobRepository() {
|
||||||
return blobRepository;
|
return blobRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1771,12 +1771,12 @@ public class CoreContainer {
|
||||||
// ---------------- CoreContainer request handlers --------------
|
// ---------------- CoreContainer request handlers --------------
|
||||||
|
|
||||||
protected <T> T createHandler(String path, String handlerClass, Class<T> clazz) {
|
protected <T> T createHandler(String path, String handlerClass, Class<T> clazz) {
|
||||||
T handler = loader.newInstance(handlerClass, clazz, null, new Class[] { CoreContainer.class }, new Object[] { this });
|
T handler = loader.newInstance(handlerClass, clazz, null, new Class[]{CoreContainer.class}, new Object[]{this});
|
||||||
if (handler instanceof SolrRequestHandler) {
|
if (handler instanceof SolrRequestHandler) {
|
||||||
containerHandlers.put(path, (SolrRequestHandler)handler);
|
containerHandlers.put(path, (SolrRequestHandler) handler);
|
||||||
}
|
}
|
||||||
if (handler instanceof SolrMetricProducer) {
|
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;
|
return handler;
|
||||||
}
|
}
|
||||||
|
@ -1789,7 +1789,9 @@ public class CoreContainer {
|
||||||
return collectionsHandler;
|
return collectionsHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HealthCheckHandler getHealthCheckHandler() { return healthCheckHandler; }
|
public HealthCheckHandler getHealthCheckHandler() {
|
||||||
|
return healthCheckHandler;
|
||||||
|
}
|
||||||
|
|
||||||
public InfoHandler getInfoHandler() {
|
public InfoHandler getInfoHandler() {
|
||||||
return infoHandler;
|
return infoHandler;
|
||||||
|
@ -1820,7 +1822,6 @@ public class CoreContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the core is already loaded or not but does NOT load the core
|
* Determines whether the core is already loaded or not but does NOT load the core
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public boolean isLoaded(String name) {
|
public boolean isLoaded(String name) {
|
||||||
return solrCores.isLoaded(name);
|
return solrCores.isLoaded(name);
|
||||||
|
@ -1834,6 +1835,7 @@ public class CoreContainer {
|
||||||
public void queueCoreToClose(SolrCore coreToClose) {
|
public void queueCoreToClose(SolrCore coreToClose) {
|
||||||
solrCores.queueCoreToClose(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
|
* 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.
|
* loaded core, the unloaded descriptor will be returned.
|
||||||
|
@ -1861,7 +1863,9 @@ public class CoreContainer {
|
||||||
return cfg;
|
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() {
|
public ShardHandlerFactory getShardHandlerFactory() {
|
||||||
return shardHandlerFactory;
|
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.
|
* @param prop The property that needs to be repaired.
|
||||||
* @return true if we were able to successfuly perisist the repaired coreDescriptor, false otherwise.
|
* @return true if we were able to successfuly perisist the repaired coreDescriptor, false otherwise.
|
||||||
*
|
* <p>
|
||||||
* See SOLR-11503, This can be removed when there's no chance we'll need to upgrade a
|
* 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
|
* 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) {
|
if (CoreDescriptor.CORE_NODE_NAME.equals(prop) == false) {
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR,
|
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));
|
CoreDescriptor.CORE_NODE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1930,7 +1933,7 @@ public class CoreContainer {
|
||||||
for (Replica rep : coll.getReplicas()) {
|
for (Replica rep : coll.getReplicas()) {
|
||||||
if (coreName.equals(rep.getCoreName())) {
|
if (coreName.equals(rep.getCoreName())) {
|
||||||
log.warn("Core properties file for node {} found with no coreNodeName, attempting to repair with value {}. See SOLR-11503. " +
|
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());
|
rep.getCoreName(), rep.getName());
|
||||||
cd.getCloudDescriptor().setCoreNodeName(rep.getName());
|
cd.getCloudDescriptor().setCoreNodeName(rep.getName());
|
||||||
coresLocator.persist(this, cd);
|
coresLocator.persist(this, cd);
|
||||||
|
@ -2012,7 +2015,7 @@ class CloserThread extends Thread {
|
||||||
// essentially create a single-threaded process anyway.
|
// essentially create a single-threaded process anyway.
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (! container.isShutDown()) {
|
while (!container.isShutDown()) {
|
||||||
synchronized (solrCores.getModifyLock()) { // need this so we can wait and be awoken.
|
synchronized (solrCores.getModifyLock()) { // need this so we can wait and be awoken.
|
||||||
try {
|
try {
|
||||||
solrCores.getModifyLock().wait();
|
solrCores.getModifyLock().wait();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -168,7 +168,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
protected final CoreContainer coreContainer;
|
protected final CoreContainer coreContainer;
|
||||||
private final CollectionHandlerApi v2Handler ;
|
private final CollectionHandlerApi v2Handler;
|
||||||
|
|
||||||
public CollectionsHandler() {
|
public CollectionsHandler() {
|
||||||
super();
|
super();
|
||||||
|
@ -228,11 +228,11 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
CoreContainer cores = getCoreContainer();
|
CoreContainer cores = getCoreContainer();
|
||||||
if (cores == null) {
|
if (cores == null) {
|
||||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
||||||
"Core container instance missing");
|
"Core container instance missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the core is ZKAware
|
// Make sure that the core is ZKAware
|
||||||
if(!cores.isZooKeeperAware()) {
|
if (!cores.isZooKeeperAware()) {
|
||||||
throw new SolrException(ErrorCode.BAD_REQUEST,
|
throw new SolrException(ErrorCode.BAD_REQUEST,
|
||||||
"Solr instance is not running in SolrCloud mode.");
|
"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;
|
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 {
|
public SolrResponse sendToOCPQueue(ZkNodeProps m) throws KeeperException, InterruptedException {
|
||||||
return sendToOCPQueue(m, DEFAULT_COLLECTION_OP_TIMEOUT);
|
return sendToOCPQueue(m, DEFAULT_COLLECTION_OP_TIMEOUT);
|
||||||
|
@ -319,44 +319,44 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
}
|
}
|
||||||
if (m.get(ASYNC) != null) {
|
if (m.get(ASYNC) != null) {
|
||||||
|
|
||||||
String asyncId = m.getStr(ASYNC);
|
String asyncId = m.getStr(ASYNC);
|
||||||
|
|
||||||
if (asyncId.equals("-1")) {
|
if (asyncId.equals("-1")) {
|
||||||
throw new SolrException(ErrorCode.BAD_REQUEST, "requestid can not be -1. It is reserved for cleanup purposes.");
|
throw new SolrException(ErrorCode.BAD_REQUEST, "requestid can not be -1. It is reserved for cleanup purposes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedList<String> r = new NamedList<>();
|
NamedList<String> r = new NamedList<>();
|
||||||
|
|
||||||
if (CHECK_ASYNC_ID_BACK_COMPAT_LOCATIONS && (
|
if (CHECK_ASYNC_ID_BACK_COMPAT_LOCATIONS && (
|
||||||
coreContainer.getZkController().getOverseerCompletedMap().contains(asyncId) ||
|
coreContainer.getZkController().getOverseerCompletedMap().contains(asyncId) ||
|
||||||
coreContainer.getZkController().getOverseerFailureMap().contains(asyncId) ||
|
coreContainer.getZkController().getOverseerFailureMap().contains(asyncId) ||
|
||||||
coreContainer.getZkController().getOverseerRunningMap().contains(asyncId) ||
|
coreContainer.getZkController().getOverseerRunningMap().contains(asyncId) ||
|
||||||
overseerCollectionQueueContains(asyncId))) {
|
overseerCollectionQueueContains(asyncId))) {
|
||||||
// for back compatibility, check in the old places. This can be removed in Solr 9
|
// 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.");
|
r.add("error", "Task with the same requestid already exists.");
|
||||||
} else {
|
} else {
|
||||||
if (coreContainer.getZkController().claimAsyncId(asyncId)) {
|
if (coreContainer.getZkController().claimAsyncId(asyncId)) {
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
coreContainer.getZkController().getOverseerCollectionQueue()
|
coreContainer.getZkController().getOverseerCollectionQueue()
|
||||||
.offer(Utils.toJSON(m));
|
.offer(Utils.toJSON(m));
|
||||||
success = true;
|
success = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
try {
|
try {
|
||||||
coreContainer.getZkController().clearAsyncId(asyncId);
|
coreContainer.getZkController().clearAsyncId(asyncId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// let the original exception bubble up
|
// let the original exception bubble up
|
||||||
log.error("Unable to release async ID={}", asyncId, e);
|
log.error("Unable to release async ID={}", asyncId, e);
|
||||||
SolrZkClient.checkInterrupted(e);
|
SolrZkClient.checkInterrupted(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.add("error", "Task with the same requestid already exists.");
|
r.add("error", "Task with the same requestid already exists.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.add(CoreAdminParams.REQUESTID, (String) m.get(ASYNC));
|
r.add(CoreAdminParams.REQUESTID, (String) m.get(ASYNC));
|
||||||
|
|
||||||
return new OverseerSolrResponse(r);
|
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.
|
* 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 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.
|
* @param prefix The prefix to select.
|
||||||
* @return the map supplied in the props parameter, modified to contain the prefixed params.
|
* @return the map supplied in the props parameter, modified to contain the prefixed params.
|
||||||
*/
|
*/
|
||||||
private static Map<String, Object> copyPropertiesWithPrefix(SolrParams params, Map<String, Object> props, String prefix) {
|
private static Map<String, Object> copyPropertiesWithPrefix(SolrParams params, Map<String, Object> props, String prefix) {
|
||||||
Iterator<String> iter = params.getParameterNamesIterator();
|
Iterator<String> iter = params.getParameterNamesIterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
String param = iter.next();
|
String param = iter.next();
|
||||||
if (param.startsWith(prefix)) {
|
if (param.startsWith(prefix)) {
|
||||||
|
@ -665,7 +665,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
}
|
}
|
||||||
if (createCollParams.get(COLL_CONF) == null) {
|
if (createCollParams.get(COLL_CONF) == null) {
|
||||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
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
|
// 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
|
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...
|
// the aliases themselves...
|
||||||
rsp.getValues().add("aliases", aliases.getCollectionAliasMap());
|
rsp.getValues().add("aliases", aliases.getCollectionAliasMap());
|
||||||
// Any properties for the above aliases.
|
// Any properties for the above aliases.
|
||||||
Map<String,Map<String,String>> meta = new LinkedHashMap<>();
|
Map<String, Map<String, String>> meta = new LinkedHashMap<>();
|
||||||
for (String alias : aliases.getCollectionAliasListMap().keySet()) {
|
for (String alias : aliases.getCollectionAliasListMap().keySet()) {
|
||||||
Map<String, String> collectionAliasProperties = aliases.getCollectionAliasProperties(alias);
|
Map<String, String> collectionAliasProperties = aliases.getCollectionAliasProperties(alias);
|
||||||
if (!collectionAliasProperties.isEmpty()) {
|
if (!collectionAliasProperties.isEmpty()) {
|
||||||
|
@ -792,8 +792,8 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
DELETE_DATA_DIR,
|
DELETE_DATA_DIR,
|
||||||
DELETE_INSTANCE_DIR,
|
DELETE_INSTANCE_DIR,
|
||||||
DELETE_METRICS_HISTORY,
|
DELETE_METRICS_HISTORY,
|
||||||
COUNT_PROP, REPLICA_PROP,
|
COUNT_PROP, REPLICA_PROP,
|
||||||
SHARD_ID_PROP,
|
SHARD_ID_PROP,
|
||||||
ONLY_IF_DOWN);
|
ONLY_IF_DOWN);
|
||||||
}),
|
}),
|
||||||
MIGRATE_OP(MIGRATE, (req, rsp, h) -> {
|
MIGRATE_OP(MIGRATE, (req, rsp, h) -> {
|
||||||
|
@ -877,11 +877,11 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
if (flush) {
|
if (flush) {
|
||||||
Collection<String> completed = zkController.getOverseerCompletedMap().keys();
|
Collection<String> completed = zkController.getOverseerCompletedMap().keys();
|
||||||
Collection<String> failed = zkController.getOverseerFailureMap().keys();
|
Collection<String> failed = zkController.getOverseerFailureMap().keys();
|
||||||
for (String asyncId:completed) {
|
for (String asyncId : completed) {
|
||||||
zkController.getOverseerCompletedMap().remove(asyncId);
|
zkController.getOverseerCompletedMap().remove(asyncId);
|
||||||
zkController.clearAsyncId(asyncId);
|
zkController.clearAsyncId(asyncId);
|
||||||
}
|
}
|
||||||
for (String asyncId:failed) {
|
for (String asyncId : failed) {
|
||||||
zkController.getOverseerFailureMap().remove(asyncId);
|
zkController.getOverseerFailureMap().remove(asyncId);
|
||||||
zkController.clearAsyncId(asyncId);
|
zkController.clearAsyncId(asyncId);
|
||||||
}
|
}
|
||||||
|
@ -1013,7 +1013,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
MODIFYCOLLECTION_OP(MODIFYCOLLECTION, (req, rsp, h) -> {
|
MODIFYCOLLECTION_OP(MODIFYCOLLECTION, (req, rsp, h) -> {
|
||||||
Map<String, Object> m = copy(req.getParams(), null, CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES);
|
Map<String, Object> m = copy(req.getParams(), null, CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES);
|
||||||
copyPropertiesWithPrefix(req.getParams(), m, COLL_PROP_PREFIX);
|
copyPropertiesWithPrefix(req.getParams(), m, COLL_PROP_PREFIX);
|
||||||
if (m.isEmpty()) {
|
if (m.isEmpty()) {
|
||||||
throw new SolrException(ErrorCode.BAD_REQUEST,
|
throw new SolrException(ErrorCode.BAD_REQUEST,
|
||||||
formatString("no supported values provided {0}", CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES.toString()));
|
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, RULE);
|
||||||
addMapObject(m, SNITCH);
|
addMapObject(m, SNITCH);
|
||||||
for (String prop : m.keySet()) {
|
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
|
// set to an empty string is equivalent to removing the property, see SOLR-12507
|
||||||
m.put(prop, null);
|
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.
|
* 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 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
|
* @param prefix The prefix to identify properties to be extracted
|
||||||
* @return The sink map, or a new map if the sink map was null
|
* @return The sink map, or a new map if the sink map was null
|
||||||
*/
|
*/
|
||||||
private static Map<String, Object> convertPrefixToMap(SolrParams params, Map<String, Object> sink, String prefix) {
|
private static Map<String, Object> convertPrefixToMap(SolrParams params, Map<String, Object> sink, String prefix) {
|
||||||
Map<String,Object> result = new LinkedHashMap<>();
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
Iterator<String> iter = params.getParameterNamesIterator();
|
Iterator<String> iter = params.getParameterNamesIterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
String param = iter.next();
|
String param = iter.next();
|
||||||
if (param.startsWith(prefix)) {
|
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) {
|
if (sink == null) {
|
||||||
|
@ -1396,7 +1396,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
});
|
});
|
||||||
} catch (TimeoutException | InterruptedException e) {
|
} 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);
|
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
|
// 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.
|
// 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<String, Object> copy(SolrParams source, Map<String, Object> sink, Collection<String> paramNames) {
|
static Map<String, Object> copy(SolrParams source, Map<String, Object> sink, Collection<String> paramNames) {
|
||||||
if (sink == null) sink = new LinkedHashMap<>();
|
if (sink == null) sink = new LinkedHashMap<>();
|
||||||
for (String param : paramNames) {
|
for (String param : paramNames) {
|
||||||
|
@ -1478,8 +1480,10 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Copy all params to the given map or if the given map is null create a new one */
|
/**
|
||||||
static Map<String, Object> copy(SolrParams source, Map<String, Object> sink, String... paramNames){
|
* Copy all params to the given map or if the given map is null create a new one
|
||||||
|
*/
|
||||||
|
static Map<String, Object> copy(SolrParams source, Map<String, Object> sink, String... paramNames) {
|
||||||
return copy(source, sink, paramNames == null ? Collections.emptyList() : Arrays.asList(paramNames));
|
return copy(source, sink, paramNames == null ? Collections.emptyList() : Arrays.asList(paramNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
public static final String STATE_PROP = "state";
|
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)
|
// 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";
|
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 CORE_NAME_PROP = "core";
|
||||||
public static final String COLLECTION_PROP = "collection";
|
public static final String COLLECTION_PROP = "collection";
|
||||||
public static final String ELECTION_NODE_PROP = "election_node";
|
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 ROLES = "/roles.json";
|
||||||
|
|
||||||
public static final String CONFIGS_ZKNODE = "/configs";
|
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 LEGACY_CLOUD = "legacyCloud";
|
||||||
public static final String SAMPLE_PERCENTAGE = "samplePercentage";
|
public static final String SAMPLE_PERCENTAGE = "samplePercentage";
|
||||||
|
@ -147,33 +149,48 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
public static final String REPLICA_TYPE = "type";
|
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;
|
protected volatile ClusterState clusterState;
|
||||||
|
|
||||||
private static final int GET_LEADER_RETRY_INTERVAL_MS = 50;
|
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 LEADER_ELECT_ZKNODE = "leader_elect";
|
||||||
|
|
||||||
public static final String SHARD_LEADERS_ZKNODE = "leaders";
|
public static final String SHARD_LEADERS_ZKNODE = "leaders";
|
||||||
public static final String ELECTION_NODE = "election";
|
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<String, ClusterState.CollectionRef> legacyCollectionStates = emptyMap();
|
private Map<String, ClusterState.CollectionRef> legacyCollectionStates = emptyMap();
|
||||||
|
|
||||||
/** Last seen ZK version of clusterstate.json. */
|
/**
|
||||||
|
* Last seen ZK version of clusterstate.json.
|
||||||
|
*/
|
||||||
private int legacyClusterStateVersion = 0;
|
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<String, DocCollection> watchedCollectionStates = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, DocCollection> 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<String, LazyCollectionRef> lazyCollectionStates = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, LazyCollectionRef> lazyCollectionStates = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** Collection properties being actively watched */
|
/**
|
||||||
|
* Collection properties being actively watched
|
||||||
|
*/
|
||||||
private final ConcurrentHashMap<String, VersionedCollectionProps> watchedCollectionProps = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, VersionedCollectionProps> watchedCollectionProps = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** Collection properties being actively watched */
|
/**
|
||||||
|
* Collection properties being actively watched
|
||||||
|
*/
|
||||||
private final ConcurrentHashMap<String, PropsWatcher> collectionPropsWatchers = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, PropsWatcher> collectionPropsWatchers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private volatile SortedSet<String> liveNodes = emptySortedSet();
|
private volatile SortedSet<String> liveNodes = emptySortedSet();
|
||||||
|
@ -199,7 +216,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
private Set<ClusterPropertiesListener> clusterPropertiesListeners = ConcurrentHashMap.newKeySet();
|
private Set<ClusterPropertiesListener> 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 final ExecutorService collectionPropsNotifications = ExecutorUtil.newMDCAwareSingleThreadExecutor(new SolrjNamedThreadFactory("collectionPropsNotifications"));
|
||||||
|
|
||||||
private static final long LAZY_CACHE_TIME = TimeUnit.NANOSECONDS.convert(STATE_UPDATE_DELAY, TimeUnit.MILLISECONDS);
|
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}.
|
* Get current {@link AutoScalingConfig}.
|
||||||
|
*
|
||||||
* @return current configuration from <code>autoscaling.json</code>. NOTE:
|
* @return current configuration from <code>autoscaling.json</code>. NOTE:
|
||||||
* this data is retrieved from ZK on each call.
|
* this data is retrieved from ZK on each call.
|
||||||
*/
|
*/
|
||||||
|
@ -217,6 +237,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current {@link AutoScalingConfig}.
|
* Get current {@link AutoScalingConfig}.
|
||||||
|
*
|
||||||
* @param watcher optional {@link Watcher} to set on a znode to watch for config changes.
|
* @param watcher optional {@link Watcher} to set on a znode to watch for config changes.
|
||||||
* @return current configuration from <code>autoscaling.json</code>. NOTE:
|
* @return current configuration from <code>autoscaling.json</code>. NOTE:
|
||||||
* this data is retrieved from ZK on each call.
|
* this data is retrieved from ZK on each call.
|
||||||
|
@ -237,7 +258,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
return new AutoScalingConfig(map);
|
return new AutoScalingConfig(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CollectionWatch <T> {
|
private static class CollectionWatch<T> {
|
||||||
|
|
||||||
int coreRefCount = 0;
|
int coreRefCount = 0;
|
||||||
Set<T> stateWatchers = ConcurrentHashMap.newKeySet();
|
Set<T> 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.
|
* Forcibly refresh cluster state from ZK. Do this only to avoid race conditions because it's expensive.
|
||||||
*
|
* <p>
|
||||||
* It is cheaper to call {@link #forceUpdateCollection(String)} on a single collection if you must.
|
* It is cheaper to call {@link #forceUpdateCollection(String)} on a single collection if you must.
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @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 {
|
public void updateLiveNodes() throws KeeperException, InterruptedException {
|
||||||
refreshLiveNodes(null);
|
refreshLiveNodes(null);
|
||||||
}
|
}
|
||||||
|
@ -449,7 +472,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
if (collection.getZNodeVersion() < version) {
|
if (collection.getZNodeVersion() < version) {
|
||||||
log.debug("Server older than client {}<{}", collection.getZNodeVersion(), version);
|
log.debug("Server older than client {}<{}", collection.getZNodeVersion(), version);
|
||||||
DocCollection nu = getCollectionLive(this, coll);
|
DocCollection nu = getCollectionLive(this, coll);
|
||||||
if (nu == null) return -1 ;
|
if (nu == null) return -1;
|
||||||
if (nu.getZNodeVersion() > collection.getZNodeVersion()) {
|
if (nu.getZNodeVersion() > collection.getZNodeVersion()) {
|
||||||
if (updateWatchedCollection(coll, nu)) {
|
if (updateWatchedCollection(coll, nu)) {
|
||||||
synchronized (getUpdateLock()) {
|
synchronized (getUpdateLock()) {
|
||||||
|
@ -478,7 +501,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
// Sanity check ZK structure.
|
// Sanity check ZK structure.
|
||||||
if (!zkClient.exists(CLUSTER_STATE, true)) {
|
if (!zkClient.exists(CLUSTER_STATE, true)) {
|
||||||
throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE,
|
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.
|
// 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.
|
* Search for any lazy-loadable state format2 collections.
|
||||||
*
|
* <p>
|
||||||
* A stateFormat=1 collection which is not interesting to us can also
|
* A stateFormat=1 collection which is not interesting to us can also
|
||||||
* be put into the {@link #lazyCollectionStates} map here. But that is okay
|
* be put into the {@link #lazyCollectionStates} map here. But that is okay
|
||||||
* because {@link #constructState(Set)} will give priority to collections in the
|
* because {@link #constructState(Set)} will give priority to collections in the
|
||||||
|
@ -761,7 +784,8 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
Stat exists = null;
|
Stat exists = null;
|
||||||
try {
|
try {
|
||||||
exists = zkClient.exists(getCollectionPath(collName), null, true);
|
exists = zkClient.exists(getCollectionPath(collName), null, true);
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
if (exists != null && exists.getVersion() == cachedDocCollection.getZNodeVersion()) {
|
if (exists != null && exists.getVersion() == cachedDocCollection.getZNodeVersion()) {
|
||||||
shouldFetch = false;
|
shouldFetch = false;
|
||||||
}
|
}
|
||||||
|
@ -873,11 +897,13 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
this.closed = true;
|
this.closed = true;
|
||||||
|
|
||||||
notifications.shutdownNow();
|
notifications.shutdownNow();
|
||||||
|
|
||||||
waitLatches.parallelStream().forEach(c -> { c.countDown(); });
|
waitLatches.parallelStream().forEach(c -> {
|
||||||
|
c.countDown();
|
||||||
|
});
|
||||||
|
|
||||||
ExecutorUtil.shutdownAndAwaitTermination(notifications);
|
ExecutorUtil.shutdownAndAwaitTermination(notifications);
|
||||||
ExecutorUtil.shutdownAndAwaitTermination(collectionPropsNotifications);
|
ExecutorUtil.shutdownAndAwaitTermination(collectionPropsNotifications);
|
||||||
|
@ -904,6 +930,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Replica getLeader(String collection, String shard) {
|
public Replica getLeader(String collection, String shard) {
|
||||||
if (clusterState != null) {
|
if (clusterState != null) {
|
||||||
DocCollection docCollection = clusterState.getCollectionOrNull(collection);
|
DocCollection docCollection = clusterState.getCollectionOrNull(collection);
|
||||||
|
@ -961,7 +988,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
*/
|
*/
|
||||||
public static String getShardLeadersElectPath(String collection, String shardId) {
|
public static String getShardLeadersElectPath(String collection, String shardId) {
|
||||||
return COLLECTIONS_ZKNODE + "/" + collection + "/"
|
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<ZkCoreNodeProps> getReplicaProps(String collection, String shardId, String thisCoreNodeName,
|
public List<ZkCoreNodeProps> getReplicaProps(String collection, String shardId, String thisCoreNodeName,
|
||||||
Replica.State mustMatchStateFilter) {
|
Replica.State mustMatchStateFilter) {
|
||||||
return getReplicaProps(collection, shardId, thisCoreNodeName, mustMatchStateFilter, null);
|
return getReplicaProps(collection, shardId, thisCoreNodeName, mustMatchStateFilter, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ZkCoreNodeProps> getReplicaProps(String collection, String shardId, String thisCoreNodeName,
|
public List<ZkCoreNodeProps> 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
|
//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<ZkCoreNodeProps> getReplicaProps(String collection, String shardId, String thisCoreNodeName,
|
public List<ZkCoreNodeProps> getReplicaProps(String collection, String shardId, String thisCoreNodeName,
|
||||||
Replica.State mustMatchStateFilter, Replica.State mustNotMatchStateFilter, final EnumSet<Replica.Type> acceptReplicaType) {
|
Replica.State mustMatchStateFilter, Replica.State mustNotMatchStateFilter, final EnumSet<Replica.Type> acceptReplicaType) {
|
||||||
assert thisCoreNodeName != null;
|
assert thisCoreNodeName != null;
|
||||||
ClusterState clusterState = this.clusterState;
|
ClusterState clusterState = this.clusterState;
|
||||||
if (clusterState == null) {
|
if (clusterState == null) {
|
||||||
|
@ -994,15 +1021,15 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
"Could not find collection in zk: " + collection);
|
"Could not find collection in zk: " + collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String,Slice> slices = docCollection.getSlicesMap();
|
Map<String, Slice> slices = docCollection.getSlicesMap();
|
||||||
Slice replicas = slices.get(shardId);
|
Slice replicas = slices.get(shardId);
|
||||||
if (replicas == null) {
|
if (replicas == null) {
|
||||||
throw new ZooKeeperException(ErrorCode.BAD_REQUEST, "Could not find shardId in zk: " + shardId);
|
throw new ZooKeeperException(ErrorCode.BAD_REQUEST, "Could not find shardId in zk: " + shardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String,Replica> shardMap = replicas.getReplicasMap();
|
Map<String, Replica> shardMap = replicas.getReplicasMap();
|
||||||
List<ZkCoreNodeProps> nodes = new ArrayList<>(shardMap.size());
|
List<ZkCoreNodeProps> nodes = new ArrayList<>(shardMap.size());
|
||||||
for (Entry<String,Replica> entry : shardMap.entrySet().stream().filter((e)->acceptReplicaType.contains(e.getValue().getType())).collect(Collectors.toList())) {
|
for (Entry<String, Replica> entry : shardMap.entrySet().stream().filter((e) -> acceptReplicaType.contains(e.getValue().getType())).collect(Collectors.toList())) {
|
||||||
ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(entry.getValue());
|
ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(entry.getValue());
|
||||||
|
|
||||||
String coreNodeName = entry.getValue().getName();
|
String coreNodeName = entry.getValue().getName();
|
||||||
|
@ -1029,32 +1056,33 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a cluster property
|
* Get a cluster property
|
||||||
*
|
* <p>
|
||||||
* N.B. Cluster properties are updated via ZK watchers, and so may not necessarily
|
* 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
|
* be completely up-to-date. If you need to get the latest version, then use a
|
||||||
* {@link ClusterProperties} instance.
|
* {@link ClusterProperties} instance.
|
||||||
*
|
*
|
||||||
* @param key the property to read
|
* @param key the property to read
|
||||||
* @param defaultValue a default value to use if no such property exists
|
* @param defaultValue a default value to use if no such property exists
|
||||||
* @param <T> the type of the property
|
* @param <T> the type of the property
|
||||||
* @return the cluster property, or a default if the property is not set
|
* @return the cluster property, or a default if the property is not set
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T getClusterProperty(String key, T defaultValue) {
|
public <T> 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)
|
if (value == null)
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
return value;
|
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
|
* @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
|
* @return the cluster property, or a default if the property is not set
|
||||||
*/
|
*/
|
||||||
public <T> T getClusterProperty(List<String> keyPath, T defaultValue) {
|
public <T> T getClusterProperty(List<String> keyPath, T defaultValue) {
|
||||||
T value = (T) Utils.getObjectByPath( clusterProperties, false, keyPath);
|
T value = (T) Utils.getObjectByPath(clusterProperties, false, keyPath);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
return value;
|
return value;
|
||||||
|
@ -1062,7 +1090,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all cluster properties for this cluster
|
* Get all cluster properties for this cluster
|
||||||
*
|
* <p>
|
||||||
* N.B. Cluster properties are updated via ZK watchers, and so may not necessarily
|
* 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
|
* be completely up-to-date. If you need to get the latest version, then use a
|
||||||
* {@link ClusterProperties} instance.
|
* {@link ClusterProperties} instance.
|
||||||
|
@ -1090,7 +1118,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
this.clusterProperties = ClusterProperties.convertCollectionDefaultsToNestedFormat((Map<String, Object>) Utils.fromJSON(data));
|
this.clusterProperties = ClusterProperties.convertCollectionDefaultsToNestedFormat((Map<String, Object>) Utils.fromJSON(data));
|
||||||
log.debug("Loaded cluster properties: {}", this.clusterProperties);
|
log.debug("Loaded cluster properties: {}", this.clusterProperties);
|
||||||
|
|
||||||
for (ClusterPropertiesListener listener: clusterPropertiesListeners) {
|
for (ClusterPropertiesListener listener : clusterPropertiesListeners) {
|
||||||
listener.onChange(getClusterProperties());
|
listener.onChange(getClusterProperties());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1116,7 +1144,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
* @return a map representing the key/value properties for the collection.
|
* @return a map representing the key/value properties for the collection.
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getCollectionProperties(final String collection) {
|
public Map<String, String> 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
|
* This version of {@code getCollectionProperties} should be used when properties need to be consulted
|
||||||
* frequently in the absence of an active {@link CollectionPropsWatcher}.
|
* 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
|
* @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
|
* 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
|
* 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;
|
properties = vcp.props;
|
||||||
if (cacheForMillis > 0) {
|
if (cacheForMillis > 0) {
|
||||||
vcp.cacheUntilNs = untilNs;
|
vcp.cacheUntilNs = untilNs;
|
||||||
watchedCollectionProps.put(collection,vcp);
|
watchedCollectionProps.put(collection, vcp);
|
||||||
} else {
|
} else {
|
||||||
// we're synchronized on watchedCollectionProps and we can only get here if we have found an expired
|
// 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.
|
// 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 {
|
private class VersionedCollectionProps {
|
||||||
int zkVersion;
|
int zkVersion;
|
||||||
Map<String,String> props;
|
Map<String, String> props;
|
||||||
long cacheUntilNs = 0;
|
long cacheUntilNs = 0;
|
||||||
|
|
||||||
VersionedCollectionProps(int zkVersion, Map<String, String> props) {
|
VersionedCollectionProps(int zkVersion, Map<String, String> props) {
|
||||||
|
@ -1202,7 +1230,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
try {
|
try {
|
||||||
Stat stat = new Stat();
|
Stat stat = new Stat();
|
||||||
byte[] data = zkClient.getData(znodePath, watcher, stat, true);
|
byte[] data = zkClient.getData(znodePath, watcher, stat, true);
|
||||||
return new VersionedCollectionProps(stat.getVersion(),(Map<String, String>) Utils.fromJSON(data));
|
return new VersionedCollectionProps(stat.getVersion(), (Map<String, String>) Utils.fromJSON(data));
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to parse collection properties for collection " + collection, e);
|
throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to parse collection properties for collection " + collection, e);
|
||||||
} catch (KeeperException.NoNodeException e) {
|
} catch (KeeperException.NoNodeException e) {
|
||||||
|
@ -1226,12 +1254,12 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
*/
|
*/
|
||||||
public ConfigData getSecurityProps(boolean getFresh) {
|
public ConfigData getSecurityProps(boolean getFresh) {
|
||||||
if (!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);
|
return new ConfigData(securityData.data, securityData.version);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Stat stat = new Stat();
|
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);
|
final byte[] data = getZkClient().getData(ZkStateReader.SOLR_SECURITY_CONF_PATH, null, stat, true);
|
||||||
return data != null && data.length > 0 ?
|
return data != null && data.length > 0 ?
|
||||||
new ConfigData((Map<String, Object>) Utils.fromJSON(data), stat.getVersion()) :
|
new ConfigData((Map<String, Object>) Utils.fromJSON(data), stat.getVersion()) :
|
||||||
|
@ -1239,9 +1267,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
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) {
|
} 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1250,13 +1278,16 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
* Returns the baseURL corresponding to a given node's nodeName --
|
* Returns the baseURL corresponding to a given node's nodeName --
|
||||||
* NOTE: does not (currently) imply that the nodeName (or resulting
|
* NOTE: does not (currently) imply that the nodeName (or resulting
|
||||||
* baseURL) exists in the cluster.
|
* baseURL) exists in the cluster.
|
||||||
|
*
|
||||||
* @lucene.experimental
|
* @lucene.experimental
|
||||||
*/
|
*/
|
||||||
public String getBaseUrlForNodeName(final String nodeName) {
|
public String getBaseUrlForNodeName(final String nodeName) {
|
||||||
return Utils.getBaseUrlForNodeName(nodeName, getClusterProperty(URL_SCHEME, "http"));
|
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 {
|
class StateWatcher implements Watcher {
|
||||||
private final String coll;
|
private final String coll;
|
||||||
|
|
||||||
|
@ -1279,7 +1310,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
Set<String> liveNodes = ZkStateReader.this.liveNodes;
|
Set<String> liveNodes = ZkStateReader.this.liveNodes;
|
||||||
log.info("A cluster state change: [{}] for collection [{}] has occurred - updating... (live nodes size: [{}])",
|
log.info("A cluster state change: [{}] for collection [{}] has occurred - updating... (live nodes size: [{}])",
|
||||||
event, coll, liveNodes.size());
|
event, coll, liveNodes.size());
|
||||||
|
|
||||||
refreshAndWatch();
|
refreshAndWatch();
|
||||||
|
|
||||||
|
@ -1310,7 +1341,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Watches the legacy clusterstate.json. */
|
/**
|
||||||
|
* Watches the legacy clusterstate.json.
|
||||||
|
*/
|
||||||
class LegacyClusterStateWatcher implements Watcher {
|
class LegacyClusterStateWatcher implements Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1324,13 +1357,15 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
refreshAndWatch();
|
refreshAndWatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Must hold {@link #getUpdateLock()} before calling this method. */
|
/**
|
||||||
|
* Must hold {@link #getUpdateLock()} before calling this method.
|
||||||
|
*/
|
||||||
public void refreshAndWatch() {
|
public void refreshAndWatch() {
|
||||||
try {
|
try {
|
||||||
refreshLegacyClusterState(this);
|
refreshLegacyClusterState(this);
|
||||||
} catch (KeeperException.NoNodeException e) {
|
} catch (KeeperException.NoNodeException e) {
|
||||||
throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE,
|
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) {
|
} catch (KeeperException.SessionExpiredException | KeeperException.ConnectionLossException e) {
|
||||||
log.warn("ZooKeeper watch triggered, but Solr cannot talk to ZK: [{}]", e.getMessage());
|
log.warn("ZooKeeper watch triggered, but Solr cannot talk to ZK: [{}]", e.getMessage());
|
||||||
} catch (KeeperException e) {
|
} catch (KeeperException e) {
|
||||||
|
@ -1344,7 +1379,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Watches collection properties */
|
/**
|
||||||
|
* Watches collection properties
|
||||||
|
*/
|
||||||
class PropsWatcher implements Watcher {
|
class PropsWatcher implements Watcher {
|
||||||
private final String coll;
|
private final String coll;
|
||||||
private long watchUntilNs;
|
private long watchUntilNs;
|
||||||
|
@ -1356,11 +1393,11 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
|
|
||||||
PropsWatcher(String coll, long forMillis) {
|
PropsWatcher(String coll, long forMillis) {
|
||||||
this.coll = coll;
|
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) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1428,7 +1465,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Watches /collections children . */
|
/**
|
||||||
|
* Watches /collections children .
|
||||||
|
*/
|
||||||
class CollectionsChildWatcher implements Watcher {
|
class CollectionsChildWatcher implements Watcher {
|
||||||
|
|
||||||
@Override
|
@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() {
|
public void refreshAndWatch() {
|
||||||
try {
|
try {
|
||||||
refreshCollectionList(this);
|
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 {
|
class LiveNodeWatcher implements Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1531,7 +1574,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCollectionPathRoot(String coll) {
|
public static String getCollectionPathRoot(String coll) {
|
||||||
return COLLECTIONS_ZKNODE+"/"+coll;
|
return COLLECTIONS_ZKNODE + "/" + coll;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCollectionPath(String 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
|
* Notify this reader that a local Core is a member of a collection, and so that collection
|
||||||
* state should be watched.
|
* state should be watched.
|
||||||
*
|
* <p>
|
||||||
* Not a public API. This method should only be called from ZkController.
|
* Not a public API. This method should only be called from ZkController.
|
||||||
*
|
* <p>
|
||||||
* The number of cores per-collection is tracked, and adding multiple cores from the same
|
* The number of cores per-collection is tracked, and adding multiple cores from the same
|
||||||
* collection does not increase the number of watches.
|
* collection does not increase the number of watches.
|
||||||
*
|
*
|
||||||
* @param collection the collection that the core is a member of
|
* @param collection the collection that the core is a member of
|
||||||
*
|
|
||||||
* @see ZkStateReader#unregisterCore(String)
|
* @see ZkStateReader#unregisterCore(String)
|
||||||
*/
|
*/
|
||||||
public void registerCore(String collection) {
|
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.
|
* Notify this reader that a local core that is a member of a collection has been closed.
|
||||||
*
|
* <p>
|
||||||
* Not a public API. This method should only be called from ZkController.
|
* Not a public API. This method should only be called from ZkController.
|
||||||
*
|
* <p>
|
||||||
* If no cores are registered for a collection, and there are no {@link CollectionStateWatcher}s
|
* 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.
|
* for that collection either, the collection watch will be removed.
|
||||||
*
|
*
|
||||||
|
@ -1619,7 +1661,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
*/
|
*/
|
||||||
public void registerCollectionStateWatcher(String collection, CollectionStateWatcher stateWatcher) {
|
public void registerCollectionStateWatcher(String collection, CollectionStateWatcher stateWatcher) {
|
||||||
final DocCollectionAndLiveNodesWatcherWrapper wrapper
|
final DocCollectionAndLiveNodesWatcherWrapper wrapper
|
||||||
= new DocCollectionAndLiveNodesWatcherWrapper(collection, stateWatcher);
|
= new DocCollectionAndLiveNodesWatcherWrapper(collection, stateWatcher);
|
||||||
|
|
||||||
registerDocCollectionWatcher(collection, wrapper);
|
registerDocCollectionWatcher(collection, wrapper);
|
||||||
registerLiveNodesListener(wrapper);
|
registerLiveNodesListener(wrapper);
|
||||||
|
@ -1673,14 +1715,14 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
* instead
|
* instead
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see #waitForState(String, long, TimeUnit, Predicate)
|
|
||||||
* @see #registerCollectionStateWatcher
|
|
||||||
* @param collection the collection to watch
|
* @param collection the collection to watch
|
||||||
* @param wait how long to wait
|
* @param wait how long to wait
|
||||||
* @param unit the units of the wait parameter
|
* @param unit the units of the wait parameter
|
||||||
* @param predicate the predicate to call on state changes
|
* @param predicate the predicate to call on state changes
|
||||||
* @throws InterruptedException on interrupt
|
* @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)
|
public void waitForState(final String collection, long wait, TimeUnit unit, CollectionStatePredicate predicate)
|
||||||
throws InterruptedException, TimeoutException {
|
throws InterruptedException, TimeoutException {
|
||||||
|
@ -1707,8 +1749,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
if (!latch.await(wait, unit))
|
if (!latch.await(wait, unit))
|
||||||
throw new TimeoutException("Timeout waiting to see state for collection=" + collection + " :" + docCollection.get());
|
throw new TimeoutException("Timeout waiting to see state for collection=" + collection + " :" + docCollection.get());
|
||||||
|
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
removeCollectionStateWatcher(collection, watcher);
|
removeCollectionStateWatcher(collection, watcher);
|
||||||
waitLatches.remove(latch);
|
waitLatches.remove(latch);
|
||||||
}
|
}
|
||||||
|
@ -1727,7 +1768,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
* @param unit the units of the wait parameter
|
* @param unit the units of the wait parameter
|
||||||
* @param predicate the predicate to call on state changes
|
* @param predicate the predicate to call on state changes
|
||||||
* @throws InterruptedException on interrupt
|
* @throws InterruptedException on interrupt
|
||||||
* @throws TimeoutException on timeout
|
* @throws TimeoutException on timeout
|
||||||
*/
|
*/
|
||||||
public void waitForState(final String collection, long wait, TimeUnit unit, Predicate<DocCollection> predicate)
|
public void waitForState(final String collection, long wait, TimeUnit unit, Predicate<DocCollection> predicate)
|
||||||
throws InterruptedException, TimeoutException {
|
throws InterruptedException, TimeoutException {
|
||||||
|
@ -1754,8 +1795,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
if (!latch.await(wait, unit))
|
if (!latch.await(wait, unit))
|
||||||
throw new TimeoutException("Timeout waiting to see state for collection=" + collection + " :" + docCollection.get());
|
throw new TimeoutException("Timeout waiting to see state for collection=" + collection + " :" + docCollection.get());
|
||||||
|
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
removeDocCollectionWatcher(collection, watcher);
|
removeDocCollectionWatcher(collection, watcher);
|
||||||
waitLatches.remove(latch);
|
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
|
* 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.
|
* implementors should avoid changing state within the predicate call itself.
|
||||||
* </p>
|
* </p>
|
||||||
* @param wait how long to wait
|
*
|
||||||
* @param unit the units of the wait parameter
|
* @param wait how long to wait
|
||||||
* @param predicate the predicate to call on state changes
|
* @param unit the units of the wait parameter
|
||||||
|
* @param predicate the predicate to call on state changes
|
||||||
* @throws InterruptedException on interrupt
|
* @throws InterruptedException on interrupt
|
||||||
* @throws TimeoutException on timeout
|
* @throws TimeoutException on timeout
|
||||||
*/
|
*/
|
||||||
public void waitForLiveNodes(long wait, TimeUnit unit, LiveNodesPredicate predicate)
|
public void waitForLiveNodes(long wait, TimeUnit unit, LiveNodesPredicate predicate)
|
||||||
throws InterruptedException, TimeoutException {
|
throws InterruptedException, TimeoutException {
|
||||||
|
@ -1798,8 +1839,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
if (!latch.await(wait, unit))
|
if (!latch.await(wait, unit))
|
||||||
throw new TimeoutException("Timeout waiting for live nodes, currently they are: " + getClusterState().getLiveNodes());
|
throw new TimeoutException("Timeout waiting for live nodes, currently they are: " + getClusterState().getLiveNodes());
|
||||||
|
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
removeLiveNodesListener(listener);
|
removeLiveNodesListener(listener);
|
||||||
waitLatches.remove(latch);
|
waitLatches.remove(latch);
|
||||||
}
|
}
|
||||||
|
@ -1813,13 +1853,13 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
* collection.
|
* collection.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see #registerCollectionStateWatcher
|
|
||||||
* @param collection the collection
|
* @param collection the collection
|
||||||
* @param watcher the watcher
|
* @param watcher the watcher
|
||||||
|
* @see #registerCollectionStateWatcher
|
||||||
*/
|
*/
|
||||||
public void removeCollectionStateWatcher(String collection, CollectionStateWatcher watcher) {
|
public void removeCollectionStateWatcher(String collection, CollectionStateWatcher watcher) {
|
||||||
final DocCollectionAndLiveNodesWatcherWrapper wrapper
|
final DocCollectionAndLiveNodesWatcherWrapper wrapper
|
||||||
= new DocCollectionAndLiveNodesWatcherWrapper(collection, watcher);
|
= new DocCollectionAndLiveNodesWatcherWrapper(collection, watcher);
|
||||||
|
|
||||||
removeDocCollectionWatcher(collection, wrapper);
|
removeDocCollectionWatcher(collection, wrapper);
|
||||||
removeLiveNodesListener(wrapper);
|
removeLiveNodesListener(wrapper);
|
||||||
|
@ -1832,9 +1872,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
* collection.
|
* collection.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see #registerDocCollectionWatcher
|
|
||||||
* @param collection the collection
|
* @param collection the collection
|
||||||
* @param watcher the watcher
|
* @param watcher the watcher
|
||||||
|
* @see #registerDocCollectionWatcher
|
||||||
*/
|
*/
|
||||||
public void removeDocCollectionWatcher(String collection, DocCollectionWatcher watcher) {
|
public void removeDocCollectionWatcher(String collection, DocCollectionWatcher watcher) {
|
||||||
AtomicBoolean reconstructState = new AtomicBoolean(false);
|
AtomicBoolean reconstructState = new AtomicBoolean(false);
|
||||||
|
@ -1967,8 +2007,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
notifications.submit(new Notification(collection, collectionState));
|
notifications.submit(new Notification(collection, collectionState));
|
||||||
}
|
} catch (RejectedExecutionException e) {
|
||||||
catch (RejectedExecutionException e) {
|
|
||||||
if (closed == false) {
|
if (closed == false) {
|
||||||
log.error("Couldn't run collection notifications for {}", collection, e);
|
log.error("Couldn't run collection notifications for {}", collection, e);
|
||||||
}
|
}
|
||||||
|
@ -2011,7 +2050,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
// Aliases related
|
// Aliases related
|
||||||
//
|
//
|
||||||
|
|
||||||
/** Access to the {@link Aliases}. */
|
/**
|
||||||
|
* Access to the {@link Aliases}.
|
||||||
|
*/
|
||||||
public final AliasesManager aliasesManager = new AliasesManager();
|
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
|
* 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.
|
* 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?
|
// 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());
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
@ -2247,9 +2288,9 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other instanceof DocCollectionAndLiveNodesWatcherWrapper) {
|
if (other instanceof DocCollectionAndLiveNodesWatcherWrapper) {
|
||||||
DocCollectionAndLiveNodesWatcherWrapper that
|
DocCollectionAndLiveNodesWatcherWrapper that
|
||||||
= (DocCollectionAndLiveNodesWatcherWrapper) other;
|
= (DocCollectionAndLiveNodesWatcherWrapper) other;
|
||||||
return this.collectionName.equals(that.collectionName)
|
return this.collectionName.equals(that.collectionName)
|
||||||
&& this.delegate.equals(that.delegate);
|
&& this.delegate.equals(that.delegate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2263,7 +2304,7 @@ public class ZkStateReader implements SolrCloseable {
|
||||||
@Override
|
@Override
|
||||||
public boolean onStateChanged(DocCollection collectionState) {
|
public boolean onStateChanged(DocCollection collectionState) {
|
||||||
final boolean result = delegate.onStateChanged(ZkStateReader.this.liveNodes,
|
final boolean result = delegate.onStateChanged(ZkStateReader.this.liveNodes,
|
||||||
collectionState);
|
collectionState);
|
||||||
if (result) {
|
if (result) {
|
||||||
// it might be a while before live nodes changes, so proactively remove ourselves
|
// it might be a while before live nodes changes, so proactively remove ourselves
|
||||||
removeLiveNodesListener(this);
|
removeLiveNodesListener(this);
|
||||||
|
|
Loading…
Reference in New Issue