Skip to content

Commit 6149441

Browse files
committed
group allocation deciders by purpose
1 parent f31bd69 commit 6149441

File tree

50 files changed

+454
-236
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+454
-236
lines changed

server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/ShardRoutingRoleIT.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.elasticsearch.cluster.routing.allocation.command.CancelAllocationCommand;
3636
import org.elasticsearch.cluster.routing.allocation.decider.AllocationDecider;
3737
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
38+
import org.elasticsearch.cluster.routing.allocation.decider.DefaultAllocationDecider;
3839
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
3940
import org.elasticsearch.cluster.service.ClusterService;
4041
import org.elasticsearch.common.bytes.BytesReference;
@@ -179,7 +180,7 @@ public Collection<ActionHandler> getActions() {
179180

180181
@Override
181182
public Collection<AllocationDecider> createAllocationDeciders(Settings settings, ClusterSettings clusterSettings) {
182-
return List.of(new AllocationDecider() {
183+
return List.of(new DefaultAllocationDecider() {
183184
@Override
184185
public Decision canForceAllocatePrimary(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
185186
// once a primary is cancelled it _stays_ cancelled

server/src/internalClusterTest/java/org/elasticsearch/gateway/GatewayServiceIT.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.cluster.routing.allocation.FailedShard;
1616
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
1717
import org.elasticsearch.cluster.routing.allocation.decider.AllocationDecider;
18+
import org.elasticsearch.cluster.routing.allocation.decider.DefaultAllocationDecider;
1819
import org.elasticsearch.common.settings.ClusterSettings;
1920
import org.elasticsearch.common.settings.Setting;
2021
import org.elasticsearch.common.settings.Settings;
@@ -104,7 +105,7 @@ public int getNumberOfInFlightFetches() {
104105
}
105106
}
106107

107-
private static class TestAllocationDecider extends AllocationDecider {
108+
private static class TestAllocationDecider extends DefaultAllocationDecider {
108109
TestAllocationDecider(Settings settings, ClusterSettings clusterSettings, AtomicBoolean settingApplied) {
109110
if (TEST_SETTING.get(settings)) {
110111
settingApplied.set(true);

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

Lines changed: 89 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -14,102 +14,94 @@
1414
import org.elasticsearch.cluster.routing.RoutingNode;
1515
import org.elasticsearch.cluster.routing.ShardRouting;
1616
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
17-
import org.elasticsearch.cluster.routing.allocation.decider.Decision.Type;
1817

1918
import java.util.Optional;
2019
import java.util.Set;
2120

2221
/**
23-
* {@link AllocationDecider} is an abstract base class that allows to make
24-
* dynamic cluster- or index-wide shard allocation decisions on a per-node
25-
* basis.
22+
* A collection of Decider interfaces.
2623
*/
27-
public abstract class AllocationDecider {
28-
/**
29-
* Returns a {@link Decision} whether the given shard routing can be
30-
* re-balanced to the given allocation. The default is
31-
* {@link Decision#ALWAYS}.
32-
*/
33-
public Decision canRebalance(ShardRouting shardRouting, RoutingAllocation allocation) {
34-
return Decision.ALWAYS;
35-
}
24+
public interface AllocationDecider {
3625

37-
/**
38-
* Returns a {@link Decision} whether the given shard routing can be
39-
* allocated on the given node. The default is {@link Decision#ALWAYS}.
40-
*/
41-
public Decision canAllocate(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
42-
return Decision.ALWAYS;
43-
}
26+
interface ShardToNode extends AllocationDecider {
27+
/**
28+
* Returns a {@link Decision} whether the given shard routing can be allocated on the given node.
29+
*/
30+
Decision canAllocate(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation);
4431

45-
/**
46-
* Returns a {@link Decision} whether the given shard routing can be remain
47-
* on the given node. The default is {@link Decision#ALWAYS}.
48-
*/
49-
public Decision canRemain(IndexMetadata indexMetadata, ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
50-
return Decision.ALWAYS;
51-
}
32+
/**
33+
* Returns a {@link Decision} whether the given primary shard can be
34+
* forcibly allocated on the given node. This method should only be called
35+
* for unassigned primary shards where the node has a shard copy on disk.
36+
*
37+
* Note: all implementations that override this behavior should take into account
38+
* the results of {@link ShardToNode#canAllocate(ShardRouting, RoutingNode, RoutingAllocation)}
39+
* before making a decision on force allocation, because force allocation should only
40+
* be considered if all deciders return {@link Decision#NO}.
41+
*/
42+
default Decision canForceAllocatePrimary(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
43+
assert shardRouting.primary() : "must not call canForceAllocatePrimary on a non-primary shard " + shardRouting;
44+
assert shardRouting.unassigned() : "must not call canForceAllocatePrimary on an assigned shard " + shardRouting;
45+
Decision decision = canAllocate(shardRouting, node, allocation);
46+
if (decision.type() == Decision.Type.NO) {
47+
// On a NO decision, by default, we allow force allocating the primary.
48+
return allocation.decision(
49+
Decision.YES,
50+
decision.label(),
51+
"primary shard [%s] allowed to force allocate on node [%s]",
52+
shardRouting.shardId(),
53+
node.nodeId()
54+
);
55+
} else {
56+
// On a THROTTLE/YES decision, we use the same decision instead of forcing allocation
57+
return decision;
58+
}
59+
}
5260

53-
/**
54-
* Returns a {@link Decision} whether the given shard routing can be allocated at all at this state of the
55-
* {@link RoutingAllocation}. The default is {@link Decision#ALWAYS}.
56-
*/
57-
public Decision canAllocate(ShardRouting shardRouting, RoutingAllocation allocation) {
58-
return Decision.ALWAYS;
59-
}
61+
/**
62+
* Returns a {@link Decision} whether the given replica shard can be
63+
* allocated to the given node when there is an existing retention lease
64+
* already existing on the node (meaning it has been allocated there previously)
65+
*
66+
* This method does not actually check whether there is a retention lease,
67+
* that is the responsibility of the caller.
68+
*
69+
* It defaults to the same value as {@code canAllocate}.
70+
*/
71+
default Decision canAllocateReplicaWhenThereIsRetentionLease(
72+
ShardRouting shardRouting,
73+
RoutingNode node,
74+
RoutingAllocation allocation
75+
) {
76+
return canAllocate(shardRouting, node, allocation);
77+
}
6078

61-
/**
62-
* Returns a {@link Decision} whether the given shard routing can be allocated at all at this state of the
63-
* {@link RoutingAllocation}. The default is {@link Decision#ALWAYS}.
64-
*/
65-
public Decision canAllocate(IndexMetadata indexMetadata, RoutingNode node, RoutingAllocation allocation) {
66-
return Decision.ALWAYS;
6779
}
6880

6981
/**
70-
* Returns a {@link Decision} whether shards of the given index should be auto-expanded to this node at this state of the
71-
* {@link RoutingAllocation}. The default is {@link Decision#ALWAYS}.
82+
* Returns a {@link Decision} whether any shard of index can be allocated to given node.
7283
*/
73-
public Decision shouldAutoExpandToNode(IndexMetadata indexMetadata, DiscoveryNode node, RoutingAllocation allocation) {
74-
return Decision.ALWAYS;
84+
@FunctionalInterface
85+
interface IndexToNode extends AllocationDecider {
86+
Decision canAllocate(IndexMetadata indexMetadata, RoutingNode node, RoutingAllocation allocation);
7587
}
7688

7789
/**
78-
* Returns a {@link Decision} on whether the cluster is allowed to rebalance shards to improve relative node shard weights and
79-
* performance.
80-
* @return {@link Decision#ALWAYS} is returned by default if not overridden.
90+
* Returns a {@link Decision} whether the given shard routing can be allocated at all at this state of the {@link RoutingAllocation}.
8191
*/
82-
public Decision canRebalance(RoutingAllocation allocation) {
83-
return Decision.ALWAYS;
92+
@FunctionalInterface
93+
interface ShardToCluster extends AllocationDecider {
94+
Decision canAllocate(ShardRouting shardRouting, RoutingAllocation allocation);
8495
}
8596

8697
/**
87-
* Returns a {@link Decision} whether the given primary shard can be
88-
* forcibly allocated on the given node. This method should only be called
89-
* for unassigned primary shards where the node has a shard copy on disk.
98+
* Returns a {@code empty()} if shard could be initially allocated anywhere or {@code Optional.of(Set.of(nodeIds))} if shard could be
99+
* initially allocated only on subset of a nodes.
90100
*
91-
* Note: all implementations that override this behavior should take into account
92-
* the results of {@link #canAllocate(ShardRouting, RoutingNode, RoutingAllocation)}
93-
* before making a decision on force allocation, because force allocation should only
94-
* be considered if all deciders return {@link Decision#NO}.
101+
* This might be required for splitting or shrinking index as resulting shards have to be on the same node as a source shard.
95102
*/
96-
public Decision canForceAllocatePrimary(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
97-
assert shardRouting.primary() : "must not call canForceAllocatePrimary on a non-primary shard " + shardRouting;
98-
assert shardRouting.unassigned() : "must not call canForceAllocatePrimary on an assigned shard " + shardRouting;
99-
Decision decision = canAllocate(shardRouting, node, allocation);
100-
if (decision.type() == Type.NO) {
101-
// On a NO decision, by default, we allow force allocating the primary.
102-
return allocation.decision(
103-
Decision.YES,
104-
decision.label(),
105-
"primary shard [%s] allowed to force allocate on node [%s]",
106-
shardRouting.shardId(),
107-
node.nodeId()
108-
);
109-
} else {
110-
// On a THROTTLE/YES decision, we use the same decision instead of forcing allocation
111-
return decision;
112-
}
103+
interface ForcedInitialShardAllocation extends AllocationDecider {
104+
Optional<Set<String>> getForcedInitialShardAllocationToNodes(ShardRouting shardRouting, RoutingAllocation allocation);
113105
}
114106

115107
/**
@@ -126,31 +118,37 @@ public Decision canForceAllocatePrimary(ShardRouting shardRouting, RoutingNode n
126118
* - that a replacement is ongoing
127119
* - the shard routing's current node is the source of the replacement
128120
*/
129-
public Decision canForceAllocateDuringReplace(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
130-
return Decision.YES;
121+
interface ForceDuringReplace extends AllocationDecider {
122+
Decision canForceAllocateDuringReplace(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation);
131123
}
132124

133125
/**
134-
* Returns a {@link Decision} whether the given replica shard can be
135-
* allocated to the given node when there is an existing retention lease
136-
* already existing on the node (meaning it has been allocated there previously)
137-
*
138-
* This method does not actually check whether there is a retention lease,
139-
* that is the responsibility of the caller.
140-
*
141-
* It defaults to the same value as {@code canAllocate}.
126+
* Returns a {@link Decision} on whether the cluster is allowed to rebalance shards to improve relative node shard weights and
127+
* performance.
142128
*/
143-
public Decision canAllocateReplicaWhenThereIsRetentionLease(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) {
144-
return canAllocate(shardRouting, node, allocation);
129+
interface ClusterRebalance extends AllocationDecider {
130+
Decision canRebalance(RoutingAllocation allocation);
145131
}
146132

147133
/**
148-
* Returns a {@code empty()} if shard could be initially allocated anywhere or {@code Optional.of(Set.of(nodeIds))} if shard could be
149-
* initially allocated only on subset of a nodes.
150-
*
151-
* This might be required for splitting or shrinking index as resulting shards have to be on the same node as a source shard.
134+
* Returns a {@link Decision} whether shards of the given index should be auto-expanded to this node at this state of the
135+
* {@link RoutingAllocation}.
136+
*/
137+
interface AutoExpandToNode extends AllocationDecider {
138+
Decision shouldAutoExpandToNode(IndexMetadata indexMetadata, DiscoveryNode node, RoutingAllocation allocation);
139+
}
140+
141+
/**
142+
* Returns a {@link Decision} whether the given shard routing can be remain on the given node.
143+
*/
144+
interface ShardRemain extends AllocationDecider {
145+
Decision canRemain(IndexMetadata indexMetadata, ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation);
146+
}
147+
148+
/**
149+
* Returns a {@link Decision} whether the given shard routing can be re-balanced to the given allocation.
152150
*/
153-
public Optional<Set<String>> getForcedInitialShardAllocationToNodes(ShardRouting shardRouting, RoutingAllocation allocation) {
154-
return Optional.empty();
151+
interface ShardRebalance extends AllocationDecider {
152+
Decision canRebalance(ShardRouting shardRouting, RoutingAllocation allocation);
155153
}
156154
}

0 commit comments

Comments
 (0)