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); + } + } + } }
