You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by an...@apache.org on 2014/08/13 09:41:54 UTC
svn commit: r1617673 - in /lucene/dev/trunk/solr: CHANGES.txt
core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java
core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java
Author: anshum
Date: Wed Aug 13 07:41:54 2014
New Revision: 1617673
URL: http://svn.apache.org/r1617673
Log:
SOLR-6347: Fix NPE during last replica deletion for custom sharded collections using DELETEREPLICA
Added:
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java (with props)
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1617673&r1=1617672&r2=1617673&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Wed Aug 13 07:41:54 2014
@@ -260,6 +260,8 @@ Bug Fixes
* SOLR-6336: DistributedQueue can easily create too many ZooKeeper Watches.
(Ramkumar Aiyengar via Mark Miller)
+* SOLR-6347: DELETEREPLICA throws a NPE while removing the last Replica in a Custom sharded collection.
+
Optimizations
---------------------
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java?rev=1617673&r1=1617672&r2=1617673&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java Wed Aug 13 07:41:54 2014
@@ -907,8 +907,15 @@ public class OverseerCollectionProcessor
boolean deleted = false;
while (System.nanoTime() < waitUntil) {
Thread.sleep(100);
- deleted = zkStateReader.getClusterState().getCollection(collectionName).getSlice(shard).getReplica(replicaName) == null;
- if (deleted) break;
+ DocCollection docCollection = zkStateReader.getClusterState().getCollection(collectionName);
+ if(docCollection != null) {
+ Slice slice = docCollection.getSlice(shard);
+ if(slice == null || slice.getReplica(replicaName) == null) {
+ deleted = true;
+ }
+ }
+ // Return true if either someone already deleted the collection/slice/replica.
+ if (docCollection == null || deleted) break;
}
return deleted;
}
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java?rev=1617673&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/DeleteLastCustomShardedReplicaTest.java Wed Aug 13 07:41:54 2014
@@ -0,0 +1,138 @@
+package org.apache.solr.cloud;
+
+/*
+ * 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.
+ */
+
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.CloudSolrServer;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.ImplicitDocRouter;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ZkNodeProps;
+import org.apache.solr.common.params.MapSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.cloud.OverseerCollectionProcessor.DELETEREPLICA;
+import static org.apache.solr.cloud.OverseerCollectionProcessor.MAX_SHARDS_PER_NODE;
+import static org.apache.solr.cloud.OverseerCollectionProcessor.NUM_SLICES;
+import static org.apache.solr.cloud.OverseerCollectionProcessor.REPLICATION_FACTOR;
+import static org.apache.solr.cloud.OverseerCollectionProcessor.SHARDS_PROP;
+import static org.apache.solr.common.cloud.ZkNodeProps.makeMap;
+
+public class DeleteLastCustomShardedReplicaTest extends AbstractFullDistribZkTestBase {
+ private CloudSolrServer client;
+
+ @BeforeClass
+ public static void beforeThisClass2() throws Exception {
+
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ System.setProperty("numShards", Integer.toString(sliceCount));
+ System.setProperty("solr.xml.persist", "true");
+ client = createCloudClient(null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ client.shutdown();
+ }
+
+ protected String getSolrXml() {
+ return "solr-no-core.xml";
+ }
+
+ public DeleteLastCustomShardedReplicaTest() {
+ fixShardCount = true;
+
+ sliceCount = 2;
+ shardCount = 2;
+
+ checkCreatedVsState = false;
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ int replicationFactor = 1;
+ int maxShardsPerNode = 5;
+
+ Map<String, Object> props = ZkNodeProps.makeMap(
+ "router.name", ImplicitDocRouter.NAME,
+ REPLICATION_FACTOR, replicationFactor,
+ MAX_SHARDS_PER_NODE, maxShardsPerNode,
+ NUM_SLICES, 1,
+ SHARDS_PROP,"a,b");
+
+ Map<String,List<Integer>> collectionInfos = new HashMap<>();
+
+ String collectionName = "customcollreplicadeletion";
+
+ createCollection(collectionInfos, collectionName, props, client);
+
+ waitForRecoveriesToFinish(collectionName, false);
+
+ DocCollection testcoll = getCommonCloudSolrServer().getZkStateReader()
+ .getClusterState().getCollection(collectionName);
+ Replica replica = testcoll.getSlice("a").getReplicas().iterator().next();
+
+ removeAndWaitForLastReplicaGone(collectionName, replica, "a");
+ }
+
+ protected void removeAndWaitForLastReplicaGone(String COLL_NAME, Replica replica, String shard)
+ throws SolrServerException, IOException, InterruptedException {
+ Map m = makeMap("collection", COLL_NAME, "action", DELETEREPLICA, "shard",
+ shard, "replica", replica.getName());
+ SolrParams params = new MapSolrParams(m);
+ SolrRequest request = new QueryRequest(params);
+ request.setPath("/admin/collections");
+ this.client.request(request);
+ long endAt = System.currentTimeMillis() + 3000;
+ boolean success = false;
+ DocCollection testcoll = null;
+ while (System.currentTimeMillis() < endAt) {
+ testcoll = getCommonCloudSolrServer().getZkStateReader()
+ .getClusterState().getCollection(COLL_NAME);
+ // In case of a custom sharded collection, the last replica deletion would also lead to
+ // the deletion of the slice.
+ success = testcoll.getSlice(shard) == null;
+ if (success) {
+ log.info("replica cleaned up {}/{} core {}",
+ shard + "/" + replica.getName(), replica.getStr("core"));
+ log.info("current state {}", testcoll);
+ break;
+ }
+ Thread.sleep(100);
+ }
+ assertTrue("Replica not cleaned up", success);
+ }
+
+}
+