You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ma...@apache.org on 2021/01/20 21:51:31 UTC

[lucene-solr] branch reference_impl_dev updated (6d66eea -> 07e6231)

This is an automated email from the ASF dual-hosted git repository.

markrmiller pushed a change to branch reference_impl_dev
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git.


    from 6d66eea  @1259 Add benchmark jar.
     new 4f5e704  @1260 Finish up work on Jetty start/stop and some cleanup.
     new 07e6231  @1261 Some cleanup around leader election and stale state and schemaless.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 solr/bin/jetty.sh                                  |   4 +-
 solr/bin/solr                                      |   3 +-
 .../org/apache/solr/cloud/ElectionContext.java     |   2 +-
 .../java/org/apache/solr/cloud/LeaderElector.java  |  48 +--
 .../apache/solr/cloud/OverseerElectionContext.java |   5 +-
 .../org/apache/solr/cloud/RecoveryStrategy.java    |  35 +--
 .../solr/cloud/ShardLeaderElectionContext.java     |  17 +-
 .../solr/cloud/ShardLeaderElectionContextBase.java |   4 +-
 .../java/org/apache/solr/cloud/StatePublisher.java |  20 +-
 .../java/org/apache/solr/cloud/ZkController.java   |  23 +-
 .../java/org/apache/solr/cloud/ZkShardTerms.java   |  11 -
 .../java/org/apache/solr/core/CoreContainer.java   |  55 +++-
 .../src/java/org/apache/solr/core/SolrCore.java    |   9 +
 .../java/org/apache/solr/handler/IndexFetcher.java |   4 +-
 .../org/apache/solr/handler/SchemaHandler.java     |   2 +-
 .../apache/solr/handler/admin/PrepRecoveryOp.java  |   2 +-
 .../handler/component/RealTimeGetComponent.java    |   2 +-
 .../apache/solr/handler/loader/JavabinLoader.java  |   9 +-
 .../org/apache/solr/request/SolrQueryRequest.java  |   2 -
 .../apache/solr/request/SolrQueryRequestBase.java  |   6 -
 .../java/org/apache/solr/schema/IndexSchema.java   | 102 ++++---
 .../org/apache/solr/schema/ManagedIndexSchema.java | 135 ++++----
 .../solr/schema/ManagedIndexSchemaFactory.java     |   6 +-
 .../apache/solr/schema/ZkIndexSchemaReader.java    |  18 +-
 .../apache/solr/servlet/SolrDispatchFilter.java    |  22 +-
 .../apache/solr/update/DefaultSolrCoreState.java   |   4 +-
 .../java/org/apache/solr/update/UpdateCommand.java |   4 +-
 .../AddSchemaFieldsUpdateProcessorFactory.java     |   2 +-
 .../org/apache/solr/cloud/CleanupOldIndexTest.java |   9 +-
 .../org/apache/solr/cloud/LeaderElectionTest.java  |   3 +-
 .../solr/cloud/MissingSegmentRecoveryTest.java     |   3 +-
 .../org/apache/solr/core/TestCoreContainer.java    |   2 +-
 .../org/apache/solr/schema/SchemaWatcherTest.java  |   2 +-
 .../org/apache/solr/schema/TestPointFields.java    |  16 +-
 solr/server/build.gradle                           |   1 -
 solr/server/contexts/solr-jetty-context.xml        |   1 +
 .../apache/solr/common/cloud/ZkStateReader.java    |   2 +-
 .../java/org/apache/solr/common/util/TimeOut.java  |   2 +-
 .../ConcurrentUpdateSolrClientBuilderTest.java     |   3 +-
 solr/webapp/web/WEB-INF/quickstart-web.xml         | 339 +++++++++++++++++++++
 40 files changed, 663 insertions(+), 276 deletions(-)
 create mode 100644 solr/webapp/web/WEB-INF/quickstart-web.xml


[lucene-solr] 01/02: @1260 Finish up work on Jetty start/stop and some cleanup.

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markrmiller pushed a commit to branch reference_impl_dev
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 4f5e70484635293e79bdde885011d6d580231ac9
Author: markrmiller@gmail.com <ma...@gmail.com>
AuthorDate: Wed Jan 20 08:40:57 2021 -0600

    @1260 Finish up work on Jetty start/stop and some cleanup.
---
 solr/bin/jetty.sh                                  |   4 +-
 solr/bin/solr                                      |   3 +-
 .../java/org/apache/solr/cloud/LeaderElector.java  |  16 +-
 .../java/org/apache/solr/cloud/ZkController.java   |   4 +-
 .../java/org/apache/solr/core/CoreContainer.java   |  20 +-
 .../apache/solr/servlet/SolrDispatchFilter.java    |  22 +-
 .../org/apache/solr/cloud/CleanupOldIndexTest.java |   9 +-
 .../org/apache/solr/core/TestCoreContainer.java    |   2 +-
 solr/server/build.gradle                           |   1 -
 solr/server/contexts/solr-jetty-context.xml        |   1 +
 .../java/org/apache/solr/common/util/TimeOut.java  |   2 +-
 solr/webapp/web/WEB-INF/quickstart-web.xml         | 339 +++++++++++++++++++++
 12 files changed, 383 insertions(+), 40 deletions(-)

diff --git a/solr/bin/jetty.sh b/solr/bin/jetty.sh
index fbe55cb..e30a504 100644
--- a/solr/bin/jetty.sh
+++ b/solr/bin/jetty.sh
@@ -140,7 +140,7 @@ started()
     #local PID=$(cat "$2" 2>/dev/null) || return 1
     #kill -0 "$PID" 2>/dev/null || return 1
     echo -n ". "
-    sleep .1
+    sleep .3
   done
 
   return 1;
@@ -442,7 +442,7 @@ fi
 ##################################################
 case "$ACTION" in
   start)
-    echo -n "Starting Jetty: "
+    echo -n "Starting Solr: "
 
     if (( NO_START )); then
       echo "Not starting ${NAME} - NO_START=1";
