Skip to content

Commit 5453a2d

Browse files
authored
Remove nesting from multi allocation decision (#130844)
1 parent d52aad2 commit 5453a2d

File tree

3 files changed

+78
-125
lines changed

3 files changed

+78
-125
lines changed

server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocator.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,22 +1134,22 @@ private boolean tryRelocateShard(ModelNode minNode, ModelNode maxNode, ProjectIn
11341134
continue;
11351135
}
11361136

1137-
final Decision decision = new Decision.Multi().add(allocationDecision).add(rebalanceDecision);
1137+
final Decision.Type canAllocateOrRebalance = Decision.Type.min(allocationDecision.type(), rebalanceDecision.type());
11381138

11391139
maxNode.removeShard(projectIndex(shard), shard);
11401140
long shardSize = allocation.clusterInfo().getShardSize(shard, ShardRouting.UNAVAILABLE_EXPECTED_SHARD_SIZE);
11411141

1142-
assert decision.type() == Type.YES || decision.type() == Type.THROTTLE : decision.type();
1142+
assert canAllocateOrRebalance == Type.YES || canAllocateOrRebalance == Type.THROTTLE : canAllocateOrRebalance;
11431143
logger.debug(
11441144
"decision [{}]: relocate [{}] from [{}] to [{}]",
1145-
decision.type(),
1145+
canAllocateOrRebalance,
11461146
shard,
11471147
maxNode.getNodeId(),
11481148
minNode.getNodeId()
11491149
);
11501150
minNode.addShard(
11511151
projectIndex(shard),
1152-
decision.type() == Type.YES
1152+
canAllocateOrRebalance == Type.YES
11531153
/* only allocate on the cluster if we are not throttled */
11541154
? routingNodes.relocateShard(shard, minNode.getNodeId(), shardSize, "rebalance", allocation.changes()).v1()
11551155
: shard.relocate(minNode.getNodeId(), shardSize)

server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/AllocationDeciders.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ private Decision withDeciders(
205205
BiFunction<String, Decision, String> logMessageCreator
206206
) {
207207
if (debugMode == RoutingAllocation.DebugMode.OFF) {
208-
var result = Decision.YES;
208+
Decision result = Decision.YES;
209209
for (AllocationDecider decider : deciders) {
210210
var decision = deciderAction.apply(decider);
211211
if (decision.type() == Decision.Type.NO) {

server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/Decision.java

Lines changed: 73 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,18 @@
2323
import java.util.Collections;
2424
import java.util.List;
2525
import java.util.Locale;
26-
import java.util.Objects;
2726

2827
/**
29-
* This abstract class defining basic {@link Decision} used during shard
30-
* allocation process.
28+
* A {@link Decision} used during shard allocation process.
3129
*
3230
* @see AllocationDecider
3331
*/
34-
public abstract class Decision implements ToXContent, Writeable {
32+
public sealed interface Decision extends ToXContent, Writeable permits Decision.Single, Decision.Multi {
3533

36-
public static final Decision ALWAYS = new Single(Type.YES);
37-
public static final Decision YES = new Single(Type.YES);
38-
public static final Decision NO = new Single(Type.NO);
39-
public static final Decision THROTTLE = new Single(Type.THROTTLE);
34+
Single ALWAYS = new Single(Type.YES);
35+
Single YES = new Single(Type.YES);
36+
Single NO = new Single(Type.NO);
37+
Single THROTTLE = new Single(Type.THROTTLE);
4038

4139
/**
4240
* Creates a simple decision
@@ -46,40 +44,69 @@ public abstract class Decision implements ToXContent, Writeable {
4644
* @param explanationParams additional parameters for the decision
4745
* @return new {@link Decision} instance
4846
*/
49-
public static Decision single(Type type, @Nullable String label, @Nullable String explanation, @Nullable Object... explanationParams) {
47+
static Decision single(Type type, @Nullable String label, @Nullable String explanation, @Nullable Object... explanationParams) {
5048
return new Single(type, label, explanation, explanationParams);
5149
}
5250

53-
public static Decision readFrom(StreamInput in) throws IOException {
51+
static Decision readFrom(StreamInput in) throws IOException {
5452
// Determine whether to read a Single or Multi Decision
5553
if (in.readBoolean()) {
5654
Multi result = new Multi();
5755
int decisionCount = in.readVInt();
5856
for (int i = 0; i < decisionCount; i++) {
59-
Decision s = readFrom(in);
60-
result.decisions.add(s);
57+
var flag = in.readBoolean();
58+
assert flag == false : "nested multi decision is not permitted";
59+
var single = readSingleFrom(in);
60+
result.decisions.add(single);
6161
}
6262
return result;
6363
} else {
64-
final Type type = Type.readFrom(in);
65-
final String label = in.readOptionalString();
66-
final String explanation = in.readOptionalString();
67-
if (label == null && explanation == null) {
68-
return switch (type) {
69-
case YES -> YES;
70-
case THROTTLE -> THROTTLE;
71-
case NO -> NO;
72-
};
73-
}
74-
return new Single(type, label, explanation);
64+
return readSingleFrom(in);
65+
}
66+
}
67+
68+
private static Single readSingleFrom(StreamInput in) throws IOException {
69+
final Type type = Type.readFrom(in);
70+
final String label = in.readOptionalString();
71+
final String explanation = in.readOptionalString();
72+
if (label == null && explanation == null) {
73+
return switch (type) {
74+
case YES -> YES;
75+
case THROTTLE -> THROTTLE;
76+
case NO -> NO;
77+
};
7578
}
79+
return new Single(type, label, explanation);
7680
}
7781

82+
/**
83+
* Get the {@link Type} of this decision
84+
* @return {@link Type} of this decision
85+
*/
86+
Type type();
87+
88+
/**
89+
* Get the description label for this decision.
90+
*/
91+
@Nullable
92+
String label();
93+
94+
/**
95+
* Get the explanation for this decision.
96+
*/
97+
@Nullable
98+
String getExplanation();
99+
100+
/**
101+
* Return the list of all decisions that make up this decision
102+
*/
103+
List<Decision> getDecisions();
104+
78105
/**
79106
* This enumeration defines the
80107
* possible types of decisions
81108
*/
82-
public enum Type implements Writeable {
109+
enum Type implements Writeable {
83110
YES(1),
84111
THROTTLE(2),
85112
NO(0);
@@ -110,45 +137,22 @@ public boolean higherThan(Type other) {
110137
return false;
111138
} else if (other == NO) {
112139
return true;
113-
} else if (other == THROTTLE && this == YES) {
114-
return true;
115-
}
116-
return false;
140+
} else return other == THROTTLE && this == YES;
117141
}
118142

119-
}
120-
121-
/**
122-
* Get the {@link Type} of this decision
123-
* @return {@link Type} of this decision
124-
*/
125-
public abstract Type type();
126-
127-
/**
128-
* Get the description label for this decision.
129-
*/
130-
@Nullable
131-
public abstract String label();
132-
133-
/**
134-
* Get the explanation for this decision.
135-
*/
136-
@Nullable
137-
public abstract String getExplanation();
143+
/**
144+
* @return lowest decision by precedence NO->THROTTLE->YES
145+
*/
146+
public static Type min(Type a, Type b) {
147+
return a.higherThan(b) ? b : a;
148+
}
138149

139-
/**
140-
* Return the list of all decisions that make up this decision
141-
*/
142-
public abstract List<Decision> getDecisions();
150+
}
143151

144152
/**
145153
* Simple class representing a single decision
146154
*/
147-
public static class Single extends Decision implements ToXContentObject {
148-
private final Type type;
149-
private final String label;
150-
private final String explanationString;
151-
155+
record Single(Type type, String label, String explanationString) implements Decision, ToXContentObject {
152156
/**
153157
* Creates a new {@link Single} decision of a given type
154158
* @param type {@link Type} of the decision
@@ -165,24 +169,13 @@ private Single(Type type) {
165169
* @param explanationParams A set of additional parameters
166170
*/
167171
public Single(Type type, @Nullable String label, @Nullable String explanation, @Nullable Object... explanationParams) {
168-
this.type = type;
169-
this.label = label;
170-
if (explanationParams != null && explanationParams.length > 0) {
171-
this.explanationString = String.format(Locale.ROOT, explanation, explanationParams);
172-
} else {
173-
this.explanationString = explanation;
174-
}
175-
}
176-
177-
@Override
178-
public Type type() {
179-
return this.type;
180-
}
181-
182-
@Override
183-
@Nullable
184-
public String label() {
185-
return this.label;
172+
this(
173+
type,
174+
label,
175+
explanationParams != null && explanationParams.length > 0
176+
? String.format(Locale.ROOT, explanation, explanationParams)
177+
: explanation
178+
);
186179
}
187180

188181
@Override
@@ -199,29 +192,6 @@ public String getExplanation() {
199192
return this.explanationString;
200193
}
201194

202-
@Override
203-
public boolean equals(Object object) {
204-
if (this == object) {
205-
return true;
206-
}
207-
208-
if (object == null || getClass() != object.getClass()) {
209-
return false;
210-
}
211-
212-
Decision.Single s = (Decision.Single) object;
213-
return this.type == s.type && Objects.equals(label, s.label) && Objects.equals(explanationString, s.explanationString);
214-
}
215-
216-
@Override
217-
public int hashCode() {
218-
int result = type.hashCode();
219-
result = 31 * result + (label == null ? 0 : label.hashCode());
220-
String explanationStr = explanationString;
221-
result = 31 * result + (explanationStr == null ? 0 : explanationStr.hashCode());
222-
return result;
223-
}
224-
225195
@Override
226196
public String toString() {
227197
if (explanationString != null) {
@@ -254,17 +224,20 @@ public void writeTo(StreamOutput out) throws IOException {
254224
/**
255225
* Simple class representing a list of decisions
256226
*/
257-
public static class Multi extends Decision implements ToXContentFragment {
227+
record Multi(List<Single> decisions) implements Decision, ToXContentFragment {
258228

259-
private final List<Decision> decisions = new ArrayList<>();
229+
public Multi() {
230+
this(new ArrayList<>());
231+
}
260232

261233
/**
262234
* Add a decision to this {@link Multi}decision instance
263235
* @param decision {@link Decision} to add
264236
* @return {@link Multi}decision instance with the given decision added
265237
*/
266238
public Multi add(Decision decision) {
267-
decisions.add(decision);
239+
assert decision instanceof Single;
240+
decisions.add((Single) decision);
268241
return this;
269242
}
270243

@@ -300,26 +273,6 @@ public List<Decision> getDecisions() {
300273
return Collections.unmodifiableList(this.decisions);
301274
}
302275

303-
@Override
304-
public boolean equals(final Object object) {
305-
if (this == object) {
306-
return true;
307-
}
308-
309-
if (object == null || getClass() != object.getClass()) {
310-
return false;
311-
}
312-
313-
final Decision.Multi m = (Decision.Multi) object;
314-
315-
return this.decisions.equals(m.decisions);
316-
}
317-
318-
@Override
319-
public int hashCode() {
320-
return 31 * decisions.hashCode();
321-
}
322-
323276
@Override
324277
public String toString() {
325278
StringBuilder sb = new StringBuilder();

0 commit comments

Comments
 (0)