org.elasticsearch.cluster.node.DiscoveryNodes Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.
*/
package org.elasticsearch.cluster.node;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.collect.UnmodifiableIterator;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.transport.TransportAddress;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.common.collect.Lists.*;
import static org.elasticsearch.common.collect.Maps.*;
/**
* @author kimchy (Shay Banon)
*/
public class DiscoveryNodes implements Iterable {
public static final DiscoveryNodes EMPTY_NODES = newNodesBuilder().build();
private final ImmutableMap nodes;
private final ImmutableMap dataNodes;
private final ImmutableMap masterNodes;
private final String masterNodeId;
private final String localNodeId;
private DiscoveryNodes(ImmutableMap nodes, ImmutableMap dataNodes, ImmutableMap masterNodes, String masterNodeId, String localNodeId) {
this.nodes = nodes;
this.dataNodes = dataNodes;
this.masterNodes = masterNodes;
this.masterNodeId = masterNodeId;
this.localNodeId = localNodeId;
}
@Override public UnmodifiableIterator iterator() {
return nodes.values().iterator();
}
/**
* Is this a valid nodes that has the minimal information set. The minimal set is defined
* by the localNodeId being set.
*/
public boolean valid() {
return localNodeId != null;
}
/**
* Returns true if the local node is the master node.
*/
public boolean localNodeMaster() {
if (localNodeId == null) {
// we don't know yet the local node id, return false
return false;
}
return localNodeId.equals(masterNodeId);
}
public int size() {
return nodes.size();
}
public int getSize() {
return size();
}
public ImmutableMap nodes() {
return this.nodes;
}
public ImmutableMap getNodes() {
return nodes();
}
public ImmutableMap dataNodes() {
return this.dataNodes;
}
public ImmutableMap getDataNodes() {
return dataNodes();
}
public ImmutableMap masterNodes() {
return this.masterNodes;
}
public ImmutableMap getMasterNodes() {
return masterNodes();
}
public ImmutableMap masterAndDataNodes() {
return MapBuilder.newMapBuilder().putAll(dataNodes).putAll(masterNodes).immutableMap();
}
public DiscoveryNode get(String nodeId) {
return nodes.get(nodeId);
}
public boolean nodeExists(String nodeId) {
return nodes.containsKey(nodeId);
}
public String masterNodeId() {
return this.masterNodeId;
}
public String getMasterNodeId() {
return masterNodeId();
}
public String localNodeId() {
return this.localNodeId;
}
public String getLocalNodeId() {
return localNodeId();
}
public DiscoveryNode localNode() {
return nodes.get(localNodeId);
}
public DiscoveryNode getLocalNode() {
return localNode();
}
public DiscoveryNode masterNode() {
return nodes.get(masterNodeId);
}
public DiscoveryNode getMasterNode() {
return masterNode();
}
public DiscoveryNode findByAddress(TransportAddress address) {
for (DiscoveryNode node : nodes.values()) {
if (node.address().equals(address)) {
return node;
}
}
return null;
}
public boolean isAllNodes(String... nodesIds) {
return nodesIds == null || nodesIds.length == 0 || (nodesIds.length == 1 && nodesIds[0].equals("_all"));
}
public String[] resolveNodes(String... nodesIds) {
if (isAllNodes(nodesIds)) {
int index = 0;
nodesIds = new String[nodes.size()];
for (DiscoveryNode node : this) {
nodesIds[index++] = node.id();
}
return nodesIds;
} else {
Set resolvedNodesIds = new HashSet(nodesIds.length);
for (String nodeId : nodesIds) {
if (nodeId.equals("_local")) {
resolvedNodesIds.add(localNodeId());
} else if (nodeId.equals("_master")) {
resolvedNodesIds.add(masterNodeId());
} else if (nodeExists(nodeId)) {
resolvedNodesIds.add(nodeId);
} else {
// not a node id, try and search by name
for (DiscoveryNode node : this) {
if (Regex.simpleMatch(nodeId, node.name())) {
resolvedNodesIds.add(node.id());
}
}
for (DiscoveryNode node : this) {
if (node.address().match(nodeId)) {
resolvedNodesIds.add(node.id());
}
}
int index = nodeId.indexOf(':');
if (index != -1) {
String matchAttrName = nodeId.substring(0, index);
String matchAttrValue = nodeId.substring(index + 1);
for (DiscoveryNode node : this) {
for (Map.Entry entry : node.attributes().entrySet()) {
String attrName = entry.getKey();
String attrValue = entry.getValue();
if (Regex.simpleMatch(matchAttrName, attrName) && Regex.simpleMatch(matchAttrValue, attrValue)) {
resolvedNodesIds.add(node.id());
}
}
}
}
}
}
return resolvedNodesIds.toArray(new String[resolvedNodesIds.size()]);
}
}
public DiscoveryNodes removeDeadMembers(Set newNodes, String masterNodeId) {
Builder builder = new Builder().masterNodeId(masterNodeId).localNodeId(localNodeId);
for (DiscoveryNode node : this) {
if (newNodes.contains(node.id())) {
builder.put(node);
}
}
return builder.build();
}
public DiscoveryNodes newNode(DiscoveryNode node) {
return new Builder().putAll(this).put(node).build();
}
/**
* Returns the changes comparing this nodes to the provided nodes.
*/
public Delta delta(DiscoveryNodes other) {
List removed = newArrayList();
List added = newArrayList();
for (DiscoveryNode node : other) {
if (!this.nodeExists(node.id())) {
removed.add(node);
}
}
for (DiscoveryNode node : this) {
if (!other.nodeExists(node.id())) {
added.add(node);
}
}
DiscoveryNode previousMasterNode = null;
DiscoveryNode newMasterNode = null;
if (masterNodeId != null) {
if (other.masterNodeId == null || !other.masterNodeId.equals(masterNodeId)) {
previousMasterNode = other.masterNode();
newMasterNode = masterNode();
}
}
return new Delta(previousMasterNode, newMasterNode, localNodeId, ImmutableList.copyOf(removed), ImmutableList.copyOf(added));
}
@Override public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
for (DiscoveryNode node : this) {
sb.append(node).append(',');
}
sb.append("}");
return sb.toString();
}
public String prettyPrint() {
StringBuilder sb = new StringBuilder();
sb.append("nodes: \n");
for (DiscoveryNode node : this) {
sb.append(" ").append(node);
if (node == localNode()) {
sb.append(", local");
}
if (node == masterNode()) {
sb.append(", master");
}
sb.append("\n");
}
return sb.toString();
}
public Delta emptyDelta() {
return new Delta(null, null, localNodeId, DiscoveryNode.EMPTY_LIST, DiscoveryNode.EMPTY_LIST);
}
public static class Delta {
private final String localNodeId;
private final DiscoveryNode previousMasterNode;
private final DiscoveryNode newMasterNode;
private final ImmutableList removed;
private final ImmutableList added;
public Delta(String localNodeId, ImmutableList removed, ImmutableList added) {
this(null, null, localNodeId, removed, added);
}
public Delta(@Nullable DiscoveryNode previousMasterNode, @Nullable DiscoveryNode newMasterNode, String localNodeId, ImmutableList removed, ImmutableList added) {
this.previousMasterNode = previousMasterNode;
this.newMasterNode = newMasterNode;
this.localNodeId = localNodeId;
this.removed = removed;
this.added = added;
}
public boolean hasChanges() {
return masterNodeChanged() || !removed.isEmpty() || !added.isEmpty();
}
public boolean masterNodeChanged() {
return newMasterNode != null;
}
public DiscoveryNode previousMasterNode() {
return previousMasterNode;
}
public DiscoveryNode newMasterNode() {
return newMasterNode;
}
public boolean removed() {
return !removed.isEmpty();
}
public ImmutableList removedNodes() {
return removed;
}
public boolean added() {
return !added.isEmpty();
}
public ImmutableList addedNodes() {
return added;
}
public String shortSummary() {
StringBuilder sb = new StringBuilder();
if (!removed() && masterNodeChanged()) {
if (newMasterNode.id().equals(localNodeId)) {
// we are the master, no nodes we removed, we are actually the first master
sb.append("new_master ").append(newMasterNode());
} else {
// we are not the master, so we just got this event. No nodes were removed, so its not a *new* master
sb.append("detected_master ").append(newMasterNode());
}
} else {
if (masterNodeChanged()) {
sb.append("master {new ").append(newMasterNode());
if (previousMasterNode() != null) {
sb.append(", previous ").append(previousMasterNode());
}
sb.append("}");
}
if (removed()) {
if (masterNodeChanged()) {
sb.append(", ");
}
sb.append("removed {");
for (DiscoveryNode node : removedNodes()) {
sb.append(node).append(',');
}
sb.append("}");
}
}
if (added()) {
// don't print if there is one added, and it is us
if (!(addedNodes().size() == 1 && addedNodes().get(0).id().equals(localNodeId))) {
if (removed() || masterNodeChanged()) {
sb.append(", ");
}
sb.append("added {");
for (DiscoveryNode node : addedNodes()) {
if (!node.id().equals(localNodeId)) {
// don't print ourself
sb.append(node).append(',');
}
}
sb.append("}");
}
}
return sb.toString();
}
}
public static Builder newNodesBuilder() {
return new Builder();
}
public static class Builder {
private Map nodes = newHashMap();
private String masterNodeId;
private String localNodeId;
public Builder putAll(DiscoveryNodes nodes) {
this.masterNodeId = nodes.masterNodeId();
this.localNodeId = nodes.localNodeId();
for (DiscoveryNode node : nodes) {
put(node);
}
return this;
}
public Builder put(DiscoveryNode node) {
nodes.put(node.id(), node);
return this;
}
public Builder putAll(Iterable nodes) {
for (DiscoveryNode node : nodes) {
put(node);
}
return this;
}
public Builder remove(String nodeId) {
nodes.remove(nodeId);
return this;
}
public Builder masterNodeId(String masterNodeId) {
this.masterNodeId = masterNodeId;
return this;
}
public Builder localNodeId(String localNodeId) {
this.localNodeId = localNodeId;
return this;
}
public DiscoveryNodes build() {
ImmutableMap.Builder dataNodesBuilder = ImmutableMap.builder();
ImmutableMap.Builder masterNodesBuilder = ImmutableMap.builder();
for (Map.Entry nodeEntry : nodes.entrySet()) {
if (nodeEntry.getValue().dataNode()) {
dataNodesBuilder.put(nodeEntry.getKey(), nodeEntry.getValue());
}
if (nodeEntry.getValue().masterNode()) {
masterNodesBuilder.put(nodeEntry.getKey(), nodeEntry.getValue());
}
}
return new DiscoveryNodes(ImmutableMap.copyOf(nodes), dataNodesBuilder.build(), masterNodesBuilder.build(), masterNodeId, localNodeId);
}
public static void writeTo(DiscoveryNodes nodes, StreamOutput out) throws IOException {
if (nodes.masterNodeId() == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeUTF(nodes.masterNodeId);
}
out.writeVInt(nodes.size());
for (DiscoveryNode node : nodes) {
node.writeTo(out);
}
}
public static DiscoveryNodes readFrom(StreamInput in, @Nullable DiscoveryNode localNode) throws IOException {
Builder builder = new Builder();
if (in.readBoolean()) {
builder.masterNodeId(in.readUTF());
}
if (localNode != null) {
builder.localNodeId(localNode.id());
}
int size = in.readVInt();
for (int i = 0; i < size; i++) {
DiscoveryNode node = DiscoveryNode.readNode(in);
if (localNode != null && node.id().equals(localNode.id())) {
// reuse the same instance of our address and local node id for faster equality
node = localNode;
}
builder.put(node);
}
return builder.build();
}
}
}