SOLR-8323: DocCollection.isFullyActive needs to know how many replicas to expect

This commit is contained in:
Alan Woodward 2016-05-14 11:17:57 +01:00
parent 77962f4af4
commit 963c6522b6
3 changed files with 36 additions and 17 deletions

View File

@ -226,17 +226,24 @@ public class DocCollection extends ZkNodeProps implements Iterable<Slice> {
*
* @see CollectionStatePredicate
*/
public static boolean isFullyActive(Set<String> liveNodes, DocCollection collectionState) {
public static boolean isFullyActive(Set<String> liveNodes, DocCollection collectionState,
int expectedShards, int expectedReplicas) {
Objects.requireNonNull(liveNodes);
if (collectionState == null)
return false;
int activeShards = 0;
for (Slice slice : collectionState) {
int activeReplicas = 0;
for (Replica replica : slice) {
if (replica.isActive(liveNodes) == false)
return false;
activeReplicas++;
}
if (activeReplicas != expectedReplicas)
return false;
activeShards++;
}
return true;
return activeShards == expectedShards;
}
@Override

View File

@ -518,9 +518,10 @@ public class ZkStateReader implements Closeable {
if (ref == null)
continue;
// legacy collections are always in-memory
DocCollection newState = ref.get();
DocCollection oldState = ref.get();
DocCollection newState = loadedData.getCollectionStates().get(coll).get();
if (!collWatch.stateWatchers.isEmpty()
&& !Objects.equals(loadedData.getCollectionStates().get(coll).get(), newState)) {
&& !Objects.equals(oldState, newState)) {
notifyStateWatchers(liveNodes, coll, newState);
}
}

View File

@ -89,9 +89,11 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
public void testSimpleCollectionWatch() throws Exception {
CloudSolrClient client = cluster.getSolrClient();
cluster.createCollection("testcollection", CLUSTER_SIZE, 1, "config", new HashMap<>());
CollectionAdminRequest.createCollection("testcollection", "config", 4, 1)
.processAndWait(client, MAX_WAIT_TIMEOUT);
client.waitForState("testcollection", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS, DocCollection::isFullyActive);
client.waitForState("testcollection", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS,
(n, c) -> DocCollection.isFullyActive(n, c, 4, 1));
// shutdown a node and check that we get notified about the change
final AtomicInteger nodeCount = new AtomicInteger(0);
@ -121,14 +123,16 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
public void testWaitForStateChecksCurrentState() throws Exception {
CloudSolrClient client = cluster.getSolrClient();
cluster.createCollection("waitforstate", 1, 1, "config", new HashMap<>());
CollectionAdminRequest.createCollection("waitforstate", "config", 1, 1)
.processAndWait(client, MAX_WAIT_TIMEOUT);
client.waitForState("waitforstate", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS, DocCollection::isFullyActive);
client.waitForState("waitforstate", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS,
(n, c) -> DocCollection.isFullyActive(n, c, 1, 1));
// several goes, to check that we're not getting delayed state changes
for (int i = 0; i < 10; i++) {
try {
client.waitForState("waitforstate", 1, TimeUnit.SECONDS, DocCollection::isFullyActive);
client.waitForState("waitforstate", 1, TimeUnit.SECONDS, (n, c) -> DocCollection.isFullyActive(n, c, 1, 1));
}
catch (TimeoutException e) {
fail("waitForState should return immediately if the predicate is already satisfied");
@ -140,8 +144,12 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
@Test
public void testCanWaitForNonexistantCollection() throws Exception {
Future<Boolean> future = waitInBackground("delayed", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS, DocCollection::isFullyActive);
cluster.createCollection("delayed", 1, 1, "config", new HashMap<>());
Future<Boolean> future = waitInBackground("delayed", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS,
(n, c) -> DocCollection.isFullyActive(n, c, 1, 1));
CollectionAdminRequest.createCollection("delayed", "config", 1, 1)
.processAndWait(cluster.getSolrClient(), MAX_WAIT_TIMEOUT);
assertTrue("waitForState was not triggered by collection creation", future.get());
}
@ -162,8 +170,11 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
public void testWaitForStateWatcherIsRetainedOnPredicateFailure() throws Exception {
CloudSolrClient client = cluster.getSolrClient();
cluster.createCollection("falsepredicate", 4, 1, "config", new HashMap<>());
client.waitForState("falsepredicate", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS, DocCollection::isFullyActive);
CollectionAdminRequest.createCollection("falsepredicate", "config", 4, 1)
.processAndWait(client, MAX_WAIT_TIMEOUT);
client.waitForState("falsepredicate", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS,
(n, c) -> DocCollection.isFullyActive(n, c, 4, 1));
final CountDownLatch firstCall = new CountDownLatch(1);
@ -172,7 +183,7 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
Future<Boolean> future = waitInBackground("falsepredicate", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS, (liveNodes, collectionState) -> {
firstCall.countDown();
return DocCollection.isFullyActive(liveNodes, collectionState);
return DocCollection.isFullyActive(liveNodes, collectionState, 4, 1);
});
// first, stop another node; the watch should not be fired after this!
@ -195,7 +206,7 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
client.getZkStateReader().getStateWatchers("no-such-collection") == null);
expectThrows(TimeoutException.class, () -> {
client.waitForState("no-such-collection", 10, TimeUnit.MILLISECONDS, DocCollection::isFullyActive);
client.waitForState("no-such-collection", 10, TimeUnit.MILLISECONDS, (n, c) -> DocCollection.isFullyActive(n, c, 1, 1));
});
Set<CollectionStateWatcher> watchers = client.getZkStateReader().getStateWatchers("no-such-collection");
@ -219,8 +230,8 @@ public class TestCollectionStateWatchers extends SolrCloudTestCase {
final CloudSolrClient client = cluster.getSolrClient();
Future<Boolean> future
= waitInBackground("stateformat1", MAX_WAIT_TIMEOUT, TimeUnit.SECONDS, DocCollection::isFullyActive);
Future<Boolean> future = waitInBackground("stateformat1", 10, TimeUnit.SECONDS,
(n, c) -> DocCollection.isFullyActive(n, c, 1, 1));
CollectionAdminRequest.createCollection("stateformat1", "config", 1, 1).setStateFormat(1)
.processAndWait(client, MAX_WAIT_TIMEOUT);