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 2015/05/26 17:28:40 UTC

svn commit: r1681777 - in /lucene/dev/branches/branch_5x: ./ solr/ solr/CHANGES.txt solr/core/ solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java

Author: shalin
Date: Tue May 26 15:28:40 2015
New Revision: 1681777

URL: http://svn.apache.org/r1681777
Log:
SOLR-7389: Expose znodeVersion property for each of the collections returned for the clusterstatus operation in the collections API

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/core/   (props changed)
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.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=1681777&r1=1681776&r2=1681777&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/solr/CHANGES.txt Tue May 26 15:28:40 2015
@@ -10,7 +10,34 @@ See http://lucene.apache.org/solr for mo
 
 
 ==================  5.3.0 ==================
-(No Changes)
+Versions of Major Components
+---------------------
+(no changes)
+
+Upgrading from Solr 5.2
+-----------------------
+(no changes)
+
+Detailed Change List
+----------------------
+
+New Features
+----------------------
+
+* SOLR-7389: Expose znodeVersion property for each of the collections returned for the clusterstatus
+  operation in the collections API (Marius Grama via shalin)
+
+Bug Fixes
+----------------------
+(no changes)
+
+Optimizations
+----------------------
+(no changes)
+
+Other Changes
+----------------------
+(no changes)
 
 ==================  5.2.0 ==================
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java?rev=1681777&r1=1681776&r2=1681777&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java Tue May 26 15:28:40 2015
@@ -42,7 +42,6 @@ import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.lang.StringUtils;
@@ -61,7 +60,6 @@ import org.apache.solr.cloud.rule.Replic
 import org.apache.solr.cloud.rule.ReplicaAssigner.Position;
 import org.apache.solr.cloud.overseer.ClusterStateMutator;
 import org.apache.solr.cloud.overseer.OverseerAction;
-import org.apache.solr.cloud.rule.SnitchContext;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.cloud.Aliases;
@@ -106,8 +104,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
 
