You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2017/07/31 02:54:40 UTC

[1/2] lucene-solr:master: SOLR-6086: Replica is active during autowarming resulting in queries being sent to a replica that may not have a registered searcher. This causes spikes in response times when adding a replica in busy clusters

Repository: lucene-solr
Updated Branches:
  refs/heads/master 8b32d6beb -> b1a65c8f5


SOLR-6086: Replica is active during autowarming resulting in queries being sent to a replica that may not have a registered searcher. This causes spikes in response times when adding a replica in busy clusters


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/90da5ce8
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/90da5ce8
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/90da5ce8

Branch: refs/heads/master
Commit: 90da5ce81cea82424dad6ba9ab1bf12d34d196e2
Parents: 8b32d6b
Author: Shalin Shekhar Mangar <sh...@apache.org>
Authored: Sun Jul 30 20:20:20 2017 +0530
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Sun Jul 30 20:20:20 2017 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   4 +
 .../org/apache/solr/cloud/ZkController.java     |  59 ++-
 .../handler/component/RealTimeGetComponent.java |   8 +-
 .../org/apache/solr/util/TestInjection.java     |  36 ++
 .../solr/cloud/TestCloudSearcherWarming.java    | 360 +++++++++++++++++++
 5 files changed, 464 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/90da5ce8/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index e5abb3b..cb6b887 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -77,6 +77,10 @@ Bug Fixes
 
 * SOLR-10944: Get expression fails to return EOF tuple (Susheel Kumar, Joel Bernstein)
 
+* SOLR-6086: Replica is active during autowarming resulting in queries being sent to a replica that
+  may not have a registered searcher. This causes spikes in response times when adding a replica
+  in busy clusters. (Ludovic Boutros, Timothy Potter, shalin)
+
 Optimizations
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/90da5ce8/solr/core/src/java/org/apache/solr/cloud/ZkController.java
----------------------------------------------------------------------
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 dee833f..a529e94 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -42,6 +42,7 @@ import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -93,8 +94,11 @@ import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrCoreInitializationException;
 import org.apache.solr.handler.admin.ConfigSetsHandlerApi;
 import org.apache.solr.logging.MDCLoggingContext;
+import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.servlet.SolrDispatchFilter;
 import org.apache.solr.update.UpdateLog;
