This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_9x by this push:
new 8ee2fe280cf SOLR-17453: Leverage waitForState() instead of busy
waiting (#2737)
8ee2fe280cf is described below
commit 8ee2fe280cf84b8f8780a18c4b52c404e7cfaa81
Author: Pierre Salagnac <[email protected]>
AuthorDate: Thu Nov 7 08:14:40 2024 +0100
SOLR-17453: Leverage waitForState() instead of busy waiting (#2737)
Leverage waitForState() instead of busy waiting in CREATE, MIGRATE,
REINDEXCOLLECTION, MOVEREPLICA commands, and in some tests.
(cherry picked from commit b657ec0c2176ef58c224147b71a91fa5a8267e51)
---
solr/CHANGES.txt | 4 +-
.../cloud/api/collections/CreateCollectionCmd.java | 19 +-
.../solr/cloud/api/collections/MigrateCmd.java | 39 ++-
.../solr/cloud/api/collections/MoveReplicaCmd.java | 45 ++-
.../api/collections/ReindexCollectionCmd.java | 23 +-
.../java/org/apache/solr/servlet/HttpSolrCall.java | 25 +-
...aosMonkeyNothingIsSafeWithPullReplicasTest.java | 2 +-
.../ChaosMonkeySafeLeaderWithPullReplicasTest.java | 2 +-
.../org/apache/solr/cloud/DeleteReplicaTest.java | 12 +-
.../org/apache/solr/cloud/HttpPartitionTest.java | 39 ++-
.../cloud/LeaderFailureAfterFreshStartTest.java | 8 +-
.../apache/solr/cloud/PeerSyncReplicationTest.java | 8 +-
.../org/apache/solr/cloud/TestPullReplica.java | 21 +-
.../solr/cloud/TestPullReplicaErrorHandling.java | 18 +-
.../apache/solr/cloud/TestRebalanceLeaders.java | 312 +++++++++------------
.../org/apache/solr/cloud/TestTlogReplica.java | 65 ++---
.../solr/cloud/api/collections/ShardSplitTest.java | 4 +-
.../SharedFileSystemAutoReplicaFailoverTest.java | 71 ++---
.../org/apache/solr/hdfs/cloud/StressHdfsTest.java | 12 +-
.../AbstractChaosMonkeyNothingIsSafeTestBase.java | 2 +-
.../AbstractChaosMonkeySafeLeaderTestBase.java | 2 +-
.../solr/cloud/AbstractDistribZkTestBase.java | 87 ++----
.../solr/cloud/AbstractFullDistribZkTestBase.java | 128 ++++-----
.../cloud/AbstractUnloadDistributedZkTestBase.java | 69 ++---
24 files changed, 419 insertions(+), 598 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index c1a7cd0f8d2..c72ffca0cdb 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -30,7 +30,7 @@ Improvements
when PKI is used between nodes. (Jason Gerlowski)
* SOLR-17383: Resolved overlapping arguments in the Solr CLI. Removed
duplicative but differing arguments,
- consolidated use of short form arguments -v to not have differing meanings
based on tool. Provide deprecation warning
+ consolidated use of short form arguments -v to not have differing meanings
based on tool. Provide deprecation warning
in command line when deprecated arguments are used. (Eric Pugh, Christos
Malliaridis)
* SOLR-17256: Deprecate SolrRequest `setBasePath` and `getBasePath` methods.
SolrJ users wishing to temporarily
@@ -68,6 +68,8 @@ Optimizations
* SOLR-16503: Switched from HTTP1 to HTTP2 in SolrClientCloudManager by
replacing CloudLegacySolrClient with CloudHttp2SolrClient. (Sanjay Dutt, David
Smiley)
+* SOLR-17453: Leverage waitForState() instead of busy waiting in CREATE,
MIGRATE, REINDEXCOLLECTION, MOVEREPLICA commands, and in some tests. (Pierre
Salagnac)
+
Bug Fixes
---------------------
* SOLR-12429: Uploading a configset with a symbolic link produces a
IOException. Now a error message to user generated instead. (Eric Pugh)
diff --git
a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
index d2aee09883d..b2b2f7a722b 100644
---
a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
+++
b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
@@ -40,9 +40,11 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.apache.solr.client.solrj.cloud.AlreadyExistsException;
import org.apache.solr.client.solrj.cloud.BadVersionException;
import org.apache.solr.client.solrj.cloud.DelegatingCloudManager;
@@ -211,24 +213,19 @@ public class CreateCollectionCmd implements
CollApiCmds.CollectionApiCommand {
}
// wait for a while until we see the collection
- TimeOut waitUntil =
- new TimeOut(30, TimeUnit.SECONDS,
ccc.getSolrCloudManager().getTimeSource());
- boolean created = false;
- while (!waitUntil.hasTimedOut()) {
- waitUntil.sleep(100);
- created =
ccc.getSolrCloudManager().getClusterState().hasCollection(collectionName);
- if (created) break;
- }
- if (!created) {
+ try {
+ newColl =
+ zkStateReader.waitForState(collectionName, 30, TimeUnit.SECONDS,
Objects::nonNull);
+ } catch (TimeoutException e) {
throw new SolrException(
SolrException.ErrorCode.SERVER_ERROR,
- "Could not fully create collection: " + collectionName);
+ "Could not fully create collection: " + collectionName,
+ e);
}
// refresh cluster state (value read below comes from Zookeeper watch
firing following the
// update done previously, be it by Overseer or by this thread when
updates are distributed)
clusterState = ccc.getSolrCloudManager().getClusterState();
- newColl = clusterState.getCollection(collectionName);
}
final List<ReplicaPosition> replicaPositions;
diff --git
a/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
b/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
index 4ee59d13ca9..905ad2bdf7a 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/MigrateCmd.java
@@ -32,6 +32,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.apache.solr.client.solrj.request.CoreAdminRequest;
import org.apache.solr.cloud.DistributedClusterStateUpdater;
import org.apache.solr.cloud.Overseer;
@@ -53,7 +54,6 @@ import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Utils;
import org.apache.solr.handler.component.ShardHandler;
-import org.apache.solr.util.TimeOut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -273,27 +273,26 @@ public class MigrateCmd implements
CollApiCmds.CollectionApiCommand {
// wait for a while until we see the new rule
log.info("Waiting to see routing rule updated in clusterstate");
- TimeOut waitUntil =
- new TimeOut(60, TimeUnit.SECONDS,
ccc.getSolrCloudManager().getTimeSource());
- boolean added = false;
- while (!waitUntil.hasTimedOut()) {
- waitUntil.sleep(100);
- sourceCollection =
zkStateReader.getClusterState().getCollection(sourceCollection.getName());
- sourceSlice = sourceCollection.getSlice(sourceSlice.getName());
- Map<String, RoutingRule> rules = sourceSlice.getRoutingRules();
- if (rules != null) {
- RoutingRule rule =
rules.get(sourceRouter.getRouteKeyNoSuffix(splitKey) + "!");
- if (rule != null && rule.getRouteRanges().contains(splitRange)) {
- added = true;
- break;
- }
- }
- }
- if (!added) {
+
+ try {
+ sourceCollection =
+ zkStateReader.waitForState(
+ sourceCollection.getName(),
+ 60,
+ TimeUnit.SECONDS,
+ c -> {
+ Slice s = c.getSlice(sourceSlice.getName());
+ Map<String, RoutingRule> rules = s.getRoutingRules();
+ if (rules != null) {
+ RoutingRule rule =
rules.get(sourceRouter.getRouteKeyNoSuffix(splitKey) + "!");
+ return rule != null &&
rule.getRouteRanges().contains(splitRange);
+ }
+ return false;
+ });
+ } catch (TimeoutException e) {
throw new SolrException(
- SolrException.ErrorCode.SERVER_ERROR, "Could not add routing rule: "
+ m);
+ SolrException.ErrorCode.SERVER_ERROR, "Could not add routing rule: "
+ m, e);
}
-
log.info("Routing rule added successfully");
// Create temp core on source shard
diff --git
a/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java
b/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java
index cd5097993b4..48f065f537e 100644
---
a/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java
+++
b/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java
@@ -33,6 +33,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.apache.solr.cloud.ActiveReplicaWatcher;
import org.apache.solr.common.SolrCloseableLatch;
import org.apache.solr.common.SolrException;
@@ -46,7 +47,6 @@ import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Utils;
-import org.apache.solr.util.TimeOut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -161,9 +161,7 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
dataDir.toString(),
targetNode,
async,
- coll,
replica,
- slice,
timeout,
waitForFinalState);
} else {
@@ -187,9 +185,7 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
String dataDir,
String targetNode,
String async,
- DocCollection coll,
Replica replica,
- Slice slice,
int timeout,
boolean waitForFinalState)
throws Exception {
@@ -198,8 +194,8 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
skipCreateReplicaInClusterState = "false";
ZkNodeProps removeReplicasProps =
new ZkNodeProps(
- COLLECTION_PROP, coll.getName(),
- SHARD_ID_PROP, slice.getName(),
+ COLLECTION_PROP, replica.getCollection(),
+ SHARD_ID_PROP, replica.getShard(),
REPLICA_PROP, replica.getName());
removeReplicasProps.getProperties().put(CoreAdminParams.DELETE_DATA_DIR,
false);
removeReplicasProps.getProperties().put(CoreAdminParams.DELETE_INDEX,
false);
@@ -217,8 +213,8 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
String.format(
Locale.ROOT,
"Failed to cleanup replica collection=%s shard=%s name=%s,
failure=%s",
- coll.getName(),
- slice.getName(),
+ replica.getCollection(),
+ replica.getShard(),
replica.getName(),
deleteResult.get("failure"));
log.warn(errorString);
@@ -226,17 +222,14 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
return;
}
- TimeOut timeOut =
- new TimeOut(20L, TimeUnit.SECONDS,
ccc.getSolrCloudManager().getTimeSource());
- while (!timeOut.hasTimedOut()) {
- coll =
ccc.getZkStateReader().getClusterState().getCollection(coll.getName());
- if (coll.getReplica(replica.getName()) != null) {
- timeOut.sleep(100);
- } else {
- break;
- }
- }
- if (timeOut.hasTimedOut()) {
+ try {
+ ccc.getZkStateReader()
+ .waitForState(
+ replica.getCollection(),
+ 20L,
+ TimeUnit.SECONDS,
+ c -> c.getReplica(replica.getName()) != null);
+ } catch (TimeoutException e) {
results.add("failure", "Still see deleted replica in clusterstate!");
return;
}
@@ -246,9 +239,9 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
ZkNodeProps addReplicasProps =
new ZkNodeProps(
COLLECTION_PROP,
- coll.getName(),
+ replica.getCollection(),
SHARD_ID_PROP,
- slice.getName(),
+ replica.getShard(),
CoreAdminParams.NODE,
targetNode,
CoreAdminParams.CORE_NODE_NAME,
@@ -277,8 +270,8 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
String.format(
Locale.ROOT,
"Failed to create replica for collection=%s shard=%s" + " on
node=%s, failure=%s",
- coll.getName(),
- slice.getName(),
+ replica.getCollection(),
+ replica.getShard(),
targetNode,
addResult.get("failure"));
results.add("failure", errorString);
@@ -302,8 +295,8 @@ public class MoveReplicaCmd implements
CollApiCmds.CollectionApiCommand {
String.format(
Locale.ROOT,
"Failed to create replica for collection=%s shard=%s" + " on
node=%s, failure=%s",
- coll.getName(),
- slice.getName(),
+ replica.getCollection(),
+ replica.getShard(),
targetNode,
addResult.get("failure"));
log.warn(errorString);
diff --git
a/solr/core/src/java/org/apache/solr/cloud/api/collections/ReindexCollectionCmd.java
b/solr/core/src/java/org/apache/solr/cloud/api/collections/ReindexCollectionCmd.java
index 5ff49538971..8448f6f2999 100644
---
a/solr/core/src/java/org/apache/solr/cloud/api/collections/ReindexCollectionCmd.java
+++
b/solr/core/src/java/org/apache/solr/cloud/api/collections/ReindexCollectionCmd.java
@@ -26,8 +26,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -370,22 +372,17 @@ public class ReindexCollectionCmd implements
CollApiCmds.CollectionApiCommand {
CollectionHandlingUtils.checkResults(
"creating checkpoint collection " + chkCollection, cmdResults, true);
// wait for a while until we see both collections
- TimeOut waitUntil =
- new TimeOut(30, TimeUnit.SECONDS,
ccc.getSolrCloudManager().getTimeSource());
- boolean created = false;
- while (!waitUntil.hasTimedOut()) {
- waitUntil.sleep(100);
- // this also refreshes our local var clusterState
- clusterState = ccc.getSolrCloudManager().getClusterState();
- created =
- clusterState.hasCollection(targetCollection)
- && clusterState.hasCollection(chkCollection);
- if (created) break;
- }
- if (!created) {
+ try {
+ for (String col : List.of(targetCollection, chkCollection)) {
+ ccc.getZkStateReader().waitForState(col, 30, TimeUnit.SECONDS,
Objects::nonNull);
+ }
+ } catch (TimeoutException e) {
throw new SolrException(
SolrException.ErrorCode.SERVER_ERROR, "Could not fully create
temporary collection(s)");
}
+
+ clusterState = ccc.getSolrCloudManager().getClusterState();
+
if (maybeAbort(collection)) {
aborted = true;
return;
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 329cd307b3f..37641ff236b 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -54,6 +54,7 @@ import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -97,7 +98,6 @@ import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.SuppressForbidden;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.common.util.Utils;
import org.apache.solr.common.util.ValidatingJsonMap;
import org.apache.solr.core.CoreContainer;
@@ -126,7 +126,6 @@ import org.apache.solr.servlet.cache.HttpCacheHeaderUtil;
import org.apache.solr.servlet.cache.Method;
import org.apache.solr.update.processor.DistributingUpdateProcessorFactory;
import org.apache.solr.util.RTimerTree;
-import org.apache.solr.util.TimeOut;
import org.apache.solr.util.tracing.TraceUtils;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
@@ -389,18 +388,16 @@ public class HttpSolrCall {
+ " collection: "
+ Utils.toJSONString(rsp.getValues()));
}
- TimeOut timeOut = new TimeOut(3, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- for (; ; ) {
- if
(cores.getZkController().getClusterState().getCollectionOrNull(SYSTEM_COLL) !=
null) {
- break;
- } else {
- if (timeOut.hasTimedOut()) {
- throw new SolrException(
- ErrorCode.SERVER_ERROR,
- "Could not find " + SYSTEM_COLL + " collection even after 3
seconds");
- }
- timeOut.sleep(50);
- }
+
+ try {
+ cores
+ .getZkController()
+ .getZkStateReader()
+ .waitForState(SYSTEM_COLL, 3, TimeUnit.SECONDS, Objects::nonNull);
+ } catch (TimeoutException e) {
+ throw new SolrException(
+ ErrorCode.SERVER_ERROR,
+ "Could not find " + SYSTEM_COLL + " collection even after 3
seconds");
}
action = RETRY;
diff --git
a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java
b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java
index ddb72aad118..6652009774f 100644
---
a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java
+++
b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java
@@ -343,7 +343,7 @@ public class ChaosMonkeyNothingIsSafeWithPullReplicasTest
extends AbstractFullDi
List<Integer> numShardsNumReplicas = new ArrayList<>(2);
numShardsNumReplicas.add(1);
numShardsNumReplicas.add(1 + getPullReplicaCount());
- checkForCollection("testcollection", numShardsNumReplicas, null);
+ checkForCollection("testcollection", numShardsNumReplicas);
testSuccessful = true;
} finally {
diff --git
a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeySafeLeaderWithPullReplicasTest.java
b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeySafeLeaderWithPullReplicasTest.java
index 764035dc043..b097ebea968 100644
---
a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeySafeLeaderWithPullReplicasTest.java
+++
b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeySafeLeaderWithPullReplicasTest.java
@@ -255,7 +255,7 @@ public class ChaosMonkeySafeLeaderWithPullReplicasTest
extends AbstractFullDistr
List<Integer> numShardsNumReplicas = new ArrayList<>(2);
numShardsNumReplicas.add(1);
numShardsNumReplicas.add(1 + getPullReplicaCount());
- checkForCollection("testcollection", numShardsNumReplicas, null);
+ checkForCollection("testcollection", numShardsNumReplicas);
}
private void tryDelete() throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
b/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
index 686a0a2554a..16242bcc5eb 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
@@ -488,11 +488,13 @@ public class DeleteReplicaTest extends SolrCloudTestCase {
}
private void waitForNodeLeave(String lostNodeName) throws
InterruptedException {
- ZkStateReader reader = cluster.getZkStateReader();
- TimeOut timeOut = new TimeOut(20, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- while (reader.getClusterState().getLiveNodes().contains(lostNodeName)) {
- Thread.sleep(100);
- if (timeOut.hasTimedOut()) fail("Wait for " + lostNodeName + " to leave
failed!");
+
+ try {
+ cluster
+ .getZkStateReader()
+ .waitForLiveNodes(20, TimeUnit.SECONDS, (o, n) ->
!n.contains(lostNodeName));
+ } catch (TimeoutException e) {
+ fail("Wait for " + lostNodeName + " to leave failed!");
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
index 2f3f62ad763..0d4f1c2b722 100644
--- a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
@@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.solr.JSONTestUtil;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
@@ -48,13 +49,11 @@ import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkCoreNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.util.RTimer;
import org.apache.solr.util.TestInjection;
-import org.apache.solr.util.TimeOut;
import org.apache.zookeeper.KeeperException;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -291,27 +290,23 @@ public class HttpPartitionTest extends
AbstractFullDistribZkTestBase {
protected void waitForState(String collection, String replicaName,
Replica.State state, long ms)
throws KeeperException, InterruptedException {
- TimeOut timeOut = new TimeOut(ms, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
- Replica.State replicaState = Replica.State.ACTIVE;
- while (!timeOut.hasTimedOut()) {
- ZkStateReader zkr = ZkStateReader.from(cloudClient);
- zkr.forceUpdateCollection(collection); // force the state to be fresh
- ClusterState cs = zkr.getClusterState();
- Collection<Slice> slices =
cs.getCollection(collection).getActiveSlices();
- Slice slice = slices.iterator().next();
- Replica partitionedReplica = slice.getReplica(replicaName);
- replicaState = partitionedReplica.getState();
- if (replicaState == state) return;
+ ZkStateReader zkr = ZkStateReader.from(cloudClient);
+
+ try {
+ zkr.waitForState(
+ collection,
+ ms,
+ TimeUnit.MILLISECONDS,
+ c -> {
+ Collection<Slice> slices = c.getActiveSlices();
+ Slice slice = slices.iterator().next();
+ Replica partitionedReplica = slice.getReplica(replicaName);
+ Replica.State replicaState = partitionedReplica.getState();
+ return replicaState == state;
+ });
+ } catch (TimeoutException e) {
+ fail("Timeout waiting for state " + state + " of replica " +
replicaName);
}
- assertEquals(
- "Timeout waiting for state "
- + state
- + " of replica "
- + replicaName
- + ", current state "
- + replicaState,
- state,
- replicaState);
}
protected void testRf3() throws Exception {
diff --git
a/solr/core/src/test/org/apache/solr/cloud/LeaderFailureAfterFreshStartTest.java
b/solr/core/src/test/org/apache/solr/cloud/LeaderFailureAfterFreshStartTest.java
index 5b7ff3f0428..1bc87e4f4e1 100644
---
a/solr/core/src/test/org/apache/solr/cloud/LeaderFailureAfterFreshStartTest.java
+++
b/solr/core/src/test/org/apache/solr/cloud/LeaderFailureAfterFreshStartTest.java
@@ -39,8 +39,6 @@ import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.common.util.TimeSource;
-import org.apache.solr.util.TimeOut;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -154,11 +152,7 @@ public class LeaderFailureAfterFreshStartTest extends
AbstractFullDistribZkTestB
// shutdown the original leader
log.info("Now shutting down initial leader");
forceNodeFailures(singletonList(initialLeaderJetty));
- waitForNewLeader(
- cloudClient,
- "shard1",
- (Replica) initialLeaderJetty.client.info,
- new TimeOut(15, TimeUnit.SECONDS, TimeSource.NANO_TIME));
+ waitForNewLeader(cloudClient, "shard1", (Replica)
initialLeaderJetty.client.info);
waitTillNodesActive();
log.info("Updating mappings from zk");
updateMappingsFromZk(jettys, clients, true);
diff --git
a/solr/core/src/test/org/apache/solr/cloud/PeerSyncReplicationTest.java
b/solr/core/src/test/org/apache/solr/cloud/PeerSyncReplicationTest.java
index 7042c3018e2..d9e501e69b6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/PeerSyncReplicationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/PeerSyncReplicationTest.java
@@ -44,10 +44,8 @@ import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.metrics.SolrMetricManager;
-import org.apache.solr.util.TimeOut;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -154,11 +152,7 @@ public class PeerSyncReplicationTest extends
AbstractFullDistribZkTestBase {
log.info("Now shutting down initial leader");
forceNodeFailures(singletonList(initialLeaderJetty));
log.info("Updating mappings from zk");
- waitForNewLeader(
- cloudClient,
- "shard1",
- (Replica) initialLeaderJetty.client.info,
- new TimeOut(15, TimeUnit.SECONDS, TimeSource.NANO_TIME));
+ waitForNewLeader(cloudClient, "shard1", (Replica)
initialLeaderJetty.client.info);
updateMappingsFromZk(jettys, clients, true);
assertEquals(
"PeerSynced node did not become leader",
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
index f5cf82c701e..ec0564c249d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
@@ -749,20 +749,13 @@ public class TestPullReplica extends SolrCloudTestCase {
}
}
- static void waitForDeletion(String collection) throws InterruptedException,
KeeperException {
- TimeOut t = new TimeOut(10, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- while
(cluster.getSolrClient().getClusterState().hasCollection(collection)) {
- log.info("Collection not yet deleted");
- try {
- Thread.sleep(100);
- if (t.hasTimedOut()) {
- fail("Timed out waiting for collection " + collection + " to be
deleted.");
- }
- cluster.getZkStateReader().forceUpdateCollection(collection);
- } catch (SolrException e) {
- return;
- }
- }
+ static void waitForDeletion(String collection) {
+ waitForState(
+ "Waiting for collection " + collection + " to be deleted",
+ collection,
+ (n, c) -> c == null,
+ 10,
+ TimeUnit.SECONDS);
}
private DocCollection assertNumberOfReplicas(
diff --git
a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
index 9906d3041f1..12069199e99 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
@@ -118,7 +118,7 @@ public class TestPullReplicaErrorHandling extends
SolrCloudTestCase {
log.info("tearDown deleting collection");
CollectionAdminRequest.deleteCollection(collectionName).process(cluster.getSolrClient());
log.info("Collection deleted");
- waitForDeletion(collectionName);
+ TestPullReplica.waitForDeletion(collectionName);
}
collectionName = null;
super.tearDown();
@@ -345,22 +345,6 @@ public class TestPullReplicaErrorHandling extends
SolrCloudTestCase {
return proxy;
}
- private void waitForDeletion(String collection) throws InterruptedException,
KeeperException {
- TimeOut t = new TimeOut(10, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- while
(cluster.getSolrClient().getClusterState().hasCollection(collection)) {
- log.info("Collection not yet deleted");
- try {
- Thread.sleep(100);
- if (t.hasTimedOut()) {
- fail("Timed out waiting for collection " + collection + " to be
deleted.");
- }
- cluster.getZkStateReader().forceUpdateCollection(collection);
- } catch (SolrException e) {
- return;
- }
- }
- }
-
private CollectionStatePredicate activeReplicaCount(
int numWriter, int numActive, int numPassive) {
return (liveNodes, collectionState) -> {
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
b/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
index 0b59d5d74ab..20343487523 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
@@ -111,8 +111,7 @@ public class TestRebalanceLeaders extends SolrCloudTestCase
{
// shardUnique=true for the special property preferredLeader. That was
removed at one point, so
// we're explicitly testing that as well.
@Test
- public void testSetArbitraryPropertySliceUnique()
- throws IOException, SolrServerException, InterruptedException {
+ public void testSetArbitraryPropertySliceUnique() throws IOException,
SolrServerException {
// Check both special (preferredLeader) and something arbitrary.
doTestSetArbitraryPropertySliceUnique("foo" + random().nextInt(1_000_000));
removeAllProperties();
@@ -124,8 +123,7 @@ public class TestRebalanceLeaders extends SolrCloudTestCase
{
// individual properties on individual nodes. This one relies on Solr to
pick which replicas to
// set the property on
@Test
- public void testBalancePropertySliceUnique()
- throws InterruptedException, IOException, SolrServerException {
+ public void testBalancePropertySliceUnique() throws IOException,
SolrServerException {
// Check both cases of "special" property preferred(Ll)eader
doTestBalancePropertySliceUnique("foo" + random().nextInt(1_000_000));
removeAllProperties();
@@ -160,7 +158,7 @@ public class TestRebalanceLeaders extends SolrCloudTestCase
{
// on an individual
// replica.
private void doTestSetArbitraryPropertySliceUnique(String propIn)
- throws InterruptedException, IOException, SolrServerException {
+ throws IOException, SolrServerException {
final String prop = (random().nextBoolean()) ? propIn :
propIn.toUpperCase(Locale.ROOT);
// First set the property in some replica in some slice
forceUpdateCollectionStatus();
@@ -176,43 +174,29 @@ public class TestRebalanceLeaders extends
SolrCloudTestCase {
Replica rep = reps[random().nextInt(reps.length)];
// Set the property on a particular replica
setProp(slice, rep, prop);
- TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
-
- long count = 0;
- boolean rightRep = false;
- Slice modSlice;
- DocCollection modColl = null; // keeps IDE happy
// ensure that no other replica in that slice has the property when we
return.
- while (timeout.hasTimedOut() == false) {
- forceUpdateCollectionStatus();
- modColl =
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
- modSlice = modColl.getSlice(slice.getName());
- rightRep =
- modSlice
- .getReplica(rep.getName())
- .getBool("property." + prop.toLowerCase(Locale.ROOT), false);
- count =
- modSlice.getReplicas().stream()
- .filter(
- thisRep -> thisRep.getBool("property." +
prop.toLowerCase(Locale.ROOT), false))
- .count();
-
- if (count == 1 && rightRep) {
- break;
- }
-
- TimeUnit.MILLISECONDS.sleep(50);
- }
- if (count != 1 || rightRep == false) {
- fail(
- "The property "
- + prop
- + " was not uniquely distributed in slice "
- + slice.getName()
- + " "
- + modColl.toString());
- }
+ waitForState(
+ "Check property is uniquely distributed in slice: " + prop,
+ COLLECTION_NAME,
+ (n, c) -> {
+ forceUpdateCollectionStatus();
+ Slice modSlice = c.getSlice(slice.getName());
+ boolean rightRep =
+ modSlice
+ .getReplica(rep.getName())
+ .getBool("property." + prop.toLowerCase(Locale.ROOT),
false);
+ long count =
+ modSlice.getReplicas().stream()
+ .filter(
+ thisRep ->
+ thisRep.getBool("property." +
prop.toLowerCase(Locale.ROOT), false))
+ .count();
+
+ return count == 1 && rightRep;
+ },
+ timeoutMs,
+ TimeUnit.MILLISECONDS);
}
}
@@ -332,7 +316,7 @@ public class TestRebalanceLeaders extends SolrCloudTestCase
{
// re-assigned with the
// BALANCESHARDUNIQUE command.
private void doTestBalancePropertySliceUnique(String propIn)
- throws InterruptedException, IOException, SolrServerException {
+ throws IOException, SolrServerException {
final String prop = (random().nextBoolean()) ? propIn :
propIn.toUpperCase(Locale.ROOT);
// Concentrate the properties on as few replicas a possible
@@ -350,63 +334,55 @@ public class TestRebalanceLeaders extends
SolrCloudTestCase {
private void verifyPropCorrectlyDistributed(String prop) {
- TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
-
String propLC = prop.toLowerCase(Locale.ROOT);
- DocCollection docCollection = null;
- while (timeout.hasTimedOut() == false) {
- forceUpdateCollectionStatus();
- docCollection =
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
- int maxPropCount = Integer.MAX_VALUE;
- int minPropCount = Integer.MIN_VALUE;
- for (Slice slice : docCollection.getSlices()) {
- int repCount = 0;
- for (Replica rep : slice.getReplicas()) {
- if (rep.getBool("property." + propLC, false)) {
- repCount++;
+ waitForState(
+ "Check property is distributed evenly: " + prop,
+ COLLECTION_NAME,
+ (liveNodes, docCollection) -> {
+ int maxPropCount = 0;
+ int minPropCount = Integer.MAX_VALUE;
+ for (Slice slice : docCollection.getSlices()) {
+ int repCount = 0;
+ for (Replica rep : slice.getReplicas()) {
+ if (rep.getBool("property." + propLC, false)) {
+ repCount++;
+ }
+ }
+ maxPropCount = Math.max(maxPropCount, repCount);
+ minPropCount = Math.min(minPropCount, repCount);
}
- }
- maxPropCount = Math.max(maxPropCount, repCount);
- minPropCount = Math.min(minPropCount, repCount);
- }
- if (Math.abs(maxPropCount - minPropCount) < 2) return;
- }
- log.error("Property {} is not distributed evenly. {}", prop,
docCollection);
- fail("Property is not distributed evenly " + prop);
+ return Math.abs(maxPropCount - minPropCount) < 2;
+ },
+ timeoutMs,
+ TimeUnit.MILLISECONDS);
}
// Used when we concentrate the leader on a few nodes.
private void verifyPropDistributedAsExpected(
- Map<String, String> expectedShardReplicaMap, String prop) throws
InterruptedException {
+ Map<String, String> expectedShardReplicaMap, String prop) {
// Make sure that the shard unique are where you expect.
- TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
-
String propLC = prop.toLowerCase(Locale.ROOT);
- boolean failure = false;
- DocCollection docCollection = null;
- while (timeout.hasTimedOut() == false) {
- forceUpdateCollectionStatus();
- docCollection =
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
- failure = false;
- for (Map.Entry<String, String> ent : expectedShardReplicaMap.entrySet())
{
- Replica rep =
docCollection.getSlice(ent.getKey()).getReplica(ent.getValue());
- if (rep.getBool("property." + propLC, false) == false) {
- failure = true;
- }
- }
- if (failure == false) {
- return;
- }
- TimeUnit.MILLISECONDS.sleep(100);
- }
+ String message =
+ String.format(
+ Locale.ROOT,
+ "Checking properties are on the expected replicas. Props:%s
Expected:%s",
+ prop,
+ expectedShardReplicaMap.toString());
- fail(
- prop
- + " properties are not on the expected replicas: "
- + docCollection.toString()
- + System.lineSeparator()
- + "Expected "
- + expectedShardReplicaMap.toString());
+ waitForState(
+ message,
+ COLLECTION_NAME,
+ (liveNodes, docCollection) -> {
+ for (Map.Entry<String, String> ent :
expectedShardReplicaMap.entrySet()) {
+ Replica rep =
docCollection.getSlice(ent.getKey()).getReplica(ent.getValue());
+ if (rep.getBool("property." + propLC, false) == false) {
+ return false;
+ }
+ }
+ return true;
+ },
+ timeoutMs,
+ TimeUnit.MILLISECONDS);
}
// Just check that the property is distributed as expectecd. This does _not_
rebalance the leaders
@@ -558,14 +534,6 @@ public class TestRebalanceLeaders extends
SolrCloudTestCase {
// then start them again to concentrate the leaders. It's not necessary
that all shards have a
// leader.
- ExecutorService executorService =
ExecutorUtil.newMDCAwareCachedThreadPool("Start Jetty");
-
- for (JettySolrRunner jetty : jettys) {
- cluster.stopJettySolrRunner(jetty);
- }
-
- ExecutorUtil.shutdownAndAwaitTermination(executorService);
-
for (JettySolrRunner jetty : jettys) {
cluster.stopJettySolrRunner(jetty);
}
@@ -575,7 +543,7 @@ public class TestRebalanceLeaders extends SolrCloudTestCase
{
}
checkReplicasInactive(jettys);
- executorService = ExecutorUtil.newMDCAwareCachedThreadPool("Start Jetty");
+ ExecutorService executorService =
ExecutorUtil.newMDCAwareCachedThreadPool("Start Jetty");
for (int idx = 0; idx < jettys.size(); ++idx) {
int finalIdx = idx;
@@ -604,74 +572,61 @@ public class TestRebalanceLeaders extends
SolrCloudTestCase {
// Since we have to restart jettys, we don't want to try re-balancing etc.
until we're sure all
// jettys that should be up are and all replicas are active.
- private void checkReplicasInactive(List<JettySolrRunner> downJettys) throws
InterruptedException {
- TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
- DocCollection docCollection = null;
- Set<String> liveNodes = null;
+ private void checkReplicasInactive(List<JettySolrRunner> downJettys) {
Set<String> downJettyNodes = new TreeSet<>();
for (JettySolrRunner jetty : downJettys) {
downJettyNodes.add(
jetty.getBaseUrl().getHost() + ":" + jetty.getBaseUrl().getPort() +
"_solr");
}
- while (timeout.hasTimedOut() == false) {
- forceUpdateCollectionStatus();
- docCollection =
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
- liveNodes = cluster.getSolrClient().getClusterState().getLiveNodes();
- boolean expectedInactive = true;
-
- for (Slice slice : docCollection.getSlices()) {
- for (Replica rep : slice.getReplicas()) {
- if (downJettyNodes.contains(rep.getNodeName()) == false) {
- continue; // We are on a live node
- }
- // A replica on an allegedly down node is reported as active.
- if (rep.isActive(liveNodes)) {
- expectedInactive = false;
+
+ waitForState(
+ "Waiting for all replicas to become inactive",
+ COLLECTION_NAME,
+ (liveNodes, docCollection) -> {
+ boolean expectedInactive = true;
+
+ for (Slice slice : docCollection.getSlices()) {
+ for (Replica rep : slice.getReplicas()) {
+ if (downJettyNodes.contains(rep.getNodeName()) == false) {
+ continue; // We are on a live node
+ }
+ // A replica on an allegedly down node is reported as active.
+ if (rep.isActive(liveNodes)) {
+ expectedInactive = false;
+ }
+ }
}
- }
- }
- if (expectedInactive) {
- return;
- }
- TimeUnit.MILLISECONDS.sleep(100);
- }
- fail(
- "timed out waiting for all replicas to become inactive: livenodes: "
- + liveNodes
- + " Collection state: "
- + docCollection.toString());
+ return expectedInactive;
+ },
+ timeoutMs,
+ TimeUnit.MILLISECONDS);
}
// We need to wait around until all replicas are active before expecting
rebalancing or
// distributing shard-unique properties to work.
- private void checkAllReplicasActive() throws InterruptedException {
- TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
- while (timeout.hasTimedOut() == false) {
- forceUpdateCollectionStatus();
- DocCollection docCollection =
-
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
- Set<String> liveNodes =
cluster.getSolrClient().getClusterState().getLiveNodes();
- boolean allActive = true;
- for (Slice slice : docCollection.getSlices()) {
- for (Replica rep : slice.getReplicas()) {
- if (rep.isActive(liveNodes) == false) {
- allActive = false;
+ private void checkAllReplicasActive() {
+ waitForState(
+ "Waiting for all replicas to become active",
+ COLLECTION_NAME,
+ (liveNodes, docCollection) -> {
+ boolean allActive = true;
+ for (Slice slice : docCollection.getSlices()) {
+ for (Replica rep : slice.getReplicas()) {
+ if (rep.isActive(liveNodes) == false) {
+ allActive = false;
+ }
+ }
}
- }
- }
- if (allActive) {
- return;
- }
- TimeUnit.MILLISECONDS.sleep(100);
- }
- fail("timed out waiting for all replicas to become active");
+ return allActive;
+ },
+ timeoutMs,
+ TimeUnit.MILLISECONDS);
}
// use a simple heuristic to put as many replicas with the property on as
few nodes as possible.
// The point is that then we can execute BALANCESHARDUNIQUE and be sure it
worked correctly
- private void concentrateProp(String prop)
- throws InterruptedException, IOException, SolrServerException {
+ private void concentrateProp(String prop) throws IOException,
SolrServerException {
// find all the live nodes for each slice, assign the leader to the first
replica that is in the
// lowest position on live_nodes
List<String> liveNodes =
@@ -704,43 +659,26 @@ public class TestRebalanceLeaders extends
SolrCloudTestCase {
}
// make sure that the property in question is unique per shard.
- private Map<String, String> verifyPropUniquePerShard(String prop) throws
InterruptedException {
- Map<String, String> uniquePropMaps = new TreeMap<>();
-
- TimeOut timeout = new TimeOut(timeoutMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
- while (timeout.hasTimedOut() == false) {
- uniquePropMaps.clear();
- if (checkUniquePropPerShard(uniquePropMaps, prop)) {
- return uniquePropMaps;
- }
- TimeUnit.MILLISECONDS.sleep(10);
- }
- fail(
- "There should be exactly one replica with value "
- + prop
- + " set to true per shard: "
- +
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME).toString());
- return null; // keeps IDE happy.
- }
-
- // return true if every shard has exactly one replica with the unique
property set to "true"
- private boolean checkUniquePropPerShard(Map<String, String> uniques, String
prop) {
- forceUpdateCollectionStatus();
- DocCollection docCollection =
-
cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
+ private void verifyPropUniquePerShard(String prop) {
- for (Slice slice : docCollection.getSlices()) {
- int propCount = 0;
- for (Replica rep : slice.getReplicas()) {
- if (rep.getBool("property." + prop.toLowerCase(Locale.ROOT), false)) {
- propCount++;
- uniques.put(slice.getName(), rep.getName());
- }
- }
- if (1 != propCount) {
- return false;
- }
- }
- return true;
+ waitForState(
+ "Waiting to have exactly one replica with " + prop + "set per shard",
+ COLLECTION_NAME,
+ (liveNodes, docCollection) -> {
+ for (Slice slice : docCollection.getSlices()) {
+ int propCount = 0;
+ for (Replica rep : slice.getReplicas()) {
+ if (rep.getBool("property." + prop.toLowerCase(Locale.ROOT),
false)) {
+ propCount++;
+ }
+ }
+ if (1 != propCount) {
+ return false;
+ }
+ }
+ return true;
+ },
+ timeoutMs,
+ TimeUnit.MILLISECONDS);
}
}
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
index 563ed686298..d559de6d333 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
@@ -815,17 +815,17 @@ public class TestTlogReplica extends SolrCloudTestCase {
cloudClient.request(request);
// Wait until a preferredleader flag is set to the new leader candidate
- TimeOut timeout = new TimeOut(10, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- while (!timeout.hasTimedOut()) {
- Map<String, Slice> slices =
-
cloudClient.getClusterState().getCollection(collectionName).getSlicesMap();
- Replica me = slices.get(slice.getName()).getReplica(newLeader.getName());
- if (me.getBool("property.preferredleader", false)) {
- break;
- }
- Thread.sleep(100);
- }
- assertFalse("Timeout waiting for setting preferredleader flag",
timeout.hasTimedOut());
+ String newLeaderName = newLeader.getName();
+ waitForState(
+ "Waiting for setting preferredleader flag",
+ collectionName,
+ (n, c) -> {
+ Map<String, Slice> slices = c.getSlicesMap();
+ Replica me = slices.get(slice.getName()).getReplica(newLeaderName);
+ return me.getBool("property.preferredleader", false);
+ },
+ 10,
+ TimeUnit.SECONDS);
// Rebalance leaders
params = new ModifiableSolrParams();
@@ -837,18 +837,17 @@ public class TestTlogReplica extends SolrCloudTestCase {
cloudClient.request(request);
// Wait until a new leader is elected
- timeout = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- while (!timeout.hasTimedOut()) {
- docCollection = getCollectionState(collectionName);
- Replica leader = docCollection.getSlice(slice.getName()).getLeader();
- if (leader != null
- && leader.getName().equals(newLeader.getName())
- && leader.isActive(cloudClient.getClusterState().getLiveNodes())) {
- break;
- }
- Thread.sleep(100);
- }
- assertFalse("Timeout waiting for a new leader to be elected",
timeout.hasTimedOut());
+ waitForState(
+ "Waiting for a new leader to be elected",
+ collectionName,
+ (n, c) -> {
+ Replica leader = c.getSlice(slice.getName()).getLeader();
+ return leader != null
+ && leader.getName().equals(newLeaderName)
+ && leader.isActive(cloudClient.getClusterState().getLiveNodes());
+ },
+ 30,
+ TimeUnit.SECONDS);
new UpdateRequest()
.add(sdoc("id", "1"))
@@ -1027,19 +1026,13 @@ public class TestTlogReplica extends SolrCloudTestCase {
}
}
- private void waitForDeletion(String collection) throws InterruptedException,
KeeperException {
- TimeOut t = new TimeOut(10, TimeUnit.SECONDS, TimeSource.NANO_TIME);
- while
(cluster.getSolrClient().getClusterState().hasCollection(collection)) {
- try {
- Thread.sleep(100);
- if (t.hasTimedOut()) {
- fail("Timed out waiting for collection " + collection + " to be
deleted.");
- }
- cluster.getZkStateReader().forceUpdateCollection(collection);
- } catch (SolrException e) {
- return;
- }
- }
+ private void waitForDeletion(String collection) {
+ waitForState(
+ "Waiting for collection " + collection + " to be deleted",
+ collection,
+ (n, c) -> c == null,
+ 10,
+ TimeUnit.SECONDS);
}
private DocCollection assertNumberOfReplicas(
diff --git
a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
index 59bad33ba96..ccd528851b7 100644
---
a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
+++
b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
@@ -961,7 +961,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
}
List<Integer> list = collectionInfos.get(collectionName);
- checkForCollection(collectionName, list, null);
+ checkForCollection(collectionName, list);
waitForRecoveriesToFinish(false);
@@ -1032,7 +1032,7 @@ public class ShardSplitTest extends
BasicDistributedZkTest {
}
List<Integer> list = collectionInfos.get(collectionName);
- checkForCollection(collectionName, list, null);
+ checkForCollection(collectionName, list);
waitForRecoveriesToFinish(false);
diff --git
a/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/SharedFileSystemAutoReplicaFailoverTest.java
b/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/SharedFileSystemAutoReplicaFailoverTest.java
index 329cc7fee11..34e3b2a1492 100644
---
a/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/SharedFileSystemAutoReplicaFailoverTest.java
+++
b/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/SharedFileSystemAutoReplicaFailoverTest.java
@@ -31,6 +31,7 @@ import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.lucene.tests.util.LuceneTestCase;
@@ -57,13 +58,11 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.SolrNamedThreadFactory;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.hdfs.util.BadHdfsThreadsFilter;
import org.apache.solr.util.LogLevel;
import org.apache.solr.util.TestInjection;
-import org.apache.solr.util.TimeOut;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -425,37 +424,43 @@ public class SharedFileSystemAutoReplicaFailoverTest
extends AbstractFullDistrib
private void assertSliceAndReplicaCount(
String collection, int numSlices, int numReplicas, int timeOutInMs)
- throws InterruptedException, IOException {
- TimeOut timeOut = new TimeOut(timeOutInMs, TimeUnit.MILLISECONDS,
TimeSource.NANO_TIME);
- while (!timeOut.hasTimedOut()) {
- ClusterState clusterState = cloudClient.getClusterState();
- Collection<Slice> slices =
clusterState.getCollection(collection).getActiveSlices();
- if (slices.size() == numSlices) {
- boolean isMatch = true;
- for (Slice slice : slices) {
- int count = 0;
- for (Replica replica : slice.getReplicas()) {
- if (replica.getState() == Replica.State.ACTIVE
- && clusterState.liveNodesContain(replica.getNodeName())) {
- count++;
- }
- }
- if (count < numReplicas) {
- isMatch = false;
- }
- }
- if (isMatch) return;
- }
- Thread.sleep(200);
+ throws InterruptedException {
+
+ try {
+ ZkStateReader.from(cloudClient)
+ .waitForState(
+ collection,
+ timeOutInMs,
+ TimeUnit.MILLISECONDS,
+ (liveNodes, c) -> {
+ Collection<Slice> slices = c.getActiveSlices();
+ if (slices.size() == numSlices) {
+ for (Slice slice : slices) {
+ int count = 0;
+ for (Replica replica : slice.getReplicas()) {
+ if (replica.getState() == Replica.State.ACTIVE
+ && liveNodes.contains(replica.getNodeName())) {
+ count++;
+ }
+ }
+ if (count < numReplicas) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ });
+ } catch (TimeoutException e) {
+ fail(
+ "Expected numSlices="
+ + numSlices
+ + " numReplicas="
+ + numReplicas
+ + " but found "
+ + cloudClient.getClusterState().getCollection(collection)
+ + " with /live_nodes: "
+ + cloudClient.getClusterState().getLiveNodes());
}
- fail(
- "Expected numSlices="
- + numSlices
- + " numReplicas="
- + numReplicas
- + " but found "
- + cloudClient.getClusterState().getCollection(collection)
- + " with /live_nodes: "
- + cloudClient.getClusterState().getLiveNodes());
}
}
diff --git
a/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
b/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
index 7bb98b8d97b..326daaddc03 100644
--- a/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
+++ b/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
@@ -48,9 +48,7 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.CollectionParams.CollectionAction;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.hdfs.util.BadHdfsThreadsFilter;
-import org.apache.solr.util.TimeOut;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -232,14 +230,8 @@ public class StressHdfsTest extends
AbstractBasicDistributedZkTestBase {
request.setPath("/admin/collections");
solrClient.request(request);
- final TimeOut timeout = new TimeOut(10, TimeUnit.SECONDS,
TimeSource.NANO_TIME);
- while
(cloudClient.getClusterState().hasCollection(DELETE_DATA_DIR_COLLECTION)) {
- if (timeout.hasTimedOut()) {
- throw new AssertionError("Timeout waiting to see removed collection
leave clusterstate");
- }
-
- Thread.sleep(200);
- }
+ waitForCollectionToDisappear(
+ DELETE_DATA_DIR_COLLECTION, ZkStateReader.from(cloudClient), true, 10);
// check that all dirs are gone
for (String dataDir : dataDirs) {
diff --git
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeyNothingIsSafeTestBase.java
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeyNothingIsSafeTestBase.java
index fb138876b30..8c8a115636e 100644
---
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeyNothingIsSafeTestBase.java
+++
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeyNothingIsSafeTestBase.java
@@ -303,7 +303,7 @@ public abstract class
AbstractChaosMonkeyNothingIsSafeTestBase
List<Integer> numShardsNumReplicas = new ArrayList<>(2);
numShardsNumReplicas.add(1);
numShardsNumReplicas.add(1);
- checkForCollection("testcollection", numShardsNumReplicas, null);
+ checkForCollection("testcollection", numShardsNumReplicas);
testSuccessful = true;
} finally {
diff --git
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeySafeLeaderTestBase.java
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeySafeLeaderTestBase.java
index ab765d32699..ef371efcad4 100644
---
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeySafeLeaderTestBase.java
+++
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractChaosMonkeySafeLeaderTestBase.java
@@ -203,7 +203,7 @@ public abstract class AbstractChaosMonkeySafeLeaderTestBase
extends AbstractFull
List<Integer> numShardsNumReplicas = new ArrayList<>(2);
numShardsNumReplicas.add(1);
numShardsNumReplicas.add(1);
- checkForCollection("testcollection", numShardsNumReplicas, null);
+ checkForCollection("testcollection", numShardsNumReplicas);
}
private void tryDelete() throws Exception {
diff --git
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractDistribZkTestBase.java
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractDistribZkTestBase.java
index 37c90d98db9..f256a5fb937 100644
---
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractDistribZkTestBase.java
+++
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractDistribZkTestBase.java
@@ -16,7 +16,6 @@
*/
package org.apache.solr.cloud;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.File;
@@ -41,7 +40,6 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.core.Diagnostics;
import org.apache.solr.core.MockDirectoryFactory;
import org.apache.solr.embedded.JettySolrRunner;
-import org.apache.solr.util.TimeOut;
import org.apache.zookeeper.KeeperException;
import org.junit.BeforeClass;
import org.slf4j.Logger;
@@ -242,65 +240,42 @@ public abstract class AbstractDistribZkTestBase extends
BaseDistributedSearchTes
log.info("Collection has disappeared - collection:{}", collection);
}
- static void waitForNewLeader(
- CloudSolrClient cloudClient, String shardName, Replica oldLeader,
TimeOut timeOut)
+ static void waitForNewLeader(CloudSolrClient cloudClient, String shardName,
Replica oldLeader)
throws Exception {
- log.info("Will wait for a node to become leader for {} secs",
timeOut.timeLeft(SECONDS));
+ log.info("Will wait for a node to become leader for 15 secs");
ZkStateReader zkStateReader = ZkStateReader.from(cloudClient);
- zkStateReader.forceUpdateCollection(DEFAULT_COLLECTION);
-
- for (; ; ) {
- ClusterState clusterState = zkStateReader.getClusterState();
- DocCollection coll = clusterState.getCollection("collection1");
- Slice slice = coll.getSlice(shardName);
- if (slice.getLeader() != null
- && !slice.getLeader().equals(oldLeader)
- && slice.getLeader().getState() == Replica.State.ACTIVE) {
- if (log.isInfoEnabled()) {
- log.info(
- "Old leader {}, new leader {}. New leader got elected in {} ms",
- oldLeader,
- slice.getLeader(),
- timeOut.timeElapsed(MILLISECONDS));
- }
- break;
- }
-
- if (timeOut.hasTimedOut()) {
- Diagnostics.logThreadDumps("Could not find new leader in specified
timeout");
- zkStateReader.getZkClient().printLayoutToStream(System.out);
- fail(
- "Could not find new leader even after waiting for "
- + timeOut.timeElapsed(MILLISECONDS)
- + "ms");
- }
- Thread.sleep(100);
- }
+ long startNs = System.nanoTime();
+ try {
+ zkStateReader.waitForState(
+ "collection1",
+ 15,
+ TimeUnit.SECONDS,
+ (docCollection) -> {
+ if (docCollection == null) return false;
- zkStateReader.waitForState(
- "collection1",
- timeOut.timeLeft(SECONDS),
- TimeUnit.SECONDS,
- (docCollection) -> {
- if (docCollection == null) return false;
-
- Slice slice = docCollection.getSlice(shardName);
- if (slice != null
- && slice.getLeader() != null
- && !slice.getLeader().equals(oldLeader)
- && slice.getLeader().getState() == Replica.State.ACTIVE) {
- if (log.isInfoEnabled()) {
- log.info(
- "Old leader {}, new leader {}. New leader got elected in {}
ms",
- oldLeader,
- slice.getLeader(),
- timeOut.timeElapsed(MILLISECONDS));
+ Slice slice = docCollection.getSlice(shardName);
+ if (slice != null
+ && slice.getLeader() != null
+ && !slice.getLeader().equals(oldLeader)
+ && slice.getLeader().getState() == Replica.State.ACTIVE) {
+ if (log.isInfoEnabled()) {
+ log.info(
+ "Old leader {}, new leader {}. New leader got elected in
{} ms",
+ oldLeader,
+ slice.getLeader(),
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() -
startNs));
+ }
+ return true;
}
- return true;
- }
- return false;
- });
+ return false;
+ });
+ } catch (TimeoutException e) {
+ // If we failed to get a new leader, print some diagnotics before the
test fails
+ Diagnostics.logThreadDumps("Could not find new leader in specified
timeout");
+ zkStateReader.getZkClient().printLayoutToStream(System.out);
+ fail("Could not find new leader even after waiting for 15s");
+ }
}
public static void verifyReplicaStatus(
diff --git
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
index cd451253893..a10cbbd1a90 100644
---
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
+++
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
@@ -44,6 +44,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
@@ -2220,83 +2221,60 @@ public abstract class AbstractFullDistribZkTestBase
extends AbstractDistribZkTes
return sdoc(fields);
}
- private String checkCollectionExpectations(
- String collectionName,
- List<Integer> numShardsNumReplicaList,
- List<String> nodesAllowedToRunShards)
- throws IOException {
- getCommonCloudSolrClient();
- ClusterState clusterState = cloudClient.getClusterState();
- int expectedSlices = numShardsNumReplicaList.get(0);
- // The Math.min thing is here, because we expect replication-factor to be
reduced to if there
- // are not enough live nodes to spread all shards of a collection over
different nodes
- int expectedShardsPerSlice = numShardsNumReplicaList.get(1);
- int expectedTotalShards = expectedSlices * expectedShardsPerSlice;
-
- // Map<String,DocCollection> collections = clusterState
- // .getCollectionStates();
- if (clusterState.hasCollection(collectionName)) {
- Map<String, Slice> slices =
clusterState.getCollection(collectionName).getSlicesMap();
- // did we find expectedSlices slices/shards?
- if (slices.size() != expectedSlices) {
- return "Found new collection "
- + collectionName
- + ", but mismatch on number of slices. Expected: "
- + expectedSlices
- + ", actual: "
- + slices.size();
- }
- int totalShards = 0;
- for (String sliceName : slices.keySet()) {
- for (Replica replica : slices.get(sliceName).getReplicas()) {
- if (nodesAllowedToRunShards != null
- &&
!nodesAllowedToRunShards.contains(replica.getStr(ZkStateReader.NODE_NAME_PROP)))
{
- return "Shard "
- + replica.getName()
- + " created on node "
- + replica.getNodeName()
- + " not allowed to run shards for the created collection "
- + collectionName;
- }
- }
- totalShards += slices.get(sliceName).getReplicas().size();
- }
- if (totalShards != expectedTotalShards) {
- return "Found new collection "
- + collectionName
- + " with correct number of slices, but mismatch on number of
shards. Expected: "
- + expectedTotalShards
- + ", actual: "
- + totalShards;
- }
- return null;
- } else {
- return "Could not find new collection " + collectionName;
- }
- }
-
- protected void checkForCollection(
- String collectionName,
- List<Integer> numShardsNumReplicaList,
- List<String> nodesAllowedToRunShards)
+ protected void checkForCollection(String collectionName, List<Integer>
numShardsNumReplicaList)
throws Exception {
// check for an expectedSlices new collection - we poll the state
- final TimeOut timeout = new TimeOut(120, TimeUnit.SECONDS,
TimeSource.NANO_TIME);
- boolean success = false;
- String checkResult = "Didnt get to perform a single check";
- while (!timeout.hasTimedOut()) {
- checkResult =
- checkCollectionExpectations(
- collectionName, numShardsNumReplicaList,
nodesAllowedToRunShards);
- if (checkResult == null) {
- success = true;
- break;
- }
- Thread.sleep(500);
- }
- if (!success) {
- super.printLayout();
- fail(checkResult);
+ ZkStateReader reader = ZkStateReader.from(cloudClient);
+
+ AtomicReference<String> message = new AtomicReference<>();
+ try {
+ reader.waitForState(
+ collectionName,
+ 120,
+ TimeUnit.SECONDS,
+ c -> {
+ int expectedSlices = numShardsNumReplicaList.get(0);
+ // The Math.min thing is here, because we expect
replication-factor to be reduced to if
+ // there are not enough live nodes to spread all shards of a
collection over different
+ // nodes.
+ int expectedShardsPerSlice = numShardsNumReplicaList.get(1);
+ int expectedTotalShards = expectedSlices * expectedShardsPerSlice;
+
+ if (c != null) {
+ Collection<Slice> slices = c.getSlices();
+ // did we find expectedSlices slices/shards?
+ if (slices.size() != expectedSlices) {
+ message.set(
+ "Found new collection "
+ + collectionName
+ + ", but mismatch on number of slices. Expected: "
+ + expectedSlices
+ + ", actual: "
+ + slices.size());
+ return false;
+ }
+ int totalShards = 0;
+ for (Slice slice : slices) {
+ totalShards += slice.getReplicas().size();
+ }
+ if (totalShards != expectedTotalShards) {
+ message.set(
+ "Found new collection "
+ + collectionName
+ + " with correct number of slices, but mismatch on
number of shards. Expected: "
+ + expectedTotalShards
+ + ", actual: "
+ + totalShards);
+ return false;
+ }
+ return true;
+ } else {
+ message.set("Could not find new collection " + collectionName);
+ return false;
+ }
+ });
+ } catch (TimeoutException e) {
+ fail(message.get());
}
}
diff --git
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
index 2f77b69b27b..ee7fac68736 100644
---
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
+++
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
@@ -26,6 +26,7 @@ import java.util.Set;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
@@ -33,7 +34,6 @@ import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.CoreAdminRequest.Unload;
import org.apache.solr.common.SolrInputDocument;
-import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkCoreNodeProps;
@@ -41,12 +41,10 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.SolrNamedThreadFactory;
-import org.apache.solr.common.util.TimeSource;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrPaths;
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.util.TestInjection;
-import org.apache.solr.util.TimeOut;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,42 +95,37 @@ public abstract class AbstractUnloadDistributedZkTestBase
extends AbstractFullDi
private void checkCoreNamePresenceAndSliceCount(
String collectionName, String coreName, boolean shouldBePresent, int
expectedSliceCount)
throws Exception {
- final TimeOut timeout = new TimeOut(45, TimeUnit.SECONDS,
TimeSource.NANO_TIME);
- Boolean isPresent = null; // null meaning "don't know"
- while (null == isPresent || shouldBePresent != isPresent) {
- getCommonCloudSolrClient();
- final DocCollection docCollection =
- cloudClient.getClusterState().getCollectionOrNull(collectionName);
- final Collection<Slice> slices =
- (docCollection != null) ? docCollection.getSlices() :
Collections.emptyList();
- if (timeout.hasTimedOut()) {
- printLayout();
- fail(
- "checkCoreNamePresenceAndSliceCount failed:"
- + " collection="
- + collectionName
- + " CoreName="
- + coreName
- + " shouldBePresent="
- + shouldBePresent
- + " isPresent="
- + isPresent
- + " expectedSliceCount="
- + expectedSliceCount
- + " actualSliceCount="
- + slices.size());
- }
- if (expectedSliceCount == slices.size()) {
- isPresent = false;
- for (Slice slice : slices) {
- for (Replica replica : slice.getReplicas()) {
- if (coreName.equals(replica.get("core"))) {
- isPresent = true;
+ ZkStateReader reader = ZkStateReader.from(cloudClient);
+ try {
+ reader.waitForState(
+ collectionName,
+ 45,
+ TimeUnit.SECONDS,
+ c -> {
+ final Collection<Slice> slices = (c != null) ? c.getSlices() :
Collections.emptyList();
+ if (expectedSliceCount == slices.size()) {
+ for (Slice slice : slices) {
+ for (Replica replica : slice.getReplicas()) {
+ if (coreName.equals(replica.get("core"))) {
+ return shouldBePresent;
+ }
+ }
+ }
+ return !shouldBePresent;
+ } else {
+ return false;
}
- }
- }
- }
- Thread.sleep(1000);
+ });
+ } catch (TimeoutException e) {
+ printLayout();
+ fail(
+ "checkCoreNamePresenceAndSliceCount failed:"
+ + " collection="
+ + collectionName
+ + " CoreName="
+ + coreName
+ + " shouldBePresent="
+ + shouldBePresent);
}
}