4444import org .opensearch .common .settings .Setting ;
4545import org .opensearch .common .settings .Setting .Property ;
4646import org .opensearch .common .settings .Settings ;
47+ import org .opensearch .common .util .FeatureFlags ;
4748import org .opensearch .node .remotestore .RemoteStoreNodeService ;
4849
4950import java .util .Map ;
@@ -88,6 +89,8 @@ public class FilterAllocationDecider extends AllocationDecider {
8889 private static final String CLUSTER_ROUTING_REQUIRE_GROUP_PREFIX = "cluster.routing.allocation.require" ;
8990 private static final String CLUSTER_ROUTING_INCLUDE_GROUP_PREFIX = "cluster.routing.allocation.include" ;
9091 private static final String CLUSTER_ROUTING_EXCLUDE_GROUP_PREFIX = "cluster.routing.allocation.exclude" ;
92+ private static final String SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX = "cluster.routing.allocation.search.replica.dedicated.include" ;
93+
9194 public static final Setting .AffixSetting <String > CLUSTER_ROUTING_REQUIRE_GROUP_SETTING = Setting .prefixKeySetting (
9295 CLUSTER_ROUTING_REQUIRE_GROUP_PREFIX + "." ,
9396 key -> Setting .simpleString (key , value -> IP_VALIDATOR .accept (key , value ), Property .Dynamic , Property .NodeScope )
@@ -100,7 +103,12 @@ public class FilterAllocationDecider extends AllocationDecider {
100103 CLUSTER_ROUTING_EXCLUDE_GROUP_PREFIX + "." ,
101104 key -> Setting .simpleString (key , value -> IP_VALIDATOR .accept (key , value ), Property .Dynamic , Property .NodeScope )
102105 );
106+ public static final Setting .AffixSetting <String > SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_SETTING = Setting .prefixKeySetting (
107+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX + "." ,
108+ key -> Setting .simpleString (key , value -> IP_VALIDATOR .accept (key , value ), Property .Dynamic , Property .NodeScope )
109+ );
103110
111+ private volatile DiscoveryNodeFilters searchReplicaIncludeFilters ;
104112 private volatile DiscoveryNodeFilters clusterRequireFilters ;
105113 private volatile DiscoveryNodeFilters clusterIncludeFilters ;
106114 private volatile DiscoveryNodeFilters clusterExcludeFilters ;
@@ -113,7 +121,6 @@ public FilterAllocationDecider(Settings settings, ClusterSettings clusterSetting
113121 setClusterIncludeFilters (CLUSTER_ROUTING_INCLUDE_GROUP_SETTING .getAsMap (settings ));
114122 this .migrationDirection = RemoteStoreNodeService .MIGRATION_DIRECTION_SETTING .get (settings );
115123 this .compatibilityMode = RemoteStoreNodeService .REMOTE_STORE_COMPATIBILITY_MODE_SETTING .get (settings );
116-
117124 clusterSettings .addAffixMapUpdateConsumer (CLUSTER_ROUTING_REQUIRE_GROUP_SETTING , this ::setClusterRequireFilters , (a , b ) -> {});
118125 clusterSettings .addAffixMapUpdateConsumer (CLUSTER_ROUTING_EXCLUDE_GROUP_SETTING , this ::setClusterExcludeFilters , (a , b ) -> {});
119126 clusterSettings .addAffixMapUpdateConsumer (CLUSTER_ROUTING_INCLUDE_GROUP_SETTING , this ::setClusterIncludeFilters , (a , b ) -> {});
@@ -122,6 +129,15 @@ public FilterAllocationDecider(Settings settings, ClusterSettings clusterSetting
122129 RemoteStoreNodeService .REMOTE_STORE_COMPATIBILITY_MODE_SETTING ,
123130 this ::setCompatibilityMode
124131 );
132+
133+ if (FeatureFlags .isEnabled (FeatureFlags .READER_WRITER_SPLIT_EXPERIMENTAL )) {
134+ setSearchReplicaIncludeFilters (SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_SETTING .getAsMap (settings ));
135+ clusterSettings .addAffixMapUpdateConsumer (
136+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_SETTING ,
137+ this ::setSearchReplicaIncludeFilters ,
138+ (a , b ) -> {}
139+ );
140+ }
125141 }
126142
127143 private void setMigrationDirection (RemoteStoreNodeService .Direction migrationDirection ) {
@@ -203,6 +219,9 @@ private Decision shouldFilter(ShardRouting shardRouting, DiscoveryNode node, Rou
203219 decision = shouldIndexFilter (allocation .metadata ().getIndexSafe (shardRouting .index ()), node , allocation );
204220 if (decision != null ) return decision ;
205221
222+ decision = shouldSearchReplicaShardTypeFilter (shardRouting , node , allocation );
223+ if (decision != null ) return decision ;
224+
206225 return allocation .decision (Decision .YES , NAME , "node passes include/exclude/require filters" );
207226 }
208227
@@ -294,6 +313,32 @@ private Decision shouldClusterFilter(DiscoveryNode node, RoutingAllocation alloc
294313 return null ;
295314 }
296315
316+ private Decision shouldSearchReplicaShardTypeFilter (ShardRouting routing , DiscoveryNode node , RoutingAllocation allocation ) {
317+ if (searchReplicaIncludeFilters != null ) {
318+ final boolean match = searchReplicaIncludeFilters .match (node );
319+ if (match == false && routing .isSearchOnly ()) {
320+ return allocation .decision (
321+ Decision .NO ,
322+ NAME ,
323+ "node does not match shard setting [%s] filters [%s]" ,
324+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX ,
325+ searchReplicaIncludeFilters
326+ );
327+ }
328+ // filter will only apply to search replicas
329+ if (routing .isSearchOnly () == false && match ) {
330+ return allocation .decision (
331+ Decision .NO ,
332+ NAME ,
333+ "only search replicas can be allocated to node with setting [%s] filters [%s]" ,
334+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX ,
335+ searchReplicaIncludeFilters
336+ );
337+ }
338+ }
339+ return null ;
340+ }
341+
297342 private void setClusterRequireFilters (Map <String , String > filters ) {
298343 clusterRequireFilters = DiscoveryNodeFilters .trimTier (
299344 DiscoveryNodeFilters .buildOrUpdateFromKeyValue (clusterRequireFilters , AND , filters )
@@ -311,4 +356,10 @@ private void setClusterExcludeFilters(Map<String, String> filters) {
311356 DiscoveryNodeFilters .buildOrUpdateFromKeyValue (clusterExcludeFilters , OR , filters )
312357 );
313358 }
359+
360+ private void setSearchReplicaIncludeFilters (Map <String , String > filters ) {
361+ searchReplicaIncludeFilters = DiscoveryNodeFilters .trimTier (
362+ DiscoveryNodeFilters .buildOrUpdateFromKeyValue (searchReplicaIncludeFilters , OR , filters )
363+ );
364+ }
314365}
0 commit comments