1414import org .elasticsearch .cluster .routing .RoutingNode ;
1515import org .elasticsearch .cluster .routing .ShardRouting ;
1616import org .elasticsearch .cluster .routing .allocation .RoutingAllocation ;
17- import org .elasticsearch .cluster .routing .allocation .decider .Decision .Type ;
1817
1918import java .util .Optional ;
2019import 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