lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From no...@apache.org
Subject svn commit: r1658549 - in /lucene/dev/branches/branch_5x: ./ solr/ solr/contrib/ solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/ solr/core/ solr/core/src/java/org/apache/solr/handler/component/ solr/core/src/java/org/apache/solr/handler/loader...
Date Mon, 09 Feb 2015 19:07:44 GMT
Author: noble
Date: Mon Feb  9 19:07:43 2015
New Revision: 1658549

URL: http://svn.apache.org/r1658549
Log:
SOLR-5890: Delete silently fails if not sent to shard where document was added

Modified:
    lucene/dev/branches/branch_5x/   (props changed)
    lucene/dev/branches/branch_5x/solr/   (props changed)
    lucene/dev/branches/branch_5x/solr/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_5x/solr/contrib/   (props changed)
    lucene/dev/branches/branch_5x/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/SolrCloudPartitioner.java
    lucene/dev/branches/branch_5x/solr/core/   (props changed)
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/DeleteUpdateCommand.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestHashPartitioner.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java
    lucene/dev/branches/branch_5x/solr/solrj/   (props changed)
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/DocRouter.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/HashBasedRouter.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/ImplicitDocRouter.java

Modified: lucene/dev/branches/branch_5x/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/CHANGES.txt?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/solr/CHANGES.txt Mon Feb  9 19:07:43 2015
@@ -68,6 +68,9 @@ Bug Fixes
 * SOLR-6775: Creating backup snapshot results in null pointer exception.
   (Ryan Hesson, Varun Thacker via shalin)
 
+* SOLR-5890: Delete silently fails if not sent to shard where document was
+  added (Ishan Chattopadhyaya, Noble Paul)
+
 Optimizations
 ----------------------
  * SOLR-7049: Move work done by the LIST Collections API call to the Collections

Modified: lucene/dev/branches/branch_5x/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/SolrCloudPartitioner.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/SolrCloudPartitioner.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/SolrCloudPartitioner.java
(original)
+++ lucene/dev/branches/branch_5x/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/SolrCloudPartitioner.java
Mon Feb  9 19:07:43 2015
@@ -113,7 +113,7 @@ public class SolrCloudPartitioner extend
     String keyStr = key.toString();
     
     // TODO: scalability: replace linear search in HashBasedRouter.hashToSlice() with binary
search on sorted hash ranges
-    Slice slice = docRouter.getTargetSlice(keyStr, doc, emptySolrParams, docCollection);

+    Slice slice = docRouter.getTargetSlice(keyStr, doc, null, emptySolrParams, docCollection);

     
 //    LOG.info("slice: {}", slice);
     if (slice == null) {

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
Mon Feb  9 19:07:43 2015
@@ -380,7 +380,7 @@ public class RealTimeGetComponent extend
 
       Map<String, List<String>> sliceToId = new HashMap<>();
       for (String id : allIds) {
-        Slice slice = coll.getRouter().getTargetSlice(id, null, params, coll);
+        Slice slice = coll.getRouter().getTargetSlice(id, null, null, params, coll);
 
         List<String> idsForShard = sliceToId.get(slice.getName());
         if (idsForShard == null) {

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
Mon Feb  9 19:07:43 2015
@@ -139,6 +139,12 @@ public class JavabinLoader extends Conte
             delcmd.setVersion(version);
           }
         }
+        if (map != null) {
+          String route = (String) map.get(UpdateRequest.ROUTE);
+          if (route != null) {
+            delcmd.setRoute(route);
+          }
+        }
         processor.processDelete(delcmd);
         delcmd.clear();
       }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java
Mon Feb  9 19:07:43 2015
@@ -371,6 +371,8 @@ public class JsonLoader extends ContentS
               cmd.commitWithin = (int)parser.getLong();
             } else if( "_version_".equals(key) ) {
               cmd.setVersion(parser.getLong());
+            } else if ("_route_".equals(key)) {
+              cmd.setRoute(parser.getString());
             } else {
               throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Unknown key:
"+key+" ["+parser.getPosition()+"]" );
             }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java