-import com.google.common.collect.ImmutableSet;
-
 
 public class OverseerCollectionProcessor implements Runnable, Closeable {
 
@@ -818,62 +814,48 @@ public class OverseerCollectionProcessor
     byte[] bytes = ZkStateReader.toJSON(clusterState);
     Map<String, Object> stateMap = (Map<String,Object>) ZkStateReader.fromJSON(bytes);
 
+    Set<String> collections = new HashSet<>();
+    String routeKey = message.getStr(ShardParams._ROUTE_);
     String shard = message.getStr(ZkStateReader.SHARD_ID_PROP);
-    NamedList<Object> collectionProps = new SimpleOrderedMap<Object>();
     if (collection == null) {
-      Set<String> collections = clusterState.getCollections();
-      for (String name : collections) {
-        Map<String, Object> collectionStatus = null;
-        if (clusterState.getCollection(name).getStateFormat() > 1) {
-          bytes = ZkStateReader.toJSON(clusterState.getCollection(name));
-          Map<String, Object> docCollection = (Map<String,Object>) ZkStateReader.fromJSON(bytes);
-          collectionStatus = getCollectionStatus(docCollection, name, shard);
-        } else  {
-          collectionStatus = getCollectionStatus((Map<String,Object>) stateMap.get(name), name, shard);
-        }
-        if (collectionVsAliases.containsKey(name) && !collectionVsAliases.get(name).isEmpty())  {
-          collectionStatus.put("aliases", collectionVsAliases.get(name));
+      collections = new HashSet<>(clusterState.getCollections());
+    } else  {
+      collections = Collections.singleton(collection);
+    }
+
+    NamedList<Object> collectionProps = new SimpleOrderedMap<Object>();
+
+    for (String name : collections) {
+      Map<String, Object> collectionStatus = null;
+      DocCollection clusterStateCollection = clusterState.getCollection(name);
+
+      Set<String> requestedShards = new HashSet<>();
+      if (routeKey != null) {
+        DocRouter router = clusterStateCollection.getRouter();
+        Collection<Slice> slices = router.getSearchSlices(routeKey, null, clusterStateCollection);
+        for (Slice slice : slices) {
+          requestedShards.add(slice.getName());
         }
-        String configName = zkStateReader.readConfigName(name);
-        collectionStatus.put("configName", configName);
-        collectionProps.add(name, collectionStatus);
       }
-    } else {
-      String routeKey = message.getStr(ShardParams._ROUTE_);
-      Map<String, Object> docCollection = null;
-      if (clusterState.getCollection(collection).getStateFormat() > 1) {
-        bytes = ZkStateReader.toJSON(clusterState.getCollection(collection));
-        docCollection = (Map<String,Object>) ZkStateReader.fromJSON(bytes);
-      } else  {
-        docCollection = (Map<String,Object>) stateMap.get(collection);
+      if (shard != null) {
+        requestedShards.add(shard);
       }
-      if (routeKey == null) {
-        Map<String, Object> collectionStatus = getCollectionStatus(docCollection, collection, shard);
-        if (collectionVsAliases.containsKey(collection) && !collectionVsAliases.get(collection).isEmpty())  {
-          collectionStatus.put("aliases", collectionVsAliases.get(collection));
-        }
-        String configName = zkStateReader.readConfigName(collection);
-        collectionStatus.put("configName", configName);
-        collectionProps.add(collection, collectionStatus);
+
+      if (clusterStateCollection.getStateFormat() > 1) {
+        bytes = ZkStateReader.toJSON(clusterStateCollection);
+        Map<String, Object> docCollection = (Map<String, Object>) ZkStateReader.fromJSON(bytes);
+        collectionStatus = getCollectionStatus(docCollection, name, requestedShards);
       } else {
-        DocCollection coll = clusterState.getCollection(collection);
-        DocRouter router = coll.getRouter();
-        Collection<Slice> slices = router.getSearchSlices(routeKey, null, coll);
-        String s = "";
-        for (Slice slice : slices) {
-          s += slice.getName() + ",";
-        }
-        if (shard != null)  {
-          s += shard;
-        }
-        Map<String, Object> collectionStatus = getCollectionStatus(docCollection, collection, s);
-        if (collectionVsAliases.containsKey(collection) && !collectionVsAliases.get(collection).isEmpty())  {
-          collectionStatus.put("aliases", collectionVsAliases.get(collection));
-        }
-        String configName = zkStateReader.readConfigName(collection);
-        collectionStatus.put("configName", configName);
-        collectionProps.add(collection, collectionStatus);
+        collectionStatus = getCollectionStatus((Map<String, Object>) stateMap.get(name), name, requestedShards);
+      }
+
+      collectionStatus.put("znodeVersion", clusterStateCollection.getZNodeVersion());
+      if (collectionVsAliases.containsKey(name) && !collectionVsAliases.get(name).isEmpty()) {
+        collectionStatus.put("aliases", collectionVsAliases.get(name));
       }
+      String configName = zkStateReader.readConfigName(name);
+      collectionStatus.put("configName", configName);
+      collectionProps.add(name, collectionStatus);
     }
 
     List<String> liveNodes = zkStateReader.getZkClient().getChildren(ZkStateReader.LIVE_NODES_ZKNODE, null, true);
@@ -946,21 +928,21 @@ public class OverseerCollectionProcessor
    *
    * @param collection collection map parsed from JSON-serialized {@link ClusterState}
    * @param name  collection name
-   * @param shardStr comma separated shard names
+   * @param requestedShards a set of shards to be returned in the status.
+   *                        An empty or null values indicates <b>all</b> shards.
    * @return map of collection properties
    */
   @SuppressWarnings("unchecked")
-  private Map<String, Object> getCollectionStatus(Map<String, Object> collection, String name, String shardStr) {
+  private Map<String, Object> getCollectionStatus(Map<String, Object> collection, String name, Set<String> requestedShards) {
     if (collection == null)  {
       throw new SolrException(ErrorCode.BAD_REQUEST, "Collection: " + name + " not found");
     }
-    if (shardStr == null) {
+    if (requestedShards == null || requestedShards.isEmpty()) {
       return collection;
     } else {
       Map<String, Object> shards = (Map<String, Object>) collection.get("shards");
       Map<String, Object>  selected = new HashMap<>();
-      List<String> selectedShards = Arrays.asList(shardStr.split(","));
-      for (String selectedShard : selectedShards) {
+      for (String selectedShard : requestedShards) {
         if (!shards.containsKey(selectedShard)) {
           throw new SolrException(ErrorCode.BAD_REQUEST, "Collection: " + name + " shard: " + selectedShard + " not found");
         }

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java?rev=1681777&r1=1681776&r2=1681777&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java Tue May 26 15:28:40 2015
@@ -22,6 +22,7 @@ import com.google.common.collect.Lists;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
@@ -80,6 +81,7 @@ public class TestCollectionAPI extends R
     clusterStatusAliasTest();
     clusterStatusRolesTest();
     replicaPropTest();
+    clusterStatusZNodeVersion();
   }
 
   private void clusterStatusWithCollectionAndShard() throws IOException, SolrServerException {
@@ -169,6 +171,55 @@ public class TestCollectionAPI extends R
     }
   }
 
+  private void clusterStatusZNodeVersion() throws Exception {
+    String cname = "clusterStatusZNodeVersion";
+    try (CloudSolrClient client = createCloudClient(null)) {
+
+      CollectionAdminRequest.Create create = new CollectionAdminRequest.Create();
+      create.setCollectionName(cname);
+      create.setMaxShardsPerNode(1);
+      create.setNumShards(1);
+      create.setReplicationFactor(1);
+      create.setConfigName("conf1");
+      create.process(client);
+
+      waitForRecoveriesToFinish(cname, true);
+
+      ModifiableSolrParams params = new ModifiableSolrParams();
+      params.set("action", CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
+      params.set("collection", cname);
+      SolrRequest request = new QueryRequest(params);
+      request.setPath("/admin/collections");
+
+      NamedList<Object> rsp = client.request(request);
+      NamedList<Object> cluster = (NamedList<Object>) rsp.get("cluster");
+      assertNotNull("Cluster state should not be null", cluster);
+      NamedList<Object> collections = (NamedList<Object>) cluster.get("collections");
+      assertNotNull("Collections should not be null in cluster state", collections);
+      assertEquals(1, collections.size());
+      Map<String, Object> collection = (Map<String, Object>) collections.get(cname);
+      assertNotNull(collection);
+      assertEquals("conf1", collection.get("configName"));
+      Integer znodeVersion = (Integer) collection.get("znodeVersion");
+      assertNotNull(znodeVersion);
+
+      CollectionAdminRequest.AddReplica addReplica = new CollectionAdminRequest.AddReplica();
+      addReplica.setCollectionName(cname);
+      addReplica.setShardName("shard1");
+      addReplica.process(client);
+
+      waitForRecoveriesToFinish(cname, true);
+
+      rsp = client.request(request);
+      cluster = (NamedList<Object>) rsp.get("cluster");
+      collections = (NamedList<Object>) cluster.get("collections");
+      collection = (Map<String, Object>) collections.get(cname);
+      Integer newVersion = (Integer) collection.get("znodeVersion");
+      assertNotNull(newVersion);
+      assertTrue(newVersion > znodeVersion);
+    }
+  }
+
   private void clusterStatusWithRouteKey() throws IOException, SolrServerException {
     try (CloudSolrClient client = createCloudClient(DEFAULT_COLLECTION)) {
       SolrInputDocument doc = new SolrInputDocument();