diff --git a/solr/bin/solr b/solr/bin/solr
index 093f8ff..3216d78 100755
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -2168,12 +2168,11 @@ function start_solr() {
     exec "$JAVA" "${SOLR_START_OPTS[@]}" $SOLR_ADDL_ARGS -XX:-UseBiasedLocking -jar start.jar "${SOLR_JETTY_CONFIG[@]}" $SOLR_JETTY_ADDL_CONFIG
   else
     # run Solr in the background
-    echo "java is $JAVA"
     export JAVA=$JAVA
     export JETTY_HOME="$SOLR_SERVER_DIR"
     export JETTY_PID="$SOLR_PID_DIR/solr-$SOLR_PORT.pid"
     export JETTY_ARGS="${SOLR_JETTY_CONFIG[@]} $SOLR_JETTY_ADDL_CONFIG"
-    export JAVA_OPTIONS="-Djetty.state=${SOLR_HOME}/jetty.state ${SOLR_START_OPTS[@]}" "$SOLR_ADDL_ARGS" "-XX:-UseBiasedLocking" "-Dsolr.log.muteconsole" "-XX:OnOutOfMemoryError=$SOLR_TIP/bin/oom_solr.sh" "$SOLR_PORT" "$SOLR_LOGS_DIR"
+    export JAVA_OPTIONS="-Djetty.state=${SOLR_HOME}/jetty.state ${SOLR_START_OPTS[@]} $SOLR_ADDL_ARGS -XX:-UseBiasedLocking -Dsolr.log.muteconsole -XX:OnOutOfMemoryError=$SOLR_TIP/bin/oom_solr.sh"
     export JETTY_STATE="${SOLR_HOME}/jetty.state"
     bash $SOLR_SERVER_DIR/../bin/jetty.sh start
   fi
diff --git a/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java b/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
index 3da2f7a..1fd6b69 100644
--- a/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
+++ b/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
@@ -217,14 +217,16 @@ public class LeaderElector implements Closeable {
           state = WAITING_IN_ELECTION;
           if (log.isDebugEnabled()) log.debug("Watching path {} to know if I could be the leader, my node is {}", watchedNode, context.leaderSeqPath);
 
-          log.info("Start recovery for core {}", context.leaderProps.getName());
-          try (SolrCore core = zkController.getCoreContainer().getCore(context.leaderProps.getName())) {
-            if (core != null) {
-             // if (!core.getSolrCoreState().isRecoverying()) {
+          if (context instanceof ShardLeaderElectionContext) {
+            log.info("Start recovery for core {}", context.leaderProps.getName());
+            try (SolrCore core = zkController.getCoreContainer().getCore(context.leaderProps.getName())) {
+              if (core != null) {
+                // if (!core.getSolrCoreState().isRecoverying()) {
                 core.getSolrCoreState().doRecovery(core);
-             // }
-            } else {
-              log.warn("No core found to start recovery with {}", context.leaderProps.getName());
+                // }
+              } else {
+                log.warn("No core found to start recovery with {}", context.leaderProps.getName());
+              }
             }
           }
           return false;
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
index 99be781..6048255 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -1005,7 +1005,7 @@ public class ZkController implements Closeable, Runnable {
     //
     //    });
     //   synchronized (initLock) {
-    log.info("making shutdown watcher for cluster");
+    if (log.isDebugEnabled()) log.debug("making shutdown watcher for cluster");
     try {
       zkClient.exists(CLUSTER_SHUTDOWN, new Watcher() {
         @Override
@@ -1014,7 +1014,7 @@ public class ZkController implements Closeable, Runnable {
             return;
           }
 
-          log.info("Got even for shutdown {}" + event);
+          log.info("Got event for shutdown {}" + event);
           if (event.getType().equals(Event.EventType.NodeCreated)) {
             log.info("Shutdown zk node created, shutting down");
             shutdown();
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index e2748ec..cba6827 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -148,6 +148,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
 
 /**
@@ -157,11 +158,6 @@ public class CoreContainer implements Closeable {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  static {
-    log.warn("expected pre init of xml factories {} {} {} {} {}",
-        FieldTypeXmlAdapter.dbf, XMLResponseParser.inputFactory, XMLResponseParser.saxFactory);
-  }
-
   final SolrCores solrCores = new SolrCores(this);
   private final boolean isZkAware;
   private volatile boolean startedLoadingCores;
@@ -222,7 +218,7 @@ public class CoreContainer implements Closeable {
 
   private final PluginBag<SolrRequestHandler> containerHandlers = new PluginBag<>(SolrRequestHandler.class, null);
 
-  private volatile boolean asyncSolrCoreLoad;
+  private volatile boolean asyncSolrCoreLoad = true;
 
   protected volatile SecurityConfHandler securityConfHandler;
 
@@ -342,7 +338,7 @@ public class CoreContainer implements Closeable {
   }
 
   public CoreContainer(NodeConfig config, CoresLocator locator) {
-    this(config, locator, config.getCloudConfig() != null);
+    this(config, locator, true);
   }
 
   public CoreContainer(NodeConfig config, CoresLocator locator, boolean asyncSolrCoreLoad) {
@@ -627,7 +623,7 @@ public class CoreContainer implements Closeable {
    */
   public static CoreContainer createAndLoad(Path solrHome, Path configFile, SolrZkClient zkClient) throws IOException {
     NodeConfig config = new SolrXmlConfig().fromFile(solrHome, configFile, new Properties());
-    CoreContainer cc = new CoreContainer(zkClient, config, new CorePropertiesLocator(config.getCoreRootDirectory()), true);
+    CoreContainer cc = new CoreContainer(zkClient, config, new CorePropertiesLocator(config.getCoreRootDirectory()), false);
     try {
       cc.load();
     } catch (Exception e) {
@@ -685,7 +681,8 @@ public class CoreContainer implements Closeable {
   /**
    * Load the cores defined for this CoreContainer
    */
-  public synchronized void load() {
+  public void load() {
+    long start = System.nanoTime();
     if (log.isDebugEnabled()) {
       log.debug("Loading cores into CoreContainer [instanceDir={}]", getSolrHome());
     }
@@ -926,8 +923,7 @@ public class CoreContainer implements Closeable {
     } finally {
 
       startedLoadingCores = true;
-      if (coreLoadFutures != null) {
-
+      if (coreLoadFutures != null && !asyncSolrCoreLoad) {
         for (Future<SolrCore> future : coreLoadFutures) {
           try {
             future.get();
@@ -946,7 +942,7 @@ public class CoreContainer implements Closeable {
     }
     // This is a bit redundant but these are two distinct concepts for all they're accomplished at the same time.
     status |= LOAD_COMPLETE | INITIAL_CORE_LOAD_COMPLETE;
-
+    log.info("load took {}ms", TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS));
   }
 
   // MetricsHistoryHandler supports both cloud and standalone configs
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index 075b0d4..7a782ea 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -45,6 +45,7 @@ import java.util.Locale;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
@@ -106,11 +107,12 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   static {
-    log.warn("expected pre init of xml factories {} {} {} {} {}",
+    log.warn("expected pre init of xml factories {} {} {}",
         FieldTypeXmlAdapter.dbf, XMLResponseParser.inputFactory, XMLResponseParser.saxFactory);
   }
 
   private volatile StopRunnable stopRunnable;
+  private volatile Future<?> loadCoresFuture;
 
   private static class LiveThread extends Thread {
     @Override
@@ -177,9 +179,6 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   @Override
   public void init(FilterConfig config) throws ServletException {
     log.info("SolrDispatchFilter.init(): {}", this.getClass().getClassLoader());
-    if (log.isTraceEnabled()) {
-      log.trace("SolrDispatchFilter.init(): {}", this.getClass().getClassLoader());
-    }
 
     Properties extraProperties = (Properties) config.getServletContext().getAttribute(PROPERTIES_ATTRIBUTE);
     if (extraProperties == null) extraProperties = new Properties();
@@ -189,15 +188,17 @@ public class SolrDispatchFilter extends BaseSolrFilter {
       initCall.run();
     }
 
-    log.info("Using extra properties {}", extraProperties);
+    if (extraProperties.size() > 0) {
+      log.info("Using extra properties {}", extraProperties);
+    }
 
     CoreContainer coresInit = null;
     try {
 
       StartupLoggingUtils.checkLogDir();
-      if (log.isInfoEnabled()) {
-        log.info("Using logger factory {}", StartupLoggingUtils.getLoggerImplStr());
-      }
+
+      log.info("Using logger factory {}", StartupLoggingUtils.getLoggerImplStr());
+
       logWelcomeBanner();
       String muteConsole = System.getProperty(SOLR_LOG_MUTECONSOLE);
       if (muteConsole != null && !Arrays.asList("false", "0", "off", "no").contains(muteConsole.toLowerCase(Locale.ROOT))) {
@@ -232,6 +233,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
         if (log.isDebugEnabled()) {
           log.debug("user.dir={}", System.getProperty("user.dir"));
         }
+        loadCoresFuture.get();
       } catch (Throwable t) {
         // catch this so our filter still works
         log.error("Could not start Solr. Check solr/home property and the logs");
@@ -241,11 +243,11 @@ public class SolrDispatchFilter extends BaseSolrFilter {
         }
       }
     } finally {
-      log.trace("SolrDispatchFilter.init() done");
       if (cores != null) {
         this.httpClient = cores.getUpdateShardHandler().getTheSharedHttpClient().getHttpClient();
       }
       init.countDown();
+      log.info("SolrDispatchFilter.init() end");
     }
   }
 
@@ -358,7 +360,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
         return cores.isShutDown();
       }
     });
-    cores.load();
+    loadCoresFuture = ParWork.getRootSharedExecutor().submit(() -> cores.load());
     return cores;
   }
 
diff --git a/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java b/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
index c3b98fa..e6050ac 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
@@ -20,11 +20,14 @@ import java.io.File;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.common.util.TimeOut;
+import org.apache.solr.common.util.TimeSource;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.SnapShooter;
@@ -126,9 +129,11 @@ public class CleanupOldIndexTest extends SolrCloudTestCase {
     indexThread.safeStop();
     indexThread.join();
 
-    assertTrue(!oldIndexDir1.exists());
-    assertTrue(!oldIndexDir2.exists());
+    TimeOut timeout = new TimeOut(500, TimeUnit.MILLISECONDS, TimeSource.NANO_TIME);
+    timeout.waitFor("", () -> !oldIndexDir1.exists());
 
+    TimeOut timeout2 = new TimeOut(500, TimeUnit.MILLISECONDS, TimeSource.NANO_TIME);
+    timeout2.waitFor("", () -> !oldIndexDir2.exists());
 
     jetty.stop();
   }
diff --git a/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java b/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
index df2ca59..a6ebd2c 100644
--- a/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
+++ b/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
@@ -206,7 +206,7 @@ public class TestCoreContainer extends SolrTestCaseJ4 {
     Path solrHome = createTempDir();
     System.setProperty("configsets", getFile("solr/configsets").getAbsolutePath());
 
-    final CoreContainer cc = new CoreContainer(new SolrXmlConfig().fromString(solrHome, CONFIGSETS_SOLR_XML), cl);
+    final CoreContainer cc = new CoreContainer(new SolrXmlConfig().fromString(solrHome, CONFIGSETS_SOLR_XML), cl, false);
     Path corePath = solrHome.resolve("badcore");
     CoreDescriptor badcore = new CoreDescriptor("badcore", corePath, cc,
         "configSet", "nosuchconfigset");
diff --git a/solr/server/build.gradle b/solr/server/build.gradle
index 209bd1a..1960f2e 100644
--- a/solr/server/build.gradle
+++ b/solr/server/build.gradle
@@ -55,7 +55,6 @@ dependencies {
   api 'org.eclipse.jetty:jetty-servlet'
   api 'org.eclipse.jetty:jetty-servlets'
   api 'org.eclipse.jetty:jetty-util'
-  api 'org.eclipse.jetty:jetty-webapp'
   api 'org.eclipse.jetty:jetty-xml'
   api 'org.eclipse.jetty:jetty-alpn-server'
   api 'org.eclipse.jetty:jetty-quickstart'
diff --git a/solr/server/contexts/solr-jetty-context.xml b/solr/server/contexts/solr-jetty-context.xml
index 3d06ad7..f117f52 100644
--- a/solr/server/contexts/solr-jetty-context.xml
+++ b/solr/server/contexts/solr-jetty-context.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0"?>
 <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
 <Configure class="org.eclipse.jetty.quickstart.QuickStartWebApp">
+  <Set name="autoPreconfigure">false</Set>
   <Set name="contextPath"><Property name="hostContext" default="/solr"/></Set>
   <Set name="war"><Property name="jetty.base"/>/solr-webapp/webapp</Set>
   <Set name="defaultsDescriptor"><Property name="jetty.base"/>/etc/webdefault.xml</Set>
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/TimeOut.java b/solr/solrj/src/java/org/apache/solr/common/util/TimeOut.java
index 934d10c..adba260 100644
--- a/solr/solrj/src/java/org/apache/solr/common/util/TimeOut.java
+++ b/solr/solrj/src/java/org/apache/solr/common/util/TimeOut.java
@@ -65,7 +65,7 @@ public class TimeOut {
   public void waitFor(String messageOnTimeOut, Supplier<Boolean> supplier)
       throws InterruptedException, TimeoutException {
     while (!supplier.get() && !hasTimedOut()) {
-      timeSource.sleep(250);
+      timeSource.sleep(150);
     }
     if (hasTimedOut()) throw new TimeoutException(messageOnTimeOut);
   }
diff --git a/solr/webapp/web/WEB-INF/quickstart-web.xml b/solr/webapp/web/WEB-INF/quickstart-web.xml
new file mode 100644
index 0000000..331c973
--- /dev/null
+++ b/solr/webapp/web/WEB-INF/quickstart-web.xml
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" metadata-complete="true" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
+  <context-param>
+    <param-name>org.eclipse.jetty.containerInitializers</param-name>
+    <param-value><![CDATA[
+    "ContainerInitializer{org.apache.logging.log4j.web.Log4jServletContainerInitializer,interested=[],applicable=[],annotated=[]}"]]></param-value>
+  </context-param>
+  <context-param>
+    <param-name>org.eclipse.jetty.tlds</param-name>
+    <param-value><![CDATA[]]></param-value>
+  </context-param>
+  <context-param>
+    <param-name>org.eclipse.jetty.resources</param-name>
+    <param-value><![CDATA[]]></param-value>
+  </context-param>
+  <context-param>
+    <param-name>org.eclipse.jetty.jsp.precompiled</param-name>
+    <param-value>true</param-value>
+  </context-param>
+  <listener>
+    <listener-class>org.eclipse.jetty.servlet.listener.ELContextCleaner</listener-class>
+  </listener>
+  <listener>
+    <listener-class>org.eclipse.jetty.servlet.listener.IntrospectorCleaner</listener-class>
+  </listener>
+  <filter>
+    <filter-name>SolrQosFilter</filter-name>
+    <filter-class>org.apache.solr.servlet.SolrQoSFilter</filter-class>
+    <async-supported>true</async-supported>
+  </filter>
+  <filter>
+    <filter-name>SolrRequestFilter</filter-name>
+    <filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class>
+    <async-supported>true</async-supported>
+    <init-param>
+      <param-name>excludePatterns</param-name>
+      <param-value>/partials/.+,/libs/.+,/css/.+,/js/.+,/img/.+,/templates/.+</param-value>
+    </init-param>
+  </filter>
+  <filter-mapping>
+    <filter-name>SolrQosFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>ASYNC</dispatcher>
+  </filter-mapping>
+  <filter-mapping>
+    <filter-name>SolrRequestFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>ASYNC</dispatcher>
+  </filter-mapping>
+  <servlet>
+    <servlet-name>default</servlet-name>
+    <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+    <init-param>
+      <param-name>aliases</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>dirAllowed</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCacheSize</param-name>
+      <param-value>256000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFileSize</param-name>
+      <param-value>200000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>welcomeServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>useFileMappedBuffer</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>gzip</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>acceptRanges</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFiles</param-name>
+      <param-value>2048</param-value>
+    </init-param>
+    <init-param>
+      <param-name>redirectWelcome</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <load-on-startup>0</load-on-startup>
+    <async-supported>false</async-supported>
+  </servlet>
+  <servlet>
+    <servlet-name>jsp</servlet-name>
+    <servlet-class>org.eclipse.jetty.servlet.NoJspServlet</servlet-class>
+    <init-param>
+      <param-name>logVerbosityLevel</param-name>
+      <param-value>DEBUG</param-value>
+    </init-param>
+    <init-param>
+      <param-name>fork</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>xpoweredBy</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <load-on-startup>0</load-on-startup>
+    <async-supported>false</async-supported>
+  </servlet>
+  <servlet>
+    <servlet-name>LoadAdminUI</servlet-name>
+    <servlet-class>org.apache.solr.servlet.LoadAdminUiServlet</servlet-class>
+    <async-supported>false</async-supported>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>default</servlet-name>
+    <url-pattern>/</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>jsp</servlet-name>
+    <url-pattern>*.jsp</url-pattern>
+    <url-pattern>*.jspf</url-pattern>
+    <url-pattern>*.jspx</url-pattern>
+    <url-pattern>*.xsp</url-pattern>
+    <url-pattern>*.JSP</url-pattern>
+    <url-pattern>*.JSPF</url-pattern>
+    <url-pattern>*.JSPX</url-pattern>
+    <url-pattern>*.XSP</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>LoadAdminUI</servlet-name>
+    <url-pattern>/index.html</url-pattern>
+  </servlet-mapping>
+  <security-constraint>
+    <web-resource-collection>
+      <web-resource-name>Disable TRACE</web-resource-name>
+      <url-pattern>/</url-pattern>
+      <http-method>TRACE</http-method>
+    </web-resource-collection>
+    <auth-constraint/>
+  </security-constraint>
+  <security-constraint>
+    <web-resource-collection>
+      <web-resource-name>Disable TRACE</web-resource-name>
+      <url-pattern>/</url-pattern>
+      <http-method>TRACE</http-method>
+    </web-resource-collection>
+    <auth-constraint/>
+  </security-constraint>
+  <security-constraint>
+    <web-resource-collection>
+      <web-resource-name>Enable everything but TRACE</web-resource-name>
+      <url-pattern>/</url-pattern>
+      <http-method-omission>TRACE</http-method-omission>
+    </web-resource-collection>
+  </security-constraint>
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+  <locale-encoding-mapping-list>
+    <locale-encoding-mapping>
+      <locale>de</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>no</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>be</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>fi</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ru</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>pt</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>bg</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>lt</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>hr</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>lv</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>fr</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>hu</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>zh_TW</locale>
+      <encoding>Big5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sh</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>uk</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sk</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sl</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ca</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>mk</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sq</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sr</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sv</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ko</locale>
+      <encoding>EUC-KR</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>el</locale>
+      <encoding>ISO-8859-7</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>en</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>is</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>it</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>es</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>iw</locale>
+      <encoding>ISO-8859-8</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>zh</locale>
+      <encoding>GB2312</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>et</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>cs</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ar</locale>
+      <encoding>ISO-8859-6</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ja</locale>
+      <encoding>Shift_JIS</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>pl</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>da</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ro</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>nl</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>tr</locale>
+      <encoding>ISO-8859-9</encoding>
+    </locale-encoding-mapping>
+  </locale-encoding-mapping-list>
+  <session-config>
+    <session-timeout>30</session-timeout>
+    <cookie-config>
+      <name>JSESSIONID</name>
+      <http-only>false</http-only>
+      <secure>false</secure>
+      <max-age>-1</max-age>
+    </cookie-config>
+    <tracking-mode>URL</tracking-mode>
+    <tracking-mode>COOKIE</tracking-mode>
+  </session-config>
+  <mime-mapping>
+    <extension>xsl</extension>
+    <mime-type>application/xslt+xml</mime-type>
+  </mime-mapping>
+</web-app>


[lucene-solr] 02/02: @1261 Some cleanup around leader election and stale state and schemaless.

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markrmiller pushed a commit to branch reference_impl_dev
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 07e623177055dc2188efb9e286f5f3116767db4d
Author: markrmiller@gmail.com <ma...@gmail.com>
AuthorDate: Wed Jan 20 15:50:53 2021 -0600

    @1261 Some cleanup around leader election and stale state and schemaless.
---
 .../org/apache/solr/cloud/ElectionContext.java     |   2 +-
 .../java/org/apache/solr/cloud/LeaderElector.java  |  50 +++-----
 .../apache/solr/cloud/OverseerElectionContext.java |   5 +-
 .../org/apache/solr/cloud/RecoveryStrategy.java    |  35 +++---
 .../solr/cloud/ShardLeaderElectionContext.java     |  17 +--
 .../solr/cloud/ShardLeaderElectionContextBase.java |   4 +-
 .../java/org/apache/solr/cloud/StatePublisher.java |  20 +--
 .../java/org/apache/solr/cloud/ZkController.java   |  19 ++-
 .../java/org/apache/solr/cloud/ZkShardTerms.java   |  11 --
 .../java/org/apache/solr/core/CoreContainer.java   |  35 +++++-
 .../src/java/org/apache/solr/core/SolrCore.java    |   9 ++
 .../java/org/apache/solr/handler/IndexFetcher.java |   4 +-
 .../org/apache/solr/handler/SchemaHandler.java     |   2 +-
 .../apache/solr/handler/admin/PrepRecoveryOp.java  |   2 +-
 .../handler/component/RealTimeGetComponent.java    |   2 +-
 .../apache/solr/handler/loader/JavabinLoader.java  |   9 +-
 .../org/apache/solr/request/SolrQueryRequest.java  |   2 -
 .../apache/solr/request/SolrQueryRequestBase.java  |   6 -
 .../java/org/apache/solr/schema/IndexSchema.java   | 102 +++++++++-------
 .../org/apache/solr/schema/ManagedIndexSchema.java | 135 ++++++++++++---------
 .../solr/schema/ManagedIndexSchemaFactory.java     |   6 +-
 .../apache/solr/schema/ZkIndexSchemaReader.java    |  18 +--
 .../apache/solr/update/DefaultSolrCoreState.java   |   4 +-
 .../java/org/apache/solr/update/UpdateCommand.java |   4 +-
 .../AddSchemaFieldsUpdateProcessorFactory.java     |   2 +-
 .../org/apache/solr/cloud/LeaderElectionTest.java  |   3 +-
 .../solr/cloud/MissingSegmentRecoveryTest.java     |   3 +-
 .../org/apache/solr/schema/SchemaWatcherTest.java  |   2 +-
 .../org/apache/solr/schema/TestPointFields.java    |  16 ++-
 .../apache/solr/common/cloud/ZkStateReader.java    |   2 +-
 .../ConcurrentUpdateSolrClientBuilderTest.java     |   3 +-
 31 files changed, 289 insertions(+), 245 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/cloud/ElectionContext.java b/solr/core/src/java/org/apache/solr/cloud/ElectionContext.java
index e66622d..e0d775e 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ElectionContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ElectionContext.java
@@ -47,7 +47,7 @@ public abstract class ElectionContext {
   protected void cancelElection() throws InterruptedException, KeeperException {
   }
 
-  abstract void runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs) throws KeeperException, InterruptedException, IOException;
+  abstract boolean runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs) throws KeeperException, InterruptedException, IOException;
 
   public void checkIfIamLeaderFired() {}
 
diff --git a/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java b/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
index 1fd6b69..090dc83 100644
--- a/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
+++ b/solr/core/src/java/org/apache/solr/cloud/LeaderElector.java
@@ -25,7 +25,6 @@ import org.apache.solr.common.cloud.SolrZooKeeper;
 import org.apache.solr.common.cloud.ZooKeeperException;
 import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.ObjectReleaseTracker;
-import org.apache.solr.core.SolrCore;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.KeeperException.ConnectionLossException;
@@ -213,22 +212,15 @@ public class LeaderElector implements Closeable {
           }
 
           watcher = new ElectionWatcher(context.leaderSeqPath, watchedNode, context);
-          zkClient.exists(watchedNode, watcher);
+          Stat exists = zkClient.exists(watchedNode, watcher);
+          if (exists == null) {
+            state = OUT_OF_ELECTION;
+            return true;
+          }
+
           state = WAITING_IN_ELECTION;
           if (log.isDebugEnabled()) log.debug("Watching path {} to know if I could be the leader, my node is {}", watchedNode, context.leaderSeqPath);
 
-          if (context instanceof ShardLeaderElectionContext) {
-            log.info("Start recovery for core {}", context.leaderProps.getName());
-            try (SolrCore core = zkController.getCoreContainer().getCore(context.leaderProps.getName())) {
-              if (core != null) {
-                // if (!core.getSolrCoreState().isRecoverying()) {
-                core.getSolrCoreState().doRecovery(core);
-                // }
-              } else {
-                log.warn("No core found to start recovery with {}", context.leaderProps.getName());
-              }
-            }
-          }
           return false;
         } catch (KeeperException.SessionExpiredException e) {
           state = OUT_OF_ELECTION;
@@ -275,10 +267,13 @@ public class LeaderElector implements Closeable {
       throw new IllegalStateException("Already in leader state");
     }
 
-    context.runLeaderProcess(context, weAreReplacement,0);
+    boolean success = context.runLeaderProcess(context, weAreReplacement, 0);
 
-
-    state = LEADER;
+    if (success) {
+      state = LEADER;
+    } else {
+      state = OUT_OF_ELECTION;
+    }
   }
 
   /**
@@ -436,25 +431,8 @@ public class LeaderElector implements Closeable {
 
     while (tryagain) {
       tryagain = checkIfIamLeader(context, replacement);
-
-      if (tryagain) {
-        try {
-          try (SolrCore core = zkController.getCoreContainer().getCore(context.leaderProps.getName())) {
-            if (core != null) {
-              if (!core.getSolrCoreState().isRecoverying()) {
-                core.getSolrCoreState().doRecovery(core);
-              }
-            }
-          }
-        } catch (Exception e) {
-          log.error("Exception trying to kick off or check for recovery", e);
-        }
-
-      }
-
     }
 
-
 //    boolean tryagain = false;
 //    while (tryagain) {
 //      tryagain = checkIfIamLeader(context, replacement);
@@ -572,6 +550,7 @@ public class LeaderElector implements Closeable {
             }
           }
         }
+        // we don't kick off recovery here, the leader sync will do that if necessary for its replicas
       } catch (AlreadyClosedException | InterruptedException e) {
         log.info("Already shutting down");
         return;
@@ -620,4 +599,7 @@ public class LeaderElector implements Closeable {
     joinElection(true, joinAtHead);
   }
 
+  public boolean isLeader() {
+    return LEADER.equals(state);
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerElectionContext.java b/solr/core/src/java/org/apache/solr/cloud/OverseerElectionContext.java
index db607f0..43feae3 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerElectionContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerElectionContext.java
@@ -50,13 +50,13 @@ final class OverseerElectionContext extends ShardLeaderElectionContextBase {
   }
 
   @Override
-  void runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs) throws KeeperException,
+  boolean runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs) throws KeeperException,
           InterruptedException, IOException {
     log.info("Running the leader process for Overseer");
 
     if (overseer.isDone()) {
       log.info("Already closed, bailing ...");
-      return;
+      return false;
     }
 
     // TODO: the idea here is that we could clear the Overseer queue
@@ -87,6 +87,7 @@ final class OverseerElectionContext extends ShardLeaderElectionContextBase {
       log.info("Will not start Overseer because we are closed");
     }
 
+    return true;
   }
 
   public Overseer getOverseer() {
diff --git a/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
index c5406a8..2ecf60b 100644
--- a/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
@@ -56,6 +56,7 @@ import org.apache.solr.util.plugin.NamedListInitializedPlugin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTIONS_ZKNODE;
 import java.io.Closeable;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
@@ -180,27 +181,22 @@ public class RecoveryStrategy implements Runnable, Closeable {
   final public void close() {
     close = true;
 
-    //
-    //
-    //        try {
-    //          if (prevSendPreRecoveryHttpUriRequest != null) {
-    //            prevSendPreRecoveryHttpUriRequest.cancel();
-    //          }
-    //          prevSendPreRecoveryHttpUriRequest = null;
-    //        } catch (NullPointerException e) {
-    //          // expected
-    //        }
-    //
-    //
+    try {
+      if (prevSendPreRecoveryHttpUriRequest != null) {
+        prevSendPreRecoveryHttpUriRequest.cancel();
+      }
+      prevSendPreRecoveryHttpUriRequest = null;
+    } catch (NullPointerException e) {
+      // expected
+    }
+
     ReplicationHandler finalReplicationHandler = replicationHandler;
     if (finalReplicationHandler != null) {
 
       finalReplicationHandler.abortFetch();
     }
     if (latch != null) {
-
       latch.countDown();
-
     }
 
     log.warn("Stopping recovery for core=[{}]", coreName);
@@ -345,7 +341,7 @@ public class RecoveryStrategy implements Runnable, Closeable {
       try {
         try {
           Replica leader = zkController.getZkStateReader().getLeaderRetry(coreDescriptor.getCollectionName(), coreDescriptor.getCloudDescriptor().getShardId(), 1500);
-          if (leader != null && leader.getName().equals(coreName)) {
+          if (leader != null && leader.getName().equals(coreName) &&  zkController.getZkClient().exists(COLLECTIONS_ZKNODE + "/" + coreDescriptor.getCollectionName() + "/leaders/" + coreDescriptor.getCloudDescriptor().getShardId() + "/leader")) {
             log.info("We are the leader, STOP recovery");
             close = true;
             return;
@@ -356,10 +352,11 @@ public class RecoveryStrategy implements Runnable, Closeable {
             return;
           }
         } catch (InterruptedException e) {
-          log.info("InterruptedException, won't do recovery", e);
+          log.info("InterruptedException", e);
           throw new SolrException(ErrorCode.BAD_REQUEST, e);
         } catch (TimeoutException e) {
-          log.info("Timeout waiting for leader, won't do recovery", e);
+          log.info("Timeout waiting for leader", e);
+          continue;
           //   throw new SolrException(ErrorCode.SERVER_ERROR, e);
         }
 
@@ -604,8 +601,8 @@ public class RecoveryStrategy implements Runnable, Closeable {
 //        } catch (NullPointerException e) {
 //          // okay
 //        }
-
-       // sendPrepRecoveryCmd(leader.getBaseUrl(), leader.getName(), slice);
+       // TODO can we do this with commit on leader
+        sendPrepRecoveryCmd(leader.getBaseUrl(), leader.getName(), zkStateReader.getClusterState().getCollection(coreDescriptor.getCollectionName()).getSlice(cloudDesc.getShardId()));
 
         // we wait a bit so that any updates on the leader
         // that started before they saw recovering state
diff --git a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
index f02e7d3..8256084 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
@@ -93,7 +93,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
    * weAreReplacement: has someone else been the leader already?
    */
   @Override
-  void runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStart) throws KeeperException,
+  boolean runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStart) throws KeeperException,
           InterruptedException, IOException {
 
     String coreName = leaderProps.getName();
@@ -106,7 +106,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
       }
       if (core.isClosing() || core.getCoreContainer().isShutDown()) {
         log.info("We are closed, will not become leader");
-        return;
+        return false;
       }
       try {
         ActionThrottle lt;
@@ -138,7 +138,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
         if (zkShardTerms.registered(coreName) && !zkShardTerms.canBecomeLeader(coreName)) {
           if (!waitForEligibleBecomeLeaderAfterTimeout(zkShardTerms, coreName, leaderVoteWait)) {
             rejoinLeaderElection(core);
-            return;
+            return false;
           } else {
             // only log an error if this replica win the election
             setTermToMax = true;
@@ -150,7 +150,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
         PeerSync.PeerSyncResult result = null;
         boolean success = false;
         if (core.getCoreContainer().isShutDown()) {
-          return;
+          return false;
         }
         result = syncStrategy.sync(zkController, core, leaderProps, weAreReplacement);
         log.info("Sync strategy sync result {}", result);
@@ -177,7 +177,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
             if (result.getOtherHasVersions().orElse(false)) {
               log.info("We failed sync, but we have no versions - we can't sync in that case. But others have some versions, so we should not become leader");
               rejoinLeaderElection(core);
-              return;
+              return false;
             } else {
               log.info("We failed sync, but we have no versions - we can't sync in that case - we did not find versions on other replicas, so become leader anyway");
               success = true;
@@ -204,7 +204,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
         if (!success) {
           log.info("Sync with potential leader failed, rejoining election ...");
           rejoinLeaderElection(core);
-          return;
+          return false;
         }
 
         if (replicaType == Replica.Type.TLOG) {
@@ -250,13 +250,16 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
         // we could not publish ourselves as leader - try and rejoin election
 
         rejoinLeaderElection(core);
+        return false;
       }
 
+
     } catch (AlreadyClosedException e) {
       log.info("CoreContainer is shutting down, won't become leader");
     } finally {
       MDCLoggingContext.clear();
     }
+    return true;
   }
 
   /**
@@ -316,8 +319,6 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
     log.info("There may be a better leader candidate than us - will cancel election, rejoin election, and kick off recovery");
 
     leaderElector.retryElection(false);
-
-    core.getUpdateHandler().getSolrCoreState().doRecovery(core);
   }
 
   public String getShardId() {
diff --git a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContextBase.java b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContextBase.java
index aa5cc80..b11c180 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContextBase.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContextBase.java
@@ -138,7 +138,7 @@ class ShardLeaderElectionContextBase extends ElectionContext {
   }
 
   @Override
-  synchronized void runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs)
+  synchronized boolean runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs)
           throws KeeperException, InterruptedException, IOException {
     // register as leader - if an ephemeral is already there, wait to see if it goes away
 
@@ -188,7 +188,7 @@ class ShardLeaderElectionContextBase extends ElectionContext {
       ParWork.propagateInterrupt(t);
       throw new SolrException(ErrorCode.SERVER_ERROR, "Could not register as the leader because creating the ephemeral registration node in ZooKeeper failed: " + errors, t);
     }
-
+    return true;
   }
 
   @Override
diff --git a/solr/core/src/java/org/apache/solr/cloud/StatePublisher.java b/solr/core/src/java/org/apache/solr/cloud/StatePublisher.java
index 2b83a81..341ffa3 100644
--- a/solr/core/src/java/org/apache/solr/cloud/StatePublisher.java
+++ b/solr/core/src/java/org/apache/solr/cloud/StatePublisher.java
@@ -30,7 +30,6 @@ import org.slf4j.LoggerFactory;
 import java.io.Closeable;
 import java.lang.invoke.MethodHandles;
 import java.util.Collections;
-import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Future;
@@ -41,6 +40,7 @@ public class StatePublisher implements Closeable {
       .getLogger(MethodHandles.lookup().lookupClass());
 
   private final Map<String,String> stateCache = new ConcurrentHashMap<>(32, 0.75f, 4);
+  private final ZkStateReader zkStateReader;
 
   public static class NoOpMessage extends ZkNodeProps {
   }
@@ -131,8 +131,9 @@ public class StatePublisher implements Closeable {
     }
   }
 
-  public StatePublisher(ZkDistributedQueue overseerJobQueue) {
+  public StatePublisher(ZkDistributedQueue overseerJobQueue, ZkStateReader zkStateReader) {
     this.overseerJobQueue = overseerJobQueue;
+    this.zkStateReader = zkStateReader;
   }
 
   public void submitState(ZkNodeProps stateMessage) {
@@ -142,15 +143,16 @@ public class StatePublisher implements Closeable {
       if (operation.equals("state")) {
         String core = stateMessage.getStr(ZkStateReader.CORE_NAME_PROP);
         String state = stateMessage.getStr(ZkStateReader.STATE_PROP);
+        String collection = stateMessage.getStr(ZkStateReader.COLLECTION_PROP);
 
-
+        Replica replica = zkStateReader.getClusterState().getCollection(collection).getReplica(core);
         String lastState = stateCache.get(core);
         // nocommit
-//        if (state.equals(lastState) && !Replica.State.ACTIVE.toString().toLowerCase(Locale.ROOT).equals(state)) {
-//          log.info("Skipping publish state as {} for {}, because it was the last state published", state, core);
-//          // nocommit
-//          return;
-//        }
+        if (collection != null && replica != null && state.equals(lastState) && replica.getState().toString().equals(state)) {
+          log.info("Skipping publish state as {} for {}, because it was the last state published", state, core);
+          // nocommit
+          return;
+        }
         if (core == null || state == null) {
           log.error("Nulls in published state");
           throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Nulls in published state " + stateMessage);
@@ -158,7 +160,7 @@ public class StatePublisher implements Closeable {
 
         stateCache.put(core, state);
       } else if (operation.equalsIgnoreCase("downnode")) {
-        // nocommit - set all statecache entries for replica to DOWN
+        // set all statecache entries for replica to DOWN
 
       } else {
         throw new IllegalArgumentException(stateMessage.toString());
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
index 6048255..f1c7416 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -430,8 +430,6 @@ public class ZkController implements Closeable, Runnable {
     this.overseerJobQueue = overseer.getStateUpdateQueue();
     this.overseerCollectionQueue = overseer.getCollectionQueue(zkClient);
     this.overseerConfigSetQueue = overseer.getConfigSetQueue(zkClient);
-    statePublisher = new StatePublisher(overseerJobQueue);
-    statePublisher.start();
 
     boolean isRegistered = SolrLifcycleListener.isRegistered(this);
     if (!isRegistered) {
@@ -1156,6 +1154,8 @@ public class ZkController implements Closeable, Runnable {
 
       zkStateReader.createClusterStateWatchersAndUpdate();
 
+      statePublisher = new StatePublisher(overseerJobQueue, zkStateReader);
+      statePublisher.start();
 
       this.sysPropsCacher = new NodesSysPropsCacher(getSolrCloudManager().getNodeStateProvider(), getNodeName(), zkStateReader);
       overseerElector = new LeaderElector(this, new ContextKey("overseer", "overseer"));
@@ -1411,13 +1411,21 @@ public class ZkController implements Closeable, Runnable {
       if (log.isDebugEnabled()) log.debug("Wait to see leader for {}, {}", collection, shardId);
       Replica leader = null;
       for (int i = 0; i < 30; i++) {
+//        if (leaderElector.isLeader()) {
+//          leader = replica;
+//          break;
+//        }
+
         try {
           if (getCoreContainer().isShutDown() || isDcCalled() || isClosed()) {
             throw new AlreadyClosedException();
           }
 
           leader = zkStateReader.getLeaderRetry(collection, shardId, 500);
-          break;
+
+          if (zkClient.exists(COLLECTIONS_ZKNODE + "/" + collection + "/leaders/" + shardId  + "/leader")) {
+            break;
+          }
         } catch (TimeoutException timeoutException) {
 
         }
@@ -1493,13 +1501,14 @@ public class ZkController implements Closeable, Runnable {
         }
       }
 
-      desc.getCloudDescriptor().setHasRegistered(true);
-
       // the watcher is added to a set so multiple calls of this method will left only one watcher
       // nocommit
       registerUnloadWatcher(cloudDesc.getCollectionName(), cloudDesc.getShardId(), desc.getName());
 
       log.info("SolrCore Registered, core{} baseUrl={} collection={}, shard={}", coreName, baseUrl, collection, shardId);
+
+      desc.getCloudDescriptor().setHasRegistered(true);
+
       return shardId;
     } finally {
       if (isDcCalled() || isClosed()) {
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkShardTerms.java b/solr/core/src/java/org/apache/solr/cloud/ZkShardTerms.java
index 5851483..d9eb9a3 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkShardTerms.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkShardTerms.java
@@ -76,8 +76,6 @@ public class ZkShardTerms implements Closeable {
   private final Set<CoreTermWatcher> listeners = ConcurrentHashMap.newKeySet();
   private final AtomicBoolean isClosed = new AtomicBoolean(false);
 
-  private final Object termUpdate = new Object();
-
   private final AtomicReference<ShardTerms> terms = new AtomicReference<>();
 
   /**
@@ -326,10 +324,7 @@ public class ZkShardTerms implements Closeable {
    */
   private boolean saveTerms(ShardTerms newTerms) throws KeeperException, InterruptedException {
     byte[] znodeData = Utils.toJSON(newTerms);
-    ShardTerms terms = this.terms.get();
-    int version = 0;
     try {
-      version = newTerms.getVersion();
       Stat stat = zkClient.setData(znodePath, znodeData, newTerms.getVersion(), true);
       ShardTerms newShardTerms = new ShardTerms(newTerms, stat.getVersion());
       setNewTerms(newShardTerms);
@@ -341,9 +336,6 @@ public class ZkShardTerms implements Closeable {
       if (isClosed.get()) {
         throw new AlreadyClosedException();
       }
-      synchronized (termUpdate) {
-        termUpdate.wait(250);
-      }
 
       refreshTerms(false);
     }
@@ -430,8 +422,5 @@ public class ZkShardTerms implements Closeable {
 
   private void onTermUpdates(ShardTerms newTerms) {
     listeners.removeIf(coreTermWatcher -> !coreTermWatcher.onTermChanged(newTerms));
-    synchronized (termUpdate) {
-      termUpdate.notifyAll();
-    }
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index cba6827..f25ea91 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -32,7 +32,6 @@ import org.apache.solr.client.solrj.impl.CloudHttp2SolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
 import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder;
-import org.apache.solr.client.solrj.impl.XMLResponseParser;
 import org.apache.solr.client.solrj.io.SolrClientCache;
 import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
 import org.apache.solr.cloud.CloudDescriptor;
@@ -89,7 +88,6 @@ import org.apache.solr.metrics.SolrMetricsContext;
 import org.apache.solr.pkg.PackageLoader;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.rest.schema.FieldTypeXmlAdapter;
 import org.apache.solr.search.SolrFieldCacheBean;
 import org.apache.solr.security.AuditLoggerPlugin;
 import org.apache.solr.security.AuthenticationPlugin;
@@ -149,6 +147,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.locks.ReentrantLock;
 
 /**
@@ -918,7 +917,37 @@ public class CoreContainer implements Closeable {
         }
       }
       if (zkSys != null && zkSys.getZkController() != null) {
-        zkSys.getZkController().createEphemeralLiveNode();
+        ParWork.getRootSharedExecutor().submit(() -> {
+//          Collection<SolrCore> cores = getCores();
+//          for (SolrCore core : cores) {
+//            CoreDescriptor desc = core.getCoreDescriptor();
+//            String collection = desc.getCollectionName();
+//            try {
+//              zkSys.getZkController().zkStateReader.waitForState(collection, 10, TimeUnit.SECONDS, (n, c) -> {
+//                if (c != null) {
+//                  List<Replica> replicas = c.getReplicas();
+//                  for (Replica replica : replicas) {
+//                    if (replica.getNodeName().equals(zkSys.getZkController().getNodeName())) {
+//                      if (!replica.getState().equals(Replica.State.DOWN)) {
+//                        //log.info("Found state {} {}", replica.getState(), replica.getNodeName());
+//                        return false;
+//                      }
+//                    }
+//                  }
+//                }
+//                return true;
+//              });
+//            } catch (InterruptedException e) {
+//              ParWork.propagateInterrupt(e);
+//              return;
+//            } catch (TimeoutException e) {
+//              log.error("Timeout", e);
+//            }
+//          }
+
+          zkSys.getZkController().createEphemeralLiveNode();
+        });
+
       }
     } finally {
 
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 8d06233..e363319 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -717,6 +717,12 @@ public final class SolrCore implements SolrInfoBean, Closeable {
     if (coreContainer.isShutDown() || isClosed() || closing) {
       throw new AlreadyClosedException();
     }
+    ReentrantLock schemaLock = null;
+    if (schema instanceof ManagedIndexSchema) {
+      schemaLock = ((ManagedIndexSchema) schema).getSchemaLock();
+      schemaLock.lock();
+    }
+
     // only one reload at a time
     ReentrantLock lock = getUpdateHandler().getSolrCoreState().getReloadLock();
     boolean locked = lock.tryLock();
@@ -802,6 +808,9 @@ public final class SolrCore implements SolrInfoBean, Closeable {
       if (lock != null && lock.isHeldByCurrentThread()) {
         lock.unlock();
       }
+      if (schemaLock != null && schemaLock.isHeldByCurrentThread()) {
+        schemaLock.unlock();
+      }
     }
   }
 
diff --git a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
index be65b25..ab4821b 100644
--- a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
+++ b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
@@ -619,7 +619,7 @@ public class IndexFetcher {
               if (successfulInstall) deleteTmpIdxDir = false;
             } else {
               terminateAndWaitFsyncService();
-              moveIndexFiles(tmpIndexDir, indexDir);
+              successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
             }
             if (successfulInstall) {
               if (isFullCopyNeeded) {
@@ -649,7 +649,7 @@ public class IndexFetcher {
               if (successfulInstall) deleteTmpIdxDir = false;
             } else if (successfulInstall) {
               terminateAndWaitFsyncService();
-              moveIndexFiles(tmpIndexDir, indexDir);
+              successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
 
               if (!successfulInstall) {
                 log.error("Move index files failed");
diff --git a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
index 3cde92d..df71dc9 100644
--- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
@@ -170,7 +170,7 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
               log.info("REFRESHING SCHEMA (refreshIfBelowVersion={}, currentVersion={}) before returning version!"
                   , refreshIfBelowVersion, zkVersion);
               ZkIndexSchemaReader zkIndexSchemaReader =  managed.getManagedIndexSchemaFactory().getZkIndexSchemaReader();
-              managed = (ManagedIndexSchema) zkIndexSchemaReader.updateSchema(null, -1, req.getCore());
+              managed = (ManagedIndexSchema) zkIndexSchemaReader.updateSchema();
               zkVersion = managed.getSchemaZkVersion();
             }
           }
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/PrepRecoveryOp.java b/solr/core/src/java/org/apache/solr/handler/admin/PrepRecoveryOp.java
index dadaa8b..b31795a 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/PrepRecoveryOp.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/PrepRecoveryOp.java
@@ -68,7 +68,7 @@ class PrepRecoveryOp implements CoreAdminHandler.CoreAdminOp {
     AtomicReference<String> errorMessage = new AtomicReference<>();
 
     try {
-      coreContainer.getZkController().getZkStateReader().waitForState(collection, 15, TimeUnit.SECONDS, (n, c) -> {
+      coreContainer.getZkController().getZkStateReader().waitForState(collection, 5, TimeUnit.SECONDS, (n, c) -> {
         if (c == null) {
           log.info("collection not found {}", collection);
           return false;
diff --git a/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java b/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
index 160e022..a7d71d1 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
@@ -1144,7 +1144,7 @@ public class RealTimeGetComponent extends SearchComponent
       // TODO: more complex response?
       rb.rsp.add("sync", success);
 
-      if (!success && rb.req.getCore().getCoreContainer().isZooKeeperAware()) {
+      if (!success && rb.req.getCore().getCoreContainer().isZooKeeperAware() && !rb.req.getCore().getSolrCoreState().isRecoverying()) {
         rb.req.getCore().getSolrCoreState().doRecovery(rb.req.getCore().getCoreContainer(), rb.req.getCore().getCoreDescriptor());
       }
     } catch (IOException e) {
diff --git a/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java b/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
index f785eb2..e8c9642 100644
--- a/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
+++ b/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
@@ -42,7 +42,6 @@ import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.Utils;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.schema.SchemaField;
 import org.apache.solr.update.AddUpdateCommand;
 import org.apache.solr.update.DeleteUpdateCommand;
 import org.apache.solr.update.processor.UpdateRequestProcessor;
@@ -84,16 +83,15 @@ public class JavabinLoader extends ContentStreamLoader {
     }
     UpdateRequest update = null;
     JavaBinUpdateRequestCodec.StreamingUpdateHandler handler = new JavaBinUpdateRequestCodec.StreamingUpdateHandler() {
-      private AddUpdateCommand addCmd = null;
 
       @Override
       public void update(SolrInputDocument document, UpdateRequest updateRequest, Integer commitWithin, Boolean overwrite) {
         if (document == null) {
           return;
         }
-        if (addCmd == null) {
-          addCmd = getAddCommand(req, updateRequest.getParams());
-        }
+
+        AddUpdateCommand addCmd = getAddCommand(req, updateRequest.getParams());
+
         addCmd.solrDoc = document;
         if (commitWithin != null) {
           addCmd.commitWithin = commitWithin;
@@ -109,7 +107,6 @@ public class JavabinLoader extends ContentStreamLoader {
 
         try {
           processor.processAdd(addCmd);
-          addCmd.clear();
         } catch (ZooKeeperException | IOException e) {
           throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "ERROR adding document " + addCmd.getPrintableId(), e);
         }
diff --git a/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java b/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java
index 72ee023..2c5090b 100644
--- a/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java
+++ b/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java
@@ -86,8 +86,6 @@ public interface SolrQueryRequest extends AutoCloseable {
   public IndexSchema getSchema();
 
   /** Replaces the current schema snapshot with the latest from the core. */
-  public void updateSchemaToLatest(IndexSchema schema);
-
   public void updateSchemaToLatest();
 
   /**
diff --git a/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java b/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java
index 81d022a..c461af3 100644
--- a/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java
+++ b/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java
@@ -139,12 +139,6 @@ public abstract class SolrQueryRequestBase implements SolrQueryRequest, Closeabl
   }
 
   @Override
-  public void updateSchemaToLatest(IndexSchema schema) {
-    this.schema = schema;
-    //this.core.setLatestSchema(schema);
-  }
-
-  @Override
   public void updateSchemaToLatest() {
     this.schema = core.getLatestSchema();
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index 93796b9..a54a6b6 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -758,8 +758,9 @@ public class IndexSchema {
     // in DocumentBuilder.getDoc()
     requiredFields.addAll(fieldsWithDefaultValue);
 
-
-    Collections.sort(dynamicFields);
+    synchronized (dynamicFields) {
+      Collections.sort(dynamicFields);
+    }
     return explicitRequiredProp;
   }
 
@@ -866,7 +867,9 @@ public class IndexSchema {
         addDynamicFieldNoDupCheck(dynFields, field);
       }
     }
-    dynamicFields.addAll(dynFields);
+    synchronized (dynamicFields) {
+      dynamicFields.addAll(dynFields);
+    }
   }
 
   private void addDynamicFieldNoDupCheck(List<DynamicField> dFields, SchemaField f) {
@@ -926,28 +929,30 @@ public class IndexSchema {
     
     if (null == destSchemaField || (null == sourceSchemaField && ! sourceIsExplicitFieldGlob)) {
       // Go through dynamicFields array only once, collecting info for both source and dest fields, if needed
-      for (DynamicField dynamicField : dynamicFields) {
-        if (null == sourceSchemaField && ! sourceIsDynamicFieldReference && ! sourceIsExplicitFieldGlob) {
-          if (dynamicField.matches(source)) {
-            sourceIsDynamicFieldReference = true;
-            if ( ! source.equals(dynamicField.getRegex())) {
-              sourceDynamicBase = dynamicField;
+      synchronized (dynamicFields) {
+        for (DynamicField dynamicField : dynamicFields) {
+          if (null == sourceSchemaField && !sourceIsDynamicFieldReference && !sourceIsExplicitFieldGlob) {
+            if (dynamicField.matches(source)) {
+              sourceIsDynamicFieldReference = true;
+              if (!source.equals(dynamicField.getRegex())) {
+                sourceDynamicBase = dynamicField;
+              }
             }
           }
-        }
-        if (null == destSchemaField) {
-          if (dest.equals(dynamicField.getRegex())) {
-            destDynamicField = dynamicField;
-            destSchemaField = dynamicField.prototype;
-          } else if (dynamicField.matches(dest)) {
-            destSchemaField = dynamicField.makeSchemaField(dest);
-            destDynamicField = new DynamicField(destSchemaField);
-            destDynamicBase = dynamicField;
+          if (null == destSchemaField) {
+            if (dest.equals(dynamicField.getRegex())) {
+              destDynamicField = dynamicField;
+              destSchemaField = dynamicField.prototype;
+            } else if (dynamicField.matches(dest)) {
+              destSchemaField = dynamicField.makeSchemaField(dest);
+              destDynamicField = new DynamicField(destSchemaField);
+              destDynamicBase = dynamicField;
+            }
+          }
+          if (null != destSchemaField
+                  && (null != sourceSchemaField || sourceIsDynamicFieldReference || sourceIsExplicitFieldGlob)) {
+            break;
           }
-        }
-        if (null != destSchemaField 
-            && (null != sourceSchemaField || sourceIsDynamicFieldReference || sourceIsExplicitFieldGlob)) {
-          break;
         }
       }
     }
@@ -1186,17 +1191,21 @@ public class IndexSchema {
   public SchemaField[] getDynamicFieldPrototypes() {
     SchemaField[] df = new SchemaField[dynamicFields.size()];
     int[] cnt = new int[]{0};
-    dynamicFields.forEach(dynamicField -> {
+    synchronized (dynamicFields) {
+      dynamicFields.forEach(dynamicField -> {
         df[cnt[0]] = dynamicFields.get(cnt[0]++).prototype;
-    });
+      });
+    }
     return df;
   }
 
   public String getDynamicPattern(String fieldName) {
-   for (DynamicField df : dynamicFields) {
-     if (df.matches(fieldName)) return df.getRegex();
-   }
-   return  null;
+    synchronized (dynamicFields) {
+      for (DynamicField df : dynamicFields) {
+        if (df.matches(fieldName)) return df.getRegex();
+      }
+      return null;
+    }
   }
   
   /**
@@ -1209,9 +1218,10 @@ public class IndexSchema {
     if (fields.containsKey(fieldName)) {
       return true;
     }
-
-    for (DynamicField df : dynamicFields) {
-      if (fieldName.equals(df.getRegex())) return true;
+    synchronized (dynamicFields) {
+      for (DynamicField df : dynamicFields) {
+        if (fieldName.equals(df.getRegex())) return true;
+      }
     }
 
     return false;
@@ -1225,9 +1235,10 @@ public class IndexSchema {
     if(fields.containsKey(fieldName)) {
       return false;
     }
-
-    for (DynamicField df : dynamicFields) {
-      if (df.matches(fieldName)) return true;
+    synchronized (dynamicFields) {
+      for (DynamicField df : dynamicFields) {
+        if (df.matches(fieldName)) return true;
+      }
     }
 
     return false;
@@ -1248,11 +1259,12 @@ public class IndexSchema {
     if (f != null) return f;
     f = dynamicFieldCache.get(fieldName);
     if (f != null) return f;
-
-    for (DynamicField df : dynamicFields) {
-      if (df.matches(fieldName)) {
-        dynamicFieldCache.put(fieldName, f = df.makeSchemaField(fieldName));
-        break;
+    synchronized (dynamicFields) {
+      for (DynamicField df : dynamicFields) {
+        if (df.matches(fieldName)) {
+          dynamicFieldCache.put(fieldName, f = df.makeSchemaField(fieldName));
+          break;
+        }
       }
     }
 
@@ -1345,15 +1357,19 @@ public class IndexSchema {
    * @see #getFieldTypeNoEx
    */
   public FieldType getDynamicFieldType(String fieldName) {
-     for (DynamicField df : dynamicFields) {
-      if (df.matches(fieldName)) return df.prototype.getType();
+    synchronized (dynamicFields) {
+      for (DynamicField df : dynamicFields) {
+        if (df.matches(fieldName)) return df.prototype.getType();
+      }
     }
     throw new SolrException(ErrorCode.BAD_REQUEST,"undefined field "+fieldName);
   }
 
   private FieldType dynFieldType(String fieldName) {
-     for (DynamicField df : dynamicFields) {
-      if (df.matches(fieldName)) return df.prototype.getType();
+    synchronized (dynamicFields) {
+      for (DynamicField df : dynamicFields) {
+        if (df.matches(fieldName)) return df.prototype.getType();
+      }
     }
     return null;
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
index bb4d3c1..bd437b8 100644
--- a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
@@ -77,6 +77,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
 
 /** Solr-managed schema - non-user-editable, but can be mutable via internal and external REST API requests. */
 public final class ManagedIndexSchema extends IndexSchema {
@@ -326,7 +327,11 @@ public final class ManagedIndexSchema extends IndexSchema {
     return activeReplicaCoreUrls;
   }
 
-  private static class GetZkSchemaVersionCallable extends SolrRequest implements Callable<Integer> {
+    public ReentrantLock getSchemaLock() {
+      return managedIndexSchemaFactory.getSchemaUpdateLock();
+    }
+
+    private static class GetZkSchemaVersionCallable extends SolrRequest implements Callable<Integer> {
 
     private final ConnectionManager.IsClosed isClosed;
     private final Http2SolrClient solrClient;
@@ -628,7 +633,9 @@ public final class ManagedIndexSchema extends IndexSchema {
           throw new FieldExistsException(ErrorCode.BAD_REQUEST, msg);
         }
         dFields.add(new DynamicField(newDynamicField));
-        newSchema.dynamicFields.addAll(dFields);
+        synchronized (dynamicFields) {
+          newSchema.dynamicFields.addAll(dFields);
+        }
 
         Collection<String> copyFields = copyFieldNames.get(newDynamicField.getName());
         if (copyFields != null) {
@@ -671,51 +678,52 @@ public final class ManagedIndexSchema extends IndexSchema {
       List<DynamicCopy> dynamicCopyFieldsToRebuild = new ArrayList<>();
       List<DynamicCopy> newDynamicCopyFields = new ArrayList<>();
 
-      for (String fieldNamePattern : fieldNamePatterns) {
-        DynamicField dynamicField = null;
-        int dfPos = 0;
-        for ( ; dfPos < newSchema.dynamicFields.size() ; ++dfPos) {
-          DynamicField df = newSchema.dynamicFields.get(dfPos);
-          if (df.getRegex().equals(fieldNamePattern)) {
-            dynamicField = df;
-            break;
+      synchronized (dynamicFields) {
+        for (String fieldNamePattern : fieldNamePatterns) {
+          DynamicField dynamicField = null;
+          int dfPos = 0;
+          for (; dfPos < newSchema.dynamicFields.size(); ++dfPos) {
+            DynamicField df = newSchema.dynamicFields.get(dfPos);
+            if (df.getRegex().equals(fieldNamePattern)) {
+              dynamicField = df;
+              break;
+            }
           }
-        }
-        if (null == dynamicField) {
-          String msg = "The dynamic field '" + fieldNamePattern
-              + "' is not present in this schema, and so cannot be deleted.";
-          throw new SolrException(ErrorCode.BAD_REQUEST, msg);
-        }          
-        for (int i = 0 ; i < newSchema.dynamicCopyFields.length ; ++i) {
-          DynamicCopy dynamicCopy = newSchema.dynamicCopyFields[i];
-          DynamicField destDynamicBase = dynamicCopy.getDestDynamicBase();
-          DynamicField sourceDynamicBase = dynamicCopy.getSourceDynamicBase();
-          if ((null != destDynamicBase && fieldNamePattern.equals(destDynamicBase.getRegex()))
-              || (null != sourceDynamicBase && fieldNamePattern.equals(sourceDynamicBase.getRegex()))
-              || dynamicField.matches(dynamicCopy.getRegex())
-              || dynamicField.matches(dynamicCopy.getDestFieldName())) {
-            dynamicCopyFieldsToRebuild.add(dynamicCopy);
-            newSchema.decrementCopyFieldTargetCount(dynamicCopy.getDestination().getPrototype());
-            // don't add this dynamic copy field to newDynamicCopyFields - effectively removing it
+          if (null == dynamicField) {
+            String msg = "The dynamic field '" + fieldNamePattern
+                    + "' is not present in this schema, and so cannot be deleted.";
+            throw new SolrException(ErrorCode.BAD_REQUEST, msg);
+          }
+          for (int i = 0; i < newSchema.dynamicCopyFields.length; ++i) {
+            DynamicCopy dynamicCopy = newSchema.dynamicCopyFields[i];
+            DynamicField destDynamicBase = dynamicCopy.getDestDynamicBase();
+            DynamicField sourceDynamicBase = dynamicCopy.getSourceDynamicBase();
+            if ((null != destDynamicBase && fieldNamePattern.equals(destDynamicBase.getRegex()))
+                    || (null != sourceDynamicBase && fieldNamePattern.equals(sourceDynamicBase.getRegex()))
+                    || dynamicField.matches(dynamicCopy.getRegex())
+                    || dynamicField.matches(dynamicCopy.getDestFieldName())) {
+              dynamicCopyFieldsToRebuild.add(dynamicCopy);
+              newSchema.decrementCopyFieldTargetCount(dynamicCopy.getDestination().getPrototype());
+              // don't add this dynamic copy field to newDynamicCopyFields - effectively removing it
+            } else {
+              newDynamicCopyFields.add(dynamicCopy);
+            }
+          }
+          if (newSchema.dynamicFields.size() > 1) {
+            newSchema.dynamicFields.remove(dfPos);
           } else {
-            newDynamicCopyFields.add(dynamicCopy);
+            newSchema.dynamicFields.clear();
           }
         }
-        if (newSchema.dynamicFields.size() > 1) {
-          newSchema.dynamicFields.remove(dfPos);
-        } else {
-          newSchema.dynamicFields.clear();
-        }
-      }
-      // After removing all dynamic fields, rebuild affected dynamic copy fields.
-      // This may trigger an exception, if one of the deleted dynamic fields was the only matching source or target.
-      if (dynamicCopyFieldsToRebuild.size() > 0) {
-        newSchema.dynamicCopyFields = newDynamicCopyFields.toArray(new DynamicCopy[newDynamicCopyFields.size()]);
-        for (DynamicCopy dynamicCopy : dynamicCopyFieldsToRebuild) {
-          newSchema.registerCopyField(dynamicCopy.getRegex(), dynamicCopy.getDestFieldName(), dynamicCopy.getMaxChars());
+        // After removing all dynamic fields, rebuild affected dynamic copy fields.
+        // This may trigger an exception, if one of the deleted dynamic fields was the only matching source or target.
+        if (dynamicCopyFieldsToRebuild.size() > 0) {
+          newSchema.dynamicCopyFields = newDynamicCopyFields.toArray(new DynamicCopy[newDynamicCopyFields.size()]);
+          for (DynamicCopy dynamicCopy : dynamicCopyFieldsToRebuild) {
+            newSchema.registerCopyField(dynamicCopy.getRegex(), dynamicCopy.getDestFieldName(), dynamicCopy.getMaxChars());
+          }
         }
       }
-
       newSchema.postReadInform();
       newSchema.refreshAnalyzers();
     } else {
@@ -723,6 +731,7 @@ public final class ManagedIndexSchema extends IndexSchema {
       log.error(msg);
       throw new SolrException(ErrorCode.SERVER_ERROR, msg);
     }
+
     return newSchema;
   }
 
@@ -733,11 +742,13 @@ public final class ManagedIndexSchema extends IndexSchema {
     if (isMutable) {
       DynamicField oldDynamicField = null;
       int dfPos = 0;
-      for ( ; dfPos < dynamicFields.size() ; ++dfPos) {
-        DynamicField dynamicField = dynamicFields.get(dfPos);
-        if (dynamicField.getRegex().equals(fieldNamePattern)) {
-          oldDynamicField = dynamicField;
-          break;
+      synchronized (dynamicFields) {
+        for (; dfPos < dynamicFields.size(); ++dfPos) {
+          DynamicField dynamicField = dynamicFields.get(dfPos);
+          if (dynamicField.getRegex().equals(fieldNamePattern)) {
+            oldDynamicField = dynamicField;
+            break;
+          }
         }
       }
       if (null == oldDynamicField) {
@@ -748,10 +759,12 @@ public final class ManagedIndexSchema extends IndexSchema {
 
       newSchema = shallowCopy(true);
 
-      Iterator<DynamicField> it = newSchema.dynamicFields.iterator();
-      while (it.hasNext()) {
-        if (it.next().getRegex().equals(fieldNamePattern)) {
-          it.remove();
+      synchronized (dynamicFields) {
+        Iterator<DynamicField> it = newSchema.dynamicFields.iterator();
+        while (it.hasNext()) {
+          if (it.next().getRegex().equals(fieldNamePattern)) {
+            it.remove();
+          }
         }
       }
 
@@ -1053,10 +1066,12 @@ public final class ManagedIndexSchema extends IndexSchema {
                 + "' because it's the field type of field '" + field.getName() + "'.");
           }
         }
-        for (DynamicField dynamicField : dynamicFields) {
-          if (dynamicField.getPrototype().getType().getTypeName().equals(name)) {
-            throw new SolrException(ErrorCode.BAD_REQUEST, "Can't delete '" + name
-                + "' because it's the field type of dynamic field '" + dynamicField.getRegex() + "'.");
+        synchronized (dynamicFields) {
+          for (DynamicField dynamicField : dynamicFields) {
+            if (dynamicField.getPrototype().getType().getTypeName().equals(name)) {
+              throw new SolrException(ErrorCode.BAD_REQUEST, "Can't delete '" + name
+                      + "' because it's the field type of dynamic field '" + dynamicField.getRegex() + "'.");
+            }
           }
         }
       }
@@ -1158,10 +1173,12 @@ public final class ManagedIndexSchema extends IndexSchema {
         }
       }
       // Rebuild dynamic fields of the type being replaced
-      for (int i = 0; i < newSchema.dynamicFields.size(); ++i) {
-        SchemaField prototype = newSchema.dynamicFields.get(i).getPrototype();
-        if (typeName.equals(prototype.getType().getTypeName())) {
-          newSchema.dynamicFields.set(i, new DynamicField(SchemaField.create(prototype.getName(), replacementFieldType, prototype.getArgs())));
+      synchronized (dynamicFields) {
+        for (int i = 0; i < newSchema.dynamicFields.size(); ++i) {
+          SchemaField prototype = newSchema.dynamicFields.get(i).getPrototype();
+          if (typeName.equals(prototype.getType().getTypeName())) {
+            newSchema.dynamicFields.set(i, new DynamicField(SchemaField.create(prototype.getName(), replacementFieldType, prototype.getArgs())));
+          }
         }
       }
       // Find dynamic copy fields where the destination field's type is being replaced
@@ -1387,7 +1404,7 @@ public final class ManagedIndexSchema extends IndexSchema {
     this.managedSchemaResourceName = managedSchemaResourceName;
     this.schemaZkVersion = schemaZkVersion;
     this.collection = collection;
-    log.info("Copy to new ManagedIndexSchemaFactory with version {}", schemaZkVersion);
+    if (log.isDebugEnabled()) log.debug("Copy to new ManagedIndexSchemaFactory with version {}", schemaZkVersion);
   }
 
   /**
diff --git a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchemaFactory.java b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchemaFactory.java
index fed467a..9946cc5 100644
--- a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchemaFactory.java
+++ b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchemaFactory.java
@@ -450,8 +450,10 @@ public class ManagedIndexSchemaFactory extends IndexSchemaFactory implements Sol
   }
 
   public void setSchema(ManagedIndexSchema schema) {
-    core.setLatestSchema(schema);
-    this.schema = schema;
+    if (schema.getSchemaZkVersion() > this.schema.getSchemaZkVersion()) {
+      this.schema = schema;
+      core.setLatestSchema(schema);
+    }
   }
   
   public boolean isMutable() {
diff --git a/solr/core/src/java/org/apache/solr/schema/ZkIndexSchemaReader.java b/solr/core/src/java/org/apache/solr/schema/ZkIndexSchemaReader.java
index a82f88f..c942a4a 100644
--- a/solr/core/src/java/org/apache/solr/schema/ZkIndexSchemaReader.java
+++ b/solr/core/src/java/org/apache/solr/schema/ZkIndexSchemaReader.java
@@ -80,7 +80,7 @@ public class ZkIndexSchemaReader implements OnReconnect {
       }
     });
 
-    updateSchema(schemaWatcher, -1, solrCore);
+    updateSchema();
 
     solrCore.getCoreContainer().getZkController().addOnReconnectListener(this);
   }
@@ -122,7 +122,7 @@ public class ZkIndexSchemaReader implements OnReconnect {
       }
       log.info("A schema change: {}, has occurred - updating schema from ZooKeeper ...", event);
       try {
-        schemaReader.updateSchema(this, -1, null);
+        schemaReader.updateSchema();
       } catch (Exception e) {
         log.error("", e);
       }
@@ -144,7 +144,7 @@ public class ZkIndexSchemaReader implements OnReconnect {
 //  }
 
   // package visibility for test purposes
-  public IndexSchema updateSchema(Watcher watcher, int version, SolrCore core) throws KeeperException, InterruptedException {
+  public IndexSchema updateSchema() throws KeeperException, InterruptedException {
     ManagedIndexSchema newSchema;
     ReentrantLock  lock = getSchemaUpdateLock();
     lock.lock();
@@ -159,11 +159,8 @@ public class ZkIndexSchemaReader implements OnReconnect {
 
       int existsVersion = exists.getVersion();
       int v;
-      if (core != null) {
-        v = ((ManagedIndexSchema) core.getLatestSchema()).getSchemaZkVersion();
-      } else {
-        v = managedIndexSchemaFactory.getSchema().getSchemaZkVersion();
-      }
+
+      v = managedIndexSchemaFactory.getSchema().getSchemaZkVersion();
 
       log.info("Retrieved schema version {} from Zookeeper, existing={} schema={}", existsVersion, v, managedIndexSchemaFactory.getSchema());
 
@@ -181,9 +178,6 @@ public class ZkIndexSchemaReader implements OnReconnect {
       newSchema = new ManagedIndexSchema(managedIndexSchemaFactory, collection, managedIndexSchemaFactory.getConfig(), resourceName, inputSource, managedIndexSchemaFactory.isMutable(), resourceName,
           stat.getVersion());
       managedIndexSchemaFactory.setSchema(newSchema);
-      if (core != null) {
-        core.setLatestSchema(newSchema);
-      }
 
       long stop = System.nanoTime();
       log.info("Finished refreshing schema in {} ms", TimeUnit.MILLISECONDS.convert(stop - start, TimeUnit.NANOSECONDS));
@@ -204,7 +198,7 @@ public class ZkIndexSchemaReader implements OnReconnect {
   public void command() {
     try {
       // force update now as the schema may have changed while our zk session was expired
-      updateSchema(schemaWatcher, -1, null);
+      updateSchema();
     } catch (Exception exc) {
       log.error("Failed to update managed-schema watcher after session expiration due to: {}", exc);
     }
diff --git a/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java b/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java
index a877eed..475abe4 100644
--- a/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java
+++ b/solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java
@@ -363,7 +363,7 @@ public final class DefaultSolrCoreState extends SolrCoreState implements Recover
         if (!locked) {
           recoveryWaiting.incrementAndGet();
           if (log.isDebugEnabled()) log.debug("Wait for recovery lock");
-
+          cancelRecovery();
           while (!recoveryLock.tryLock(250, TimeUnit.MILLISECONDS)) {
             if (closed || prepForClose) {
               log.warn("Skipping recovery because we are closed");
@@ -486,7 +486,7 @@ public final class DefaultSolrCoreState extends SolrCoreState implements Recover
     // though
     // iwLock.writeLock().lock();
     if (recoverying) {
-      cancelRecovery();
+      cancelRecovery(false, true);
     }
     try {
       closeIndexWriter(closer);
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateCommand.java b/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
index b124271..a91cf25 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
@@ -18,14 +18,13 @@ package org.apache.solr.update;
 
 import org.apache.solr.request.SolrQueryRequest;
 
-
 /** An index update command encapsulated in an object (Command pattern)
  *
  *
  */
 public abstract class UpdateCommand implements Cloneable {
   protected SolrQueryRequest req;
-  protected long version;
+  protected volatile long version;
   protected String route;
   protected int flags;
 
@@ -62,6 +61,7 @@ public abstract class UpdateCommand implements Cloneable {
   public long getVersion() {
     return version;
   }
+
   public void setVersion(long version) {
     this.version = version;
   }
diff --git a/solr/core/src/java/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactory.java
index 3053feb..3a26571 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactory.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactory.java
@@ -509,7 +509,7 @@ public class AddSchemaFieldsUpdateProcessorFactory extends UpdateRequestProcesso
           cmd.getReq().updateSchemaToLatest();
         } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
           try {
-            ((ManagedIndexSchema) cmd.getReq().getSchema()).getManagedIndexSchemaFactory().getZkIndexSchemaReader().updateSchema(null, -1, cmd.getReq().getCore());
+            ((ManagedIndexSchema) cmd.getReq().getSchema()).getManagedIndexSchemaFactory().getZkIndexSchemaReader().updateSchema();
             cmd.getReq().updateSchemaToLatest();
 
             log.info("Schema changed while processing request ... current latest version {} try={}", ((ManagedIndexSchema) cmd.getReq().getSchema()).getSchemaZkVersion(), cnt);
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java
index 1cf2d3b..abd6edd 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionTest.java
@@ -102,13 +102,14 @@ public class LeaderElectionTest extends SolrTestCaseJ4 {
     }
 
     @Override
-    void runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs)
+    boolean runLeaderProcess(ElectionContext context, boolean weAreReplacement, int pauseBeforeStartMs)
         throws KeeperException, InterruptedException, IOException {
       super.runLeaderProcess(context, weAreReplacement, pauseBeforeStartMs);
       if (runLeaderDelay > 0) {
         log.info("Sleeping for {}ms to simulate leadership takeover delay", runLeaderDelay);
         Thread.sleep(runLeaderDelay);
       }
+      return true;
     }
   }
 
diff --git a/solr/core/src/test/org/apache/solr/cloud/MissingSegmentRecoveryTest.java b/solr/core/src/test/org/apache/solr/cloud/MissingSegmentRecoveryTest.java
index 4e19bf1..c0907f2 100644
--- a/solr/core/src/test/org/apache/solr/cloud/MissingSegmentRecoveryTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/MissingSegmentRecoveryTest.java
@@ -112,7 +112,8 @@ public class MissingSegmentRecoveryTest extends SolrCloudTestCase {
     JettySolrRunner jetty = cluster.getReplicaJetty(replica);
     jetty.stop();
     jetty.start();
-    
+
+    cluster.waitForActiveCollection(collection, 1, 2);
     QueryResponse resp = cluster.getSolrClient().query(collection, new SolrQuery("*:*"));
     assertEquals(10, resp.getResults().getNumFound());
   }
diff --git a/solr/core/src/test/org/apache/solr/schema/SchemaWatcherTest.java b/solr/core/src/test/org/apache/solr/schema/SchemaWatcherTest.java
index 5f34c45..321f41b 100644
--- a/solr/core/src/test/org/apache/solr/schema/SchemaWatcherTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/SchemaWatcherTest.java
@@ -44,7 +44,7 @@ public class SchemaWatcherTest {
   @Test
   public void testProcess() throws Exception {
     schemaWatcher.process(new WatchedEvent(EventType.NodeDataChanged, KeeperState.SyncConnected, "/test"));
-    verify(mockSchemaReader).updateSchema(schemaWatcher, -1, null);
+    verify(mockSchemaReader).updateSchema();
   }
 
 }
diff --git a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
index a230461..730f799 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
@@ -657,9 +657,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
    */
   private static SortedSet<String> dynFieldRegexesForType(final Class<? extends FieldType> clazz) {
     SortedSet<String> typesToTest = new TreeSet<>();
-    for (DynamicField dynField : h.getCore().getLatestSchema().getDynamicFields()) {
-      if (clazz.isInstance(dynField.getPrototype().getType())) {
-        typesToTest.add(dynField.getRegex());
+    synchronized (h.getCore().getLatestSchema().getDynamicFields()) {
+      for (DynamicField dynField : h.getCore().getLatestSchema().getDynamicFields()) {
+        if (clazz.isInstance(dynField.getPrototype().getType())) {
+          typesToTest.add(dynField.getRegex());
+        }
       }
     }
     return typesToTest;
@@ -2326,9 +2328,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
       }
     }
     Set<String> typesToTest = new HashSet<>();
-    for (DynamicField dynField:h.getCore().getLatestSchema().getDynamicFields()) {
-      if (dynField.getPrototype().getType() instanceof PointField) {
-        typesToTest.add(dynField.getRegex());
+    synchronized (h.getCore().getLatestSchema().getDynamicFields()) {
+      for (DynamicField dynField : h.getCore().getLatestSchema().getDynamicFields()) {
+        if (dynField.getPrototype().getType() instanceof PointField) {
+          typesToTest.add(dynField.getRegex());
+        }
       }
     }
     assertEquals("Missing types in the test", typesTested, typesToTest);
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
index 78b860a..ff87426 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
@@ -2658,7 +2658,7 @@ public class ZkStateReader implements SolrCloseable, Replica.NodeNameToBaseUrl {
       }
 
       if (expectedReplicas == 0 && !exact) {
-        log.info("0 replicaes expected and found, return");
+        log.info("0 replicas expected and found, return");
         return true;
       }
 
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java
index 282b88d..59569a0 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java
@@ -50,8 +50,9 @@ public class ConcurrentUpdateSolrClientBuilderTest extends SolrTestCase {
    * Test that connection timeout information is passed to the HttpSolrClient that handles non add operations.
    */
   @Test(timeout = 10000)
+  @Nightly
   public void testSocketTimeoutOnCommit() throws IOException, SolrServerException {
-    InetAddress localHost = InetAddress.getLocalHost();
+    InetAddress localHost = InetAddress.getLocalHost(); // this can fail java.net.BindException: Can't assign requested address (Bind failed) (seen on OSX)
     try (ServerSocket server = new ServerSocket(0, 1, localHost);
          ConcurrentUpdateSolrClient client = new ConcurrentUpdateSolrClient.Builder(
              "http://" + localHost.getHostAddress() + ":" + server.getLocalPort() + "/noOneThere")