5656import org .elasticsearch .common .inject .AbstractModule ;
5757import org .elasticsearch .common .logging .ESLogger ;
5858import org .elasticsearch .common .logging .Loggers ;
59+ import org .elasticsearch .common .settings .ClusterSettings ;
5960import org .elasticsearch .common .settings .Setting ;
6061import org .elasticsearch .common .settings .Setting .Property ;
6162import org .elasticsearch .common .settings .Settings ;
6263import org .elasticsearch .common .util .ExtensionPoint ;
6364import org .elasticsearch .gateway .GatewayAllocator ;
65+ import org .elasticsearch .plugins .ClusterPlugin ;
6466import org .elasticsearch .tasks .TaskResultsService ;
6567
66- import java .util .Arrays ;
67- import java .util .Collections ;
68+ import java .util .Collection ;
69+ import java .util .HashMap ;
6870import java .util .List ;
71+ import java .util .Map ;
6972import java .util .function .Function ;
7073
7174/**
@@ -77,48 +80,27 @@ public class ClusterModule extends AbstractModule {
7780 public static final String BALANCED_ALLOCATOR = "balanced" ; // default
7881 public static final Setting <String > SHARDS_ALLOCATOR_TYPE_SETTING =
7982 new Setting <>("cluster.routing.allocation.type" , BALANCED_ALLOCATOR , Function .identity (), Property .NodeScope );
80- public static final List <Class <? extends AllocationDecider >> DEFAULT_ALLOCATION_DECIDERS =
81- Collections .unmodifiableList (Arrays .asList (
82- MaxRetryAllocationDecider .class ,
83- SameShardAllocationDecider .class ,
84- FilterAllocationDecider .class ,
85- ReplicaAfterPrimaryActiveAllocationDecider .class ,
86- ThrottlingAllocationDecider .class ,
87- RebalanceOnlyWhenActiveAllocationDecider .class ,
88- ClusterRebalanceAllocationDecider .class ,
89- ConcurrentRebalanceAllocationDecider .class ,
90- EnableAllocationDecider .class ,
91- AwarenessAllocationDecider .class ,
92- ShardsLimitAllocationDecider .class ,
93- NodeVersionAllocationDecider .class ,
94- DiskThresholdDecider .class ,
95- SnapshotInProgressAllocationDecider .class ));
9683
9784 private final Settings settings ;
9885 private final ExtensionPoint .SelectedType <ShardsAllocator > shardsAllocators = new ExtensionPoint .SelectedType <>("shards_allocator" , ShardsAllocator .class );
99- private final ExtensionPoint .ClassSet <AllocationDecider > allocationDeciders = new ExtensionPoint .ClassSet <>("allocation_decider" , AllocationDecider .class , AllocationDeciders .class );
10086 private final ExtensionPoint .ClassSet <IndexTemplateFilter > indexTemplateFilters = new ExtensionPoint .ClassSet <>("index_template_filter" , IndexTemplateFilter .class );
10187 private final ClusterService clusterService ;
10288 private final IndexNameExpressionResolver indexNameExpressionResolver ;
89+ // pkg private for tests
90+ final Collection <AllocationDecider > allocationDeciders ;
10391
10492 // pkg private so tests can mock
10593 Class <? extends ClusterInfoService > clusterInfoServiceImpl = InternalClusterInfoService .class ;
10694
107- public ClusterModule (Settings settings , ClusterService clusterService ) {
95+ public ClusterModule (Settings settings , ClusterService clusterService , List < ClusterPlugin > clusterPlugins ) {
10896 this .settings = settings ;
109- for (Class <? extends AllocationDecider > decider : ClusterModule .DEFAULT_ALLOCATION_DECIDERS ) {
110- registerAllocationDecider (decider );
111- }
97+ this .allocationDeciders = createAllocationDeciders (settings , clusterService .getClusterSettings (), clusterPlugins );
11298 registerShardsAllocator (ClusterModule .BALANCED_ALLOCATOR , BalancedShardsAllocator .class );
11399 registerShardsAllocator (ClusterModule .EVEN_SHARD_COUNT_ALLOCATOR , BalancedShardsAllocator .class );
114100 this .clusterService = clusterService ;
115101 indexNameExpressionResolver = new IndexNameExpressionResolver (settings );
116102 }
117103
118- public void registerAllocationDecider (Class <? extends AllocationDecider > allocationDecider ) {
119- allocationDeciders .registerExtension (allocationDecider );
120- }
121-
122104 public void registerShardsAllocator (String name , Class <? extends ShardsAllocator > clazz ) {
123105 shardsAllocators .registerExtension (name , clazz );
124106 }
@@ -131,6 +113,41 @@ public IndexNameExpressionResolver getIndexNameExpressionResolver() {
131113 return indexNameExpressionResolver ;
132114 }
133115
116+ // TODO: this is public so allocation benchmark can access the default deciders...can we do that in another way?
117+ /** Return a new {@link AllocationDecider} instance with builtin deciders as well as those from plugins. */
118+ public static Collection <AllocationDecider > createAllocationDeciders (Settings settings , ClusterSettings clusterSettings ,
119+ List <ClusterPlugin > clusterPlugins ) {
120+ // collect deciders by class so that we can detect duplicates
121+ Map <Class , AllocationDecider > deciders = new HashMap <>();
122+ addAllocationDecider (deciders , new MaxRetryAllocationDecider (settings ));
123+ addAllocationDecider (deciders , new SameShardAllocationDecider (settings ));
124+ addAllocationDecider (deciders , new FilterAllocationDecider (settings , clusterSettings ));
125+ addAllocationDecider (deciders , new ReplicaAfterPrimaryActiveAllocationDecider (settings ));
126+ addAllocationDecider (deciders , new ThrottlingAllocationDecider (settings , clusterSettings ));
127+ addAllocationDecider (deciders , new RebalanceOnlyWhenActiveAllocationDecider (settings ));
128+ addAllocationDecider (deciders , new ClusterRebalanceAllocationDecider (settings , clusterSettings ));
129+ addAllocationDecider (deciders , new ConcurrentRebalanceAllocationDecider (settings , clusterSettings ));
130+ addAllocationDecider (deciders , new EnableAllocationDecider (settings , clusterSettings ));
131+ addAllocationDecider (deciders , new AwarenessAllocationDecider (settings , clusterSettings ));
132+ addAllocationDecider (deciders , new ShardsLimitAllocationDecider (settings , clusterSettings ));
133+ addAllocationDecider (deciders , new NodeVersionAllocationDecider (settings ));
134+ addAllocationDecider (deciders , new DiskThresholdDecider (settings , clusterSettings ));
135+ addAllocationDecider (deciders , new SnapshotInProgressAllocationDecider (settings , clusterSettings ));
136+
137+ clusterPlugins .stream ()
138+ .flatMap (p -> p .createAllocationDeciders (settings , clusterSettings ).stream ())
139+ .forEach (d -> addAllocationDecider (deciders , d ));
140+
141+ return deciders .values ();
142+ }
143+
144+ /** Add the given allocation decider to the given deciders collection, erroring if the class name is already used. */
145+ private static void addAllocationDecider (Map <Class , AllocationDecider > deciders , AllocationDecider decider ) {
146+ if (deciders .put (decider .getClass (), decider ) != null ) {
147+ throw new IllegalArgumentException ("Cannot specify allocation decider [" + decider .getClass ().getName () + "] twice" );
148+ }
149+ }
150+
134151 @ Override
135152 protected void configure () {
136153 // bind ShardsAllocator
@@ -139,7 +156,6 @@ protected void configure() {
139156 final ESLogger logger = Loggers .getLogger (getClass (), settings );
140157 logger .warn ("{} allocator has been removed in 2.0 using {} instead" , ClusterModule .EVEN_SHARD_COUNT_ALLOCATOR , ClusterModule .BALANCED_ALLOCATOR );
141158 }
142- allocationDeciders .bind (binder ());
143159 indexTemplateFilters .bind (binder ());
144160
145161 bind (ClusterInfoService .class ).to (clusterInfoServiceImpl ).asEagerSingleton ();
@@ -161,5 +177,6 @@ protected void configure() {
161177 bind (NodeMappingRefreshAction .class ).asEagerSingleton ();
162178 bind (MappingUpdatedAction .class ).asEagerSingleton ();
163179 bind (TaskResultsService .class ).asEagerSingleton ();
180+ bind (AllocationDeciders .class ).toInstance (new AllocationDeciders (settings , allocationDeciders ));
164181 }
165182}
0 commit comments