Skip to content

Commit 0f9b4c4

Browse files
Make MasterService.patchVersions not Rebuild the Full CS (#79860)
This makes the method really just patch the version via a cheap copy constructor. Moreover, it makes the cluster state builder smarter when it comes to updating the routing nodes so they aren't rebuilt so often as well.
1 parent 610043f commit 0f9b4c4

File tree

6 files changed

+233
-46
lines changed

6 files changed

+233
-46
lines changed

server/src/main/java/org/elasticsearch/cluster/ClusterState.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.elasticsearch.common.io.stream.StreamOutput;
3939
import org.elasticsearch.common.io.stream.VersionedNamedWriteable;
4040
import org.elasticsearch.common.settings.Settings;
41+
import org.elasticsearch.core.Nullable;
4142
import org.elasticsearch.xcontent.ToXContentFragment;
4243
import org.elasticsearch.xcontent.XContentBuilder;
4344

@@ -121,12 +122,21 @@ default boolean isPrivate() {
121122

122123
public ClusterState(long version, String stateUUID, ClusterState state) {
123124
this(state.clusterName, version, stateUUID, state.metadata(), state.routingTable(), state.nodes(), state.blocks(),
124-
state.customs(), false);
125-
}
126-
127-
public ClusterState(ClusterName clusterName, long version, String stateUUID, Metadata metadata, RoutingTable routingTable,
128-
DiscoveryNodes nodes, ClusterBlocks blocks, ImmutableOpenMap<String, Custom> customs,
129-
boolean wasReadFromDiff) {
125+
state.customs(), false, state.routingNodes);
126+
}
127+
128+
public ClusterState(
129+
ClusterName clusterName,
130+
long version,
131+
String stateUUID,
132+
Metadata metadata,
133+
RoutingTable routingTable,
134+
DiscoveryNodes nodes,
135+
ClusterBlocks blocks,
136+
ImmutableOpenMap<String, Custom> customs,
137+
boolean wasReadFromDiff,
138+
@Nullable RoutingNodes routingNodes
139+
) {
130140
this.version = version;
131141
this.stateUUID = stateUUID;
132142
this.clusterName = clusterName;
@@ -136,6 +146,9 @@ public ClusterState(ClusterName clusterName, long version, String stateUUID, Met
136146
this.blocks = blocks;
137147
this.customs = customs;
138148
this.wasReadFromDiff = wasReadFromDiff;
149+
this.routingNodes = routingNodes;
150+
assert routingNodes == null || routingNodes.equals(new RoutingNodes(this)) :
151+
"RoutingNodes [" + routingNodes + "] are not consistent with this cluster state [" + new RoutingNodes(this) + "]";
139152
}
140153

141154
public long term() {
@@ -476,6 +489,8 @@ public static Builder builder(ClusterState state) {
476489

477490
public static class Builder {
478491

492+
private ClusterState previous;
493+
479494
private final ClusterName clusterName;
480495
private long version = 0;
481496
private String uuid = UNKNOWN_UUID;
@@ -487,6 +502,7 @@ public static class Builder {
487502
private boolean fromDiff;
488503

489504
public Builder(ClusterState state) {
505+
this.previous = state;
490506
this.clusterName = state.clusterName;
491507
this.version = state.version();
492508
this.uuid = state.stateUUID();
@@ -580,7 +596,16 @@ public ClusterState build() {
580596
if (UNKNOWN_UUID.equals(uuid)) {
581597
uuid = UUIDs.randomBase64UUID();
582598
}
583-
return new ClusterState(clusterName, version, uuid, metadata, routingTable, nodes, blocks, customs.build(), fromDiff);
599+
final RoutingNodes routingNodes;
600+
if (previous != null && routingTable.indicesRouting() == previous.routingTable.indicesRouting() && nodes == previous.nodes) {
601+
// routing table contents and nodes haven't changed so we can try to reuse the previous state's routing nodes which are
602+
// expensive to compute
603+
routingNodes = previous.routingNodes;
604+
} else {
605+
routingNodes = null;
606+
}
607+
return new ClusterState(clusterName, version, uuid, metadata, routingTable, nodes, blocks, customs.build(), fromDiff,
608+
routingNodes);
584609
}
585610

586611
public static byte[] toBytes(ClusterState state) throws IOException {

server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -192,34 +192,41 @@ public interface NonRestorableCustom extends Custom {
192192

193193
private SortedMap<String, IndexAbstraction> indicesLookup;
194194

195-
Metadata(String clusterUUID, boolean clusterUUIDCommitted, long version, CoordinationMetadata coordinationMetadata,
196-
Settings transientSettings, Settings persistentSettings, DiffableStringMap hashesOfConsistentSettings,
197-
ImmutableOpenMap<String, IndexMetadata> indices, ImmutableOpenMap<String, IndexTemplateMetadata> templates,
198-
ImmutableOpenMap<String, Custom> customs, String[] allIndices, String[] visibleIndices, String[] allOpenIndices,
199-
String[] visibleOpenIndices, String[] allClosedIndices, String[] visibleClosedIndices,
200-
SortedMap<String, IndexAbstraction> indicesLookup) {
195+
private Metadata(
196+
String clusterUUID,
197+
boolean clusterUUIDCommitted,
198+
long version,
199+
CoordinationMetadata coordinationMetadata,
200+
Settings transientSettings,
201+
Settings persistentSettings,
202+
Settings settings,
203+
DiffableStringMap hashesOfConsistentSettings,
204+
int totalNumberOfShards,
205+
int totalOpenIndexShards,
206+
ImmutableOpenMap<String, IndexMetadata> indices,
207+
ImmutableOpenMap<String, IndexTemplateMetadata> templates,
208+
ImmutableOpenMap<String, Custom> customs,
209+
String[] allIndices,
210+
String[] visibleIndices,
211+
String[] allOpenIndices,
212+
String[] visibleOpenIndices,
213+
String[] allClosedIndices,
214+
String[] visibleClosedIndices,
215+
SortedMap<String, IndexAbstraction> indicesLookup
216+
) {
201217
this.clusterUUID = clusterUUID;
202218
this.clusterUUIDCommitted = clusterUUIDCommitted;
203219
this.version = version;
204220
this.coordinationMetadata = coordinationMetadata;
205221
this.transientSettings = transientSettings;
206222
this.persistentSettings = persistentSettings;
207-
this.settings = Settings.builder().put(persistentSettings).put(transientSettings).build();
223+
this.settings = settings;
208224
this.hashesOfConsistentSettings = hashesOfConsistentSettings;
209225
this.indices = indices;
210226
this.customs = customs;
211227
this.templates = templates;
212-
int totalNumberOfShards = 0;
213-
int totalOpenIndexShards = 0;
214-
for (IndexMetadata indexMetadata : indices.values()) {
215-
totalNumberOfShards += indexMetadata.getTotalNumberOfShards();
216-
if (IndexMetadata.State.OPEN.equals(indexMetadata.getState())) {
217-
totalOpenIndexShards += indexMetadata.getTotalNumberOfShards();
218-
}
219-
}
220228
this.totalNumberOfShards = totalNumberOfShards;
221229
this.totalOpenIndexShards = totalOpenIndexShards;
222-
223230
this.allIndices = allIndices;
224231
this.visibleIndices = visibleIndices;
225232
this.allOpenIndices = allOpenIndices;
@@ -229,6 +236,31 @@ public interface NonRestorableCustom extends Custom {
229236
this.indicesLookup = indicesLookup;
230237
}
231238

239+
public Metadata withIncrementedVersion() {
240+
return new Metadata(
241+
clusterUUID,
242+
clusterUUIDCommitted,
243+
version + 1,
244+
coordinationMetadata,
245+
transientSettings,
246+
persistentSettings,
247+
settings,
248+
hashesOfConsistentSettings,
249+
totalNumberOfShards,
250+
totalOpenIndexShards,
251+
indices,
252+
templates,
253+
customs,
254+
allIndices,
255+
visibleIndices,
256+
allOpenIndices,
257+
visibleOpenIndices,
258+
allClosedIndices,
259+
visibleClosedIndices,
260+
indicesLookup
261+
);
262+
}
263+
232264
public long version() {
233265
return this.version;
234266
}
@@ -1613,9 +1645,37 @@ public Metadata build(boolean builtIndicesLookupEagerly) {
16131645
String[] allClosedIndicesArray = allClosedIndices.toArray(Strings.EMPTY_ARRAY);
16141646
String[] visibleClosedIndicesArray = visibleClosedIndices.toArray(Strings.EMPTY_ARRAY);
16151647

1616-
return new Metadata(clusterUUID, clusterUUIDCommitted, version, coordinationMetadata, transientSettings, persistentSettings,
1617-
hashesOfConsistentSettings, indices, templates.build(), customs.build(), allIndicesArray, visibleIndicesArray,
1618-
allOpenIndicesArray, visibleOpenIndicesArray, allClosedIndicesArray, visibleClosedIndicesArray, indicesLookup);
1648+
int totalNumberOfShards = 0;
1649+
int totalOpenIndexShards = 0;
1650+
for (IndexMetadata indexMetadata : indices.values()) {
1651+
totalNumberOfShards += indexMetadata.getTotalNumberOfShards();
1652+
if (IndexMetadata.State.OPEN.equals(indexMetadata.getState())) {
1653+
totalOpenIndexShards += indexMetadata.getTotalNumberOfShards();
1654+
}
1655+
}
1656+
1657+
return new Metadata(
1658+
clusterUUID,
1659+
clusterUUIDCommitted,
1660+
version,
1661+
coordinationMetadata,
1662+
transientSettings,
1663+
persistentSettings,
1664+
Settings.builder().put(persistentSettings).put(transientSettings).build(),
1665+
hashesOfConsistentSettings,
1666+
totalNumberOfShards,
1667+
totalOpenIndexShards,
1668+
indices,
1669+
templates.build(),
1670+
customs.build(),
1671+
allIndicesArray,
1672+
visibleIndicesArray,
1673+
allOpenIndicesArray,
1674+
visibleOpenIndicesArray,
1675+
allClosedIndicesArray,
1676+
visibleClosedIndicesArray,
1677+
indicesLookup
1678+
);
16191679
}
16201680

16211681
static SortedMap<String, IndexAbstraction> buildIndicesLookup(DataStreamMetadata dataStreamMetadata,

server/src/main/java/org/elasticsearch/cluster/routing/RoutingNode.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.LinkedHashSet;
2323
import java.util.List;
2424
import java.util.Map;
25+
import java.util.Objects;
2526
import java.util.Set;
2627
import java.util.function.Predicate;
2728
import java.util.stream.Collectors;
@@ -34,6 +35,7 @@ public class RoutingNode implements Iterable<ShardRouting> {
3435

3536
private final String nodeId;
3637

38+
@Nullable
3739
private final DiscoveryNode node;
3840

3941
private final LinkedHashMap<ShardId, ShardRouting> shards; // LinkedHashMap to preserve order
@@ -48,7 +50,7 @@ public RoutingNode(String nodeId, DiscoveryNode node, ShardRouting... shards) {
4850
this(nodeId, node, buildShardRoutingMap(shards));
4951
}
5052

51-
RoutingNode(String nodeId, DiscoveryNode node, LinkedHashMap<ShardId, ShardRouting> shards) {
53+
RoutingNode(String nodeId, @Nullable DiscoveryNode node, LinkedHashMap<ShardId, ShardRouting> shards) {
5254
this.nodeId = nodeId;
5355
this.node = node;
5456
this.shards = shards;
@@ -88,6 +90,7 @@ public Iterator<ShardRouting> iterator() {
8890
*
8991
* @return discoveryNode of this node
9092
*/
93+
@Nullable
9194
public DiscoveryNode node() {
9295
return this.node;
9396
}
@@ -298,13 +301,17 @@ public String prettyPrint() {
298301
public String toString() {
299302
StringBuilder sb = new StringBuilder();
300303
sb.append("routingNode ([");
301-
sb.append(node.getName());
302-
sb.append("][");
303-
sb.append(node.getId());
304-
sb.append("][");
305-
sb.append(node.getHostName());
306-
sb.append("][");
307-
sb.append(node.getHostAddress());
304+
if (node != null) {
305+
sb.append(node.getName());
306+
sb.append("][");
307+
sb.append(node.getId());
308+
sb.append("][");
309+
sb.append(node.getHostName());
310+
sb.append("][");
311+
sb.append(node.getHostAddress());
312+
} else {
313+
sb.append("null");
314+
}
308315
sb.append("], [");
309316
sb.append(shards.size());
310317
sb.append(" assigned shards])");
@@ -320,7 +327,6 @@ public boolean isEmpty() {
320327
}
321328

322329
private boolean invariant() {
323-
324330
// initializingShards must consistent with that in shards
325331
Collection<ShardRouting> shardRoutingsInitializing =
326332
shards.values().stream().filter(ShardRouting::initializing).collect(Collectors.toList());
@@ -339,4 +345,21 @@ private boolean invariant() {
339345

340346
return true;
341347
}
348+
349+
@Override
350+
public boolean equals(Object o) {
351+
if (this == o) {
352+
return true;
353+
}
354+
if (o == null || getClass() != o.getClass()) {
355+
return false;
356+
}
357+
RoutingNode that = (RoutingNode) o;
358+
return nodeId.equals(that.nodeId) && Objects.equals(node, that.node) && shards.equals(that.shards);
359+
}
360+
361+
@Override
362+
public int hashCode() {
363+
return Objects.hash(nodeId, node, shards);
364+
}
342365
}

server/src/main/java/org/elasticsearch/cluster/routing/RoutingNodes.java

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,46 @@ public int size() {
778778
return nodesToShards.size();
779779
}
780780

781+
@Override
782+
public boolean equals(Object o) {
783+
if (this == o) {
784+
return true;
785+
}
786+
if (o == null || getClass() != o.getClass()) {
787+
return false;
788+
}
789+
RoutingNodes that = (RoutingNodes) o;
790+
return readOnly == that.readOnly
791+
&& inactivePrimaryCount == that.inactivePrimaryCount
792+
&& inactiveShardCount == that.inactiveShardCount
793+
&& relocatingShards == that.relocatingShards
794+
&& activeShardCount == that.activeShardCount
795+
&& totalShardCount == that.totalShardCount
796+
&& nodesToShards.equals(that.nodesToShards)
797+
&& unassignedShards.equals(that.unassignedShards)
798+
&& assignedShards.equals(that.assignedShards)
799+
&& attributeValuesByAttribute.equals(that.attributeValuesByAttribute)
800+
&& recoveriesPerNode.equals(that.recoveriesPerNode
801+
);
802+
}
803+
804+
@Override
805+
public int hashCode() {
806+
return Objects.hash(
807+
nodesToShards,
808+
unassignedShards,
809+
assignedShards,
810+
readOnly,
811+
inactivePrimaryCount,
812+
inactiveShardCount,
813+
relocatingShards,
814+
activeShardCount,
815+
totalShardCount,
816+
attributeValuesByAttribute,
817+
recoveriesPerNode
818+
);
819+
}
820+
781821
public static final class UnassignedShards implements Iterable<ShardRouting> {
782822

783823
private final RoutingNodes nodes;
@@ -990,6 +1030,26 @@ public ShardRouting[] drain() {
9901030
primaries = 0;
9911031
return mutableShardRoutings;
9921032
}
1033+
1034+
@Override
1035+
public boolean equals(Object o) {
1036+
if (this == o) {
1037+
return true;
1038+
}
1039+
if (o == null || getClass() != o.getClass()) {
1040+
return false;
1041+
}
1042+
UnassignedShards that = (UnassignedShards) o;
1043+
return primaries == that.primaries
1044+
&& ignoredPrimaries == that.ignoredPrimaries
1045+
&& unassigned.equals(that.unassigned)
1046+
&& ignored.equals(that.ignored);
1047+
}
1048+
1049+
@Override
1050+
public int hashCode() {
1051+
return Objects.hash(unassigned, ignored, primaries, ignoredPrimaries);
1052+
}
9931053
}
9941054

9951055

@@ -1183,5 +1243,22 @@ public static Recoveries getOrAdd(Map<String, Recoveries> map, String key) {
11831243
}
11841244
return recoveries;
11851245
}
1186-
}
1246+
1247+
@Override
1248+
public boolean equals(Object o) {
1249+
if (this == o) {
1250+
return true;
1251+
}
1252+
if (o == null || getClass() != o.getClass()) {
1253+
return false;
1254+
}
1255+
Recoveries that = (Recoveries) o;
1256+
return incoming == that.incoming && outgoing == that.outgoing;
1257+
}
1258+
1259+
@Override
1260+
public int hashCode() {
1261+
return Objects.hash(incoming, outgoing);
1262+
}
1263+
}
11871264
}

0 commit comments

Comments
 (0)