diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java index 73d2c35da40..5f33d01a370 100644 --- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java +++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java @@ -33,6 +33,7 @@ import java.lang.reflect.Array; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -2902,10 +2903,8 @@ public boolean checkIfCoreNodeNameAlreadyExists(CoreDescriptor dcore) { */ public Collection publishNodeAsDown(String nodeName) { log.info("Publish node={} as DOWN", nodeName); + Map> replicasPerCollectionOnNode = getReplicasPerCollectionOnThisNode(); - ClusterState clusterState = getClusterState(); - Map> replicasPerCollectionOnNode = - clusterState.getReplicaNamesPerCollectionOnNode(nodeName); if (distributedClusterStateUpdater.isDistributedStateUpdate()) { // Note that with the current implementation, when distributed cluster state updates are // enabled, we mark the node down synchronously from this thread, whereas the Overseer cluster @@ -2917,20 +2916,18 @@ public Collection publishNodeAsDown(String nodeName) { } else { try { boolean sendToOverseer = false; - for (String collName : replicasPerCollectionOnNode.keySet()) { - DocCollection coll = null; - if (collName != null - && (coll = zkStateReader.getCollection(collName)) != null - && coll.isPerReplicaState()) { + for (DocCollection coll : replicasPerCollectionOnNode.keySet()) { + if (coll.isPerReplicaState()) { PerReplicaStatesOps.downReplicas( - replicasPerCollectionOnNode.get(collName).stream() + replicasPerCollectionOnNode.get(coll).stream() .map(Replica::getName) .collect(Collectors.toList()), PerReplicaStatesOps.fetch( coll.getZNode(), zkClient, coll.getPerReplicaStates())) .persist(coll.getZNode(), zkClient); - } - if (coll != null && !coll.isPerReplicaState()) { + } else { + // if this node contains any non PRS collection, then we need to notify the overseer as overseer + // manages the replica state for non PRS collections sendToOverseer = true; } } @@ -2958,7 +2955,42 @@ public Collection publishNodeAsDown(String nodeName) { log.warn("Could not publish node as down: ", e); } } - return replicasPerCollectionOnNode.keySet(); + return replicasPerCollectionOnNode.keySet().stream().map(DocCollection::getName).collect(Collectors.toSet()); + } + + private Map> getReplicasPerCollectionOnThisNode() { + Map> result = new HashMap<>(); + if (cc.isStatusLoadComplete()) { + Set processedCollections = new HashSet<>(); + for (CoreDescriptor cd : cc.getCoreDescriptors()) { + String collName = cd.getCollectionName(); + DocCollection coll; + if (collName != null + && processedCollections.add(collName) + && (coll = zkStateReader.getCollection(collName)) != null) { + final List replicasOnThisNode = new ArrayList<>(); + coll.forEachReplica( + (s, replica) -> { + if (replica.getNodeName().equals(nodeName)) { + replicasOnThisNode.add(replica); + } + }); + result.put(coll, replicasOnThisNode); + } + } + } else { + getClusterState().getCollectionStates().values().stream() + .map(ClusterState.CollectionRef::get) + .filter(Objects::nonNull) + .forEach( + col -> { + List replicas = col.getReplicas(nodeName); + if (replicas != null && !replicas.isEmpty()) { + result.put(col, replicas); + } + }); + } + return result; } /** diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java index 5f7a23f2ed0..b3e18dea862 100644 --- a/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java +++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java @@ -211,21 +211,6 @@ public String getShardId(String collectionName, String nodeName, String coreName return null; } - public Map> getReplicaNamesPerCollectionOnNode(final String nodeName) { - Map> replicaNamesPerCollectionOnNode = new HashMap<>(); - collectionStates.values().stream() - .map(CollectionRef::get) - .filter(Objects::nonNull) - .forEach( - col -> { - List replicas = col.getReplicas(nodeName); - if (replicas != null && !replicas.isEmpty()) { - replicaNamesPerCollectionOnNode.put(col.getName(), replicas); - } - }); - return replicaNamesPerCollectionOnNode; - } - /** Check if node is alive. */ public boolean liveNodesContain(String name) { return liveNodes.contains(name);