From dc6eca4e2e4b80fc69100bbf41840f4a48b5280b Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Thu, 15 Nov 2018 12:57:19 +0300 Subject: [PATCH 01/22] CoordinationState inside ClusterState --- .../bootstrap/BootstrapConfiguration.java | 2 +- .../TransportAddVotingTombstonesAction.java | 6 +- .../TransportClearVotingTombstonesAction.java | 9 +- .../state/TransportClusterStateAction.java | 4 +- .../elasticsearch/cluster/ClusterState.java | 226 +++------------- .../coordination/CoordinationMetaData.java | 250 ++++++++++++++++++ .../coordination/CoordinationState.java | 6 +- .../cluster/coordination/Coordinator.java | 17 +- .../cluster/coordination/JoinHelper.java | 4 +- .../cluster/coordination/Reconfigurator.java | 7 +- .../BootstrapConfigurationTests.java | 2 +- .../AddVotingTombstonesRequestTests.java | 3 +- ...ansportAddVotingTombstonesActionTests.java | 28 +- ...sportClearVotingTombstonesActionTests.java | 7 +- .../reroute/ClusterRerouteResponseTests.java | 16 +- .../cluster/ClusterStateDiffIT.java | 18 +- .../cluster/ClusterStateTests.java | 73 ----- .../CoordinationMetaDataTests.java | 149 +++++++++++ .../coordination/CoordinationStateTests.java | 16 +- .../coordination/CoordinatorTests.java | 2 +- .../cluster/coordination/MessagesTests.java | 4 +- .../cluster/coordination/NodeJoinTests.java | 11 +- .../coordination/PreVoteCollectorTests.java | 2 +- .../coordination/PublicationTests.java | 4 +- .../PublicationTransportHandlerTests.java | 5 +- .../coordination/ReconfiguratorTests.java | 25 +- .../zen/PublishClusterStateActionTests.java | 2 +- .../test/ESSingleNodeTestCase.java | 6 +- 28 files changed, 559 insertions(+), 345 deletions(-) create mode 100644 server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java create mode 100644 server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfiguration.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfiguration.java index f6207459c9616..822287af77465 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfiguration.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfiguration.java @@ -19,7 +19,7 @@ package org.elasticsearch.action.admin.cluster.bootstrap; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.io.stream.StreamInput; diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java index 34f452988d209..abd2e37f29286 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java @@ -24,12 +24,12 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.Builder; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.ClusterStateObserver.Listener; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; @@ -90,9 +90,9 @@ public ClusterState execute(ClusterState currentState) { assert resolvedNodes == null : resolvedNodes; resolvedNodes = resolveNodesAndCheckMaximum(request, currentState); - final Builder builder = ClusterState.builder(currentState); + CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData()); resolvedNodes.forEach(builder::addVotingTombstone); - final ClusterState newState = builder.build(); + final ClusterState newState = ClusterState.builder(currentState).coordinationMetaData(builder.build()).build(); assert newState.getVotingTombstones().size() <= MAXIMUM_VOTING_TOMBSTONES_SETTING.get(currentState.metaData().settings()); return newState; } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java index 14592b37ed13f..4aa1fdf09d965 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java @@ -24,12 +24,12 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.Builder; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.ClusterStateObserver.Listener; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; @@ -119,9 +119,10 @@ private void submitClearTombstonesTask(ClearVotingTombstonesRequest request, lon clusterService.submitStateUpdateTask("clear-voting-tombstones", new ClusterStateUpdateTask(Priority.URGENT) { @Override public ClusterState execute(ClusterState currentState) { - final Builder builder = ClusterState.builder(currentState); - builder.clearVotingTombstones(); - return builder.build(); + return ClusterState.builder(currentState) + .coordinationMetaData(CoordinationMetaData.builder( + currentState.coordinationMetaData()).clearVotingTombstones().build()) + .build(); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java index 3fa123569ff7a..f405363d97bc1 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java @@ -77,11 +77,9 @@ protected void masterOperation(final ClusterStateRequest request, final ClusterS ClusterState currentState = clusterService.state(); logger.trace("Serving cluster state request using version {}", currentState.version()); ClusterState.Builder builder = ClusterState.builder(currentState.getClusterName()); - builder.term(currentState.term()); builder.version(currentState.version()); builder.stateUUID(currentState.stateUUID()); - builder.lastCommittedConfiguration(currentState.getLastCommittedConfiguration()); - builder.lastAcceptedConfiguration(currentState.getLastAcceptedConfiguration()); + builder.coordinationMetaData(currentState.coordinationMetaData()); if (request.nodes()) { builder.nodes(currentState.nodes()); } diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index 90f8c9317fa3f..4fc2f30095b2a 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -27,6 +27,7 @@ import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlocks; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; @@ -51,10 +52,8 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.io.stream.VersionedNamedWriteable; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.xcontent.ToXContentFragment; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentHelper; @@ -62,18 +61,12 @@ import org.elasticsearch.discovery.zen.PublishClusterStateAction; import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; -import java.util.HashSet; import java.util.Locale; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; /** * Represents the current state of the cluster. @@ -164,8 +157,6 @@ default boolean isPrivate() { public static final long UNKNOWN_VERSION = -1; - private final long term; - private final long version; private final String stateUUID; @@ -184,26 +175,19 @@ default boolean isPrivate() { private final boolean wasReadFromDiff; - private final VotingConfiguration lastCommittedConfiguration; - - private final VotingConfiguration lastAcceptedConfiguration; - - private final Set votingTombstones; + private final CoordinationMetaData coordinationMetaData; // built on demand private volatile RoutingNodes routingNodes; - public ClusterState(long term, long version, String stateUUID, ClusterState state) { - this(state.clusterName, term, version, stateUUID, state.metaData(), state.routingTable(), state.nodes(), state.blocks(), - state.customs(), state.getLastCommittedConfiguration(), state.getLastAcceptedConfiguration(), state.getVotingTombstones(), - false); + public ClusterState(long version, String stateUUID, ClusterState state) { + this(state.clusterName, version, stateUUID, state.metaData(), state.routingTable(), state.nodes(), state.blocks(), + state.customs(), state.coordinationMetaData(), false); } - public ClusterState(ClusterName clusterName, long term, long version, String stateUUID, MetaData metaData, RoutingTable routingTable, + public ClusterState(ClusterName clusterName, long version, String stateUUID, MetaData metaData, RoutingTable routingTable, DiscoveryNodes nodes, ClusterBlocks blocks, ImmutableOpenMap customs, - VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration, - Set votingTombstones, boolean wasReadFromDiff) { - this.term = term; + CoordinationMetaData coordinationMetaData, boolean wasReadFromDiff) { this.version = version; this.stateUUID = stateUUID; this.clusterName = clusterName; @@ -212,14 +196,12 @@ public ClusterState(ClusterName clusterName, long term, long version, String sta this.nodes = nodes; this.blocks = blocks; this.customs = customs; - this.lastCommittedConfiguration = lastCommittedConfiguration; - this.lastAcceptedConfiguration = lastAcceptedConfiguration; - this.votingTombstones = votingTombstones; + this.coordinationMetaData = coordinationMetaData; this.wasReadFromDiff = wasReadFromDiff; } public long term() { - return term; + return coordinationMetaData.term(); } public long version() { @@ -254,6 +236,10 @@ public MetaData getMetaData() { return metaData(); } + public CoordinationMetaData coordinationMetaData() { + return coordinationMetaData; + } + public RoutingTable routingTable() { return routingTable; } @@ -286,16 +272,16 @@ public ClusterName getClusterName() { return this.clusterName; } - public VotingConfiguration getLastAcceptedConfiguration() { - return lastAcceptedConfiguration; + public CoordinationMetaData.VotingConfiguration getLastAcceptedConfiguration() { + return coordinationMetaData.getLastAcceptedConfiguration(); } - public VotingConfiguration getLastCommittedConfiguration() { - return lastCommittedConfiguration; + public CoordinationMetaData.VotingConfiguration getLastCommittedConfiguration() { + return coordinationMetaData.getLastCommittedConfiguration(); } public Set getVotingTombstones() { - return votingTombstones; + return coordinationMetaData.getVotingTombstones(); } // Used for testing and logging to determine how this cluster state was send over the wire @@ -317,16 +303,17 @@ public RoutingNodes getRoutingNodes() { @Override public String toString() { StringBuilder sb = new StringBuilder(); + final String TAB = " "; sb.append("cluster uuid: ").append(metaData.clusterUUID()).append("\n"); - sb.append("term: ").append(term).append("\n"); sb.append("version: ").append(version).append("\n"); sb.append("state uuid: ").append(stateUUID).append("\n"); - sb.append("last committed config: ").append(getLastCommittedConfiguration()).append("\n"); - sb.append("last accepted config: ").append(getLastAcceptedConfiguration()).append("\n"); - sb.append("voting tombstones: ").append(votingTombstones).append("\n"); + sb.append("coordination_metadata:\n"); + sb.append(TAB).append("term: ").append(coordinationMetaData.term()).append("\n"); + sb.append(TAB).append("last_committed_config: ").append(coordinationMetaData.getLastCommittedConfiguration()).append("\n"); + sb.append(TAB).append("last_accepted_config: ").append(coordinationMetaData.getLastAcceptedConfiguration()).append("\n"); + sb.append(TAB).append("voting tombstones: ").append(coordinationMetaData.getVotingTombstones()).append("\n"); sb.append("from_diff: ").append(wasReadFromDiff).append("\n"); sb.append("meta data version: ").append(metaData.version()).append("\n"); - final String TAB = " "; for (IndexMetaData indexMetaData : metaData) { sb.append(TAB).append(indexMetaData.getIndex()); sb.append(": v[").append(indexMetaData.getVersion()) @@ -434,12 +421,11 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.field("cluster_uuid", metaData().clusterUUID()); if (metrics.contains(Metric.VERSION)) { - builder.field("term", term); builder.field("version", version); builder.field("state_uuid", stateUUID); - builder.field("last_committed_config", lastCommittedConfiguration); - builder.field("last_accepted_config", lastAcceptedConfiguration); - // TODO include voting tombstones here + builder.startObject("coordination"); + coordinationMetaData.toXContent(builder, params); + builder.endObject(); } if (metrics.contains(Metric.MASTER_NODE)) { @@ -639,28 +625,22 @@ public static Builder builder(ClusterState state) { public static class Builder { private final ClusterName clusterName; - private long term = 0; private long version = 0; private String uuid = UNKNOWN_UUID; - private VotingConfiguration lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG; - private VotingConfiguration lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG; + private CoordinationMetaData coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; private MetaData metaData = MetaData.EMPTY_META_DATA; private RoutingTable routingTable = RoutingTable.EMPTY_ROUTING_TABLE; private DiscoveryNodes nodes = DiscoveryNodes.EMPTY_NODES; private ClusterBlocks blocks = ClusterBlocks.EMPTY_CLUSTER_BLOCK; private final ImmutableOpenMap.Builder customs; - private final Set votingTombstones = new HashSet<>(); private boolean fromDiff; public Builder(ClusterState state) { this.clusterName = state.clusterName; - this.term = state.term(); this.version = state.version(); this.uuid = state.stateUUID(); - this.lastCommittedConfiguration = state.getLastCommittedConfiguration(); - this.lastAcceptedConfiguration = state.getLastAcceptedConfiguration(); - this.votingTombstones.addAll(state.getVotingTombstones()); + this.coordinationMetaData = state.coordinationMetaData(); this.nodes = state.nodes(); this.routingTable = state.routingTable(); this.metaData = state.metaData(); @@ -710,11 +690,6 @@ public Builder blocks(ClusterBlocks blocks) { return this; } - public Builder term(long term) { - this.term = term; - return this; - } - public Builder version(long version) { this.version = version; return this; @@ -731,13 +706,8 @@ public Builder stateUUID(String uuid) { return this; } - public Builder lastCommittedConfiguration(VotingConfiguration config) { - this.lastCommittedConfiguration = config; - return this; - } - - public Builder lastAcceptedConfiguration(VotingConfiguration config) { - this.lastAcceptedConfiguration = config; + public Builder coordinationMetaData(CoordinationMetaData coordinationMetaData) { + this.coordinationMetaData = coordinationMetaData; return this; } @@ -765,9 +735,8 @@ public ClusterState build() { if (UNKNOWN_UUID.equals(uuid)) { uuid = UUIDs.randomBase64UUID(); } - return new ClusterState(clusterName, term, version, uuid, metaData, routingTable, nodes, blocks, customs.build(), - lastCommittedConfiguration, lastAcceptedConfiguration, Collections.unmodifiableSet(new HashSet<>(votingTombstones)), - fromDiff); + return new ClusterState(clusterName, version, uuid, metaData, routingTable, nodes, blocks, customs.build(), + coordinationMetaData, fromDiff); } public static byte[] toBytes(ClusterState state) throws IOException { @@ -785,14 +754,6 @@ public static ClusterState fromBytes(byte[] data, DiscoveryNode localNode, Named return readFrom(in, localNode); } - - public void addVotingTombstone(DiscoveryNode tombstone) { - votingTombstones.add(tombstone); - } - - public void clearVotingTombstones() { - votingTombstones.clear(); - } } @Override @@ -807,15 +768,10 @@ public static Diff readDiffFrom(StreamInput in, DiscoveryNode loca public static ClusterState readFrom(StreamInput in, DiscoveryNode localNode) throws IOException { ClusterName clusterName = new ClusterName(in); Builder builder = new Builder(clusterName); - if (in.getVersion().onOrAfter(Version.V_7_0_0)) { - builder.term = in.readLong(); - } builder.version = in.readLong(); builder.uuid = in.readString(); if (in.getVersion().onOrAfter(Version.V_7_0_0)) { - builder.lastCommittedConfiguration(new VotingConfiguration(in)); - builder.lastAcceptedConfiguration(new VotingConfiguration(in)); - in.readSet(DiscoveryNode::new).forEach(builder::addVotingTombstone); + builder.coordinationMetaData(new CoordinationMetaData(in)); } builder.metaData = MetaData.readFrom(in); builder.routingTable = RoutingTable.readFrom(in); @@ -832,15 +788,10 @@ public static ClusterState readFrom(StreamInput in, DiscoveryNode localNode) thr @Override public void writeTo(StreamOutput out) throws IOException { clusterName.writeTo(out); - if (out.getVersion().onOrAfter(Version.V_7_0_0)) { - out.writeLong(term); - } out.writeLong(version); out.writeString(stateUUID); if (out.getVersion().onOrAfter(Version.V_7_0_0)) { - lastCommittedConfiguration.writeTo(out); - lastAcceptedConfiguration.writeTo(out); - out.writeCollection(votingTombstones, (o, v) -> v.writeTo(o)); + coordinationMetaData.writeTo(out); } metaData.writeTo(out); routingTable.writeTo(out); @@ -863,8 +814,6 @@ public void writeTo(StreamOutput out) throws IOException { private static class ClusterStateDiff implements Diff { - private final long toTerm; - private final long toVersion; private final String fromUuid; @@ -873,11 +822,7 @@ private static class ClusterStateDiff implements Diff { private final ClusterName clusterName; - private final VotingConfiguration lastCommittedConfiguration; - - private final VotingConfiguration lastAcceptedConfiguration; - - private final Set votingTombstones; + private final CoordinationMetaData coordinationMetaData; private final Diff routingTable; @@ -892,12 +837,9 @@ private static class ClusterStateDiff implements Diff { ClusterStateDiff(ClusterState before, ClusterState after) { fromUuid = before.stateUUID; toUuid = after.stateUUID; - toTerm = after.term; toVersion = after.version; clusterName = after.clusterName; - lastCommittedConfiguration = after.lastCommittedConfiguration; - lastAcceptedConfiguration = after.lastAcceptedConfiguration; - votingTombstones = after.votingTombstones; + coordinationMetaData = after.coordinationMetaData; routingTable = after.routingTable.diff(before.routingTable); nodes = after.nodes.diff(before.nodes); metaData = after.metaData.diff(before.metaData); @@ -909,20 +851,11 @@ private static class ClusterStateDiff implements Diff { clusterName = new ClusterName(in); fromUuid = in.readString(); toUuid = in.readString(); - if (in.getVersion().onOrAfter(Version.V_7_0_0)) { - toTerm = in.readLong(); - } else { - toTerm = 0L; - } toVersion = in.readLong(); if (in.getVersion().onOrAfter(Version.V_7_0_0)) { - lastCommittedConfiguration = new VotingConfiguration(in); - lastAcceptedConfiguration = new VotingConfiguration(in); - votingTombstones = in.readSet(DiscoveryNode::new); + coordinationMetaData = new CoordinationMetaData(in); } else { - lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG; - lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG; - votingTombstones = Collections.emptySet(); + coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; } routingTable = RoutingTable.readDiffFrom(in); nodes = DiscoveryNodes.readDiffFrom(in, localNode); @@ -936,14 +869,9 @@ public void writeTo(StreamOutput out) throws IOException { clusterName.writeTo(out); out.writeString(fromUuid); out.writeString(toUuid); - if (out.getVersion().onOrAfter(Version.V_7_0_0)) { - out.writeLong(toTerm); - } out.writeLong(toVersion); if (out.getVersion().onOrAfter(Version.V_7_0_0)) { - lastCommittedConfiguration.writeTo(out); - lastAcceptedConfiguration.writeTo(out); - out.writeCollection(votingTombstones, (o, v) -> v.writeTo(o)); + coordinationMetaData.writeTo(out); } routingTable.writeTo(out); nodes.writeTo(out); @@ -963,11 +891,8 @@ public ClusterState apply(ClusterState state) { throw new IncompatibleClusterStateVersionException(state.version, state.stateUUID, toVersion, fromUuid); } builder.stateUUID(toUuid); - builder.term(toTerm); builder.version(toVersion); - builder.lastCommittedConfiguration(lastCommittedConfiguration); - builder.lastAcceptedConfiguration(lastAcceptedConfiguration); - votingTombstones.forEach(builder::addVotingTombstone); + builder.coordinationMetaData(coordinationMetaData); builder.routingTable(routingTable.apply(state.routingTable)); builder.nodes(nodes.apply(state.nodes)); builder.metaData(metaData.apply(state.metaData)); @@ -978,73 +903,4 @@ public ClusterState apply(ClusterState state) { } } - - /** - * A collection of persistent node ids, denoting the voting configuration for cluster state changes. - */ - public static class VotingConfiguration implements Writeable, ToXContentFragment { - - public static final VotingConfiguration EMPTY_CONFIG = new VotingConfiguration(Collections.emptySet()); - - private final Set nodeIds; - - public VotingConfiguration(Set nodeIds) { - this.nodeIds = Collections.unmodifiableSet(new HashSet<>(nodeIds)); - } - - public VotingConfiguration(StreamInput in) throws IOException { - nodeIds = Collections.unmodifiableSet(Sets.newHashSet(in.readStringArray())); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeStringArray(nodeIds.toArray(new String[nodeIds.size()])); - } - - public boolean hasQuorum(Collection votes) { - final HashSet intersection = new HashSet<>(nodeIds); - intersection.retainAll(votes); - return intersection.size() * 2 > nodeIds.size(); - } - - public Set getNodeIds() { - return nodeIds; - } - - @Override - public String toString() { - return "VotingConfiguration{" + String.join(",", nodeIds) + "}"; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - VotingConfiguration that = (VotingConfiguration) o; - return Objects.equals(nodeIds, that.nodeIds); - } - - @Override - public int hashCode() { - return Objects.hash(nodeIds); - } - - public boolean isEmpty() { - return nodeIds.isEmpty(); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startArray(); - for (String nodeId : nodeIds) { - builder.value(nodeId); - } - return builder.endArray(); - } - - public static VotingConfiguration of(DiscoveryNode... nodes) { - // this could be used in many more places - TODO use this where appropriate - return new VotingConfiguration(Arrays.stream(nodes).map(DiscoveryNode::getId).collect(Collectors.toSet())); - } - } } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java new file mode 100644 index 0000000000000..5b06b324b2043 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java @@ -0,0 +1,250 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.coordination; + +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.util.set.Sets; +import org.elasticsearch.common.xcontent.ToXContentFragment; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class CoordinationMetaData implements Writeable, ToXContentFragment { + + public static final CoordinationMetaData EMPTY_META_DATA = builder().build(); + + private final long term; + + private final VotingConfiguration lastCommittedConfiguration; + + private final VotingConfiguration lastAcceptedConfiguration; + + private final Set votingTombstones; + + CoordinationMetaData(long term, VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration, + Set votingTombstones) { + this.term = term; + this.lastCommittedConfiguration = lastCommittedConfiguration; + this.lastAcceptedConfiguration = lastAcceptedConfiguration; + this.votingTombstones = votingTombstones; + } + + public CoordinationMetaData(StreamInput in) throws IOException { + term = in.readLong(); + lastCommittedConfiguration = new VotingConfiguration(in); + lastAcceptedConfiguration = new VotingConfiguration(in); + votingTombstones = Collections.unmodifiableSet(in.readSet(DiscoveryNode::new)); + } + + public static Builder builder() { + return new Builder(); + } + + public static Builder builder(CoordinationMetaData coordinationMetaData) { + return new Builder(coordinationMetaData); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeLong(term); + lastCommittedConfiguration.writeTo(out); + lastAcceptedConfiguration.writeTo(out); + out.writeCollection(votingTombstones, (o, v) -> v.writeTo(o)); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder + .field("term", term) + .field("last_committed_config", lastCommittedConfiguration) + .field("last_accepted_config", lastAcceptedConfiguration); + // TODO include voting tombstones here + } + + public long term() { + return term; + } + + public VotingConfiguration getLastAcceptedConfiguration() { + return lastAcceptedConfiguration; + } + + public VotingConfiguration getLastCommittedConfiguration() { + return lastCommittedConfiguration; + } + + public Set getVotingTombstones() { + return votingTombstones; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CoordinationMetaData)) return false; + + CoordinationMetaData that = (CoordinationMetaData) o; + + if (term != that.term) return false; + if (!lastCommittedConfiguration.equals(that.lastCommittedConfiguration)) return false; + return lastAcceptedConfiguration.equals(that.lastAcceptedConfiguration); + } + + @Override + public int hashCode() { + int result = (int) (term ^ (term >>> 32)); + result = 31 * result + lastCommittedConfiguration.hashCode(); + result = 31 * result + lastAcceptedConfiguration.hashCode(); + return result; + } + + @Override + public String toString() { + return "CoordinationMetaData{" + + "term=" + term + + ", lastCommittedConfiguration=" + lastCommittedConfiguration + + ", lastAcceptedConfiguration=" + lastAcceptedConfiguration + + '}'; + } + + public static class Builder { + private long term = 0; + private VotingConfiguration lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG; + private VotingConfiguration lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG; + private final Set votingTombstones = new HashSet<>(); + + public Builder() { + + } + + public Builder(CoordinationMetaData state) { + this.term = state.term; + this.lastCommittedConfiguration = state.lastCommittedConfiguration; + this.lastAcceptedConfiguration = state.lastAcceptedConfiguration; + } + + public Builder term(long term) { + this.term = term; + return this; + } + + public Builder lastCommittedConfiguration(VotingConfiguration config) { + this.lastCommittedConfiguration = config; + return this; + } + + public Builder lastAcceptedConfiguration(VotingConfiguration config) { + this.lastAcceptedConfiguration = config; + return this; + } + + public Builder addVotingTombstone(DiscoveryNode tombstone) { + votingTombstones.add(tombstone); + return this; + } + + public Builder clearVotingTombstones() { + votingTombstones.clear(); + return this; + } + + public CoordinationMetaData build() { + return new CoordinationMetaData(term, lastCommittedConfiguration, lastAcceptedConfiguration, + Collections.unmodifiableSet(new HashSet<>(votingTombstones))); + } + } + + /** + * A collection of persistent node ids, denoting the voting configuration for cluster state changes. + */ + public static class VotingConfiguration implements Writeable, ToXContentFragment { + + public static final VotingConfiguration EMPTY_CONFIG = new VotingConfiguration(Collections.emptySet()); + + private final Set nodeIds; + + public VotingConfiguration(Set nodeIds) { + this.nodeIds = Collections.unmodifiableSet(new HashSet<>(nodeIds)); + } + + public VotingConfiguration(StreamInput in) throws IOException { + nodeIds = Collections.unmodifiableSet(Sets.newHashSet(in.readStringArray())); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeStringArray(nodeIds.toArray(new String[nodeIds.size()])); + } + + public boolean hasQuorum(Collection votes) { + final HashSet intersection = new HashSet<>(nodeIds); + intersection.retainAll(votes); + return intersection.size() * 2 > nodeIds.size(); + } + + public Set getNodeIds() { + return nodeIds; + } + + @Override + public String toString() { + return "VotingConfiguration{" + String.join(",", nodeIds) + "}"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VotingConfiguration that = (VotingConfiguration) o; + return Objects.equals(nodeIds, that.nodeIds); + } + + @Override + public int hashCode() { + return Objects.hash(nodeIds); + } + + public boolean isEmpty() { + return nodeIds.isEmpty(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startArray(); + for (String nodeId : nodeIds) { + builder.value(nodeId); + } + return builder.endArray(); + } + + public static VotingConfiguration of(DiscoveryNode... nodes) { + // this could be used in many more places - TODO use this where appropriate + return new VotingConfiguration(Arrays.stream(nodes).map(DiscoveryNode::getId).collect(Collectors.toSet())); + } + } +} diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java index f89a6784e20fa..0ad4cebaf77b3 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java @@ -21,7 +21,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.settings.Settings; @@ -458,7 +458,9 @@ public interface PersistedState { default void markLastAcceptedConfigAsCommitted() { final ClusterState lastAcceptedState = getLastAcceptedState(); setLastAcceptedState(ClusterState.builder(lastAcceptedState) - .lastCommittedConfiguration(lastAcceptedState.getLastAcceptedConfiguration()) + .coordinationMetaData(CoordinationMetaData.builder(lastAcceptedState.coordinationMetaData()) + .lastCommittedConfiguration(lastAcceptedState.getLastAcceptedConfiguration()) + .build()) .build()); } } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java index ae69ff27718ba..64003f8812578 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java @@ -27,10 +27,10 @@ import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState.Builder; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; import org.elasticsearch.cluster.ClusterStateTaskConfig; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlocks; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.coordination.FollowersChecker.FollowerCheckRequest; import org.elasticsearch.cluster.coordination.JoinHelper.InitialJoinAccumulator; import org.elasticsearch.cluster.metadata.MetaData; @@ -622,11 +622,15 @@ public boolean setInitialConfiguration(final VotingConfiguration votingConfigura logger.info("setting initial configuration to {}", votingConfiguration); final Builder builder = masterService.incrementVersion(currentState); - builder.lastAcceptedConfiguration(votingConfiguration); - builder.lastCommittedConfiguration(votingConfiguration); + final CoordinationMetaData coordinationMetaData = CoordinationMetaData.builder() + .term(currentState.term()) + .lastAcceptedConfiguration(votingConfiguration) + .lastCommittedConfiguration(votingConfiguration) + .build(); MetaData.Builder metaDataBuilder = MetaData.builder(); // automatically generate a UID for the metadata if we need to metaDataBuilder.generateClusterUuidIfNeeded(); // TODO generate UUID in bootstrapping tool? + builder.coordinationMetaData(coordinationMetaData); builder.metaData(metaDataBuilder); coordinationState.get().setInitialState(builder.build()); preVoteCollector.update(getPreVoteResponse(), null); // pick up the change to last-accepted version @@ -641,14 +645,15 @@ ClusterState improveConfiguration(ClusterState clusterState) { final Set liveNodes = StreamSupport.stream(clusterState.nodes().spliterator(), false) .filter(this::hasJoinVoteFrom).collect(Collectors.toSet()); - final ClusterState.VotingConfiguration newConfig = reconfigurator.reconfigure(liveNodes, + final VotingConfiguration newConfig = reconfigurator.reconfigure(liveNodes, clusterState.getVotingTombstones().stream().map(DiscoveryNode::getId).collect(Collectors.toSet()), clusterState.getLastAcceptedConfiguration()); if (newConfig.equals(clusterState.getLastAcceptedConfiguration()) == false) { assert coordinationState.get().joinVotesHaveQuorumFor(newConfig); - return ClusterState.builder(clusterState).lastAcceptedConfiguration(newConfig).build(); + return ClusterState.builder(clusterState) + .coordinationMetaData(CoordinationMetaData.builder(clusterState.coordinationMetaData()) + .lastAcceptedConfiguration(newConfig).build()).build(); } - return clusterState; } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java b/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java index 2b161f967754d..9b80f662bfd99 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java @@ -96,7 +96,9 @@ public ClusterTasksResult execute(ClusterState currentSta final long currentTerm = currentTermSupplier.getAsLong(); if (currentState.term() != currentTerm) { - currentState = ClusterState.builder(currentState).term(currentTerm).build(); + currentState = ClusterState.builder(currentState).coordinationMetaData( + CoordinationMetaData.builder(currentState.coordinationMetaData()).term(currentTerm).build()) + .build(); } return super.execute(currentState, joiningTasks); } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/Reconfigurator.java b/server/src/main/java/org/elasticsearch/cluster/coordination/Reconfigurator.java index 503427cdb3104..8b227c0b261ce 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/Reconfigurator.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/Reconfigurator.java @@ -21,7 +21,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Setting; @@ -93,8 +93,7 @@ public String toString() { * @param currentConfig The current configuration. As far as possible, we prefer to keep the current config as-is. * @return An optimal configuration, or leave the current configuration unchanged if the optimal configuration has no live quorum. */ - public ClusterState.VotingConfiguration reconfigure(Set liveNodes, Set retiredNodeIds, - ClusterState.VotingConfiguration currentConfig) { + public VotingConfiguration reconfigure(Set liveNodes, Set retiredNodeIds, VotingConfiguration currentConfig) { logger.trace("{} reconfiguring {} based on liveNodes={}, retiredNodeIds={}", this, currentConfig, liveNodes, retiredNodeIds); /* @@ -150,7 +149,7 @@ public ClusterState.VotingConfiguration reconfigure(Set liveNodes /* * The new configuration is formed by taking this many nodes in the following preference order: */ - final ClusterState.VotingConfiguration newConfig = new ClusterState.VotingConfiguration( + final VotingConfiguration newConfig = new VotingConfiguration( // live nodes first, preferring the current config, and if we need more then use non-live nodes Stream.of(nonRetiredInConfigLiveIds, nonRetiredLiveNotInConfigIds, nonRetiredInConfigNotLiveIds) .flatMap(Collection::stream).limit(targetSize).collect(Collectors.toSet())); diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfigurationTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfigurationTests.java index f39026e6db456..7294a9c4773d7 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfigurationTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/bootstrap/BootstrapConfigurationTests.java @@ -21,7 +21,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.bootstrap.BootstrapConfiguration.NodeDescription; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode.Role; import org.elasticsearch.test.ESTestCase; diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java index cac669aa7c820..a1e522317dace 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode.Role; import org.elasticsearch.cluster.node.DiscoveryNodes.Builder; @@ -82,7 +83,7 @@ public void testResolveAndCheckMaximum() { final ClusterState.Builder builder = ClusterState.builder(new ClusterName("cluster")).nodes(new Builder() .add(localNode).add(otherNode1).add(otherNode2).localNodeId(localNode.getId())); - builder.addVotingTombstone(otherNode1); + builder.coordinationMetaData(CoordinationMetaData.builder().addVotingTombstone(otherNode1).build()); final ClusterState clusterState = builder.build(); assertThat(makeRequest().resolveNodesAndCheckMaximum(clusterState, 3, "setting.name"), diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java index 87db69ef7877b..e196e7a44af79 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java @@ -24,10 +24,11 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.ClusterStateObserver.Listener; import org.elasticsearch.cluster.ClusterStateUpdateTask; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; @@ -116,7 +117,8 @@ public void setupForTest() { setState(clusterService, builder(new ClusterName("cluster")) .nodes(new Builder().add(localNode).add(otherNode1).add(otherNode2).add(otherDataNode) .localNodeId(localNode.getId()).masterNodeId(localNode.getId())) - .lastAcceptedConfiguration(allNodesConfig).lastCommittedConfiguration(allNodesConfig)); + .coordinationMetaData(CoordinationMetaData.builder().lastAcceptedConfiguration(allNodesConfig) + .lastCommittedConfiguration(allNodesConfig).build())); clusterStateObserver = new ClusterStateObserver(clusterService, null, logger, threadPool.getThreadContext()); } @@ -204,8 +206,10 @@ public void testWithdrawsVoteFromLocalNode() throws InterruptedException { public void testReturnsImmediatelyIfVoteAlreadyWithdrawn() throws InterruptedException { setState(clusterService, builder(clusterService.state()) - .lastCommittedConfiguration(VotingConfiguration.of(localNode, otherNode2)) - .lastAcceptedConfiguration(VotingConfiguration.of(localNode, otherNode2))); + .coordinationMetaData(CoordinationMetaData.builder() + .lastCommittedConfiguration(VotingConfiguration.of(localNode, otherNode2)) + .lastAcceptedConfiguration(VotingConfiguration.of(localNode, otherNode2)) + .build())); final CountDownLatch countDownLatch = new CountDownLatch(1); @@ -261,7 +265,8 @@ public void testOnlyMatchesMasterEligibleNodes() throws InterruptedException { public void testSucceedsEvenIfAllTombstonesAlreadyAdded() throws InterruptedException { final ClusterState.Builder builder = builder(clusterService.state()); - builder.addVotingTombstone(otherNode1); + builder.coordinationMetaData(CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) + .addVotingTombstone(otherNode1).build()); setState(clusterService, builder); final CountDownLatch countDownLatch = new CountDownLatch(1); @@ -283,10 +288,12 @@ public void testReturnsErrorIfMaximumTombstoneCountExceeded() throws Interrupted .metaData(MetaData.builder(clusterService.state().metaData()).persistentSettings( Settings.builder().put(clusterService.state().metaData().persistentSettings()) .put(MAXIMUM_VOTING_TOMBSTONES_SETTING.getKey(), 2).build())); - builder.addVotingTombstone(localNode); + builder.coordinationMetaData(CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) + .addVotingTombstone(localNode).build()); final int existingCount, newCount; if (randomBoolean()) { - builder.addVotingTombstone(otherNode1); + builder.coordinationMetaData(CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) + .addVotingTombstone(otherNode1).build()); existingCount = 2; newCount = 1; } else { @@ -381,8 +388,11 @@ public ClusterState execute(ClusterState currentState) { currentState.getVotingTombstones().forEach(t -> votingNodeIds.remove(t.getId())); final VotingConfiguration votingConfiguration = new VotingConfiguration(votingNodeIds); return builder(currentState) - .lastAcceptedConfiguration(votingConfiguration) - .lastCommittedConfiguration(votingConfiguration).build(); + .coordinationMetaData(CoordinationMetaData.builder(currentState.coordinationMetaData()) + .lastAcceptedConfiguration(votingConfiguration) + .lastCommittedConfiguration(votingConfiguration) + .build()) + .build(); } @Override diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java index ff978adcee85e..8261a3b14c283 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java @@ -24,6 +24,7 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; @@ -97,8 +98,10 @@ public void setupForTest() { final ClusterState.Builder builder = builder(new ClusterName("cluster")) .nodes(new Builder().add(localNode).add(otherNode1).add(otherNode2) .localNodeId(localNode.getId()).masterNodeId(localNode.getId())); - builder.addVotingTombstone(otherNode1); - builder.addVotingTombstone(otherNode2); + builder.coordinationMetaData(CoordinationMetaData.builder() + .addVotingTombstone(otherNode1) + .addVotingTombstone(otherNode2) + .build()); setState(clusterService, builder); } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java index 20a9035df9aaf..e3e3ddfde71f1 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java @@ -70,11 +70,13 @@ public void testToXContent() throws IOException { " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + - " \"term\" : 0,\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + - " \"last_committed_config\" : [ ],\n" + - " \"last_accepted_config\" : [ ],\n" + + " \"coordination\" : {\n" + + " \"term\" : 0,\n" + + " \"last_committed_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ],\n" + + " },\n" + " \"master_node\" : \"node0\",\n" + " \"blocks\" : { },\n" + " \"nodes\" : {\n" + @@ -141,11 +143,13 @@ public void testToXContent() throws IOException { " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + - " \"term\" : 0,\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + - " \"last_committed_config\" : [ ],\n" + - " \"last_accepted_config\" : [ ],\n" + + " \"coordination\" : {\n" + + " \"term\" : 0,\n" + + " \"last_committed_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ],\n" + + " },\n" + " \"master_node\" : \"node0\"\n" + " },\n" + " \"explanations\" : [\n" + diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java index d66012a9dc62b..978dbf33681cb 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java @@ -23,6 +23,7 @@ import org.elasticsearch.Version; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlocks; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.IndexGraveyard; import org.elasticsearch.cluster.metadata.IndexGraveyardTests; @@ -114,13 +115,13 @@ public void testClusterStateDiffSerialization() throws Exception { builder = randomMetaDataChanges(clusterState); break; case 5: - builder = randomVotingConfiguration(clusterState); + builder = randomCoordinationMetaData(clusterState); break; default: throw new IllegalArgumentException("Shouldn't be here"); } } - clusterState = builder.incrementVersion().term(randomLong()).build(); + clusterState = builder.incrementVersion().build(); if (randomIntBetween(0, 10) < 1) { // Update cluster state via full serialization from time to time @@ -199,17 +200,18 @@ public void testClusterStateDiffSerialization() throws Exception { } - private ClusterState.Builder randomVotingConfiguration(ClusterState clusterState) { + private ClusterState.Builder randomCoordinationMetaData(ClusterState clusterState) { ClusterState.Builder builder = ClusterState.builder(clusterState); + CoordinationMetaData.Builder metaBuilder = CoordinationMetaData.builder(); + metaBuilder.term(randomNonNegativeLong()); if (randomBoolean()) { - builder.lastCommittedConfiguration( - new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); + metaBuilder.lastCommittedConfiguration( + new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); } if (randomBoolean()) { - builder.lastAcceptedConfiguration( - new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); + metaBuilder.lastAcceptedConfiguration( + new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); } - return builder; } diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java index 7d900406e0804..3138fb19b6cc5 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java @@ -19,18 +19,10 @@ package org.elasticsearch.cluster; import org.elasticsearch.Version; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.test.EqualsHashCodeTestUtils; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; @@ -64,69 +56,4 @@ public void testSupersedes() { // state from the same master compare by version assertThat(withMaster1a.supersedes(withMaster1b), equalTo(withMaster1a.version() > withMaster1b.version())); } - - public void testVotingConfiguration() { - VotingConfiguration config0 = new VotingConfiguration(Sets.newHashSet()); - assertThat(config0, equalTo(VotingConfiguration.EMPTY_CONFIG)); - assertThat(config0.getNodeIds(), equalTo(Sets.newHashSet())); - assertThat(config0.isEmpty(), equalTo(true)); - assertThat(config0.hasQuorum(Sets.newHashSet()), equalTo(false)); - assertThat(config0.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); - - VotingConfiguration config1 = new VotingConfiguration(Sets.newHashSet("id1")); - assertThat(config1.getNodeIds(), equalTo(Sets.newHashSet("id1"))); - assertThat(config1.isEmpty(), equalTo(false)); - assertThat(config1.hasQuorum(Sets.newHashSet("id1")), equalTo(true)); - assertThat(config1.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); - assertThat(config1.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); - assertThat(config1.hasQuorum(Sets.newHashSet()), equalTo(false)); - - VotingConfiguration config2 = new VotingConfiguration(Sets.newHashSet("id1", "id2")); - assertThat(config2.getNodeIds(), equalTo(Sets.newHashSet("id1", "id2"))); - assertThat(config2.isEmpty(), equalTo(false)); - assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); - assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id2", "id3")), equalTo(true)); - assertThat(config2.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); - assertThat(config2.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); - assertThat(config2.hasQuorum(Sets.newHashSet("id3")), equalTo(false)); - assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id3")), equalTo(false)); - assertThat(config2.hasQuorum(Sets.newHashSet()), equalTo(false)); - - VotingConfiguration config3 = new VotingConfiguration(Sets.newHashSet("id1", "id2", "id3")); - assertThat(config3.getNodeIds(), equalTo(Sets.newHashSet("id1", "id2", "id3"))); - assertThat(config3.isEmpty(), equalTo(false)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); - assertThat(config3.hasQuorum(Sets.newHashSet("id2", "id3")), equalTo(true)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id3")), equalTo(true)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2", "id3")), equalTo(true)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2", "id4")), equalTo(true)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); - assertThat(config3.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); - assertThat(config3.hasQuorum(Sets.newHashSet("id3")), equalTo(false)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id4")), equalTo(false)); - assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id4", "id5")), equalTo(false)); - assertThat(config3.hasQuorum(Sets.newHashSet()), equalTo(false)); - } - - public void testVotingConfigurationSerializationEqualsHashCode() { - VotingConfiguration initialConfig = new VotingConfiguration( - Sets.newHashSet(generateRandomStringArray(randomInt(10), 20, false))); - EqualsHashCodeTestUtils.checkEqualsAndHashCode(initialConfig, - orig -> ESTestCase.copyWriteable(orig, new NamedWriteableRegistry(Collections.emptyList()), VotingConfiguration::new), - cfg -> { - Set newNodeIds = new HashSet<>(cfg.getNodeIds()); - if (cfg.isEmpty() == false && randomBoolean()) { - // remove random element - newNodeIds.remove(randomFrom(cfg.getNodeIds())); - } else if (cfg.isEmpty() == false && randomBoolean()) { - // change random element - newNodeIds.remove(randomFrom(cfg.getNodeIds())); - newNodeIds.add(randomAlphaOfLength(20)); - } else { - // add random element - newNodeIds.add(randomAlphaOfLength(20)); - } - return new VotingConfiguration(newNodeIds); - }); - } } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java new file mode 100644 index 0000000000000..bf34901a03774 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java @@ -0,0 +1,149 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.coordination; + +import org.elasticsearch.Version; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.UUIDs; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.util.set.Sets; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.EqualsHashCodeTestUtils; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singleton; +import static org.hamcrest.Matchers.equalTo; + +public class CoordinationMetaDataTests extends ESTestCase { + + public void testVotingConfiguration() { + VotingConfiguration config0 = new VotingConfiguration(Sets.newHashSet()); + assertThat(config0, equalTo(VotingConfiguration.EMPTY_CONFIG)); + assertThat(config0.getNodeIds(), equalTo(Sets.newHashSet())); + assertThat(config0.isEmpty(), equalTo(true)); + assertThat(config0.hasQuorum(Sets.newHashSet()), equalTo(false)); + assertThat(config0.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); + + VotingConfiguration config1 = new VotingConfiguration(Sets.newHashSet("id1")); + assertThat(config1.getNodeIds(), equalTo(Sets.newHashSet("id1"))); + assertThat(config1.isEmpty(), equalTo(false)); + assertThat(config1.hasQuorum(Sets.newHashSet("id1")), equalTo(true)); + assertThat(config1.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); + assertThat(config1.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); + assertThat(config1.hasQuorum(Sets.newHashSet()), equalTo(false)); + + VotingConfiguration config2 = new VotingConfiguration(Sets.newHashSet("id1", "id2")); + assertThat(config2.getNodeIds(), equalTo(Sets.newHashSet("id1", "id2"))); + assertThat(config2.isEmpty(), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id2", "id3")), equalTo(true)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id3")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id3")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet()), equalTo(false)); + + VotingConfiguration config3 = new VotingConfiguration(Sets.newHashSet("id1", "id2", "id3")); + assertThat(config3.getNodeIds(), equalTo(Sets.newHashSet("id1", "id2", "id3"))); + assertThat(config3.isEmpty(), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id2", "id3")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id3")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2", "id3")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2", "id4")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id3")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id4")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id4", "id5")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet()), equalTo(false)); + } + + public void testVotingConfigurationSerializationEqualsHashCode() { + VotingConfiguration initialConfig = randomVotingConfig(); + EqualsHashCodeTestUtils.checkEqualsAndHashCode(initialConfig, + orig -> ESTestCase.copyWriteable(orig, new NamedWriteableRegistry(Collections.emptyList()), VotingConfiguration::new), + cfg -> randomlyChangeVotingConfiguration(cfg)); + } + + private static VotingConfiguration randomVotingConfig() { + return new VotingConfiguration(Sets.newHashSet(generateRandomStringArray(randomInt(10), 20, false))); + } + + private VotingConfiguration randomlyChangeVotingConfiguration(VotingConfiguration cfg) { + Set newNodeIds = new HashSet<>(cfg.getNodeIds()); + if (cfg.isEmpty() == false && randomBoolean()) { + // remove random element + newNodeIds.remove(randomFrom(cfg.getNodeIds())); + } else if (cfg.isEmpty() == false && randomBoolean()) { + // change random element + newNodeIds.remove(randomFrom(cfg.getNodeIds())); + newNodeIds.add(randomAlphaOfLength(20)); + } else { + // add random element + newNodeIds.add(randomAlphaOfLength(20)); + } + return new VotingConfiguration(newNodeIds); + } + + private Set randomDiscoveryNodeSet() { + final int size = randomIntBetween(1, 10); + final Set nodes = new HashSet<>(size); + while (nodes.size() < size) { + assertTrue(nodes.add(new DiscoveryNode(randomAlphaOfLength(10), randomAlphaOfLength(10), + UUIDs.randomBase64UUID(random()), randomAlphaOfLength(10), randomAlphaOfLength(10), buildNewFakeTransportAddress(), + emptyMap(), singleton(DiscoveryNode.Role.MASTER), Version.CURRENT))); + } + return nodes; + } + + public void testCoordinationMetaDataSerializationEqualsHashCode() { + CoordinationMetaData initialMetaData = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), + randomDiscoveryNodeSet()); + EqualsHashCodeTestUtils.checkEqualsAndHashCode(initialMetaData, + orig -> ESTestCase.copyWriteable(orig, new NamedWriteableRegistry(Collections.emptyList()), CoordinationMetaData::new), + meta -> { + CoordinationMetaData.Builder builder = CoordinationMetaData.builder(meta); + switch (randomInt(3)) { + case 0: + builder.term(randomValueOtherThan(meta.term(), ESTestCase::randomNonNegativeLong)); + break; + case 1: + builder.lastCommittedConfiguration(randomlyChangeVotingConfiguration(meta.getLastCommittedConfiguration())); + break; + case 2: + builder.lastAcceptedConfiguration(randomlyChangeVotingConfiguration(meta.getLastAcceptedConfiguration())); + break; + case 3: + if (meta.getVotingTombstones().isEmpty() == false && randomBoolean()) { + builder.clearVotingTombstones(); + } else { + randomDiscoveryNodeSet().forEach(dn -> builder.addVotingTombstone(dn)); + } + break; + } + return builder.build(); + }); + } +} diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java index 9c7ac31497f12..a23f3adf4f3d7 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java @@ -22,7 +22,7 @@ import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode.Role; @@ -785,9 +785,11 @@ public static ClusterState clusterState(long term, long version, DiscoveryNodes VotingConfiguration lastAcceptedConfig, long value) { return setValue(ClusterState.builder(ClusterName.DEFAULT) .version(version) - .term(term) - .lastCommittedConfiguration(lastCommittedConfig) - .lastAcceptedConfiguration(lastAcceptedConfig) + .coordinationMetaData(CoordinationMetaData.builder() + .term(term) + .lastCommittedConfiguration(lastCommittedConfig) + .lastAcceptedConfiguration(lastAcceptedConfig) + .build()) .nodes(discoveryNodes) .metaData(MetaData.builder() .clusterUUID(UUIDs.randomBase64UUID(random()))) // generate cluster UUID deterministically for repeatable tests @@ -829,8 +831,10 @@ void reboot() { void setInitialState(VotingConfiguration initialConfig, long initialValue) { final ClusterState.Builder builder = ClusterState.builder(state.getLastAcceptedState()).incrementVersion(); - builder.lastAcceptedConfiguration(initialConfig); - builder.lastCommittedConfiguration(initialConfig); + builder.coordinationMetaData(CoordinationMetaData.builder() + .lastAcceptedConfiguration(initialConfig) + .lastCommittedConfiguration(initialConfig) + .build()); state.setInitialState(setValue(builder.build(), initialValue)); } } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinatorTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinatorTests.java index 20e64d21abb2e..95f55b850853b 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinatorTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinatorTests.java @@ -25,7 +25,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.ESAllocationTestCase; import org.elasticsearch.cluster.coordination.ClusterStatePublisher.AckListener; diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/MessagesTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/MessagesTests.java index c96cff233551a..d885f42e554f0 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/MessagesTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/MessagesTests.java @@ -193,8 +193,8 @@ public void testJoinRequestEqualsHashCodeSerialization() { public ClusterState randomClusterState() { return CoordinationStateTests.clusterState(randomNonNegativeLong(), randomNonNegativeLong(), createNode(randomAlphaOfLength(10)), - new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false))), - new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false))), + new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false))), + new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false))), randomLong()); } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java index 193ae721d927d..5f2cdb55e095d 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java @@ -22,7 +22,7 @@ import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.ESAllocationTestCase; import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.node.DiscoveryNode; @@ -106,10 +106,13 @@ private static ClusterState initialState(boolean withMaster, DiscoveryNode local .add(localNode) .localNodeId(localNode.getId()) .masterNodeId(withMaster ? localNode.getId() : null)) - .term(term) + .coordinationMetaData( + CoordinationMetaData.builder() + .term(term) + .lastAcceptedConfiguration(config) + .lastCommittedConfiguration(config) + .build()) .version(version) - .lastAcceptedConfiguration(config) - .lastCommittedConfiguration(config) .blocks(ClusterBlocks.EMPTY_CLUSTER_BLOCK).build(); return initialClusterState; } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/PreVoteCollectorTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/PreVoteCollectorTests.java index f0324ddad1ad0..78896752bae4d 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/PreVoteCollectorTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/PreVoteCollectorTests.java @@ -21,7 +21,7 @@ import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.lease.Releasable; diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTests.java index 720a140fabfa3..3042e794cef34 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTests.java @@ -21,7 +21,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.collect.Tuple; @@ -61,7 +61,7 @@ class MockNode { MockNode(Settings settings, DiscoveryNode localNode) { this.localNode = localNode; ClusterState initialState = CoordinationStateTests.clusterState(0L, 0L, localNode, - VotingConfiguration.EMPTY_CONFIG, VotingConfiguration.EMPTY_CONFIG, 0L); + CoordinationMetaData.VotingConfiguration.EMPTY_CONFIG, CoordinationMetaData.VotingConfiguration.EMPTY_CONFIG, 0L); coordinationState = new CoordinationState(settings, localNode, new InMemoryPersistedState(0L, initialState)); } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java index 1af7b958b0bec..709171e33a46b 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/PublicationTransportHandlerTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.Diff; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.io.stream.StreamOutput; @@ -59,9 +60,9 @@ public void testDiffSerializationFailure() { final DiscoveryNode otherNode = new DiscoveryNode("otherNode", buildNewFakeTransportAddress(), Version.CURRENT); final ClusterState clusterState = CoordinationStateTests.clusterState(2L, 1L, DiscoveryNodes.builder().add(localNode).add(otherNode).localNodeId(localNode.getId()).build(), - ClusterState.VotingConfiguration.EMPTY_CONFIG, ClusterState.VotingConfiguration.EMPTY_CONFIG, 0L); + VotingConfiguration.EMPTY_CONFIG, VotingConfiguration.EMPTY_CONFIG, 0L); - final ClusterState unserializableClusterState = new ClusterState(clusterState.term(), clusterState.version(), + final ClusterState unserializableClusterState = new ClusterState(clusterState.version(), clusterState.stateUUID(), clusterState) { @Override public Diff diff(ClusterState previousState) { diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/ReconfiguratorTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/ReconfiguratorTests.java index e93756c81defb..7e7c7adbe1af9 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/ReconfiguratorTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/ReconfiguratorTests.java @@ -21,8 +21,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage; import org.elasticsearch.Version; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterState.VotingConfiguration; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; @@ -121,11 +120,11 @@ public void testAutoShrinking() { } final Reconfigurator reconfigurator = makeReconfigurator(settingsBuilder.build()); final Set liveNodesSet = nodes(liveNodes); - final ClusterState.VotingConfiguration initialConfig = conf(initialVotingNodes); + final VotingConfiguration initialConfig = conf(initialVotingNodes); final int quorumSize = Math.max(liveNodes.length / 2 + 1, initialVotingNodes.length < 3 ? 1 : 2); - final ClusterState.VotingConfiguration finalConfig = reconfigurator.reconfigure(liveNodesSet, emptySet(), initialConfig); + final VotingConfiguration finalConfig = reconfigurator.reconfigure(liveNodesSet, emptySet(), initialConfig); final String description = "reconfigure " + liveNodesSet + " from " + initialConfig + " yielded " + finalConfig; @@ -149,11 +148,11 @@ public void testManualShrinking() { final Reconfigurator reconfigurator = makeReconfigurator(Settings.builder().put(CLUSTER_AUTO_SHRINK_VOTING_CONFIGURATION.getKey(), false).build()); final Set liveNodesSet = nodes(liveNodes); - final ClusterState.VotingConfiguration initialConfig = conf(initialVotingNodes); + final VotingConfiguration initialConfig = conf(initialVotingNodes); final int quorumSize = Math.max(liveNodes.length, initialVotingNodes.length) / 2 + 1; - final ClusterState.VotingConfiguration finalConfig = reconfigurator.reconfigure(liveNodesSet, emptySet(), initialConfig); + final VotingConfiguration finalConfig = reconfigurator.reconfigure(liveNodesSet, emptySet(), initialConfig); final String description = "reconfigure " + liveNodesSet + " from " + initialConfig + " yielded " + finalConfig; @@ -165,8 +164,8 @@ public void testManualShrinking() { } } - private ClusterState.VotingConfiguration conf(String... nodes) { - return new ClusterState.VotingConfiguration(Sets.newHashSet(nodes)); + private VotingConfiguration conf(String... nodes) { + return new VotingConfiguration(Sets.newHashSet(nodes)); } private Set nodes(String... nodes) { @@ -181,18 +180,18 @@ private Set retired(String... nodes) { return Arrays.stream(nodes).collect(Collectors.toSet()); } - private void check(Set liveNodes, ClusterState.VotingConfiguration config, boolean autoShrinkVotingConfiguration, - ClusterState.VotingConfiguration expectedConfig) { + private void check(Set liveNodes, VotingConfiguration config, boolean autoShrinkVotingConfiguration, + VotingConfiguration expectedConfig) { check(liveNodes, retired(), config, autoShrinkVotingConfiguration, expectedConfig); } - private void check(Set liveNodes, Set retired, ClusterState.VotingConfiguration config, - boolean autoShrinkVotingConfiguration, ClusterState.VotingConfiguration expectedConfig) { + private void check(Set liveNodes, Set retired, VotingConfiguration config, + boolean autoShrinkVotingConfiguration, VotingConfiguration expectedConfig) { final Reconfigurator reconfigurator = makeReconfigurator(Settings.builder() .put(CLUSTER_AUTO_SHRINK_VOTING_CONFIGURATION.getKey(), autoShrinkVotingConfiguration) .build()); - final ClusterState.VotingConfiguration adaptedConfig = reconfigurator.reconfigure(liveNodes, retired, config); + final VotingConfiguration adaptedConfig = reconfigurator.reconfigure(liveNodes, retired, config); assertEquals(new ParameterizedMessage("[liveNodes={}, retired={}, config={}, autoShrinkVotingConfiguration={}]", liveNodes, retired, config, autoShrinkVotingConfiguration).getFormattedMessage(), expectedConfig, adaptedConfig); diff --git a/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java b/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java index a1e67f8edad31..4bd7b4e663a17 100644 --- a/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java +++ b/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java @@ -488,7 +488,7 @@ public void clusterChanged(ClusterChangedEvent event) { clusterState = ClusterState.builder(clusterState).blocks(ClusterBlocks.builder() .addGlobalBlock(MetaData.CLUSTER_READ_ONLY_BLOCK)).incrementVersion().build(); - ClusterState unserializableClusterState = new ClusterState(clusterState.term(), clusterState.version(), clusterState.stateUUID(), + ClusterState unserializableClusterState = new ClusterState(clusterState.version(), clusterState.stateUUID(), clusterState) { @Override public Diff diff(ClusterState previousState) { diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESSingleNodeTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESSingleNodeTestCase.java index 13a8eae467c8f..7ac91342c2437 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESSingleNodeTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESSingleNodeTestCase.java @@ -123,10 +123,8 @@ public void tearDown() throws Exception { super.tearDown(); assertAcked(client().admin().indices().prepareDelete("*").get()); MetaData metaData = client().admin().cluster().prepareState().get().getState().getMetaData(); - Settings.Builder unexpectedPersistentSettingsBuilder = Settings.builder().put(metaData.persistentSettings()); - Settings unexpectedPersistentSettings = unexpectedPersistentSettingsBuilder.build(); - assertThat("test leaves persistent cluster metadata behind: " + unexpectedPersistentSettings.keySet(), - unexpectedPersistentSettings.size(), equalTo(0)); + assertThat("test leaves persistent cluster metadata behind: " + metaData.persistentSettings().keySet(), + metaData.persistentSettings().size(), equalTo(0)); assertThat("test leaves transient cluster metadata behind: " + metaData.transientSettings().keySet(), metaData.transientSettings().size(), equalTo(0)); if (resetNodeAfterTest()) { From b39243521300b1276ab1eeb8dd93c42298649ec2 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Thu, 15 Nov 2018 16:14:23 +0300 Subject: [PATCH 02/22] Bug fix --- .../cluster/coordination/CoordinationMetaData.java | 5 ++++- .../admin/cluster/reroute/ClusterRerouteResponseTests.java | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java index 5b06b324b2043..7e3d8d2a5f8af 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java @@ -112,7 +112,8 @@ public boolean equals(Object o) { if (term != that.term) return false; if (!lastCommittedConfiguration.equals(that.lastCommittedConfiguration)) return false; - return lastAcceptedConfiguration.equals(that.lastAcceptedConfiguration); + if (!lastAcceptedConfiguration.equals(that.lastAcceptedConfiguration)) return false; + return votingTombstones.equals(that.votingTombstones); } @Override @@ -120,6 +121,7 @@ public int hashCode() { int result = (int) (term ^ (term >>> 32)); result = 31 * result + lastCommittedConfiguration.hashCode(); result = 31 * result + lastAcceptedConfiguration.hashCode(); + result = 31 * result + votingTombstones.hashCode(); return result; } @@ -146,6 +148,7 @@ public Builder(CoordinationMetaData state) { this.term = state.term; this.lastCommittedConfiguration = state.lastCommittedConfiguration; this.lastAcceptedConfiguration = state.lastAcceptedConfiguration; + this.votingTombstones.addAll(state.votingTombstones); } public Builder term(long term) { diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java index e3e3ddfde71f1..4ef6f6c010c66 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java @@ -75,7 +75,7 @@ public void testToXContent() throws IOException { " \"coordination\" : {\n" + " \"term\" : 0,\n" + " \"last_committed_config\" : [ ],\n" + - " \"last_accepted_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ]\n" + " },\n" + " \"master_node\" : \"node0\",\n" + " \"blocks\" : { },\n" + @@ -148,7 +148,7 @@ public void testToXContent() throws IOException { " \"coordination\" : {\n" + " \"term\" : 0,\n" + " \"last_committed_config\" : [ ],\n" + - " \"last_accepted_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ]\n" + " },\n" + " \"master_node\" : \"node0\"\n" + " },\n" + From f04e55b518146d46948f8deabf8370fba7fb1edf Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Thu, 15 Nov 2018 18:20:33 +0300 Subject: [PATCH 03/22] Move CoordinationMetaData to MetaData --- .../TransportAddVotingTombstonesAction.java | 4 +- .../TransportClearVotingTombstonesAction.java | 10 +-- .../state/TransportClusterStateAction.java | 3 +- .../elasticsearch/cluster/ClusterState.java | 67 ++++++------------- .../coordination/CoordinationState.java | 9 +-- .../cluster/coordination/Coordinator.java | 6 +- .../cluster/coordination/JoinHelper.java | 8 ++- .../cluster/metadata/MetaData.java | 42 ++++++++++-- .../AddVotingTombstonesRequestTests.java | 3 +- ...ansportAddVotingTombstonesActionTests.java | 49 ++++++++------ ...sportClearVotingTombstonesActionTests.java | 10 +-- .../reroute/ClusterRerouteResponseTests.java | 20 +++--- .../coordination/CoordinationStateTests.java | 21 +++--- .../cluster/coordination/NodeJoinTests.java | 14 ++-- 14 files changed, 148 insertions(+), 118 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java index abd2e37f29286..67652bf247ac6 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java @@ -31,6 +31,7 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; @@ -92,7 +93,8 @@ public ClusterState execute(ClusterState currentState) { CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData()); resolvedNodes.forEach(builder::addVotingTombstone); - final ClusterState newState = ClusterState.builder(currentState).coordinationMetaData(builder.build()).build(); + final MetaData newMetaData = MetaData.builder(currentState.metaData()).coordinationMetaData(builder.build()).build(); + final ClusterState newState = ClusterState.builder(currentState).metaData(newMetaData).build(); assert newState.getVotingTombstones().size() <= MAXIMUM_VOTING_TOMBSTONES_SETTING.get(currentState.metaData().settings()); return newState; } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java index 4aa1fdf09d965..dfaf93bd44a0c 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesAction.java @@ -31,6 +31,7 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; @@ -119,10 +120,11 @@ private void submitClearTombstonesTask(ClearVotingTombstonesRequest request, lon clusterService.submitStateUpdateTask("clear-voting-tombstones", new ClusterStateUpdateTask(Priority.URGENT) { @Override public ClusterState execute(ClusterState currentState) { - return ClusterState.builder(currentState) - .coordinationMetaData(CoordinationMetaData.builder( - currentState.coordinationMetaData()).clearVotingTombstones().build()) - .build(); + final CoordinationMetaData newCoordinationMetaData = + CoordinationMetaData.builder(currentState.coordinationMetaData()).clearVotingTombstones().build(); + final MetaData newMetaData = MetaData.builder(currentState.metaData()). + coordinationMetaData(newCoordinationMetaData).build(); + return ClusterState.builder(currentState).metaData(newMetaData).build(); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java index f405363d97bc1..a484a3f383e6a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java @@ -79,7 +79,7 @@ protected void masterOperation(final ClusterStateRequest request, final ClusterS ClusterState.Builder builder = ClusterState.builder(currentState.getClusterName()); builder.version(currentState.version()); builder.stateUUID(currentState.stateUUID()); - builder.coordinationMetaData(currentState.coordinationMetaData()); + if (request.nodes()) { builder.nodes(currentState.nodes()); } @@ -103,6 +103,7 @@ protected void masterOperation(final ClusterStateRequest request, final ClusterS MetaData.Builder mdBuilder = MetaData.builder(); mdBuilder.clusterUUID(currentState.metaData().clusterUUID()); + mdBuilder.coordinationMetaData(currentState.coordinationMetaData()); if (request.metaData()) { if (request.indices().length > 0) { diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index 4fc2f30095b2a..5ac19cc70ade8 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -23,7 +23,6 @@ import com.carrotsearch.hppc.cursors.ObjectCursor; import com.carrotsearch.hppc.cursors.ObjectObjectCursor; -import org.elasticsearch.Version; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlocks; @@ -175,19 +174,17 @@ default boolean isPrivate() { private final boolean wasReadFromDiff; - private final CoordinationMetaData coordinationMetaData; - // built on demand private volatile RoutingNodes routingNodes; public ClusterState(long version, String stateUUID, ClusterState state) { this(state.clusterName, version, stateUUID, state.metaData(), state.routingTable(), state.nodes(), state.blocks(), - state.customs(), state.coordinationMetaData(), false); + state.customs(), false); } public ClusterState(ClusterName clusterName, long version, String stateUUID, MetaData metaData, RoutingTable routingTable, DiscoveryNodes nodes, ClusterBlocks blocks, ImmutableOpenMap customs, - CoordinationMetaData coordinationMetaData, boolean wasReadFromDiff) { + boolean wasReadFromDiff) { this.version = version; this.stateUUID = stateUUID; this.clusterName = clusterName; @@ -196,12 +193,11 @@ public ClusterState(ClusterName clusterName, long version, String stateUUID, Met this.nodes = nodes; this.blocks = blocks; this.customs = customs; - this.coordinationMetaData = coordinationMetaData; this.wasReadFromDiff = wasReadFromDiff; } public long term() { - return coordinationMetaData.term(); + return coordinationMetaData().term(); } public long version() { @@ -237,7 +233,7 @@ public MetaData getMetaData() { } public CoordinationMetaData coordinationMetaData() { - return coordinationMetaData; + return metaData.coordinationMetaData(); } public RoutingTable routingTable() { @@ -273,15 +269,15 @@ public ClusterName getClusterName() { } public CoordinationMetaData.VotingConfiguration getLastAcceptedConfiguration() { - return coordinationMetaData.getLastAcceptedConfiguration(); + return coordinationMetaData().getLastAcceptedConfiguration(); } public CoordinationMetaData.VotingConfiguration getLastCommittedConfiguration() { - return coordinationMetaData.getLastCommittedConfiguration(); + return coordinationMetaData().getLastCommittedConfiguration(); } public Set getVotingTombstones() { - return coordinationMetaData.getVotingTombstones(); + return coordinationMetaData().getVotingTombstones(); } // Used for testing and logging to determine how this cluster state was send over the wire @@ -307,13 +303,16 @@ public String toString() { sb.append("cluster uuid: ").append(metaData.clusterUUID()).append("\n"); sb.append("version: ").append(version).append("\n"); sb.append("state uuid: ").append(stateUUID).append("\n"); - sb.append("coordination_metadata:\n"); - sb.append(TAB).append("term: ").append(coordinationMetaData.term()).append("\n"); - sb.append(TAB).append("last_committed_config: ").append(coordinationMetaData.getLastCommittedConfiguration()).append("\n"); - sb.append(TAB).append("last_accepted_config: ").append(coordinationMetaData.getLastAcceptedConfiguration()).append("\n"); - sb.append(TAB).append("voting tombstones: ").append(coordinationMetaData.getVotingTombstones()).append("\n"); sb.append("from_diff: ").append(wasReadFromDiff).append("\n"); sb.append("meta data version: ").append(metaData.version()).append("\n"); + sb.append(TAB).append("coordination_metadata:\n"); + sb.append(TAB).append(TAB).append("term: ").append(coordinationMetaData().term()).append("\n"); + sb.append(TAB).append(TAB) + .append("last_committed_config: ").append(coordinationMetaData().getLastCommittedConfiguration()).append("\n"); + sb.append(TAB).append(TAB) + .append("last_accepted_config: ").append(coordinationMetaData().getLastAcceptedConfiguration()).append("\n"); + sb.append(TAB).append(TAB) + .append("voting tombstones: ").append(coordinationMetaData().getVotingTombstones()).append("\n"); for (IndexMetaData indexMetaData : metaData) { sb.append(TAB).append(indexMetaData.getIndex()); sb.append(": v[").append(indexMetaData.getVersion()) @@ -423,9 +422,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (metrics.contains(Metric.VERSION)) { builder.field("version", version); builder.field("state_uuid", stateUUID); - builder.startObject("coordination"); - coordinationMetaData.toXContent(builder, params); - builder.endObject(); } if (metrics.contains(Metric.MASTER_NODE)) { @@ -471,6 +467,11 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (metrics.contains(Metric.METADATA)) { builder.startObject("metadata"); builder.field("cluster_uuid", metaData().clusterUUID()); + + builder.startObject("coordination"); + coordinationMetaData().toXContent(builder, params); + builder.endObject(); + builder.startObject("templates"); for (ObjectCursor cursor : metaData().templates().values()) { IndexTemplateMetaData templateMetaData = cursor.value; @@ -627,7 +628,6 @@ public static class Builder { private final ClusterName clusterName; private long version = 0; private String uuid = UNKNOWN_UUID; - private CoordinationMetaData coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; private MetaData metaData = MetaData.EMPTY_META_DATA; private RoutingTable routingTable = RoutingTable.EMPTY_ROUTING_TABLE; private DiscoveryNodes nodes = DiscoveryNodes.EMPTY_NODES; @@ -640,7 +640,6 @@ public Builder(ClusterState state) { this.clusterName = state.clusterName; this.version = state.version(); this.uuid = state.stateUUID(); - this.coordinationMetaData = state.coordinationMetaData(); this.nodes = state.nodes(); this.routingTable = state.routingTable(); this.metaData = state.metaData(); @@ -706,11 +705,6 @@ public Builder stateUUID(String uuid) { return this; } - public Builder coordinationMetaData(CoordinationMetaData coordinationMetaData) { - this.coordinationMetaData = coordinationMetaData; - return this; - } - public Builder putCustom(String type, Custom custom) { customs.put(type, custom); return this; @@ -735,8 +729,7 @@ public ClusterState build() { if (UNKNOWN_UUID.equals(uuid)) { uuid = UUIDs.randomBase64UUID(); } - return new ClusterState(clusterName, version, uuid, metaData, routingTable, nodes, blocks, customs.build(), - coordinationMetaData, fromDiff); + return new ClusterState(clusterName, version, uuid, metaData, routingTable, nodes, blocks, customs.build(), fromDiff); } public static byte[] toBytes(ClusterState state) throws IOException { @@ -770,9 +763,6 @@ public static ClusterState readFrom(StreamInput in, DiscoveryNode localNode) thr Builder builder = new Builder(clusterName); builder.version = in.readLong(); builder.uuid = in.readString(); - if (in.getVersion().onOrAfter(Version.V_7_0_0)) { - builder.coordinationMetaData(new CoordinationMetaData(in)); - } builder.metaData = MetaData.readFrom(in); builder.routingTable = RoutingTable.readFrom(in); builder.nodes = DiscoveryNodes.readFrom(in, localNode); @@ -790,9 +780,6 @@ public void writeTo(StreamOutput out) throws IOException { clusterName.writeTo(out); out.writeLong(version); out.writeString(stateUUID); - if (out.getVersion().onOrAfter(Version.V_7_0_0)) { - coordinationMetaData.writeTo(out); - } metaData.writeTo(out); routingTable.writeTo(out); nodes.writeTo(out); @@ -822,8 +809,6 @@ private static class ClusterStateDiff implements Diff { private final ClusterName clusterName; - private final CoordinationMetaData coordinationMetaData; - private final Diff routingTable; private final Diff nodes; @@ -839,7 +824,6 @@ private static class ClusterStateDiff implements Diff { toUuid = after.stateUUID; toVersion = after.version; clusterName = after.clusterName; - coordinationMetaData = after.coordinationMetaData; routingTable = after.routingTable.diff(before.routingTable); nodes = after.nodes.diff(before.nodes); metaData = after.metaData.diff(before.metaData); @@ -852,11 +836,6 @@ private static class ClusterStateDiff implements Diff { fromUuid = in.readString(); toUuid = in.readString(); toVersion = in.readLong(); - if (in.getVersion().onOrAfter(Version.V_7_0_0)) { - coordinationMetaData = new CoordinationMetaData(in); - } else { - coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; - } routingTable = RoutingTable.readDiffFrom(in); nodes = DiscoveryNodes.readDiffFrom(in, localNode); metaData = MetaData.readDiffFrom(in); @@ -870,9 +849,6 @@ public void writeTo(StreamOutput out) throws IOException { out.writeString(fromUuid); out.writeString(toUuid); out.writeLong(toVersion); - if (out.getVersion().onOrAfter(Version.V_7_0_0)) { - coordinationMetaData.writeTo(out); - } routingTable.writeTo(out); nodes.writeTo(out); metaData.writeTo(out); @@ -892,7 +868,6 @@ public ClusterState apply(ClusterState state) { } builder.stateUUID(toUuid); builder.version(toVersion); - builder.coordinationMetaData(coordinationMetaData); builder.routingTable(routingTable.apply(state.routingTable)); builder.nodes(nodes.apply(state.nodes)); builder.metaData(metaData.apply(state.metaData)); diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java index 0ad4cebaf77b3..099f7ecaabb61 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java @@ -22,6 +22,7 @@ import org.apache.logging.log4j.Logger; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.settings.Settings; @@ -457,11 +458,11 @@ public interface PersistedState { */ default void markLastAcceptedConfigAsCommitted() { final ClusterState lastAcceptedState = getLastAcceptedState(); - setLastAcceptedState(ClusterState.builder(lastAcceptedState) - .coordinationMetaData(CoordinationMetaData.builder(lastAcceptedState.coordinationMetaData()) + final CoordinationMetaData cmd = CoordinationMetaData.builder(lastAcceptedState.coordinationMetaData()) .lastCommittedConfiguration(lastAcceptedState.getLastAcceptedConfiguration()) - .build()) - .build()); + .build(); + final MetaData metaData = MetaData.builder(lastAcceptedState.metaData()).coordinationMetaData(cmd).build(); + setLastAcceptedState(ClusterState.builder(lastAcceptedState).metaData(metaData).build()); } } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java index 64003f8812578..07a50bf9ccd41 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java @@ -630,7 +630,7 @@ public boolean setInitialConfiguration(final VotingConfiguration votingConfigura MetaData.Builder metaDataBuilder = MetaData.builder(); // automatically generate a UID for the metadata if we need to metaDataBuilder.generateClusterUuidIfNeeded(); // TODO generate UUID in bootstrapping tool? - builder.coordinationMetaData(coordinationMetaData); + metaDataBuilder.coordinationMetaData(coordinationMetaData); builder.metaData(metaDataBuilder); coordinationState.get().setInitialState(builder.build()); preVoteCollector.update(getPreVoteResponse(), null); // pick up the change to last-accepted version @@ -650,9 +650,9 @@ ClusterState improveConfiguration(ClusterState clusterState) { clusterState.getLastAcceptedConfiguration()); if (newConfig.equals(clusterState.getLastAcceptedConfiguration()) == false) { assert coordinationState.get().joinVotesHaveQuorumFor(newConfig); - return ClusterState.builder(clusterState) + return ClusterState.builder(clusterState).metaData(MetaData.builder(clusterState.metaData()) .coordinationMetaData(CoordinationMetaData.builder(clusterState.coordinationMetaData()) - .lastAcceptedConfiguration(newConfig).build()).build(); + .lastAcceptedConfiguration(newConfig).build())).build(); } return clusterState; } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java b/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java index 9b80f662bfd99..6175a1be7f7f0 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java @@ -25,6 +25,7 @@ import org.elasticsearch.cluster.ClusterStateTaskConfig; import org.elasticsearch.cluster.ClusterStateTaskListener; import org.elasticsearch.cluster.coordination.Coordinator.Mode; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.service.MasterService; @@ -96,9 +97,10 @@ public ClusterTasksResult execute(ClusterState currentSta final long currentTerm = currentTermSupplier.getAsLong(); if (currentState.term() != currentTerm) { - currentState = ClusterState.builder(currentState).coordinationMetaData( - CoordinationMetaData.builder(currentState.coordinationMetaData()).term(currentTerm).build()) - .build(); + final CoordinationMetaData cmd = + CoordinationMetaData.builder(currentState.coordinationMetaData()).term(currentTerm).build(); + final MetaData metaData = MetaData.builder(currentState.metaData()).coordinationMetaData(cmd).build(); + currentState = ClusterState.builder(currentState).metaData(metaData).build(); } return super.execute(currentState, joiningTasks); } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index acd28a55604d3..faea54285953b 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -26,6 +26,7 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.Version; import org.elasticsearch.action.AliasesRequest; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState.FeatureAware; @@ -36,6 +37,7 @@ import org.elasticsearch.cluster.NamedDiffableValueSerializer; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; import org.elasticsearch.common.UUIDs; @@ -159,6 +161,8 @@ public interface Custom extends NamedDiffable, ToXContentFragment, Clust private final String clusterUUID; private final long version; + private final CoordinationMetaData coordinationMetaData; + private final Settings transientSettings; private final Settings persistentSettings; private final Settings settings; @@ -176,12 +180,14 @@ public interface Custom extends NamedDiffable, ToXContentFragment, Clust private final SortedMap aliasAndIndexLookup; - MetaData(String clusterUUID, long version, Settings transientSettings, Settings persistentSettings, + MetaData(String clusterUUID, long version, CoordinationMetaData coordinationMetaData, + Settings transientSettings, Settings persistentSettings, ImmutableOpenMap indices, ImmutableOpenMap templates, ImmutableOpenMap customs, String[] allIndices, String[] allOpenIndices, String[] allClosedIndices, SortedMap aliasAndIndexLookup) { this.clusterUUID = clusterUUID; this.version = version; + this.coordinationMetaData = coordinationMetaData; this.transientSettings = transientSettings; this.persistentSettings = persistentSettings; this.settings = Settings.builder().put(persistentSettings).put(transientSettings).build(); @@ -231,6 +237,10 @@ public Settings persistentSettings() { return this.persistentSettings; } + public CoordinationMetaData coordinationMetaData() { + return this.coordinationMetaData; + } + public boolean hasAlias(String alias) { AliasOrIndex aliasOrIndex = getAliasAndIndexLookup().get(alias); if (aliasOrIndex != null) { @@ -798,9 +808,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws private static class MetaDataDiff implements Diff { private long version; - private String clusterUUID; - + private CoordinationMetaData coordinationMetaData; private Settings transientSettings; private Settings persistentSettings; private Diff> indices; @@ -810,6 +819,7 @@ private static class MetaDataDiff implements Diff { MetaDataDiff(MetaData before, MetaData after) { clusterUUID = after.clusterUUID; version = after.version; + coordinationMetaData = after.coordinationMetaData; transientSettings = after.transientSettings; persistentSettings = after.persistentSettings; indices = DiffableUtils.diff(before.indices, after.indices, DiffableUtils.getStringKeySerializer()); @@ -820,6 +830,11 @@ private static class MetaDataDiff implements Diff { MetaDataDiff(StreamInput in) throws IOException { clusterUUID = in.readString(); version = in.readLong(); + if (in.getVersion().onOrAfter(Version.V_7_0_0)) { + coordinationMetaData = new CoordinationMetaData(in); + } else { + coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; + } transientSettings = Settings.readSettingsFromStream(in); persistentSettings = Settings.readSettingsFromStream(in); indices = DiffableUtils.readImmutableOpenMapDiff(in, DiffableUtils.getStringKeySerializer(), IndexMetaData::readFrom, @@ -833,6 +848,9 @@ private static class MetaDataDiff implements Diff { public void writeTo(StreamOutput out) throws IOException { out.writeString(clusterUUID); out.writeLong(version); + if (out.getVersion().onOrAfter(Version.V_7_0_0)) { + coordinationMetaData.writeTo(out); + } Settings.writeSettingsToStream(transientSettings, out); Settings.writeSettingsToStream(persistentSettings, out); indices.writeTo(out); @@ -845,6 +863,7 @@ public MetaData apply(MetaData part) { Builder builder = builder(); builder.clusterUUID(clusterUUID); builder.version(version); + builder.coordinationMetaData(coordinationMetaData); builder.transientSettings(transientSettings); builder.persistentSettings(persistentSettings); builder.indices(indices.apply(part.indices)); @@ -858,6 +877,9 @@ public static MetaData readFrom(StreamInput in) throws IOException { Builder builder = new Builder(); builder.version = in.readLong(); builder.clusterUUID = in.readString(); + if (in.getVersion().onOrAfter(Version.V_7_0_0)) { + builder.coordinationMetaData(new CoordinationMetaData(in)); + } builder.transientSettings(readSettingsFromStream(in)); builder.persistentSettings(readSettingsFromStream(in)); int size = in.readVInt(); @@ -880,6 +902,9 @@ public static MetaData readFrom(StreamInput in) throws IOException { public void writeTo(StreamOutput out) throws IOException { out.writeLong(version); out.writeString(clusterUUID); + if (out.getVersion().onOrAfter(Version.V_7_0_0)) { + coordinationMetaData.writeTo(out); + } writeSettingsToStream(transientSettings, out); writeSettingsToStream(persistentSettings, out); out.writeVInt(indices.size()); @@ -918,6 +943,7 @@ public static class Builder { private String clusterUUID; private long version; + private CoordinationMetaData coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; private Settings transientSettings = Settings.Builder.EMPTY_SETTINGS; private Settings persistentSettings = Settings.Builder.EMPTY_SETTINGS; @@ -935,6 +961,7 @@ public Builder() { public Builder(MetaData metaData) { this.clusterUUID = metaData.clusterUUID; + this.coordinationMetaData = metaData.coordinationMetaData; this.transientSettings = metaData.transientSettings; this.persistentSettings = metaData.persistentSettings; this.version = metaData.version; @@ -1076,6 +1103,11 @@ public Builder updateNumberOfReplicas(final int numberOfReplicas, final String[] return this; } + public Builder coordinationMetaData(CoordinationMetaData coordinationMetaData) { + this.coordinationMetaData = coordinationMetaData; + return this; + } + public Settings transientSettings() { return this.transientSettings; } @@ -1161,8 +1193,8 @@ public MetaData build() { String[] allOpenIndicesArray = allOpenIndices.toArray(new String[allOpenIndices.size()]); String[] allClosedIndicesArray = allClosedIndices.toArray(new String[allClosedIndices.size()]); - return new MetaData(clusterUUID, version, transientSettings, persistentSettings, indices.build(), templates.build(), - customs.build(), allIndicesArray, allOpenIndicesArray, allClosedIndicesArray, aliasAndIndexLookup); + return new MetaData(clusterUUID, version, coordinationMetaData, transientSettings, persistentSettings, indices.build(), + templates.build(), customs.build(), allIndicesArray, allOpenIndicesArray, allClosedIndicesArray, aliasAndIndexLookup); } private SortedMap buildAliasAndIndexLookup() { diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java index a1e522317dace..514700818305a 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/AddVotingTombstonesRequestTests.java @@ -22,6 +22,7 @@ import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.coordination.CoordinationMetaData; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode.Role; import org.elasticsearch.cluster.node.DiscoveryNodes.Builder; @@ -83,7 +84,7 @@ public void testResolveAndCheckMaximum() { final ClusterState.Builder builder = ClusterState.builder(new ClusterName("cluster")).nodes(new Builder() .add(localNode).add(otherNode1).add(otherNode2).localNodeId(localNode.getId())); - builder.coordinationMetaData(CoordinationMetaData.builder().addVotingTombstone(otherNode1).build()); + builder.metaData(MetaData.builder().coordinationMetaData(CoordinationMetaData.builder().addVotingTombstone(otherNode1).build())); final ClusterState clusterState = builder.build(); assertThat(makeRequest().resolveNodesAndCheckMaximum(clusterState, 3, "setting.name"), diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java index e196e7a44af79..c40a16397e4c9 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java @@ -117,8 +117,9 @@ public void setupForTest() { setState(clusterService, builder(new ClusterName("cluster")) .nodes(new Builder().add(localNode).add(otherNode1).add(otherNode2).add(otherDataNode) .localNodeId(localNode.getId()).masterNodeId(localNode.getId())) - .coordinationMetaData(CoordinationMetaData.builder().lastAcceptedConfiguration(allNodesConfig) - .lastCommittedConfiguration(allNodesConfig).build())); + .metaData(MetaData.builder() + .coordinationMetaData(CoordinationMetaData.builder().lastAcceptedConfiguration(allNodesConfig) + .lastCommittedConfiguration(allNodesConfig).build()))); clusterStateObserver = new ClusterStateObserver(clusterService, null, logger, threadPool.getThreadContext()); } @@ -206,10 +207,11 @@ public void testWithdrawsVoteFromLocalNode() throws InterruptedException { public void testReturnsImmediatelyIfVoteAlreadyWithdrawn() throws InterruptedException { setState(clusterService, builder(clusterService.state()) - .coordinationMetaData(CoordinationMetaData.builder() - .lastCommittedConfiguration(VotingConfiguration.of(localNode, otherNode2)) - .lastAcceptedConfiguration(VotingConfiguration.of(localNode, otherNode2)) - .build())); + .metaData(MetaData.builder() + .coordinationMetaData(CoordinationMetaData.builder() + .lastCommittedConfiguration(VotingConfiguration.of(localNode, otherNode2)) + .lastAcceptedConfiguration(VotingConfiguration.of(localNode, otherNode2)) + .build()))); final CountDownLatch countDownLatch = new CountDownLatch(1); @@ -265,8 +267,11 @@ public void testOnlyMatchesMasterEligibleNodes() throws InterruptedException { public void testSucceedsEvenIfAllTombstonesAlreadyAdded() throws InterruptedException { final ClusterState.Builder builder = builder(clusterService.state()); - builder.coordinationMetaData(CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) - .addVotingTombstone(otherNode1).build()); + builder.metaData(MetaData.builder(). + coordinationMetaData( + CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) + .addVotingTombstone(otherNode1). + build())); setState(clusterService, builder); final CountDownLatch countDownLatch = new CountDownLatch(1); @@ -284,22 +289,25 @@ public void testSucceedsEvenIfAllTombstonesAlreadyAdded() throws InterruptedExce } public void testReturnsErrorIfMaximumTombstoneCountExceeded() throws InterruptedException { - final ClusterState.Builder builder = builder(clusterService.state()) - .metaData(MetaData.builder(clusterService.state().metaData()).persistentSettings( + final MetaData.Builder metaDataBuilder = MetaData.builder(clusterService.state().metaData()).persistentSettings( Settings.builder().put(clusterService.state().metaData().persistentSettings()) - .put(MAXIMUM_VOTING_TOMBSTONES_SETTING.getKey(), 2).build())); - builder.coordinationMetaData(CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) - .addVotingTombstone(localNode).build()); + .put(MAXIMUM_VOTING_TOMBSTONES_SETTING.getKey(), 2).build()); + CoordinationMetaData.Builder cmdb = + CoordinationMetaData.builder(clusterService.state().coordinationMetaData()).addVotingTombstone(localNode); + final int existingCount, newCount; if (randomBoolean()) { - builder.coordinationMetaData(CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) - .addVotingTombstone(otherNode1).build()); + cmdb.addVotingTombstone(otherNode1); existingCount = 2; newCount = 1; } else { existingCount = 1; newCount = 2; } + + metaDataBuilder.coordinationMetaData(cmdb.build()); + + final ClusterState.Builder builder = builder(clusterService.state()).metaData(metaDataBuilder); setState(clusterService, builder); final CountDownLatch countDownLatch = new CountDownLatch(1); @@ -388,11 +396,12 @@ public ClusterState execute(ClusterState currentState) { currentState.getVotingTombstones().forEach(t -> votingNodeIds.remove(t.getId())); final VotingConfiguration votingConfiguration = new VotingConfiguration(votingNodeIds); return builder(currentState) - .coordinationMetaData(CoordinationMetaData.builder(currentState.coordinationMetaData()) - .lastAcceptedConfiguration(votingConfiguration) - .lastCommittedConfiguration(votingConfiguration) - .build()) - .build(); + .metaData(MetaData.builder() + .coordinationMetaData(CoordinationMetaData.builder(currentState.coordinationMetaData()) + .lastAcceptedConfiguration(votingConfiguration) + .lastCommittedConfiguration(votingConfiguration) + .build())) + .build(); } @Override diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java index 8261a3b14c283..19794a3cc55b8 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportClearVotingTombstonesActionTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.coordination.CoordinationMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes.Builder; @@ -98,10 +99,11 @@ public void setupForTest() { final ClusterState.Builder builder = builder(new ClusterName("cluster")) .nodes(new Builder().add(localNode).add(otherNode1).add(otherNode2) .localNodeId(localNode.getId()).masterNodeId(localNode.getId())); - builder.coordinationMetaData(CoordinationMetaData.builder() - .addVotingTombstone(otherNode1) - .addVotingTombstone(otherNode2) - .build()); + builder.metaData(MetaData.builder() + .coordinationMetaData(CoordinationMetaData.builder() + .addVotingTombstone(otherNode1) + .addVotingTombstone(otherNode2) + .build())); setState(clusterService, builder); } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java index 4ef6f6c010c66..cb3fce0b2e142 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java @@ -72,11 +72,6 @@ public void testToXContent() throws IOException { " \"cluster_uuid\" : \"_na_\",\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + - " \"coordination\" : {\n" + - " \"term\" : 0,\n" + - " \"last_committed_config\" : [ ],\n" + - " \"last_accepted_config\" : [ ]\n" + - " },\n" + " \"master_node\" : \"node0\",\n" + " \"blocks\" : { },\n" + " \"nodes\" : {\n" + @@ -89,6 +84,11 @@ public void testToXContent() throws IOException { " },\n" + " \"metadata\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + + " \"coordination\" : {\n" + + " \"term\" : 0,\n" + + " \"last_committed_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ]\n" + + " },\n" + " \"templates\" : { },\n" + " \"indices\" : {\n" + " \"index\" : {\n" + @@ -145,11 +145,6 @@ public void testToXContent() throws IOException { " \"cluster_uuid\" : \"_na_\",\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + - " \"coordination\" : {\n" + - " \"term\" : 0,\n" + - " \"last_committed_config\" : [ ],\n" + - " \"last_accepted_config\" : [ ]\n" + - " },\n" + " \"master_node\" : \"node0\"\n" + " },\n" + " \"explanations\" : [\n" + @@ -183,6 +178,11 @@ public void testToXContent() throws IOException { " \"cluster_uuid\" : \"_na_\",\n" + " \"metadata\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + + " \"coordination\" : {\n" + + " \"term\" : 0,\n" + + " \"last_committed_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ]\n" + + " },\n" + " \"templates\" : { },\n" + " \"indices\" : {\n" + " \"index\" : {\n" + diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java index a23f3adf4f3d7..ab2ad25e72152 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationStateTests.java @@ -785,14 +785,14 @@ public static ClusterState clusterState(long term, long version, DiscoveryNodes VotingConfiguration lastAcceptedConfig, long value) { return setValue(ClusterState.builder(ClusterName.DEFAULT) .version(version) - .coordinationMetaData(CoordinationMetaData.builder() - .term(term) - .lastCommittedConfiguration(lastCommittedConfig) - .lastAcceptedConfiguration(lastAcceptedConfig) - .build()) .nodes(discoveryNodes) .metaData(MetaData.builder() - .clusterUUID(UUIDs.randomBase64UUID(random()))) // generate cluster UUID deterministically for repeatable tests + .clusterUUID(UUIDs.randomBase64UUID(random())) // generate cluster UUID deterministically for repeatable tests + .coordinationMetaData(CoordinationMetaData.builder() + .term(term) + .lastCommittedConfiguration(lastCommittedConfig) + .lastAcceptedConfiguration(lastAcceptedConfig) + .build())) .stateUUID(UUIDs.randomBase64UUID(random())) // generate cluster state UUID deterministically for repeatable tests .build(), value); } @@ -831,10 +831,11 @@ void reboot() { void setInitialState(VotingConfiguration initialConfig, long initialValue) { final ClusterState.Builder builder = ClusterState.builder(state.getLastAcceptedState()).incrementVersion(); - builder.coordinationMetaData(CoordinationMetaData.builder() - .lastAcceptedConfiguration(initialConfig) - .lastCommittedConfiguration(initialConfig) - .build()); + builder.metaData(MetaData.builder() + .coordinationMetaData(CoordinationMetaData.builder() + .lastAcceptedConfiguration(initialConfig) + .lastCommittedConfiguration(initialConfig) + .build())); state.setInitialState(setValue(builder.build(), initialValue)); } } diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java index 5f2cdb55e095d..ee5a2cb1ea8fb 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/NodeJoinTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.ESAllocationTestCase; import org.elasticsearch.cluster.block.ClusterBlocks; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.service.MasterService; @@ -106,12 +107,13 @@ private static ClusterState initialState(boolean withMaster, DiscoveryNode local .add(localNode) .localNodeId(localNode.getId()) .masterNodeId(withMaster ? localNode.getId() : null)) - .coordinationMetaData( - CoordinationMetaData.builder() - .term(term) - .lastAcceptedConfiguration(config) - .lastCommittedConfiguration(config) - .build()) + .metaData(MetaData.builder() + .coordinationMetaData( + CoordinationMetaData.builder() + .term(term) + .lastAcceptedConfiguration(config) + .lastCommittedConfiguration(config) + .build())) .version(version) .blocks(ClusterBlocks.EMPTY_CLUSTER_BLOCK).build(); return initialClusterState; From 8d546ae536bdf2648dc3f3d9512201bc65ebcff6 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Fri, 16 Nov 2018 12:28:35 +0300 Subject: [PATCH 04/22] CoordinationMetaData.fromXContent, toString and isGlobalStateEquals --- .../coordination/CoordinationMetaData.java | 45 +++++++++++++++-- .../cluster/metadata/MetaData.java | 11 +++- .../CoordinationMetaDataTests.java | 21 ++++++++ .../cluster/metadata/MetaDataTests.java | 50 +++++++++++++++++++ 4 files changed, 122 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java index 7e3d8d2a5f8af..a82a461ff6488 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java @@ -19,18 +19,22 @@ package org.elasticsearch.cluster.coordination; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.util.set.Sets; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ToXContentFragment; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -47,7 +51,35 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment { private final Set votingTombstones; - CoordinationMetaData(long term, VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration, + private static final ParseField TERM_PARSE_FIELD = new ParseField("term"); + private static final ParseField LAST_COMMITTED_CONFIGURATION_FIELD = new ParseField("last_committed_config"); + private static final ParseField LAST_ACCEPTED_CONFIGURATION_FIELD = new ParseField("last_accepted_config"); + + private static long term(Object[] termAndConfigs) { + return (long)termAndConfigs[0]; + } + + private static VotingConfiguration lastCommittedConfig(Object[] termAndConfig) { + List nodeIds = (List) termAndConfig[1]; + return new VotingConfiguration(new HashSet<>(nodeIds)); + } + + private static VotingConfiguration lastAcceptedConfig(Object[] termAndConfig) { + List nodeIds = (List) termAndConfig[2]; + return new VotingConfiguration(new HashSet<>(nodeIds)); + } + + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + "coordination", + termAndConfigs -> new CoordinationMetaData(term(termAndConfigs), lastCommittedConfig(termAndConfigs), + lastAcceptedConfig(termAndConfigs), Collections.emptySet())); + static { + PARSER.declareLong(ConstructingObjectParser.constructorArg(), TERM_PARSE_FIELD); + PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), LAST_COMMITTED_CONFIGURATION_FIELD); + PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), LAST_ACCEPTED_CONFIGURATION_FIELD); + } + + public CoordinationMetaData(long term, VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration, Set votingTombstones) { this.term = term; this.lastCommittedConfiguration = lastCommittedConfiguration; @@ -81,12 +113,16 @@ public void writeTo(StreamOutput out) throws IOException { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { return builder - .field("term", term) - .field("last_committed_config", lastCommittedConfiguration) - .field("last_accepted_config", lastAcceptedConfiguration); + .field(TERM_PARSE_FIELD.getPreferredName(), term) + .field(LAST_COMMITTED_CONFIGURATION_FIELD.getPreferredName(), lastCommittedConfiguration) + .field(LAST_ACCEPTED_CONFIGURATION_FIELD.getPreferredName(), lastAcceptedConfiguration); // TODO include voting tombstones here } + public static CoordinationMetaData fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } + public long term() { return term; } @@ -131,6 +167,7 @@ public String toString() { "term=" + term + ", lastCommittedConfiguration=" + lastCommittedConfiguration + ", lastAcceptedConfiguration=" + lastAcceptedConfiguration + + ", votingTombstones=" + votingTombstones + '}'; } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index faea54285953b..a5c81ab3bac7c 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -762,6 +762,9 @@ public Iterator iterator() { } public static boolean isGlobalStateEquals(MetaData metaData1, MetaData metaData2) { + if (!metaData1.coordinationMetaData.equals(metaData2.coordinationMetaData)) { + return false; + } if (!metaData1.persistentSettings.equals(metaData2.persistentSettings)) { return false; } @@ -1238,6 +1241,10 @@ public static void toXContent(MetaData metaData, XContentBuilder builder, ToXCon builder.field("version", metaData.version()); builder.field("cluster_uuid", metaData.clusterUUID); + builder.startObject("coordination"); + metaData.coordinationMetaData().toXContent(builder, params); + builder.endObject(); + if (!metaData.persistentSettings().isEmpty()) { builder.startObject("settings"); metaData.persistentSettings().toXContent(builder, new MapParams(Collections.singletonMap("flat_settings", "true"))); @@ -1305,7 +1312,9 @@ public static MetaData fromXContent(XContentParser parser) throws IOException { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { - if ("settings".equals(currentFieldName)) { + if ("coordination".equals(currentFieldName)) { + builder.coordinationMetaData(CoordinationMetaData.fromXContent(parser)); + } else if ("settings".equals(currentFieldName)) { builder.persistentSettings(Settings.fromXContent(parser)); } else if ("indices".equals(currentFieldName)) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { diff --git a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java index bf34901a03774..58e755d4e6f4a 100644 --- a/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/coordination/CoordinationMetaDataTests.java @@ -22,11 +22,17 @@ import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.UUIDs; +import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.util.set.Sets; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.EqualsHashCodeTestUtils; +import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -146,4 +152,19 @@ public void testCoordinationMetaDataSerializationEqualsHashCode() { return builder.build(); }); } + + public void testXContent() throws IOException { + CoordinationMetaData originalMeta = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), + Collections.emptySet()); //TODO use non-empty tombstones set once toXContent for tombstones is implemented + + final XContentBuilder builder = JsonXContent.contentBuilder(); + builder.startObject(); + originalMeta.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + + try (XContentParser parser = createParser(JsonXContent.jsonXContent, BytesReference.bytes(builder))) { + final CoordinationMetaData fromXContentMeta = CoordinationMetaData.fromXContent(parser); + assertThat(originalMeta, equalTo(fromXContentMeta)); + } + } } diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java index f5ac710510718..347a949845149 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java @@ -22,6 +22,8 @@ import org.elasticsearch.Version; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.cluster.ClusterModule; +import org.elasticsearch.cluster.coordination.CoordinationMetaData; +import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.Strings; import org.elasticsearch.common.UUIDs; import org.elasticsearch.common.bytes.BytesReference; @@ -31,6 +33,7 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentHelper; @@ -41,12 +44,15 @@ import org.elasticsearch.test.ESTestCase; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singleton; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; @@ -408,6 +414,50 @@ public void testXContentWithIndexGraveyard() throws IOException { } } + private static CoordinationMetaData.VotingConfiguration randomVotingConfig() { + return new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(randomInt(10), 20, false))); + } + + private Set randomDiscoveryNodeSet() { + final int size = randomIntBetween(1, 10); + final Set nodes = new HashSet<>(size); + while (nodes.size() < size) { + assertTrue(nodes.add(new DiscoveryNode(randomAlphaOfLength(10), randomAlphaOfLength(10), + UUIDs.randomBase64UUID(random()), randomAlphaOfLength(10), randomAlphaOfLength(10), buildNewFakeTransportAddress(), + emptyMap(), singleton(DiscoveryNode.Role.MASTER), Version.CURRENT))); + } + return nodes; + } + + public void testXContentWithCoordinationMetaData() throws IOException { + CoordinationMetaData originalMeta = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), + Collections.emptySet()); //TODO use non-empty tombstones set once toXContent for tombstones is implemented + + MetaData metaData = MetaData.builder().coordinationMetaData(originalMeta).build(); + + final XContentBuilder builder = JsonXContent.contentBuilder(); + builder.startObject(); + metaData.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + + try (XContentParser parser = createParser(JsonXContent.jsonXContent, BytesReference.bytes(builder))) { + final CoordinationMetaData fromXContentMeta = MetaData.fromXContent(parser).coordinationMetaData(); + assertThat(fromXContentMeta, equalTo(originalMeta)); + } + } + + public void testGlobalStateEqualsCoordinationMetaData() { + CoordinationMetaData cmd1 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), + randomDiscoveryNodeSet()); + MetaData md1 = MetaData.builder().coordinationMetaData(cmd1).build(); + CoordinationMetaData cmd2 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), + randomDiscoveryNodeSet()); + MetaData md2 = MetaData.builder().coordinationMetaData(cmd2).build(); + + assertTrue(MetaData.isGlobalStateEquals(md1, md1)); + assertFalse(MetaData.isGlobalStateEquals(md1, md2)); + } + public void testSerializationWithIndexGraveyard() throws IOException { final IndexGraveyard graveyard = IndexGraveyardTests.createRandom(); final MetaData originalMeta = MetaData.builder().indexGraveyard(graveyard).build(); From 4480147dc6a63910753a64826eef06bd4feda812 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:00:06 +0100 Subject: [PATCH 05/22] final builder --- .../configuration/TransportAddVotingTombstonesAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java index 67652bf247ac6..852ae6839c14a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesAction.java @@ -91,7 +91,7 @@ public ClusterState execute(ClusterState currentState) { assert resolvedNodes == null : resolvedNodes; resolvedNodes = resolveNodesAndCheckMaximum(request, currentState); - CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData()); + final CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData()); resolvedNodes.forEach(builder::addVotingTombstone); final MetaData newMetaData = MetaData.builder(currentState.metaData()).coordinationMetaData(builder.build()).build(); final ClusterState newState = ClusterState.builder(currentState).metaData(newMetaData).build(); From 58c856fdc57dde12d93a772b851a106c03dcb017 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:00:47 +0100 Subject: [PATCH 06/22] import VotingConfiguration --- .../main/java/org/elasticsearch/cluster/ClusterState.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index 5ac19cc70ade8..10e1ccd905900 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -27,6 +27,7 @@ import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.coordination.CoordinationMetaData; +import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; @@ -268,11 +269,11 @@ public ClusterName getClusterName() { return this.clusterName; } - public CoordinationMetaData.VotingConfiguration getLastAcceptedConfiguration() { + public VotingConfiguration getLastAcceptedConfiguration() { return coordinationMetaData().getLastAcceptedConfiguration(); } - public CoordinationMetaData.VotingConfiguration getLastCommittedConfiguration() { + public VotingConfiguration getLastCommittedConfiguration() { return coordinationMetaData().getLastCommittedConfiguration(); } From a0e86bf1672762276c5c236922cd0e32062165fb Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:09:22 +0100 Subject: [PATCH 07/22] cmd -> coordinationMetaData, cmdb -> coordinationMetaDataBuilder --- .../coordination/CoordinationState.java | 4 ++-- .../cluster/coordination/JoinHelper.java | 4 ++-- ...ransportAddVotingTombstonesActionTests.java | 6 +++--- .../cluster/metadata/MetaDataTests.java | 18 +++++++++--------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java index 099f7ecaabb61..ec106e1a1fe8f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationState.java @@ -458,10 +458,10 @@ public interface PersistedState { */ default void markLastAcceptedConfigAsCommitted() { final ClusterState lastAcceptedState = getLastAcceptedState(); - final CoordinationMetaData cmd = CoordinationMetaData.builder(lastAcceptedState.coordinationMetaData()) + final CoordinationMetaData coordinationMetaData = CoordinationMetaData.builder(lastAcceptedState.coordinationMetaData()) .lastCommittedConfiguration(lastAcceptedState.getLastAcceptedConfiguration()) .build(); - final MetaData metaData = MetaData.builder(lastAcceptedState.metaData()).coordinationMetaData(cmd).build(); + final MetaData metaData = MetaData.builder(lastAcceptedState.metaData()).coordinationMetaData(coordinationMetaData).build(); setLastAcceptedState(ClusterState.builder(lastAcceptedState).metaData(metaData).build()); } } diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java b/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java index 6175a1be7f7f0..8dbe2a35c0ea4 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/JoinHelper.java @@ -97,9 +97,9 @@ public ClusterTasksResult execute(ClusterState currentSta final long currentTerm = currentTermSupplier.getAsLong(); if (currentState.term() != currentTerm) { - final CoordinationMetaData cmd = + final CoordinationMetaData coordinationMetaData = CoordinationMetaData.builder(currentState.coordinationMetaData()).term(currentTerm).build(); - final MetaData metaData = MetaData.builder(currentState.metaData()).coordinationMetaData(cmd).build(); + final MetaData metaData = MetaData.builder(currentState.metaData()).coordinationMetaData(coordinationMetaData).build(); currentState = ClusterState.builder(currentState).metaData(metaData).build(); } return super.execute(currentState, joiningTasks); diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java index c40a16397e4c9..6e8bdff1292fd 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java @@ -292,12 +292,12 @@ public void testReturnsErrorIfMaximumTombstoneCountExceeded() throws Interrupted final MetaData.Builder metaDataBuilder = MetaData.builder(clusterService.state().metaData()).persistentSettings( Settings.builder().put(clusterService.state().metaData().persistentSettings()) .put(MAXIMUM_VOTING_TOMBSTONES_SETTING.getKey(), 2).build()); - CoordinationMetaData.Builder cmdb = + CoordinationMetaData.Builder coordinationMetaDataBuilder = CoordinationMetaData.builder(clusterService.state().coordinationMetaData()).addVotingTombstone(localNode); final int existingCount, newCount; if (randomBoolean()) { - cmdb.addVotingTombstone(otherNode1); + coordinationMetaDataBuilder.addVotingTombstone(otherNode1); existingCount = 2; newCount = 1; } else { @@ -305,7 +305,7 @@ public void testReturnsErrorIfMaximumTombstoneCountExceeded() throws Interrupted newCount = 2; } - metaDataBuilder.coordinationMetaData(cmdb.build()); + metaDataBuilder.coordinationMetaData(coordinationMetaDataBuilder.build()); final ClusterState.Builder builder = builder(clusterService.state()).metaData(metaDataBuilder); setState(clusterService, builder); diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java index 347a949845149..b9c015f22dc16 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java @@ -447,15 +447,15 @@ public void testXContentWithCoordinationMetaData() throws IOException { } public void testGlobalStateEqualsCoordinationMetaData() { - CoordinationMetaData cmd1 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), - randomDiscoveryNodeSet()); - MetaData md1 = MetaData.builder().coordinationMetaData(cmd1).build(); - CoordinationMetaData cmd2 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(), - randomDiscoveryNodeSet()); - MetaData md2 = MetaData.builder().coordinationMetaData(cmd2).build(); - - assertTrue(MetaData.isGlobalStateEquals(md1, md1)); - assertFalse(MetaData.isGlobalStateEquals(md1, md2)); + CoordinationMetaData coordinationMetaData1 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), + randomVotingConfig(), randomDiscoveryNodeSet()); + MetaData metaData1 = MetaData.builder().coordinationMetaData(coordinationMetaData1).build(); + CoordinationMetaData coordinationMetaData2 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), + randomVotingConfig(), randomDiscoveryNodeSet()); + MetaData metaData2 = MetaData.builder().coordinationMetaData(coordinationMetaData2).build(); + + assertTrue(MetaData.isGlobalStateEquals(metaData1, metaData1)); + assertFalse(MetaData.isGlobalStateEquals(metaData1, metaData2)); } public void testSerializationWithIndexGraveyard() throws IOException { From ef622d76b6834a515459f24fad8ecc46af1e71ea Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:16:32 +0100 Subject: [PATCH 08/22] Reuse old coordination metadata --- .../elasticsearch/cluster/coordination/Coordinator.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java index 7466875dc2bb3..be39f5c7038fa 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java @@ -627,15 +627,10 @@ public boolean setInitialConfiguration(final VotingConfiguration votingConfigura logger.info("setting initial configuration to {}", votingConfiguration); final Builder builder = masterService.incrementVersion(currentState); - final CoordinationMetaData coordinationMetaData = CoordinationMetaData.builder() - .term(currentState.term()) - .lastAcceptedConfiguration(votingConfiguration) - .lastCommittedConfiguration(votingConfiguration) - .build(); MetaData.Builder metaDataBuilder = MetaData.builder(); // automatically generate a UID for the metadata if we need to metaDataBuilder.generateClusterUuidIfNeeded(); // TODO generate UUID in bootstrapping tool? - metaDataBuilder.coordinationMetaData(coordinationMetaData); + metaDataBuilder.coordinationMetaData(CoordinationMetaData.builder(currentState.coordinationMetaData()).build()); builder.metaData(metaDataBuilder); coordinationState.get().setInitialState(builder.build()); preVoteCollector.update(getPreVoteResponse(), null); // pick up the change to last-accepted version From 9232c57f92149dd441f02f103309e013ed6071d4 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:21:07 +0100 Subject: [PATCH 09/22] do not loose old metadata --- .../TransportAddVotingTombstonesActionTests.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java index 6e8bdff1292fd..b4f69c417db88 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java @@ -206,9 +206,10 @@ public void testWithdrawsVoteFromLocalNode() throws InterruptedException { } public void testReturnsImmediatelyIfVoteAlreadyWithdrawn() throws InterruptedException { - setState(clusterService, builder(clusterService.state()) - .metaData(MetaData.builder() - .coordinationMetaData(CoordinationMetaData.builder() + final ClusterState state = clusterService.state(); + setState(clusterService, builder(state) + .metaData(MetaData.builder(state.metaData()) + .coordinationMetaData(CoordinationMetaData.builder(state.coordinationMetaData()) .lastCommittedConfiguration(VotingConfiguration.of(localNode, otherNode2)) .lastAcceptedConfiguration(VotingConfiguration.of(localNode, otherNode2)) .build()))); From 143a9ec5e4010e797a4712943a94b914dbf77e9c Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:22:44 +0100 Subject: [PATCH 10/22] do not loose old metadata 2 --- .../TransportAddVotingTombstonesActionTests.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java index b4f69c417db88..1ad55954fefd0 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java @@ -267,10 +267,11 @@ public void testOnlyMatchesMasterEligibleNodes() throws InterruptedException { } public void testSucceedsEvenIfAllTombstonesAlreadyAdded() throws InterruptedException { - final ClusterState.Builder builder = builder(clusterService.state()); - builder.metaData(MetaData.builder(). + final ClusterState state = clusterService.state(); + final ClusterState.Builder builder = builder(state); + builder.metaData(MetaData.builder(state.metaData()). coordinationMetaData( - CoordinationMetaData.builder(clusterService.state().coordinationMetaData()) + CoordinationMetaData.builder(state.coordinationMetaData()) .addVotingTombstone(otherNode1). build())); setState(clusterService, builder); From c3b07765e2c7ca2402de40084dfbe4c0e53a030e Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:23:29 +0100 Subject: [PATCH 11/22] do not loose old metadata 3 --- .../configuration/TransportAddVotingTombstonesActionTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java index 1ad55954fefd0..4153ce373ce39 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/configuration/TransportAddVotingTombstonesActionTests.java @@ -398,7 +398,7 @@ public ClusterState execute(ClusterState currentState) { currentState.getVotingTombstones().forEach(t -> votingNodeIds.remove(t.getId())); final VotingConfiguration votingConfiguration = new VotingConfiguration(votingNodeIds); return builder(currentState) - .metaData(MetaData.builder() + .metaData(MetaData.builder(currentState.metaData()) .coordinationMetaData(CoordinationMetaData.builder(currentState.coordinationMetaData()) .lastAcceptedConfiguration(votingConfiguration) .lastCommittedConfiguration(votingConfiguration) From 43936667c6e6dccd778e4b299960d177b6adfd3f Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:34:58 +0100 Subject: [PATCH 12/22] Add voting tombstone to coordination meta in test --- .../cluster/ClusterStateDiffIT.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java index 978dbf33681cb..c62cb3cab6494 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java @@ -20,7 +20,6 @@ package org.elasticsearch.cluster; import com.carrotsearch.hppc.cursors.ObjectCursor; -import org.elasticsearch.Version; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.coordination.CoordinationMetaData; @@ -79,10 +78,8 @@ public class ClusterStateDiffIT extends ESIntegTestCase { public void testClusterStateDiffSerialization() throws Exception { NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry(ClusterModule.getNamedWriteables()); - DiscoveryNode masterNode = new DiscoveryNode("master", buildNewFakeTransportAddress(), - emptyMap(), emptySet(), Version.CURRENT); - DiscoveryNode otherNode = new DiscoveryNode("other", buildNewFakeTransportAddress(), - emptyMap(), emptySet(), Version.CURRENT); + DiscoveryNode masterNode = randomNode("master"); + DiscoveryNode otherNode = randomNode("other"); DiscoveryNodes discoveryNodes = DiscoveryNodes.builder().add(masterNode).add(otherNode).localNodeId(masterNode.getId()).build(); ClusterState clusterState = ClusterState.builder(new ClusterName("test")).nodes(discoveryNodes).build(); ClusterState clusterStateFromDiffs = @@ -149,6 +146,7 @@ public void testClusterStateDiffSerialization() throws Exception { assertThat(clusterStateFromDiffs.stateUUID(), equalTo(clusterState.stateUUID())); assertThat(clusterStateFromDiffs.getLastAcceptedConfiguration(), equalTo(clusterState.getLastAcceptedConfiguration())); assertThat(clusterStateFromDiffs.getLastCommittedConfiguration(), equalTo(clusterState.getLastCommittedConfiguration())); + assertThat(clusterStateFromDiffs.getVotingTombstones(), equalTo(clusterState.getVotingTombstones())); // Check nodes assertThat(clusterStateFromDiffs.nodes().getNodes(), equalTo(clusterState.nodes().getNodes())); @@ -212,9 +210,16 @@ private ClusterState.Builder randomCoordinationMetaData(ClusterState clusterStat metaBuilder.lastAcceptedConfiguration( new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); } + if (randomBoolean()) { + metaBuilder.addVotingTombstone(randomNode("node-" + randomAlphaOfLength(10))); + } return builder; } + private DiscoveryNode randomNode(String nodeId) { + return new DiscoveryNode(nodeId, buildNewFakeTransportAddress(), emptyMap(), emptySet(), randomVersion(random())); + } + /** * Randomly updates nodes in the cluster state */ @@ -226,15 +231,13 @@ private ClusterState.Builder randomNodes(ClusterState clusterState) { if (nodeId.startsWith("node-")) { nodes.remove(nodeId); if (randomBoolean()) { - nodes.add(new DiscoveryNode(nodeId, buildNewFakeTransportAddress(), emptyMap(), - emptySet(), randomVersion(random()))); + nodes.add(randomNode(nodeId)); } } } int additionalNodeCount = randomIntBetween(1, 20); for (int i = 0; i < additionalNodeCount; i++) { - nodes.add(new DiscoveryNode("node-" + randomAlphaOfLength(10), buildNewFakeTransportAddress(), - emptyMap(), emptySet(), randomVersion(random()))); + nodes.add(randomNode("node-" + randomAlphaOfLength(10))); } return ClusterState.builder(clusterState).nodes(nodes); } From 452b91e07213c069b5054c92d2744c4dbe8168ad Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:36:01 +0100 Subject: [PATCH 13/22] do not loose coordination meta data --- .../test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java index c62cb3cab6494..cc9f5afae954b 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java @@ -200,7 +200,7 @@ public void testClusterStateDiffSerialization() throws Exception { private ClusterState.Builder randomCoordinationMetaData(ClusterState clusterState) { ClusterState.Builder builder = ClusterState.builder(clusterState); - CoordinationMetaData.Builder metaBuilder = CoordinationMetaData.builder(); + CoordinationMetaData.Builder metaBuilder = CoordinationMetaData.builder(clusterState.coordinationMetaData()); metaBuilder.term(randomNonNegativeLong()); if (randomBoolean()) { metaBuilder.lastCommittedConfiguration( From 04e2324c3948b02eb0321c87b310710c57af95a0 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:37:46 +0100 Subject: [PATCH 14/22] squash fields equals assert into coordination metadata eq assert --- .../java/org/elasticsearch/cluster/ClusterStateDiffIT.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java index cc9f5afae954b..aa7f07c1bc027 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java @@ -142,11 +142,7 @@ public void testClusterStateDiffSerialization() throws Exception { try { // Check non-diffable elements assertThat(clusterStateFromDiffs.version(), equalTo(clusterState.version())); - assertThat(clusterStateFromDiffs.term(), equalTo(clusterState.term())); - assertThat(clusterStateFromDiffs.stateUUID(), equalTo(clusterState.stateUUID())); - assertThat(clusterStateFromDiffs.getLastAcceptedConfiguration(), equalTo(clusterState.getLastAcceptedConfiguration())); - assertThat(clusterStateFromDiffs.getLastCommittedConfiguration(), equalTo(clusterState.getLastCommittedConfiguration())); - assertThat(clusterStateFromDiffs.getVotingTombstones(), equalTo(clusterState.getVotingTombstones())); + assertThat(clusterStateFromDiffs.coordinationMetaData(), equalTo(clusterState.coordinationMetaData())); // Check nodes assertThat(clusterStateFromDiffs.nodes().getNodes(), equalTo(clusterState.nodes().getNodes())); From 9006e32fcb0f385af8d8dd91fda67c810b0a61c6 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:40:05 +0100 Subject: [PATCH 15/22] Add Zen2 BWC TODO --- .../main/java/org/elasticsearch/cluster/metadata/MetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index a5c81ab3bac7c..9efa73b82ff9f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -833,7 +833,7 @@ private static class MetaDataDiff implements Diff { MetaDataDiff(StreamInput in) throws IOException { clusterUUID = in.readString(); version = in.readLong(); - if (in.getVersion().onOrAfter(Version.V_7_0_0)) { + if (in.getVersion().onOrAfter(Version.V_7_0_0)) { //TODO revisit after Zen2 BWC is implemented coordinationMetaData = new CoordinationMetaData(in); } else { coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; From ef5341e5fc19b796911a5e54dbadd254ea41198d Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 17:51:56 +0100 Subject: [PATCH 16/22] Fix ClusterStatsMonitoringDocTests --- .../collector/cluster/ClusterStatsMonitoringDocTests.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java index 1825c7a7c2673..9b536b02c3ad0 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java @@ -331,6 +331,7 @@ public void testToXContent() throws IOException { needToEnableTLS); final BytesReference xContent = XContentHelper.toXContent(doc, XContentType.JSON, false); + logger.error(xContent.utf8ToString()); assertEquals("{" + "\"cluster_uuid\":\"_cluster\"," + "\"timestamp\":\"2017-08-07T12:03:22.133Z\"," @@ -519,11 +520,8 @@ public void testToXContent() throws IOException { + "\"nodes_hash\":1314980060," + "\"status\":\"green\"," + "\"cluster_uuid\":\"_cluster\"," - + "\"term\":0," + "\"version\":12," + "\"state_uuid\":\"_state_uuid\"," - + "\"last_committed_config\":[]," - + "\"last_accepted_config\":[]," + "\"master_node\":\"_node\"," + "\"nodes\":{" + "\"_node_id\":{" From 91171e9a1d649424393fff97665dda6cd1c2a813 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Mon, 19 Nov 2018 21:18:09 +0100 Subject: [PATCH 17/22] Fix bug --- .../elasticsearch/cluster/coordination/Coordinator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java index be39f5c7038fa..062a0b806f835 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java @@ -627,10 +627,15 @@ public boolean setInitialConfiguration(final VotingConfiguration votingConfigura logger.info("setting initial configuration to {}", votingConfiguration); final Builder builder = masterService.incrementVersion(currentState); + final CoordinationMetaData coordinationMetaData = CoordinationMetaData.builder(currentState.coordinationMetaData()) + .lastAcceptedConfiguration(votingConfiguration) + .lastCommittedConfiguration(votingConfiguration) + .build(); + MetaData.Builder metaDataBuilder = MetaData.builder(); // automatically generate a UID for the metadata if we need to metaDataBuilder.generateClusterUuidIfNeeded(); // TODO generate UUID in bootstrapping tool? - metaDataBuilder.coordinationMetaData(CoordinationMetaData.builder(currentState.coordinationMetaData()).build()); + metaDataBuilder.coordinationMetaData(coordinationMetaData); builder.metaData(metaDataBuilder); coordinationState.get().setInitialState(builder.build()); preVoteCollector.update(getPreVoteResponse(), null); // pick up the change to last-accepted version From 16c4884403f4ca268ab747e93d405f9d7b7b88b1 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Tue, 20 Nov 2018 19:31:34 +0100 Subject: [PATCH 18/22] @SuppressWarnings("unchecked") --- .../cluster/coordination/CoordinationMetaData.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java index a82a461ff6488..872410c922184 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java @@ -59,11 +59,13 @@ private static long term(Object[] termAndConfigs) { return (long)termAndConfigs[0]; } + @SuppressWarnings("unchecked") private static VotingConfiguration lastCommittedConfig(Object[] termAndConfig) { List nodeIds = (List) termAndConfig[1]; return new VotingConfiguration(new HashSet<>(nodeIds)); } + @SuppressWarnings("unchecked") private static VotingConfiguration lastAcceptedConfig(Object[] termAndConfig) { List nodeIds = (List) termAndConfig[2]; return new VotingConfiguration(new HashSet<>(nodeIds)); From 310d65a5b5ae0dcd9c582b7fb8a9965bb22985e5 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Tue, 20 Nov 2018 19:33:45 +0100 Subject: [PATCH 19/22] Move set copy from builder to constructor --- .../cluster/coordination/CoordinationMetaData.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java index 872410c922184..58cf0d9e084e0 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java @@ -86,7 +86,7 @@ public CoordinationMetaData(long term, VotingConfiguration lastCommittedConfigur this.term = term; this.lastCommittedConfiguration = lastCommittedConfiguration; this.lastAcceptedConfiguration = lastAcceptedConfiguration; - this.votingTombstones = votingTombstones; + this.votingTombstones = Collections.unmodifiableSet(new HashSet<>(votingTombstones)); } public CoordinationMetaData(StreamInput in) throws IOException { @@ -216,8 +216,7 @@ public Builder clearVotingTombstones() { } public CoordinationMetaData build() { - return new CoordinationMetaData(term, lastCommittedConfiguration, lastAcceptedConfiguration, - Collections.unmodifiableSet(new HashSet<>(votingTombstones))); + return new CoordinationMetaData(term, lastCommittedConfiguration, lastAcceptedConfiguration, votingTombstones); } } From 39392e114fbf16b730d47e98a6cba384082efaf9 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Wed, 21 Nov 2018 13:38:48 +0100 Subject: [PATCH 20/22] Remove log from test --- .../collector/cluster/ClusterStatsMonitoringDocTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java index 9b536b02c3ad0..08cdbaa497044 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java @@ -331,7 +331,6 @@ public void testToXContent() throws IOException { needToEnableTLS); final BytesReference xContent = XContentHelper.toXContent(doc, XContentType.JSON, false); - logger.error(xContent.utf8ToString()); assertEquals("{" + "\"cluster_uuid\":\"_cluster\"," + "\"timestamp\":\"2017-08-07T12:03:22.133Z\"," From d99c52d27586ef04a4ce64d3ce4daf6ef471cf73 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Wed, 21 Nov 2018 13:39:39 +0100 Subject: [PATCH 21/22] Rename JSON fields --- .../src/main/java/org/elasticsearch/cluster/ClusterState.java | 2 +- .../cluster/coordination/CoordinationMetaData.java | 2 +- .../java/org/elasticsearch/cluster/metadata/MetaData.java | 2 +- .../admin/cluster/reroute/ClusterRerouteResponseTests.java | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index 10e1ccd905900..535aed7c60a39 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -469,7 +469,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject("metadata"); builder.field("cluster_uuid", metaData().clusterUUID()); - builder.startObject("coordination"); + builder.startObject("cluster_coordination"); coordinationMetaData().toXContent(builder, params); builder.endObject(); diff --git a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java index 58cf0d9e084e0..072a31b1790fb 100644 --- a/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java @@ -72,7 +72,7 @@ private static VotingConfiguration lastAcceptedConfig(Object[] termAndConfig) { } private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( - "coordination", + "coordination_metadata", termAndConfigs -> new CoordinationMetaData(term(termAndConfigs), lastCommittedConfig(termAndConfigs), lastAcceptedConfig(termAndConfigs), Collections.emptySet())); static { diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index 9efa73b82ff9f..b9a4d3e1b9977 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -1241,7 +1241,7 @@ public static void toXContent(MetaData metaData, XContentBuilder builder, ToXCon builder.field("version", metaData.version()); builder.field("cluster_uuid", metaData.clusterUUID); - builder.startObject("coordination"); + builder.startObject("cluster_coordination"); metaData.coordinationMetaData().toXContent(builder, params); builder.endObject(); diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java index cb3fce0b2e142..863ced3c1b306 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java @@ -84,7 +84,7 @@ public void testToXContent() throws IOException { " },\n" + " \"metadata\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + - " \"coordination\" : {\n" + + " \"cluster_coordination\" : {\n" + " \"term\" : 0,\n" + " \"last_committed_config\" : [ ],\n" + " \"last_accepted_config\" : [ ]\n" + @@ -178,7 +178,7 @@ public void testToXContent() throws IOException { " \"cluster_uuid\" : \"_na_\",\n" + " \"metadata\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + - " \"coordination\" : {\n" + + " \"cluster_coordination\" : {\n" + " \"term\" : 0,\n" + " \"last_committed_config\" : [ ],\n" + " \"last_accepted_config\" : [ ]\n" + From 219b569ebc080efbf424afe1ecd066c92b553879 Mon Sep 17 00:00:00 2001 From: Andrey Ershov Date: Wed, 21 Nov 2018 13:53:46 +0100 Subject: [PATCH 22/22] MetaData.fromXContent fix --- .../main/java/org/elasticsearch/cluster/metadata/MetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index b9a4d3e1b9977..36fa6c6e6fbd5 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -1312,7 +1312,7 @@ public static MetaData fromXContent(XContentParser parser) throws IOException { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { - if ("coordination".equals(currentFieldName)) { + if ("cluster_coordination".equals(currentFieldName)) { builder.coordinationMetaData(CoordinationMetaData.fromXContent(parser)); } else if ("settings".equals(currentFieldName)) { builder.persistentSettings(Settings.fromXContent(parser));