+import org.apache.solr.util.RTimer;
+import org.apache.solr.util.RefCounted;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.KeeperException.ConnectionLossException;
@@ -1299,8 +1303,11 @@ public class ZkController {
         props.put(ZkStateReader.CORE_NODE_NAME_PROP, coreNodeName);
       }
       try (SolrCore core = cc.getCore(cd.getName())) {
+        if (core != null && state == Replica.State.ACTIVE) {
+          ensureRegisteredSearcher(core);
+        }
         if (core != null && core.getDirectoryFactory().isSharedStorage()) {
-          if (core != null && core.getDirectoryFactory().isSharedStorage()) {
+          if (core.getDirectoryFactory().isSharedStorage()) {
             props.put("dataDir", core.getDataDir());
             UpdateLog ulog = core.getUpdateHandler().getUpdateLog();
             if (ulog != null) {
@@ -1312,7 +1319,7 @@ public class ZkController {
         // The core had failed to initialize (in a previous request, not this one), hence nothing to do here.
         log.info("The core '{}' had failed to initialize before.", cd.getName());
       }
-      
+
       ZkNodeProps m = new ZkNodeProps(props);
       
       if (updateLastState) {
@@ -2511,4 +2518,52 @@ public class ZkController {
       log.warn("Could not publish node as down: " + e.getMessage());
     } 
   }
+
+  /**
+   * Ensures that a searcher is registered for the given core and if not, waits until one is registered
+   */
+  private static void ensureRegisteredSearcher(SolrCore core) throws InterruptedException {
+    if (!core.getSolrConfig().useColdSearcher) {
+      RefCounted<SolrIndexSearcher> registeredSearcher = core.getRegisteredSearcher();
+      if (registeredSearcher != null) {
+        log.debug("Found a registered searcher: {} for core: {}", registeredSearcher.get(), core);
+        registeredSearcher.decref();
+      } else  {
+        Future[] waitSearcher = new Future[1];
+        log.info("No registered searcher found for core: {}, waiting until a searcher is registered before publishing as active", core.getName());
+        final RTimer timer = new RTimer();
+        RefCounted<SolrIndexSearcher> searcher = null;
+        try {
+          searcher = core.getSearcher(false, true, waitSearcher, true);
+          boolean success = true;
+          if (waitSearcher[0] != null)  {
+            log.debug("Waiting for first searcher of core {}, id: {} to be registered", core.getName(), core);
+            try {
+              waitSearcher[0].get();
+            } catch (ExecutionException e) {
+              log.warn("Wait for a searcher to be registered for core " + core.getName() + ",id: " + core + " failed due to: " + e, e);
+              success = false;
+            }
+          }
+          if (success)  {
+            if (searcher == null) {
+              // should never happen
+              log.debug("Did not find a searcher even after the future callback for core: {}, id: {}!!!", core.getName(), core);
+            } else  {
+              log.info("Found a registered searcher: {}, took: {} ms for core: {}, id: {}", searcher.get(), timer.getTime(), core.getName(), core);
+            }
+          }
+        } finally {
+          if (searcher != null) {
+            searcher.decref();
+          }
+        }
+      }
+      RefCounted<SolrIndexSearcher> newestSearcher = core.getNewestSearcher(false);
+      if (newestSearcher != null) {
+        log.debug("Found newest searcher: {} for core: {}, id: {}", newestSearcher.get(), core.getName(), core);
+        newestSearcher.decref();
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/90da5ce8/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
----------------------------------------------------------------------
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 6d70435..85cb6f6 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
@@ -84,6 +84,7 @@ import org.apache.solr.update.IndexFingerprint;
 import org.apache.solr.update.PeerSync;
 import org.apache.solr.update.UpdateLog;
 import org.apache.solr.util.RefCounted;
+import org.apache.solr.util.TestInjection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -955,10 +956,15 @@ public class RealTimeGetComponent extends SearchComponent
   }
 
   public void processGetFingeprint(ResponseBuilder rb) throws IOException {
+    TestInjection.injectFailIndexFingerprintRequests();
+
     SolrQueryRequest req = rb.req;
     SolrParams params = req.getParams();
-    
+
     long maxVersion = params.getLong("getFingerprint", Long.MAX_VALUE);
+    if (TestInjection.injectWrongIndexFingerprint())  {
+      maxVersion = -1;
+    }
     IndexFingerprint fingerprint = IndexFingerprint.getFingerprint(req.getCore(), Math.abs(maxVersion));
     rb.rsp.add("fingerprint", fingerprint);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/90da5ce8/solr/core/src/java/org/apache/solr/util/TestInjection.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/TestInjection.java b/solr/core/src/java/org/apache/solr/util/TestInjection.java
index d7584da..422de73 100644
--- a/solr/core/src/java/org/apache/solr/util/TestInjection.java
+++ b/solr/core/src/java/org/apache/solr/util/TestInjection.java
@@ -135,6 +135,10 @@ public class TestInjection {
   public static String splitFailureBeforeReplicaCreation = null;
 
   public static String waitForReplicasInSync = "true:60";
+
+  public static String failIndexFingerprintRequests = null;
+
+  public static String wrongIndexFingerprint = null;
   
   private static Set<Timer> timers = Collections.synchronizedSet(new HashSet<Timer>());
 
@@ -152,11 +156,43 @@ public class TestInjection {
     prepRecoveryOpPauseForever = null;
     countPrepRecoveryOpPauseForever = new AtomicInteger(0);
     waitForReplicasInSync = "true:60";
+    failIndexFingerprintRequests = null;
+    wrongIndexFingerprint = null;
 
     for (Timer timer : timers) {
       timer.cancel();
     }
   }
+
+  public static boolean injectWrongIndexFingerprint() {
+    if (wrongIndexFingerprint != null)  {
+      Random rand = random();
+      if (null == rand) return true;
+
+      Pair<Boolean,Integer> pair = parseValue(wrongIndexFingerprint);
+      boolean enabled = pair.first();
+      int chanceIn100 = pair.second();
+      if (enabled && rand.nextInt(100) >= (100 - chanceIn100)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static boolean injectFailIndexFingerprintRequests()  {
+    if (failIndexFingerprintRequests != null) {
+      Random rand = random();
+      if (null == rand) return true;
+
+      Pair<Boolean,Integer> pair = parseValue(failIndexFingerprintRequests);
+      boolean enabled = pair.first();
+      int chanceIn100 = pair.second();
+      if (enabled && rand.nextInt(100) >= (100 - chanceIn100)) {
+        throw new SolrException(ErrorCode.SERVER_ERROR, "Random test index fingerprint fail");
+      }
+    }
+    return true;
+  }
   
   public static boolean injectRandomDelayInCoreCreation() {
     if (randomDelayInCoreCreation != null) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/90da5ce8/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
new file mode 100644
index 0000000..c0cd5b8
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
@@ -0,0 +1,360 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.cloud;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.response.SolrResponseBase;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.cloud.CollectionStatePredicate;
+import org.apache.solr.common.cloud.CollectionStateWatcher;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrEventListener;
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.servlet.SolrDispatchFilter;
+import org.apache.solr.util.LogLevel;
+import org.apache.solr.util.RefCounted;
+import org.apache.solr.util.TestInjection;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tests related to SOLR-6086
+ */
+@LogLevel("org.apache.solr.cloud.overseer.*=DEBUG,org.apache.solr.cloud.Overseer=DEBUG,org.apache.solr.cloud.ZkController=DEBUG")
+public class TestCloudSearcherWarming extends SolrCloudTestCase {
+  public static final AtomicReference<String> coreNodeNameRef = new AtomicReference<>(null),
+      coreNameRef = new AtomicReference<>(null);
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+  private static final AtomicInteger sleepTime = new AtomicInteger(-1);
+
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    useFactory("solr.StandardDirectoryFactory"); // necessary to find the index+tlog intact after restart
+    configureCluster(1)
+        .addConfig("conf", configset("cloud-minimal"))
+        .configure();
+  }
+
+  @Before
+  public void before() {
+    coreNameRef.set(null);
+    coreNodeNameRef.set(null);
+    sleepTime.set(-1);
+
+    try {
+      CollectionAdminRequest.deleteCollection("testRepFactor1LeaderStartup").process(cluster.getSolrClient());
+    } catch (Exception e) {
+      // ignore
+    }
+    try {
+      CollectionAdminRequest.deleteCollection("testPeersyncFailureReplicationSuccess").process(cluster.getSolrClient());
+    } catch (Exception e) {
+      // ignore
+    }
+  }
+
+  @Test
+  public void testRepFactor1LeaderStartup() throws Exception {
+    CloudSolrClient solrClient = cluster.getSolrClient();
+
+    String collectionName = "testRepFactor1LeaderStartup";
+    CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection(collectionName, 1, 1)
+        .setCreateNodeSet(cluster.getJettySolrRunner(0).getNodeName());
+    create.process(solrClient);
+
+    waitForState("The collection should have 1 shard and 1 replica", collectionName, clusterShape(1, 1));
+
+    solrClient.setDefaultCollection(collectionName);
+    solrClient.getZkStateReader().registerCore(collectionName);
+
+    String addListenerCommand = "{" +
+        "'add-listener' : {'name':'newSearcherListener','event':'newSearcher', 'class':'" + SleepingSolrEventListener.class.getName() + "'}" +
+        "'add-listener' : {'name':'firstSearcherListener','event':'firstSearcher', 'class':'" + SleepingSolrEventListener.class.getName() + "'}" +
+        "}";
+
+    ConfigRequest request = new ConfigRequest(SolrRequest.METHOD.POST, "/config", addListenerCommand);
+    solrClient.request(request);
+
+    solrClient.add(new SolrInputDocument("id", "1"));
+    solrClient.commit();
+
+    AtomicInteger expectedDocs = new AtomicInteger(1);
+    AtomicReference<String> failingCoreNodeName = new AtomicReference<>();
+    CollectionStateWatcher stateWatcher = createActiveReplicaSearcherWatcher(expectedDocs, failingCoreNodeName);
+
+    JettySolrRunner runner = cluster.getJettySolrRunner(0);
+    cluster.stopJettySolrRunner(0);
+    waitForState("", collectionName, clusterShape(1, 0));
+    // restart
+    sleepTime.set(10000);
+    cluster.startJettySolrRunner(runner);
+    cluster.getSolrClient().getZkStateReader().registerCollectionStateWatcher(collectionName, stateWatcher);
+    waitForState("", collectionName, clusterShape(1, 1));
+    assertNull("No replica should have been active without registering a searcher, found: " + failingCoreNodeName.get(), failingCoreNodeName.get());
+    cluster.getSolrClient().getZkStateReader().removeCollectionStateWatcher(collectionName, stateWatcher);
+  }
+
+  public void testPeersyncFailureReplicationSuccess() throws Exception {
+    CloudSolrClient solrClient = cluster.getSolrClient();
+
+    String collectionName = "testPeersyncFailureReplicationSuccess";
+    CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection(collectionName, 1, 1)
+        .setCreateNodeSet(cluster.getJettySolrRunner(0).getNodeName());
+    create.process(solrClient);
+
+    waitForState("The collection should have 1 shard and 1 replica", collectionName, clusterShape(1, 1));
+
+    solrClient.setDefaultCollection(collectionName);
+    solrClient.getZkStateReader().registerCore(collectionName);
+
+    String addListenerCommand = "{" +
+        "'add-listener' : {'name':'newSearcherListener','event':'newSearcher', 'class':'" + SleepingSolrEventListener.class.getName() + "'}" +
+        "'add-listener' : {'name':'firstSearcherListener','event':'firstSearcher', 'class':'" + SleepingSolrEventListener.class.getName() + "'}" +
+        "}";
+
+    ConfigRequest request = new ConfigRequest(SolrRequest.METHOD.POST, "/config", addListenerCommand);
+    solrClient.request(request);
+
+    solrClient.add(new SolrInputDocument("id", "1"));
+    solrClient.commit();
+
+    AtomicInteger expectedDocs = new AtomicInteger(1);
+    AtomicReference<String> failingCoreNodeName = new AtomicReference<>();
+
+    QueryResponse response = solrClient.query(new SolrQuery("*:*"));
+    assertEquals(1, response.getResults().getNumFound());
+
+    // reset
+    coreNameRef.set(null);
+    coreNodeNameRef.set(null);
+    failingCoreNodeName.set(null);
+    sleepTime.set(5000);
+
+    CollectionStateWatcher stateWatcher = createActiveReplicaSearcherWatcher(expectedDocs, failingCoreNodeName);
+    cluster.getSolrClient().getZkStateReader().registerCollectionStateWatcher(collectionName, stateWatcher);
+
+    JettySolrRunner newNode = cluster.startJettySolrRunner();
+    CollectionAdminRequest.addReplicaToShard(collectionName, "shard1")
+        .setNode(newNode.getNodeName())
+        .process(solrClient);
+
+    waitForState("The collection should have 1 shard and 2 replica", collectionName, clusterShape(1, 2));
+    assertNull("No replica should have been active without registering a searcher, found: " + failingCoreNodeName.get(), failingCoreNodeName.get());
+
+    // stop the old node
+    log.info("Stopping old node 1");
+    AtomicReference<String> oldNodeName = new AtomicReference<>(cluster.getJettySolrRunner(0).getNodeName());
+    JettySolrRunner oldNode = cluster.stopJettySolrRunner(0);
+    // the newly created replica should become leader
+    waitForState("The collection should have 1 shard and 1 replica", collectionName, clusterShape(1, 1));
+    // the above call is not enough because we want to assert that the down'ed replica is not active
+    // but clusterShape will also return true if replica is not live -- which we don't want
+    CollectionStatePredicate collectionStatePredicate = (liveNodes, collectionState) -> {
+      for (Replica r : collectionState.getReplicas()) {
+        if (r.getNodeName().equals(oldNodeName.get())) {
+          return r.getState() == Replica.State.DOWN;
+        }
+      }
+      return false;
+    };
+    waitForState("", collectionName, collectionStatePredicate);
+    assertNotNull(solrClient.getZkStateReader().getLeaderRetry(collectionName, "shard1"));
+
+    // reset
+    coreNameRef.set(null);
+    coreNodeNameRef.set(null);
+    failingCoreNodeName.set(null);
+    sleepTime.set(5000);
+
+    // inject wrong signature output
+    TestInjection.wrongIndexFingerprint = "true:100";
+    // now lets restart the old node
+    log.info("Starting old node 1");
+    cluster.startJettySolrRunner(oldNode);
+    waitForState("", collectionName, clusterShape(1, 2));
+    // invoke statewatcher explicitly to avoid race condition where the assert happens before the state watcher is invoked by ZkStateReader
+    cluster.getSolrClient().getZkStateReader().registerCollectionStateWatcher(collectionName, stateWatcher);
+    assertNull("No replica should have been active without registering a searcher, found: " + failingCoreNodeName.get(), failingCoreNodeName.get());
+
+    oldNodeName.set(cluster.getJettySolrRunner(1).getNodeName());
+    assertSame(oldNode, cluster.stopJettySolrRunner(1)); // old node is now at 1
+    log.info("Stopping old node 2");
+    waitForState("", collectionName, clusterShape(1, 1));
+    waitForState("", collectionName, collectionStatePredicate);
+
+    // reset
+    coreNameRef.set(null);
+    coreNodeNameRef.set(null);
+    failingCoreNodeName.set(null);
+    sleepTime.set(14000);  // has to be higher than the twice the recovery wait pause between attempts plus some margin
+
+    // inject failure
+    TestInjection.failIndexFingerprintRequests = "true:100";
+    // now lets restart the old node again
+    log.info("Starting old node 2");
+    cluster.startJettySolrRunner(oldNode);
+    waitForState("", collectionName, clusterShape(1, 2));
+    // invoke statewatcher explicitly to avoid race condition where the assert happens before the state watcher is invoked by ZkStateReader
+    cluster.getSolrClient().getZkStateReader().registerCollectionStateWatcher(collectionName, stateWatcher);
+    assertNull("No replica should have been active without registering a searcher, found: " + failingCoreNodeName.get(), failingCoreNodeName.get());
+    cluster.getSolrClient().getZkStateReader().removeCollectionStateWatcher(collectionName, stateWatcher);
+  }
+
+  private CollectionStateWatcher createActiveReplicaSearcherWatcher(AtomicInteger expectedDocs, AtomicReference<String> failingCoreNodeName) {
+    return new CollectionStateWatcher() {
+      @Override
+      public boolean onStateChanged(Set<String> liveNodes, DocCollection collectionState) {
+        try {
+          String coreNodeName = coreNodeNameRef.get();
+          String coreName = coreNameRef.get();
+          if (coreNodeName == null || coreName == null) return false;
+          Replica replica = collectionState.getReplica(coreNodeName);
+          if (replica == null) return false;
+          log.info("Collection state: {}", collectionState);
+          if (replica.isActive(liveNodes)) {
+            log.info("Active replica: {}", coreNodeName);
+            for (int i = 0; i < cluster.getJettySolrRunners().size(); i++) {
+              JettySolrRunner jettySolrRunner = cluster.getJettySolrRunner(i);
+              log.info("Checking node: {}", jettySolrRunner.getNodeName());
+              if (jettySolrRunner.getNodeName().equals(replica.getNodeName())) {
+                SolrDispatchFilter solrDispatchFilter = jettySolrRunner.getSolrDispatchFilter();
+                try (SolrCore core = solrDispatchFilter.getCores().getCore(coreName)) {
+                  if (core.getSolrConfig().useColdSearcher) {
+                    log.error("useColdSearcher is enabled! It should not be enabled for this test!");
+                    assert false;
+                    return false;
+                  }
+                  log.info("Found SolrCore: {}, id: {}", core.getName(), core);
+                  RefCounted<SolrIndexSearcher> registeredSearcher = core.getRegisteredSearcher();
+                  if (registeredSearcher != null) {
+                    log.error("registered searcher not null, maxdocs = {}", registeredSearcher.get().maxDoc());
+                    if (registeredSearcher.get().maxDoc() != expectedDocs.get()) {
+                      failingCoreNodeName.set(coreNodeName);
+                      registeredSearcher.decref();
+                      return false;
+                    } else {
+                      registeredSearcher.decref();
+                      return false;
+                    }
+                  } else {
+                    log.error("registered searcher was null!");
+                    RefCounted<SolrIndexSearcher> newestSearcher = core.getNewestSearcher(false);
+                    if (newestSearcher != null) {
+                      SolrIndexSearcher searcher = newestSearcher.get();
+                      log.warn("newest searcher was: {}", searcher);
+                      newestSearcher.decref();
+                    } else {
+                      log.error("newest searcher was also null!");
+                    }
+                    // no registered searcher but replica is active!
+                    failingCoreNodeName.set(coreNodeName);
+                  }
+                }
+              }
+            }
+          }
+        } catch (Exception e) {
+          log.error("Unexpected exception in state watcher", e);
+        }
+        return false;
+      }
+    };
+  }
+
+  public static class SleepingSolrEventListener implements SolrEventListener {
+    @Override
+    public void init(NamedList args) {
+      new RuntimeException().printStackTrace();
+      System.out.println(args);
+    }
+
+    @Override
+    public void postCommit() {
+
+    }
+
+    @Override
+    public void postSoftCommit() {
+
+    }
+
+    @Override
+    public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
+      if (sleepTime.get() > 0) {
+        TestCloudSearcherWarming.coreNodeNameRef.set(newSearcher.getCore().getCoreDescriptor().getCloudDescriptor().getCoreNodeName());
+        TestCloudSearcherWarming.coreNameRef.set(newSearcher.getCore().getName());
+        log.info("Sleeping for {} on newSearcher: {}, currentSearcher: {} belonging to (newest) core: {}, id: {}", sleepTime.get(), newSearcher, currentSearcher, newSearcher.getCore().getName(), newSearcher.getCore());
+        try {
+          Thread.sleep(sleepTime.get());
+        } catch (InterruptedException e) {
+          e.printStackTrace();
+        }
+        log.info("Finished sleeping for {} on newSearcher: {}, currentSearcher: {} belonging to (newest) core: {}, id: {}", sleepTime.get(), newSearcher, currentSearcher, newSearcher.getCore().getName(), newSearcher.getCore());
+      }
+    }
+  }
+
+  public static class ConfigRequest extends SolrRequest {
+    protected final String message;
+
+    public ConfigRequest(METHOD m, String path, String message) {
+      super(m, path);
+      this.message = message;
+    }
+
+    @Override
+    public SolrParams getParams() {
+      return null;
+    }
+
+    @Override
+    public Collection<ContentStream> getContentStreams() throws IOException {
+      return message != null ? Collections.singletonList(new ContentStreamBase.StringStream(message)) : null;
+    }
+
+    @Override
+    protected SolrResponse createResponse(SolrClient client) {
+      return new SolrResponseBase();
+    }
+  }
+}


[2/2] lucene-solr:master: SOLR-6086: Remove unused import

Posted by sh...@apache.org.
SOLR-6086: Remove unused import


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b1a65c8f
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b1a65c8f
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b1a65c8f

Branch: refs/heads/master
Commit: b1a65c8f5572004cabc2b8d5548bf07f22fd2b3e
Parents: 90da5ce
Author: Shalin Shekhar Mangar <sh...@apache.org>
Authored: Mon Jul 31 08:12:29 2017 +0530
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Mon Jul 31 08:12:29 2017 +0530

----------------------------------------------------------------------
 .../src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java    | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b1a65c8f/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
index c0cd5b8..761785d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudSearcherWarming.java
@@ -29,7 +29,6 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;