mirror of https://github.com/apache/lucene.git
SOLR-8196: TestMiniSolrCloudCluster.testStopAllStartAll case plus necessary MiniSolrCloudCluster tweak
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1710824 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e5c4ba48df
commit
676a0e4f2f
|
@ -389,6 +389,9 @@ Other Changes
|
|||
* SOLR-4854: Add a test to assert that [elevated] DocTransfer works correctly with javabin
|
||||
response format. (Ray, shalin)
|
||||
|
||||
* SOLR-8196: TestMiniSolrCloudCluster.testStopAllStartAll case plus necessary
|
||||
MiniSolrCloudCluster tweak (Christine Poerschke)
|
||||
|
||||
================== 5.3.1 ==================
|
||||
|
||||
Bug Fixes
|
||||
|
|
|
@ -19,8 +19,12 @@ package org.apache.solr.cloud;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -90,15 +94,26 @@ public class TestMiniSolrCloudCluster extends LuceneTestCase {
|
|||
}
|
||||
|
||||
private MiniSolrCloudCluster createMiniSolrCloudCluster() throws Exception {
|
||||
return createMiniSolrCloudCluster(false);
|
||||
}
|
||||
|
||||
private MiniSolrCloudCluster createMiniSolrCloudCluster(boolean multipleBaseDirs) throws Exception {
|
||||
|
||||
File solrXml = new File(SolrTestCaseJ4.TEST_HOME(), "solr-no-core.xml");
|
||||
Builder jettyConfig = JettyConfig.builder();
|
||||
jettyConfig.waitForLoadingCoresToFinish(null);
|
||||
MiniSolrCloudCluster miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, createTempDir().toFile(), solrXml, jettyConfig.build());
|
||||
return miniCluster;
|
||||
if (multipleBaseDirs) {
|
||||
final File baseDirs[] = new File[NUM_SERVERS];
|
||||
for (int ii = 0; ii < NUM_SERVERS; ++ii) {
|
||||
baseDirs[ii] = createTempDir().toFile();
|
||||
}
|
||||
return new MiniSolrCloudCluster(baseDirs, solrXml, jettyConfig.build(), null);
|
||||
} else {
|
||||
return new MiniSolrCloudCluster(NUM_SERVERS, createTempDir().toFile(), solrXml, jettyConfig.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void createCollection(MiniSolrCloudCluster miniCluster, String collectionName, String createNodeSet, String asyncId) throws Exception {
|
||||
private void createCollection(MiniSolrCloudCluster miniCluster, String collectionName, String createNodeSet, String asyncId, boolean persistIndex) throws Exception {
|
||||
String configName = "solrCloudCollectionConfig";
|
||||
File configDir = new File(SolrTestCaseJ4.TEST_HOME() + File.separator + "collection1" + File.separator + "conf");
|
||||
miniCluster.uploadConfigDir(configDir, configName);
|
||||
|
@ -110,7 +125,7 @@ public class TestMiniSolrCloudCluster extends LuceneTestCase {
|
|||
// use non-test classes so RandomizedRunner isn't necessary
|
||||
collectionProperties.put("solr.tests.mergePolicy", "org.apache.lucene.index.TieredMergePolicy");
|
||||
collectionProperties.put("solr.tests.mergeScheduler", "org.apache.lucene.index.ConcurrentMergeScheduler");
|
||||
collectionProperties.put("solr.directoryFactory", "solr.RAMDirectoryFactory");
|
||||
collectionProperties.put("solr.directoryFactory", (persistIndex ? "solr.StandardDirectoryFactory" : "solr.RAMDirectoryFactory"));
|
||||
|
||||
miniCluster.createCollection(collectionName, NUM_SHARDS, REPLICATION_FACTOR, configName, createNodeSet, asyncId, collectionProperties);
|
||||
}
|
||||
|
@ -141,7 +156,7 @@ public class TestMiniSolrCloudCluster extends LuceneTestCase {
|
|||
|
||||
// create collection
|
||||
final String asyncId = (random().nextBoolean() ? null : "asyncId("+collectionName+".create)="+random().nextInt());
|
||||
createCollection(miniCluster, collectionName, null, asyncId);
|
||||
createCollection(miniCluster, collectionName, null, asyncId, random().nextBoolean());
|
||||
if (asyncId != null) {
|
||||
assertEquals("did not see async createCollection completion", "completed", AbstractFullDistribZkTestBase.getRequestStateAfterCompletion(asyncId, 330, cloudSolrClient));
|
||||
}
|
||||
|
@ -295,7 +310,7 @@ public class TestMiniSolrCloudCluster extends LuceneTestCase {
|
|||
|
||||
// create collection
|
||||
final String asyncId = (random().nextBoolean() ? null : "asyncId("+collectionName+".create)="+random().nextInt());
|
||||
createCollection(miniCluster, collectionName, OverseerCollectionMessageHandler.CREATE_NODE_SET_EMPTY, asyncId);
|
||||
createCollection(miniCluster, collectionName, OverseerCollectionMessageHandler.CREATE_NODE_SET_EMPTY, asyncId, random().nextBoolean());
|
||||
if (asyncId != null) {
|
||||
assertEquals("did not see async createCollection completion", "completed", AbstractFullDistribZkTestBase.getRequestStateAfterCompletion(asyncId, 330, cloudSolrClient));
|
||||
}
|
||||
|
@ -326,4 +341,122 @@ public class TestMiniSolrCloudCluster extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopAllStartAll() throws Exception {
|
||||
|
||||
final String collectionName = "testStopAllStartAllCollection";
|
||||
|
||||
final MiniSolrCloudCluster miniCluster = createMiniSolrCloudCluster(true);
|
||||
|
||||
try {
|
||||
assertNotNull(miniCluster.getZkServer());
|
||||
List<JettySolrRunner> jettys = miniCluster.getJettySolrRunners();
|
||||
assertEquals(NUM_SERVERS, jettys.size());
|
||||
for (JettySolrRunner jetty : jettys) {
|
||||
assertTrue(jetty.isRunning());
|
||||
}
|
||||
|
||||
createCollection(miniCluster, collectionName, null, null, true);
|
||||
final CloudSolrClient cloudSolrClient = miniCluster.getSolrClient();
|
||||
cloudSolrClient.setDefaultCollection(collectionName);
|
||||
final SolrQuery query = new SolrQuery("*:*");
|
||||
final SolrInputDocument doc = new SolrInputDocument();
|
||||
|
||||
try (SolrZkClient zkClient = new SolrZkClient
|
||||
(miniCluster.getZkServer().getZkAddress(), AbstractZkTestCase.TIMEOUT, 45000, null);
|
||||
ZkStateReader zkStateReader = new ZkStateReader(zkClient)) {
|
||||
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collectionName, zkStateReader, true, true, 330);
|
||||
|
||||
// modify collection
|
||||
final int numDocs = 1 + random().nextInt(10);
|
||||
for (int ii = 1; ii <= numDocs; ++ii) {
|
||||
doc.setField("id", ""+ii);
|
||||
cloudSolrClient.add(doc);
|
||||
if (ii*2 == numDocs) cloudSolrClient.commit();
|
||||
}
|
||||
cloudSolrClient.commit();
|
||||
// query collection
|
||||
{
|
||||
final QueryResponse rsp = cloudSolrClient.query(query);
|
||||
assertEquals(numDocs, rsp.getResults().getNumFound());
|
||||
}
|
||||
|
||||
// the test itself
|
||||
zkStateReader.updateClusterState();
|
||||
final ClusterState clusterState = zkStateReader.getClusterState();
|
||||
|
||||
final HashSet<Integer> leaderIndices = new HashSet<Integer>();
|
||||
final HashSet<Integer> followerIndices = new HashSet<Integer>();
|
||||
{
|
||||
final HashMap<String,Boolean> shardLeaderMap = new HashMap<String,Boolean>();
|
||||
for (final Slice slice : clusterState.getSlices(collectionName)) {
|
||||
for (final Replica replica : slice.getReplicas()) {
|
||||
shardLeaderMap.put(replica.getNodeName().replace("_solr", "/solr"), Boolean.FALSE);
|
||||
}
|
||||
shardLeaderMap.put(slice.getLeader().getNodeName().replace("_solr", "/solr"), Boolean.TRUE);
|
||||
}
|
||||
for (int ii = 0; ii < jettys.size(); ++ii) {
|
||||
final URL jettyBaseUrl = jettys.get(ii).getBaseUrl();
|
||||
final String jettyBaseUrlString = jettyBaseUrl.toString().substring((jettyBaseUrl.getProtocol() + "://").length());
|
||||
final Boolean isLeader = shardLeaderMap.get(jettyBaseUrlString);
|
||||
if (Boolean.TRUE.equals(isLeader)) {
|
||||
leaderIndices.add(new Integer(ii));
|
||||
} else if (Boolean.FALSE.equals(isLeader)) {
|
||||
followerIndices.add(new Integer(ii));
|
||||
} // else neither leader nor follower i.e. node without a replica (for our collection)
|
||||
}
|
||||
}
|
||||
final List<Integer> leaderIndicesList = new ArrayList<Integer>(leaderIndices);
|
||||
final List<Integer> followerIndicesList = new ArrayList<Integer>(followerIndices);
|
||||
|
||||
// first stop the followers (in no particular order)
|
||||
Collections.shuffle(followerIndicesList, random());
|
||||
for (Integer ii : followerIndicesList) {
|
||||
if (!leaderIndices.contains(ii)) {
|
||||
miniCluster.stopJettySolrRunner(jettys.get(ii.intValue()));
|
||||
}
|
||||
}
|
||||
|
||||
// then stop the leaders (again in no particular order)
|
||||
Collections.shuffle(leaderIndicesList, random());
|
||||
for (Integer ii : leaderIndicesList) {
|
||||
miniCluster.stopJettySolrRunner(jettys.get(ii.intValue()));
|
||||
}
|
||||
|
||||
// calculate restart order
|
||||
final List<Integer> restartIndicesList = new ArrayList<Integer>();
|
||||
Collections.shuffle(leaderIndicesList, random());
|
||||
restartIndicesList.addAll(leaderIndicesList);
|
||||
Collections.shuffle(followerIndicesList, random());
|
||||
restartIndicesList.addAll(followerIndicesList);
|
||||
if (random().nextBoolean()) Collections.shuffle(restartIndicesList, random());
|
||||
|
||||
// and then restart jettys in that order
|
||||
for (Integer ii : restartIndicesList) {
|
||||
final JettySolrRunner jetty = jettys.get(ii.intValue());
|
||||
if (!jetty.isRunning()) {
|
||||
miniCluster.startJettySolrRunner(jetty);
|
||||
assertTrue(jetty.isRunning());
|
||||
}
|
||||
}
|
||||
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collectionName, zkStateReader, true, true, 330);
|
||||
|
||||
zkStateReader.updateClusterState();
|
||||
|
||||
// re-query collection
|
||||
{
|
||||
final QueryResponse rsp = cloudSolrClient.query(query);
|
||||
assertEquals(numDocs, rsp.getResults().getNumFound());
|
||||
}
|
||||
|
||||
// delete the collection we created earlier
|
||||
miniCluster.deleteCollection(collectionName);
|
||||
AbstractDistribZkTestBase.waitForCollectionToDisappear(collectionName, zkStateReader, true, true, 330);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
miniCluster.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ public class MiniSolrCloudCluster {
|
|||
private final boolean externalZkServer;
|
||||
private final List<JettySolrRunner> jettys = new LinkedList<>();
|
||||
private final File testDir;
|
||||
private final File testDirs[];
|
||||
private final CloudSolrClient solrClient;
|
||||
private final JettyConfig jettyConfig;
|
||||
|
||||
|
@ -141,13 +142,22 @@ public class MiniSolrCloudCluster {
|
|||
* @throws Exception if there was an error starting the cluster
|
||||
*/
|
||||
public MiniSolrCloudCluster(int numServers, File baseDir, File solrXml, JettyConfig jettyConfig, ZkTestServer zkTestServer) throws Exception {
|
||||
this(numServers, baseDir, null, solrXml, jettyConfig, zkTestServer);
|
||||
}
|
||||
|
||||
public MiniSolrCloudCluster(File[] baseDirs, File solrXml, JettyConfig jettyConfig, ZkTestServer zkTestServer) throws Exception {
|
||||
this(baseDirs.length, null, baseDirs, solrXml, jettyConfig, zkTestServer);
|
||||
}
|
||||
|
||||
private MiniSolrCloudCluster(int numServers, File baseDir, File[] baseDirs, File solrXml, JettyConfig jettyConfig, ZkTestServer zkTestServer) throws Exception {
|
||||
|
||||
this.testDir = baseDir;
|
||||
this.testDirs = baseDirs;
|
||||
this.jettyConfig = jettyConfig;
|
||||
|
||||
this.externalZkServer = zkTestServer != null;
|
||||
if (!externalZkServer) {
|
||||
String zkDir = testDir.getAbsolutePath() + File.separator
|
||||
String zkDir = (testDir != null ? testDir : testDirs[0]).getAbsolutePath() + File.separator
|
||||
+ "zookeeper/server1/data";
|
||||
zkTestServer = new ZkTestServer(zkDir);
|
||||
zkTestServer.run();
|
||||
|
@ -167,10 +177,14 @@ public class MiniSolrCloudCluster {
|
|||
|
||||
List<Callable<JettySolrRunner>> startups = new ArrayList<>(numServers);
|
||||
for (int i = 0; i < numServers; ++i) {
|
||||
final Integer testDirsIdx = new Integer(i);
|
||||
startups.add(new Callable<JettySolrRunner>() {
|
||||
@Override
|
||||
public JettySolrRunner call() throws Exception {
|
||||
return startJettySolrRunner(jettyConfig);
|
||||
if (testDir != null)
|
||||
return startJettySolrRunner(jettyConfig);
|
||||
else
|
||||
return startJettySolrRunner(testDirsIdx, jettyConfig.context, jettyConfig);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -283,9 +297,12 @@ public class MiniSolrCloudCluster {
|
|||
* @return a JettySolrRunner
|
||||
*/
|
||||
public JettySolrRunner startJettySolrRunner(String hostContext, JettyConfig config) throws Exception {
|
||||
return startJettySolrRunner(null, hostContext, config);
|
||||
}
|
||||
public JettySolrRunner startJettySolrRunner(Integer testDirsIdx, String hostContext, JettyConfig config) throws Exception {
|
||||
String context = getHostContextSuitableForServletContext(hostContext);
|
||||
JettyConfig newConfig = JettyConfig.builder(config).setContext(context).build();
|
||||
JettySolrRunner jetty = new JettySolrRunner(testDir.getAbsolutePath(), newConfig);
|
||||
JettySolrRunner jetty = new JettySolrRunner((testDirsIdx != null ? testDirs[testDirsIdx.intValue()] : testDir).getAbsolutePath(), newConfig);
|
||||
jetty.start();
|
||||
jettys.add(jetty);
|
||||
return jetty;
|
||||
|
@ -312,6 +329,11 @@ public class MiniSolrCloudCluster {
|
|||
return jetty;
|
||||
}
|
||||
|
||||
protected JettySolrRunner startJettySolrRunner(JettySolrRunner jetty) throws Exception {
|
||||
jetty.start();
|
||||
return jetty;
|
||||
}
|
||||
|
||||
protected JettySolrRunner stopJettySolrRunner(JettySolrRunner jetty) throws Exception {
|
||||
jetty.stop();
|
||||
return jetty;
|
||||
|
|
Loading…
Reference in New Issue