You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ds...@apache.org on 2018/05/08 19:12:04 UTC

lucene-solr:branch_7x: SOLR-12258: A V2 request referencing a collection or alias may fail to resolve it if it was just recently created. Now we sync with ZooKeeper and try one more time. V1 partially did this but only for aliases; now it does both.

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_7x 4cab3eba9 -> cfa4a82b3


SOLR-12258: A V2 request referencing a collection or alias may fail to resolve it if it was just recently created.
Now we sync with ZooKeeper and try one more time.  V1 partially did this but only for aliases; now it does both.

(cherry picked from commit c3d28a5)


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

Branch: refs/heads/branch_7x
Commit: cfa4a82b3b0462a3d921bddfbaaf97f7cabb24a4
Parents: 4cab3eb
Author: David Smiley <ds...@apache.org>
Authored: Tue May 8 15:10:07 2018 -0400
Committer: David Smiley <ds...@apache.org>
Committed: Tue May 8 15:11:57 2018 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  4 ++
 .../java/org/apache/solr/api/V2HttpCall.java    | 45 +++++++++++++++-----
 .../org/apache/solr/servlet/HttpSolrCall.java   |  4 +-
 .../apache/solr/common/cloud/ZkStateReader.java |  1 +
 4 files changed, 42 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cfa4a82b/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index a71c56c..f0c5812 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -184,6 +184,10 @@ Bug Fixes
 
 * SOLR-12192: Fixed a solr cli error message when ulimits are unlimited. (Martijn Koster)
 
+* SOLR-12258: A V2 request referencing a collection or alias may fail to resolve it if it was just recently created.
+  Now we sync with ZooKeeper and try one more time.  V1 partially did this but only for aliases; now it does both.
+  (David Smiley)
+
 Optimizations
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cfa4a82b/solr/core/src/java/org/apache/solr/api/V2HttpCall.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/api/V2HttpCall.java b/solr/core/src/java/org/apache/solr/api/V2HttpCall.java
index 8716e1a..d2b891e 100644
--- a/solr/core/src/java/org/apache/solr/api/V2HttpCall.java
+++ b/solr/core/src/java/org/apache/solr/api/V2HttpCall.java
@@ -27,6 +27,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Supplier;
 
 import com.google.common.collect.ImmutableSet;
 import org.apache.solr.client.solrj.SolrRequest;
@@ -34,6 +35,8 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.DocCollection;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.util.JsonSchemaValidator;
+import org.apache.solr.common.util.PathTrie;
 import org.apache.solr.common.util.ValidatingJsonMap;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.PluginBag;
@@ -48,17 +51,15 @@ import org.apache.solr.security.AuthorizationContext;
 import org.apache.solr.servlet.HttpSolrCall;
 import org.apache.solr.servlet.SolrDispatchFilter;
 import org.apache.solr.servlet.SolrRequestParsers;
-import org.apache.solr.common.util.JsonSchemaValidator;
-import org.apache.solr.common.util.PathTrie;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
 import static org.apache.solr.common.params.CommonParams.JSON;
 import static org.apache.solr.common.params.CommonParams.WT;
+import static org.apache.solr.common.util.PathTrie.getPathSegments;
 import static org.apache.solr.servlet.SolrDispatchFilter.Action.ADMIN;
 import static org.apache.solr.servlet.SolrDispatchFilter.Action.PROCESS;
-import static org.apache.solr.common.util.PathTrie.getPathSegments;
 import static org.apache.solr.servlet.SolrDispatchFilter.Action.REMOTEQUERY;
 
 // class that handle the '/v2' path
@@ -109,11 +110,8 @@ public class V2HttpCall extends HttpSolrCall {
       if ("c".equals(prefix) || "collections".equals(prefix)) {
         origCorename = pieces.get(1);
 
-        collectionsList = resolveCollectionListOrAlias(queryParams.get(COLLECTION_PROP, origCorename));
-        String collectionName = collectionsList.get(0); // first
-        //TODO try the other collections if can't find a local replica of the first?
+        DocCollection collection = resolveDocCollection(queryParams.get(COLLECTION_PROP, origCorename));
 
-        DocCollection collection = getDocCollection(collectionName);
         if (collection == null) {
           if ( ! path.endsWith(CommonParams.INTROSPECT)) {
             throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "no such collection or alias");
@@ -123,7 +121,7 @@ public class V2HttpCall extends HttpSolrCall {
           core = getCoreByCollection(collection.getName(), isPreferLeader);
           if (core == null) {
             //this collection exists , but this node does not have a replica for that collection
-            extractRemotePath(collectionName, origCorename);
+            extractRemotePath(collection.getName(), origCorename);
             if (action == REMOTEQUERY) {
               this.path = path = path.substring(prefix.length() + origCorename.length() + 2);
               return;
@@ -184,12 +182,39 @@ public class V2HttpCall extends HttpSolrCall {
     if (solrReq == null) solrReq = parser.parse(core, path, req);
   }
 
-  protected DocCollection getDocCollection(String collectionName) { // note: don't send an alias; resolve it first
+  /**
+   * Lookup the collection from the collection string (maybe comma delimited).
+   * Also sets {@link #collectionsList} by side-effect.
+   * if {@code secondTry} is false then we'll potentially recursively try this all one more time while ensuring
+   * the alias and collection info is sync'ed from ZK.
+   */
+  protected DocCollection resolveDocCollection(String collectionStr) {
     if (!cores.isZooKeeperAware()) {
       throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Solr not running in cloud mode ");
     }
     ZkStateReader zkStateReader = cores.getZkController().getZkStateReader();
-    return zkStateReader.getClusterState().getCollectionOrNull(collectionName);
+
+    Supplier<DocCollection> logic = () -> {
+      this.collectionsList = resolveCollectionListOrAlias(collectionStr); // side-effect
+      String collectionName = collectionsList.get(0); // first
+      //TODO an option to choose another collection in the list if can't find a local replica of the first?
+
+      return zkStateReader.getClusterState().getCollectionOrNull(collectionName);
+    };
+
+    DocCollection docCollection = logic.get();
+    if (docCollection != null) {
+      return docCollection;
+    }
+    // ensure our view is up to date before trying again
+    try {
+      zkStateReader.aliasesManager.update();
+      zkStateReader.forceUpdateCollection(collectionsList.get(0));
+    } catch (Exception e) {
+      log.error("Error trying to update state while resolving collection.", e);
+      //don't propagate exception on purpose
+    }
+    return logic.get();
   }
 
   public static Api getApiInfo(PluginBag<SolrRequestHandler> requestHandlers,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cfa4a82b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 50fa71c..9266ced 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -442,9 +442,9 @@ public class HttpSolrCall {
       action = REMOTEQUERY;
     } else {
       if (!retry) {
-        // we couldn't find a core to work with, try reloading aliases
-        // TODO: it would be nice if admin ui elements skipped this...
+        // we couldn't find a core to work with, try reloading aliases & this collection
         cores.getZkController().getZkStateReader().aliasesManager.update();
+        cores.getZkController().zkStateReader.forceUpdateCollection(collectionName);
         action = RETRY;
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cfa4a82b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
----------------------------------------------------------------------
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 505c7b2..fa52678 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
@@ -353,6 +353,7 @@ public class ZkStateReader implements Closeable {
    * Forcibly refresh a collection's internal state from ZK. Try to avoid having to resort to this when
    * a better design is possible.
    */
+  //TODO shouldn't we call ZooKeeper.sync() at the right places to prevent reading a stale value?  We do so for aliases.
   public void forceUpdateCollection(String collection) throws KeeperException, InterruptedException {
 
     synchronized (getUpdateLock()) {