Mon Feb  9 19:07:43 2015
@@ -17,7 +17,9 @@ package org.apache.solr.handler.loader;
  */
 
 import com.google.common.collect.Lists;
+
 import org.apache.commons.io.IOUtils;
+import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.CommonParams;
@@ -56,6 +58,7 @@ import javax.xml.transform.TransformerEx
 import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.sax.SAXSource;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -328,6 +331,9 @@ public class XMLLoader extends ContentSt
               if (UpdateRequestHandler.VERSION.equals(attrName)) {
                 deleteCmd.setVersion(Long.parseLong(attrVal));
               }
+              if (UpdateRequest.ROUTE.equals(attrName)) {
+                deleteCmd.setRoute(attrVal);
+              }
             }
           }
           break;

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/DeleteUpdateCommand.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/DeleteUpdateCommand.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/DeleteUpdateCommand.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/DeleteUpdateCommand.java
Mon Feb  9 19:07:43 2015
@@ -108,6 +108,8 @@ public class DeleteUpdateCommand extends
     if (indexedId!=null) sb.append(",indexedId=").append(getId());
     if (query != null) sb.append(",query=`").append(query).append('`');
     sb.append(",commitWithin=").append(commitWithin);
+    if (route != null)
+      sb.append(",_route_=").append(route);
      sb.append('}');
      return sb.toString();
   }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
