This is an automated email from the ASF dual-hosted git repository.

ishan pushed a commit to branch jira/SOLR15694
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 75d841055857c49aad8db976919b56da9a6c6a35
Author: Noble Paul <[email protected]>
AuthorDate: Wed Nov 17 13:39:38 2021 +1100

    added APIs
---
 .../impl/SimpleClusterAbstractionsImpl.java        | 45 ++++++++--------------
 .../java/org/apache/solr/handler/ClusterAPI.java   | 40 ++++++++++++++++++-
 .../client/solrj/cloud/DistribStateManager.java    | 23 +++++++++++
 3 files changed, 78 insertions(+), 30 deletions(-)

diff --git 
a/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
 
b/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
index f403aed..16ce53c 100644
--- 
a/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
+++ 
b/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
@@ -19,6 +19,8 @@ package org.apache.solr.cluster.placement.impl;
 
 import java.io.IOException;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
 import com.google.common.collect.Maps;
@@ -90,39 +92,26 @@ class SimpleClusterAbstractionsImpl {
 
   private static Set<String> filterNonDataNodes(SolrCloudManager 
solrCloudManager) {
     Set<String> liveNodes = 
solrCloudManager.getClusterStateProvider().getLiveNodes();
-    Set<String> liveNodesCopy = liveNodes;
+    AtomicReference<Set<String>> liveNodesCopy = new 
AtomicReference<>(liveNodes);
     try {
-      List<String> nodesWithRoles =  
solrCloudManager.getDistribStateManager().listData(ZkStateReader.NODE_ROLES);
-      if(!nodesWithRoles.isEmpty()) {
-        for (String node : nodesWithRoles) {
-          VersionedData data = null;
-          try {
-            data = solrCloudManager.getDistribStateManager()
-                    .getData(ZkStateReader.NODE_ROLES + "/" + node);
-          } catch (NoSuchElementException e) {
-            //this node probably went down
-            continue;
-          }
-          if(data != null && data.getData() != null && data.getData().length 
>0) {
-            @SuppressWarnings("unchecked")
-            Map<String,Object> map = (Map<String, Object>) 
Utils.fromJSON(data.getData());
-            if(Boolean.FALSE.equals(map.get("hasData"))) {
-              if(liveNodesCopy == liveNodes) {
-                //the map provided should not be modified. So we make a copy
-                liveNodesCopy = new HashSet<>(liveNodes);
-              }
-              liveNodesCopy.remove(node);
-            }
-          }
-        }
-      }
+     
solrCloudManager.getDistribStateManager().forEachChild(ZkStateReader.NODE_ROLES,
 (name, data) -> {
+       if(data != null && data.getData() != null && data.getData().length >0) {
+         @SuppressWarnings("unchecked")
+         Map<String,Object> map = (Map<String, Object>) 
Utils.fromJSON(data.getData());
+         if(Boolean.FALSE.equals(map.get("hasData"))) {
+           if(liveNodesCopy.get() == liveNodes) {
+             //the map provided should not be modified. So we make a copy
+             liveNodesCopy.set(new HashSet<>(liveNodes));
+           }
+           liveNodesCopy.get().remove(name);
+         }
+       }
+     });
 
-    } catch (NoSuchElementException nsee) {
-      //no problem
     } catch (Exception e) {
       throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unable to 
communicate with Zookeeper");
     }
-    return liveNodesCopy;
+    return liveNodesCopy.get();
   }
 
 
diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java 
b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
index be5c7de..6f6773d 100644
--- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
@@ -17,8 +17,7 @@
 
 package org.apache.solr.handler;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 import com.google.common.collect.Maps;
 import org.apache.solr.api.Command;
@@ -31,6 +30,7 @@ import org.apache.solr.cloud.ConfigSetCmds;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.annotation.JsonProperty;
 import org.apache.solr.common.cloud.ClusterProperties;
+import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ConfigSetParams;
@@ -73,6 +73,42 @@ public class ClusterAPI {
   }
 
   @EndPoint(method = GET,
+          path = "/cluster/node-roles",
+          permission = COLL_READ_PERM)
+  public void roles(SolrQueryRequest req, SolrQueryResponse rsp) throws 
Exception {
+    Map <String, Map<String,Object>> result = new LinkedHashMap<>();
+    
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager().
+            forEachChild(ZkStateReader.NODE_ROLES, (node, data) -> {
+      if(data != null && data.getData() != null) {
+        result.put(node, (Map<String, Object>) Utils.fromJSON(data.getData()));
+      }
+    });
+    rsp.add("node-roles", result);
+  }
+
+  @EndPoint(method = GET,
+          path = "/cluster/node-roles/{role}",
+          permission = COLL_READ_PERM)
+  public void rolesOfNode(SolrQueryRequest req, SolrQueryResponse rsp) throws 
Exception {
+    String role = req.getPathTemplateValues().get("role");
+
+    List<String> result = new ArrayList<>();
+    
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager().
+            forEachChild(ZkStateReader.NODE_ROLES, (node, data) -> {
+
+      if(data != null && data.getData() != null) {
+        @SuppressWarnings("unchecked")
+        Map<String, Object> roleData = (Map<String, Object>) 
Utils.fromJSON(data.getData());
+        if(role.equals(roleData.get("role"))) {
+          result.add(node);
+        }
+      }
+    });
+    rsp.add("nodes", result);
+  }
+
+
+  @EndPoint(method = GET,
       path = "/cluster/aliases",
       permission = COLL_READ_PERM)
   public void aliases(SolrQueryRequest req, SolrQueryResponse rsp) throws 
Exception {
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/cloud/DistribStateManager.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/cloud/DistribStateManager.java
index feae27f..ebd4db7 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/cloud/DistribStateManager.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/cloud/DistribStateManager.java
@@ -24,8 +24,10 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.NoSuchElementException;
 
+import java.util.function.BiConsumer;
 import org.apache.solr.common.SolrCloseable;
 import org.apache.solr.common.cloud.PerReplicaStates;
+import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Op;
@@ -141,4 +143,25 @@ public interface DistribStateManager extends SolrCloseable 
{
       }
     }
   }
+  default void  forEachChild(String path,  BiConsumer<String, VersionedData> 
fun)
+          throws InterruptedException, IOException, KeeperException {
+    List<String> children = null;
+    try {
+      children = listData(ZkStateReader.NODE_ROLES);
+    } catch (NoSuchElementException e) {
+      return;
+    }
+    if(!children.isEmpty()) {
+      for (String node : children) {
+        VersionedData data = null;
+        try {
+          data = getData(ZkStateReader.NODE_ROLES + "/" + node);
+        } catch (NoSuchElementException e) {
+          //this node probably was deleted
+          continue;
+        }
+        fun.accept(node, data);
+      }
+    }
+  }
 }

Reply via email to