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/02/27 11:53:15 UTC

[lucene-solr] branch reference_impl_dev updated: @1415 "You're tense, I'm calm. You apply excessive force; I control that force through fluid motion. That means relaxing the whole body so it can react instantly without resistance-no, without thought. Do you see now? It means becoming like clear water."

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


The following commit(s) were added to refs/heads/reference_impl_dev by this push:
     new b582415  @1415 "You're tense, I'm calm. You apply excessive force; I control that force through fluid motion. That means relaxing the whole body so it can react instantly without resistance-no, without thought. Do you see now? It means becoming like clear water."
b582415 is described below

commit b582415fa3df9ede87fb37ac79b6feb4516067dd
Author: markrmiller@gmail.com <ma...@gmail.com>
AuthorDate: Sat Feb 27 05:52:44 2021 -0600

    @1415 "You're tense, I'm calm. You apply excessive force; I control that force through fluid motion. That means relaxing the whole body so it can react instantly without resistance-no, without thought. Do you see now? It means becoming like clear water."
    
    Took 2 hours 16 minutes
---
 .../src/java/org/apache/solr/cloud/Overseer.java   |  6 +-
 .../solr/cloud/ShardLeaderElectionContext.java     |  2 +-
 .../solr/cloud/ShardLeaderElectionContextBase.java |  2 +-
 .../java/org/apache/solr/cloud/ZkController.java   |  7 +-
 .../java/org/apache/solr/cloud/ZkShardTerms.java   |  4 +-
 .../apache/solr/cloud/ZkSolrResourceLoader.java    |  4 ++
 .../apache/solr/cloud/overseer/ZkStateWriter.java  | 13 ++--
 .../org/apache/solr/core/ConfigSetService.java     | 12 ++--
 .../java/org/apache/solr/core/CoreContainer.java   |  4 +-
 .../src/java/org/apache/solr/core/SolrCore.java    | 19 +++---
 .../org/apache/solr/core/SolrResourceLoader.java   |  2 +-
 .../java/org/apache/solr/core/XmlConfigFile.java   | 45 +++++++++++--
 .../apache/solr/cloud/CollectionsAPISolrJTest.java |  2 +-
 .../solr/client/solrj/impl/Http2SolrClient.java    |  8 +--
 .../src/java/org/apache/solr/common/ParWork.java   |  2 +-
 .../solr/common/cloud/ConnectionManager.java       |  6 +-
 .../src/resources/logconf/log4j2-std.xml           | 77 ++++++++++++++++++++++
 17 files changed, 169 insertions(+), 46 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index 88db849..2d42625 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -744,11 +744,7 @@ public class Overseer implements SolrCloseable {
   }
 
   public void writePendingUpdates() {
-    if (zkStateWriter != null) {
-      new OverseerTaskExecutorTask.WriteTask(getCoreContainer(), zkStateWriter).run();
-    } else {
-      throw new AlreadyClosedException("No longer Overseer it seems, won't write pending updates");
-    }
+    new OverseerTaskExecutorTask.WriteTask(getCoreContainer(), zkStateWriter).run();
   }
 
   private static abstract class QueueWatcher implements Watcher, Closeable {
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 91533b5..5bf92b4 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java
@@ -144,7 +144,7 @@ final class ShardLeaderElectionContext extends ShardLeaderElectionContextBase {
         try {
           if (zkShardTerms != null) {
             //  guarantees that a live-fetch will be enough for this core to see max term published
-            log.info("refresh shard terms for core {}", coreName);
+            if (log.isDebugEnabled()) log.debug("refresh shard terms for core {}", coreName);
             zkShardTerms.refreshTerms(false, -1);
           }
         } catch (Exception e) {
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 d8ce0d6..ab1515a 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContextBase.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContextBase.java
@@ -157,7 +157,7 @@ class ShardLeaderElectionContextBase extends ElectionContext {
           if (log.isDebugEnabled()) log.debug("Delete leader seq election path {} path we watch is {}", leaderSeqPath, watchedSeqPath);
           try {
             zkClient.delete(leaderSeqPath, -1);
-          } catch (NoNodeException e1) {
+          } catch (NoNodeException | AlreadyClosedException e1) {
             // fine
           }
         }
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 2f611d7..04bb43e 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -487,6 +487,8 @@ public class ZkController implements Closeable, Runnable {
 
               removeEphemeralLiveNode();
 
+              publishNodeAs(getNodeName(), OverseerAction.RECOVERYNODE);
+
               // recreate our watchers first so that they exist even on any problems below
               zkStateReader.createClusterStateWatchersAndUpdate();
 
@@ -1476,8 +1478,11 @@ public class ZkController implements Closeable, Runnable {
       desc.getCloudDescriptor().setHasRegistered(true);
 
       return shardId;
+    } catch (AlreadyClosedException e) {
+      log.warn("Won't register with ZooKeeper, already shutting down core={}", desc.getName());
+      throw e;
     } catch (Exception e) {
-      log.error("Error registering SolrCore with Zookeeper", e);
+      log.error("Error registering SolrCore with Zookeeper core={}", desc, e);
       throw new SolrException(ErrorCode.SERVER_ERROR, "Error registering SolrCore with Zookeeper", e);
     } 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 d113c8d..d7b5e7b 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkShardTerms.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkShardTerms.java
@@ -387,7 +387,7 @@ public class ZkShardTerms implements Closeable {
         Stat stat = new Stat();
         byte[] data = zkClient.getData(znodePath, setWatch ? watcher : null, stat, true);
         Map<String,Long> values = Collections.unmodifiableMap(new HashMap<>((Map<String,Long>) Utils.fromJSON(data)));
-        log.info("refresh shard terms to zk version {}", stat.getVersion());
+        if (log.isDebugEnabled()) log.debug("refresh shard terms to zk version {}", stat.getVersion());
         newTerms = new ShardTerms(values, stat.getVersion());
       } catch (KeeperException.NoNodeException e) {
         log.info("No node found for shard terms");
@@ -420,7 +420,7 @@ public class ZkShardTerms implements Closeable {
     int cnt = 0;
     for (;;)  {
       cnt++;
-      log.info("set new terms {} {}", newTerms, cnt);
+      if (log.isDebugEnabled()) log.debug("set new terms {} {}", newTerms, cnt);
       ShardTerms terms = this.terms.get();
       if (terms == null || newTerms.getVersion() > terms.getVersion())  {
         if (this.terms.compareAndSet(terms, newTerms))  {
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java b/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
index fab501e..f7bbccc 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java
@@ -109,6 +109,10 @@ public class ZkSolrResourceLoader extends SolrResourceLoader implements Resource
     public Stat getStat(){
       return stat;
     }
+
+    public byte[] getBytes() {
+      return buf;
+    }
   }
 
   public String getConfigSetZkPath() {
diff --git a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
index 349e7c9..3729e95 100644
--- a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
+++ b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
@@ -75,8 +75,7 @@ public class ZkStateWriter {
 
   private volatile ClusterState cs;
 
-  protected final ReentrantLock ourLock = new ReentrantLock(true);
-  protected final ReentrantLock writeLock = new ReentrantLock(true);
+  protected final ReentrantLock ourLock = new ReentrantLock();
 
   private final ActionThrottle throttle = new ActionThrottle("ZkStateWriter", Integer.getInteger("solr.zkstatewriter.throttle", 10), new TimeSource.NanoTimeSource(){
     public void sleep(long ms) throws InterruptedException {
@@ -208,7 +207,7 @@ public class ZkStateWriter {
               } else if (OverseerAction.RECOVERYNODE.equals(OverseerAction.get(entry.getKey()))) {
                 continue;
               } else {
-                log.info("state cmd entry {} asOverseerCmd={}", entry, OverseerAction.get(entry.getKey()));
+                if (log.isDebugEnabled()) log.debug("state cmd entry {} asOverseerCmd={}", entry, OverseerAction.get(entry.getKey()));
                 String core = entry.getKey();
                 String collectionAndStateString = (String) entry.getValue();
                 if (log.isDebugEnabled()) {
@@ -409,6 +408,10 @@ public class ZkStateWriter {
     // writeLock.lock();
     // try {
     //   log.info("Get our write lock");
+    if (log.isDebugEnabled()) {
+      log.debug("writePendingUpdates {}", cs);
+    }
+
     ourLock.lock();
     try {
  //     log.info("Got our write lock");
@@ -416,10 +419,6 @@ public class ZkStateWriter {
       throttle.minimumWaitBetweenActions();
       throttle.markAttemptingAction();
 
-      if (log.isTraceEnabled()) {
-        log.trace("writePendingUpdates {}", cs);
-      }
-
       if (failedUpdates.size() > 0) {
         Exception lfe = lastFailedException.get();
         log.warn("Some collection updates failed {} logging last exception", failedUpdates, lfe); // MRM TODO: expand
diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java
index 30e92b4..e88fe5e 100644
--- a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java
+++ b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java
@@ -66,18 +66,18 @@ public abstract class ConfigSetService {
    */
   @SuppressWarnings({"rawtypes"})
   public final ConfigSet loadConfigSet(CoreDescriptor dcore) {
-    StopWatch timeCreateResourceLoader = new StopWatch(dcore.getName() + "-createResourceLoader");
+    StopWatch timeCreateResourceLoader = StopWatch.getStopWatch(dcore.getName() + "-createResourceLoader");
     SolrResourceLoader coreLoader = createCoreResourceLoader(dcore);
     timeCreateResourceLoader.done();
     try {
-      StopWatch timeLoadConfigProps = new StopWatch(dcore.getName() + "-loadConfigProps");
+      StopWatch timeLoadConfigProps = StopWatch.getStopWatch(dcore.getName() + "-loadConfigProps");
       // ConfigSet properties are loaded from ConfigSetProperties.DEFAULT_FILENAME file.
       NamedList properties = loadConfigSetProperties(dcore, coreLoader);
       timeLoadConfigProps.done();
       // ConfigSet flags are loaded from the metadata of the ZK node of the configset.
 
       // there are no flags in non cloud mode, it just returns null
-      StopWatch timeLoadConfigSetFlags = new StopWatch(dcore.getName() + "-loadConfigSetFlags");
+      StopWatch timeLoadConfigSetFlags = StopWatch.getStopWatch(dcore.getName() + "-loadConfigSetFlags");
       NamedList flags = null;
       try {
         flags = loadConfigSetFlags(dcore, coreLoader);
@@ -89,14 +89,14 @@ public abstract class ConfigSetService {
       boolean trusted = !(coreLoader instanceof ZkSolrResourceLoader) || flags == null || flags.get("trusted") == null || flags.getBooleanArg("trusted");
 
       if (log.isDebugEnabled()) log.debug("Trusted configset={} {}", trusted, flags);
-      StopWatch timeCreateSolrConfig = new StopWatch(dcore.getName() + "-createSolrConfig");
+      StopWatch timeCreateSolrConfig = StopWatch.getStopWatch(dcore.getName() + "-createSolrConfig");
       SolrConfig solrConfig = createSolrConfig(dcore, coreLoader, trusted);
       timeCreateSolrConfig.done();
-      StopWatch timeCreateSchema = new StopWatch(dcore.getName() + "-createSchema");
+      StopWatch timeCreateSchema = StopWatch.getStopWatch(dcore.getName() + "-createSchema");
       IndexSchema schema = createIndexSchema(dcore, solrConfig);
       timeCreateSchema.done();
 
-      StopWatch timeCreateConfigSet = new StopWatch(dcore.getName() + "-createConfigSet");
+      StopWatch timeCreateConfigSet = StopWatch.getStopWatch(dcore.getName() + "-createConfigSet");
       ConfigSet configSet = new ConfigSet(configSetName(dcore), solrConfig, schema, properties, trusted);
       timeCreateConfigSet.done();
 
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 b4078f1..fbdf554 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -191,10 +191,10 @@ public class CoreContainer implements Closeable {
   private volatile UpdateShardHandler updateShardHandler;
 
   public final ThreadPoolExecutor solrCoreExecutor = (ThreadPoolExecutor) ParWork.getParExecutorService("Core",
-      4, Math.max(6, SysStats.PROC_COUNT * 2), 1000, new BlockingArrayQueue<>(256, 256));
+      4, 256, 1000, new BlockingArrayQueue<>(64, 64));
 
   public final ThreadPoolExecutor coreContainerExecutor = (ThreadPoolExecutor) ParWork.getParExecutorService("Core",
-      8, SysStats.PROC_COUNT, 1000, new BlockingArrayQueue<>(256, 256));
+      4, SysStats.PROC_COUNT * 2, 1000, new BlockingArrayQueue<>(64, 64));
 
   {
     solrCoreExecutor.prestartAllCoreThreads();
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 ac1bc5f..6e2e9a8 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -176,6 +176,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Condition;
@@ -1219,16 +1220,12 @@ public final class SolrCore implements SolrInfoBean, Closeable {
       // Processors initialized before the handlers
       updateProcessorChains = loadUpdateProcessorChains();
 
-      future.get();
-
       // Finally tell anyone who wants to know
       StopWatch timeInform = StopWatch.getStopWatch(this + "-startCore-inform");
       this.updateHandler.informEventListeners(this);
       resourceLoader.inform(resourceLoader);
-      resourceLoader.inform(this); // last call before the latch is released.
       timeInform.done();
 
-      searcherReadyLatch.countDown();
       // this must happen after the latch is released, because a JMX server impl may
       // choose to block on registering until properties can be fetched from an MBean,
       // and a SolrCoreAware MBean may have properties that depend on getting a Searcher
@@ -1237,6 +1234,12 @@ public final class SolrCore implements SolrInfoBean, Closeable {
       resourceLoader.inform(infoRegistry);
       timeRInform.done();
 
+      future.get(120, TimeUnit.SECONDS);
+
+      resourceLoader.inform(this); // last call before the latch is released.
+
+      searcherReadyLatch.countDown();
+
       // seed version buckets with max from index during core initialization ... requires a searcher!
       StopWatch timeWaitForSearcher = StopWatch.getStopWatch(this + "-startCore-waitForSearcher");
       // MRM TODO: - wait before publish active?
@@ -1273,11 +1276,11 @@ public final class SolrCore implements SolrInfoBean, Closeable {
       }
       timeReloadAndDirChange.done();
 
-     // if (!isReloaded || dirChanged) { // MRM TODO: reload could move to a different index?
+      if (!isReloaded || dirChanged) { // MRM TODO: reload could move to a different index?
         StopWatch timeSeedVersions = StopWatch.getStopWatch(this + "-startCore-seedVersions");
         seedVersionBuckets();
         timeSeedVersions.done();
-     // }
+      }
 
       StopWatch timeRegConfListener = StopWatch.getStopWatch(this + "-startCore-regConfListener");
       registerConfListener();
@@ -1306,8 +1309,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
 //      }
       try {
         throw e;
-      } catch (IOException | InterruptedException | ExecutionException ioException) {
-        throw new SolrException(ErrorCode.SERVER_ERROR, ioException);
+      } catch (IOException | InterruptedException | ExecutionException | TimeoutException exception) {
+        throw new SolrException(ErrorCode.SERVER_ERROR, exception);
       }
     } finally {
       timeStartCore.done();
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index 65ccda6..c7046d8 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -872,7 +872,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable {
    */
   public void inform(SolrCore core) {
     while (waitingForCore.size() > 0) {
-      try (ParWork worker = new ParWork(this, false, false)) {
+      try (ParWork worker = new ParWork(this, false, true)) {
         waitingForCore.forEach(aware -> {
           worker.collect("informSolrCore", ()-> {
             try {
diff --git a/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java b/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java
index 8666515..7772732 100644
--- a/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java
+++ b/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java
@@ -23,6 +23,7 @@ import net.sf.saxon.lib.Validation;
 import net.sf.saxon.om.NodeInfo;
 import net.sf.saxon.trans.XPathException;
 import net.sf.saxon.tree.tiny.TinyDocumentImpl;
+import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.solr.cloud.ZkSolrResourceLoader;
 import org.apache.solr.common.ParWork;
 import org.apache.solr.common.SolrException;
@@ -30,7 +31,8 @@ import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.StopWatch;
 import org.apache.solr.common.util.XMLErrorLogger;
 import org.apache.solr.util.DOMUtil;
-import org.apache.solr.util.SystemIdResolver;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
@@ -48,6 +50,7 @@ import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -67,6 +70,15 @@ public class XmlConfigFile { // formerly simply "Config"
 
   public static final XMLErrorLogger xmllog = new XMLErrorLogger(log);
 
+  private static Map CONFIG_CACHE = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK) {
+    {
+      purgeBeforeRead();
+      purgeBeforeWrite();
+    }
+  };
+
+  private static Map<String, ZkSolrResourceLoader.ZkByteArrayInputStream> SYNC_CONFIG_CACHE = Collections.synchronizedMap(CONFIG_CACHE);
+
   protected final String prefix;
   private final String name;
   protected final SolrResourceLoader loader;
@@ -115,18 +127,41 @@ public class XmlConfigFile { // formerly simply "Config"
     this.name = name;
     this.prefix = (prefix != null && !prefix.endsWith("/")) ? prefix + '/' : prefix;
 
-    StopWatch parseXmlFile = new StopWatch(name + "-parseXmlFile");
+    StopWatch parseXmlFile = StopWatch.getStopWatch(name + "-parseXmlFile");
     if (is == null) {
       if (name == null || name.length() == 0) {
         throw new IllegalArgumentException("Null or empty name:" + name);
       }
-      InputStream in = loader.openResource(name);
+
+      InputStream in = null;
+
+      if (loader instanceof  ZkSolrResourceLoader) {
+        ZkSolrResourceLoader.ZkByteArrayInputStream cached = SYNC_CONFIG_CACHE.get(name);
+        if (cached != null) {
+          Stat checkStat;
+          try {
+            checkStat = ((ZkSolrResourceLoader) loader).getZkClient().exists(loader.getConfigDir() + "/" + name, null);
+          } catch (KeeperException | InterruptedException e) {
+            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
+          }
+          if (checkStat != null && checkStat.getVersion() <- cached.getStat().getVersion()) {
+            in = new ZkSolrResourceLoader.ZkByteArrayInputStream(cached.getBytes(), cached.getStat());
+          }
+        }
+      }
+      if (in == null) {
+        in = loader.openResource(name);
+      }
+      
       if (in instanceof ZkSolrResourceLoader.ZkByteArrayInputStream) {
+        SYNC_CONFIG_CACHE.put(name, (ZkSolrResourceLoader.ZkByteArrayInputStream) in);
         zkVersion = ((ZkSolrResourceLoader.ZkByteArrayInputStream) in).getStat().getVersion();
-        log.debug("loaded config {} with version {} ", name, zkVersion);
+        if (log.isDebugEnabled()) {
+          log.debug("loaded config {} with version {} ", name, zkVersion);
+        }
       }
       is = new InputSource(in);
-      is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(name));
+   //   is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(name));
     }
 
     try {
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
index 9847f1c..d6fe96d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
@@ -244,7 +244,7 @@ public class CollectionsAPISolrJTest extends SolrCloudTestCase {
   @Ignore // MRM TODO: - testing large numbers
   public void testCreateAndDeleteCollection() throws Exception {
     String collectionName = "solrj_test";
-    CollectionAdminResponse response = CollectionAdminRequest.createCollection(collectionName, "conf", 12, 12)
+    CollectionAdminResponse response = CollectionAdminRequest.createCollection(collectionName, "conf", 24, 24) // 24 * 24 = 576
             .process(cluster.getSolrClient());
 
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java
index 6c83b00..c59e680 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java
@@ -249,7 +249,7 @@ public class Http2SolrClient extends SolrClient {
       } else {
         if (log.isTraceEnabled()) log.trace("Create Http2SolrClient with HTTP/1.1 transport");
       }
-      SolrHttpClientTransportOverHTTP transport = new SolrHttpClientTransportOverHTTP(3);
+      SolrHttpClientTransportOverHTTP transport = new SolrHttpClientTransportOverHTTP(4);
       httpClient = new SolrInternalHttpClient(transport, sslContextFactory);
     } else {
       if (log.isTraceEnabled()) log.trace("Create Http2SolrClient with HTTP/2 transport");
@@ -265,7 +265,7 @@ public class Http2SolrClient extends SolrClient {
 //          }
 
       HTTP2Client http2client = new HTTP2Client();
-      http2client.setSelectors(3);
+      http2client.setSelectors(4);
       http2client.setMaxConcurrentPushedStreams(512);
       http2client.setInputBufferSize(8192);
       HttpClientTransportOverHTTP2 transport = new HttpClientTransportOverHTTP2(http2client);
@@ -1142,7 +1142,7 @@ public class Http2SolrClient extends SolrClient {
 
   public static class Builder {
 
-    public static int DEFAULT_MAX_THREADS = Integer.getInteger("solr.maxHttp2ClientThreads", Math.max(12, PROC_COUNT * 2));
+    public static int DEFAULT_MAX_THREADS = Integer.getInteger("solr.maxHttp2ClientThreads", Math.max(32, 512));
     private static final Integer DEFAULT_IDLE_TIME = Integer.getInteger("solr.http2solrclient.default.idletimeout", 120000);
     public int maxThreadPoolSize = DEFAULT_MAX_THREADS;
     public int maxRequestsQueuedPerDestination = 1600;
@@ -1150,7 +1150,7 @@ public class Http2SolrClient extends SolrClient {
     private SSLConfig sslConfig = defaultSSLConfig;
     private Integer idleTimeout = DEFAULT_IDLE_TIME;
     private Integer connectionTimeout;
-    private Integer maxConnectionsPerHost = 32;
+    private Integer maxConnectionsPerHost = 12;
     private boolean useHttp1_1 = Boolean.getBoolean("solr.http1");
     protected String baseSolrUrl;
     protected Map<String,String> headers = new HashMap<>(6);
diff --git a/solr/solrj/src/java/org/apache/solr/common/ParWork.java b/solr/solrj/src/java/org/apache/solr/common/ParWork.java
index 4cdbe06..4e2201c 100644
--- a/solr/solrj/src/java/org/apache/solr/common/ParWork.java
+++ b/solr/solrj/src/java/org/apache/solr/common/ParWork.java
@@ -435,7 +435,7 @@ public class ParWork implements Closeable {
         Integer minThreads;
         Integer maxThreads;
         minThreads = 4;
-        maxThreads = PROC_COUNT / 2;
+        maxThreads = PROC_COUNT;
         exec = getExecutorService(Math.max(minThreads, maxThreads)); // keep alive directly affects how long a worker might
        // ((PerThreadExecService)exec).closeLock(true);
         // be stuck in poll without an enqueue on shutdown
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java
index 1716b5f..350a9b8 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ConnectionManager.java
@@ -161,6 +161,10 @@ public class ConnectionManager implements Watcher, Closeable {
         log.warn("Fired connected when it appears we were last in a connected state zkstate={} closed={} cmconnected={}", getKeeper().getState(), isClosed, connected);
       }
 
+      if (isClosed) {
+        return;
+      }
+
       connected = true;
       disconnectedLatch = new CountDownLatch(1);
       lastConnectedState = 1;
@@ -252,7 +256,7 @@ public class ConnectionManager implements Watcher, Closeable {
         if (isClosed()) return;
         if (log.isDebugEnabled()) log.debug("zkClient has connected");
         // MRM TODO: - maybe use root shared
-        client.zkConnManagerCallbackExecutor.execute(() -> {
+        ParWork.getRootSharedExecutor().execute(() -> {
           connected();
         });
 
diff --git a/solr/test-framework/src/resources/logconf/log4j2-std.xml b/solr/test-framework/src/resources/logconf/log4j2-std.xml
new file mode 100644
index 0000000..7e384fc
--- /dev/null
+++ b/solr/test-framework/src/resources/logconf/log4j2-std.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<!-- Configuration for asynchronous logging -->
+<Configuration>
+    <Appenders>
+
+        <Console name="STDERR_COLOR" target="SYSTEM_ERR">
+            <PatternLayout pattern="%style{%-4r}{yellow} %highlight{%maxLen{%-5p}{6}} %style{(%maxLen{%t}{8})}{yellow,bold} [%style{%X{node_name} %X{core}}{cyan}] %style{%c{1.}}{cyan} %highlight{%m %notEmpty{%ex}}\n"/>
+        </Console>
+
+        <File name="FILE" fileName="${sys:user.home}/solr-test.log" immediateFlush="false" append="false">
+            <PatternLayout pattern="%style{%-4r}{yellow} %highlight{%maxLen{%-5p}{6}} %style{(%maxLen{%t}{8})}{yellow,bold} [%style{%X{node_name} %X{core}}{cyan}] %style{%c{1.}}{cyan} %highlight{%m %notEmpty{%ex}}\n"/>
+        </File>
+
+    </Appenders>
+    <Loggers>
+        <AsyncLogger name="org.apache.zookeeper" level="WARN"/>
+        <AsyncLogger name="org.apache.zookeeper.ClientCnxn" level="ERROR"/>
+        <AsyncLogger name="org.apache.zookeeper.server.ZooKeeperCriticalThread" level="OFF"/>
+
+        <AsyncLogger name="org.apache.hadoop" level="WARN"/>
+        <AsyncLogger name="org.apache.directory" level="WARN"/>
+        <AsyncLogger name="org.apache.solr.hadoop" level="INFO"/>
+        <AsyncLogger name="org.eclipse.jetty" level="INFO"/>
+
+        <AsyncLogger name="org.apache.solr.core.SolrCore" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.core.DefaultSolrCore" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.core.SolrCoreState" level="INFO"/>
+
+        <AsyncLogger name="org.apache.solr.handler.admin.CollectionsHandler" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.api.collections.OverseerCollectionMessageHandler" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.api.collections.CreateCollectionCmd" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.overseer.ZkStateWriter" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.Overseer" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.OverseerTaskProcessor" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.ZkDistributedQueue" level="INFO"/>
+        <!-- <AsyncLogger name="org.apache.solr.common.cloud.SolrZkClient" level="DEBUG"/> -->
+        <AsyncLogger name="org.apache.solr.cloud.overseer.SliceMutator" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.client.solrj.impl.LBSolrClient" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.cloud.ZkController" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.common.cloud.ZkMaintenanceUtils" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.update.processor.DistributedZkUpdateProcessor" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.update.processor.DistributedUpdateProcessor" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.update.SolrCmdDistributor" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.update.processor.LogUpdateProcessorFactory" level="INFO"/>
+
+        <AsyncLogger name="org.apache.solr.common.ParWork" level="INFO"/>
+
+        <AsyncLogger name="org.apache.solr.update.LoggingInfoStream" level="OFF"/>
+
+        <AsyncLogger name="org.apache.solr.core.CoreContainer.Deprecation" level="OFF"/>
+
+
+        <AsyncLogger name="com.google.inject.servlet" level="INFO"/>
+        <AsyncLogger name="org.apache.solr.client.solrj.impl.Http2SolrClient" level="INFO"/>
+
+        <AsyncRoot level="INFO">
+            <AppenderRef ref="STDERR_COLOR"/>
+            <AppenderRef ref="FILE"/>
+         </AsyncRoot>
+     </Loggers>
+ </Configuration>