You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ma...@apache.org on 2015/05/27 17:37:30 UTC
svn commit: r1682060 - in /lucene/dev/trunk/solr: ./
core/src/java/org/apache/solr/client/solrj/embedded/
core/src/java/org/apache/solr/cloud/ core/src/java/org/apache/solr/core/
core/src/java/org/apache/solr/servlet/ core/src/test/org/apache/solr/clou...
Author: markrmiller
Date: Wed May 27 15:37:29 2015
New Revision: 1682060
URL: http://svn.apache.org/r1682060
Log:
SOLR-7361: Slow loading SolrCores should not hold up all other SolrCores that have finished loading from serving requests.
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCores.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/ExternalCollectionsTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudCluster.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java
lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Wed May 27 15:37:29 2015
@@ -86,7 +86,9 @@ New Features
Bug Fixes
----------------------
-(no changes)
+
+* SOLR-7361: Slow loading SolrCores should not hold up all other SolrCores that have finished loading from serving
+ requests. (Mark Miller, Timothy Potter, Ramkumar Aiyengar)
Optimizations
----------------------
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettyConfig.java Wed May 27 15:37:29 2015
@@ -30,6 +30,8 @@ public class JettyConfig {
public final String context;
public final boolean stopAtShutdown;
+
+ public final Long waitForLoadingCoresToFinishMs;
public final Map<ServletHolder, String> extraServlets;
@@ -37,11 +39,12 @@ public class JettyConfig {
public final SSLConfig sslConfig;
- private JettyConfig(int port, String context, boolean stopAtShutdown, Map<ServletHolder, String> extraServlets,
+ private JettyConfig(int port, String context, boolean stopAtShutdown, Long waitForLoadingCoresToFinishMs, Map<ServletHolder, String> extraServlets,
Map<Class<? extends Filter>, String> extraFilters, SSLConfig sslConfig) {
this.port = port;
this.context = context;
this.stopAtShutdown = stopAtShutdown;
+ this.waitForLoadingCoresToFinishMs = waitForLoadingCoresToFinishMs;
this.extraServlets = extraServlets;
this.extraFilters = extraFilters;
this.sslConfig = sslConfig;
@@ -67,6 +70,7 @@ public class JettyConfig {
int port = 0;
String context = "/solr";
boolean stopAtShutdown = true;
+ Long waitForLoadingCoresToFinishMs = 300000L;
Map<ServletHolder, String> extraServlets = new TreeMap<>();
Map<Class<? extends Filter>, String> extraFilters = new TreeMap<>();
SSLConfig sslConfig = null;
@@ -85,6 +89,11 @@ public class JettyConfig {
this.stopAtShutdown = stopAtShutdown;
return this;
}
+
+ public Builder waitForLoadingCoresToFinish(Long waitForLoadingCoresToFinishMs) {
+ this.waitForLoadingCoresToFinishMs = waitForLoadingCoresToFinishMs;
+ return this;
+ }
public Builder withServlet(ServletHolder servlet, String servletName) {
extraServlets.put(servlet, servletName);
@@ -114,7 +123,7 @@ public class JettyConfig {
}
public JettyConfig build() {
- return new JettyConfig(port, context, stopAtShutdown, extraServlets, extraFilters, sslConfig);
+ return new JettyConfig(port, context, stopAtShutdown, waitForLoadingCoresToFinishMs, extraServlets, extraFilters, sslConfig);
}
}
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java Wed May 27 15:37:29 2015
@@ -17,6 +17,7 @@
package org.apache.solr.client.solrj.embedded;
+import org.apache.solr.core.CoreContainer;
import org.apache.solr.servlet.SolrDispatchFilter;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
@@ -393,6 +394,8 @@ public class JettySolrRunner {
}
}
}
+
+ if (config.waitForLoadingCoresToFinishMs != null && config.waitForLoadingCoresToFinishMs > 0L) waitForLoadingCoresToFinish(config.waitForLoadingCoresToFinishMs);
} finally {
if (prevContext != null) {
MDC.setContextMap(prevContext);
@@ -562,4 +565,14 @@ public class JettySolrRunner {
public String getSolrHome() {
return solrHome;
}
+
+ private void waitForLoadingCoresToFinish(long timeoutMs) {
+ if (dispatchFilter != null) {
+ SolrDispatchFilter solrFilter = (SolrDispatchFilter) dispatchFilter.getFilter();
+ CoreContainer cores = solrFilter.getCores();
+ if (cores != null) {
+ cores.waitForLoadingCoresToFinish(timeoutMs);
+ }
+ }
+ }
}
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java Wed May 27 15:37:29 2015
@@ -1902,7 +1902,7 @@ public final class ZkController {
} catch (NoNodeException nne) {
return;
} catch (Exception e) {
- log.warn("could not readd the overseer designate ", e);
+ log.warn("could not read the overseer designate ", e);
}
}
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java Wed May 27 15:37:29 2015
@@ -27,7 +27,10 @@ import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@@ -99,6 +102,9 @@ public class CoreContainer {
protected ShardHandlerFactory shardHandlerFactory;
private UpdateShardHandler updateShardHandler;
+
+ private ExecutorService coreContainerWorkExecutor = ExecutorUtil.newMDCAwareCachedThreadPool(
+ new DefaultSolrThreadFactory("coreContainerWorkExecutor") );
protected LogWatcher logging = null;
@@ -122,6 +128,8 @@ public class CoreContainer {
private PluginBag<SolrRequestHandler> containerHandlers = new PluginBag<>(SolrRequestHandler.class, null);
+ private boolean asyncSolrCoreLoad;
+
public ExecutorService getCoreZkRegisterExecutorService() {
return zkSys.getCoreZkRegisterExecutorService();
}
@@ -183,13 +191,22 @@ public class CoreContainer {
public CoreContainer(NodeConfig config, Properties properties) {
this(config, properties, new CorePropertiesLocator(config.getCoreRootDirectory()));
}
+
+ public CoreContainer(NodeConfig config, Properties properties, boolean asyncSolrCoreLoad) {
+ this(config, properties, new CorePropertiesLocator(config.getCoreRootDirectory()), asyncSolrCoreLoad);
+ }
public CoreContainer(NodeConfig config, Properties properties, CoresLocator locator) {
+ this(config, properties, locator, false);
+ }
+
+ public CoreContainer(NodeConfig config, Properties properties, CoresLocator locator, boolean asyncSolrCoreLoad) {
this.loader = config.getSolrResourceLoader();
this.solrHome = loader.getInstanceDir();
this.cfg = checkNotNull(config);
this.coresLocator = locator;
this.containerProperties = new Properties(properties);
+ this.asyncSolrCoreLoad = asyncSolrCoreLoad;
}
private void intializeAuthorizationPlugin() {
@@ -359,57 +376,77 @@ public class CoreContainer {
ExecutorService coreLoadExecutor = ExecutorUtil.newMDCAwareFixedThreadPool(
( zkSys.getZkController() == null ? cfg.getCoreLoadThreadCount() : Integer.MAX_VALUE ),
new DefaultSolrThreadFactory("coreLoadExecutor") );
-
+ final List<Future<SolrCore>> futures = new ArrayList<Future<SolrCore>>();
try {
List<CoreDescriptor> cds = coresLocator.discover(this);
checkForDuplicateCoreNames(cds);
- List<Callable<SolrCore>> creators = new ArrayList<>();
+
for (final CoreDescriptor cd : cds) {
if (cd.isTransient() || !cd.isLoadOnStartup()) {
solrCores.putDynamicDescriptor(cd.getName(), cd);
+ } else if (asyncSolrCoreLoad) {
+ solrCores.markCoreAsLoading(cd);
}
if (cd.isLoadOnStartup()) {
- creators.add(new Callable<SolrCore>() {
+ futures.add(coreLoadExecutor.submit(new Callable<SolrCore>() {
@Override
public SolrCore call() throws Exception {
- if (zkSys.getZkController() != null) {
- zkSys.getZkController().throwErrorIfReplicaReplaced(cd);
+ SolrCore core;
+ try {
+ if (zkSys.getZkController() != null) {
+ zkSys.getZkController().throwErrorIfReplicaReplaced(cd);
+ }
+
+ core = create(cd, false);
+ } finally {
+ if (asyncSolrCoreLoad) {
+ solrCores.markCoreAsNotLoading(cd);
+ }
}
- return create(cd, false);
+ try {
+ zkSys.registerInZk(core, true);
+ } catch (Throwable t) {
+ SolrException.log(log, "Error registering SolrCore", t);
+ }
+ return core;
}
- });
+ }));
}
}
- try {
- coreLoadExecutor.invokeAll(creators);
- }
- catch (InterruptedException e) {
- throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Interrupted while loading cores");
- }
// Start the background thread
backgroundCloser = new CloserThread(this, solrCores, cfg);
backgroundCloser.start();
} finally {
- ExecutorUtil.shutdownNowAndAwaitTermination(coreLoadExecutor);
+ if (asyncSolrCoreLoad && futures != null) {
+ Thread shutdownThread = new Thread() {
+ public void run() {
+ try {
+ for (Future<SolrCore> future : futures) {
+ try {
+ future.get();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } catch (ExecutionException e) {
+ log.error("Error waiting for SolrCore to be created", e);
+ }
+ }
+ } finally {
+ ExecutorUtil.shutdownNowAndAwaitTermination(coreLoadExecutor);
+ }
+ }
+ };
+ coreContainerWorkExecutor.submit(shutdownThread);
+ } else {
+ ExecutorUtil.shutdownAndAwaitTermination(coreLoadExecutor);
+ }
}
if (isZooKeeperAware()) {
- // register in zk in background threads
- Collection<SolrCore> cores = getCores();
- if (cores != null) {
- for (SolrCore core : cores) {
- try {
- zkSys.registerInZk(core, true);
- } catch (Throwable t) {
- SolrException.log(log, "Error registering SolrCore", t);
- }
- }
- }
zkSys.getZkController().checkOverseerDesignate();
}
}
@@ -441,6 +478,8 @@ public class CoreContainer {
isShutDown = true;
+ ExecutorUtil.shutdownAndAwaitTermination(coreContainerWorkExecutor);
+
if (isZooKeeperAware()) {
cancelCoreRecoveries();
zkSys.publishCoresAsDown(solrCores.getCores());
@@ -621,7 +660,7 @@ public class CoreContainer {
public SolrCore create(CoreDescriptor dcore, boolean publishState) {
if (isShutDown) {
- throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Solr has close.");
+ throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Solr has been shutdown.");
}
SolrCore core = null;
@@ -912,6 +951,20 @@ public class CoreContainer {
public JarRepository getJarRepository(){
return jarRepository;
}
+
+ /**
+ * If using asyncSolrCoreLoad=true, calling this after {@link #load()} will
+ * not return until all cores have finished loading.
+ *
+ * @param timeoutMs timeout, upon which method simply returns
+ */
+ public void waitForLoadingCoresToFinish(long timeoutMs) {
+ solrCores.waitForLoadingCoresToFinish(timeoutMs);
+ }
+
+ public void waitForLoadingCore(String name, long timeoutMs) {
+ solrCores.waitForLoadingCoreToFinish(name, timeoutMs);
+ }
// ---------------- CoreContainer request handlers --------------
@@ -1001,6 +1054,10 @@ public class CoreContainer {
public SolrResourceLoader getResourceLoader() {
return loader;
}
+
+ public boolean isCoreLoading(String name) {
+ return solrCores.isCoreLoading(name);
+ }
public AuthorizationPlugin getAuthorizationPlugin() {
return authorizationPlugin;
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCores.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCores.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCores.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCores.java Wed May 27 15:37:29 2015
@@ -25,12 +25,15 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
class SolrCores {
@@ -46,8 +49,10 @@ class SolrCores {
private final Map<String, SolrCore> createdCores = new LinkedHashMap<>();
private final CoreContainer container;
+
+ private Set<String> currentlyLoadingCores = Collections.newSetFromMap(new ConcurrentHashMap<String,Boolean>());
- private static final Logger logger = LoggerFactory.getLogger(SolrCores.class);
+ private static final Logger log = LoggerFactory.getLogger(SolrCores.class);
// This map will hold objects that are being currently operated on. The core (value) may be null in the case of
// initial load. The rule is, never to any operation on a core that is currently being operated upon.
@@ -72,7 +77,7 @@ class SolrCores {
if (size() > cacheSize) {
synchronized (modifyLock) {
SolrCore coreToClose = eldest.getValue();
- logger.info("Closing transient core [{}]", coreToClose.getName());
+ log.info("Closing transient core [{}]", coreToClose.getName());
pendingCloses.add(coreToClose); // Essentially just queue this core up for closing.
modifyLock.notifyAll(); // Wakes up closer thread too
}
@@ -395,6 +400,7 @@ class SolrCores {
/**
* Return the CoreDescriptor corresponding to a given core name.
+ * Blocks if the SolrCore is still loading until it is ready.
* @param coreName the name of the core
* @return the CoreDescriptor
*/
@@ -425,4 +431,63 @@ class SolrCores {
}
return cds;
}
+
+ // cores marked as loading will block on getCore
+ public void markCoreAsLoading(CoreDescriptor cd) {
+ synchronized (modifyLock) {
+ currentlyLoadingCores.add(cd.getName());
+ }
+ }
+
+ //cores marked as loading will block on getCore
+ public void markCoreAsNotLoading(CoreDescriptor cd) {
+ synchronized (modifyLock) {
+ currentlyLoadingCores.remove(cd.getName());
+ }
+ }
+
+ // returns when no cores are marked as loading
+ public void waitForLoadingCoresToFinish(long timeoutMs) {
+ long time = System.nanoTime();
+ long timeout = time + TimeUnit.NANOSECONDS.convert(timeoutMs, TimeUnit.MILLISECONDS);
+ synchronized (modifyLock) {
+ while (!currentlyLoadingCores.isEmpty()) {
+ try {
+ modifyLock.wait(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ if (System.nanoTime() >= timeout) {
+ log.warn("Timed out waiting for SolrCores to finish loading.");
+ break;
+ }
+ }
+ }
+ }
+
+ // returns when core is finished loading, throws exception if no such core loading or loaded
+ public void waitForLoadingCoreToFinish(String core, long timeoutMs) {
+ long time = System.nanoTime();
+ long timeout = time + TimeUnit.NANOSECONDS.convert(timeoutMs, TimeUnit.MILLISECONDS);
+ synchronized (modifyLock) {
+ while (isCoreLoading(core)) {
+ try {
+ modifyLock.wait(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ if (System.nanoTime() >= timeout) {
+ log.warn("Timed out waiting for SolrCore, {}, to finish loading.", core);
+ break;
+ }
+ }
+ }
+ }
+
+ public boolean isCoreLoading(String name) {
+ if (currentlyLoadingCores.contains(name)) {
+ return true;
+ }
+ return false;
+ }
}
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java Wed May 27 15:37:29 2015
@@ -71,6 +71,7 @@ import org.apache.http.entity.InputStrea
import org.apache.http.util.EntityUtils;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.Aliases;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.Replica;
@@ -232,6 +233,14 @@ public class HttpSolrCall {
core = cores.getCore(corename);
if (core != null) {
path = path.substring(idx);
+ } else if (cores.isCoreLoading(corename)) { // extra mem barriers, so don't look at this before trying to get core
+ throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "SolrCore is loading");
+ } else {
+ // the core may have just finished loading
+ core = cores.getCore(corename);
+ if (core != null) {
+ path = path.substring(idx);
+ }
}
}
if (core == null) {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java Wed May 27 15:37:29 2015
@@ -136,7 +136,7 @@ public class SolrDispatchFilter extends
*/
protected CoreContainer createCoreContainer(String solrHome, Properties extraProperties) {
NodeConfig nodeConfig = loadNodeConfig(solrHome, extraProperties);
- cores = new CoreContainer(nodeConfig, extraProperties);
+ cores = new CoreContainer(nodeConfig, extraProperties, true);
cores.load();
return cores;
}
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java Wed May 27 15:37:29 2015
@@ -519,7 +519,7 @@ public class BasicDistributedZkTest exte
createCores(httpSolrClient, executor, "multiunload2", 1, cnt);
} finally {
if (executor != null) {
- ExecutorUtil.shutdownAndAwaitTermination(executor, 120, TimeUnit.SECONDS);
+ ExecutorUtil.shutdownAndAwaitTermination(executor);
}
}
}
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java Wed May 27 15:37:29 2015
@@ -158,8 +158,6 @@ public class CollectionsAPIDistributedZk
public CollectionsAPIDistributedZkTest() {
sliceCount = 2;
- checkCreatedVsState = false;
-
}
@Override
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java Wed May 27 15:37:29 2015
@@ -93,8 +93,6 @@ public class CustomCollectionTest extend
public CustomCollectionTest() {
sliceCount = 2;
- checkCreatedVsState = false;
-
}
@Override
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java Wed May 27 15:37:29 2015
@@ -71,7 +71,6 @@ public class DeleteLastCustomShardedRepl
public DeleteLastCustomShardedReplicaTest() {
sliceCount = 2;
- checkCreatedVsState = false;
}
@Test
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java Wed May 27 15:37:29 2015
@@ -70,7 +70,6 @@ public class DeleteReplicaTest extends A
public DeleteReplicaTest() {
sliceCount = 2;
- checkCreatedVsState = false;
}
@Test
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/ExternalCollectionsTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/ExternalCollectionsTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/ExternalCollectionsTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/ExternalCollectionsTest.java Wed May 27 15:37:29 2015
@@ -49,7 +49,6 @@ public class ExternalCollectionsTest ext
}
public ExternalCollectionsTest() {
- checkCreatedVsState = false;
}
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java Wed May 27 15:37:29 2015
@@ -80,8 +80,6 @@ public class OverseerRolesTest extends
public OverseerRolesTest() {
sliceCount = 2;
fixShardCount(TEST_NIGHTLY ? 6 : 2);
-
- checkCreatedVsState = false;
}
@Test
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java Wed May 27 15:37:29 2015
@@ -100,8 +100,6 @@ public class SharedFSAutoReplicaFailover
sliceCount = 2;
completionService = new ExecutorCompletionService<>(executor);
pending = new HashSet<>();
- checkCreatedVsState = false;
-
}
@Test
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudCluster.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudCluster.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudCluster.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudCluster.java Wed May 27 15:37:29 2015
@@ -22,10 +22,13 @@ import org.apache.lucene.util.LuceneTest
import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettyConfig;
+import org.apache.solr.client.solrj.embedded.JettyConfig.Builder;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.Replica;
@@ -88,7 +91,9 @@ public class TestMiniSolrCloudCluster ex
protected void testCollectionCreateSearchDelete() throws Exception {
File solrXml = new File(SolrTestCaseJ4.TEST_HOME(), "solr-no-core.xml");
- MiniSolrCloudCluster miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, null, createTempDir().toFile(), solrXml, null, null);
+ Builder jettyConfig = JettyConfig.builder();
+ jettyConfig.waitForLoadingCoresToFinish(null);
+ MiniSolrCloudCluster miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, createTempDir().toFile(), solrXml, jettyConfig.build());
try {
assertNotNull(miniCluster.getZkServer());
@@ -174,6 +179,16 @@ public class TestMiniSolrCloudCluster ex
startedServer = miniCluster.startJettySolrRunner(null, null, null);
assertTrue(startedServer.isRunning());
assertEquals(NUM_SERVERS, miniCluster.getJettySolrRunners().size());
+ Thread.sleep(15000);
+ try {
+ cloudSolrClient.query(query);
+ fail("Expected exception on query because collection should not be ready - we have turned on async core loading");
+ } catch (SolrServerException e) {
+ SolrException rc = (SolrException) e.getRootCause();
+ assertTrue(rc.code() >= 500 && rc.code() < 600);
+ } catch (SolrException e) {
+ assertTrue(e.code() >= 500 && e.code() < 600);
+ }
// delete the collection we created earlier
miniCluster.deleteCollection(collectionName);
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java Wed May 27 15:37:29 2015
@@ -56,7 +56,6 @@ public class UnloadDistributedZkTest ext
public UnloadDistributedZkTest() {
super();
- checkCreatedVsState = false;
}
@Test
@@ -375,7 +374,7 @@ public class UnloadDistributedZkTest ext
// create the cores
createCores(adminClient, executor, "multiunload", 2, cnt);
} finally {
- ExecutorUtil.shutdownAndAwaitTermination(executor, 120, TimeUnit.SECONDS);
+ ExecutorUtil.shutdownAndAwaitTermination(executor);
}
executor = new ExecutorUtil.MDCAwareThreadPoolExecutor(0, Integer.MAX_VALUE, 5,
@@ -399,7 +398,7 @@ public class UnloadDistributedZkTest ext
Thread.sleep(random().nextInt(50));
}
} finally {
- ExecutorUtil.shutdownAndAwaitTermination(executor, 120, TimeUnit.SECONDS);
+ ExecutorUtil.shutdownAndAwaitTermination(executor);
}
}
}
Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java Wed May 27 15:37:29 2015
@@ -1068,7 +1068,7 @@ public class CloudSolrClient extends Sol
for (String s : collectionNames) {
if(s!=null) collectionStateCache.remove(s);
}
- throw new SolrException(SolrException.ErrorCode.INVALID_STATE, "Not enough nodes to handle the request");
+ throw new SolrException(SolrException.ErrorCode.INVALID_STATE, "Could not find a healthy node to handle the request.");
}
Collections.shuffle(theUrlList, rand);
Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java Wed May 27 15:37:29 2015
@@ -37,42 +37,37 @@ import org.slf4j.MDC;
public class ExecutorUtil {
public static Logger log = LoggerFactory.getLogger(ExecutorUtil.class);
+ // this will interrupt the threads! Lucene and Solr do not like this because it can close channels, so only use
+ // this if you know what you are doing - you probably want shutdownAndAwaitTermination
public static void shutdownNowAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
- pool.shutdownNow(); // Cancel currently executing tasks
+ pool.shutdownNow(); // Cancel currently executing tasks - NOTE: this interrupts!
boolean shutdown = false;
while (!shutdown) {
try {
// Wait a while for existing tasks to terminate
- shutdown = pool.awaitTermination(5, TimeUnit.SECONDS);
+ shutdown = pool.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
// Preserve interrupt status
Thread.currentThread().interrupt();
}
if (!shutdown) {
- pool.shutdownNow(); // Cancel currently executing tasks
+ pool.shutdownNow(); // Cancel currently executing tasks - NOTE: this interrupts!
}
}
}
-
- public static void shutdownAndAwaitTermination(ExecutorService pool) {
- shutdownAndAwaitTermination(pool, 60, TimeUnit.SECONDS);
- }
- public static void shutdownAndAwaitTermination(ExecutorService pool, long timeout, TimeUnit timeUnit) {
+ public static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
boolean shutdown = false;
while (!shutdown) {
try {
// Wait a while for existing tasks to terminate
- shutdown = pool.awaitTermination(timeout, timeUnit);
+ shutdown = pool.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
// Preserve interrupt status
Thread.currentThread().interrupt();
}
- if (!shutdown) {
- pool.shutdownNow(); // Cancel currently executing tasks
- }
}
}
Modified: lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java?rev=1682060&r1=1682059&r2=1682060&view=diff
==============================================================================
--- lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java (original)
+++ lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java Wed May 27 15:37:29 2015
@@ -118,7 +118,6 @@ public abstract class AbstractFullDistri
protected Map<String,CloudJettyRunner> shardToLeaderJetty = new HashMap<>();
private boolean cloudInit;
- protected boolean checkCreatedVsState;
protected boolean useJettyDataDir = true;
protected Map<URI,SocketProxy> proxies = new HashMap<>();
@@ -305,7 +304,7 @@ public abstract class AbstractFullDistri
initCloud();
- createJettys(numServers, checkCreatedVsState).size();
+ createJettys(numServers).size();
int cnt = getTotalReplicas(DEFAULT_COLLECTION);
if (cnt > 0) {
@@ -336,10 +335,6 @@ public abstract class AbstractFullDistri
}
}
- protected List<JettySolrRunner> createJettys(int numJettys) throws Exception {
- return createJettys(numJettys, false);
- }
-
protected String defaultStateFormat = String.valueOf( 1 + random().nextInt(2));
protected String getStateFormat() {
@@ -350,13 +345,7 @@ public abstract class AbstractFullDistri
return defaultStateFormat; // random
}
- /**
- * @param checkCreatedVsState
- * if true, make sure the number created (numJettys) matches the
- * number in the cluster state - if you add more jetties this may not
- * be the case
- */
- protected List<JettySolrRunner> createJettys(int numJettys, boolean checkCreatedVsState) throws Exception {
+ protected List<JettySolrRunner> createJettys(int numJettys) throws Exception {
List<JettySolrRunner> jettys = new ArrayList<>();
List<SolrClient> clients = new ArrayList<>();
StringBuilder sb = new StringBuilder();
@@ -393,26 +382,24 @@ public abstract class AbstractFullDistri
this.clients.addAll(clients);
int numShards = getTotalReplicas(DEFAULT_COLLECTION);
- if (checkCreatedVsState) {
- // now wait until we see that the number of shards in the cluster state
- // matches what we expect
- int retries = 0;
- while (numShards != getShardCount()) {
- numShards = getTotalReplicas(DEFAULT_COLLECTION);
- if (numShards == getShardCount()) break;
- if (retries++ == 60) {
- printLayoutOnTearDown = true;
- fail("Shards in the state does not match what we set:" + numShards
- + " vs " + getShardCount());
- }
- Thread.sleep(500);
- }
- ZkStateReader zkStateReader = cloudClient.getZkStateReader();
- // also make sure we have a leader for each shard
- for (int i = 1; i <= sliceCount; i++) {
- zkStateReader.getLeaderRetry(DEFAULT_COLLECTION, "shard" + i, 10000);
+ // now wait until we see that the number of shards in the cluster state
+ // matches what we expect
+ int retries = 0;
+ while (numShards != getShardCount()) {
+ numShards = getTotalReplicas(DEFAULT_COLLECTION);
+ if (numShards == getShardCount()) break;
+ if (retries++ == 60) {
+ printLayoutOnTearDown = true;
+ fail("Shards in the state does not match what we set:" + numShards + " vs " + getShardCount());
}
+ Thread.sleep(500);
+ }
+
+ ZkStateReader zkStateReader = cloudClient.getZkStateReader();
+ // make sure we have a leader for each shard
+ for (int i = 1; i <= sliceCount; i++) {
+ zkStateReader.getLeaderRetry(DEFAULT_COLLECTION, "shard" + i, 10000);
}
if (numShards > 0) {
@@ -1784,7 +1771,7 @@ public abstract class AbstractFullDistri
throw new RuntimeException("Could not find a live node for collection:" + collection);
}
- public static void waitForNon403or404or503(HttpSolrClient collectionClient)
+ public static void waitForNon403or404or503(HttpSolrClient collectionClient)
throws Exception {
SolrException exp = null;
long timeoutAt = System.currentTimeMillis() + 30000;