SOLR-9566: Don't put replicas into recovery when collections are created

This commit is contained in:
Alan Woodward 2016-09-26 22:51:39 +01:00
parent 927fd51d64
commit 65f55802ee
9 changed files with 41 additions and 32 deletions

View File

@ -195,6 +195,8 @@ Optimizations
reader rather than ask for a global view. In extreme cases, this leads to a 100x speedup. reader rather than ask for a global view. In extreme cases, this leads to a 100x speedup.
(Takahiro Ishikawa, yonik) (Takahiro Ishikawa, yonik)
* SOLR-9566: Don't put replicas into recovery when first creating a Collection
(Alan Woodward)
Other Changes Other Changes
---------------------- ----------------------

View File

@ -217,6 +217,7 @@ public class CreateCollectionCmd implements Cmd {
params.set(CoreAdminParams.COLLECTION, collectionName); params.set(CoreAdminParams.COLLECTION, collectionName);
params.set(CoreAdminParams.SHARD, position.shard); params.set(CoreAdminParams.SHARD, position.shard);
params.set(ZkStateReader.NUM_SHARDS_PROP, numSlices); params.set(ZkStateReader.NUM_SHARDS_PROP, numSlices);
params.set(CoreAdminParams.NEW_COLLECTION, "true");
if (async != null) { if (async != null) {
String coreAdminAsyncId = async + Math.abs(System.nanoTime()); String coreAdminAsyncId = async + Math.abs(System.nanoTime());

View File

@ -231,7 +231,7 @@ public class ZkController {
public Object call() throws Exception { public Object call() throws Exception {
log.info("Registering core {} afterExpiration? {}", descriptor.getName(), afterExpiration); log.info("Registering core {} afterExpiration? {}", descriptor.getName(), afterExpiration);
register(descriptor.getName(), descriptor, recoverReloadedCores, afterExpiration); register(descriptor.getName(), descriptor, recoverReloadedCores, afterExpiration, false);
return descriptor; return descriptor;
} }
} }
@ -354,7 +354,7 @@ public class ZkController {
if (executorService != null) { if (executorService != null) {
executorService.submit(new RegisterCoreAsync(descriptor, true, true)); executorService.submit(new RegisterCoreAsync(descriptor, true, true));
} else { } else {
register(descriptor.getName(), descriptor, true, true); register(descriptor.getName(), descriptor, true, true, false);
} }
} catch (Exception e) { } catch (Exception e) {
SolrException.log(log, "Error registering SolrCore", e); SolrException.log(log, "Error registering SolrCore", e);
@ -840,8 +840,8 @@ public class ZkController {
* *
* @return the shardId for the SolrCore * @return the shardId for the SolrCore
*/ */
public String register(String coreName, final CoreDescriptor desc) throws Exception { public String register(String coreName, final CoreDescriptor desc, boolean skipRecovery) throws Exception {
return register(coreName, desc, false, false); return register(coreName, desc, false, false, skipRecovery);
} }
@ -850,7 +850,8 @@ public class ZkController {
* *
* @return the shardId for the SolrCore * @return the shardId for the SolrCore
*/ */
public String register(String coreName, final CoreDescriptor desc, boolean recoverReloadedCores, boolean afterExpiration) throws Exception { public String register(String coreName, final CoreDescriptor desc, boolean recoverReloadedCores,
boolean afterExpiration, boolean skipRecovery) throws Exception {
try (SolrCore core = cc.getCore(desc.getName())) { try (SolrCore core = cc.getCore(desc.getName())) {
MDCLoggingContext.setCore(core); MDCLoggingContext.setCore(core);
} }
@ -929,8 +930,8 @@ public class ZkController {
} }
} }
} }
boolean didRecovery = checkRecovery(coreName, desc, recoverReloadedCores, isLeader, cloudDesc, collection, boolean didRecovery
coreZkNodeName, shardId, leaderProps, core, cc, afterExpiration); = checkRecovery(recoverReloadedCores, isLeader, skipRecovery, collection, coreZkNodeName, core, cc, afterExpiration);
if (!didRecovery) { if (!didRecovery) {
publish(desc, Replica.State.ACTIVE); publish(desc, Replica.State.ACTIVE);
} }
@ -1080,10 +1081,8 @@ public class ZkController {
/** /**
* Returns whether or not a recovery was started * Returns whether or not a recovery was started
*/ */
private boolean checkRecovery(String coreName, final CoreDescriptor desc, private boolean checkRecovery(boolean recoverReloadedCores, final boolean isLeader, boolean skipRecovery,
boolean recoverReloadedCores, final boolean isLeader, final String collection, String shardId,
final CloudDescriptor cloudDesc, final String collection,
final String shardZkNodeName, String shardId, ZkNodeProps leaderProps,
SolrCore core, CoreContainer cc, boolean afterExpiration) { SolrCore core, CoreContainer cc, boolean afterExpiration) {
if (SKIP_AUTO_RECOVERY) { if (SKIP_AUTO_RECOVERY) {
log.warn("Skipping recovery according to sys prop solrcloud.skip.autorecovery"); log.warn("Skipping recovery according to sys prop solrcloud.skip.autorecovery");
@ -1092,7 +1091,7 @@ public class ZkController {
boolean doRecovery = true; boolean doRecovery = true;
if (!isLeader) { if (!isLeader) {
if (!afterExpiration && core.isReloaded() && !recoverReloadedCores) { if (skipRecovery || (!afterExpiration && core.isReloaded() && !recoverReloadedCores)) {
doRecovery = false; doRecovery = false;
} }

View File

@ -517,14 +517,14 @@ public class CoreContainer {
zkSys.getZkController().throwErrorIfReplicaReplaced(cd); zkSys.getZkController().throwErrorIfReplicaReplaced(cd);
} }
core = create(cd, false); core = create(cd, false, false);
} finally { } finally {
if (asyncSolrCoreLoad) { if (asyncSolrCoreLoad) {
solrCores.markCoreAsNotLoading(cd); solrCores.markCoreAsNotLoading(cd);
} }
} }
try { try {
zkSys.registerInZk(core, true); zkSys.registerInZk(core, true, false);
} catch (RuntimeException e) { } catch (RuntimeException e) {
SolrException.log(log, "Error registering SolrCore", e); SolrException.log(log, "Error registering SolrCore", e);
} }
@ -706,7 +706,7 @@ public class CoreContainer {
return coresLocator; return coresLocator;
} }
protected SolrCore registerCore(String name, SolrCore core, boolean registerInZk) { protected SolrCore registerCore(String name, SolrCore core, boolean registerInZk, boolean skipRecovery) {
if( core == null ) { if( core == null ) {
throw new RuntimeException( "Can not register a null core." ); throw new RuntimeException( "Can not register a null core." );
} }
@ -744,7 +744,7 @@ public class CoreContainer {
if( old == null || old == core) { if( old == null || old == core) {
log.debug( "registering core: "+name ); log.debug( "registering core: "+name );
if (registerInZk) { if (registerInZk) {
zkSys.registerInZk(core, false); zkSys.registerInZk(core, false, skipRecovery);
} }
return null; return null;
} }
@ -752,7 +752,7 @@ public class CoreContainer {
log.debug( "replacing core: "+name ); log.debug( "replacing core: "+name );
old.close(); old.close();
if (registerInZk) { if (registerInZk) {
zkSys.registerInZk(core, false); zkSys.registerInZk(core, false, skipRecovery);
} }
return old; return old;
} }
@ -765,7 +765,7 @@ public class CoreContainer {
* @return the newly created core * @return the newly created core
*/ */
public SolrCore create(String coreName, Map<String, String> parameters) { public SolrCore create(String coreName, Map<String, String> parameters) {
return create(coreName, cfg.getCoreRootDirectory().resolve(coreName), parameters); return create(coreName, cfg.getCoreRootDirectory().resolve(coreName), parameters, false);
} }
/** /**
@ -775,7 +775,7 @@ public class CoreContainer {
* @param parameters the core parameters * @param parameters the core parameters
* @return the newly created core * @return the newly created core
*/ */
public SolrCore create(String coreName, Path instancePath, Map<String, String> parameters) { public SolrCore create(String coreName, Path instancePath, Map<String, String> parameters, boolean newCollection) {
CoreDescriptor cd = new CoreDescriptor(this, coreName, instancePath, parameters); CoreDescriptor cd = new CoreDescriptor(this, coreName, instancePath, parameters);
@ -798,7 +798,7 @@ public class CoreContainer {
preExisitingZkEntry = getZkController().checkIfCoreNodeNameAlreadyExists(cd); preExisitingZkEntry = getZkController().checkIfCoreNodeNameAlreadyExists(cd);
} }
SolrCore core = create(cd, true); SolrCore core = create(cd, true, newCollection);
// only write out the descriptor if the core is successfully created // only write out the descriptor if the core is successfully created
coresLocator.create(this, cd); coresLocator.create(this, cd);
@ -845,7 +845,7 @@ public class CoreContainer {
* *
* @return the newly created core * @return the newly created core
*/ */
private SolrCore create(CoreDescriptor dcore, boolean publishState) { private SolrCore create(CoreDescriptor dcore, boolean publishState, boolean newCollection) {
if (isShutDown) { if (isShutDown) {
throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Solr has been shutdown."); throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Solr has been shutdown.");
@ -868,7 +868,7 @@ public class CoreContainer {
core.getUpdateHandler().getUpdateLog().recoverFromLog(); core.getUpdateHandler().getUpdateLog().recoverFromLog();
} }
registerCore(dcore.getName(), core, publishState); registerCore(dcore.getName(), core, publishState, newCollection);
return core; return core;
} catch (Exception e) { } catch (Exception e) {
@ -964,7 +964,7 @@ public class CoreContainer {
ConfigSet coreConfig = coreConfigService.getConfig(cd); ConfigSet coreConfig = coreConfigService.getConfig(cd);
log.info("Reloading SolrCore '{}' using configuration from {}", cd.getName(), coreConfig.getName()); log.info("Reloading SolrCore '{}' using configuration from {}", cd.getName(), coreConfig.getName());
SolrCore newCore = core.reload(coreConfig); SolrCore newCore = core.reload(coreConfig);
registerCore(name, newCore, false); registerCore(name, newCore, false, false);
} catch (SolrCoreState.CoreIsClosedException e) { } catch (SolrCoreState.CoreIsClosedException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
@ -1061,7 +1061,7 @@ public class CoreContainer {
SolrIdentifierValidator.validateCoreName(toName); SolrIdentifierValidator.validateCoreName(toName);
try (SolrCore core = getCore(name)) { try (SolrCore core = getCore(name)) {
if (core != null) { if (core != null) {
registerCore(toName, core, true); registerCore(toName, core, true, false);
SolrCore old = solrCores.remove(name); SolrCore old = solrCores.remove(name);
coresLocator.rename(this, old.getCoreDescriptor(), core.getCoreDescriptor()); coresLocator.rename(this, old.getCoreDescriptor(), core.getCoreDescriptor());
} }
@ -1132,7 +1132,7 @@ public class CoreContainer {
if (zkSys.getZkController() != null) { if (zkSys.getZkController() != null) {
zkSys.getZkController().throwErrorIfReplicaReplaced(desc); zkSys.getZkController().throwErrorIfReplicaReplaced(desc);
} }
core = create(desc, true); // This should throw an error if it fails. core = create(desc, true, false); // This should throw an error if it fails.
} }
core.open(); core.open();
} }

View File

@ -173,12 +173,12 @@ public class ZkContainer {
return zkRun.substring(0, zkRun.lastIndexOf('/')); return zkRun.substring(0, zkRun.lastIndexOf('/'));
} }
public void registerInZk(final SolrCore core, boolean background) { public void registerInZk(final SolrCore core, boolean background, boolean skipRecovery) {
Runnable r = () -> { Runnable r = () -> {
MDCLoggingContext.setCore(core); MDCLoggingContext.setCore(core);
try { try {
try { try {
zkController.register(core.getName(), core.getCoreDescriptor()); zkController.register(core.getName(), core.getCoreDescriptor(), skipRecovery);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// Restore the interrupted status // Restore the interrupted status
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();

View File

@ -82,7 +82,9 @@ enum CoreAdminOperation implements CoreAdminOp {
instancePath = coreContainer.getCoreRootDirectory().resolve(instanceDir).normalize(); instancePath = coreContainer.getCoreRootDirectory().resolve(instanceDir).normalize();
} }
coreContainer.create(coreName, instancePath, coreParams); boolean newCollection = params.getBool(CoreAdminParams.NEW_COLLECTION, false);
coreContainer.create(coreName, instancePath, coreParams, newCollection);
it.rsp.add("core", coreName); it.rsp.add("core", coreName);
}), }),

View File

@ -219,7 +219,7 @@ public class TestCodecSupport extends SolrTestCaseJ4 {
try { try {
c = new SolrCore(new CoreDescriptor(h.getCoreContainer(), newCoreName, testSolrHome.resolve(newCoreName)), c = new SolrCore(new CoreDescriptor(h.getCoreContainer(), newCoreName, testSolrHome.resolve(newCoreName)),
new ConfigSet("fakeConfigset", config, schema, null)); new ConfigSet("fakeConfigset", config, schema, null));
assertNull(h.getCoreContainer().registerCore(newCoreName, c, false)); assertNull(h.getCoreContainer().registerCore(newCoreName, c, false, false));
h.coreName = newCoreName; h.coreName = newCoreName;
assertEquals("We are not using the correct core", "solrconfig_codec2.xml", h.getCore().getConfigResource()); assertEquals("We are not using the correct core", "solrconfig_codec2.xml", h.getCore().getConfigResource());
assertU(add(doc("string_f", "foo"))); assertU(add(doc("string_f", "foo")));

View File

@ -230,7 +230,7 @@ public class TestIndexSearcher extends SolrTestCaseJ4 {
try { try {
// Create a new core, this should call all the firstSearcherListeners // Create a new core, this should call all the firstSearcherListeners
newCore = cores.create("core1", cd.getInstanceDir(), ImmutableMap.of("config", "solrconfig-searcher-listeners1.xml")); newCore = cores.create("core1", cd.getInstanceDir(), ImmutableMap.of("config", "solrconfig-searcher-listeners1.xml"), false);
//validate that the new core was created with the correct solrconfig //validate that the new core was created with the correct solrconfig
assertNotNull(newCore.getSearchComponent("mock")); assertNotNull(newCore.getSearchComponent("mock"));
@ -280,7 +280,7 @@ public class TestIndexSearcher extends SolrTestCaseJ4 {
boolean coreCreated = false; boolean coreCreated = false;
try { try {
// Create a new core, this should call all the firstSearcherListeners // Create a new core, this should call all the firstSearcherListeners
newCore = cores.create("core1", cd.getInstanceDir(), ImmutableMap.of("config", "solrconfig-searcher-listeners1.xml")); newCore = cores.create("core1", cd.getInstanceDir(), ImmutableMap.of("config", "solrconfig-searcher-listeners1.xml"), false);
coreCreated = true; coreCreated = true;
//validate that the new core was created with the correct solrconfig //validate that the new core was created with the correct solrconfig
@ -346,7 +346,7 @@ public class TestIndexSearcher extends SolrTestCaseJ4 {
try { try {
System.setProperty("tests.solr.useColdSearcher", "true"); System.setProperty("tests.solr.useColdSearcher", "true");
// Create a new core, this should call all the firstSearcherListeners // Create a new core, this should call all the firstSearcherListeners
newCore = cores.create("core1", cd.getInstanceDir(), ImmutableMap.of("config", "solrconfig-searcher-listeners1.xml")); newCore = cores.create("core1", cd.getInstanceDir(), ImmutableMap.of("config", "solrconfig-searcher-listeners1.xml"), false);
coreCreated = true; coreCreated = true;
//validate that the new core was created with the correct solrconfig //validate that the new core was created with the correct solrconfig

View File

@ -123,6 +123,11 @@ public abstract class CoreAdminParams
*/ */
public static final String COMMIT_NAME = "commitName"; public static final String COMMIT_NAME = "commitName";
/**
* A boolean parameter specifying if a core is being created as part of a new collection
*/
public static final String NEW_COLLECTION = "newCollection";
public enum CoreAdminAction { public enum CoreAdminAction {
STATUS(true), STATUS(true),
UNLOAD, UNLOAD,