Mon Feb  9 19:07:43 2015
@@ -176,8 +176,9 @@ public class SolrCmdDistributor {
     for (Node node : nodes) {
       UpdateRequest uReq = new UpdateRequest();
       uReq.setParams(params);
+      uReq.setCommitWithin(cmd.commitWithin);
       if (cmd.isDeleteById()) {
-        uReq.deleteById(cmd.getId(), cmd.getVersion());
+        uReq.deleteById(cmd.getId(), cmd.getRoute(), cmd.getVersion());
       } else {
         uReq.deleteByQuery(cmd.query);
       }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/UpdateCommand.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/UpdateCommand.java
Mon Feb  9 19:07:43 2015
@@ -27,6 +27,7 @@ import org.apache.solr.request.SolrQuery
 public abstract class UpdateCommand implements Cloneable {
   protected SolrQueryRequest req;
   protected long version;
+  protected String route;
   protected int flags;
 
   public static int BUFFERING = 0x00000001;    // update command is being buffered.
@@ -65,6 +66,14 @@ public abstract class UpdateCommand impl
     this.version = version;
   }
 
+  public String getRoute() {
+    return route;
+  }
+
+  public void setRoute (String route) {
+    this.route = route;
+  }
+
   public void setFlags(int flags) {
     this.flags = flags;
   }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/update/processor/DistributedUpdateProcessor.java
Mon Feb  9 19:07:43 2015
@@ -309,8 +309,11 @@ public class DistributedUpdateProcessor
 
   }
 
-
   private List<Node> setupRequest(String id, SolrInputDocument doc) {
+    return setupRequest(id, doc, null);
+  }
+
+  private List<Node> setupRequest(String id, SolrInputDocument doc, String route) {
     List<Node> nodes = null;
 
     // if we are in zk mode...
@@ -324,7 +327,7 @@ public class DistributedUpdateProcessor
 
       ClusterState cstate = zkController.getClusterState();      
       DocCollection coll = cstate.getCollection(collection);
-      Slice slice = coll.getRouter().getTargetSlice(id, doc, req.getParams(), coll);
+      Slice slice = coll.getRouter().getTargetSlice(id, doc, route, req.getParams(), coll);
 
       if (slice == null) {
         // No slice found.  Most strict routers will have already thrown an exception, so
a null return is
@@ -1136,7 +1139,7 @@ public class DistributedUpdateProcessor
 
     if (zkEnabled) {
       zkCheck();
-      nodes = setupRequest(cmd.getId(), null);
+      nodes = setupRequest(cmd.getId(), null, cmd.getRoute());
     } else {
       isLeader = getNonZkLeaderAssumption(req);
     }

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
Mon Feb  9 19:07:43 2015
@@ -24,8 +24,10 @@ import org.apache.solr.client.solrj.Solr
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
@@ -35,6 +37,7 @@ import org.apache.solr.common.cloud.ZkNo
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CollectionParams.CollectionAction;
 import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.update.VersionInfo;
 import org.apache.solr.update.processor.DistributedUpdateProcessor;
 import org.apache.zookeeper.CreateMode;
@@ -44,6 +47,7 @@ import org.junit.Test;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Super basic testing, no shard restarting or anything.
@@ -136,13 +140,269 @@ public class FullSolrCloudDistribCmdsTes
     // TODO: testOptimisticUpdate(results);
     
     testDeleteByQueryDistrib();
-    
+
+    testDeleteByIdImplicitRouter();
+
+    testDeleteByIdCompositeRouterWithRouterField();
+
     docId = testThatCantForwardToLeaderFails(docId);
-    
-    
+
+
     docId = testIndexingBatchPerRequestWithHttpSolrClient(docId);
   }
 
+  private void testDeleteByIdImplicitRouter() throws Exception {
+    SolrClient server = createNewSolrClient("", getBaseUrl((HttpSolrClient) clients.get(0)));
+    CollectionAdminResponse response;
+    Map<String, NamedList<Integer>> coresStatus;
+
+    CollectionAdminRequest.Create createCollectionRequest = new CollectionAdminRequest.Create();
+    createCollectionRequest.setCollectionName("implicit_collection_without_routerfield");
+    createCollectionRequest.setRouterName("implicit");
+    createCollectionRequest.setNumShards(2);
+    createCollectionRequest.setShards("shard1,shard2");
+    createCollectionRequest.setReplicationFactor(2);
+    createCollectionRequest.setConfigName("conf1");
+    response = createCollectionRequest.process(server);
+
+    assertEquals(0, response.getStatus());
+    assertTrue(response.isSuccess());
+    coresStatus = response.getCollectionCoresStatus();
+    assertEquals(4, coresStatus.size());
+    for (int i = 0; i < 4; i++) {
+      NamedList<Integer> status = coresStatus.get("implicit_collection_without_routerfield_shard"
+ (i / 2 + 1) + "_replica" + (i % 2 + 1));
+      assertEquals(0, (int) status.get("status"));
+      assertTrue(status.get("QTime") > 0);
+    }
+
+    SolrClient shard1 = createNewSolrClient("implicit_collection_without_routerfield_shard1_replica1",
+        getBaseUrl((HttpSolrClient) clients.get(0)));
+    SolrClient shard2 = createNewSolrClient("implicit_collection_without_routerfield_shard2_replica1",
+        getBaseUrl((HttpSolrClient) clients.get(0)));
+
+    SolrInputDocument doc = new SolrInputDocument();
+    int docCounts1, docCounts2;
+
+    // Add three documents to shard1
+    doc.clear();
+    doc.addField("id", "1");
+    doc.addField("title", "s1 one");
+    shard1.add(doc);
+    shard1.commit();
+
+    doc.clear();
+    doc.addField("id", "2");
+    doc.addField("title", "s1 two");
+    shard1.add(doc);
+    shard1.commit();
+
+    doc.clear();
+    doc.addField("id", "3");
+    doc.addField("title", "s1 three");
+    shard1.add(doc);
+    shard1.commit();
+
+    docCounts1 = 3; // Three documents in shard1
+
+    // Add two documents to shard2
+    doc.clear();
+    doc.addField("id", "4");
+    doc.addField("title", "s2 four");
+    shard2.add(doc);
+    shard2.commit();
+
+    doc.clear();
+    doc.addField("id", "5");
+    doc.addField("title", "s2 five");
+    shard2.add(doc);
+    shard2.commit();
+
+    docCounts2 = 2; // Two documents in shard2
+
+    // Verify the documents were added to correct shards
+    ModifiableSolrParams query = new ModifiableSolrParams();
+    query.set("q", "*:*");
+    QueryResponse respAll = shard1.query(query);
+    assertEquals(docCounts1 + docCounts2, respAll.getResults().getNumFound());
+
+    query.set("shards", "shard1");
+    QueryResponse resp1 = shard1.query(query);
+    assertEquals(docCounts1, resp1.getResults().getNumFound());
+
+    query.set("shards", "shard2");
+    QueryResponse resp2 = shard2.query(query);
+    assertEquals(docCounts2, resp2.getResults().getNumFound());
+
+
+    // Delete a document in shard2 with update to shard1, with _route_ param
+    // Should delete.
+    UpdateRequest deleteRequest = new UpdateRequest();
+    deleteRequest.deleteById("4", "shard2");
+    shard1.request(deleteRequest);
+    shard1.commit();
+    query.set("shards", "shard2");
+    resp2 = shard2.query(query);
+    assertEquals(--docCounts2, resp2.getResults().getNumFound());
+
+    // Delete a document in shard2 with update to shard1, without _route_ param
+    // Shouldn't delete, since deleteById requests are not broadcast to all shard leaders.
+    deleteRequest = new UpdateRequest();
+    deleteRequest.deleteById("5");
+    shard1.request(deleteRequest);
+    shard1.commit();
+    query.set("shards", "shard2");
+    resp2 = shard2.query(query);
+    assertEquals(docCounts2, resp2.getResults().getNumFound());
+
+    // Multiple deleteById commands in a single request
+    deleteRequest.clear();
+    deleteRequest.deleteById("2", "shard1");
+    deleteRequest.deleteById("3", "shard1");
+    deleteRequest.setCommitWithin(1);
+    query.set("shards", "shard1");
+    shard2.request(deleteRequest);
+    resp1 = shard1.query(query);
+    --docCounts1;
+    --docCounts1;
+    assertEquals(docCounts1, resp1.getResults().getNumFound());
+
+    // Test commitWithin, update to shard2, document deleted in shard1
+    deleteRequest.clear();
+    deleteRequest.deleteById("1", "shard1");
+    deleteRequest.setCommitWithin(1);
+    shard2.request(deleteRequest);
+    Thread.sleep(1000);
+    query.set("shards", "shard1");
+    resp1 = shard1.query(query);
+    assertEquals(--docCounts1, resp1.getResults().getNumFound());
+  }
+
+  private void testDeleteByIdCompositeRouterWithRouterField() throws Exception {
+    SolrClient server = createNewSolrClient("", getBaseUrl((HttpSolrClient) clients.get(0)));
+    CollectionAdminResponse response;
+    Map<String, NamedList<Integer>> coresStatus;
+
+    CollectionAdminRequest.Create createCollectionRequest = new CollectionAdminRequest.Create();
+    createCollectionRequest.setCollectionName("compositeid_collection_with_routerfield");
+    createCollectionRequest.setRouterName("compositeId");
+    createCollectionRequest.setRouterField("routefield_s");
+    createCollectionRequest.setNumShards(2);
+    createCollectionRequest.setShards("shard1,shard2");
+    createCollectionRequest.setReplicationFactor(2);
+    createCollectionRequest.setConfigName("conf1");
+    response = createCollectionRequest.process(server);
+
+    assertEquals(0, response.getStatus());
+    assertTrue(response.isSuccess());
+    coresStatus = response.getCollectionCoresStatus();
+    assertEquals(4, coresStatus.size());
+    for (int i = 0; i < 4; i++) {
+      NamedList<Integer> status = coresStatus.get("compositeid_collection_with_routerfield_shard"
+ (i / 2 + 1) + "_replica" + (i % 2 + 1));
+      assertEquals(0, (int) status.get("status"));
+      assertTrue(status.get("QTime") > 0);
+    }
+
+    SolrClient shard1 = createNewSolrClient("compositeid_collection_with_routerfield_shard1_replica1",
+        getBaseUrl((HttpSolrClient) clients.get(0)));
+    SolrClient shard2 = createNewSolrClient("compositeid_collection_with_routerfield_shard2_replica1",
+        getBaseUrl((HttpSolrClient) clients.get(0)));
+
+    SolrInputDocument doc = new SolrInputDocument();
+    int docCounts1 = 0, docCounts2 = 0;
+
+    // Add three documents to shard1
+    doc.clear();
+    doc.addField("id", "1");
+    doc.addField("title", "s1 one");
+    doc.addField("routefield_s", "europe");
+    shard1.add(doc);
+    shard1.commit();
+
+    doc.clear();
+    doc.addField("id", "2");
+    doc.addField("title", "s1 two");
+    doc.addField("routefield_s", "europe");
+    shard1.add(doc);
+    shard1.commit();
+
+    doc.clear();
+    doc.addField("id", "3");
+    doc.addField("title", "s1 three");
+    doc.addField("routefield_s", "europe");
+    shard1.add(doc);
+    shard1.commit();
+
+    docCounts1 = 3; // Three documents in shard1
+
+    // Add two documents to shard2
+    doc.clear();
+    doc.addField("id", "4");
+    doc.addField("title", "s2 four");
+    doc.addField("routefield_s", "africa");
+    shard2.add(doc);
+    //shard2.commit();
+
+    doc.clear();
+    doc.addField("id", "5");
+    doc.addField("title", "s2 five");
+    doc.addField("routefield_s", "africa");
+    shard2.add(doc);
+    shard2.commit();
+
+    docCounts2 = 2; // Two documents in shard2
+
+    // Verify the documents were added to correct shards
+    ModifiableSolrParams query = new ModifiableSolrParams();
+    query.set("q", "*:*");
+    QueryResponse respAll = shard1.query(query);
+    assertEquals(docCounts1 + docCounts2, respAll.getResults().getNumFound());
+
+    query.set("shards", "shard1");
+    QueryResponse resp1 = shard1.query(query);
+    assertEquals(docCounts1, resp1.getResults().getNumFound());
+
+    query.set("shards", "shard2");
+    QueryResponse resp2 = shard2.query(query);
+    assertEquals(docCounts2, resp2.getResults().getNumFound());
+
+    // Delete a document in shard2 with update to shard1, with _route_ param
+    // Should delete.
+    UpdateRequest deleteRequest = new UpdateRequest();
+    deleteRequest.deleteById("4", "africa");
+    deleteRequest.setCommitWithin(1);
+    shard1.request(deleteRequest);
+    shard1.commit();
+
+    query.set("shards", "shard2");
+    resp2 = shard2.query(query);
+    --docCounts2;
+    assertEquals(docCounts2, resp2.getResults().getNumFound());
+
+    // Multiple deleteById commands in a single request
+    deleteRequest.clear();
+    deleteRequest.deleteById("2", "europe");
+    deleteRequest.deleteById("3", "europe");
+    deleteRequest.setCommitWithin(1);
+    query.set("shards", "shard1");
+    shard1.request(deleteRequest);
+    shard1.commit();
+    Thread.sleep(1000);
+    resp1 = shard1.query(query);
+    --docCounts1;
+    --docCounts1;
+    assertEquals(docCounts1, resp1.getResults().getNumFound());
+
+    // Test commitWithin, update to shard2, document deleted in shard1
+    deleteRequest.clear();
+    deleteRequest.deleteById("1", "europe");
+    deleteRequest.setCommitWithin(1);
+    shard2.request(deleteRequest);
+    query.set("shards", "shard1");
+    resp1 = shard1.query(query);
+    --docCounts1;
+    assertEquals(docCounts1, resp1.getResults().getNumFound());
+  }
+
   private long testThatCantForwardToLeaderFails(long docId) throws Exception {
     ZkStateReader zkStateReader = cloudClient.getZkStateReader();
     ZkNodeProps props = zkStateReader.getLeaderRetry(DEFAULT_COLLECTION, "shard1");

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestHashPartitioner.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestHashPartitioner.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestHashPartitioner.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestHashPartitioner.java
Mon Feb  9 19:07:43 2015
@@ -137,7 +137,7 @@ public class TestHashPartitioner extends
 
   public void doIndex(DocCollection coll, String id, String expectedShard) {
     DocRouter router = coll.getRouter();
-    Slice target = router.getTargetSlice(id, null, null, coll);
+    Slice target = router.getTargetSlice(id, null, null, null, coll);
     assertEquals(expectedShard, target.getName());
   }
 
@@ -206,7 +206,7 @@ public class TestHashPartitioner extends
                      "A!B/-5", "!/130!", "!!A/1000", "A//8!B///10!C////" };
     for (int i = 0 ; i < ids.length ; ++i) {
       try {
-        Slice targetSlice = coll.getRouter().getTargetSlice(ids[i], null, null, coll);
+        Slice targetSlice = coll.getRouter().getTargetSlice(ids[i], null, null, null, coll);
         assertNotNull(targetSlice);
       } catch (Exception e) {
         throw new Exception("Exception routing id '" + ids[i] + "'", e);
@@ -238,7 +238,7 @@ public class TestHashPartitioner extends
       }
       String id = idBuilder.toString();
       try {
-        Slice targetSlice = router.getTargetSlice(id, null, null, coll);
+        Slice targetSlice = router.getTargetSlice(id, null, null, null, coll);
         assertNotNull(targetSlice);
       } catch (Exception e) {
         throw new Exception("Exception routing id '" + id + "'", e);

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
Mon Feb  9 19:07:43 2015
@@ -589,6 +589,7 @@ public class JsonLoaderTest extends Solr
         +"\n ,'delete':['30','40']"
         +"\n ,'delete':{'id':50, '_version_':12345}"
         +"\n ,'delete':[{'id':60, '_version_':67890}, {'id':70, '_version_':77777}, {'query':'id:80',
'_version_':88888}]"
+        +"\n ,'delete':{'id':90, '_route_':'shard1', '_version_':88888}"
         + "\n}\n";
     str = str.replace('\'', '"');
     SolrQueryRequest req = req();
@@ -598,7 +599,7 @@ public class JsonLoaderTest extends Solr
     loader.load(req, rsp, new ContentStreamBase.StringStream(str), p);
 
     // DELETE COMMANDS
-    assertEquals( 8, p.deleteCommands.size() );
+    assertEquals( 9, p.deleteCommands.size() );
     DeleteUpdateCommand delete = p.deleteCommands.get( 0 );
     assertEquals( delete.id, "10" );
     assertEquals( delete.query, null );
@@ -637,7 +638,13 @@ public class JsonLoaderTest extends Solr
     delete = p.deleteCommands.get( 7 );
     assertEquals( delete.id, null );
     assertEquals( delete.query, "id:80" );
-    assertEquals( delete.getVersion(), 88888L);
+    assertEquals(delete.getVersion(), 88888L);
+
+    delete = p.deleteCommands.get(8);
+    assertEquals(delete.id, "90");
+    assertEquals(delete.query, null);
+    assertEquals(delete.getRoute(), "shard1");
+    assertEquals(delete.getVersion(), 88888L);
 
     req.close();
   }

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java
(original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java
Mon Feb  9 19:07:43 2015
@@ -173,15 +173,27 @@ public class XmlUpdateRequestHandlerTest
         " <delete>" +
         "   <id>150</id>" +
         " </delete>" +
+        " <delete>" +
+        "   <id version=\"42\">300</id>" +
+        " </delete>" +
+        " <delete>" +
+        "   <id _route_=\"shard1\">400</id>" +
+        " </delete>" +
+        " <delete>" +
+        "   <id _route_=\"shard1\" version=\"42\">500</id>" +
+        " </delete>" +
         "</update>";
 
       MockUpdateRequestProcessor p = new MockUpdateRequestProcessor(null);
-      p.expectDelete(null, "id:150", -1);
-      p.expectDelete("150", null, -1);
-      p.expectDelete("200", null, -1);
-      p.expectDelete(null, "id:200", -1);
-      p.expectDelete(null, "id:150", 500);
-      p.expectDelete("150", null, -1);
+      p.expectDelete(null, "id:150", -1, 0, null);
+      p.expectDelete("150", null, -1, 0, null);
+      p.expectDelete("200", null, -1, 0, null);
+      p.expectDelete(null, "id:200", -1, 0, null);
+      p.expectDelete(null, "id:150", 500, 0, null);
+      p.expectDelete("150", null, -1, 0, null);
+      p.expectDelete("300", null, -1, 42, null);
+      p.expectDelete("400", null, -1, 0, "shard1");
+      p.expectDelete("500", null, -1, 42, "shard1");
 
       XMLLoader loader = new XMLLoader().init(null);
       loader.load(req(), new SolrQueryResponse(), new ContentStreamBase.StringStream(xml),
p);
@@ -197,11 +209,15 @@ public class XmlUpdateRequestHandlerTest
         super(next);
       }
 
-      public void expectDelete(String id, String query, int commitWithin) {
+      public void expectDelete(String id, String query, int commitWithin, long version, String
route) {
         DeleteUpdateCommand cmd = new DeleteUpdateCommand(null);
         cmd.id = id;
         cmd.query = query;
         cmd.commitWithin = commitWithin;
+        if (version!=0)
+          cmd.setVersion(version);
+        if (route!=null)
+          cmd.setRoute(route);
         deleteCommands.add(cmd);
       }
 
@@ -216,7 +232,8 @@ public class XmlUpdateRequestHandlerTest
         assertTrue("Expected [" + expected + "] but found [" + cmd + "]",
             ObjectUtils.equals(expected.id, cmd.id) &&
             ObjectUtils.equals(expected.query, cmd.query) &&
-            expected.commitWithin==cmd.commitWithin);
+            expected.commitWithin==cmd.commitWithin && 
+            ObjectUtils.equals(expected.getRoute(), cmd.getRoute()));
       }
     }
 

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
(original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
Mon Feb  9 19:07:43 2015
@@ -206,6 +206,9 @@ public class JavaBinUpdateRequestCodec {
         Map<String,Object> params = entry.getValue();
         if (params != null) {
           Long version = (Long) params.get(UpdateRequest.VER);
+          if (params.containsKey(UpdateRequest.ROUTE))
+            updateRequest.deleteById(entry.getKey(), (String) params.get(UpdateRequest.ROUTE));
+          else
           updateRequest.deleteById(entry.getKey(), version);
         } else {
           updateRequest.deleteById(entry.getKey());

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
(original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
Mon Feb  9 19:07:43 2015
@@ -49,6 +49,7 @@ public class UpdateRequest extends Abstr
   public static final String REPFACT = "rf";
   public static final String MIN_REPFACT = "min_rf";
   public static final String VER = "ver";
+  public static final String ROUTE = "_route_";
   public static final String OVERWRITE = "ow";
   public static final String COMMIT_WITHIN = "cw";
   private Map<SolrInputDocument,Map<String,Object>> documents = null;
@@ -132,7 +133,25 @@ public class UpdateRequest extends Abstr
     deleteById.put(id, null);
     return this;
   }
-  
+
+  public UpdateRequest deleteById(String id, String route) {
+    return deleteById(id, route, null);
+  }
+
+  public UpdateRequest deleteById(String id, String route, Long version) {
+    if (deleteById == null) {
+      deleteById = new LinkedHashMap<>();
+    }
+    Map<String, Object> params = (route == null && version == null) ? null
: new HashMap<String, Object>(1);
+    if (version != null)
+      params.put(VER, version);
+    if (route != null)
+      params.put(ROUTE, route);
+    deleteById.put(id, params);
+    return this;
+  }
+
+
   public UpdateRequest deleteById(List<String> ids) {
     if (deleteById == null) {
       deleteById = new LinkedHashMap<>();
@@ -146,13 +165,7 @@ public class UpdateRequest extends Abstr
   }
   
   public UpdateRequest deleteById(String id, Long version) {
-    if (deleteById == null) {
-      deleteById = new LinkedHashMap<>();
-    }
-    Map<String,Object> params = new HashMap<>(1);
-    params.put(VER, version);
-    deleteById.put(id, params);
-    return this;
+    return deleteById(id, null, version);
   }
   
   public UpdateRequest deleteByQuery(String q) {
@@ -190,7 +203,7 @@ public class UpdateRequest extends Abstr
           return null;
         }
         Slice slice = router.getTargetSlice(id
-            .toString(), doc, null, col);
+            .toString(), doc, null, null, col);
         if (slice == null) {
           return null;
         }
@@ -237,7 +250,7 @@ public class UpdateRequest extends Abstr
         if (map != null) {
           version = (Long) map.get(VER);
         }
-        Slice slice = router.getTargetSlice(deleteId, null, null, col);
+        Slice slice = router.getTargetSlice(deleteId, null, null, null, col);
         if (slice == null) {
           return null;
         }
@@ -384,9 +397,14 @@ public class UpdateRequest extends Abstr
           Map<String,Object> map = entry.getValue();
           if (map != null) {
             Long version = (Long) map.get(VER);
+            String route = (String)map.get(ROUTE);
             if (version != null) {
               writer.append(" version=\"" + version + "\"");
             }
+            
+            if (route != null) {
+              writer.append(" _route_=\"" + route + "\"");
+            }
           }
           writer.append(">");
           

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/DocRouter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/DocRouter.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/DocRouter.java
(original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/DocRouter.java
Mon Feb  9 19:07:43 2015
@@ -193,7 +193,7 @@ public abstract class DocRouter {
   }
 
   /** Returns the Slice that the document should reside on, or null if there is not enough
information */
-  public abstract Slice getTargetSlice(String id, SolrInputDocument sdoc, SolrParams params,
DocCollection collection);
+  public abstract Slice getTargetSlice(String id, SolrInputDocument sdoc, String route, SolrParams
params, DocCollection collection);
 
   /** This method is consulted to determine what slices should be queried for a request when
    *  an explicit shards parameter was not used.

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/HashBasedRouter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/HashBasedRouter.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/HashBasedRouter.java
(original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/HashBasedRouter.java
Mon Feb  9 19:07:43 2015
@@ -28,9 +28,14 @@ import java.util.Collections;
 public abstract class HashBasedRouter extends DocRouter {
 
   @Override
-  public Slice getTargetSlice(String id, SolrInputDocument sdoc, SolrParams params, DocCollection
collection) {
-    if (id == null) id = getId(sdoc, params);
-    int hash = sliceHash(id, sdoc, params,collection);
+  public Slice getTargetSlice(String id, SolrInputDocument sdoc, String route, SolrParams
params, DocCollection collection) {
+    int hash;
+    if (route != null) {
+      hash = sliceHash(route, sdoc, params, collection);
+    } else {
+      if (id == null) id = getId(sdoc, params);
+      hash = sliceHash(id, sdoc, params, collection);
+    }
     return hashToSlice(hash, collection);
   }
 
@@ -70,7 +75,7 @@ public abstract class HashBasedRouter ex
     }
 
     // use the shardKey as an id for plain hashing
-    Slice slice = getTargetSlice(shardKey, null, params, collection);
+    Slice slice = getTargetSlice(shardKey, null, null, params, collection);
     return slice == null ? Collections.<Slice>emptyList() : Collections.singletonList(slice);
   }
 }

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/ImplicitDocRouter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/ImplicitDocRouter.java?rev=1658549&r1=1658548&r2=1658549&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/ImplicitDocRouter.java
(original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/cloud/ImplicitDocRouter.java
Mon Feb  9 19:07:43 2015
@@ -38,9 +38,12 @@ public class ImplicitDocRouter extends D
       .getLogger(ImplicitDocRouter.class);
 
   @Override
-  public Slice getTargetSlice(String id, SolrInputDocument sdoc, SolrParams params, DocCollection
collection) {
+  public Slice getTargetSlice(String id, SolrInputDocument sdoc, String route, SolrParams
params, DocCollection collection) {
     String shard = null;
-    if (sdoc != null) {
+
+    if (route != null) // if a route is already passed in, try to use it
+      shard = route;
+    else if (sdoc != null) {
       String f = getRouteField(collection);
       if(f !=null) {
         Object o = sdoc.getFieldValue(f);



Mime
View raw message