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 2016/04/18 21:24:50 UTC
lucene-solr:master: SOLR-8983: Cleanup clusterstate in case of a
failed CREATE collection call
Repository: lucene-solr
Updated Branches:
refs/heads/master 9aefe193c -> 84a6ff697
SOLR-8983: Cleanup clusterstate in case of a failed CREATE collection call
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/84a6ff69
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/84a6ff69
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/84a6ff69
Branch: refs/heads/master
Commit: 84a6ff697e78cc944067bf7e196533dff7d88b8e
Parents: 9aefe19
Author: anshum <an...@apache.org>
Authored: Fri Apr 15 15:14:30 2016 -0700
Committer: anshum <an...@apache.org>
Committed: Mon Apr 18 11:19:50 2016 -0700
----------------------------------------------------------------------
solr/CHANGES.txt | 3 +
.../cloud/OverseerCollectionMessageHandler.java | 23 +++++-
.../cloud/CollectionsAPIDistributedZkTest.java | 25 +++++-
.../solr/cloud/CreateCollectionCleanupTest.java | 84 ++++++++++++++++++++
4 files changed, 127 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/84a6ff69/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 0a784c4..c16e757 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -129,6 +129,9 @@ Bug Fixes
* SOLR-9004: Fix "name" field type definition in films example. (Alexandre Rafalovitch via Varun Thacker)
+* SOLR-8983: Cleanup clusterstate and replicas for a failed create collection request
+ (Varun Thacker, Anshum Gupta)
+
Optimizations
----------------------
* SOLR-8722: Don't force a full ZkStateReader refresh on every Overseer operation.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/84a6ff69/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
index 503ff29..6bff648 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
@@ -1961,10 +1961,16 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler
}
processResponses(results, shardHandler, false, null, async, requestMap, Collections.emptySet());
-
- log.debug("Finished create command on all shards for collection: "
- + collectionName);
-
+ if(results.get("failure") != null && ((SimpleOrderedMap)results.get("failure")).size() > 0) {
+ // Let's cleanup as we hit an exception
+ // We shouldn't be passing 'results' here for the cleanup as the response would then contain 'success'
+ // element, which may be interpreted by the user as a positive ack
+ cleanupCollection(collectionName, new NamedList());
+ log.info("Cleaned up artifacts for failed create collection for [" + collectionName + "]");
+ } else {
+ log.debug("Finished create command on all shards for collection: "
+ + collectionName);
+ }
} catch (SolrException ex) {
throw ex;
} catch (Exception ex) {
@@ -1972,6 +1978,15 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler
}
}
+
+ private void cleanupCollection(String collectionName, NamedList results) throws KeeperException, InterruptedException {
+ log.error("Cleaning up collection [" + collectionName + "]." );
+ Map<String, Object> props = makeMap(
+ Overseer.QUEUE_OPERATION, DELETE.toLower(),
+ NAME, collectionName);
+ deleteCollection(new ZkNodeProps(props), results);
+ }
+
private Map<Position, String> identifyNodes(ClusterState clusterState,
List<String> nodeList,
ZkNodeProps message,
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/84a6ff69/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
index ad6df12..accc36a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
@@ -26,8 +26,19 @@ import java.lang.management.ManagementFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.lucene.util.LuceneTestCase.Slow;
@@ -39,7 +50,6 @@ 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.impl.HttpSolrClient;
-import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.CoreAdminRequest;
import org.apache.solr.client.solrj.request.CoreAdminRequest.Create;
@@ -375,6 +385,14 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
}
+ private NamedList<Object> makeRequest(String baseUrl, SolrRequest request, int socketTimeout)
+ throws SolrServerException, IOException {
+ try (SolrClient client = createNewSolrClient("", baseUrl)) {
+ ((HttpSolrClient) client).setSoTimeout(socketTimeout);
+ return client.request(request);
+ }
+ }
+
private NamedList<Object> makeRequest(String baseUrl, SolrRequest request)
throws SolrServerException, IOException {
try (SolrClient client = createNewSolrClient("", baseUrl)) {
@@ -525,8 +543,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
params.set(OverseerCollectionMessageHandler.CREATE_NODE_SET, nn1 + "," + nn2);
request = new QueryRequest(params);
request.setPath("/admin/collections");
- gotExp = false;
- NamedList<Object> resp = makeRequest(baseUrl, request);;
+ NamedList<Object> resp = makeRequest(baseUrl, request, 60000);
SimpleOrderedMap success = (SimpleOrderedMap) resp.get("success");
SimpleOrderedMap failure = (SimpleOrderedMap) resp.get("failure");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/84a6ff69/solr/core/src/test/org/apache/solr/cloud/CreateCollectionCleanupTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CreateCollectionCleanupTest.java b/solr/core/src/test/org/apache/solr/cloud/CreateCollectionCleanupTest.java
new file mode 100644
index 0000000..2d1a7f8
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cloud/CreateCollectionCleanupTest.java
@@ -0,0 +1,84 @@
+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 java.util.ArrayList;
+import java.util.Properties;
+
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class CreateCollectionCleanupTest extends SolrCloudTestCase {
+
+ protected static final String CLOUD_SOLR_XML_WITH_10S_CREATE_COLL_WAIT = "<solr>\n" +
+ "\n" +
+ " <str name=\"shareSchema\">${shareSchema:false}</str>\n" +
+ " <str name=\"configSetBaseDir\">${configSetBaseDir:configsets}</str>\n" +
+ " <str name=\"coreRootDirectory\">${coreRootDirectory:.}</str>\n" +
+ "\n" +
+ " <shardHandlerFactory name=\"shardHandlerFactory\" class=\"HttpShardHandlerFactory\">\n" +
+ " <str name=\"urlScheme\">${urlScheme:}</str>\n" +
+ " <int name=\"socketTimeout\">${socketTimeout:90000}</int>\n" +
+ " <int name=\"connTimeout\">${connTimeout:15000}</int>\n" +
+ " </shardHandlerFactory>\n" +
+ "\n" +
+ " <solrcloud>\n" +
+ " <str name=\"host\">127.0.0.1</str>\n" +
+ " <int name=\"hostPort\">${hostPort:8983}</int>\n" +
+ " <str name=\"hostContext\">${hostContext:solr}</str>\n" +
+ " <int name=\"zkClientTimeout\">${solr.zkclienttimeout:30000}</int>\n" +
+ " <bool name=\"genericCoreNodeNames\">${genericCoreNodeNames:true}</bool>\n" +
+ " <int name=\"leaderVoteWait\">10000</int>\n" +
+ " <int name=\"distribUpdateConnTimeout\">${distribUpdateConnTimeout:45000}</int>\n" +
+ " <int name=\"distribUpdateSoTimeout\">${distribUpdateSoTimeout:340000}</int>\n" +
+ " <int name=\"createCollectionWaitTimeTillActive\">${createCollectionWaitTimeTillActive:10}</int>\n" +
+ " </solrcloud>\n" +
+ " \n" +
+ "</solr>\n";
+
+
+ @BeforeClass
+ public static void createCluster() throws Exception {
+ configureCluster(1)
+ .addConfig("conf1", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
+ .withSolrXml(CLOUD_SOLR_XML_WITH_10S_CREATE_COLL_WAIT)
+ .configure();
+ }
+
+ @Test
+ public void testCreateCollectionCleanup() throws Exception {
+ final CloudSolrClient cloudClient = cluster.getSolrClient();
+ // Create a collection that would fail
+ CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection("foo","conf1",1,1);
+
+ Properties properties = new Properties();
+ properties.put(CoreAdminParams.DATA_DIR, "/some_invalid_dir/foo");
+ create.setProperties(properties);
+ CollectionAdminResponse rsp = create.process(cloudClient);
+ assertFalse(rsp.isSuccess());
+
+ // Confirm using LIST that the collection does not exist
+ CollectionAdminRequest.List list = CollectionAdminRequest.listCollections();
+ rsp = list.process(cloudClient);
+ assertFalse(((ArrayList) rsp.getResponse().get("collections")).contains("foo"));
+ }
+}