From 162cbebd066dd0205b13d1b2041b23747b58bde1 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 17 Aug 2022 16:31:48 +0530 Subject: [PATCH 01/55] Weighted round-robin scheduling policy for shard coordination traffic routing Signed-off-by: Anshu Agarwal --- .../metadata/WeightedRoundRobinMetadata.java | 157 ++++++++++++++ .../routing/IndexShardRoutingTable.java | 60 +++++- .../cluster/routing/OperationRouting.java | 53 ++++- .../opensearch/cluster/routing/WRRWeight.java | 77 +++++++ .../cluster/routing/WeightedRoundRobin.java | 134 ++++++++++++ .../common/settings/ClusterSettings.java | 1 + .../routing/OperationRoutingTests.java | 198 ++++++++++++++++++ 7 files changed, 671 insertions(+), 9 deletions(-) create mode 100644 server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java create mode 100644 server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java create mode 100644 server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java new file mode 100644 index 0000000000000..f863c47e66758 --- /dev/null +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java @@ -0,0 +1,157 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.metadata; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.OpenSearchParseException; +import org.opensearch.Version; +import org.opensearch.cluster.AbstractNamedDiffable; +import org.opensearch.cluster.NamedDiff; +import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.xcontent.ToXContent; +import org.opensearch.common.xcontent.XContentBuilder; +import org.opensearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +/** + * Contains metadata for weighted round-robin shard routing weights + * + * @opensearch.internal + */ +public class WeightedRoundRobinMetadata extends AbstractNamedDiffable implements Metadata.Custom { + private static final Logger logger = LogManager.getLogger(WeightedRoundRobinMetadata.class); + public static final String TYPE = "wrr_shard_routing"; + private WRRWeight wrrWeight; + + public WRRWeight getWrrWeight() { + return wrrWeight; + } + + public WeightedRoundRobinMetadata setWrrWeight(WRRWeight wrrWeight) { + this.wrrWeight = wrrWeight; + return this; + } + + public WeightedRoundRobinMetadata(StreamInput in) throws IOException { + this.wrrWeight = new WRRWeight(in); + } + + public WeightedRoundRobinMetadata(WRRWeight wrrWeight) { + this.wrrWeight = wrrWeight; + } + + @Override + public EnumSet context() { + return Metadata.API_AND_GATEWAY; + } + + @Override + public String getWriteableName() { + return TYPE; + } + + @Override + public Version getMinimalSupportedVersion() { + // TODO: Check if this needs to be changed + return Version.CURRENT.minimumCompatibilityVersion(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + wrrWeight.writeTo(out); + } + + public static NamedDiff readDiffFrom(StreamInput in) throws IOException { + return readDiffFrom(Metadata.Custom.class, TYPE, in); + } + + public static WeightedRoundRobinMetadata fromXContent(XContentParser parser) throws IOException { + String attrKey = null; + Object attrValue; + String attributeName = null; + Map weights = new HashMap<>(); + WRRWeight wrrWeight = null; + XContentParser.Token token; + // move to the first alias + parser.nextToken(); + String awarenessField = null; + + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + awarenessField = parser.currentName(); + if (parser.nextToken() != XContentParser.Token.START_OBJECT) { + throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", awarenessField); + } + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + attributeName = parser.currentName(); + if (parser.nextToken() != XContentParser.Token.START_OBJECT) { + throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", attributeName); + } + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + attrKey = parser.currentName(); + } else if (token == XContentParser.Token.VALUE_STRING) { + attrValue = parser.text(); + weights.put(attrKey, attrValue); + } else { + throw new OpenSearchParseException("failed to parse wrr metadata attribute [{}], unknown type", attributeName); + } + } + } + } else { + throw new OpenSearchParseException("failed to parse wrr metadata attribute [{}]", attributeName); + } + } + wrrWeight = new WRRWeight(attributeName, weights); + return new WeightedRoundRobinMetadata(wrrWeight); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WeightedRoundRobinMetadata that = (WeightedRoundRobinMetadata) o; + return wrrWeight.equals(that.wrrWeight); + } + + @Override + public int hashCode() { + return wrrWeight.hashCode(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { + toXContent(wrrWeight, builder); + return builder; + } + + public static void toXContent(WRRWeight wrrWeight, XContentBuilder builder) throws IOException { + builder.startObject("awareness"); + builder.startObject(wrrWeight.attributeName()); + for (Map.Entry entry : wrrWeight.weights().entrySet()) { + builder.field(entry.getKey(), entry.getValue()); + } + builder.endObject(); + builder.endObject(); + } + + @Override + public String toString() { + return Strings.toString(this); + } + +} diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index d4597f47d9a6c..2006f1bd3ef08 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -43,7 +43,6 @@ import org.opensearch.index.Index; import org.opensearch.index.shard.ShardId; import org.opensearch.node.ResponseCollectorService; - import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -292,6 +291,65 @@ public ShardIterator activeInitializingShardsRankedIt( return new PlainShardIterator(shardId, ordered); } + /** + * * + * @param wrrWeight Weighted round-robin weight entity + * @param nodes discovered nodes in the cluster + * @return an interator over active and initializing shards, ordered by weighted round-robin + * scheduling policy. Making sure that initializing shards are the last to iterate through. + */ + public ShardIterator activeInitializingShardsWRR(WRRWeight wrrWeight, DiscoveryNodes nodes) { + final int seed = shuffler.nextSeed(); + ArrayList ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); + ArrayList orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); + ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); + if (!allInitializingShards.isEmpty()) { + ArrayList orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); + ordered.addAll(shuffler.shuffle(orderedInitializingShards, seed)); + } + return new PlainShardIterator(shardId, ordered); + } + + /** + * + * @param shards shards to be ordered using weighted round-robin scheduling policy + * @param wrrWeight weights to be considered for routing + * @param nodes discovered nodes in the cluster + * @return list of shards ordered using weighted round-robin scheduling. + */ + private ArrayList getShardsWRR(List shards, WRRWeight wrrWeight, DiscoveryNodes nodes) { + List> weightedShards = calculateShardWeight(shards, wrrWeight, nodes); + WeightedRoundRobin wrr = new WeightedRoundRobin<>(weightedShards); + List> wrrOrderedActiveShards = wrr.orderEntities(); + ArrayList orderedActiveShards = new ArrayList<>(activeShards.size()); + for (WeightedRoundRobin.Entity shardRouting : wrrOrderedActiveShards) { + orderedActiveShards.add(shardRouting.getTarget()); + } + return orderedActiveShards; + } + + /** + * * + * @param shards associate weights to shards + * @param wrrWeight weights to be used for association + * @param nodes + * @return list of entity containing shard routing and associated weight. + */ + private List> calculateShardWeight( + List shards, + WRRWeight wrrWeight, + DiscoveryNodes nodes + ) { + List> weightedShards = new ArrayList<>(); + for (ShardRouting shard : shards) { + shard.currentNodeId(); + DiscoveryNode node = nodes.get(shard.currentNodeId()); + String attVal = node.getAttributes().get(wrrWeight.attributeName()); + weightedShards.add(new WeightedRoundRobin.Entity<>(Double.parseDouble(wrrWeight.weights().get(attVal).toString()), shard)); + } + return weightedShards; + } + private static Set getAllNodeIds(final List shards) { final Set nodeIds = new HashSet<>(); for (ShardRouting shard : shards) { diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 30f6408c19783..19209330eb46b 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -34,6 +34,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; import org.opensearch.cluster.node.DiscoveryNodes; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; import org.opensearch.common.Nullable; @@ -68,6 +69,12 @@ public class OperationRouting { Setting.Property.NodeScope ); + public static final Setting USE_WEIGHTED_ROUND_ROBIN = Setting.boolSetting( + "cluster.routing.use_weighted_round_robin", + true, + Setting.Property.Dynamic, + Setting.Property.NodeScope + ); public static final String IGNORE_AWARENESS_ATTRIBUTES = "cluster.search.ignore_awareness_attributes"; public static final Setting IGNORE_AWARENESS_ATTRIBUTES_SETTING = Setting.boolSetting( IGNORE_AWARENESS_ATTRIBUTES, @@ -79,6 +86,8 @@ public class OperationRouting { private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; + private volatile boolean useWeightedRoundRobin; + public OperationRouting(Settings settings, ClusterSettings clusterSettings) { // whether to ignore awareness attributes when routing requests this.ignoreAwarenessAttr = clusterSettings.get(IGNORE_AWARENESS_ATTRIBUTES_SETTING); @@ -88,8 +97,11 @@ public OperationRouting(Settings settings, ClusterSettings clusterSettings) { this::setAwarenessAttributes ); this.useAdaptiveReplicaSelection = USE_ADAPTIVE_REPLICA_SELECTION_SETTING.get(settings); + this.useWeightedRoundRobin = USE_WEIGHTED_ROUND_ROBIN.get(settings); clusterSettings.addSettingsUpdateConsumer(USE_ADAPTIVE_REPLICA_SELECTION_SETTING, this::setUseAdaptiveReplicaSelection); clusterSettings.addSettingsUpdateConsumer(IGNORE_AWARENESS_ATTRIBUTES_SETTING, this::setIgnoreAwarenessAttributes); + clusterSettings.addSettingsUpdateConsumer(USE_WEIGHTED_ROUND_ROBIN, this::setUseWeightedRoundRobin); + } void setUseAdaptiveReplicaSelection(boolean useAdaptiveReplicaSelection) { @@ -100,6 +112,14 @@ void setIgnoreAwarenessAttributes(boolean ignoreAwarenessAttributes) { this.ignoreAwarenessAttr = ignoreAwarenessAttributes; } + public boolean isUseWeightedRoundRobin() { + return useWeightedRoundRobin; + } + + public void setUseWeightedRoundRobin(boolean useWeightedRoundRobin) { + this.useWeightedRoundRobin = useWeightedRoundRobin; + } + public boolean isIgnoreAwarenessAttr() { return ignoreAwarenessAttr; } @@ -169,14 +189,22 @@ public GroupShardsIterator searchShards( final Set shards = computeTargetedShards(clusterState, concreteIndices, routing); final Set set = new HashSet<>(shards.size()); for (IndexShardRoutingTable shard : shards) { - ShardIterator iterator = preferenceActiveShardIterator( - shard, - clusterState.nodes().getLocalNodeId(), - clusterState.nodes(), - preference, - collectorService, - nodeCounts - ); + ShardIterator iterator = null; + // TODO: Do we need similar changes in getShards call?? + if (isWeightedRoundRobinEnabled(clusterState)) { + WeightedRoundRobinMetadata weightedRoundRobinMetadata = clusterState.metadata().custom(WeightedRoundRobinMetadata.TYPE); + iterator = shard.activeInitializingShardsWRR(weightedRoundRobinMetadata.getWrrWeight(), clusterState.nodes()); + } else { + iterator = preferenceActiveShardIterator( + shard, + clusterState.nodes().getLocalNodeId(), + clusterState.nodes(), + preference, + collectorService, + nodeCounts + ); + } + if (iterator != null) { set.add(iterator); } @@ -184,6 +212,14 @@ public GroupShardsIterator searchShards( return GroupShardsIterator.sortAndCreate(new ArrayList<>(set)); } + private boolean isWeightedRoundRobinEnabled(ClusterState clusterState) { + WeightedRoundRobinMetadata weightedRoundRobinMetadata = clusterState.metadata().custom(WeightedRoundRobinMetadata.TYPE); + if (useWeightedRoundRobin && weightedRoundRobinMetadata != null) { + return true; + } + return false; + } + public static ShardIterator getShards(ClusterState clusterState, ShardId shardId) { final IndexShardRoutingTable shard = clusterState.routingTable().shardRoutingTable(shardId); return shard.activeInitializingShardsRandomIt(); @@ -227,6 +263,7 @@ private ShardIterator preferenceActiveShardIterator( @Nullable ResponseCollectorService collectorService, @Nullable Map nodeCounts ) { + if (preference == null || preference.isEmpty()) { return shardRoutings(indexShard, nodes, collectorService, nodeCounts); } diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java b/server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java new file mode 100644 index 0000000000000..f27f7c88c7f55 --- /dev/null +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java @@ -0,0 +1,77 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.routing; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +import java.io.IOException; +import java.util.Map; +import java.util.Objects; + +/** + * Entity for Weighted Round Robin weights + * + * @opensearch.internal + */ +public class WRRWeight implements Writeable { + private String attributeName; + private Map weights; + + public WRRWeight(String attributeName, Map weights) { + this.attributeName = attributeName; + this.weights = weights; + } + + public WRRWeight(WRRWeight wrrWeight) { + this.attributeName = wrrWeight.attributeName(); + this.weights = wrrWeight.weights; + } + + public WRRWeight(StreamInput in) throws IOException { + attributeName = in.readString(); + weights = in.readMap(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(attributeName); + out.writeMap(weights); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + WRRWeight that = (WRRWeight) o; + + if (!attributeName.equals(that.attributeName)) return false; + return weights.equals(that.weights); + } + + @Override + public int hashCode() { + return Objects.hash(attributeName, weights); + } + + @Override + public String toString() { + return "WRRWeightsDefinition{" + attributeName + "}{" + weights().toString() + "}"; + } + + public Map weights() { + return this.weights; + } + + public String attributeName() { + return this.attributeName; + } +} diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java new file mode 100644 index 0000000000000..0e00b1aa5cedd --- /dev/null +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -0,0 +1,134 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.routing; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class WeightedRoundRobin implements Iterator, Iterable { + + private List> entities; + private int turn; + private int lastSelectedEntity; + private double currentWeight = 0; + + public WeightedRoundRobin(List> entities) { + this.entities = entities; + this.turn = 0; + this.lastSelectedEntity = -1; + } + + /* (non-Javadoc) + * @see java.util.Iterator#hasNext() + */ + @Override + public boolean hasNext() { + return entities.size() > 0; + } + + /* (non-Javadoc) + * @see java.util.Iterator#next() + */ + @Override + public T next() { + Entity entity = entities.get(turn++); + return entity.getTarget(); + } + + /* (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ + @Override + public Iterator iterator() { + return this; + } + + /** + * * + * @return list of entities that is ordered using weighted round-robin scheduling + * http://kb.linuxvirtualserver.org/wiki/Weighted_Round-Robin_Scheduling + */ + public List> orderEntities() { + int size = entities.size(); + List> orderedWeight = new ArrayList<>(); + if (size <= 0) { + return null; + } + if (size == 1) { + return entities; + } + // Find maximum weight and greatest common divisor of weight across all entities + double maxWeight = 0; + double sumWeight = 0; + Double gcd = null; + for (WeightedRoundRobin.Entity entity : entities) { + maxWeight = Math.max(maxWeight, entity.getWeight()); + gcd = (gcd == null) ? entity.getWeight() : gcd(gcd, entity.getWeight()); + sumWeight += entity.getWeight(); + } + int count = 0; + while (count < sumWeight) { + lastSelectedEntity = (lastSelectedEntity + 1) % size; + if (lastSelectedEntity == 0) { + currentWeight = currentWeight - gcd; + if (currentWeight <= 0) { + currentWeight = maxWeight; + if (currentWeight == 0) { + return orderedWeight; + } + } + } + if (entities.get(lastSelectedEntity).getWeight() >= currentWeight) { + orderedWeight.add(entities.get(lastSelectedEntity)); + count++; + } + } + return orderedWeight; + } + + /** + * Return greatest common divisor for two integers + * https://en.wikipedia.org/wiki/Greatest_common_divisor#Using_Euclid.27s_algorithm + * + * @param a + * @param b + * @return greatest common divisor + */ + private double gcd(double a, double b) { + return (b == 0) ? a : gcd(b, a % b); + } + + static final class Entity { + private double weight; + private T target; + + public Entity(double weight, T target) { + this.weight = weight; + this.target = target; + } + + public T getTarget() { + return this.target; + } + + public void setTarget(T target) { + this.target = target; + } + + public double getWeight() { + return this.weight; + } + + public void setWeight(double weight) { + this.weight = weight; + } + } + +} diff --git a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java index 971fb518ff1da..bc06987624918 100644 --- a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java @@ -529,6 +529,7 @@ public void apply(Settings value, Settings current, Settings previous) { Node.BREAKER_TYPE_KEY, OperationRouting.USE_ADAPTIVE_REPLICA_SELECTION_SETTING, OperationRouting.IGNORE_AWARENESS_ATTRIBUTES_SETTING, + OperationRouting.USE_WEIGHTED_ROUND_ROBIN, IndexGraveyard.SETTING_MAX_TOMBSTONES, PersistentTasksClusterService.CLUSTER_TASKS_ALLOCATION_RECHECK_INTERVAL_SETTING, EnableAssignmentDecider.CLUSTER_TASKS_ALLOCATION_ENABLE_SETTING, diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 8bf2b1626292a..dae65adb4baa9 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -36,6 +36,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.Metadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.cluster.node.DiscoveryNodeRole; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; @@ -102,6 +103,7 @@ public void testGenerateShardId() { .settings(settings(Version.CURRENT)) .numberOfShards(shardSplits[2]) .numberOfReplicas(1) + .setRoutingNumShards(shardSplits[0]) .build(); shrunkShard = OperationRouting.generateShardId(shrunk, term, null); @@ -759,6 +761,111 @@ public void testAdaptiveReplicaSelectionWithZoneAwarenessIgnored() throws Except terminate(threadPool); } + public void testWRR() throws Exception { + final int numIndices = 2; + final int numShards = 3; + final int numReplicas = 2; + final String[] indexNames = new String[numIndices]; + for (int i = 0; i < numIndices; i++) { + indexNames[i] = "test" + i; + } + DiscoveryNode[] allNodes = setUpNodesWRR(); + ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); + + Map> discoveryNodeMap = new HashMap<>(); + List nodesZoneA = new ArrayList<>(); + nodesZoneA.add(allNodes[0]); + nodesZoneA.add(allNodes[1]); + + List nodesZoneB = new ArrayList<>(); + nodesZoneB.add(allNodes[2]); + nodesZoneB.add(allNodes[3]); + + List nodesZoneC = new ArrayList<>(); + nodesZoneC.add(allNodes[4]); + nodesZoneC.add(allNodes[5]); + discoveryNodeMap.put("a", nodesZoneA); + discoveryNodeMap.put("b", nodesZoneB); + discoveryNodeMap.put("c", nodesZoneC); + + state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); + + Settings setting = Settings.builder() + .put("cluster.routing.allocation.awareness.attributes", "zone") + .put("cluster.routing.use_weighted_round_robin", "true") + .build(); + + TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + + OperationRouting opRouting = new OperationRouting( + setting, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) + ); + + assertTrue(opRouting.ignoreAwarenessAttributes()); + Set selectedNodes = new HashSet<>(); + ResponseCollectorService collector = new ResponseCollectorService(clusterService); + Map outstandingRequests = new HashMap<>(); + + Map weights = Map.of("a", "1", "b", "1", "c", "0"); + WRRWeight wrrWeight = new WRRWeight("zone", weights); + WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + state = ClusterState.builder(state).metadata(metadataBuilder).build(); + + GroupShardsIterator groupIterator = opRouting.searchShards( + state, + indexNames, + null, + null, + collector, + outstandingRequests + ); + + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } + } + for (String nodeID : selectedNodes) { + // No shards are assigned to nodes in zone c since its weight is 0 + assertFalse(nodeID.contains("c")); + } + + selectedNodes = new HashSet<>(); + setting = Settings.builder() + .put("cluster.routing.allocation.awareness.attributes", "zone") + .put("cluster.routing.use_weighted_round_robin", "true") + .build(); + + weights = Map.of("a", "1", "b", "0", "c", "1"); + wrrWeight = new WRRWeight("zone", weights); + wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + metadataBuilder = Metadata.builder(state.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + state = ClusterState.builder(state).metadata(metadataBuilder).build(); + + opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + + groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } + } + for (String nodeID : selectedNodes) { + // No shards are assigned to nodes in zone b since its weight is 0 + assertFalse(nodeID.contains("b")); + } + IOUtils.close(clusterService); + terminate(threadPool); + } + private DiscoveryNode[] setupNodes() { // Sets up two data nodes in zone-a and one data node in zone-b List zones = Arrays.asList("a", "a", "b"); @@ -785,6 +892,32 @@ private DiscoveryNode[] setupNodes() { return allNodes; } + private DiscoveryNode[] setUpNodesWRR() { + List zones = Arrays.asList("a", "a", "b", "b", "c", "c"); + DiscoveryNode[] allNodes = new DiscoveryNode[7]; + int i = 0; + for (String zone : zones) { + DiscoveryNode node = new DiscoveryNode( + "node_" + zone + "_" + i, + buildNewFakeTransportAddress(), + singletonMap("zone", zone), + Collections.singleton(DiscoveryNodeRole.DATA_ROLE), + Version.CURRENT + ); + allNodes[i++] = node; + } + + DiscoveryNode clusterManager = new DiscoveryNode( + "cluster-manager", + buildNewFakeTransportAddress(), + Collections.emptyMap(), + Collections.singleton(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE), + Version.CURRENT + ); + allNodes[i] = clusterManager; + return allNodes; + } + public void testAllocationAwarenessDeprecation() { OperationRouting routing = new OperationRouting( Settings.builder() @@ -841,4 +974,69 @@ private ClusterState updateStatetoTestARS( clusterState.routingTable(routingTableBuilder.build()); return clusterState.build(); } + + private ClusterState updateStatetoTestWRR( + String[] indices, + int numberOfShards, + int numberOfReplicas, + ClusterState state, + Map> discoveryNodeMap + ) { + RoutingTable.Builder routingTableBuilder = RoutingTable.builder(); + Metadata.Builder metadataBuilder = Metadata.builder(); + ClusterState.Builder clusterState = ClusterState.builder(state); + List nodesZoneA = discoveryNodeMap.get("a"); + List nodesZoneB = discoveryNodeMap.get("b"); + List nodesZoneC = discoveryNodeMap.get("c"); + for (String index : indices) { + IndexMetadata indexMetadata = IndexMetadata.builder(index) + .settings( + Settings.builder() + .put(SETTING_VERSION_CREATED, Version.CURRENT) + .put(SETTING_NUMBER_OF_SHARDS, numberOfShards) + .put(SETTING_NUMBER_OF_REPLICAS, numberOfReplicas) + .put(SETTING_CREATION_DATE, System.currentTimeMillis()) + ) + .build(); + metadataBuilder.put(indexMetadata, false).generateClusterUuidIfNeeded(); + IndexRoutingTable.Builder indexRoutingTableBuilder = IndexRoutingTable.builder(indexMetadata.getIndex()); + for (int i = 0; i < numberOfShards; i++) { + final ShardId shardId = new ShardId(index, "_na_", i); + IndexShardRoutingTable.Builder indexShardRoutingBuilder = new IndexShardRoutingTable.Builder(shardId); + // Assign all the primary shards on nodes in zone-a (node_a0 or node_a1) + indexShardRoutingBuilder.addShard( + TestShardRouting.newShardRouting( + index, + i, + nodesZoneA.get(randomInt(nodesZoneA.size() - 1)).getId(), + null, + true, + ShardRoutingState.STARTED + ) + ); + for (int replica = 0; replica < numberOfReplicas; replica++) { + // Assign all the replicas on nodes in zone-b (node_b2) + String nodeId = ""; + if (replica == 0) { + nodeId = nodesZoneB.get(randomInt(nodesZoneB.size() - 1)).getId(); + } else { + nodeId = nodesZoneC.get(randomInt(nodesZoneC.size() - 1)).getId(); + } + indexShardRoutingBuilder.addShard( + TestShardRouting.newShardRouting(index, i, nodeId, null, false, ShardRoutingState.STARTED) + ); + } + indexRoutingTableBuilder.addIndexShard(indexShardRoutingBuilder.build()); + } + routingTableBuilder.add(indexRoutingTableBuilder.build()); + } + // add wrr weights in metadata + Map weights = Map.of("a", "1", "b", "1", "c", "0"); + WRRWeight wrrWeight = new WRRWeight("zone", weights); + WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + clusterState.metadata(metadataBuilder); + clusterState.routingTable(routingTableBuilder.build()); + return clusterState.build(); + } } From 8513c4f45edd922b93deba3d82daccec53817292 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Fri, 26 Aug 2022 10:01:05 +0530 Subject: [PATCH 02/55] Add caching layer for wrr shard routing and moved wrr routing call to shardRoutings Signed-off-by: Anshu Agarwal --- .../metadata/WeightedRoundRobinMetadata.java | 18 +-- .../routing/IndexShardRoutingTable.java | 17 ++- .../cluster/routing/OperationRouting.java | 78 ++++++++----- .../cluster/routing/WRRShardsCache.java | 84 ++++++++++++++ .../{WRRWeight.java => WRRWeights.java} | 10 +- .../cluster/routing/WeightedRoundRobin.java | 2 +- .../cluster/service/ClusterService.java | 1 + .../routing/OperationRoutingTests.java | 106 +++++++++++++++++- 8 files changed, 266 insertions(+), 50 deletions(-) create mode 100644 server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java rename server/src/main/java/org/opensearch/cluster/routing/{WRRWeight.java => WRRWeights.java} (86%) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java index f863c47e66758..ed89f885bdb4a 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java @@ -14,7 +14,7 @@ import org.opensearch.Version; import org.opensearch.cluster.AbstractNamedDiffable; import org.opensearch.cluster.NamedDiff; -import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.cluster.routing.WRRWeights; import org.opensearch.common.Strings; import org.opensearch.common.io.stream.StreamInput; import org.opensearch.common.io.stream.StreamOutput; @@ -35,22 +35,22 @@ public class WeightedRoundRobinMetadata extends AbstractNamedDiffable implements Metadata.Custom { private static final Logger logger = LogManager.getLogger(WeightedRoundRobinMetadata.class); public static final String TYPE = "wrr_shard_routing"; - private WRRWeight wrrWeight; + private WRRWeights wrrWeight; - public WRRWeight getWrrWeight() { + public WRRWeights getWrrWeight() { return wrrWeight; } - public WeightedRoundRobinMetadata setWrrWeight(WRRWeight wrrWeight) { + public WeightedRoundRobinMetadata setWrrWeight(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; return this; } public WeightedRoundRobinMetadata(StreamInput in) throws IOException { - this.wrrWeight = new WRRWeight(in); + this.wrrWeight = new WRRWeights(in); } - public WeightedRoundRobinMetadata(WRRWeight wrrWeight) { + public WeightedRoundRobinMetadata(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; } @@ -84,7 +84,7 @@ public static WeightedRoundRobinMetadata fromXContent(XContentParser parser) thr Object attrValue; String attributeName = null; Map weights = new HashMap<>(); - WRRWeight wrrWeight = null; + WRRWeights wrrWeight = null; XContentParser.Token token; // move to the first alias parser.nextToken(); @@ -116,7 +116,7 @@ public static WeightedRoundRobinMetadata fromXContent(XContentParser parser) thr throw new OpenSearchParseException("failed to parse wrr metadata attribute [{}]", attributeName); } } - wrrWeight = new WRRWeight(attributeName, weights); + wrrWeight = new WRRWeights(attributeName, weights); return new WeightedRoundRobinMetadata(wrrWeight); } @@ -139,7 +139,7 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par return builder; } - public static void toXContent(WRRWeight wrrWeight, XContentBuilder builder) throws IOException { + public static void toXContent(WRRWeights wrrWeight, XContentBuilder builder) throws IOException { builder.startObject("awareness"); builder.startObject(wrrWeight.attributeName()); for (Map.Entry entry : wrrWeight.weights().entrySet()) { diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index 2006f1bd3ef08..56abf80af1cdc 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -298,14 +298,21 @@ public ShardIterator activeInitializingShardsRankedIt( * @return an interator over active and initializing shards, ordered by weighted round-robin * scheduling policy. Making sure that initializing shards are the last to iterate through. */ - public ShardIterator activeInitializingShardsWRR(WRRWeight wrrWeight, DiscoveryNodes nodes) { + public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, DiscoveryNodes nodes, WRRShardsCache cache) { final int seed = shuffler.nextSeed(); ArrayList ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); - ArrayList orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); + ArrayList orderedActiveShards; + if (cache.getCache().get(new WRRShardsCache.Key(shardId)) != null) { + orderedActiveShards = cache.getCache().get(new WRRShardsCache.Key(shardId)); + } else { + orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); + cache.getCache().put(new WRRShardsCache.Key(shardId), orderedActiveShards); + } + ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); if (!allInitializingShards.isEmpty()) { ArrayList orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); - ordered.addAll(shuffler.shuffle(orderedInitializingShards, seed)); + ordered.addAll(orderedInitializingShards); } return new PlainShardIterator(shardId, ordered); } @@ -317,7 +324,7 @@ public ShardIterator activeInitializingShardsWRR(WRRWeight wrrWeight, DiscoveryN * @param nodes discovered nodes in the cluster * @return list of shards ordered using weighted round-robin scheduling. */ - private ArrayList getShardsWRR(List shards, WRRWeight wrrWeight, DiscoveryNodes nodes) { + private ArrayList getShardsWRR(List shards, WRRWeights wrrWeight, DiscoveryNodes nodes) { List> weightedShards = calculateShardWeight(shards, wrrWeight, nodes); WeightedRoundRobin wrr = new WeightedRoundRobin<>(weightedShards); List> wrrOrderedActiveShards = wrr.orderEntities(); @@ -337,7 +344,7 @@ private ArrayList getShardsWRR(List shards, WRRWeigh */ private List> calculateShardWeight( List shards, - WRRWeight wrrWeight, + WRRWeights wrrWeight, DiscoveryNodes nodes ) { List> weightedShards = new ArrayList<>(); diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 19209330eb46b..d33b42bc69620 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -37,6 +37,7 @@ import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; import org.opensearch.cluster.node.DiscoveryNodes; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; +import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Nullable; import org.opensearch.common.Strings; import org.opensearch.common.settings.ClusterSettings; @@ -86,7 +87,32 @@ public class OperationRouting { private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; + // reads value from cluster setting private volatile boolean useWeightedRoundRobin; + /** + * Reads value from cluster setting and cluster state to determine if weighted round-robin + * search routing is enabled + * This is true if useWeightedRoundRobin=true and weights are set in cluster metadata. + */ + private volatile boolean isWeightedRoundRobinEnabled; + + private volatile WRRWeights wrrWeights; + + public WRRShardsCache getWrrShardsCache() { + return wrrShardsCache; + } + + private WRRShardsCache wrrShardsCache; + + public ClusterService getClusterService() { + return clusterService; + } + + public void setClusterService(ClusterService clusterService) { + this.clusterService = clusterService; + } + + private ClusterService clusterService; public OperationRouting(Settings settings, ClusterSettings clusterSettings) { // whether to ignore awareness attributes when routing requests @@ -112,10 +138,6 @@ void setIgnoreAwarenessAttributes(boolean ignoreAwarenessAttributes) { this.ignoreAwarenessAttr = ignoreAwarenessAttributes; } - public boolean isUseWeightedRoundRobin() { - return useWeightedRoundRobin; - } - public void setUseWeightedRoundRobin(boolean useWeightedRoundRobin) { this.useWeightedRoundRobin = useWeightedRoundRobin; } @@ -136,6 +158,10 @@ public boolean ignoreAwarenessAttributes() { return this.awarenessAttributes.isEmpty() || this.ignoreAwarenessAttr; } + public WRRWeights getWrrWeights() { + return wrrWeights; + } + public ShardIterator indexShards(ClusterState clusterState, String index, String id, @Nullable String routing) { return shards(clusterState, index, id, routing).shardsIt(); } @@ -159,6 +185,7 @@ public ShardIterator getShards( public ShardIterator getShards(ClusterState clusterState, String index, int shardId, @Nullable String preference) { final IndexShardRoutingTable indexShard = clusterState.getRoutingTable().shardRoutingTable(index, shardId); + setWeightedRoundRobinAttributes(clusterState, getClusterService()); return preferenceActiveShardIterator( indexShard, clusterState.nodes().getLocalNodeId(), @@ -188,23 +215,16 @@ public GroupShardsIterator searchShards( ) { final Set shards = computeTargetedShards(clusterState, concreteIndices, routing); final Set set = new HashSet<>(shards.size()); + setWeightedRoundRobinAttributes(clusterState, getClusterService()); for (IndexShardRoutingTable shard : shards) { - ShardIterator iterator = null; - // TODO: Do we need similar changes in getShards call?? - if (isWeightedRoundRobinEnabled(clusterState)) { - WeightedRoundRobinMetadata weightedRoundRobinMetadata = clusterState.metadata().custom(WeightedRoundRobinMetadata.TYPE); - iterator = shard.activeInitializingShardsWRR(weightedRoundRobinMetadata.getWrrWeight(), clusterState.nodes()); - } else { - iterator = preferenceActiveShardIterator( - shard, - clusterState.nodes().getLocalNodeId(), - clusterState.nodes(), - preference, - collectorService, - nodeCounts - ); - } - + ShardIterator iterator = preferenceActiveShardIterator( + shard, + clusterState.nodes().getLocalNodeId(), + clusterState.nodes(), + preference, + collectorService, + nodeCounts + ); if (iterator != null) { set.add(iterator); } @@ -212,12 +232,18 @@ public GroupShardsIterator searchShards( return GroupShardsIterator.sortAndCreate(new ArrayList<>(set)); } - private boolean isWeightedRoundRobinEnabled(ClusterState clusterState) { + private void setWeightedRoundRobinAttributes(ClusterState clusterState, ClusterService clusterService) { WeightedRoundRobinMetadata weightedRoundRobinMetadata = clusterState.metadata().custom(WeightedRoundRobinMetadata.TYPE); - if (useWeightedRoundRobin && weightedRoundRobinMetadata != null) { - return true; + this.isWeightedRoundRobinEnabled = useWeightedRoundRobin && weightedRoundRobinMetadata != null ? true : false; + if (this.isWeightedRoundRobinEnabled) { + this.wrrWeights = weightedRoundRobinMetadata.getWrrWeight(); + this.wrrShardsCache = getWrrShardsCache() != null ? getWrrShardsCache() : new WRRShardsCache(clusterService); } - return false; + + } + + private boolean isWeightedRoundRobinEnabled() { + return isWeightedRoundRobinEnabled; } public static ShardIterator getShards(ClusterState clusterState, ShardId shardId) { @@ -337,7 +363,9 @@ private ShardIterator shardRoutings( @Nullable ResponseCollectorService collectorService, @Nullable Map nodeCounts ) { - if (ignoreAwarenessAttributes()) { + if (isWeightedRoundRobinEnabled()) { + return indexShard.activeInitializingShardsWRR(getWrrWeights(), nodes, wrrShardsCache); + } else if (ignoreAwarenessAttributes()) { if (useAdaptiveReplicaSelection) { return indexShard.activeInitializingShardsRankedIt(collectorService, nodeCounts); } else { diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java new file mode 100644 index 0000000000000..966f185a29630 --- /dev/null +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java @@ -0,0 +1,84 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.routing; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.cluster.ClusterChangedEvent; +import org.opensearch.cluster.ClusterStateListener; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.cache.Cache; +import org.opensearch.common.cache.CacheBuilder; +import org.opensearch.common.lease.Releasable; +import org.opensearch.index.shard.ShardId; + +import java.util.ArrayList; + +public class WRRShardsCache implements Releasable, ClusterStateListener { + private static final Logger logger = LogManager.getLogger(WRRShardsCache.class); + + private final Cache> cache; + + public WRRShardsCache(ClusterService clusterService) { + + final long sizeInBytes = 2000000; + CacheBuilder> cacheBuilder = CacheBuilder.>builder() + .removalListener(notification -> logger.info("Object" + " {} removed from cache", notification.getKey().shardId)) + .setMaximumWeight(sizeInBytes); + cache = cacheBuilder.build(); + clusterService.addListener(this); + } + + @Override + public void close() { + logger.info("Invalidating WRRShardsCache on close"); + cache.invalidateAll(); + } + + public Cache> getCache() { + return cache; + } + + @Override + public void clusterChanged(ClusterChangedEvent event) { + logger.info("Invalidating WRRShardsCache on ClusterChangedEvent"); + cache.invalidateAll(); + } + + /** + * Key for the WRRShardsCache + * + * @opensearch.internal + */ + public static class Key { + public final ShardId shardId; + + Key(ShardId shardId) { + + this.shardId = shardId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WRRShardsCache.Key key = (WRRShardsCache.Key) o; + if (!shardId.equals(key.shardId)) return false; + return true; + } + + @Override + public int hashCode() { + int result = shardId.hashCode(); + + return result; + } + + } +} diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java b/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java similarity index 86% rename from server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java rename to server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java index f27f7c88c7f55..daf2986ea8b71 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRWeight.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java @@ -21,21 +21,21 @@ * * @opensearch.internal */ -public class WRRWeight implements Writeable { +public class WRRWeights implements Writeable { private String attributeName; private Map weights; - public WRRWeight(String attributeName, Map weights) { + public WRRWeights(String attributeName, Map weights) { this.attributeName = attributeName; this.weights = weights; } - public WRRWeight(WRRWeight wrrWeight) { + public WRRWeights(WRRWeights wrrWeight) { this.attributeName = wrrWeight.attributeName(); this.weights = wrrWeight.weights; } - public WRRWeight(StreamInput in) throws IOException { + public WRRWeights(StreamInput in) throws IOException { attributeName = in.readString(); weights = in.readMap(); } @@ -51,7 +51,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - WRRWeight that = (WRRWeight) o; + WRRWeights that = (WRRWeights) o; if (!attributeName.equals(that.attributeName)) return false; return weights.equals(that.weights); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index 0e00b1aa5cedd..ad9702544a1e4 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -58,7 +58,7 @@ public Iterator iterator() { public List> orderEntities() { int size = entities.size(); List> orderedWeight = new ArrayList<>(); - if (size <= 0) { + if (size == 0) { return null; } if (size == 1) { diff --git a/server/src/main/java/org/opensearch/cluster/service/ClusterService.java b/server/src/main/java/org/opensearch/cluster/service/ClusterService.java index d393613118af8..4a8bf9275389a 100644 --- a/server/src/main/java/org/opensearch/cluster/service/ClusterService.java +++ b/server/src/main/java/org/opensearch/cluster/service/ClusterService.java @@ -108,6 +108,7 @@ public ClusterService( this.nodeName = Node.NODE_NAME_SETTING.get(settings); this.clusterManagerService = clusterManagerService; this.operationRouting = new OperationRouting(settings, clusterSettings); + this.operationRouting.setClusterService(this); this.clusterSettings = clusterSettings; this.clusterName = ClusterName.CLUSTER_NAME_SETTING.get(settings); // Add a no-op update consumer so changes are logged diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index dae65adb4baa9..e5c07f1b3daf1 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -33,6 +33,7 @@ import org.opensearch.Version; import org.opensearch.action.support.replication.ClusterStateCreationUtils; +import org.opensearch.cluster.ClusterChangedEvent; import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.Metadata; @@ -802,14 +803,14 @@ public void testWRR() throws Exception { setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); - + opRouting.setClusterService(clusterService); assertTrue(opRouting.ignoreAwarenessAttributes()); Set selectedNodes = new HashSet<>(); ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); Map weights = Map.of("a", "1", "b", "1", "c", "0"); - WRRWeight wrrWeight = new WRRWeight("zone", weights); + WRRWeights wrrWeight = new WRRWeights("zone", weights); WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); @@ -822,6 +823,7 @@ public void testWRR() throws Exception { null, collector, outstandingRequests + ); for (ShardIterator it : groupIterator) { @@ -842,13 +844,14 @@ public void testWRR() throws Exception { .build(); weights = Map.of("a", "1", "b", "0", "c", "1"); - wrrWeight = new WRRWeight("zone", weights); + wrrWeight = new WRRWeights("zone", weights); wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); metadataBuilder = Metadata.builder(state.metadata()); metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); state = ClusterState.builder(state).metadata(metadataBuilder).build(); opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + opRouting.setClusterService(clusterService); groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); @@ -866,6 +869,99 @@ public void testWRR() throws Exception { terminate(threadPool); } + public void testWRRShardsCaching() throws Exception { + final int numIndices = 2; + final int numShards = 3; + final int numReplicas = 2; + final String[] indexNames = new String[numIndices]; + for (int i = 0; i < numIndices; i++) { + indexNames[i] = "test" + i; + } + DiscoveryNode[] allNodes = setUpNodesWRR(); + ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); + + Map> discoveryNodeMap = new HashMap<>(); + List nodesZoneA = new ArrayList<>(); + nodesZoneA.add(allNodes[0]); + nodesZoneA.add(allNodes[1]); + + List nodesZoneB = new ArrayList<>(); + nodesZoneB.add(allNodes[2]); + nodesZoneB.add(allNodes[3]); + + List nodesZoneC = new ArrayList<>(); + nodesZoneC.add(allNodes[4]); + nodesZoneC.add(allNodes[5]); + discoveryNodeMap.put("a", nodesZoneA); + discoveryNodeMap.put("b", nodesZoneB); + discoveryNodeMap.put("c", nodesZoneC); + + state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); + + Settings setting = Settings.builder() + .put("cluster.routing.allocation.awareness.attributes", "zone") + .put("cluster.routing.use_weighted_round_robin", "true") + .build(); + + TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + + OperationRouting opRouting = new OperationRouting( + setting, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) + ); + opRouting.setClusterService(clusterService); + + assertTrue(opRouting.ignoreAwarenessAttributes()); + ResponseCollectorService collector = new ResponseCollectorService(clusterService); + Map outstandingRequests = new HashMap<>(); + + Map weights = Map.of("a", "1", "b", "1", "c", "0"); + WRRWeights wrrWeight = new WRRWeights("zone", weights); + WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + state = ClusterState.builder(state).metadata(metadataBuilder).build(); + + GroupShardsIterator groupIterator = opRouting.searchShards( + state, + indexNames, + null, + null, + collector, + outstandingRequests + ); + + assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + + // Calling operation routing without any cluster state change + groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + + assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getHits()); + assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + + // Calling Operation Routing after a change in cluster metadata + weights = Map.of("a", "1", "b", "0", "c", "1"); + wrrWeight = new WRRWeights("zone", weights); + wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + metadataBuilder = Metadata.builder(state.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + ClusterState state2 = ClusterState.builder(state).metadata(metadataBuilder).build(); + + ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); + + opRouting.getWrrShardsCache().clusterChanged(event); + + groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); + + assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getHits()); + assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getMisses()); + assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + + IOUtils.close(clusterService); + terminate(threadPool); + } + private DiscoveryNode[] setupNodes() { // Sets up two data nodes in zone-a and one data node in zone-b List zones = Arrays.asList("a", "a", "b"); @@ -1032,8 +1128,8 @@ private ClusterState updateStatetoTestWRR( } // add wrr weights in metadata Map weights = Map.of("a", "1", "b", "1", "c", "0"); - WRRWeight wrrWeight = new WRRWeight("zone", weights); - WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + WRRWeights wrrWeights = new WRRWeights("zone", weights); + WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeights); metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); clusterState.metadata(metadataBuilder); clusterState.routingTable(routingTableBuilder.build()); From 4cdbee303db934d7afa202dd1b796731291fdcbc Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Sat, 27 Aug 2022 12:29:13 +0530 Subject: [PATCH 03/55] Integrate ARS with weighted round robin, Remove Cluster Settings for WRR Add Code refactoring and Java docs Signed-off-by: Anshu Agarwal --- .../metadata/WeightedRoundRobinMetadata.java | 4 +- .../routing/IndexShardRoutingTable.java | 50 ++++++++++++----- .../cluster/routing/OperationRouting.java | 17 +----- .../cluster/routing/WRRShardsCache.java | 19 +++++-- .../cluster/routing/WeightedRoundRobin.java | 38 ++----------- .../common/settings/ClusterSettings.java | 1 - .../routing/OperationRoutingTests.java | 53 +++++++++++++------ .../routing/WeightedRoundRobinTests.java | 37 +++++++++++++ 8 files changed, 137 insertions(+), 82 deletions(-) create mode 100644 server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java index ed89f885bdb4a..34a5a15114ce7 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java @@ -66,8 +66,8 @@ public String getWriteableName() { @Override public Version getMinimalSupportedVersion() { - // TODO: Check if this needs to be changed - return Version.CURRENT.minimumCompatibilityVersion(); + return Version.V_2_3_0; + } @Override diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index 56abf80af1cdc..16d8dbddf75fd 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -43,6 +43,7 @@ import org.opensearch.index.Index; import org.opensearch.index.shard.ShardId; import org.opensearch.node.ResponseCollectorService; + import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -292,16 +293,24 @@ public ShardIterator activeInitializingShardsRankedIt( } /** - * * + * Returns an iterator over active and initializing shards, shards are ordered by weighted round-robin scheduling + * policy with adaptive replica selection. The output from weighted round-robin is ordered using adaptive replica + * selection to select eligible nodes for better performance. * @param wrrWeight Weighted round-robin weight entity * @param nodes discovered nodes in the cluster - * @return an interator over active and initializing shards, ordered by weighted round-robin + * @return an iterator over active and initializing shards, ordered by weighted round-robin * scheduling policy. Making sure that initializing shards are the last to iterate through. */ - public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, DiscoveryNodes nodes, WRRShardsCache cache) { + public ShardIterator activeInitializingShardsWRR( + WRRWeights wrrWeight, + DiscoveryNodes nodes, + WRRShardsCache cache, + @Nullable ResponseCollectorService collector, + @Nullable Map nodeSearchCounts + ) { final int seed = shuffler.nextSeed(); - ArrayList ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); - ArrayList orderedActiveShards; + List ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); + List orderedActiveShards; if (cache.getCache().get(new WRRShardsCache.Key(shardId)) != null) { orderedActiveShards = cache.getCache().get(new WRRShardsCache.Key(shardId)); } else { @@ -309,9 +318,24 @@ public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, Discovery cache.getCache().put(new WRRShardsCache.Key(shardId), orderedActiveShards); } - ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); + // In case the shardRouting list returned by weighted round-robin is empty, we fail open and consider all + // activeShards + orderedActiveShards = orderedActiveShards == null || orderedActiveShards.isEmpty() ? activeShards : orderedActiveShards; + + // output from weighted round-robin is ordered using adaptive replica selection + orderedActiveShards = rankShardsAndUpdateStats(shuffler.shuffle(orderedActiveShards, seed), collector, nodeSearchCounts); + + ordered.addAll(orderedActiveShards); + if (!allInitializingShards.isEmpty()) { - ArrayList orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); + List orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); + // In case the shardRouting list returned by weighted round-robin is empty, we fail open and consider all + // initializing shards + orderedInitializingShards = orderedInitializingShards == null || orderedInitializingShards.isEmpty() + ? allInitializingShards + : orderedInitializingShards; + // output from weighted round-robin is ordered using adaptive replica selection + orderedInitializingShards = rankShardsAndUpdateStats(orderedInitializingShards, collector, nodeSearchCounts); ordered.addAll(orderedInitializingShards); } return new PlainShardIterator(shardId, ordered); @@ -324,11 +348,11 @@ public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, Discovery * @param nodes discovered nodes in the cluster * @return list of shards ordered using weighted round-robin scheduling. */ - private ArrayList getShardsWRR(List shards, WRRWeights wrrWeight, DiscoveryNodes nodes) { + private List getShardsWRR(List shards, WRRWeights wrrWeight, DiscoveryNodes nodes) { List> weightedShards = calculateShardWeight(shards, wrrWeight, nodes); WeightedRoundRobin wrr = new WeightedRoundRobin<>(weightedShards); List> wrrOrderedActiveShards = wrr.orderEntities(); - ArrayList orderedActiveShards = new ArrayList<>(activeShards.size()); + List orderedActiveShards = new ArrayList<>(activeShards.size()); for (WeightedRoundRobin.Entity shardRouting : wrrOrderedActiveShards) { orderedActiveShards.add(shardRouting.getTarget()); } @@ -336,10 +360,10 @@ private ArrayList getShardsWRR(List shards, WRRWeigh } /** - * * + * * @param shards associate weights to shards * @param wrrWeight weights to be used for association - * @param nodes + * @param nodes discovered nodes in the cluster * @return list of entity containing shard routing and associated weight. */ private List> calculateShardWeight( @@ -352,7 +376,9 @@ private List> calculateShardWeight( shard.currentNodeId(); DiscoveryNode node = nodes.get(shard.currentNodeId()); String attVal = node.getAttributes().get(wrrWeight.attributeName()); - weightedShards.add(new WeightedRoundRobin.Entity<>(Double.parseDouble(wrrWeight.weights().get(attVal).toString()), shard)); + // If weight for a zone is not defined, considering it as 1 by default + Double weight = Double.parseDouble(wrrWeight.weights().getOrDefault(attVal, 1).toString()); + weightedShards.add(new WeightedRoundRobin.Entity<>(weight, shard)); } return weightedShards; } diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index d33b42bc69620..c48450f72a244 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -70,12 +70,6 @@ public class OperationRouting { Setting.Property.NodeScope ); - public static final Setting USE_WEIGHTED_ROUND_ROBIN = Setting.boolSetting( - "cluster.routing.use_weighted_round_robin", - true, - Setting.Property.Dynamic, - Setting.Property.NodeScope - ); public static final String IGNORE_AWARENESS_ATTRIBUTES = "cluster.search.ignore_awareness_attributes"; public static final Setting IGNORE_AWARENESS_ATTRIBUTES_SETTING = Setting.boolSetting( IGNORE_AWARENESS_ATTRIBUTES, @@ -123,10 +117,8 @@ public OperationRouting(Settings settings, ClusterSettings clusterSettings) { this::setAwarenessAttributes ); this.useAdaptiveReplicaSelection = USE_ADAPTIVE_REPLICA_SELECTION_SETTING.get(settings); - this.useWeightedRoundRobin = USE_WEIGHTED_ROUND_ROBIN.get(settings); clusterSettings.addSettingsUpdateConsumer(USE_ADAPTIVE_REPLICA_SELECTION_SETTING, this::setUseAdaptiveReplicaSelection); clusterSettings.addSettingsUpdateConsumer(IGNORE_AWARENESS_ATTRIBUTES_SETTING, this::setIgnoreAwarenessAttributes); - clusterSettings.addSettingsUpdateConsumer(USE_WEIGHTED_ROUND_ROBIN, this::setUseWeightedRoundRobin); } @@ -138,10 +130,6 @@ void setIgnoreAwarenessAttributes(boolean ignoreAwarenessAttributes) { this.ignoreAwarenessAttr = ignoreAwarenessAttributes; } - public void setUseWeightedRoundRobin(boolean useWeightedRoundRobin) { - this.useWeightedRoundRobin = useWeightedRoundRobin; - } - public boolean isIgnoreAwarenessAttr() { return ignoreAwarenessAttr; } @@ -234,12 +222,11 @@ public GroupShardsIterator searchShards( private void setWeightedRoundRobinAttributes(ClusterState clusterState, ClusterService clusterService) { WeightedRoundRobinMetadata weightedRoundRobinMetadata = clusterState.metadata().custom(WeightedRoundRobinMetadata.TYPE); - this.isWeightedRoundRobinEnabled = useWeightedRoundRobin && weightedRoundRobinMetadata != null ? true : false; + this.isWeightedRoundRobinEnabled = weightedRoundRobinMetadata != null ? true : false; if (this.isWeightedRoundRobinEnabled) { this.wrrWeights = weightedRoundRobinMetadata.getWrrWeight(); this.wrrShardsCache = getWrrShardsCache() != null ? getWrrShardsCache() : new WRRShardsCache(clusterService); } - } private boolean isWeightedRoundRobinEnabled() { @@ -364,7 +351,7 @@ private ShardIterator shardRoutings( @Nullable Map nodeCounts ) { if (isWeightedRoundRobinEnabled()) { - return indexShard.activeInitializingShardsWRR(getWrrWeights(), nodes, wrrShardsCache); + return indexShard.activeInitializingShardsWRR(getWrrWeights(), nodes, wrrShardsCache, collectorService, nodeCounts); } else if (ignoreAwarenessAttributes()) { if (useAdaptiveReplicaSelection) { return indexShard.activeInitializingShardsRankedIt(collectorService, nodeCounts); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java index 966f185a29630..879f73a304c76 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java @@ -18,17 +18,23 @@ import org.opensearch.common.lease.Releasable; import org.opensearch.index.shard.ShardId; -import java.util.ArrayList; +import java.util.List; +/** + * The WRR shards cache allows caching shard ordering returned by Weighted round-robin scheduling policy ,helping with + * improving similar requests. + * + * @opensearch.internal + */ public class WRRShardsCache implements Releasable, ClusterStateListener { private static final Logger logger = LogManager.getLogger(WRRShardsCache.class); - private final Cache> cache; + private final Cache> cache; public WRRShardsCache(ClusterService clusterService) { final long sizeInBytes = 2000000; - CacheBuilder> cacheBuilder = CacheBuilder.>builder() + CacheBuilder> cacheBuilder = CacheBuilder.>builder() .removalListener(notification -> logger.info("Object" + " {} removed from cache", notification.getKey().shardId)) .setMaximumWeight(sizeInBytes); cache = cacheBuilder.build(); @@ -41,10 +47,15 @@ public void close() { cache.invalidateAll(); } - public Cache> getCache() { + public Cache> getCache() { return cache; } + /** + * Listens to cluster state change event and invalidate cache on such events + * + * @param event cluster state change event + */ @Override public void clusterChanged(ClusterChangedEvent event) { logger.info("Invalidating WRRShardsCache on ClusterChangedEvent"); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index ad9702544a1e4..bd87789bc90b9 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -9,45 +9,15 @@ package org.opensearch.cluster.routing; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -public class WeightedRoundRobin implements Iterator, Iterable { +public class WeightedRoundRobin { private List> entities; private int turn; - private int lastSelectedEntity; - private double currentWeight = 0; public WeightedRoundRobin(List> entities) { this.entities = entities; - this.turn = 0; - this.lastSelectedEntity = -1; - } - - /* (non-Javadoc) - * @see java.util.Iterator#hasNext() - */ - @Override - public boolean hasNext() { - return entities.size() > 0; - } - - /* (non-Javadoc) - * @see java.util.Iterator#next() - */ - @Override - public T next() { - Entity entity = entities.get(turn++); - return entity.getTarget(); - } - - /* (non-Javadoc) - * @see java.lang.Iterable#iterator() - */ - @Override - public Iterator iterator() { - return this; } /** @@ -56,7 +26,9 @@ public Iterator iterator() { * http://kb.linuxvirtualserver.org/wiki/Weighted_Round-Robin_Scheduling */ public List> orderEntities() { + int lastSelectedEntity = -1; int size = entities.size(); + double currentWeight = 0; List> orderedWeight = new ArrayList<>(); if (size == 0) { return null; @@ -97,8 +69,8 @@ public List> orderEntities() { * Return greatest common divisor for two integers * https://en.wikipedia.org/wiki/Greatest_common_divisor#Using_Euclid.27s_algorithm * - * @param a - * @param b + * @param a first number + * @param b second number * @return greatest common divisor */ private double gcd(double a, double b) { diff --git a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java index bc06987624918..971fb518ff1da 100644 --- a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java @@ -529,7 +529,6 @@ public void apply(Settings value, Settings current, Settings previous) { Node.BREAKER_TYPE_KEY, OperationRouting.USE_ADAPTIVE_REPLICA_SELECTION_SETTING, OperationRouting.IGNORE_AWARENESS_ATTRIBUTES_SETTING, - OperationRouting.USE_WEIGHTED_ROUND_ROBIN, IndexGraveyard.SETTING_MAX_TOMBSTONES, PersistentTasksClusterService.CLUSTER_TASKS_ALLOCATION_RECHECK_INTERVAL_SETTING, EnableAssignmentDecider.CLUSTER_TASKS_ALLOCATION_ENABLE_SETTING, diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index e5c07f1b3daf1..071f7510abe14 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -766,10 +766,13 @@ public void testWRR() throws Exception { final int numIndices = 2; final int numShards = 3; final int numReplicas = 2; + // setting up indices final String[] indexNames = new String[numIndices]; for (int i = 0; i < numIndices; i++) { indexNames[i] = "test" + i; } + + // setting up domain nodes and attributes DiscoveryNode[] allNodes = setUpNodesWRR(); ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); @@ -789,12 +792,10 @@ public void testWRR() throws Exception { discoveryNodeMap.put("b", nodesZoneB); discoveryNodeMap.put("c", nodesZoneC); + // Updating cluster state with node, index and shard details state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); - Settings setting = Settings.builder() - .put("cluster.routing.allocation.awareness.attributes", "zone") - .put("cluster.routing.use_weighted_round_robin", "true") - .build(); + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); @@ -809,6 +810,7 @@ public void testWRR() throws Exception { ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); + // Setting up weights for weighted round-robin in cluster state Map weights = Map.of("a", "1", "b", "1", "c", "0"); WRRWeights wrrWeight = new WRRWeights("zone", weights); WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); @@ -816,6 +818,7 @@ public void testWRR() throws Exception { metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); state = ClusterState.builder(state).metadata(metadataBuilder).build(); + // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -832,27 +835,29 @@ public void testWRR() throws Exception { selectedNodes.add(shardRouting.currentNodeId()); } } + // tests no nodes are assigned to nodes in zone c for (String nodeID : selectedNodes) { // No shards are assigned to nodes in zone c since its weight is 0 assertFalse(nodeID.contains("c")); } selectedNodes = new HashSet<>(); - setting = Settings.builder() - .put("cluster.routing.allocation.awareness.attributes", "zone") - .put("cluster.routing.use_weighted_round_robin", "true") - .build(); + setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); + // Updating weighted round robin weights in cluster state weights = Map.of("a", "1", "b", "0", "c", "1"); wrrWeight = new WRRWeights("zone", weights); wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); metadataBuilder = Metadata.builder(state.metadata()); metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + + // building cluster state with new weights state = ClusterState.builder(state).metadata(metadataBuilder).build(); opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); opRouting.setClusterService(clusterService); + // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); for (ShardIterator it : groupIterator) { @@ -861,6 +866,7 @@ public void testWRR() throws Exception { selectedNodes.add(shardRouting.currentNodeId()); } } + // tests that no shards are assigned to zone with weight zero for (String nodeID : selectedNodes) { // No shards are assigned to nodes in zone b since its weight is 0 assertFalse(nodeID.contains("b")); @@ -873,10 +879,13 @@ public void testWRRShardsCaching() throws Exception { final int numIndices = 2; final int numShards = 3; final int numReplicas = 2; + // setting up indices final String[] indexNames = new String[numIndices]; for (int i = 0; i < numIndices; i++) { indexNames[i] = "test" + i; } + + // setting up domain nodes and attributes DiscoveryNode[] allNodes = setUpNodesWRR(); ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); @@ -896,12 +905,10 @@ public void testWRRShardsCaching() throws Exception { discoveryNodeMap.put("b", nodesZoneB); discoveryNodeMap.put("c", nodesZoneC); + // Updating cluster state with node, index and shard details state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); - Settings setting = Settings.builder() - .put("cluster.routing.allocation.awareness.attributes", "zone") - .put("cluster.routing.use_weighted_round_robin", "true") - .build(); + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); @@ -916,6 +923,7 @@ public void testWRRShardsCaching() throws Exception { ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); + // Setting up weights for weighted round-robin in cluster state Map weights = Map.of("a", "1", "b", "1", "c", "0"); WRRWeights wrrWeight = new WRRWeights("zone", weights); WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); @@ -923,6 +931,7 @@ public void testWRRShardsCaching() throws Exception { metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); state = ClusterState.builder(state).metadata(metadataBuilder).build(); + // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -932,30 +941,44 @@ public void testWRRShardsCaching() throws Exception { outstandingRequests ); + // shard wrr ordering details are not present in cache, the details are calculated and put in cache + assertEquals(6, opRouting.getWrrShardsCache().getCache().stats().getMisses()); assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); - // Calling operation routing without any cluster state change + // Calling operation routing again without any cluster state change to test that wrr shard routing details are + // fetched from cache groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + // details are fetched from cache assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getHits()); + // cache count stays same assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + // cache misses stay same + assertEquals(6, opRouting.getWrrShardsCache().getCache().stats().getMisses()); - // Calling Operation Routing after a change in cluster metadata + // Updating cluster state to test wrr shard routing details are calculated again weights = Map.of("a", "1", "b", "0", "c", "1"); wrrWeight = new WRRWeights("zone", weights); wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); metadataBuilder = Metadata.builder(state.metadata()); metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + // building new cluster state ClusterState state2 = ClusterState.builder(state).metadata(metadataBuilder).build(); ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); - opRouting.getWrrShardsCache().clusterChanged(event); + // cache is invalidated after cluster state change, cache count is zero + assertEquals(0, opRouting.getWrrShardsCache().getCache().count()); + + // search shards call groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); + // cache hit remain same assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getHits()); + // cache miss increases by 6 assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getMisses()); + assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); IOUtils.close(clusterService); diff --git a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java new file mode 100644 index 0000000000000..398a36fba83e5 --- /dev/null +++ b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java @@ -0,0 +1,37 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.routing; + +import org.opensearch.test.OpenSearchTestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class WeightedRoundRobinTests extends OpenSearchTestCase { + + public void testWRROrder() { + + List> entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(4, "A")); + entity.add(new WeightedRoundRobin.Entity<>(3, "B")); + entity.add(new WeightedRoundRobin.Entity<>(2, "C")); + WeightedRoundRobin wrr = new WeightedRoundRobin(entity); + List> orderedEntities = wrr.orderEntities(); + + List expectedOrdering = Arrays.asList("A", "A", "B", "A", "B", "C", "A", "B", "C"); + List actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + + assertEquals(expectedOrdering, actualOrdering); + } + +} From 7a49e5ceb86d61fdf8de36914856848a3fdfd9ba Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 1 Sep 2022 13:02:14 +0530 Subject: [PATCH 04/55] Remove ARS and add tests for zone with undefined weight Signed-off-by: Anshu Agarwal --- .../org/opensearch/cluster/ClusterModule.java | 14 ++ ...=> WeightedRoundRobinRoutingMetadata.java} | 16 +- .../routing/IndexShardRoutingTable.java | 34 +--- .../cluster/routing/OperationRouting.java | 11 +- .../cluster/routing/WeightedRoundRobin.java | 1 - .../routing/OperationRoutingTests.java | 169 +++++++++++++----- 6 files changed, 160 insertions(+), 85 deletions(-) rename server/src/main/java/org/opensearch/cluster/metadata/{WeightedRoundRobinMetadata.java => WeightedRoundRobinRoutingMetadata.java} (88%) diff --git a/server/src/main/java/org/opensearch/cluster/ClusterModule.java b/server/src/main/java/org/opensearch/cluster/ClusterModule.java index f8ba520e465e2..99a342eaeb5ed 100644 --- a/server/src/main/java/org/opensearch/cluster/ClusterModule.java +++ b/server/src/main/java/org/opensearch/cluster/ClusterModule.java @@ -48,6 +48,7 @@ import org.opensearch.cluster.metadata.MetadataMappingService; import org.opensearch.cluster.metadata.MetadataUpdateSettingsService; import org.opensearch.cluster.metadata.RepositoriesMetadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; import org.opensearch.cluster.routing.DelayedAllocationService; import org.opensearch.cluster.routing.allocation.AllocationService; import org.opensearch.cluster.routing.allocation.ExistingShardsAllocator; @@ -191,6 +192,12 @@ public static List getNamedWriteables() { ComposableIndexTemplateMetadata::readDiffFrom ); registerMetadataCustom(entries, DataStreamMetadata.TYPE, DataStreamMetadata::new, DataStreamMetadata::readDiffFrom); + registerMetadataCustom( + entries, + WeightedRoundRobinRoutingMetadata.TYPE, + WeightedRoundRobinRoutingMetadata::new, + WeightedRoundRobinRoutingMetadata::readDiffFrom + ); // Task Status (not Diffable) entries.add(new Entry(Task.Status.class, PersistentTasksNodeService.Status.NAME, PersistentTasksNodeService.Status::new)); return entries; @@ -274,6 +281,13 @@ public static List getNamedXWriteables() { DataStreamMetadata::fromXContent ) ); + entries.add( + new NamedXContentRegistry.Entry( + Metadata.Custom.class, + new ParseField(WeightedRoundRobinRoutingMetadata.TYPE), + WeightedRoundRobinRoutingMetadata::fromXContent + ) + ); return entries; } diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java similarity index 88% rename from server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java rename to server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java index 34a5a15114ce7..a05e3e8aaec4d 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java @@ -32,8 +32,8 @@ * * @opensearch.internal */ -public class WeightedRoundRobinMetadata extends AbstractNamedDiffable implements Metadata.Custom { - private static final Logger logger = LogManager.getLogger(WeightedRoundRobinMetadata.class); +public class WeightedRoundRobinRoutingMetadata extends AbstractNamedDiffable implements Metadata.Custom { + private static final Logger logger = LogManager.getLogger(WeightedRoundRobinRoutingMetadata.class); public static final String TYPE = "wrr_shard_routing"; private WRRWeights wrrWeight; @@ -41,16 +41,16 @@ public WRRWeights getWrrWeight() { return wrrWeight; } - public WeightedRoundRobinMetadata setWrrWeight(WRRWeights wrrWeight) { + public WeightedRoundRobinRoutingMetadata setWrrWeight(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; return this; } - public WeightedRoundRobinMetadata(StreamInput in) throws IOException { + public WeightedRoundRobinRoutingMetadata(StreamInput in) throws IOException { this.wrrWeight = new WRRWeights(in); } - public WeightedRoundRobinMetadata(WRRWeights wrrWeight) { + public WeightedRoundRobinRoutingMetadata(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; } @@ -79,7 +79,7 @@ public static NamedDiff readDiffFrom(StreamInput in) throws IOE return readDiffFrom(Metadata.Custom.class, TYPE, in); } - public static WeightedRoundRobinMetadata fromXContent(XContentParser parser) throws IOException { + public static WeightedRoundRobinRoutingMetadata fromXContent(XContentParser parser) throws IOException { String attrKey = null; Object attrValue; String attributeName = null; @@ -117,14 +117,14 @@ public static WeightedRoundRobinMetadata fromXContent(XContentParser parser) thr } } wrrWeight = new WRRWeights(attributeName, weights); - return new WeightedRoundRobinMetadata(wrrWeight); + return new WeightedRoundRobinRoutingMetadata(wrrWeight); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - WeightedRoundRobinMetadata that = (WeightedRoundRobinMetadata) o; + WeightedRoundRobinRoutingMetadata that = (WeightedRoundRobinRoutingMetadata) o; return wrrWeight.equals(that.wrrWeight); } diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index 16d8dbddf75fd..a8ad49bd968e3 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -294,20 +294,13 @@ public ShardIterator activeInitializingShardsRankedIt( /** * Returns an iterator over active and initializing shards, shards are ordered by weighted round-robin scheduling - * policy with adaptive replica selection. The output from weighted round-robin is ordered using adaptive replica - * selection to select eligible nodes for better performance. + * policy. * @param wrrWeight Weighted round-robin weight entity * @param nodes discovered nodes in the cluster * @return an iterator over active and initializing shards, ordered by weighted round-robin * scheduling policy. Making sure that initializing shards are the last to iterate through. */ - public ShardIterator activeInitializingShardsWRR( - WRRWeights wrrWeight, - DiscoveryNodes nodes, - WRRShardsCache cache, - @Nullable ResponseCollectorService collector, - @Nullable Map nodeSearchCounts - ) { + public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, DiscoveryNodes nodes, WRRShardsCache cache) { final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); List orderedActiveShards; @@ -317,25 +310,10 @@ public ShardIterator activeInitializingShardsWRR( orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); cache.getCache().put(new WRRShardsCache.Key(shardId), orderedActiveShards); } - - // In case the shardRouting list returned by weighted round-robin is empty, we fail open and consider all - // activeShards - orderedActiveShards = orderedActiveShards == null || orderedActiveShards.isEmpty() ? activeShards : orderedActiveShards; - - // output from weighted round-robin is ordered using adaptive replica selection - orderedActiveShards = rankShardsAndUpdateStats(shuffler.shuffle(orderedActiveShards, seed), collector, nodeSearchCounts); - ordered.addAll(orderedActiveShards); if (!allInitializingShards.isEmpty()) { List orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); - // In case the shardRouting list returned by weighted round-robin is empty, we fail open and consider all - // initializing shards - orderedInitializingShards = orderedInitializingShards == null || orderedInitializingShards.isEmpty() - ? allInitializingShards - : orderedInitializingShards; - // output from weighted round-robin is ordered using adaptive replica selection - orderedInitializingShards = rankShardsAndUpdateStats(orderedInitializingShards, collector, nodeSearchCounts); ordered.addAll(orderedInitializingShards); } return new PlainShardIterator(shardId, ordered); @@ -373,11 +351,13 @@ private List> calculateShardWeight( ) { List> weightedShards = new ArrayList<>(); for (ShardRouting shard : shards) { - shard.currentNodeId(); DiscoveryNode node = nodes.get(shard.currentNodeId()); String attVal = node.getAttributes().get(wrrWeight.attributeName()); - // If weight for a zone is not defined, considering it as 1 by default - Double weight = Double.parseDouble(wrrWeight.weights().getOrDefault(attVal, 1).toString()); + // If weight for a zone is not defined, not considering shards from that zone + if (wrrWeight.weights().get(attVal) == null) { + continue; + } + Double weight = Double.parseDouble(wrrWeight.weights().get(attVal).toString()); weightedShards.add(new WeightedRoundRobin.Entity<>(weight, shard)); } return weightedShards; diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index c48450f72a244..9dd9f778fb660 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -34,7 +34,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; import org.opensearch.cluster.node.DiscoveryNodes; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; import org.opensearch.cluster.service.ClusterService; @@ -221,10 +221,11 @@ public GroupShardsIterator searchShards( } private void setWeightedRoundRobinAttributes(ClusterState clusterState, ClusterService clusterService) { - WeightedRoundRobinMetadata weightedRoundRobinMetadata = clusterState.metadata().custom(WeightedRoundRobinMetadata.TYPE); - this.isWeightedRoundRobinEnabled = weightedRoundRobinMetadata != null ? true : false; + WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterState.metadata() + .custom(WeightedRoundRobinRoutingMetadata.TYPE); + this.isWeightedRoundRobinEnabled = weightedRoundRobinRoutingMetadata != null ? true : false; if (this.isWeightedRoundRobinEnabled) { - this.wrrWeights = weightedRoundRobinMetadata.getWrrWeight(); + this.wrrWeights = weightedRoundRobinRoutingMetadata.getWrrWeight(); this.wrrShardsCache = getWrrShardsCache() != null ? getWrrShardsCache() : new WRRShardsCache(clusterService); } } @@ -351,7 +352,7 @@ private ShardIterator shardRoutings( @Nullable Map nodeCounts ) { if (isWeightedRoundRobinEnabled()) { - return indexShard.activeInitializingShardsWRR(getWrrWeights(), nodes, wrrShardsCache, collectorService, nodeCounts); + return indexShard.activeInitializingShardsWRR(getWrrWeights(), nodes, wrrShardsCache); } else if (ignoreAwarenessAttributes()) { if (useAdaptiveReplicaSelection) { return indexShard.activeInitializingShardsRankedIt(collectorService, nodeCounts); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index bd87789bc90b9..e184bc4a5dc30 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -14,7 +14,6 @@ public class WeightedRoundRobin { private List> entities; - private int turn; public WeightedRoundRobin(List> entities) { this.entities = entities; diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 071f7510abe14..9ee13e1190ed2 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -37,7 +37,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.Metadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.cluster.node.DiscoveryNodeRole; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; @@ -762,17 +762,7 @@ public void testAdaptiveReplicaSelectionWithZoneAwarenessIgnored() throws Except terminate(threadPool); } - public void testWRR() throws Exception { - final int numIndices = 2; - final int numShards = 3; - final int numReplicas = 2; - // setting up indices - final String[] indexNames = new String[numIndices]; - for (int i = 0; i < numIndices; i++) { - indexNames[i] = "test" + i; - } - - // setting up domain nodes and attributes + private ClusterState clusterStateForWRR(String[] indexNames, int numShards, int numReplicas) { DiscoveryNode[] allNodes = setUpNodesWRR(); ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); @@ -795,6 +785,22 @@ public void testWRR() throws Exception { // Updating cluster state with node, index and shard details state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); + return state; + + } + + public void testWRR() throws Exception { + final int numIndices = 2; + final int numShards = 3; + final int numReplicas = 2; + // setting up indices + final String[] indexNames = new String[numIndices]; + for (int i = 0; i < numIndices; i++) { + indexNames[i] = "test" + i; + } + + ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); @@ -813,9 +819,9 @@ public void testWRR() throws Exception { // Setting up weights for weighted round-robin in cluster state Map weights = Map.of("a", "1", "b", "1", "c", "0"); WRRWeights wrrWeight = new WRRWeights("zone", weights); - WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); state = ClusterState.builder(state).metadata(metadataBuilder).build(); // search shards call @@ -847,9 +853,9 @@ public void testWRR() throws Exception { // Updating weighted round robin weights in cluster state weights = Map.of("a", "1", "b", "0", "c", "1"); wrrWeight = new WRRWeights("zone", weights); - wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); // building cluster state with new weights state = ClusterState.builder(state).metadata(metadataBuilder).build(); @@ -885,28 +891,7 @@ public void testWRRShardsCaching() throws Exception { indexNames[i] = "test" + i; } - // setting up domain nodes and attributes - DiscoveryNode[] allNodes = setUpNodesWRR(); - ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); - - Map> discoveryNodeMap = new HashMap<>(); - List nodesZoneA = new ArrayList<>(); - nodesZoneA.add(allNodes[0]); - nodesZoneA.add(allNodes[1]); - - List nodesZoneB = new ArrayList<>(); - nodesZoneB.add(allNodes[2]); - nodesZoneB.add(allNodes[3]); - - List nodesZoneC = new ArrayList<>(); - nodesZoneC.add(allNodes[4]); - nodesZoneC.add(allNodes[5]); - discoveryNodeMap.put("a", nodesZoneA); - discoveryNodeMap.put("b", nodesZoneB); - discoveryNodeMap.put("c", nodesZoneC); - - // Updating cluster state with node, index and shard details - state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); + ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); @@ -926,9 +911,9 @@ public void testWRRShardsCaching() throws Exception { // Setting up weights for weighted round-robin in cluster state Map weights = Map.of("a", "1", "b", "1", "c", "0"); WRRWeights wrrWeight = new WRRWeights("zone", weights); - WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); state = ClusterState.builder(state).metadata(metadataBuilder).build(); // search shards call @@ -959,9 +944,9 @@ public void testWRRShardsCaching() throws Exception { // Updating cluster state to test wrr shard routing details are calculated again weights = Map.of("a", "1", "b", "0", "c", "1"); wrrWeight = new WRRWeights("zone", weights); - wrrMetadata = new WeightedRoundRobinMetadata(wrrWeight); + wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); // building new cluster state ClusterState state2 = ClusterState.builder(state).metadata(metadataBuilder).build(); @@ -985,6 +970,102 @@ public void testWRRShardsCaching() throws Exception { terminate(threadPool); } + public void testWRRWithWeightUndefinedForOneZone() throws Exception { + final int numIndices = 2; + final int numShards = 3; + final int numReplicas = 2; + // setting up indices + final String[] indexNames = new String[numIndices]; + for (int i = 0; i < numIndices; i++) { + indexNames[i] = "test" + i; + } + + ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); + + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); + + TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + + OperationRouting opRouting = new OperationRouting( + setting, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) + ); + opRouting.setClusterService(clusterService); + assertTrue(opRouting.ignoreAwarenessAttributes()); + Set selectedNodes = new HashSet<>(); + ResponseCollectorService collector = new ResponseCollectorService(clusterService); + Map outstandingRequests = new HashMap<>(); + + // Setting up weights for weighted round-robin in cluster state, weight for nodes in zone b is not set + Map weights = Map.of("a", "1", "c", "0"); + WRRWeights wrrWeight = new WRRWeights("zone", weights); + WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); + Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); + state = ClusterState.builder(state).metadata(metadataBuilder).build(); + + // search shards call + GroupShardsIterator groupIterator = opRouting.searchShards( + state, + indexNames, + null, + null, + collector, + outstandingRequests + + ); + + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } + } + // tests no nodes are assigned to nodes in zone c + for (String nodeID : selectedNodes) { + // shard from nodes in zone c is not selected since its weight is 0 + assertFalse(nodeID.contains("c")); + // shard from nodes in zone b is not selected since its weight is not set + assertFalse(nodeID.contains("b")); + } + + selectedNodes = new HashSet<>(); + setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); + + // Updating weighted round robin weights in cluster state + weights = Map.of("a", "0", "b", "1"); + wrrWeight = new WRRWeights("zone", weights); + wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); + metadataBuilder = Metadata.builder(state.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); + + // building cluster state with new weights + state = ClusterState.builder(state).metadata(metadataBuilder).build(); + + opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + opRouting.setClusterService(clusterService); + + // search shards call + groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } + } + // tests that no shards are assigned to zone with weight zero + for (String nodeID : selectedNodes) { + // shard from nodes in zone a is not selected since its weight is 0 + assertFalse(nodeID.contains("a")); + // shard from nodes in zone c is not selected since its weight is not set + assertFalse(nodeID.contains("c")); + } + IOUtils.close(clusterService); + terminate(threadPool); + } + private DiscoveryNode[] setupNodes() { // Sets up two data nodes in zone-a and one data node in zone-b List zones = Arrays.asList("a", "a", "b"); @@ -1152,8 +1233,8 @@ private ClusterState updateStatetoTestWRR( // add wrr weights in metadata Map weights = Map.of("a", "1", "b", "1", "c", "0"); WRRWeights wrrWeights = new WRRWeights("zone", weights); - WeightedRoundRobinMetadata wrrMetadata = new WeightedRoundRobinMetadata(wrrWeights); - metadataBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrMetadata); + WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeights); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); clusterState.metadata(metadataBuilder); clusterState.routingTable(routingTableBuilder.build()); return clusterState.build(); From 03c4d2344372411a84752d52311eb80cc329e8d5 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 1 Sep 2022 13:07:26 +0530 Subject: [PATCH 05/55] Add changelog for the commit Signed-off-by: Anshu Agarwal --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8132c1281e412..f8ca0f9040ca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Changed - Dependency updates (httpcore, mockito, slf4j, httpasyncclient, commons-codec) ([#4308](https://github.com/opensearch-project/OpenSearch/pull/4308)) + - Weighted round-robin scheduling policy for shard coordination traffic ([#4241](https://github.com/opensearch-project/OpenSearch/pull/4241)) + ### Deprecated From 154a3b94a85fcb180bd3966ccaa4e6ea6d1d5292 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 1 Sep 2022 14:09:42 +0530 Subject: [PATCH 06/55] Fix java doc, add test of WeightedRoundRobinRouting metadata Signed-off-by: Anshu Agarwal --- .../WeightedRoundRobinRoutingMetadata.java | 3 +- .../cluster/routing/WeightedRoundRobin.java | 5 ++- ...eightedRoundRobinRoutingMetadataTests.java | 37 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java index a05e3e8aaec4d..9ed11cb31c4d0 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java @@ -35,6 +35,7 @@ public class WeightedRoundRobinRoutingMetadata extends AbstractNamedDiffable implements Metadata.Custom { private static final Logger logger = LogManager.getLogger(WeightedRoundRobinRoutingMetadata.class); public static final String TYPE = "wrr_shard_routing"; + public static final String AWARENESS = "awareness"; private WRRWeights wrrWeight; public WRRWeights getWrrWeight() { @@ -140,7 +141,7 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par } public static void toXContent(WRRWeights wrrWeight, XContentBuilder builder) throws IOException { - builder.startObject("awareness"); + builder.startObject(AWARENESS); builder.startObject(wrrWeight.attributeName()); for (Map.Entry entry : wrrWeight.weights().entrySet()) { builder.field(entry.getKey(), entry.getValue()); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index e184bc4a5dc30..87efdc76d04bc 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -10,7 +10,10 @@ import java.util.ArrayList; import java.util.List; - +/** + * Weighted Round Robin Scheduling policy + * + */ public class WeightedRoundRobin { private List> entities; diff --git a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java new file mode 100644 index 0000000000000..a5f3b8a1ccefa --- /dev/null +++ b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java @@ -0,0 +1,37 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.metadata; + +import org.opensearch.cluster.routing.WRRWeights; +import org.opensearch.common.xcontent.XContentParser; +import org.opensearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.Map; + +public class WeightedRoundRobinRoutingMetadataTests extends AbstractXContentTestCase { + @Override + protected WeightedRoundRobinRoutingMetadata createTestInstance() { + Map weights = Map.of("a", "1", "b", "1", "c", "0"); + WRRWeights wrrWeights = new WRRWeights("zone", weights); + WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeights); + return wrrMetadata; + } + + @Override + protected WeightedRoundRobinRoutingMetadata doParseInstance(XContentParser parser) throws IOException { + return WeightedRoundRobinRoutingMetadata.fromXContent(parser); + } + + @Override + protected boolean supportsUnknownFields() { + return false; + } + +} From 3afb4e341e6a40bc534f90b63124592a75c50cf9 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 1 Sep 2022 15:35:30 +0530 Subject: [PATCH 07/55] Fix minor change related to shuffling wrr shard routings Signed-off-by: Anshu Agarwal --- .../org/opensearch/cluster/routing/IndexShardRoutingTable.java | 2 +- .../java/org/opensearch/cluster/routing/OperationRouting.java | 2 +- .../java/org/opensearch/cluster/routing/WeightedRoundRobin.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index a8ad49bd968e3..275afb6a31586 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -310,7 +310,7 @@ public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, Discovery orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); cache.getCache().put(new WRRShardsCache.Key(shardId), orderedActiveShards); } - ordered.addAll(orderedActiveShards); + ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); if (!allInitializingShards.isEmpty()) { List orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 9dd9f778fb660..4550a3a4b688d 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -223,7 +223,7 @@ public GroupShardsIterator searchShards( private void setWeightedRoundRobinAttributes(ClusterState clusterState, ClusterService clusterService) { WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterState.metadata() .custom(WeightedRoundRobinRoutingMetadata.TYPE); - this.isWeightedRoundRobinEnabled = weightedRoundRobinRoutingMetadata != null ? true : false; + this.isWeightedRoundRobinEnabled = weightedRoundRobinRoutingMetadata != null; if (this.isWeightedRoundRobinEnabled) { this.wrrWeights = weightedRoundRobinRoutingMetadata.getWrrWeight(); this.wrrShardsCache = getWrrShardsCache() != null ? getWrrShardsCache() : new WRRShardsCache(clusterService); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index 87efdc76d04bc..dd1966f1c6adb 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import java.util.List; + /** * Weighted Round Robin Scheduling policy * From d9e2b084e778b09a435edfa919d727c1c9cd6ab3 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 22 Aug 2022 16:45:58 +0530 Subject: [PATCH 08/55] Add PUT api for updating weighted round robin shard routing weights Signed-off-by: Anshu Agarwal --- .../api/cluster.put_wrr_weights.json | 25 +++ .../org/opensearch/action/ActionModule.java | 7 +- .../wrr/put/ClusterPutWRRWeightsAction.java | 27 ++++ .../wrr/put/ClusterPutWRRWeightsRequest.java | 151 ++++++++++++++++++ .../ClusterPutWRRWeightsRequestBuilder.java | 33 ++++ .../wrr/put/ClusterPutWRRWeightsResponse.java | 30 ++++ .../wrr/put/TransportPutWRRWeightsAction.java | 94 +++++++++++ .../opensearch/client/ClusterAdminClient.java | 34 ++-- .../java/org/opensearch/client/Requests.java | 18 ++- .../client/support/AbstractClient.java | 19 +++ .../org/opensearch/cluster/ClusterModule.java | 9 +- .../routing/WRRShardRoutingService.java | 109 +++++++++++++ .../RestClusterPutWRRWeightsAction.java | 63 ++++++++ .../put/ClusterPutWRRWeightsRequestTests.java | 30 ++++ .../RestClusterPutWRRWeightsActionTests.java | 76 +++++++++ 15 files changed, 709 insertions(+), 16 deletions(-) create mode 100644 rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java create mode 100644 server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java create mode 100644 server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java create mode 100644 server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java create mode 100644 server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json new file mode 100644 index 0000000000000..e4373e9f612fa --- /dev/null +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json @@ -0,0 +1,25 @@ +{ + "cluster.put_decommission_awareness": { + "documentation": { + "url": "TBA", + "description": "TBA" + }, + "stability": "experimental", + "url": { + "paths": [ + { + "path": "/_cluster/routing/awareness/{attribute}/weights", + "methods": [ + "PUT" + ], + "parts": { + "attribute": { + "type": "string", + "description": "Awareness attribute name" + } + } + } + ] + } + } +} diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 74be544123d9f..800d00bac9135 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -79,6 +79,8 @@ import org.opensearch.action.admin.cluster.settings.TransportClusterUpdateSettingsAction; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsAction; import org.opensearch.action.admin.cluster.shards.TransportClusterSearchShardsAction; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsAction; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.TransportPutWRRWeightsAction; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.clone.TransportCloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotAction; @@ -296,6 +298,7 @@ import org.opensearch.rest.action.admin.cluster.RestClusterAllocationExplainAction; import org.opensearch.rest.action.admin.cluster.RestClusterGetSettingsAction; import org.opensearch.rest.action.admin.cluster.RestClusterHealthAction; +import org.opensearch.rest.action.admin.cluster.RestClusterPutWRRWeightsAction; import org.opensearch.rest.action.admin.cluster.RestClusterRerouteAction; import org.opensearch.rest.action.admin.cluster.RestClusterSearchShardsAction; import org.opensearch.rest.action.admin.cluster.RestClusterStateAction; @@ -528,6 +531,7 @@ public void reg ) { register(new ActionHandler<>(action, transportAction, supportTransportActions)); } + } ActionRegistry actions = new ActionRegistry(); @@ -562,7 +566,7 @@ public void reg actions.register(CloneSnapshotAction.INSTANCE, TransportCloneSnapshotAction.class); actions.register(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class); actions.register(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class); - + actions.register(ClusterPutWRRWeightsAction.INSTANCE, TransportPutWRRWeightsAction.class); actions.register(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class); actions.register(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class); actions.register(IndicesShardStoresAction.INSTANCE, TransportIndicesShardStoresAction.class); @@ -745,6 +749,7 @@ public void initRestHandlers(Supplier nodesInCluster) { registerHandler.accept(new RestCloseIndexAction()); registerHandler.accept(new RestOpenIndexAction()); registerHandler.accept(new RestAddIndexBlockAction()); + registerHandler.accept(new RestClusterPutWRRWeightsAction()); registerHandler.accept(new RestUpdateSettingsAction()); registerHandler.accept(new RestGetSettingsAction()); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java new file mode 100644 index 0000000000000..08a46dacf41bf --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; + +import org.opensearch.action.ActionType; + +/** + * Action to update weights for weighted round-robin shard routing policy. + * + * @opensearch.internal + */ +public final class ClusterPutWRRWeightsAction extends ActionType { + + public static final ClusterPutWRRWeightsAction INSTANCE = new ClusterPutWRRWeightsAction(); + public static final String NAME = "cluster:admin/routing/awareness/weights/put"; + + private ClusterPutWRRWeightsAction() { + super(NAME, ClusterPutWRRWeightsResponse::new); + } + +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java new file mode 100644 index 0000000000000..46ca8ead448e5 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java @@ -0,0 +1,151 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; + +import org.opensearch.OpenSearchGenerationException; +import org.opensearch.OpenSearchParseException; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.action.support.clustermanager.ClusterManagerNodeRequest; +import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.common.bytes.BytesReference; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.NamedXContentRegistry; +import org.opensearch.common.xcontent.XContentBuilder; +import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentParser; +import org.opensearch.common.xcontent.XContentType; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.opensearch.action.ValidateActions.addValidationError; + +/** + * Request to update weights for weighted round-robin shard routing policy. + * + * @opensearch.internal + */ +public class ClusterPutWRRWeightsRequest extends ClusterManagerNodeRequest { + + private WRRWeight wrrWeight; + private String attributeName; + + public WRRWeight wrrWeight() { + return wrrWeight; + } + + public ClusterPutWRRWeightsRequest wrrWeight(WRRWeight wrrWeight) { + this.wrrWeight = wrrWeight; + return this; + } + + public void attributeName(String attributeName) { + this.attributeName = attributeName; + } + + public ClusterPutWRRWeightsRequest(StreamInput in) throws IOException { + super(in); + wrrWeight = new WRRWeight(in); + } + + public ClusterPutWRRWeightsRequest() { + + } + + public ClusterPutWRRWeightsRequest setWRRWeight(Map source) { + try { + if (source.isEmpty()) { + throw new OpenSearchParseException(("Empty request body")); + } + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.map(source); + return setWRRWeight(BytesReference.bytes(builder), builder.contentType()); + } catch (IOException e) { + throw new OpenSearchGenerationException("Failed to generate [" + source + "]", e); + } + } + + public ClusterPutWRRWeightsRequest setWRRWeight(BytesReference source, XContentType contentType) { + try ( + XContentParser parser = XContentHelper.createParser( + NamedXContentRegistry.EMPTY, + DeprecationHandler.THROW_UNSUPPORTED_OPERATION, + source, + contentType + ) + ) { + String attrValue = null; + Map weights = new HashMap<>(); + Object attrWeight = null; + XContentParser.Token token; + // move to the first alias + parser.nextToken(); + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + attrValue = parser.currentName(); + } else if (token == XContentParser.Token.VALUE_STRING) { + attrWeight = parser.text(); + weights.put(attrValue, attrWeight); + } else { + throw new OpenSearchParseException("failed to parse wrr request attribute [{}], unknown type", attrWeight); + } + } + this.wrrWeight = new WRRWeight(this.attributeName, weights); + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return this; + } + + @Override + public ActionRequestValidationException validate() { + ActionRequestValidationException validationException = null; + if (wrrWeight == null) { + validationException = addValidationError("Weights are missing", validationException); + } + int countValueWithZeroWeights = 0; + for (Object value : wrrWeight.weights().values()) { + if (value.toString().equals("0")) { + countValueWithZeroWeights++; + } + } + if (countValueWithZeroWeights > 1) { + validationException = addValidationError(("More than one value has weight set as 0 "), validationException); + } + + return validationException; + } + + /** + * + * @param source weights definition from request body + * @return this request + */ + public ClusterPutWRRWeightsRequest source(Map source) { + setWRRWeight(source); + return this; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + wrrWeight.writeTo(out); + } + + @Override + public String toString() { + return "ClusterPutWRRWeightsRequest{" + "wrrWeight= " + wrrWeight.toString() + "}"; + } + +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java new file mode 100644 index 0000000000000..4ef185231bac2 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; + +import org.opensearch.action.support.clustermanager.ClusterManagerNodeOperationRequestBuilder; +import org.opensearch.client.OpenSearchClient; +import org.opensearch.cluster.routing.WRRWeight; + +/** + * Request builder to update weights for weighted round-robin shard routing policy. + * + * @opensearch.internal + */ +public class ClusterPutWRRWeightsRequestBuilder extends ClusterManagerNodeOperationRequestBuilder< + ClusterPutWRRWeightsRequest, + ClusterPutWRRWeightsResponse, + ClusterPutWRRWeightsRequestBuilder> { + public ClusterPutWRRWeightsRequestBuilder(OpenSearchClient client, ClusterPutWRRWeightsAction action) { + super(client, action, new ClusterPutWRRWeightsRequest()); + } + + public ClusterPutWRRWeightsRequestBuilder setWRRWeights(WRRWeight wrrWeight) { + request.wrrWeight(wrrWeight); + return this; + } + +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java new file mode 100644 index 0000000000000..cc90c34b086d5 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; + +import org.opensearch.action.support.master.AcknowledgedResponse; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.xcontent.ToXContentObject; + +import java.io.IOException; + +/** + * Response from updating weights for weighted round-robin search routing policy. + * + * @opensearch.internal + */ +public class ClusterPutWRRWeightsResponse extends AcknowledgedResponse implements ToXContentObject { + public ClusterPutWRRWeightsResponse(boolean acknowledged) { + super(acknowledged); + } + + public ClusterPutWRRWeightsResponse(StreamInput in) throws IOException { + super(in); + } +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java new file mode 100644 index 0000000000000..880558bfd6a2e --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java @@ -0,0 +1,94 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.action.ActionListener; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.clustermanager.TransportClusterManagerNodeAction; +import org.opensearch.cluster.ClusterState; +import org.opensearch.cluster.block.ClusterBlockException; +import org.opensearch.cluster.metadata.IndexNameExpressionResolver; +import org.opensearch.cluster.routing.WRRShardRoutingService; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.inject.Inject; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.threadpool.ThreadPool; +import org.opensearch.transport.TransportService; + +import java.io.IOException; + +/** + * Transport action for updating weights for weighted round-robin search routing policy + * + * @opensearch.internal + */ +public class TransportPutWRRWeightsAction extends TransportClusterManagerNodeAction< + ClusterPutWRRWeightsRequest, + ClusterPutWRRWeightsResponse> { + + private final WRRShardRoutingService wrrShardRoutingService; + + @Inject + public TransportPutWRRWeightsAction( + TransportService transportService, + ClusterService clusterService, + WRRShardRoutingService wrrShardRoutingService, + ThreadPool threadPool, + ActionFilters actionFilters, + IndexNameExpressionResolver indexNameExpressionResolver + ) { + super( + ClusterPutWRRWeightsAction.NAME, + transportService, + clusterService, + threadPool, + actionFilters, + ClusterPutWRRWeightsRequest::new, + indexNameExpressionResolver + ); + this.wrrShardRoutingService = wrrShardRoutingService; + } + + @Override + protected String executor() { + // TODO: Check threadpool to use?? + return ThreadPool.Names.MANAGEMENT; + } + + @Override + protected ClusterPutWRRWeightsResponse read(StreamInput in) throws IOException { + return new ClusterPutWRRWeightsResponse(in); + } + + @Override + protected void clusterManagerOperation( + ClusterPutWRRWeightsRequest request, + ClusterState state, + ActionListener listener + ) throws Exception { + + wrrShardRoutingService.registerWRRWeightsMetadata( + request, + ActionListener.delegateFailure( + listener, + (delegatedListener, response) -> { + delegatedListener.onResponse(new ClusterPutWRRWeightsResponse(response.isAcknowledged())); + } + ) + ); + } + + @Override + protected ClusterBlockException checkBlock(ClusterPutWRRWeightsRequest request, ClusterState state) { + return null; + } + +} diff --git a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java index 7a7b98bf724f6..3372071d993be 100644 --- a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java +++ b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java @@ -86,6 +86,9 @@ import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequestBuilder; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequestBuilder; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsResponse; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequestBuilder; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; @@ -140,9 +143,8 @@ /** * Administrative actions/operations against indices. * - * @see AdminClient#cluster() - * * @opensearch.internal + * @see AdminClient#cluster() */ public interface ClusterAdminClient extends OpenSearchClient { @@ -298,8 +300,7 @@ public interface ClusterAdminClient extends OpenSearchClient { * sampled for the node ids specified in the request. Nodes usage of the * cluster. * - * @param request - * The nodes usage request + * @param request The nodes usage request * @return The result future * @see org.opensearch.client.Requests#nodesUsageRequest(String...) */ @@ -308,10 +309,8 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Nodes usage of the cluster. * - * @param request - * The nodes usage request - * @param listener - * A listener to be notified with a result + * @param request The nodes usage request + * @param listener A listener to be notified with a result * @see org.opensearch.client.Requests#nodesUsageRequest(String...) */ void nodesUsage(NodesUsageRequest request, ActionListener listener); @@ -324,7 +323,6 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Returns top N hot-threads samples per node. The hot-threads are only * sampled for the node ids specified in the request. - * */ ActionFuture nodesHotThreads(NodesHotThreadsRequest request); @@ -375,7 +373,7 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Get a task. * - * @param request the request + * @param request the request * @param listener A listener to be notified with the result * @see org.opensearch.client.Requests#getTaskRequest() */ @@ -791,4 +789,20 @@ public interface ClusterAdminClient extends OpenSearchClient { * Delete specified dangling indices. */ ActionFuture deleteDanglingIndex(DeleteDanglingIndexRequest request); + + /** + * Updates weights for weighted round-robin search routing policy. + */ + ActionFuture putWRRWeights(ClusterPutWRRWeightsRequest request); + + /** + * Updates weights for weighted round-robin search routing policy. + */ + void putWRRWeights(ClusterPutWRRWeightsRequest request, ActionListener listener); + + /** + * Updates weights for weighted round-robin search routing policy. + */ + ClusterPutWRRWeightsRequestBuilder prepareWRRWeights(); + } diff --git a/server/src/main/java/org/opensearch/client/Requests.java b/server/src/main/java/org/opensearch/client/Requests.java index b04de7830a780..527ea3ae6524c 100644 --- a/server/src/main/java/org/opensearch/client/Requests.java +++ b/server/src/main/java/org/opensearch/client/Requests.java @@ -47,6 +47,7 @@ import org.opensearch.action.admin.cluster.reroute.ClusterRerouteRequest; import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; @@ -170,6 +171,7 @@ public static IndicesSegmentsRequest indicesSegmentsRequest(String... indices) { /** * Creates an indices shard stores info request. + * * @param indices The indices to get shard store information on * @return The indices shard stores request * @see org.opensearch.client.IndicesAdminClient#shardStores(IndicesShardStoresRequest) @@ -397,8 +399,7 @@ public static NodesStatsRequest nodesStatsRequest(String... nodesIds) { * Creates a nodes usage request against one or more nodes. Pass * {@code null} or an empty array for all nodes. * - * @param nodesIds - * The nodes ids to get the usage for + * @param nodesIds The nodes ids to get the usage for * @return The nodes usage request * @see org.opensearch.client.ClusterAdminClient#nodesUsage(NodesUsageRequest) */ @@ -540,7 +541,7 @@ public static DeleteSnapshotRequest deleteSnapshotRequest(String repository, Str } /** - * Get status of snapshots + * Get status of snapshots * * @param repository repository name * @return snapshot status request @@ -548,4 +549,15 @@ public static DeleteSnapshotRequest deleteSnapshotRequest(String repository, Str public static SnapshotsStatusRequest snapshotsStatusRequest(String repository) { return new SnapshotsStatusRequest(repository); } + + /** + * Updates weights for weighted round-robin search routing policy + * + * @return update weight request + */ + public static ClusterPutWRRWeightsRequest putWRRWEightsRequest() { + return new ClusterPutWRRWeightsRequest(); + } + + } diff --git a/server/src/main/java/org/opensearch/client/support/AbstractClient.java b/server/src/main/java/org/opensearch/client/support/AbstractClient.java index bc80a2ba92bf8..eb45b2efadaff 100644 --- a/server/src/main/java/org/opensearch/client/support/AbstractClient.java +++ b/server/src/main/java/org/opensearch/client/support/AbstractClient.java @@ -110,6 +110,10 @@ import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequestBuilder; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsAction; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequestBuilder; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsResponse; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequestBuilder; @@ -1264,6 +1268,21 @@ public ActionFuture deleteDanglingIndex(DeleteDanglingInde return execute(DeleteDanglingIndexAction.INSTANCE, request); } + @Override + public ActionFuture putWRRWeights(ClusterPutWRRWeightsRequest request) { + return execute(ClusterPutWRRWeightsAction.INSTANCE, request); + } + + @Override + public void putWRRWeights(ClusterPutWRRWeightsRequest request, ActionListener listener) { + execute(ClusterPutWRRWeightsAction.INSTANCE, request, listener); + } + + @Override + public ClusterPutWRRWeightsRequestBuilder prepareWRRWeights() { + return new ClusterPutWRRWeightsRequestBuilder(this, ClusterPutWRRWeightsAction.INSTANCE); + } + @Override public void deleteDanglingIndex(DeleteDanglingIndexRequest request, ActionListener listener) { execute(DeleteDanglingIndexAction.INSTANCE, request, listener); diff --git a/server/src/main/java/org/opensearch/cluster/ClusterModule.java b/server/src/main/java/org/opensearch/cluster/ClusterModule.java index 99a342eaeb5ed..dcfe0925301b3 100644 --- a/server/src/main/java/org/opensearch/cluster/ClusterModule.java +++ b/server/src/main/java/org/opensearch/cluster/ClusterModule.java @@ -325,7 +325,10 @@ public IndexNameExpressionResolver getIndexNameExpressionResolver() { } // TODO: this is public so allocation benchmark can access the default deciders...can we do that in another way? - /** Return a new {@link AllocationDecider} instance with builtin deciders as well as those from plugins. */ + + /** + * Return a new {@link AllocationDecider} instance with builtin deciders as well as those from plugins. + */ public static Collection createAllocationDeciders( Settings settings, ClusterSettings clusterSettings, @@ -359,7 +362,9 @@ public static Collection createAllocationDeciders( return deciders.values(); } - /** Add the given allocation decider to the given deciders collection, erroring if the class name is already used. */ + /** + * Add the given allocation decider to the given deciders collection, erroring if the class name is already used. + */ private static void addAllocationDecider(Map deciders, AllocationDecider decider) { if (deciders.put(decider.getClass(), decider) != null) { throw new IllegalArgumentException("Cannot specify allocation decider [" + decider.getClass().getName() + "] twice"); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java new file mode 100644 index 0000000000000..ea7fc5647d25a --- /dev/null +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java @@ -0,0 +1,109 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.routing; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.opensearch.action.ActionListener; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.cluster.ClusterChangedEvent; +import org.opensearch.cluster.ClusterState; +import org.opensearch.cluster.ClusterStateApplier; +import org.opensearch.cluster.ClusterStateUpdateTask; +import org.opensearch.cluster.ack.ClusterStateUpdateResponse; +import org.opensearch.cluster.metadata.Metadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.Priority; +import org.opensearch.common.component.AbstractLifecycleComponent; +import org.opensearch.common.inject.Inject; + +import org.opensearch.threadpool.ThreadPool; + +import java.io.IOException; + +public class WRRShardRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { + private static final Logger logger = LogManager.getLogger(WRRShardRoutingService.class); + + private final ClusterService clusterService; + + private final ThreadPool threadPool; + + @Inject + public WRRShardRoutingService(ClusterService clusterService, ThreadPool threadPool) { + this.clusterService = clusterService; + this.threadPool = threadPool; + } + + public void registerWRRWeightsMetadata( + final ClusterPutWRRWeightsRequest request, + final ActionListener listener + ) { + final WeightedRoundRobinMetadata newWRRWeightsMetadata = new WeightedRoundRobinMetadata(request.wrrWeight()); + clusterService.submitStateUpdateTask("update_wrr_weights", new ClusterStateUpdateTask(Priority.URGENT) { + @Override + public ClusterState execute(ClusterState currentState) { + Metadata metadata = currentState.metadata(); + Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata()); + WeightedRoundRobinMetadata wrrWeights = metadata.custom(WeightedRoundRobinMetadata.TYPE); + if (wrrWeights == null) { + logger.info("put wrr weights [{}]", request.wrrWeight()); + wrrWeights = new WeightedRoundRobinMetadata(request.wrrWeight()); + } else { + WeightedRoundRobinMetadata changedMetadata = new WeightedRoundRobinMetadata(new WRRWeight(null, null)); + if (!checkIfSameWeightsInMetadata(newWRRWeightsMetadata, wrrWeights)) { + changedMetadata.setWrrWeight(newWRRWeightsMetadata.getWrrWeight()); + } else { + return currentState; + } + wrrWeights = new WeightedRoundRobinMetadata(changedMetadata.getWrrWeight()); + } + mdBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrWeights); + return ClusterState.builder(currentState).metadata(mdBuilder).build(); + } + + @Override + public void onFailure(String source, Exception e) { + logger.warn(() -> new ParameterizedMessage("failed to update cluster state for wrr attributes [{}]", e)); + listener.onFailure(e); + } + + @Override + public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { + logger.info("Cluster wrr weights metadata change is processed by all the nodes"); + listener.onResponse(new ClusterStateUpdateResponse(true)); + } + }); + } + + private boolean checkIfSameWeightsInMetadata( + WeightedRoundRobinMetadata newWRRWeightsMetadata, + WeightedRoundRobinMetadata oldWRRWeightsMetadata + ) { + if (newWRRWeightsMetadata.getWrrWeight().equals(oldWRRWeightsMetadata.getWrrWeight())) { + return true; + } + return false; + } + + @Override + public void applyClusterState(ClusterChangedEvent event) { + logger.info("Applying new cluster state with empty function called"); + } + + @Override + protected void doStart() {} + + @Override + protected void doStop() {} + + @Override + protected void doClose() throws IOException {} +} diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java new file mode 100644 index 0000000000000..65c80fb00d506 --- /dev/null +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.rest.action.admin.cluster; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.client.Requests; +import org.opensearch.client.node.NodeClient; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; + +import java.io.IOException; +import java.util.List; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.PUT; + +/** + * Update Weighted Round Robin based shard routing weights + * + * @opensearch.api + * + */ +public class RestClusterPutWRRWeightsAction extends BaseRestHandler { + + private static final Logger logger = LogManager.getLogger(RestClusterPutWRRWeightsAction.class); + + @Override + public List routes() { + return singletonList(new Route(PUT, "/_cluster/routing/awareness/{attribute}/weights")); + } + + @Override + public String getName() { + return "put_wrrweights_action"; + } + + @Override + protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + ClusterPutWRRWeightsRequest putWRRWeightsRequest = createRequest(request); + return channel -> client.admin().cluster().putWRRWeights(putWRRWeightsRequest, new RestToXContentListener<>(channel)); + } + + public static ClusterPutWRRWeightsRequest createRequest(RestRequest request) throws IOException { + ClusterPutWRRWeightsRequest putWRRWeightsRequest = Requests.putWRRWEightsRequest(); + String attributeName = null; + if (request.hasParam("attribute")) { + attributeName = request.param("attribute"); + } + putWRRWeightsRequest.attributeName(attributeName); + request.applyContentParser(p -> putWRRWeightsRequest.source(p.mapStrings())); + return putWRRWeightsRequest; + } + +} diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java new file mode 100644 index 0000000000000..ee365a695763e --- /dev/null +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; + +import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.common.bytes.BytesArray; +import org.opensearch.common.xcontent.XContentType; +import org.opensearch.test.OpenSearchTestCase; + +import java.util.Map; + +public class ClusterPutWRRWeightsRequestTests extends OpenSearchTestCase { + + public void testSetWRRWeight() { + String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; + ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + Map weights = Map.of("us-east-1a", "1", "us-east-1b", "1", "us-east-1c", "0"); + WRRWeight wrrWeight = new WRRWeight("zone", weights); + request.attributeName("zone"); + request = request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + assertEquals(request.wrrWeight(), wrrWeight); + } + +} diff --git a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java new file mode 100644 index 0000000000000..d7092f9c49b42 --- /dev/null +++ b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.rest.action.admin.cluster; + +import com.fasterxml.jackson.core.JsonParseException; +import org.junit.Before; +import org.opensearch.OpenSearchParseException; +import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.common.bytes.BytesArray; +import org.opensearch.common.xcontent.XContentType; +import org.opensearch.rest.RestRequest; +import org.opensearch.test.rest.FakeRestRequest; +import org.opensearch.test.rest.RestActionTestCase; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.singletonMap; + +public class RestClusterPutWRRWeightsActionTests extends RestActionTestCase { + private RestClusterPutWRRWeightsAction action; + + @Before + public void setupAction() { + action = new RestClusterPutWRRWeightsAction(); + controller().registerHandler(action); + } + + public void testCreateRequest_SupportedRequestBody() throws IOException { + String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; + RestRequest restRequest = buildRestRequest(req); + ClusterPutWRRWeightsRequest clusterPutWRRWeightsRequest = RestClusterPutWRRWeightsAction.createRequest(restRequest); + assertEquals("zone", clusterPutWRRWeightsRequest.wrrWeight().attributeName()); + assertNotNull(clusterPutWRRWeightsRequest.wrrWeight().weights()); + assertEquals("1", clusterPutWRRWeightsRequest.wrrWeight().weights().get("us-east-1c")); + assertEquals("1", clusterPutWRRWeightsRequest.wrrWeight().weights().get("us-east-1d")); + assertEquals("0", clusterPutWRRWeightsRequest.wrrWeight().weights().get("us-east-1a")); + } + + public void testCreateRequest_UnsupportedRequestBody() throws IOException { + Map params = new HashMap<>(); + String req = "[\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"]"; + RestRequest restRequest = buildRestRequest(req); + assertThrows(OpenSearchParseException.class, () -> RestClusterPutWRRWeightsAction.createRequest(restRequest)); + } + + public void testCreateRequest_MalformedRequestBody() throws IOException { + Map params = new HashMap<>(); + + String req = "{\"us-east-1c\" : \"1\" \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; + RestRequest restRequest = buildRestRequest(req); + assertThrows(JsonParseException.class, () -> RestClusterPutWRRWeightsAction.createRequest(restRequest)); + } + + public void testCreateRequest_EmptyRequestBody() throws IOException { + String req = "{}"; + RestRequest restRequest = buildRestRequest(req); + assertThrows(OpenSearchParseException.class, () -> RestClusterPutWRRWeightsAction.createRequest(restRequest)); + } + + private RestRequest buildRestRequest(String content) { + return new FakeRestRequest.Builder(xContentRegistry()).withMethod(RestRequest.Method.PUT) + .withPath("/_cluster/routing/awareness/zone/weights") + .withParams(singletonMap("attribute", "zone")) + .withContent(new BytesArray(content), XContentType.JSON) + .build(); + } + +} From c3b847a0b422df7de781e7731ca118938a1fd0c3 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 29 Aug 2022 18:16:49 +0530 Subject: [PATCH 09/55] Add more validations for request body for put wrr weights Incorporate review comments and more UTs Signed-off-by: Anshu Agarwal --- .../api/cluster.put_wrr_weights.json | 6 +- .../wrr/put/ClusterPutWRRWeightsRequest.java | 46 +++++++++----- .../ClusterPutWRRWeightsRequestBuilder.java | 4 +- .../wrr/put/TransportPutWRRWeightsAction.java | 34 ++++++++++- .../java/org/opensearch/client/Requests.java | 3 +- .../WeightedRoundRobinRoutingMetadata.java | 13 ++-- .../cluster/routing/OperationRouting.java | 5 +- .../routing/WRRShardRoutingService.java | 2 +- .../RestClusterPutWRRWeightsAction.java | 4 +- .../put/ClusterPutWRRWeightsRequestTests.java | 60 ++++++++++++++++++- 10 files changed, 136 insertions(+), 41 deletions(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json index e4373e9f612fa..c8242dd8887cc 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json @@ -1,10 +1,10 @@ { - "cluster.put_decommission_awareness": { + "cluster.put_wrr_weights": { "documentation": { - "url": "TBA", + "url": "http://TBA", "description": "TBA" }, - "stability": "experimental", + "stability": "stable", "url": { "paths": [ { diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java index 46ca8ead448e5..2dbce86282d21 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java @@ -8,11 +8,13 @@ package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.opensearch.OpenSearchGenerationException; import org.opensearch.OpenSearchParseException; import org.opensearch.action.ActionRequestValidationException; import org.opensearch.action.support.clustermanager.ClusterManagerNodeRequest; -import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.cluster.routing.WRRWeights; import org.opensearch.common.bytes.BytesReference; import org.opensearch.common.io.stream.StreamInput; import org.opensearch.common.io.stream.StreamOutput; @@ -36,15 +38,16 @@ * @opensearch.internal */ public class ClusterPutWRRWeightsRequest extends ClusterManagerNodeRequest { + private static final Logger logger = LogManager.getLogger(ClusterPutWRRWeightsRequest.class); - private WRRWeight wrrWeight; + private WRRWeights wrrWeight; private String attributeName; - public WRRWeight wrrWeight() { + public WRRWeights wrrWeight() { return wrrWeight; } - public ClusterPutWRRWeightsRequest wrrWeight(WRRWeight wrrWeight) { + public ClusterPutWRRWeightsRequest wrrWeight(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; return this; } @@ -55,27 +58,27 @@ public void attributeName(String attributeName) { public ClusterPutWRRWeightsRequest(StreamInput in) throws IOException { super(in); - wrrWeight = new WRRWeight(in); + wrrWeight = new WRRWeights(in); } public ClusterPutWRRWeightsRequest() { } - public ClusterPutWRRWeightsRequest setWRRWeight(Map source) { + public void setWRRWeight(Map source) { try { if (source.isEmpty()) { throw new OpenSearchParseException(("Empty request body")); } XContentBuilder builder = XContentFactory.jsonBuilder(); builder.map(source); - return setWRRWeight(BytesReference.bytes(builder), builder.contentType()); + setWRRWeight(BytesReference.bytes(builder), builder.contentType()); } catch (IOException e) { throw new OpenSearchGenerationException("Failed to generate [" + source + "]", e); } } - public ClusterPutWRRWeightsRequest setWRRWeight(BytesReference source, XContentType contentType) { + public void setWRRWeight(BytesReference source, XContentType contentType) { try ( XContentParser parser = XContentHelper.createParser( NamedXContentRegistry.EMPTY, @@ -100,25 +103,37 @@ public ClusterPutWRRWeightsRequest setWRRWeight(BytesReference source, XContentT throw new OpenSearchParseException("failed to parse wrr request attribute [{}], unknown type", attrWeight); } } - this.wrrWeight = new WRRWeight(this.attributeName, weights); - return this; + this.wrrWeight = new WRRWeights(this.attributeName, weights); } catch (IOException e) { - e.printStackTrace(); + logger.error("error while parsing put wrr weights request object", e); } - return this; } @Override public ActionRequestValidationException validate() { ActionRequestValidationException validationException = null; if (wrrWeight == null) { + validationException = addValidationError("WRRWeights object is null", validationException); + } + if (wrrWeight.attributeName() == null || wrrWeight.attributeName().isEmpty()) { + validationException = addValidationError("Attribute name is missing", validationException); + } + if (wrrWeight.weights() == null || wrrWeight.weights().isEmpty()) { validationException = addValidationError("Weights are missing", validationException); } int countValueWithZeroWeights = 0; - for (Object value : wrrWeight.weights().values()) { - if (value.toString().equals("0")) { - countValueWithZeroWeights++; + int weight; + try { + for (Object value : wrrWeight.weights().values()) { + if (value == null) { + validationException = addValidationError(("Weight is null"), validationException); + } else { + weight = Integer.parseInt(value.toString()); + countValueWithZeroWeights = (weight == 0) ? countValueWithZeroWeights + 1 : countValueWithZeroWeights; + } } + } catch (NumberFormatException e) { + validationException = addValidationError(("Weight is non-integer"), validationException); } if (countValueWithZeroWeights > 1) { validationException = addValidationError(("More than one value has weight set as 0 "), validationException); @@ -128,7 +143,6 @@ public ActionRequestValidationException validate() { } /** - * * @param source weights definition from request body * @return this request */ diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java index 4ef185231bac2..60e164dc01c25 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java @@ -10,7 +10,7 @@ import org.opensearch.action.support.clustermanager.ClusterManagerNodeOperationRequestBuilder; import org.opensearch.client.OpenSearchClient; -import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.cluster.routing.WRRWeights; /** * Request builder to update weights for weighted round-robin shard routing policy. @@ -25,7 +25,7 @@ public ClusterPutWRRWeightsRequestBuilder(OpenSearchClient client, ClusterPutWRR super(client, action, new ClusterPutWRRWeightsRequest()); } - public ClusterPutWRRWeightsRequestBuilder setWRRWeights(WRRWeight wrrWeight) { + public ClusterPutWRRWeightsRequestBuilder setWRRWeights(WRRWeights wrrWeight) { request.wrrWeight(wrrWeight); return this; } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java index 880558bfd6a2e..4a282de28116b 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java @@ -8,8 +8,7 @@ package org.opensearch.action.admin.cluster.shards.routing.wrr.put; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.opensearch.OpenSearchException; import org.opensearch.action.ActionListener; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.clustermanager.TransportClusterManagerNodeAction; @@ -17,13 +16,17 @@ import org.opensearch.cluster.block.ClusterBlockException; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.cluster.routing.WRRShardRoutingService; +import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.inject.Inject; import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.Settings; import org.opensearch.threadpool.ThreadPool; import org.opensearch.transport.TransportService; import java.io.IOException; +import java.util.List; /** * Transport action for updating weights for weighted round-robin search routing policy @@ -36,8 +39,12 @@ public class TransportPutWRRWeightsAction extends TransportClusterManagerNodeAct private final WRRShardRoutingService wrrShardRoutingService; + private volatile List awarenessAttributes; + @Inject public TransportPutWRRWeightsAction( + Settings settings, + ClusterSettings clusterSettings, TransportService transportService, ClusterService clusterService, WRRShardRoutingService wrrShardRoutingService, @@ -55,6 +62,19 @@ public TransportPutWRRWeightsAction( indexNameExpressionResolver ); this.wrrShardRoutingService = wrrShardRoutingService; + this.awarenessAttributes = AwarenessAllocationDecider.CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTE_SETTING.get(settings); + clusterSettings.addSettingsUpdateConsumer( + AwarenessAllocationDecider.CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTE_SETTING, + this::setAwarenessAttributes + ); + } + + List getAwarenessAttributes() { + return awarenessAttributes; + } + + private void setAwarenessAttributes(List awarenessAttributes) { + this.awarenessAttributes = awarenessAttributes; } @Override @@ -74,7 +94,7 @@ protected void clusterManagerOperation( ClusterState state, ActionListener listener ) throws Exception { - + verifyAwarenessAttribute(request.wrrWeight().attributeName()); wrrShardRoutingService.registerWRRWeightsMetadata( request, ActionListener.delegateFailure( @@ -86,6 +106,14 @@ protected void clusterManagerOperation( ); } + private void verifyAwarenessAttribute(String attributeName) { + // Currently, only zone is supported + if (!getAwarenessAttributes().contains(attributeName) || !attributeName.equalsIgnoreCase("zone")) throw new OpenSearchException( + "invalid awareness attribute {} requested for updating wrr weights", + attributeName + ); + } + @Override protected ClusterBlockException checkBlock(ClusterPutWRRWeightsRequest request, ClusterState state) { return null; diff --git a/server/src/main/java/org/opensearch/client/Requests.java b/server/src/main/java/org/opensearch/client/Requests.java index 527ea3ae6524c..96e2f7d5fd76d 100644 --- a/server/src/main/java/org/opensearch/client/Requests.java +++ b/server/src/main/java/org/opensearch/client/Requests.java @@ -555,9 +555,8 @@ public static SnapshotsStatusRequest snapshotsStatusRequest(String repository) { * * @return update weight request */ - public static ClusterPutWRRWeightsRequest putWRRWEightsRequest() { + public static ClusterPutWRRWeightsRequest putWRRWeightsRequest() { return new ClusterPutWRRWeightsRequest(); } - } diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java index 9ed11cb31c4d0..82577c44ae6d4 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java @@ -42,9 +42,8 @@ public WRRWeights getWrrWeight() { return wrrWeight; } - public WeightedRoundRobinRoutingMetadata setWrrWeight(WRRWeights wrrWeight) { + public void setWrrWeight(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; - return this; } public WeightedRoundRobinRoutingMetadata(StreamInput in) throws IOException { @@ -89,19 +88,23 @@ public static WeightedRoundRobinRoutingMetadata fromXContent(XContentParser pars XContentParser.Token token; // move to the first alias parser.nextToken(); - String awarenessField = null; + String awarenessKeyword = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { - awarenessField = parser.currentName(); + // parses awareness object + awarenessKeyword = parser.currentName(); + // awareness object contains object with awareness attribute name and its details if (parser.nextToken() != XContentParser.Token.START_OBJECT) { - throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", awarenessField); + throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", awarenessKeyword); } while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { attributeName = parser.currentName(); + // awareness attribute object contain wrr weight details if (parser.nextToken() != XContentParser.Token.START_OBJECT) { throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", attributeName); } + // parse weights, corresponding attribute key and puts it in a map while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { attrKey = parser.currentName(); diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 4550a3a4b688d..b5db3fbfcce3e 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -81,12 +81,9 @@ public class OperationRouting { private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; - // reads value from cluster setting - private volatile boolean useWeightedRoundRobin; /** - * Reads value from cluster setting and cluster state to determine if weighted round-robin + * Reads value from cluster state to determine if weighted round-robin * search routing is enabled - * This is true if useWeightedRoundRobin=true and weights are set in cluster metadata. */ private volatile boolean isWeightedRoundRobinEnabled; diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java index ea7fc5647d25a..9e7d6f3be6f05 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java @@ -57,7 +57,7 @@ public ClusterState execute(ClusterState currentState) { logger.info("put wrr weights [{}]", request.wrrWeight()); wrrWeights = new WeightedRoundRobinMetadata(request.wrrWeight()); } else { - WeightedRoundRobinMetadata changedMetadata = new WeightedRoundRobinMetadata(new WRRWeight(null, null)); + WeightedRoundRobinMetadata changedMetadata = new WeightedRoundRobinMetadata(new WRRWeights(null, null)); if (!checkIfSameWeightsInMetadata(newWRRWeightsMetadata, wrrWeights)) { changedMetadata.setWrrWeight(newWRRWeightsMetadata.getWrrWeight()); } else { diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java index 65c80fb00d506..af71b95deaaf6 100644 --- a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java @@ -40,7 +40,7 @@ public List routes() { @Override public String getName() { - return "put_wrrweights_action"; + return "put_wrr_weights_action"; } @Override @@ -50,7 +50,7 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli } public static ClusterPutWRRWeightsRequest createRequest(RestRequest request) throws IOException { - ClusterPutWRRWeightsRequest putWRRWeightsRequest = Requests.putWRRWEightsRequest(); + ClusterPutWRRWeightsRequest putWRRWeightsRequest = Requests.putWRRWeightsRequest(); String attributeName = null; if (request.hasParam("attribute")) { attributeName = request.param("attribute"); diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java index ee365a695763e..3bc5917944a46 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java @@ -8,7 +8,8 @@ package org.opensearch.action.admin.cluster.shards.routing.wrr.put; -import org.opensearch.cluster.routing.WRRWeight; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.cluster.routing.WRRWeights; import org.opensearch.common.bytes.BytesArray; import org.opensearch.common.xcontent.XContentType; import org.opensearch.test.OpenSearchTestCase; @@ -21,10 +22,63 @@ public void testSetWRRWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); Map weights = Map.of("us-east-1a", "1", "us-east-1b", "1", "us-east-1c", "0"); - WRRWeight wrrWeight = new WRRWeight("zone", weights); + WRRWeights wrrWeight = new WRRWeights("zone", weights); request.attributeName("zone"); - request = request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); assertEquals(request.wrrWeight(), wrrWeight); } + public void testValidate_ValuesAreProper() { + String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; + ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + request.attributeName("zone"); + request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + ActionRequestValidationException actionRequestValidationException = request.validate(); + assertNull(actionRequestValidationException); + + } + + public void testValidate_TwoZonesWithZeroWeight() { + String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; + ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + request.attributeName("zone"); + request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + ActionRequestValidationException actionRequestValidationException = request.validate(); + assertNotNull(actionRequestValidationException); + assertTrue(actionRequestValidationException.getMessage().contains("More than one value has weight set as 0")); + + } + + public void testValidate_MissingWeights() { + String reqString = "{}"; + ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + request.attributeName("zone"); + request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + ActionRequestValidationException actionRequestValidationException = request.validate(); + assertNotNull(actionRequestValidationException); + assertTrue(actionRequestValidationException.getMessage().contains("Weights are missing")); + + } + + public void testValidate_AttributeMissing() { + String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; + ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + ActionRequestValidationException actionRequestValidationException = request.validate(); + assertNotNull(actionRequestValidationException); + assertTrue(actionRequestValidationException.getMessage().contains("Attribute name is missing")); + + } + + public void testValidate_NonIntegerWeights() { + String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"5.6\",\"us-east-1a\":\"1\"}"; + ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + request.attributeName("zone"); + request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + ActionRequestValidationException actionRequestValidationException = request.validate(); + assertNotNull(actionRequestValidationException); + assertTrue(actionRequestValidationException.getMessage().contains("Weight is non-integer")); + + } + } From 9cc2cd58658fbf6419a221a92d91bc566ee41e30 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 1 Sep 2022 17:05:40 +0530 Subject: [PATCH 10/55] Update thread pool executor and do code refactoring Signed-off-by: Anshu Agarwal --- CHANGELOG.md | 3 ++- .../client/RestHighLevelClientTests.java | 3 ++- .../wrr/put/TransportPutWRRWeightsAction.java | 3 +-- .../WeightedRoundRobinRoutingMetadata.java | 2 +- .../routing/WRRShardRoutingService.java | 26 +++++++++---------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f47f4464b670a..9f49de5139aa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Use RemoteSegmentStoreDirectory instead of RemoteDirectory ([#4240](https://github.com/opensearch-project/OpenSearch/pull/4240)) - Plugin ZIP publication groupId value is configurable ([#4156](https://github.com/opensearch-project/OpenSearch/pull/4156)) - Weighted round-robin scheduling policy for shard coordination traffic ([#4241](https://github.com/opensearch-project/OpenSearch/pull/4241)) +- PUT api to update weights for weighted round-robin scheduling ([#4272](https://github.com/opensearch-project/OpenSearch/pull/4272)) ### Deprecated @@ -30,7 +31,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Add timeout on Mockito.verify to reduce flakyness in testReplicationOnDone test([#4314](https://github.com/opensearch-project/OpenSearch/pull/4314)) - Commit workflow for dependabot changelog helper ([#4331](https://github.com/opensearch-project/OpenSearch/pull/4331)) - Fixed cancellation of segment replication events ([#4225](https://github.com/opensearch-project/OpenSearch/pull/4225)) -- Bugs for dependabot changelog verifier workflow ([#4364](https://github.com/opensearch-project/OpenSearch/pull/4364)) +- Bugs for dependabot changelog verifier workflow ([#4364](https://github.com/opensearch-project/OpenSearch/pull/4364)) ### Security - CVE-2022-25857 org.yaml:snakeyaml DOS vulnerability ([#4341](https://github.com/opensearch-project/OpenSearch/pull/4341)) diff --git a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java index cdd63743f2644..bba864bd62150 100644 --- a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java @@ -887,7 +887,8 @@ public void testApiNamingConventions() throws Exception { "nodes.usage", "nodes.reload_secure_settings", "search_shards", - "remote_store.restore", }; + "remote_store.restore", + "cluster.put_wrr_weights",}; List booleanReturnMethods = Arrays.asList("security.enable_user", "security.disable_user", "security.change_password"); Set deprecatedMethods = new HashSet<>(); deprecatedMethods.add("indices.force_merge"); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java index 4a282de28116b..6ac906ad133ce 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java @@ -79,8 +79,7 @@ private void setAwarenessAttributes(List awarenessAttributes) { @Override protected String executor() { - // TODO: Check threadpool to use?? - return ThreadPool.Names.MANAGEMENT; + return ThreadPool.Names.SAME; } @Override diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java index 82577c44ae6d4..d4d5f56ce44c9 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java @@ -42,7 +42,7 @@ public WRRWeights getWrrWeight() { return wrrWeight; } - public void setWrrWeight(WRRWeights wrrWeight) { + public void setWrrWeight(WRRWeights wrrWeight) { this.wrrWeight = wrrWeight; } diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java index 9e7d6f3be6f05..aa5ed72f79469 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java @@ -19,7 +19,7 @@ import org.opensearch.cluster.ClusterStateUpdateTask; import org.opensearch.cluster.ack.ClusterStateUpdateResponse; import org.opensearch.cluster.metadata.Metadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinMetadata; +import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Priority; import org.opensearch.common.component.AbstractLifecycleComponent; @@ -46,32 +46,34 @@ public void registerWRRWeightsMetadata( final ClusterPutWRRWeightsRequest request, final ActionListener listener ) { - final WeightedRoundRobinMetadata newWRRWeightsMetadata = new WeightedRoundRobinMetadata(request.wrrWeight()); + final WeightedRoundRobinRoutingMetadata newWRRWeightsMetadata = new WeightedRoundRobinRoutingMetadata(request.wrrWeight()); clusterService.submitStateUpdateTask("update_wrr_weights", new ClusterStateUpdateTask(Priority.URGENT) { @Override public ClusterState execute(ClusterState currentState) { Metadata metadata = currentState.metadata(); Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata()); - WeightedRoundRobinMetadata wrrWeights = metadata.custom(WeightedRoundRobinMetadata.TYPE); + WeightedRoundRobinRoutingMetadata wrrWeights = metadata.custom(WeightedRoundRobinRoutingMetadata.TYPE); if (wrrWeights == null) { logger.info("put wrr weights [{}]", request.wrrWeight()); - wrrWeights = new WeightedRoundRobinMetadata(request.wrrWeight()); + wrrWeights = new WeightedRoundRobinRoutingMetadata(request.wrrWeight()); } else { - WeightedRoundRobinMetadata changedMetadata = new WeightedRoundRobinMetadata(new WRRWeights(null, null)); + WeightedRoundRobinRoutingMetadata changedMetadata = new WeightedRoundRobinRoutingMetadata(new WRRWeights(null, null)); if (!checkIfSameWeightsInMetadata(newWRRWeightsMetadata, wrrWeights)) { + logger.info("updated wrr weights [{}] in metadata", request.wrrWeight()); changedMetadata.setWrrWeight(newWRRWeightsMetadata.getWrrWeight()); } else { return currentState; } - wrrWeights = new WeightedRoundRobinMetadata(changedMetadata.getWrrWeight()); + wrrWeights = new WeightedRoundRobinRoutingMetadata(changedMetadata.getWrrWeight()); } - mdBuilder.putCustom(WeightedRoundRobinMetadata.TYPE, wrrWeights); + mdBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrWeights); + logger.info("building cluster state with wrr weights [{}]", request.wrrWeight()); return ClusterState.builder(currentState).metadata(mdBuilder).build(); } @Override public void onFailure(String source, Exception e) { - logger.warn(() -> new ParameterizedMessage("failed to update cluster state for wrr attributes [{}]", e)); + logger.warn(() -> new ParameterizedMessage("failed to update cluster state for wrr weights [{}]", e)); listener.onFailure(e); } @@ -84,8 +86,8 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS } private boolean checkIfSameWeightsInMetadata( - WeightedRoundRobinMetadata newWRRWeightsMetadata, - WeightedRoundRobinMetadata oldWRRWeightsMetadata + WeightedRoundRobinRoutingMetadata newWRRWeightsMetadata, + WeightedRoundRobinRoutingMetadata oldWRRWeightsMetadata ) { if (newWRRWeightsMetadata.getWrrWeight().equals(oldWRRWeightsMetadata.getWrrWeight())) { return true; @@ -94,9 +96,7 @@ private boolean checkIfSameWeightsInMetadata( } @Override - public void applyClusterState(ClusterChangedEvent event) { - logger.info("Applying new cluster state with empty function called"); - } + public void applyClusterState(ClusterChangedEvent event) {} @Override protected void doStart() {} From f07a9add444a9c559ecf0c9bcee2eb9892f9e678 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 1 Sep 2022 17:26:21 +0530 Subject: [PATCH 11/55] Fix missing java doc build failure Signed-off-by: Anshu Agarwal --- .../opensearch/client/RestHighLevelClientTests.java | 2 +- .../cluster/shards/routing/wrr/put/package-info.java | 10 ++++++++++ .../cluster/routing/WRRShardRoutingService.java | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java diff --git a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java index bba864bd62150..003a188f5f8dd 100644 --- a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java @@ -888,7 +888,7 @@ public void testApiNamingConventions() throws Exception { "nodes.reload_secure_settings", "search_shards", "remote_store.restore", - "cluster.put_wrr_weights",}; + "cluster.put_wrr_weights", }; List booleanReturnMethods = Arrays.asList("security.enable_user", "security.disable_user", "security.change_password"); Set deprecatedMethods = new HashSet<>(); deprecatedMethods.add("indices.force_merge"); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java new file mode 100644 index 0000000000000..c7bccf97c2243 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** add/update weighted-round robin shard routing weights. */ +package org.opensearch.action.admin.cluster.shards.routing.wrr.put; diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java index aa5ed72f79469..53e3c441c021f 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java @@ -29,6 +29,9 @@ import java.io.IOException; +/** + * * Service responsible for updating cluster state metadata with wrr weights + */ public class WRRShardRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { private static final Logger logger = LogManager.getLogger(WRRShardRoutingService.class); From e12d24756675ce35c6dd53bafda41ae5d96ef6f4 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Fri, 2 Sep 2022 15:44:56 +0530 Subject: [PATCH 12/55] Throw ActionRequestValidationException on invalid awareness attribute Signed-off-by: Anshu Agarwal --- .../wrr/put/TransportPutWRRWeightsAction.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java index 6ac906ad133ce..525e28c5116a7 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java @@ -8,8 +8,8 @@ package org.opensearch.action.admin.cluster.shards.routing.wrr.put; -import org.opensearch.OpenSearchException; import org.opensearch.action.ActionListener; +import org.opensearch.action.ActionRequestValidationException; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.clustermanager.TransportClusterManagerNodeAction; import org.opensearch.cluster.ClusterState; @@ -28,6 +28,8 @@ import java.io.IOException; import java.util.List; +import static org.opensearch.action.ValidateActions.addValidationError; + /** * Transport action for updating weights for weighted round-robin search routing policy * @@ -107,10 +109,14 @@ protected void clusterManagerOperation( private void verifyAwarenessAttribute(String attributeName) { // Currently, only zone is supported - if (!getAwarenessAttributes().contains(attributeName) || !attributeName.equalsIgnoreCase("zone")) throw new OpenSearchException( - "invalid awareness attribute {} requested for updating wrr weights", - attributeName - ); + if (!getAwarenessAttributes().contains(attributeName) || !attributeName.equalsIgnoreCase("zone")) { + ActionRequestValidationException validationException = null; + validationException = addValidationError( + "invalid awareness attribute " + attributeName + " requested for " + "updating wrr weights", + validationException + ); + throw validationException; + } } @Override From 3aa6fbb522a17500074e707a8adc586047f4e498 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 7 Sep 2022 11:49:31 +0530 Subject: [PATCH 13/55] Add default weight 1 for zones with undefined weight Signed-off-by: Anshu Agarwal --- .../routing/IndexShardRoutingTable.java | 7 ++----- .../cluster/routing/OperationRoutingTests.java | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index 275afb6a31586..b219a7178e7e0 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -353,11 +353,8 @@ private List> calculateShardWeight( for (ShardRouting shard : shards) { DiscoveryNode node = nodes.get(shard.currentNodeId()); String attVal = node.getAttributes().get(wrrWeight.attributeName()); - // If weight for a zone is not defined, not considering shards from that zone - if (wrrWeight.weights().get(attVal) == null) { - continue; - } - Double weight = Double.parseDouble(wrrWeight.weights().get(attVal).toString()); + // If weight for a zone is not defined, considering it as 1 by default + Double weight = Double.parseDouble(wrrWeight.weights().getOrDefault(attVal, 1).toString()); weightedShards.add(new WeightedRoundRobin.Entity<>(weight, shard)); } return weightedShards; diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 9ee13e1190ed2..3115070480aa9 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -1022,13 +1022,17 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { selectedNodes.add(shardRouting.currentNodeId()); } } - // tests no nodes are assigned to nodes in zone c + boolean weighAwayNodesInUndefinedZone = true; + // tests no shards are assigned to nodes in zone c + // tests shards are assigned to nodes in zone b for (String nodeID : selectedNodes) { // shard from nodes in zone c is not selected since its weight is 0 assertFalse(nodeID.contains("c")); - // shard from nodes in zone b is not selected since its weight is not set - assertFalse(nodeID.contains("b")); + if (nodeID.contains("b")) { + weighAwayNodesInUndefinedZone = false; + } } + assertFalse(weighAwayNodesInUndefinedZone); selectedNodes = new HashSet<>(); setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); @@ -1056,12 +1060,16 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { } } // tests that no shards are assigned to zone with weight zero + // tests shards are assigned to nodes in zone c + weighAwayNodesInUndefinedZone = true; for (String nodeID : selectedNodes) { // shard from nodes in zone a is not selected since its weight is 0 assertFalse(nodeID.contains("a")); - // shard from nodes in zone c is not selected since its weight is not set - assertFalse(nodeID.contains("c")); + if (nodeID.contains("c")) { + weighAwayNodesInUndefinedZone = false; + } } + assertFalse(weighAwayNodesInUndefinedZone); IOUtils.close(clusterService); terminate(threadPool); } From 111236657a53f27415308d178a9f8dc20096b579 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 12 Sep 2022 19:30:48 +0530 Subject: [PATCH 14/55] Inject WRRShardsCache on node start Signed-off-by: Anshu Agarwal --- .../WeightedRoundRobinRoutingMetadata.java | 11 ++- .../routing/IndexShardRoutingTable.java | 6 +- .../cluster/routing/OperationRouting.java | 64 +++++-------- .../cluster/routing/WRRShardsCache.java | 31 +++++-- .../cluster/service/ClusterService.java | 3 +- .../main/java/org/opensearch/node/Node.java | 6 ++ .../routing/OperationRoutingTests.java | 89 +++++++++---------- .../structure/RoutingIteratorTests.java | 9 +- 8 files changed, 116 insertions(+), 103 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java index 9ed11cb31c4d0..b1baab52aaeb4 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java @@ -48,7 +48,10 @@ public WeightedRoundRobinRoutingMetadata setWrrWeight(WRRWeights wrrWeight) { } public WeightedRoundRobinRoutingMetadata(StreamInput in) throws IOException { - this.wrrWeight = new WRRWeights(in); + if (in.available() != 0) { + this.wrrWeight = new WRRWeights(in); + + } } public WeightedRoundRobinRoutingMetadata(WRRWeights wrrWeight) { @@ -73,7 +76,9 @@ public Version getMinimalSupportedVersion() { @Override public void writeTo(StreamOutput out) throws IOException { - wrrWeight.writeTo(out); + if (wrrWeight != null) { + wrrWeight.writeTo(out); + } } public static NamedDiff readDiffFrom(StreamInput in) throws IOException { @@ -113,8 +118,6 @@ public static WeightedRoundRobinRoutingMetadata fromXContent(XContentParser pars } } } - } else { - throw new OpenSearchParseException("failed to parse wrr metadata attribute [{}]", attributeName); } } wrrWeight = new WRRWeights(attributeName, weights); diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index b219a7178e7e0..d0e79f8efda2e 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -304,11 +304,11 @@ public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, Discovery final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); List orderedActiveShards; - if (cache.getCache().get(new WRRShardsCache.Key(shardId)) != null) { - orderedActiveShards = cache.getCache().get(new WRRShardsCache.Key(shardId)); + if (cache.get(new WRRShardsCache.Key(shardId)) != null) { + orderedActiveShards = cache.get(new WRRShardsCache.Key(shardId)); } else { orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); - cache.getCache().put(new WRRShardsCache.Key(shardId), orderedActiveShards); + cache.put(new WRRShardsCache.Key(shardId), orderedActiveShards); } ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 4550a3a4b688d..24b85d991bfda 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -81,32 +81,8 @@ public class OperationRouting { private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; - // reads value from cluster setting - private volatile boolean useWeightedRoundRobin; - /** - * Reads value from cluster setting and cluster state to determine if weighted round-robin - * search routing is enabled - * This is true if useWeightedRoundRobin=true and weights are set in cluster metadata. - */ - private volatile boolean isWeightedRoundRobinEnabled; - - private volatile WRRWeights wrrWeights; - - public WRRShardsCache getWrrShardsCache() { - return wrrShardsCache; - } - - private WRRShardsCache wrrShardsCache; - - public ClusterService getClusterService() { - return clusterService; - } - - public void setClusterService(ClusterService clusterService) { - this.clusterService = clusterService; - } - - private ClusterService clusterService; + public WRRShardsCache wrrShardsCache; + public ClusterService clusterService; public OperationRouting(Settings settings, ClusterSettings clusterSettings) { // whether to ignore awareness attributes when routing requests @@ -146,8 +122,18 @@ public boolean ignoreAwarenessAttributes() { return this.awarenessAttributes.isEmpty() || this.ignoreAwarenessAttr; } - public WRRWeights getWrrWeights() { - return wrrWeights; + @Inject + public void setClusterService(ClusterService clusterService) { + this.clusterService = clusterService; + } + + @Inject + public void setWrrShardsCache(WRRShardsCache wrrShardsCache) { + this.wrrShardsCache = wrrShardsCache; + } + + public WRRShardsCache getWrrShardsCache() { + return wrrShardsCache; } public ShardIterator indexShards(ClusterState clusterState, String index, String id, @Nullable String routing) { @@ -173,7 +159,6 @@ public ShardIterator getShards( public ShardIterator getShards(ClusterState clusterState, String index, int shardId, @Nullable String preference) { final IndexShardRoutingTable indexShard = clusterState.getRoutingTable().shardRoutingTable(index, shardId); - setWeightedRoundRobinAttributes(clusterState, getClusterService()); return preferenceActiveShardIterator( indexShard, clusterState.nodes().getLocalNodeId(), @@ -203,7 +188,6 @@ public GroupShardsIterator searchShards( ) { final Set shards = computeTargetedShards(clusterState, concreteIndices, routing); final Set set = new HashSet<>(shards.size()); - setWeightedRoundRobinAttributes(clusterState, getClusterService()); for (IndexShardRoutingTable shard : shards) { ShardIterator iterator = preferenceActiveShardIterator( shard, @@ -220,18 +204,18 @@ public GroupShardsIterator searchShards( return GroupShardsIterator.sortAndCreate(new ArrayList<>(set)); } - private void setWeightedRoundRobinAttributes(ClusterState clusterState, ClusterService clusterService) { - WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterState.metadata() + private boolean isWeightedRoundRobinEnabled() { + WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterService.state() + .metadata() .custom(WeightedRoundRobinRoutingMetadata.TYPE); - this.isWeightedRoundRobinEnabled = weightedRoundRobinRoutingMetadata != null; - if (this.isWeightedRoundRobinEnabled) { - this.wrrWeights = weightedRoundRobinRoutingMetadata.getWrrWeight(); - this.wrrShardsCache = getWrrShardsCache() != null ? getWrrShardsCache() : new WRRShardsCache(clusterService); - } + return weightedRoundRobinRoutingMetadata != null; } - private boolean isWeightedRoundRobinEnabled() { - return isWeightedRoundRobinEnabled; + private WRRWeights fetchWRRWeights() { + WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterService.state() + .metadata() + .custom(WeightedRoundRobinRoutingMetadata.TYPE); + return weightedRoundRobinRoutingMetadata.getWrrWeight(); } public static ShardIterator getShards(ClusterState clusterState, ShardId shardId) { @@ -352,7 +336,7 @@ private ShardIterator shardRoutings( @Nullable Map nodeCounts ) { if (isWeightedRoundRobinEnabled()) { - return indexShard.activeInitializingShardsWRR(getWrrWeights(), nodes, wrrShardsCache); + return indexShard.activeInitializingShardsWRR(fetchWRRWeights(), nodes, wrrShardsCache); } else if (ignoreAwarenessAttributes()) { if (useAdaptiveReplicaSelection) { return indexShard.activeInitializingShardsRankedIt(collectorService, nodeCounts); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java index 879f73a304c76..f78d56d182291 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java @@ -26,6 +26,7 @@ * * @opensearch.internal */ + public class WRRShardsCache implements Releasable, ClusterStateListener { private static final Logger logger = LogManager.getLogger(WRRShardsCache.class); @@ -41,16 +42,24 @@ public WRRShardsCache(ClusterService clusterService) { clusterService.addListener(this); } + public long hits() { + return cache.stats().getHits(); + } + + public long misses() { + return cache.stats().getMisses(); + } + + public long size() { + return cache.count(); + } + @Override public void close() { - logger.info("Invalidating WRRShardsCache on close"); + logger.debug("Invalidating WRRShardsCache on close"); cache.invalidateAll(); } - public Cache> getCache() { - return cache; - } - /** * Listens to cluster state change event and invalidate cache on such events * @@ -58,10 +67,18 @@ public Cache> getCache() { */ @Override public void clusterChanged(ClusterChangedEvent event) { - logger.info("Invalidating WRRShardsCache on ClusterChangedEvent"); + logger.debug("Invalidating WRRShardsCache on ClusterChangedEvent"); cache.invalidateAll(); } + public List get(Key k) { + return cache.get(k); + } + + public void put(Key key, List value) { + cache.put(key, value); + } + /** * Key for the WRRShardsCache * @@ -71,7 +88,6 @@ public static class Key { public final ShardId shardId; Key(ShardId shardId) { - this.shardId = shardId; } @@ -87,7 +103,6 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = shardId.hashCode(); - return result; } diff --git a/server/src/main/java/org/opensearch/cluster/service/ClusterService.java b/server/src/main/java/org/opensearch/cluster/service/ClusterService.java index 4a8bf9275389a..2d31aca0073bf 100644 --- a/server/src/main/java/org/opensearch/cluster/service/ClusterService.java +++ b/server/src/main/java/org/opensearch/cluster/service/ClusterService.java @@ -45,7 +45,9 @@ import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.cluster.routing.OperationRouting; import org.opensearch.cluster.routing.RerouteService; +import org.opensearch.cluster.routing.WRRShardsCache; import org.opensearch.common.component.AbstractLifecycleComponent; +import org.opensearch.common.inject.Inject; import org.opensearch.common.settings.ClusterSettings; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Setting.Property; @@ -108,7 +110,6 @@ public ClusterService( this.nodeName = Node.NODE_NAME_SETTING.get(settings); this.clusterManagerService = clusterManagerService; this.operationRouting = new OperationRouting(settings, clusterSettings); - this.operationRouting.setClusterService(this); this.clusterSettings = clusterSettings; this.clusterName = ClusterName.CLUSTER_NAME_SETTING.get(settings); // Add a no-op update consumer so changes are logged diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index 92e9815313fa0..6c76096721754 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -36,6 +36,8 @@ import org.apache.logging.log4j.Logger; import org.apache.lucene.util.Constants; import org.apache.lucene.util.SetOnce; +import org.opensearch.cluster.routing.OperationRouting; +import org.opensearch.cluster.routing.WRRShardsCache; import org.opensearch.common.util.FeatureFlags; import org.opensearch.cluster.routing.allocation.AwarenessReplicaBalance; import org.opensearch.index.IndexingPressureService; @@ -906,6 +908,7 @@ protected Node( ); resourcesToClose.add(persistentTasksClusterService); final PersistentTasksService persistentTasksService = new PersistentTasksService(clusterService, threadPool, client); + final WRRShardsCache wrrShardsCache = new WRRShardsCache(clusterService); modules.add(b -> { b.bind(Node.class).toInstance(this); @@ -949,6 +952,7 @@ protected Node( b.bind(SnapshotsInfoService.class).toInstance(snapshotsInfoService); b.bind(GatewayMetaState.class).toInstance(gatewayMetaState); b.bind(Discovery.class).toInstance(discoveryModule.getDiscovery()); + b.bind(WRRShardsCache.class).toInstance(wrrShardsCache); { processRecoverySettings(settingsModule.getClusterSettings(), recoverySettings); b.bind(PeerRecoverySourceService.class) @@ -986,6 +990,7 @@ protected Node( b.bind(ShardLimitValidator.class).toInstance(shardLimitValidator); b.bind(FsHealthService.class).toInstance(fsHealthService); b.bind(SystemIndices.class).toInstance(systemIndices); + b.bind(OperationRouting.class).toInstance(clusterService.operationRouting()); }); injector = modules.createInjector(); @@ -1246,6 +1251,7 @@ private Node stop() { injector.getInstance(GatewayService.class).stop(); injector.getInstance(SearchService.class).stop(); injector.getInstance(TransportService.class).stop(); + injector.getInstance(WRRShardsCache.class).close(); pluginLifecycleComponents.forEach(LifecycleComponent::stop); // we should stop this last since it waits for resources to get released diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 3115070480aa9..efca5e77b4823 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -596,6 +596,7 @@ public void testAdaptiveReplicaSelection() throws Exception { ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); + opRouting.setClusterService(clusterService); GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -700,7 +701,7 @@ public void testAdaptiveReplicaSelectionWithZoneAwarenessIgnored() throws Except Set selectedNodes = new HashSet<>(numShards); ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); - + opRouting.setClusterService(clusterService); GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -789,6 +790,15 @@ private ClusterState clusterStateForWRR(String[] indexNames, int numShards, int } + private ClusterState setWRRWeights(ClusterState clusterState, Map weights) { + WRRWeights wrrWeight = new WRRWeights("zone", weights); + WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); + Metadata.Builder metadataBuilder = Metadata.builder(clusterState.metadata()); + metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); + clusterState = ClusterState.builder(clusterState).metadata(metadataBuilder).build(); + return clusterState; + } + public void testWRR() throws Exception { final int numIndices = 2; final int numShards = 3; @@ -810,7 +820,6 @@ public void testWRR() throws Exception { setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); - opRouting.setClusterService(clusterService); assertTrue(opRouting.ignoreAwarenessAttributes()); Set selectedNodes = new HashSet<>(); ResponseCollectorService collector = new ResponseCollectorService(clusterService); @@ -818,11 +827,13 @@ public void testWRR() throws Exception { // Setting up weights for weighted round-robin in cluster state Map weights = Map.of("a", "1", "b", "1", "c", "0"); - WRRWeights wrrWeight = new WRRWeights("zone", weights); - WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); - Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); - state = ClusterState.builder(state).metadata(metadataBuilder).build(); + state = setWRRWeights(state, weights); + + ClusterState.Builder builder = ClusterState.builder(state); + ClusterServiceUtils.setState(clusterService, builder); + + opRouting.setClusterService(clusterService); + opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( @@ -852,16 +863,14 @@ public void testWRR() throws Exception { // Updating weighted round robin weights in cluster state weights = Map.of("a", "1", "b", "0", "c", "1"); - wrrWeight = new WRRWeights("zone", weights); - wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); - metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); + state = setWRRWeights(state, weights); - // building cluster state with new weights - state = ClusterState.builder(state).metadata(metadataBuilder).build(); + builder = ClusterState.builder(state); + ClusterServiceUtils.setState(clusterService, builder); opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); opRouting.setClusterService(clusterService); + opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); @@ -903,6 +912,7 @@ public void testWRRShardsCaching() throws Exception { new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); opRouting.setClusterService(clusterService); + opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); assertTrue(opRouting.ignoreAwarenessAttributes()); ResponseCollectorService collector = new ResponseCollectorService(clusterService); @@ -910,11 +920,8 @@ public void testWRRShardsCaching() throws Exception { // Setting up weights for weighted round-robin in cluster state Map weights = Map.of("a", "1", "b", "1", "c", "0"); - WRRWeights wrrWeight = new WRRWeights("zone", weights); - WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); - Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); - state = ClusterState.builder(state).metadata(metadataBuilder).build(); + state = setWRRWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( @@ -927,44 +934,40 @@ public void testWRRShardsCaching() throws Exception { ); // shard wrr ordering details are not present in cache, the details are calculated and put in cache - assertEquals(6, opRouting.getWrrShardsCache().getCache().stats().getMisses()); - assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + assertEquals(6, opRouting.getWrrShardsCache().misses()); + assertEquals(6, opRouting.getWrrShardsCache().size()); // Calling operation routing again without any cluster state change to test that wrr shard routing details are // fetched from cache groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); // details are fetched from cache - assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getHits()); + assertEquals(12, opRouting.getWrrShardsCache().hits()); // cache count stays same - assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + assertEquals(6, opRouting.getWrrShardsCache().size()); // cache misses stay same - assertEquals(6, opRouting.getWrrShardsCache().getCache().stats().getMisses()); + assertEquals(6, opRouting.getWrrShardsCache().misses()); // Updating cluster state to test wrr shard routing details are calculated again weights = Map.of("a", "1", "b", "0", "c", "1"); - wrrWeight = new WRRWeights("zone", weights); - wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); - metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); // building new cluster state - ClusterState state2 = ClusterState.builder(state).metadata(metadataBuilder).build(); + ClusterState state2 = setWRRWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state2)); ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); opRouting.getWrrShardsCache().clusterChanged(event); // cache is invalidated after cluster state change, cache count is zero - assertEquals(0, opRouting.getWrrShardsCache().getCache().count()); + assertEquals(0, opRouting.getWrrShardsCache().size()); // search shards call groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); // cache hit remain same - assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getHits()); + assertEquals(12, opRouting.getWrrShardsCache().hits()); // cache miss increases by 6 - assertEquals(12, opRouting.getWrrShardsCache().getCache().stats().getMisses()); - - assertEquals(6, opRouting.getWrrShardsCache().getCache().count()); + assertEquals(12, opRouting.getWrrShardsCache().misses()); + assertEquals(6, opRouting.getWrrShardsCache().size()); IOUtils.close(clusterService); terminate(threadPool); @@ -979,7 +982,6 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { for (int i = 0; i < numIndices; i++) { indexNames[i] = "test" + i; } - ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); @@ -991,7 +993,6 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); - opRouting.setClusterService(clusterService); assertTrue(opRouting.ignoreAwarenessAttributes()); Set selectedNodes = new HashSet<>(); ResponseCollectorService collector = new ResponseCollectorService(clusterService); @@ -999,12 +1000,11 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { // Setting up weights for weighted round-robin in cluster state, weight for nodes in zone b is not set Map weights = Map.of("a", "1", "c", "0"); - WRRWeights wrrWeight = new WRRWeights("zone", weights); - WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); - Metadata.Builder metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); - state = ClusterState.builder(state).metadata(metadataBuilder).build(); + state = setWRRWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); + opRouting.setClusterService(clusterService); + opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( state, @@ -1039,16 +1039,13 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { // Updating weighted round robin weights in cluster state weights = Map.of("a", "0", "b", "1"); - wrrWeight = new WRRWeights("zone", weights); - wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); - metadataBuilder = Metadata.builder(state.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); - // building cluster state with new weights - state = ClusterState.builder(state).metadata(metadataBuilder).build(); + state = setWRRWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); opRouting.setClusterService(clusterService); + opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index 68ad47fa1bbc9..223c9531dfe1c 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -50,9 +50,12 @@ import org.opensearch.cluster.routing.ShardsIterator; import org.opensearch.cluster.routing.allocation.AllocationService; import org.opensearch.cluster.routing.allocation.decider.ClusterRebalanceAllocationDecider; +import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.settings.ClusterSettings; import org.opensearch.common.settings.Settings; import org.opensearch.index.shard.ShardId; +import org.opensearch.test.ClusterServiceUtils; +import org.opensearch.threadpool.TestThreadPool; import java.util.Arrays; import java.util.Collections; @@ -422,11 +425,14 @@ public void testShardsAndPreferNodeRouting() { clusterState = startInitializingShardsAndReroute(strategy, clusterState); clusterState = startInitializingShardsAndReroute(strategy, clusterState); + TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + OperationRouting operationRouting = new OperationRouting( Settings.EMPTY, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); - + operationRouting.setClusterService(clusterService); GroupShardsIterator shardIterators = operationRouting.searchShards( clusterState, new String[] { "test" }, @@ -468,6 +474,7 @@ public void testShardsAndPreferNodeRouting() { } else { assertThat(it.nextOrNull().currentNodeId(), equalTo("node1")); } + terminate(threadPool); } public void testReplicaShardPreferenceIters() throws Exception { From cd3e16c914ee2508ff24e5d751c04895167e7996 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 12 Sep 2022 19:49:38 +0530 Subject: [PATCH 15/55] Remove extra new lines Signed-off-by: Anshu Agarwal --- .../cluster/metadata/WeightedRoundRobinRoutingMetadata.java | 2 -- .../java/org/opensearch/cluster/routing/OperationRouting.java | 2 -- .../main/java/org/opensearch/cluster/routing/WRRWeights.java | 2 +- .../java/org/opensearch/cluster/service/ClusterService.java | 2 -- .../org/opensearch/cluster/routing/OperationRoutingTests.java | 1 - 5 files changed, 1 insertion(+), 8 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java index b1baab52aaeb4..08c7f2901b684 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java @@ -50,7 +50,6 @@ public WeightedRoundRobinRoutingMetadata setWrrWeight(WRRWeights wrrWeight) { public WeightedRoundRobinRoutingMetadata(StreamInput in) throws IOException { if (in.available() != 0) { this.wrrWeight = new WRRWeights(in); - } } @@ -71,7 +70,6 @@ public String getWriteableName() { @Override public Version getMinimalSupportedVersion() { return Version.V_2_3_0; - } @Override diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 24b85d991bfda..6eb0c16ef678b 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -95,7 +95,6 @@ public OperationRouting(Settings settings, ClusterSettings clusterSettings) { this.useAdaptiveReplicaSelection = USE_ADAPTIVE_REPLICA_SELECTION_SETTING.get(settings); clusterSettings.addSettingsUpdateConsumer(USE_ADAPTIVE_REPLICA_SELECTION_SETTING, this::setUseAdaptiveReplicaSelection); clusterSettings.addSettingsUpdateConsumer(IGNORE_AWARENESS_ATTRIBUTES_SETTING, this::setIgnoreAwarenessAttributes); - } void setUseAdaptiveReplicaSelection(boolean useAdaptiveReplicaSelection) { @@ -261,7 +260,6 @@ private ShardIterator preferenceActiveShardIterator( @Nullable ResponseCollectorService collectorService, @Nullable Map nodeCounts ) { - if (preference == null || preference.isEmpty()) { return shardRoutings(indexShard, nodes, collectorService, nodeCounts); } diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java b/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java index daf2986ea8b71..58842dded1a52 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java @@ -64,7 +64,7 @@ public int hashCode() { @Override public String toString() { - return "WRRWeightsDefinition{" + attributeName + "}{" + weights().toString() + "}"; + return "WRRWeights{" + attributeName + "}{" + weights().toString() + "}"; } public Map weights() { diff --git a/server/src/main/java/org/opensearch/cluster/service/ClusterService.java b/server/src/main/java/org/opensearch/cluster/service/ClusterService.java index 2d31aca0073bf..d393613118af8 100644 --- a/server/src/main/java/org/opensearch/cluster/service/ClusterService.java +++ b/server/src/main/java/org/opensearch/cluster/service/ClusterService.java @@ -45,9 +45,7 @@ import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.cluster.routing.OperationRouting; import org.opensearch.cluster.routing.RerouteService; -import org.opensearch.cluster.routing.WRRShardsCache; import org.opensearch.common.component.AbstractLifecycleComponent; -import org.opensearch.common.inject.Inject; import org.opensearch.common.settings.ClusterSettings; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Setting.Property; diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index efca5e77b4823..7ad5d413f6ad7 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -104,7 +104,6 @@ public void testGenerateShardId() { .settings(settings(Version.CURRENT)) .numberOfShards(shardSplits[2]) .numberOfReplicas(1) - .setRoutingNumShards(shardSplits[0]) .build(); shrunkShard = OperationRouting.generateShardId(shrunk, term, null); From 0c7dbd95f1067bdd543f3ee306d2d44bb92ec57e Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 12 Sep 2022 20:02:41 +0530 Subject: [PATCH 16/55] Fix import Signed-off-by: Anshu Agarwal --- .../java/org/opensearch/cluster/routing/OperationRouting.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 6eb0c16ef678b..b4cca1c691340 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -40,6 +40,7 @@ import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Nullable; import org.opensearch.common.Strings; +import org.opensearch.common.inject.Inject; import org.opensearch.common.settings.ClusterSettings; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Settings; From 438fe9ee1df023ca1e0756b72c5b64a9df691424 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 12 Sep 2022 20:40:20 +0530 Subject: [PATCH 17/55] Add size for shard routing cache Signed-off-by: Anshu Agarwal --- .../java/org/opensearch/cluster/routing/WRRShardsCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java index f78d56d182291..40e9a8448489f 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java @@ -31,10 +31,10 @@ public class WRRShardsCache implements Releasable, ClusterStateListener { private static final Logger logger = LogManager.getLogger(WRRShardsCache.class); private final Cache> cache; + private static final long sizeInBytes = 2000000; public WRRShardsCache(ClusterService clusterService) { - final long sizeInBytes = 2000000; CacheBuilder> cacheBuilder = CacheBuilder.>builder() .removalListener(notification -> logger.info("Object" + " {} removed from cache", notification.getKey().shardId)) .setMaximumWeight(sizeInBytes); From 694be4df1953e6323ff1e9a0a5a8fc3d780a9b03 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 12 Sep 2022 20:51:49 +0530 Subject: [PATCH 18/55] Invalidate shard routing cache on close Signed-off-by: Anshu Agarwal --- server/src/main/java/org/opensearch/node/Node.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index 6c76096721754..156d544ee14c2 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -1251,7 +1251,6 @@ private Node stop() { injector.getInstance(GatewayService.class).stop(); injector.getInstance(SearchService.class).stop(); injector.getInstance(TransportService.class).stop(); - injector.getInstance(WRRShardsCache.class).close(); pluginLifecycleComponents.forEach(LifecycleComponent::stop); // we should stop this last since it waits for resources to get released @@ -1338,6 +1337,7 @@ public synchronized void close() throws IOException { toClose.add(() -> stopWatch.stop().start("node_environment")); toClose.add(injector.getInstance(NodeEnvironment.class)); toClose.add(stopWatch::stop); + toClose.add(injector.getInstance(WRRShardsCache.class)); if (logger.isTraceEnabled()) { toClose.add(() -> logger.trace("Close times for each service:\n{}", stopWatch.prettyPrint())); From 9236b8d05f290aa52c9622c6bf82dbd77be6413d Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Tue, 13 Sep 2022 19:13:43 +0530 Subject: [PATCH 19/55] Refactor code Signed-off-by: Anshu Agarwal --- .../org/opensearch/cluster/ClusterModule.java | 13 +-- .../opensearch/cluster/metadata/Metadata.java | 8 ++ ...data.java => WeightedRoutingMetadata.java} | 67 ++++++++------ .../routing/IndexShardRoutingTable.java | 66 +++++++------- .../cluster/routing/OperationRouting.java | 33 +++---- .../cluster/routing/WeightedRoundRobin.java | 2 +- .../{WRRWeights.java => WeightedRouting.java} | 16 ++-- ...dsCache.java => WeightedRoutingCache.java} | 16 ++-- .../main/java/org/opensearch/node/Node.java | 8 +- ...java => WeightedRoutingMetadataTests.java} | 14 +-- .../routing/OperationRoutingTests.java | 44 +++++----- .../routing/WeightedRoundRobinTests.java | 88 +++++++++++++++++-- 12 files changed, 224 insertions(+), 151 deletions(-) rename server/src/main/java/org/opensearch/cluster/metadata/{WeightedRoundRobinRoutingMetadata.java => WeightedRoutingMetadata.java} (62%) rename server/src/main/java/org/opensearch/cluster/routing/{WRRWeights.java => WeightedRouting.java} (75%) rename server/src/main/java/org/opensearch/cluster/routing/{WRRShardsCache.java => WeightedRoutingCache.java} (83%) rename server/src/test/java/org/opensearch/cluster/metadata/{WeightedRoundRobinRoutingMetadataTests.java => WeightedRoutingMetadataTests.java} (52%) diff --git a/server/src/main/java/org/opensearch/cluster/ClusterModule.java b/server/src/main/java/org/opensearch/cluster/ClusterModule.java index 99a342eaeb5ed..46552bb5d6a03 100644 --- a/server/src/main/java/org/opensearch/cluster/ClusterModule.java +++ b/server/src/main/java/org/opensearch/cluster/ClusterModule.java @@ -48,7 +48,7 @@ import org.opensearch.cluster.metadata.MetadataMappingService; import org.opensearch.cluster.metadata.MetadataUpdateSettingsService; import org.opensearch.cluster.metadata.RepositoriesMetadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; +import org.opensearch.cluster.metadata.WeightedRoutingMetadata; import org.opensearch.cluster.routing.DelayedAllocationService; import org.opensearch.cluster.routing.allocation.AllocationService; import org.opensearch.cluster.routing.allocation.ExistingShardsAllocator; @@ -192,12 +192,7 @@ public static List getNamedWriteables() { ComposableIndexTemplateMetadata::readDiffFrom ); registerMetadataCustom(entries, DataStreamMetadata.TYPE, DataStreamMetadata::new, DataStreamMetadata::readDiffFrom); - registerMetadataCustom( - entries, - WeightedRoundRobinRoutingMetadata.TYPE, - WeightedRoundRobinRoutingMetadata::new, - WeightedRoundRobinRoutingMetadata::readDiffFrom - ); + registerMetadataCustom(entries, WeightedRoutingMetadata.TYPE, WeightedRoutingMetadata::new, WeightedRoutingMetadata::readDiffFrom); // Task Status (not Diffable) entries.add(new Entry(Task.Status.class, PersistentTasksNodeService.Status.NAME, PersistentTasksNodeService.Status::new)); return entries; @@ -284,8 +279,8 @@ public static List getNamedXWriteables() { entries.add( new NamedXContentRegistry.Entry( Metadata.Custom.class, - new ParseField(WeightedRoundRobinRoutingMetadata.TYPE), - WeightedRoundRobinRoutingMetadata::fromXContent + new ParseField(WeightedRoutingMetadata.TYPE), + WeightedRoutingMetadata::fromXContent ) ); return entries; diff --git a/server/src/main/java/org/opensearch/cluster/metadata/Metadata.java b/server/src/main/java/org/opensearch/cluster/metadata/Metadata.java index 5f7e98e9e1199..086865d2170c3 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/Metadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/Metadata.java @@ -810,6 +810,14 @@ public IndexGraveyard indexGraveyard() { return custom(IndexGraveyard.TYPE); } + /** + * * + * @return The weighted routing metadata for search requests + */ + public WeightedRoutingMetadata weightedRoutingMetadata() { + return custom(WeightedRoutingMetadata.TYPE); + } + public T custom(String type) { return (T) customs.get(type); } diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java similarity index 62% rename from server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java rename to server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java index 08c7f2901b684..9c9b8bf38b4a7 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java @@ -14,7 +14,7 @@ import org.opensearch.Version; import org.opensearch.cluster.AbstractNamedDiffable; import org.opensearch.cluster.NamedDiff; -import org.opensearch.cluster.routing.WRRWeights; +import org.opensearch.cluster.routing.WeightedRouting; import org.opensearch.common.Strings; import org.opensearch.common.io.stream.StreamInput; import org.opensearch.common.io.stream.StreamOutput; @@ -32,29 +32,29 @@ * * @opensearch.internal */ -public class WeightedRoundRobinRoutingMetadata extends AbstractNamedDiffable implements Metadata.Custom { - private static final Logger logger = LogManager.getLogger(WeightedRoundRobinRoutingMetadata.class); - public static final String TYPE = "wrr_shard_routing"; +public class WeightedRoutingMetadata extends AbstractNamedDiffable implements Metadata.Custom { + private static final Logger logger = LogManager.getLogger(WeightedRoutingMetadata.class); + public static final String TYPE = "weighted_shard_routing"; public static final String AWARENESS = "awareness"; - private WRRWeights wrrWeight; + private WeightedRouting weightedRouting; - public WRRWeights getWrrWeight() { - return wrrWeight; + public WeightedRouting getWeightedRouting() { + return weightedRouting; } - public WeightedRoundRobinRoutingMetadata setWrrWeight(WRRWeights wrrWeight) { - this.wrrWeight = wrrWeight; + public WeightedRoutingMetadata setWeightedRouting(WeightedRouting weightedRouting) { + this.weightedRouting = weightedRouting; return this; } - public WeightedRoundRobinRoutingMetadata(StreamInput in) throws IOException { + public WeightedRoutingMetadata(StreamInput in) throws IOException { if (in.available() != 0) { - this.wrrWeight = new WRRWeights(in); + this.weightedRouting = new WeightedRouting(in); } } - public WeightedRoundRobinRoutingMetadata(WRRWeights wrrWeight) { - this.wrrWeight = wrrWeight; + public WeightedRoutingMetadata(WeightedRouting weightedRouting) { + this.weightedRouting = weightedRouting; } @Override @@ -74,8 +74,8 @@ public Version getMinimalSupportedVersion() { @Override public void writeTo(StreamOutput out) throws IOException { - if (wrrWeight != null) { - wrrWeight.writeTo(out); + if (weightedRouting != null) { + weightedRouting.writeTo(out); } } @@ -83,12 +83,12 @@ public static NamedDiff readDiffFrom(StreamInput in) throws IOE return readDiffFrom(Metadata.Custom.class, TYPE, in); } - public static WeightedRoundRobinRoutingMetadata fromXContent(XContentParser parser) throws IOException { + public static WeightedRoutingMetadata fromXContent(XContentParser parser) throws IOException { String attrKey = null; Object attrValue; String attributeName = null; Map weights = new HashMap<>(); - WRRWeights wrrWeight = null; + WeightedRouting weightedRouting = null; XContentParser.Token token; // move to the first alias parser.nextToken(); @@ -98,12 +98,18 @@ public static WeightedRoundRobinRoutingMetadata fromXContent(XContentParser pars if (token == XContentParser.Token.FIELD_NAME) { awarenessField = parser.currentName(); if (parser.nextToken() != XContentParser.Token.START_OBJECT) { - throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", awarenessField); + throw new OpenSearchParseException( + "failed to parse weighted routing metadata [{}], expected " + "object", + awarenessField + ); } while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { attributeName = parser.currentName(); if (parser.nextToken() != XContentParser.Token.START_OBJECT) { - throw new OpenSearchParseException("failed to parse wrr metadata [{}], expected object", attributeName); + throw new OpenSearchParseException( + "failed to parse weighted routing metadata [{}], expected" + " object", + attributeName + ); } while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { @@ -112,39 +118,42 @@ public static WeightedRoundRobinRoutingMetadata fromXContent(XContentParser pars attrValue = parser.text(); weights.put(attrKey, attrValue); } else { - throw new OpenSearchParseException("failed to parse wrr metadata attribute [{}], unknown type", attributeName); + throw new OpenSearchParseException( + "failed to parse weighted routing metadata attribute " + "[{}], unknown type", + attributeName + ); } } } } } - wrrWeight = new WRRWeights(attributeName, weights); - return new WeightedRoundRobinRoutingMetadata(wrrWeight); + weightedRouting = new WeightedRouting(attributeName, weights); + return new WeightedRoutingMetadata(weightedRouting); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - WeightedRoundRobinRoutingMetadata that = (WeightedRoundRobinRoutingMetadata) o; - return wrrWeight.equals(that.wrrWeight); + WeightedRoutingMetadata that = (WeightedRoutingMetadata) o; + return weightedRouting.equals(that.weightedRouting); } @Override public int hashCode() { - return wrrWeight.hashCode(); + return weightedRouting.hashCode(); } @Override public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { - toXContent(wrrWeight, builder); + toXContent(weightedRouting, builder); return builder; } - public static void toXContent(WRRWeights wrrWeight, XContentBuilder builder) throws IOException { + public static void toXContent(WeightedRouting weightedRouting, XContentBuilder builder) throws IOException { builder.startObject(AWARENESS); - builder.startObject(wrrWeight.attributeName()); - for (Map.Entry entry : wrrWeight.weights().entrySet()) { + builder.startObject(weightedRouting.attributeName()); + for (Map.Entry entry : weightedRouting.weights().entrySet()) { builder.field(entry.getKey(), entry.getValue()); } builder.endObject(); diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index d0e79f8efda2e..e2352dd6ce6f3 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -59,6 +59,7 @@ import java.util.function.Predicate; import static java.util.Collections.emptyMap; +import static java.util.stream.Collectors.toList; /** * {@link IndexShardRoutingTable} encapsulates all instances of a single shard. @@ -293,71 +294,66 @@ public ShardIterator activeInitializingShardsRankedIt( } /** - * Returns an iterator over active and initializing shards, shards are ordered by weighted round-robin scheduling - * policy. - * @param wrrWeight Weighted round-robin weight entity - * @param nodes discovered nodes in the cluster + * Returns an iterator over active and initializing shards, shards are ordered by weighted + * round-robin scheduling policy. + * + * @param weightedRouting entity + * @param nodes discovered nodes in the cluster * @return an iterator over active and initializing shards, ordered by weighted round-robin * scheduling policy. Making sure that initializing shards are the last to iterate through. */ - public ShardIterator activeInitializingShardsWRR(WRRWeights wrrWeight, DiscoveryNodes nodes, WRRShardsCache cache) { + public ShardIterator activeInitializingShardsWeightedIt( + WeightedRouting weightedRouting, + DiscoveryNodes nodes, + WeightedRoutingCache cache + ) { final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); List orderedActiveShards; - if (cache.get(new WRRShardsCache.Key(shardId)) != null) { - orderedActiveShards = cache.get(new WRRShardsCache.Key(shardId)); + if (cache.get(new WeightedRoutingCache.Key(shardId)) != null) { + orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); } else { - orderedActiveShards = getShardsWRR(activeShards, wrrWeight, nodes); - cache.put(new WRRShardsCache.Key(shardId), orderedActiveShards); + orderedActiveShards = shardsOrderedByWeight(activeShards, weightedRouting, nodes); + cache.put(new WeightedRoutingCache.Key(shardId), orderedActiveShards); } ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); if (!allInitializingShards.isEmpty()) { - List orderedInitializingShards = getShardsWRR(allInitializingShards, wrrWeight, nodes); + List orderedInitializingShards = shardsOrderedByWeight(allInitializingShards, weightedRouting, nodes); ordered.addAll(orderedInitializingShards); } return new PlainShardIterator(shardId, ordered); } /** - * - * @param shards shards to be ordered using weighted round-robin scheduling policy - * @param wrrWeight weights to be considered for routing - * @param nodes discovered nodes in the cluster - * @return list of shards ordered using weighted round-robin scheduling. + * Returns a list containing shard routings ordered using weighted round-robin scheduling. */ - private List getShardsWRR(List shards, WRRWeights wrrWeight, DiscoveryNodes nodes) { - List> weightedShards = calculateShardWeight(shards, wrrWeight, nodes); - WeightedRoundRobin wrr = new WeightedRoundRobin<>(weightedShards); - List> wrrOrderedActiveShards = wrr.orderEntities(); - List orderedActiveShards = new ArrayList<>(activeShards.size()); - for (WeightedRoundRobin.Entity shardRouting : wrrOrderedActiveShards) { - orderedActiveShards.add(shardRouting.getTarget()); - } - return orderedActiveShards; + private List shardsOrderedByWeight(List shards, WeightedRouting weightedRouting, DiscoveryNodes nodes) { + WeightedRoundRobin weightedRoundRobin = new WeightedRoundRobin<>( + calculateShardWeight(shards, weightedRouting, nodes) + ); + return weightedRoundRobin.orderEntities().stream().map(WeightedRoundRobin.Entity::getTarget).collect(toList()); } /** - * - * @param shards associate weights to shards - * @param wrrWeight weights to be used for association - * @param nodes discovered nodes in the cluster - * @return list of entity containing shard routing and associated weight. + * Returns a list containing shard routing and associated weight. This function iterates through all the shards and + * uses weighted routing to find weight for the corresponding shard. This is fed to weighted round-robin scheduling + * to order shards by weight. */ private List> calculateShardWeight( List shards, - WRRWeights wrrWeight, + WeightedRouting weightedRouting, DiscoveryNodes nodes ) { - List> weightedShards = new ArrayList<>(); + List> shardsWithWeights = new ArrayList<>(); for (ShardRouting shard : shards) { DiscoveryNode node = nodes.get(shard.currentNodeId()); - String attVal = node.getAttributes().get(wrrWeight.attributeName()); + String attVal = node.getAttributes().get(weightedRouting.attributeName()); // If weight for a zone is not defined, considering it as 1 by default - Double weight = Double.parseDouble(wrrWeight.weights().getOrDefault(attVal, 1).toString()); - weightedShards.add(new WeightedRoundRobin.Entity<>(weight, shard)); + Double weight = Double.parseDouble(weightedRouting.weights().getOrDefault(attVal, 1).toString()); + shardsWithWeights.add(new WeightedRoundRobin.Entity<>(weight, shard)); } - return weightedShards; + return shardsWithWeights; } private static Set getAllNodeIds(final List shards) { diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index b4cca1c691340..a5acbed983cc3 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -34,7 +34,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; +import org.opensearch.cluster.metadata.WeightedRoutingMetadata; import org.opensearch.cluster.node.DiscoveryNodes; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; import org.opensearch.cluster.service.ClusterService; @@ -82,8 +82,8 @@ public class OperationRouting { private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; - public WRRShardsCache wrrShardsCache; - public ClusterService clusterService; + private WeightedRoutingCache weightedRoutingCache; + private ClusterService clusterService; public OperationRouting(Settings settings, ClusterSettings clusterSettings) { // whether to ignore awareness attributes when routing requests @@ -128,12 +128,12 @@ public void setClusterService(ClusterService clusterService) { } @Inject - public void setWrrShardsCache(WRRShardsCache wrrShardsCache) { - this.wrrShardsCache = wrrShardsCache; + public void setWeightedRoutingCache(WeightedRoutingCache weightedRoutingCache) { + this.weightedRoutingCache = weightedRoutingCache; } - public WRRShardsCache getWrrShardsCache() { - return wrrShardsCache; + public WeightedRoutingCache getWeightedRoutingCache() { + return weightedRoutingCache; } public ShardIterator indexShards(ClusterState clusterState, String index, String id, @Nullable String routing) { @@ -204,20 +204,6 @@ public GroupShardsIterator searchShards( return GroupShardsIterator.sortAndCreate(new ArrayList<>(set)); } - private boolean isWeightedRoundRobinEnabled() { - WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterService.state() - .metadata() - .custom(WeightedRoundRobinRoutingMetadata.TYPE); - return weightedRoundRobinRoutingMetadata != null; - } - - private WRRWeights fetchWRRWeights() { - WeightedRoundRobinRoutingMetadata weightedRoundRobinRoutingMetadata = clusterService.state() - .metadata() - .custom(WeightedRoundRobinRoutingMetadata.TYPE); - return weightedRoundRobinRoutingMetadata.getWrrWeight(); - } - public static ShardIterator getShards(ClusterState clusterState, ShardId shardId) { final IndexShardRoutingTable shard = clusterState.routingTable().shardRoutingTable(shardId); return shard.activeInitializingShardsRandomIt(); @@ -334,8 +320,9 @@ private ShardIterator shardRoutings( @Nullable ResponseCollectorService collectorService, @Nullable Map nodeCounts ) { - if (isWeightedRoundRobinEnabled()) { - return indexShard.activeInitializingShardsWRR(fetchWRRWeights(), nodes, wrrShardsCache); + WeightedRoutingMetadata weightedRoutingMetadata = clusterService.state().metadata().weightedRoutingMetadata(); + if (weightedRoutingMetadata != null) { + return indexShard.activeInitializingShardsWeightedIt(weightedRoutingMetadata.getWeightedRouting(), nodes, weightedRoutingCache); } else if (ignoreAwarenessAttributes()) { if (useAdaptiveReplicaSelection) { return indexShard.activeInitializingShardsRankedIt(collectorService, nodeCounts); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index dd1966f1c6adb..0484f8cd0d93e 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -46,7 +46,7 @@ public List> orderEntities() { for (WeightedRoundRobin.Entity entity : entities) { maxWeight = Math.max(maxWeight, entity.getWeight()); gcd = (gcd == null) ? entity.getWeight() : gcd(gcd, entity.getWeight()); - sumWeight += entity.getWeight(); + sumWeight += entity.getWeight() > 0 ? entity.getWeight() : 0; } int count = 0; while (count < sumWeight) { diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java similarity index 75% rename from server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java rename to server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java index 58842dded1a52..90f9b1beb2ed1 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRWeights.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java @@ -21,21 +21,21 @@ * * @opensearch.internal */ -public class WRRWeights implements Writeable { +public class WeightedRouting implements Writeable { private String attributeName; private Map weights; - public WRRWeights(String attributeName, Map weights) { + public WeightedRouting(String attributeName, Map weights) { this.attributeName = attributeName; this.weights = weights; } - public WRRWeights(WRRWeights wrrWeight) { - this.attributeName = wrrWeight.attributeName(); - this.weights = wrrWeight.weights; + public WeightedRouting(WeightedRouting weightedRouting) { + this.attributeName = weightedRouting.attributeName(); + this.weights = weightedRouting.weights; } - public WRRWeights(StreamInput in) throws IOException { + public WeightedRouting(StreamInput in) throws IOException { attributeName = in.readString(); weights = in.readMap(); } @@ -51,7 +51,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - WRRWeights that = (WRRWeights) o; + WeightedRouting that = (WeightedRouting) o; if (!attributeName.equals(that.attributeName)) return false; return weights.equals(that.weights); @@ -64,7 +64,7 @@ public int hashCode() { @Override public String toString() { - return "WRRWeights{" + attributeName + "}{" + weights().toString() + "}"; + return "WeightedRouting{" + attributeName + "}{" + weights().toString() + "}"; } public Map weights() { diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java similarity index 83% rename from server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java rename to server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java index 40e9a8448489f..a525f26e0176e 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardsCache.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java @@ -27,13 +27,13 @@ * @opensearch.internal */ -public class WRRShardsCache implements Releasable, ClusterStateListener { - private static final Logger logger = LogManager.getLogger(WRRShardsCache.class); +public class WeightedRoutingCache implements Releasable, ClusterStateListener { + private static final Logger logger = LogManager.getLogger(WeightedRoutingCache.class); private final Cache> cache; private static final long sizeInBytes = 2000000; - public WRRShardsCache(ClusterService clusterService) { + public WeightedRoutingCache(ClusterService clusterService) { CacheBuilder> cacheBuilder = CacheBuilder.>builder() .removalListener(notification -> logger.info("Object" + " {} removed from cache", notification.getKey().shardId)) @@ -56,7 +56,7 @@ public long size() { @Override public void close() { - logger.debug("Invalidating WRRShardsCache on close"); + logger.debug("Invalidating WeightedRoutingCache on close"); cache.invalidateAll(); } @@ -67,7 +67,7 @@ public void close() { */ @Override public void clusterChanged(ClusterChangedEvent event) { - logger.debug("Invalidating WRRShardsCache on ClusterChangedEvent"); + logger.debug("Invalidating WeightedRoutingCache on ClusterChangedEvent"); cache.invalidateAll(); } @@ -80,12 +80,12 @@ public void put(Key key, List value) { } /** - * Key for the WRRShardsCache + * Key for the WeightedRoutingCache * * @opensearch.internal */ public static class Key { - public final ShardId shardId; + private final ShardId shardId; Key(ShardId shardId) { this.shardId = shardId; @@ -95,7 +95,7 @@ public static class Key { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - WRRShardsCache.Key key = (WRRShardsCache.Key) o; + WeightedRoutingCache.Key key = (WeightedRoutingCache.Key) o; if (!shardId.equals(key.shardId)) return false; return true; } diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index 156d544ee14c2..d0ab73e4fcc29 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -37,7 +37,7 @@ import org.apache.lucene.util.Constants; import org.apache.lucene.util.SetOnce; import org.opensearch.cluster.routing.OperationRouting; -import org.opensearch.cluster.routing.WRRShardsCache; +import org.opensearch.cluster.routing.WeightedRoutingCache; import org.opensearch.common.util.FeatureFlags; import org.opensearch.cluster.routing.allocation.AwarenessReplicaBalance; import org.opensearch.index.IndexingPressureService; @@ -908,7 +908,7 @@ protected Node( ); resourcesToClose.add(persistentTasksClusterService); final PersistentTasksService persistentTasksService = new PersistentTasksService(clusterService, threadPool, client); - final WRRShardsCache wrrShardsCache = new WRRShardsCache(clusterService); + final WeightedRoutingCache weightedRoutingCache = new WeightedRoutingCache(clusterService); modules.add(b -> { b.bind(Node.class).toInstance(this); @@ -952,7 +952,7 @@ protected Node( b.bind(SnapshotsInfoService.class).toInstance(snapshotsInfoService); b.bind(GatewayMetaState.class).toInstance(gatewayMetaState); b.bind(Discovery.class).toInstance(discoveryModule.getDiscovery()); - b.bind(WRRShardsCache.class).toInstance(wrrShardsCache); + b.bind(WeightedRoutingCache.class).toInstance(weightedRoutingCache); { processRecoverySettings(settingsModule.getClusterSettings(), recoverySettings); b.bind(PeerRecoverySourceService.class) @@ -1337,7 +1337,7 @@ public synchronized void close() throws IOException { toClose.add(() -> stopWatch.stop().start("node_environment")); toClose.add(injector.getInstance(NodeEnvironment.class)); toClose.add(stopWatch::stop); - toClose.add(injector.getInstance(WRRShardsCache.class)); + toClose.add(injector.getInstance(WeightedRoutingCache.class)); if (logger.isTraceEnabled()) { toClose.add(() -> logger.trace("Close times for each service:\n{}", stopWatch.prettyPrint())); diff --git a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java similarity index 52% rename from server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java rename to server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java index a5f3b8a1ccefa..c1e4c380db9ac 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoundRobinRoutingMetadataTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java @@ -8,25 +8,25 @@ package org.opensearch.cluster.metadata; -import org.opensearch.cluster.routing.WRRWeights; +import org.opensearch.cluster.routing.WeightedRouting; import org.opensearch.common.xcontent.XContentParser; import org.opensearch.test.AbstractXContentTestCase; import java.io.IOException; import java.util.Map; -public class WeightedRoundRobinRoutingMetadataTests extends AbstractXContentTestCase { +public class WeightedRoutingMetadataTests extends AbstractXContentTestCase { @Override - protected WeightedRoundRobinRoutingMetadata createTestInstance() { + protected WeightedRoutingMetadata createTestInstance() { Map weights = Map.of("a", "1", "b", "1", "c", "0"); - WRRWeights wrrWeights = new WRRWeights("zone", weights); - WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeights); + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); + WeightedRoutingMetadata wrrMetadata = new WeightedRoutingMetadata(weightedRouting); return wrrMetadata; } @Override - protected WeightedRoundRobinRoutingMetadata doParseInstance(XContentParser parser) throws IOException { - return WeightedRoundRobinRoutingMetadata.fromXContent(parser); + protected WeightedRoutingMetadata doParseInstance(XContentParser parser) throws IOException { + return WeightedRoutingMetadata.fromXContent(parser); } @Override diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 7ad5d413f6ad7..2f9fe3cd991ac 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -37,7 +37,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.Metadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; +import org.opensearch.cluster.metadata.WeightedRoutingMetadata; import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.cluster.node.DiscoveryNodeRole; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; @@ -790,10 +790,10 @@ private ClusterState clusterStateForWRR(String[] indexNames, int numShards, int } private ClusterState setWRRWeights(ClusterState clusterState, Map weights) { - WRRWeights wrrWeight = new WRRWeights("zone", weights); - WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeight); + WeightedRouting wrrWeight = new WeightedRouting("zone", weights); + WeightedRoutingMetadata wrrMetadata = new WeightedRoutingMetadata(wrrWeight); Metadata.Builder metadataBuilder = Metadata.builder(clusterState.metadata()); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); + metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, wrrMetadata); clusterState = ClusterState.builder(clusterState).metadata(metadataBuilder).build(); return clusterState; } @@ -832,7 +832,7 @@ public void testWRR() throws Exception { ClusterServiceUtils.setState(clusterService, builder); opRouting.setClusterService(clusterService); - opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( @@ -869,7 +869,7 @@ public void testWRR() throws Exception { opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); opRouting.setClusterService(clusterService); - opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); @@ -911,7 +911,7 @@ public void testWRRShardsCaching() throws Exception { new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); opRouting.setClusterService(clusterService); - opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); assertTrue(opRouting.ignoreAwarenessAttributes()); ResponseCollectorService collector = new ResponseCollectorService(clusterService); @@ -933,19 +933,19 @@ public void testWRRShardsCaching() throws Exception { ); // shard wrr ordering details are not present in cache, the details are calculated and put in cache - assertEquals(6, opRouting.getWrrShardsCache().misses()); - assertEquals(6, opRouting.getWrrShardsCache().size()); + assertEquals(6, opRouting.getWeightedRoutingCache().misses()); + assertEquals(6, opRouting.getWeightedRoutingCache().size()); // Calling operation routing again without any cluster state change to test that wrr shard routing details are // fetched from cache groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); // details are fetched from cache - assertEquals(12, opRouting.getWrrShardsCache().hits()); + assertEquals(12, opRouting.getWeightedRoutingCache().hits()); // cache count stays same - assertEquals(6, opRouting.getWrrShardsCache().size()); + assertEquals(6, opRouting.getWeightedRoutingCache().size()); // cache misses stay same - assertEquals(6, opRouting.getWrrShardsCache().misses()); + assertEquals(6, opRouting.getWeightedRoutingCache().misses()); // Updating cluster state to test wrr shard routing details are calculated again weights = Map.of("a", "1", "b", "0", "c", "1"); @@ -954,19 +954,19 @@ public void testWRRShardsCaching() throws Exception { ClusterServiceUtils.setState(clusterService, ClusterState.builder(state2)); ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); - opRouting.getWrrShardsCache().clusterChanged(event); + opRouting.getWeightedRoutingCache().clusterChanged(event); // cache is invalidated after cluster state change, cache count is zero - assertEquals(0, opRouting.getWrrShardsCache().size()); + assertEquals(0, opRouting.getWeightedRoutingCache().size()); // search shards call groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); // cache hit remain same - assertEquals(12, opRouting.getWrrShardsCache().hits()); + assertEquals(12, opRouting.getWeightedRoutingCache().hits()); // cache miss increases by 6 - assertEquals(12, opRouting.getWrrShardsCache().misses()); - assertEquals(6, opRouting.getWrrShardsCache().size()); + assertEquals(12, opRouting.getWeightedRoutingCache().misses()); + assertEquals(6, opRouting.getWeightedRoutingCache().size()); IOUtils.close(clusterService); terminate(threadPool); @@ -1003,7 +1003,7 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); opRouting.setClusterService(clusterService); - opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( state, @@ -1044,7 +1044,7 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); opRouting.setClusterService(clusterService); - opRouting.setWrrShardsCache(new WRRShardsCache(clusterService)); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); @@ -1236,9 +1236,9 @@ private ClusterState updateStatetoTestWRR( } // add wrr weights in metadata Map weights = Map.of("a", "1", "b", "1", "c", "0"); - WRRWeights wrrWeights = new WRRWeights("zone", weights); - WeightedRoundRobinRoutingMetadata wrrMetadata = new WeightedRoundRobinRoutingMetadata(wrrWeights); - metadataBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrMetadata); + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); + WeightedRoutingMetadata wrrMetadata = new WeightedRoutingMetadata(weightedRouting); + metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, wrrMetadata); clusterState.metadata(metadataBuilder); clusterState.routingTable(routingTableBuilder.build()); return clusterState.build(); diff --git a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java index 398a36fba83e5..81e7992410940 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java @@ -16,22 +16,100 @@ public class WeightedRoundRobinTests extends OpenSearchTestCase { - public void testWRROrder() { - + public void testWeightedRoundRobinOrder() { + // weights set as A:4, B:3, C:2 List> entity = new ArrayList>(); entity.add(new WeightedRoundRobin.Entity<>(4, "A")); entity.add(new WeightedRoundRobin.Entity<>(3, "B")); entity.add(new WeightedRoundRobin.Entity<>(2, "C")); - WeightedRoundRobin wrr = new WeightedRoundRobin(entity); - List> orderedEntities = wrr.orderEntities(); - + WeightedRoundRobin weightedRoundRobin = new WeightedRoundRobin(entity); + List> orderedEntities = weightedRoundRobin.orderEntities(); List expectedOrdering = Arrays.asList("A", "A", "B", "A", "B", "C", "A", "B", "C"); List actualOrdering = new ArrayList<>(); for (WeightedRoundRobin.Entity en : orderedEntities) { actualOrdering.add(en.getTarget()); } + assertEquals(expectedOrdering, actualOrdering); + + // weights set as A:1, B:1, C:0 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(1, "A")); + entity.add(new WeightedRoundRobin.Entity<>(1, "B")); + entity.add(new WeightedRoundRobin.Entity<>(0, "C")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList("A", "B"); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + assertEquals(expectedOrdering, actualOrdering); + + // weights set as A:0, B:0, C:0 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(0, "A")); + entity.add(new WeightedRoundRobin.Entity<>(0, "B")); + entity.add(new WeightedRoundRobin.Entity<>(0, "C")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList(); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + assertEquals(expectedOrdering, actualOrdering); + + // weights set as A:-1, B:0, C:1 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(-1, "A")); + entity.add(new WeightedRoundRobin.Entity<>(0, "B")); + entity.add(new WeightedRoundRobin.Entity<>(1, "C")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList("C"); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + assertEquals(expectedOrdering, actualOrdering); + // weights set as A:-1, B:3, C:0, D:10 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(-1, "A")); + entity.add(new WeightedRoundRobin.Entity<>(3, "B")); + entity.add(new WeightedRoundRobin.Entity<>(0, "C")); + entity.add(new WeightedRoundRobin.Entity<>(10, "D")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList("B", "D", "B", "D", "B", "D", "D", "D", "D", "D", "D", "D", "D"); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } assertEquals(expectedOrdering, actualOrdering); + + // weights set as A:-1, B:3, C:0, D:10000 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(-1, "A")); + entity.add(new WeightedRoundRobin.Entity<>(3, "B")); + entity.add(new WeightedRoundRobin.Entity<>(0, "C")); + entity.add(new WeightedRoundRobin.Entity<>(10000, "D")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + assertEquals(10003, orderedEntities.size()); + // Count of D's + int countD = 0; + // Count of B's + int countB = 0; + for (WeightedRoundRobin.Entity en : orderedEntities) { + if (en.getTarget().equals("D")) { + countD++; + } else if (en.getTarget().equals("B")) { + countB++; + } + } + assertEquals(3, countB); + assertEquals(10000, countD); } } From 93e7587bc031c10d1b43835ac718e179f2565af2 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Tue, 13 Sep 2022 21:33:53 +0530 Subject: [PATCH 20/55] Add test for Weighted routing iterator and some refactoring changes Signed-off-by: Anshu Agarwal --- .../routing/IndexShardRoutingTable.java | 12 +- .../cluster/routing/WeightedRoutingCache.java | 5 +- .../WeightedRoutingMetadataTests.java | 5 +- .../routing/OperationRoutingTests.java | 451 +++++++++--------- .../structure/RoutingIteratorTests.java | 92 ++++ 5 files changed, 337 insertions(+), 228 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index e2352dd6ce6f3..c9f4c8a69e490 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -59,7 +59,6 @@ import java.util.function.Predicate; import static java.util.Collections.emptyMap; -import static java.util.stream.Collectors.toList; /** * {@link IndexShardRoutingTable} encapsulates all instances of a single shard. @@ -308,7 +307,7 @@ public ShardIterator activeInitializingShardsWeightedIt( WeightedRoutingCache cache ) { final int seed = shuffler.nextSeed(); - List ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size()); + List ordered = new ArrayList<>(); List orderedActiveShards; if (cache.get(new WeightedRoutingCache.Key(shardId)) != null) { orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); @@ -332,7 +331,14 @@ private List shardsOrderedByWeight(List shards, Weig WeightedRoundRobin weightedRoundRobin = new WeightedRoundRobin<>( calculateShardWeight(shards, weightedRouting, nodes) ); - return weightedRoundRobin.orderEntities().stream().map(WeightedRoundRobin.Entity::getTarget).collect(toList()); + List> shardsOrderedbyWeight = weightedRoundRobin.orderEntities(); + List orderedShardRouting = new ArrayList<>(activeShards.size()); + if (shardsOrderedbyWeight != null) { + for (WeightedRoundRobin.Entity shardRouting : shardsOrderedbyWeight) { + orderedShardRouting.add(shardRouting.getTarget()); + } + } + return orderedShardRouting; } /** diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java index a525f26e0176e..ee4fef0260a8a 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java @@ -21,12 +21,11 @@ import java.util.List; /** - * The WRR shards cache allows caching shard ordering returned by Weighted round-robin scheduling policy ,helping with - * improving similar requests. + * The weighted shard routing cache allows caching shard routing iterator returned by Weighted round-robin scheduling + * policy, helping with improving similar requests. * * @opensearch.internal */ - public class WeightedRoutingCache implements Releasable, ClusterStateListener { private static final Logger logger = LogManager.getLogger(WeightedRoutingCache.class); diff --git a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java index c1e4c380db9ac..01a55f7f4fa4a 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java @@ -20,8 +20,8 @@ public class WeightedRoutingMetadataTests extends AbstractXContentTestCase weights = Map.of("a", "1", "b", "1", "c", "0"); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); - WeightedRoutingMetadata wrrMetadata = new WeightedRoutingMetadata(weightedRouting); - return wrrMetadata; + WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); + return weightedRoutingMetadata; } @Override @@ -33,5 +33,4 @@ protected WeightedRoutingMetadata doParseInstance(XContentParser parser) throws protected boolean supportsUnknownFields() { return false; } - } diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 2f9fe3cd991ac..c9c3a929d2b97 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -762,8 +762,8 @@ public void testAdaptiveReplicaSelectionWithZoneAwarenessIgnored() throws Except terminate(threadPool); } - private ClusterState clusterStateForWRR(String[] indexNames, int numShards, int numReplicas) { - DiscoveryNode[] allNodes = setUpNodesWRR(); + private ClusterState clusterStateForWeightedRouting(String[] indexNames, int numShards, int numReplicas) { + DiscoveryNode[] allNodes = setUpNodesForWeightedRouting(); ClusterState state = ClusterStateCreationUtils.state(allNodes[0], allNodes[6], allNodes); Map> discoveryNodeMap = new HashMap<>(); @@ -783,22 +783,22 @@ private ClusterState clusterStateForWRR(String[] indexNames, int numShards, int discoveryNodeMap.put("c", nodesZoneC); // Updating cluster state with node, index and shard details - state = updateStatetoTestWRR(indexNames, numShards, numReplicas, state, discoveryNodeMap); + state = updateStatetoTestWeightedRouting(indexNames, numShards, numReplicas, state, discoveryNodeMap); return state; } - private ClusterState setWRRWeights(ClusterState clusterState, Map weights) { - WeightedRouting wrrWeight = new WeightedRouting("zone", weights); - WeightedRoutingMetadata wrrMetadata = new WeightedRoutingMetadata(wrrWeight); + private ClusterState setWeightedRoutingWeights(ClusterState clusterState, Map weights) { + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); + WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); Metadata.Builder metadataBuilder = Metadata.builder(clusterState.metadata()); - metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, wrrMetadata); + metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); clusterState = ClusterState.builder(clusterState).metadata(metadataBuilder).build(); return clusterState; } - public void testWRR() throws Exception { + public void testWeightedOperationRouting() throws Exception { final int numIndices = 2; final int numShards = 3; final int numReplicas = 2; @@ -807,89 +807,93 @@ public void testWRR() throws Exception { for (int i = 0; i < numIndices; i++) { indexNames[i] = "test" + i; } + ClusterService clusterService = null; + TestThreadPool threadPool = null; + try { + ClusterState state = clusterStateForWeightedRouting(indexNames, numShards, numReplicas); - ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); - - Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - - TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); - ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); - - OperationRouting opRouting = new OperationRouting( - setting, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) - ); - assertTrue(opRouting.ignoreAwarenessAttributes()); - Set selectedNodes = new HashSet<>(); - ResponseCollectorService collector = new ResponseCollectorService(clusterService); - Map outstandingRequests = new HashMap<>(); - - // Setting up weights for weighted round-robin in cluster state - Map weights = Map.of("a", "1", "b", "1", "c", "0"); - state = setWRRWeights(state, weights); - - ClusterState.Builder builder = ClusterState.builder(state); - ClusterServiceUtils.setState(clusterService, builder); + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); + threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + clusterService = ClusterServiceUtils.createClusterService(threadPool); - // search shards call - GroupShardsIterator groupIterator = opRouting.searchShards( - state, - indexNames, - null, - null, - collector, - outstandingRequests + OperationRouting opRouting = new OperationRouting( + setting, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) + ); + assertTrue(opRouting.ignoreAwarenessAttributes()); + Set selectedNodes = new HashSet<>(); + ResponseCollectorService collector = new ResponseCollectorService(clusterService); + Map outstandingRequests = new HashMap<>(); + + // Setting up weights for weighted round-robin in cluster state + Map weights = Map.of("a", "1", "b", "1", "c", "0"); + state = setWeightedRoutingWeights(state, weights); + + ClusterState.Builder builder = ClusterState.builder(state); + ClusterServiceUtils.setState(clusterService, builder); + + opRouting.setClusterService(clusterService); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); + + // search shards call + GroupShardsIterator groupIterator = opRouting.searchShards( + state, + indexNames, + null, + null, + collector, + outstandingRequests - ); + ); - for (ShardIterator it : groupIterator) { - List shardRoutings = Collections.singletonList(it.nextOrNull()); - for (ShardRouting shardRouting : shardRoutings) { - selectedNodes.add(shardRouting.currentNodeId()); + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } + } + // tests no nodes are assigned to nodes in zone c + for (String nodeID : selectedNodes) { + // No shards are assigned to nodes in zone c since its weight is 0 + assertFalse(nodeID.contains("c")); } - } - // tests no nodes are assigned to nodes in zone c - for (String nodeID : selectedNodes) { - // No shards are assigned to nodes in zone c since its weight is 0 - assertFalse(nodeID.contains("c")); - } - selectedNodes = new HashSet<>(); - setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); + selectedNodes = new HashSet<>(); + setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - // Updating weighted round robin weights in cluster state - weights = Map.of("a", "1", "b", "0", "c", "1"); - state = setWRRWeights(state, weights); + // Updating weighted round robin weights in cluster state + weights = Map.of("a", "1", "b", "0", "c", "1"); + state = setWeightedRoutingWeights(state, weights); - builder = ClusterState.builder(state); - ClusterServiceUtils.setState(clusterService, builder); + builder = ClusterState.builder(state); + ClusterServiceUtils.setState(clusterService, builder); - opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); + opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + opRouting.setClusterService(clusterService); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); - // search shards call - groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + // search shards call + groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); - for (ShardIterator it : groupIterator) { - List shardRoutings = Collections.singletonList(it.nextOrNull()); - for (ShardRouting shardRouting : shardRoutings) { - selectedNodes.add(shardRouting.currentNodeId()); + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } } + // tests that no shards are assigned to zone with weight zero + for (String nodeID : selectedNodes) { + // No shards are assigned to nodes in zone b since its weight is 0 + assertFalse(nodeID.contains("b")); + } + } finally { + IOUtils.close(clusterService); + terminate(threadPool); } - // tests that no shards are assigned to zone with weight zero - for (String nodeID : selectedNodes) { - // No shards are assigned to nodes in zone b since its weight is 0 - assertFalse(nodeID.contains("b")); - } - IOUtils.close(clusterService); - terminate(threadPool); } - public void testWRRShardsCaching() throws Exception { + public void testWeightedOperationRoutingCaching() throws Exception { final int numIndices = 2; final int numShards = 3; final int numReplicas = 2; @@ -898,81 +902,84 @@ public void testWRRShardsCaching() throws Exception { for (int i = 0; i < numIndices; i++) { indexNames[i] = "test" + i; } + ClusterService clusterService = null; + TestThreadPool threadPool = null; + try { + ClusterState state = clusterStateForWeightedRouting(indexNames, numShards, numReplicas); - ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); - - Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - - TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); - ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); - - OperationRouting opRouting = new OperationRouting( - setting, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) - ); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); - - assertTrue(opRouting.ignoreAwarenessAttributes()); - ResponseCollectorService collector = new ResponseCollectorService(clusterService); - Map outstandingRequests = new HashMap<>(); - - // Setting up weights for weighted round-robin in cluster state - Map weights = Map.of("a", "1", "b", "1", "c", "0"); - state = setWRRWeights(state, weights); - ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); - - // search shards call - GroupShardsIterator groupIterator = opRouting.searchShards( - state, - indexNames, - null, - null, - collector, - outstandingRequests - ); - - // shard wrr ordering details are not present in cache, the details are calculated and put in cache - assertEquals(6, opRouting.getWeightedRoutingCache().misses()); - assertEquals(6, opRouting.getWeightedRoutingCache().size()); - - // Calling operation routing again without any cluster state change to test that wrr shard routing details are - // fetched from cache - groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); - - // details are fetched from cache - assertEquals(12, opRouting.getWeightedRoutingCache().hits()); - // cache count stays same - assertEquals(6, opRouting.getWeightedRoutingCache().size()); - // cache misses stay same - assertEquals(6, opRouting.getWeightedRoutingCache().misses()); - - // Updating cluster state to test wrr shard routing details are calculated again - weights = Map.of("a", "1", "b", "0", "c", "1"); - // building new cluster state - ClusterState state2 = setWRRWeights(state, weights); - ClusterServiceUtils.setState(clusterService, ClusterState.builder(state2)); - - ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); - opRouting.getWeightedRoutingCache().clusterChanged(event); - - // cache is invalidated after cluster state change, cache count is zero - assertEquals(0, opRouting.getWeightedRoutingCache().size()); + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - // search shards call - groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); + threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + clusterService = ClusterServiceUtils.createClusterService(threadPool); - // cache hit remain same - assertEquals(12, opRouting.getWeightedRoutingCache().hits()); - // cache miss increases by 6 - assertEquals(12, opRouting.getWeightedRoutingCache().misses()); - assertEquals(6, opRouting.getWeightedRoutingCache().size()); + OperationRouting opRouting = new OperationRouting( + setting, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) + ); + opRouting.setClusterService(clusterService); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); + + assertTrue(opRouting.ignoreAwarenessAttributes()); + ResponseCollectorService collector = new ResponseCollectorService(clusterService); + Map outstandingRequests = new HashMap<>(); + + // Setting up weights for weighted round-robin in cluster state + Map weights = Map.of("a", "1", "b", "1", "c", "0"); + state = setWeightedRoutingWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); + + // search shards call + GroupShardsIterator groupIterator = opRouting.searchShards( + state, + indexNames, + null, + null, + collector, + outstandingRequests + ); - IOUtils.close(clusterService); - terminate(threadPool); + // shard weighted routing ordering details are not present in cache, the details are calculated and put in cache + assertEquals(6, opRouting.getWeightedRoutingCache().misses()); + assertEquals(6, opRouting.getWeightedRoutingCache().size()); + + // Calling operation routing again without any cluster state change to test that weighted routing details + // are fetched from cache + groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + + // details are fetched from cache + assertEquals(12, opRouting.getWeightedRoutingCache().hits()); + // cache count stays same + assertEquals(6, opRouting.getWeightedRoutingCache().size()); + // cache misses stay same + assertEquals(6, opRouting.getWeightedRoutingCache().misses()); + + // Updating cluster state to test weighted routing details are calculated again + weights = Map.of("a", "1", "b", "0", "c", "1"); + // building new cluster state + ClusterState state2 = setWeightedRoutingWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state2)); + + ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); + opRouting.getWeightedRoutingCache().clusterChanged(event); + + // cache is invalidated after cluster state change, cache count is zero + assertEquals(0, opRouting.getWeightedRoutingCache().size()); + + // search shards call + groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); + + // cache hit remain same + assertEquals(12, opRouting.getWeightedRoutingCache().hits()); + // cache miss increases by 6 + assertEquals(12, opRouting.getWeightedRoutingCache().misses()); + assertEquals(6, opRouting.getWeightedRoutingCache().size()); + } finally { + IOUtils.close(clusterService); + terminate(threadPool); + } } - public void testWRRWithWeightUndefinedForOneZone() throws Exception { + public void testWeightedOperationRoutingWeightUndefinedForOneZone() throws Exception { final int numIndices = 2; final int numShards = 3; final int numReplicas = 2; @@ -981,93 +988,99 @@ public void testWRRWithWeightUndefinedForOneZone() throws Exception { for (int i = 0; i < numIndices; i++) { indexNames[i] = "test" + i; } - ClusterState state = clusterStateForWRR(indexNames, numShards, numReplicas); - - Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); - ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + ClusterService clusterService = null; + TestThreadPool threadPool = null; + try { + ClusterState state = clusterStateForWeightedRouting(indexNames, numShards, numReplicas); - OperationRouting opRouting = new OperationRouting( - setting, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) - ); - assertTrue(opRouting.ignoreAwarenessAttributes()); - Set selectedNodes = new HashSet<>(); - ResponseCollectorService collector = new ResponseCollectorService(clusterService); - Map outstandingRequests = new HashMap<>(); + Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - // Setting up weights for weighted round-robin in cluster state, weight for nodes in zone b is not set - Map weights = Map.of("a", "1", "c", "0"); - state = setWRRWeights(state, weights); - ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); + threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + clusterService = ClusterServiceUtils.createClusterService(threadPool); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); - // search shards call - GroupShardsIterator groupIterator = opRouting.searchShards( - state, - indexNames, - null, - null, - collector, - outstandingRequests + OperationRouting opRouting = new OperationRouting( + setting, + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) + ); + assertTrue(opRouting.ignoreAwarenessAttributes()); + Set selectedNodes = new HashSet<>(); + ResponseCollectorService collector = new ResponseCollectorService(clusterService); + Map outstandingRequests = new HashMap<>(); + + // Setting up weights for weighted round-robin in cluster state, weight for nodes in zone b is not set + Map weights = Map.of("a", "1", "c", "0"); + state = setWeightedRoutingWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); + + opRouting.setClusterService(clusterService); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); + // search shards call + GroupShardsIterator groupIterator = opRouting.searchShards( + state, + indexNames, + null, + null, + collector, + outstandingRequests - ); + ); - for (ShardIterator it : groupIterator) { - List shardRoutings = Collections.singletonList(it.nextOrNull()); - for (ShardRouting shardRouting : shardRoutings) { - selectedNodes.add(shardRouting.currentNodeId()); + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } } - } - boolean weighAwayNodesInUndefinedZone = true; - // tests no shards are assigned to nodes in zone c - // tests shards are assigned to nodes in zone b - for (String nodeID : selectedNodes) { - // shard from nodes in zone c is not selected since its weight is 0 - assertFalse(nodeID.contains("c")); - if (nodeID.contains("b")) { - weighAwayNodesInUndefinedZone = false; + boolean weighAwayNodesInUndefinedZone = true; + // tests no shards are assigned to nodes in zone c + // tests shards are assigned to nodes in zone b + for (String nodeID : selectedNodes) { + // shard from nodes in zone c is not selected since its weight is 0 + assertFalse(nodeID.contains("c")); + if (nodeID.contains("b")) { + weighAwayNodesInUndefinedZone = false; + } } - } - assertFalse(weighAwayNodesInUndefinedZone); + assertFalse(weighAwayNodesInUndefinedZone); - selectedNodes = new HashSet<>(); - setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); + selectedNodes = new HashSet<>(); + setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - // Updating weighted round robin weights in cluster state - weights = Map.of("a", "0", "b", "1"); + // Updating weighted round robin weights in cluster state + weights = Map.of("a", "0", "b", "1"); - state = setWRRWeights(state, weights); - ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); + state = setWeightedRoutingWeights(state, weights); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); - opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); + opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + opRouting.setClusterService(clusterService); + opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); - // search shards call - groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); + // search shards call + groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); - for (ShardIterator it : groupIterator) { - List shardRoutings = Collections.singletonList(it.nextOrNull()); - for (ShardRouting shardRouting : shardRoutings) { - selectedNodes.add(shardRouting.currentNodeId()); + for (ShardIterator it : groupIterator) { + List shardRoutings = Collections.singletonList(it.nextOrNull()); + for (ShardRouting shardRouting : shardRoutings) { + selectedNodes.add(shardRouting.currentNodeId()); + } } - } - // tests that no shards are assigned to zone with weight zero - // tests shards are assigned to nodes in zone c - weighAwayNodesInUndefinedZone = true; - for (String nodeID : selectedNodes) { - // shard from nodes in zone a is not selected since its weight is 0 - assertFalse(nodeID.contains("a")); - if (nodeID.contains("c")) { - weighAwayNodesInUndefinedZone = false; + // tests that no shards are assigned to zone with weight zero + // tests shards are assigned to nodes in zone c + weighAwayNodesInUndefinedZone = true; + for (String nodeID : selectedNodes) { + // shard from nodes in zone a is not selected since its weight is 0 + assertFalse(nodeID.contains("a")); + if (nodeID.contains("c")) { + weighAwayNodesInUndefinedZone = false; + } } + assertFalse(weighAwayNodesInUndefinedZone); + } finally { + IOUtils.close(clusterService); + terminate(threadPool); } - assertFalse(weighAwayNodesInUndefinedZone); - IOUtils.close(clusterService); - terminate(threadPool); } private DiscoveryNode[] setupNodes() { @@ -1096,7 +1109,7 @@ private DiscoveryNode[] setupNodes() { return allNodes; } - private DiscoveryNode[] setUpNodesWRR() { + private DiscoveryNode[] setUpNodesForWeightedRouting() { List zones = Arrays.asList("a", "a", "b", "b", "c", "c"); DiscoveryNode[] allNodes = new DiscoveryNode[7]; int i = 0; @@ -1179,7 +1192,7 @@ private ClusterState updateStatetoTestARS( return clusterState.build(); } - private ClusterState updateStatetoTestWRR( + private ClusterState updateStatetoTestWeightedRouting( String[] indices, int numberOfShards, int numberOfReplicas, @@ -1234,11 +1247,11 @@ private ClusterState updateStatetoTestWRR( } routingTableBuilder.add(indexRoutingTableBuilder.build()); } - // add wrr weights in metadata + // add weighted routing weights in metadata Map weights = Map.of("a", "1", "b", "1", "c", "0"); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); - WeightedRoutingMetadata wrrMetadata = new WeightedRoutingMetadata(weightedRouting); - metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, wrrMetadata); + WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); + metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); clusterState.metadata(metadataBuilder); clusterState.routingTable(routingTableBuilder.build()); return clusterState.build(); diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index 223c9531dfe1c..5ff229682cd5e 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -48,6 +48,8 @@ import org.opensearch.cluster.routing.ShardRouting; import org.opensearch.cluster.routing.ShardShuffler; import org.opensearch.cluster.routing.ShardsIterator; +import org.opensearch.cluster.routing.WeightedRouting; +import org.opensearch.cluster.routing.WeightedRoutingCache; import org.opensearch.cluster.routing.allocation.AllocationService; import org.opensearch.cluster.routing.allocation.decider.ClusterRebalanceAllocationDecider; import org.opensearch.cluster.service.ClusterService; @@ -504,4 +506,94 @@ public void testReplicaShardPreferenceIters() throws Exception { } } + public void testWeightedRouting() { + TestThreadPool threadPool = null; + try { + Settings.Builder settings = Settings.builder() + .put("cluster.routing.allocation.node_concurrent_recoveries", 10) + .put("cluster.routing.allocation.awareness.attributes", "zone"); + AllocationService strategy = createAllocationService(settings.build()); + + Metadata metadata = Metadata.builder() + .put(IndexMetadata.builder("test").settings(settings(Version.CURRENT)).numberOfShards(1).numberOfReplicas(2)) + .build(); + + RoutingTable routingTable = RoutingTable.builder().addAsNew(metadata.index("test")).build(); + + ClusterState clusterState = ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.getDefault(Settings.EMPTY)) + .metadata(metadata) + .routingTable(routingTable) + .build(); + + threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + + Map node1Attributes = new HashMap<>(); + node1Attributes.put("zone", "zone1"); + Map node2Attributes = new HashMap<>(); + node2Attributes.put("zone", "zone2"); + Map node3Attributes = new HashMap<>(); + node3Attributes.put("zone", "zone3"); + clusterState = ClusterState.builder(clusterState) + .nodes( + DiscoveryNodes.builder() + .add(newNode("node1", unmodifiableMap(node1Attributes))) + .add(newNode("node2", unmodifiableMap(node2Attributes))) + .add(newNode("node3", unmodifiableMap(node3Attributes))) + .localNodeId("node1") + ) + .build(); + clusterState = strategy.reroute(clusterState, "reroute"); + + clusterState = startInitializingShardsAndReroute(strategy, clusterState); + clusterState = startInitializingShardsAndReroute(strategy, clusterState); + + WeightedRoutingCache cache = new WeightedRoutingCache(clusterService); + Map weights = Map.of("zone1", "1", "zone2", "1", "zone3", "0"); + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); + + ShardIterator shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + + assertEquals(2, shardIterator.size()); + ShardRouting shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(shardRouting.currentNodeId().equals("node3")); + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(shardRouting.currentNodeId().equals("node3")); + cache.close(); + + weights = Map.of("zone1", "1", "zone2", "1", "zone3", "1"); + weightedRouting = new WeightedRouting("zone", weights); + shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + assertEquals(3, shardIterator.size()); + cache.close(); + + weights = Map.of("zone1", "-1", "zone2", "0", "zone3", "1"); + weightedRouting = new WeightedRouting("zone", weights); + shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + assertEquals(1, shardIterator.size()); + cache.close(); + + weights = Map.of("zone1", "0", "zone2", "0", "zone3", "0"); + weightedRouting = new WeightedRouting("zone", weights); + shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + assertEquals(0, shardIterator.size()); + cache.close(); + } finally { + terminate(threadPool); + } + } } From 17dc58c59f5d69eb6a22ae63896a50eb998f1201 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Tue, 13 Sep 2022 21:57:12 +0530 Subject: [PATCH 21/55] Update metadata minimal supported version Signed-off-by: Anshu Agarwal --- .../opensearch/cluster/metadata/WeightedRoutingMetadata.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java index 9c9b8bf38b4a7..9c85fdfcc1ed2 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java @@ -69,7 +69,7 @@ public String getWriteableName() { @Override public Version getMinimalSupportedVersion() { - return Version.V_2_3_0; + return Version.V_2_4_0; } @Override From ed0cc1bc24f6ec936acf4db7f62a4b90884da04c Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 14 Sep 2022 08:11:40 +0530 Subject: [PATCH 22/55] Add cluster setting for default weight Signed-off-by: Anshu Agarwal --- CHANGELOG.md | 1 - .../routing/IndexShardRoutingTable.java | 26 ++++++++++++++----- .../cluster/routing/OperationRouting.java | 25 +++++++++++++++++- .../common/settings/ClusterSettings.java | 1 + .../structure/RoutingIteratorTests.java | 8 +++--- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75c3d8d407a10..cc898f1ccf834 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,6 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Use RemoteSegmentStoreDirectory instead of RemoteDirectory ([#4240](https://github.com/opensearch-project/OpenSearch/pull/4240)) - Plugin ZIP publication groupId value is configurable ([#4156](https://github.com/opensearch-project/OpenSearch/pull/4156)) - Weighted round-robin scheduling policy for shard coordination traffic ([#4241](https://github.com/opensearch-project/OpenSearch/pull/4241)) -- Update to Netty 4.1.80.Final ([#4359](https://github.com/opensearch-project/OpenSearch/pull/4359)) - Add index specific setting for remote repository ([#4253](https://github.com/opensearch-project/OpenSearch/pull/4253)) - [Segment Replication] Update replicas to commit SegmentInfos instead of relying on SIS files from primary shards. ([#4402](https://github.com/opensearch-project/OpenSearch/pull/4402)) - [CCR] Add getHistoryOperationsFromTranslog method to fetch the history snapshot from translogs ([#3948](https://github.com/opensearch-project/OpenSearch/pull/3948)) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index c9f4c8a69e490..b6ca69d75a90d 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -304,7 +304,8 @@ public ShardIterator activeInitializingShardsRankedIt( public ShardIterator activeInitializingShardsWeightedIt( WeightedRouting weightedRouting, DiscoveryNodes nodes, - WeightedRoutingCache cache + WeightedRoutingCache cache, + int defaultWeight ) { final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(); @@ -312,13 +313,18 @@ public ShardIterator activeInitializingShardsWeightedIt( if (cache.get(new WeightedRoutingCache.Key(shardId)) != null) { orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); } else { - orderedActiveShards = shardsOrderedByWeight(activeShards, weightedRouting, nodes); + orderedActiveShards = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); cache.put(new WeightedRoutingCache.Key(shardId), orderedActiveShards); } ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); if (!allInitializingShards.isEmpty()) { - List orderedInitializingShards = shardsOrderedByWeight(allInitializingShards, weightedRouting, nodes); + List orderedInitializingShards = shardsOrderedByWeight( + allInitializingShards, + weightedRouting, + nodes, + defaultWeight + ); ordered.addAll(orderedInitializingShards); } return new PlainShardIterator(shardId, ordered); @@ -327,9 +333,14 @@ public ShardIterator activeInitializingShardsWeightedIt( /** * Returns a list containing shard routings ordered using weighted round-robin scheduling. */ - private List shardsOrderedByWeight(List shards, WeightedRouting weightedRouting, DiscoveryNodes nodes) { + private List shardsOrderedByWeight( + List shards, + WeightedRouting weightedRouting, + DiscoveryNodes nodes, + int defaultWeight + ) { WeightedRoundRobin weightedRoundRobin = new WeightedRoundRobin<>( - calculateShardWeight(shards, weightedRouting, nodes) + calculateShardWeight(shards, weightedRouting, nodes, defaultWeight) ); List> shardsOrderedbyWeight = weightedRoundRobin.orderEntities(); List orderedShardRouting = new ArrayList<>(activeShards.size()); @@ -349,14 +360,15 @@ private List shardsOrderedByWeight(List shards, Weig private List> calculateShardWeight( List shards, WeightedRouting weightedRouting, - DiscoveryNodes nodes + DiscoveryNodes nodes, + int defaultWeight ) { List> shardsWithWeights = new ArrayList<>(); for (ShardRouting shard : shards) { DiscoveryNode node = nodes.get(shard.currentNodeId()); String attVal = node.getAttributes().get(weightedRouting.attributeName()); // If weight for a zone is not defined, considering it as 1 by default - Double weight = Double.parseDouble(weightedRouting.weights().getOrDefault(attVal, 1).toString()); + Double weight = Double.parseDouble(weightedRouting.weights().getOrDefault(attVal, defaultWeight).toString()); shardsWithWeights.add(new WeightedRoundRobin.Entity<>(weight, shard)); } return shardsWithWeights; diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index a5acbed983cc3..9c99a871658dd 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -78,9 +78,17 @@ public class OperationRouting { Setting.Property.Dynamic, Setting.Property.NodeScope ); + public static final Setting WEIGHTED_ROUTING_DEFAULT_WEIGHT = Setting.intSetting( + "cluster.routing.weighted.default_weight", + 1, + 1, + Setting.Property.Dynamic, + Setting.Property.NodeScope + ); private volatile List awarenessAttributes; private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; + private volatile int weightedRoutingDefaultWeight; private WeightedRoutingCache weightedRoutingCache; private ClusterService clusterService; @@ -94,8 +102,10 @@ public OperationRouting(Settings settings, ClusterSettings clusterSettings) { this::setAwarenessAttributes ); this.useAdaptiveReplicaSelection = USE_ADAPTIVE_REPLICA_SELECTION_SETTING.get(settings); + this.weightedRoutingDefaultWeight = WEIGHTED_ROUTING_DEFAULT_WEIGHT.get(settings); clusterSettings.addSettingsUpdateConsumer(USE_ADAPTIVE_REPLICA_SELECTION_SETTING, this::setUseAdaptiveReplicaSelection); clusterSettings.addSettingsUpdateConsumer(IGNORE_AWARENESS_ATTRIBUTES_SETTING, this::setIgnoreAwarenessAttributes); + clusterSettings.addSettingsUpdateConsumer(WEIGHTED_ROUTING_DEFAULT_WEIGHT, this::setWeightedRoutingDefaultWeight); } void setUseAdaptiveReplicaSelection(boolean useAdaptiveReplicaSelection) { @@ -106,6 +116,10 @@ void setIgnoreAwarenessAttributes(boolean ignoreAwarenessAttributes) { this.ignoreAwarenessAttr = ignoreAwarenessAttributes; } + void setWeightedRoutingDefaultWeight(int weightedRoutingDefaultWeight) { + this.weightedRoutingDefaultWeight = weightedRoutingDefaultWeight; + } + public boolean isIgnoreAwarenessAttr() { return ignoreAwarenessAttr; } @@ -122,6 +136,10 @@ public boolean ignoreAwarenessAttributes() { return this.awarenessAttributes.isEmpty() || this.ignoreAwarenessAttr; } + public int getWeightedRoutingDefaultWeight() { + return this.weightedRoutingDefaultWeight; + } + @Inject public void setClusterService(ClusterService clusterService) { this.clusterService = clusterService; @@ -322,7 +340,12 @@ private ShardIterator shardRoutings( ) { WeightedRoutingMetadata weightedRoutingMetadata = clusterService.state().metadata().weightedRoutingMetadata(); if (weightedRoutingMetadata != null) { - return indexShard.activeInitializingShardsWeightedIt(weightedRoutingMetadata.getWeightedRouting(), nodes, weightedRoutingCache); + return indexShard.activeInitializingShardsWeightedIt( + weightedRoutingMetadata.getWeightedRouting(), + nodes, + weightedRoutingCache, + getWeightedRoutingDefaultWeight() + ); } else if (ignoreAwarenessAttributes()) { if (useAdaptiveReplicaSelection) { return indexShard.activeInitializingShardsRankedIt(collectorService, nodeCounts); diff --git a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java index 971fb518ff1da..1665614c18496 100644 --- a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java @@ -529,6 +529,7 @@ public void apply(Settings value, Settings current, Settings previous) { Node.BREAKER_TYPE_KEY, OperationRouting.USE_ADAPTIVE_REPLICA_SELECTION_SETTING, OperationRouting.IGNORE_AWARENESS_ATTRIBUTES_SETTING, + OperationRouting.WEIGHTED_ROUTING_DEFAULT_WEIGHT, IndexGraveyard.SETTING_MAX_TOMBSTONES, PersistentTasksClusterService.CLUSTER_TASKS_ALLOCATION_RECHECK_INTERVAL_SETTING, EnableAssignmentDecider.CLUSTER_TASKS_ALLOCATION_ENABLE_SETTING, diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index 5ff229682cd5e..c75480ab782ba 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -555,7 +555,7 @@ public void testWeightedRouting() { ShardIterator shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); assertEquals(2, shardIterator.size()); ShardRouting shardRouting = shardIterator.nextOrNull(); @@ -571,7 +571,7 @@ public void testWeightedRouting() { shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); assertEquals(3, shardIterator.size()); cache.close(); @@ -580,7 +580,7 @@ public void testWeightedRouting() { shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); assertEquals(1, shardIterator.size()); cache.close(); @@ -589,7 +589,7 @@ public void testWeightedRouting() { shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); assertEquals(0, shardIterator.size()); cache.close(); } finally { From 5a5cb11a9a450526945f658853b00f1b61001f8b Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 14 Sep 2022 08:37:30 +0530 Subject: [PATCH 23/55] Fix tests due to the change Signed-off-by: Anshu Agarwal --- .../opensearch/cluster/metadata/WeightedRoutingMetadata.java | 2 +- .../org/opensearch/cluster/routing/OperationRouting.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java index 9c85fdfcc1ed2..6ab2cf22adb02 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java @@ -28,7 +28,7 @@ import java.util.Map; /** - * Contains metadata for weighted round-robin shard routing weights + * Contains metadata for weighted routing * * @opensearch.internal */ diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 9c99a871658dd..8763784a76e2e 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -338,7 +338,10 @@ private ShardIterator shardRoutings( @Nullable ResponseCollectorService collectorService, @Nullable Map nodeCounts ) { - WeightedRoutingMetadata weightedRoutingMetadata = clusterService.state().metadata().weightedRoutingMetadata(); + WeightedRoutingMetadata weightedRoutingMetadata = null; + if (clusterService != null) { + weightedRoutingMetadata = clusterService.state().metadata().weightedRoutingMetadata(); + } if (weightedRoutingMetadata != null) { return indexShard.activeInitializingShardsWeightedIt( weightedRoutingMetadata.getWeightedRouting(), From 1c339648379fe26c210c475317e12fc2935b0312 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 14 Sep 2022 10:27:37 +0530 Subject: [PATCH 24/55] Fix cache concurrency issue Signed-off-by: Anshu Agarwal --- .../opensearch/cluster/routing/IndexShardRoutingTable.java | 7 +++---- .../opensearch/cluster/routing/OperationRoutingTests.java | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index b6ca69d75a90d..a972ce4e61b5b 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -309,10 +309,9 @@ public ShardIterator activeInitializingShardsWeightedIt( ) { final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(); - List orderedActiveShards; - if (cache.get(new WeightedRoutingCache.Key(shardId)) != null) { - orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); - } else { + List orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); + if (orderedActiveShards == null) + { orderedActiveShards = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); cache.put(new WeightedRoutingCache.Key(shardId), orderedActiveShards); } diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index c9c3a929d2b97..6cad82e8ead6b 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -947,7 +947,7 @@ public void testWeightedOperationRoutingCaching() throws Exception { groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); // details are fetched from cache - assertEquals(12, opRouting.getWeightedRoutingCache().hits()); + assertEquals(6, opRouting.getWeightedRoutingCache().hits()); // cache count stays same assertEquals(6, opRouting.getWeightedRoutingCache().size()); // cache misses stay same @@ -969,7 +969,7 @@ public void testWeightedOperationRoutingCaching() throws Exception { groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); // cache hit remain same - assertEquals(12, opRouting.getWeightedRoutingCache().hits()); + assertEquals(6, opRouting.getWeightedRoutingCache().hits()); // cache miss increases by 6 assertEquals(12, opRouting.getWeightedRoutingCache().misses()); assertEquals(6, opRouting.getWeightedRoutingCache().size()); From f8638f210b009c1c35ad84d5563b3358e133f89a Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 14 Sep 2022 10:40:25 +0530 Subject: [PATCH 25/55] Spotless check fix Signed-off-by: Anshu Agarwal --- .../org/opensearch/cluster/routing/IndexShardRoutingTable.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index a972ce4e61b5b..8727652d8611a 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -310,8 +310,7 @@ public ShardIterator activeInitializingShardsWeightedIt( final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(); List orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); - if (orderedActiveShards == null) - { + if (orderedActiveShards == null) { orderedActiveShards = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); cache.put(new WeightedRoutingCache.Key(shardId), orderedActiveShards); } From 4016d2759ad6314d731d684aa7c0cb7206da42b9 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 15 Sep 2022 12:18:47 +0530 Subject: [PATCH 26/55] Fix weighted round robin logic case when there is an entity with weight 0 Signed-off-by: Anshu Agarwal --- .../cluster/routing/WeightedRoundRobin.java | 3 -- .../routing/WeightedRoundRobinTests.java | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java index 0484f8cd0d93e..15d437db9c8ff 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoundRobin.java @@ -36,9 +36,6 @@ public List> orderEntities() { if (size == 0) { return null; } - if (size == 1) { - return entities; - } // Find maximum weight and greatest common divisor of weight across all entities double maxWeight = 0; double sumWeight = 0; diff --git a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java index 81e7992410940..5f62d30486e86 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoundRobinTests.java @@ -110,6 +110,42 @@ public void testWeightedRoundRobinOrder() { } assertEquals(3, countB); assertEquals(10000, countD); + + // weights set C:0 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(0, "C")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList(); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + assertEquals(expectedOrdering, actualOrdering); + + // weights set C:1 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(1, "C")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList("C"); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + assertEquals(expectedOrdering, actualOrdering); + + // weights set C:2 + entity = new ArrayList>(); + entity.add(new WeightedRoundRobin.Entity<>(2, "C")); + weightedRoundRobin = new WeightedRoundRobin(entity); + orderedEntities = weightedRoundRobin.orderEntities(); + expectedOrdering = Arrays.asList("C", "C"); + actualOrdering = new ArrayList<>(); + for (WeightedRoundRobin.Entity en : orderedEntities) { + actualOrdering.add(en.getTarget()); + } + assertEquals(expectedOrdering, actualOrdering); } } From c98606de0d87f0feedb3ca46ceb0ae0dea4dc2fc Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 15 Sep 2022 16:48:34 +0530 Subject: [PATCH 27/55] Changes weight data type to double Signed-off-by: Anshu Agarwal --- .../metadata/WeightedRoutingMetadata.java | 8 ++++---- .../cluster/routing/IndexShardRoutingTable.java | 8 ++++---- .../cluster/routing/OperationRouting.java | 12 ++++++------ .../cluster/routing/WeightedRouting.java | 10 +++++----- .../metadata/WeightedRoutingMetadataTests.java | 2 +- .../cluster/routing/OperationRoutingTests.java | 16 ++++++++-------- .../cluster/structure/RoutingIteratorTests.java | 8 ++++---- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java index 6ab2cf22adb02..fbe7692bd52e2 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java @@ -85,9 +85,9 @@ public static NamedDiff readDiffFrom(StreamInput in) throws IOE public static WeightedRoutingMetadata fromXContent(XContentParser parser) throws IOException { String attrKey = null; - Object attrValue; + Double attrValue; String attributeName = null; - Map weights = new HashMap<>(); + Map weights = new HashMap<>(); WeightedRouting weightedRouting = null; XContentParser.Token token; // move to the first alias @@ -115,7 +115,7 @@ public static WeightedRoutingMetadata fromXContent(XContentParser parser) throws if (token == XContentParser.Token.FIELD_NAME) { attrKey = parser.currentName(); } else if (token == XContentParser.Token.VALUE_STRING) { - attrValue = parser.text(); + attrValue = Double.parseDouble(parser.text()); weights.put(attrKey, attrValue); } else { throw new OpenSearchParseException( @@ -153,7 +153,7 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par public static void toXContent(WeightedRouting weightedRouting, XContentBuilder builder) throws IOException { builder.startObject(AWARENESS); builder.startObject(weightedRouting.attributeName()); - for (Map.Entry entry : weightedRouting.weights().entrySet()) { + for (Map.Entry entry : weightedRouting.weights().entrySet()) { builder.field(entry.getKey(), entry.getValue()); } builder.endObject(); diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index 8727652d8611a..b54caad6584e3 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -305,7 +305,7 @@ public ShardIterator activeInitializingShardsWeightedIt( WeightedRouting weightedRouting, DiscoveryNodes nodes, WeightedRoutingCache cache, - int defaultWeight + double defaultWeight ) { final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(); @@ -335,7 +335,7 @@ private List shardsOrderedByWeight( List shards, WeightedRouting weightedRouting, DiscoveryNodes nodes, - int defaultWeight + double defaultWeight ) { WeightedRoundRobin weightedRoundRobin = new WeightedRoundRobin<>( calculateShardWeight(shards, weightedRouting, nodes, defaultWeight) @@ -359,14 +359,14 @@ private List> calculateShardWeight( List shards, WeightedRouting weightedRouting, DiscoveryNodes nodes, - int defaultWeight + double defaultWeight ) { List> shardsWithWeights = new ArrayList<>(); for (ShardRouting shard : shards) { DiscoveryNode node = nodes.get(shard.currentNodeId()); String attVal = node.getAttributes().get(weightedRouting.attributeName()); // If weight for a zone is not defined, considering it as 1 by default - Double weight = Double.parseDouble(weightedRouting.weights().getOrDefault(attVal, defaultWeight).toString()); + Double weight = weightedRouting.weights().getOrDefault(attVal, defaultWeight); shardsWithWeights.add(new WeightedRoundRobin.Entity<>(weight, shard)); } return shardsWithWeights; diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 8763784a76e2e..175298374415d 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -78,17 +78,17 @@ public class OperationRouting { Setting.Property.Dynamic, Setting.Property.NodeScope ); - public static final Setting WEIGHTED_ROUTING_DEFAULT_WEIGHT = Setting.intSetting( + public static final Setting WEIGHTED_ROUTING_DEFAULT_WEIGHT = Setting.doubleSetting( "cluster.routing.weighted.default_weight", - 1, - 1, + 1.0, + 1.0, Setting.Property.Dynamic, Setting.Property.NodeScope ); private volatile List awarenessAttributes; private volatile boolean useAdaptiveReplicaSelection; private volatile boolean ignoreAwarenessAttr; - private volatile int weightedRoutingDefaultWeight; + private volatile double weightedRoutingDefaultWeight; private WeightedRoutingCache weightedRoutingCache; private ClusterService clusterService; @@ -116,7 +116,7 @@ void setIgnoreAwarenessAttributes(boolean ignoreAwarenessAttributes) { this.ignoreAwarenessAttr = ignoreAwarenessAttributes; } - void setWeightedRoutingDefaultWeight(int weightedRoutingDefaultWeight) { + void setWeightedRoutingDefaultWeight(double weightedRoutingDefaultWeight) { this.weightedRoutingDefaultWeight = weightedRoutingDefaultWeight; } @@ -136,7 +136,7 @@ public boolean ignoreAwarenessAttributes() { return this.awarenessAttributes.isEmpty() || this.ignoreAwarenessAttr; } - public int getWeightedRoutingDefaultWeight() { + public double getWeightedRoutingDefaultWeight() { return this.weightedRoutingDefaultWeight; } diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java index 90f9b1beb2ed1..02ed0a110a42e 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java @@ -23,9 +23,9 @@ */ public class WeightedRouting implements Writeable { private String attributeName; - private Map weights; + private Map weights; - public WeightedRouting(String attributeName, Map weights) { + public WeightedRouting(String attributeName, Map weights) { this.attributeName = attributeName; this.weights = weights; } @@ -37,13 +37,13 @@ public WeightedRouting(WeightedRouting weightedRouting) { public WeightedRouting(StreamInput in) throws IOException { attributeName = in.readString(); - weights = in.readMap(); + weights = (Map) in.readGenericValue(); } @Override public void writeTo(StreamOutput out) throws IOException { out.writeString(attributeName); - out.writeMap(weights); + out.writeGenericValue(weights); } @Override @@ -67,7 +67,7 @@ public String toString() { return "WeightedRouting{" + attributeName + "}{" + weights().toString() + "}"; } - public Map weights() { + public Map weights() { return this.weights; } diff --git a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java index 01a55f7f4fa4a..a0a9d2bd9586b 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java @@ -18,7 +18,7 @@ public class WeightedRoutingMetadataTests extends AbstractXContentTestCase { @Override protected WeightedRoutingMetadata createTestInstance() { - Map weights = Map.of("a", "1", "b", "1", "c", "0"); + Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); return weightedRoutingMetadata; diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 6cad82e8ead6b..2a2c5d0fd731b 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -789,7 +789,7 @@ private ClusterState clusterStateForWeightedRouting(String[] indexNames, int num } - private ClusterState setWeightedRoutingWeights(ClusterState clusterState, Map weights) { + private ClusterState setWeightedRoutingWeights(ClusterState clusterState, Map weights) { WeightedRouting weightedRouting = new WeightedRouting("zone", weights); WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); Metadata.Builder metadataBuilder = Metadata.builder(clusterState.metadata()); @@ -827,7 +827,7 @@ public void testWeightedOperationRouting() throws Exception { Map outstandingRequests = new HashMap<>(); // Setting up weights for weighted round-robin in cluster state - Map weights = Map.of("a", "1", "b", "1", "c", "0"); + Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); state = setWeightedRoutingWeights(state, weights); ClusterState.Builder builder = ClusterState.builder(state); @@ -863,7 +863,7 @@ public void testWeightedOperationRouting() throws Exception { setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); // Updating weighted round robin weights in cluster state - weights = Map.of("a", "1", "b", "0", "c", "1"); + weights = Map.of("a", 1.0, "b", 0.0, "c", 1.0); state = setWeightedRoutingWeights(state, weights); builder = ClusterState.builder(state); @@ -924,7 +924,7 @@ public void testWeightedOperationRoutingCaching() throws Exception { Map outstandingRequests = new HashMap<>(); // Setting up weights for weighted round-robin in cluster state - Map weights = Map.of("a", "1", "b", "1", "c", "0"); + Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); state = setWeightedRoutingWeights(state, weights); ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); @@ -954,7 +954,7 @@ public void testWeightedOperationRoutingCaching() throws Exception { assertEquals(6, opRouting.getWeightedRoutingCache().misses()); // Updating cluster state to test weighted routing details are calculated again - weights = Map.of("a", "1", "b", "0", "c", "1"); + weights = Map.of("a", 1.0, "b", 0.0, "c", 1.0); // building new cluster state ClusterState state2 = setWeightedRoutingWeights(state, weights); ClusterServiceUtils.setState(clusterService, ClusterState.builder(state2)); @@ -1009,7 +1009,7 @@ public void testWeightedOperationRoutingWeightUndefinedForOneZone() throws Excep Map outstandingRequests = new HashMap<>(); // Setting up weights for weighted round-robin in cluster state, weight for nodes in zone b is not set - Map weights = Map.of("a", "1", "c", "0"); + Map weights = Map.of("a", 1.0, "c", 0.0); state = setWeightedRoutingWeights(state, weights); ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); @@ -1048,7 +1048,7 @@ public void testWeightedOperationRoutingWeightUndefinedForOneZone() throws Excep setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); // Updating weighted round robin weights in cluster state - weights = Map.of("a", "0", "b", "1"); + weights = Map.of("a", 0.0, "b", 1.0); state = setWeightedRoutingWeights(state, weights); ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); @@ -1248,7 +1248,7 @@ private ClusterState updateStatetoTestWeightedRouting( routingTableBuilder.add(indexRoutingTableBuilder.build()); } // add weighted routing weights in metadata - Map weights = Map.of("a", "1", "b", "1", "c", "0"); + Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index c75480ab782ba..0e6e7eb51b168 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -549,7 +549,7 @@ public void testWeightedRouting() { clusterState = startInitializingShardsAndReroute(strategy, clusterState); WeightedRoutingCache cache = new WeightedRoutingCache(clusterService); - Map weights = Map.of("zone1", "1", "zone2", "1", "zone3", "0"); + Map weights = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); ShardIterator shardIterator = clusterState.routingTable() @@ -566,7 +566,7 @@ public void testWeightedRouting() { assertFalse(shardRouting.currentNodeId().equals("node3")); cache.close(); - weights = Map.of("zone1", "1", "zone2", "1", "zone3", "1"); + weights = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 1.0); weightedRouting = new WeightedRouting("zone", weights); shardIterator = clusterState.routingTable() .index("test") @@ -575,7 +575,7 @@ public void testWeightedRouting() { assertEquals(3, shardIterator.size()); cache.close(); - weights = Map.of("zone1", "-1", "zone2", "0", "zone3", "1"); + weights = Map.of("zone1", -1.0, "zone2", 0.0, "zone3", 1.0); weightedRouting = new WeightedRouting("zone", weights); shardIterator = clusterState.routingTable() .index("test") @@ -584,7 +584,7 @@ public void testWeightedRouting() { assertEquals(1, shardIterator.size()); cache.close(); - weights = Map.of("zone1", "0", "zone2", "0", "zone3", "0"); + weights = Map.of("zone1", 0.0, "zone2", 0.0, "zone3", 0.0); weightedRouting = new WeightedRouting("zone", weights); shardIterator = clusterState.routingTable() .index("test") From 1bd83f3c536b302bf9af389ec5ee7d0794282b2d Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 15 Sep 2022 17:19:49 +0530 Subject: [PATCH 28/55] Fix test Signed-off-by: Anshu Agarwal --- .../opensearch/cluster/metadata/WeightedRoutingMetadata.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java index fbe7692bd52e2..6b69a208d5b97 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java @@ -114,7 +114,7 @@ public static WeightedRoutingMetadata fromXContent(XContentParser parser) throws while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { attrKey = parser.currentName(); - } else if (token == XContentParser.Token.VALUE_STRING) { + } else if (token == XContentParser.Token.VALUE_NUMBER) { attrValue = Double.parseDouble(parser.text()); weights.put(attrKey, attrValue); } else { From 8a72dc0d85732b6b7195e2b4c70389198e9fc85f Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 15 Sep 2022 18:00:59 +0530 Subject: [PATCH 29/55] Empty commit Signed-off-by: Anshu Agarwal From bff61b92ff73d43d9b93ecac7d9d71442dc299d8 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 15 Sep 2022 18:00:59 +0530 Subject: [PATCH 30/55] Empty commit Signed-off-by: Anshu Agarwal --- .../cluster/metadata/WeightedRoutingMetadataTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java index a0a9d2bd9586b..08e9167471fe1 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java @@ -21,7 +21,7 @@ protected WeightedRoutingMetadata createTestInstance() { Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); - return weightedRoutingMetadata; + return weightedRoutingMetadata; } @Override From 910261669efc86128e62c8d2cebd928e56b7540e Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 15 Sep 2022 18:32:36 +0530 Subject: [PATCH 31/55] Fix spotless check Signed-off-by: Anshu Agarwal --- .../cluster/metadata/WeightedRoutingMetadataTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java index 08e9167471fe1..a0a9d2bd9586b 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/WeightedRoutingMetadataTests.java @@ -21,7 +21,7 @@ protected WeightedRoutingMetadata createTestInstance() { Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); - return weightedRoutingMetadata; + return weightedRoutingMetadata; } @Override From a291634ac30e26d5d8c91f09141930fda7bba24e Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Fri, 16 Sep 2022 19:45:58 +0530 Subject: [PATCH 32/55] Create in-memory cache for shard routings Signed-off-by: Anshu Agarwal --- .../routing/IndexShardRoutingTable.java | 83 +++++++++---- .../cluster/routing/OperationRouting.java | 43 ++----- .../cluster/routing/WeightedRoutingCache.java | 109 ------------------ .../main/java/org/opensearch/node/Node.java | 6 - .../routing/OperationRoutingTests.java | 98 ---------------- .../structure/RoutingIteratorTests.java | 15 +-- 6 files changed, 77 insertions(+), 277 deletions(-) delete mode 100644 server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index b54caad6584e3..bc24d66447a67 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -85,6 +85,10 @@ public class IndexShardRoutingTable implements Iterable { private volatile Map activeShardsByAttributes = emptyMap(); private volatile Map initializingShardsByAttributes = emptyMap(); private final Object shardsByAttributeMutex = new Object(); + private final Object activeShardsByWeightMutex = new Object(); + private final Object initializingShardsByWeightMutex = new Object(); + private volatile Map> activeShardsByWeight = emptyMap(); + private volatile Map> initializingShardsByWeight = emptyMap(); /** * The initializing list, including ones that are initializing on a target node because of relocation. @@ -301,28 +305,13 @@ public ShardIterator activeInitializingShardsRankedIt( * @return an iterator over active and initializing shards, ordered by weighted round-robin * scheduling policy. Making sure that initializing shards are the last to iterate through. */ - public ShardIterator activeInitializingShardsWeightedIt( - WeightedRouting weightedRouting, - DiscoveryNodes nodes, - WeightedRoutingCache cache, - double defaultWeight - ) { + public ShardIterator activeInitializingShardsWeightedIt(WeightedRouting weightedRouting, DiscoveryNodes nodes, double defaultWeight) { final int seed = shuffler.nextSeed(); List ordered = new ArrayList<>(); - List orderedActiveShards = cache.get(new WeightedRoutingCache.Key(shardId)); - if (orderedActiveShards == null) { - orderedActiveShards = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); - cache.put(new WeightedRoutingCache.Key(shardId), orderedActiveShards); - } + List orderedActiveShards = getActiveShardsByWeight(weightedRouting, nodes, defaultWeight); ordered.addAll(shuffler.shuffle(orderedActiveShards, seed)); - if (!allInitializingShards.isEmpty()) { - List orderedInitializingShards = shardsOrderedByWeight( - allInitializingShards, - weightedRouting, - nodes, - defaultWeight - ); + List orderedInitializingShards = getInitializingShardsByWeight(weightedRouting, nodes, defaultWeight); ordered.addAll(orderedInitializingShards); } return new PlainShardIterator(shardId, ordered); @@ -675,7 +664,7 @@ private AttributesRoutings getActiveAttribute(AttributesKey key, DiscoveryNodes List to = collectAttributeShards(key, nodes, from); shardRoutings = new AttributesRoutings(to, Collections.unmodifiableList(from)); - activeShardsByAttributes = MapBuilder.newMapBuilder(activeShardsByAttributes).put(key, shardRoutings).immutableMap(); + activeShardsByAttributes = new MapBuilder().put(key, shardRoutings).immutableMap(); } } return shardRoutings; @@ -688,9 +677,7 @@ private AttributesRoutings getInitializingAttribute(AttributesKey key, Discovery ArrayList from = new ArrayList<>(allInitializingShards); List to = collectAttributeShards(key, nodes, from); shardRoutings = new AttributesRoutings(to, Collections.unmodifiableList(from)); - initializingShardsByAttributes = MapBuilder.newMapBuilder(initializingShardsByAttributes) - .put(key, shardRoutings) - .immutableMap(); + initializingShardsByAttributes = new MapBuilder().put(key, shardRoutings).immutableMap(); } } return shardRoutings; @@ -778,6 +765,58 @@ public int shardsMatchingPredicateCount(Predicate predicate) { return count; } + /** + * Key for WeightedRouting + * + * @opensearch.internal + */ + static class WeightedRoutingKey { + private final WeightedRouting weightedRouting; + + WeightedRoutingKey(WeightedRouting weightedRouting) { + this.weightedRouting = weightedRouting; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WeightedRoutingKey key = (WeightedRoutingKey) o; + if (!weightedRouting.equals(key.weightedRouting)) return false; + return true; + } + + @Override + public int hashCode() { + int result = weightedRouting.hashCode(); + return result; + } + } + + private List getActiveShardsByWeight(WeightedRouting weightedRouting, DiscoveryNodes nodes, double defaultWeight) { + WeightedRoutingKey key = new WeightedRoutingKey(weightedRouting); + List shardRoutings = activeShardsByWeight.get(key); + if (shardRoutings == null) { + synchronized (activeShardsByWeightMutex) { + shardRoutings = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); + activeShardsByWeight = MapBuilder.newMapBuilder(activeShardsByWeight).put(key, shardRoutings).immutableMap(); + } + } + return shardRoutings; + } + + private List getInitializingShardsByWeight(WeightedRouting weightedRouting, DiscoveryNodes nodes, double defaultWeight) { + WeightedRoutingKey key = new WeightedRoutingKey(weightedRouting); + List shardRoutings = initializingShardsByWeight.get(key); + if (shardRoutings == null) { + synchronized (initializingShardsByWeightMutex) { + shardRoutings = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); + initializingShardsByWeight = MapBuilder.newMapBuilder(initializingShardsByWeight).put(key, shardRoutings).immutableMap(); + } + } + return shardRoutings; + } + /** * Builder of an index shard routing table. * diff --git a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java index 175298374415d..9026da667ccb0 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java @@ -37,10 +37,8 @@ import org.opensearch.cluster.metadata.WeightedRoutingMetadata; import org.opensearch.cluster.node.DiscoveryNodes; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; -import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Nullable; import org.opensearch.common.Strings; -import org.opensearch.common.inject.Inject; import org.opensearch.common.settings.ClusterSettings; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Settings; @@ -90,9 +88,6 @@ public class OperationRouting { private volatile boolean ignoreAwarenessAttr; private volatile double weightedRoutingDefaultWeight; - private WeightedRoutingCache weightedRoutingCache; - private ClusterService clusterService; - public OperationRouting(Settings settings, ClusterSettings clusterSettings) { // whether to ignore awareness attributes when routing requests this.ignoreAwarenessAttr = clusterSettings.get(IGNORE_AWARENESS_ATTRIBUTES_SETTING); @@ -140,20 +135,6 @@ public double getWeightedRoutingDefaultWeight() { return this.weightedRoutingDefaultWeight; } - @Inject - public void setClusterService(ClusterService clusterService) { - this.clusterService = clusterService; - } - - @Inject - public void setWeightedRoutingCache(WeightedRoutingCache weightedRoutingCache) { - this.weightedRoutingCache = weightedRoutingCache; - } - - public WeightedRoutingCache getWeightedRoutingCache() { - return weightedRoutingCache; - } - public ShardIterator indexShards(ClusterState clusterState, String index, String id, @Nullable String routing) { return shards(clusterState, index, id, routing).shardsIt(); } @@ -171,7 +152,8 @@ public ShardIterator getShards( clusterState.nodes(), preference, null, - null + null, + clusterState.getMetadata().weightedRoutingMetadata() ); } @@ -183,7 +165,8 @@ public ShardIterator getShards(ClusterState clusterState, String index, int shar clusterState.nodes(), preference, null, - null + null, + clusterState.metadata().weightedRoutingMetadata() ); } @@ -213,7 +196,8 @@ public GroupShardsIterator searchShards( clusterState.nodes(), preference, collectorService, - nodeCounts + nodeCounts, + clusterState.metadata().weightedRoutingMetadata() ); if (iterator != null) { set.add(iterator); @@ -263,10 +247,11 @@ private ShardIterator preferenceActiveShardIterator( DiscoveryNodes nodes, @Nullable String preference, @Nullable ResponseCollectorService collectorService, - @Nullable Map nodeCounts + @Nullable Map nodeCounts, + @Nullable WeightedRoutingMetadata weightedRoutingMetadata ) { if (preference == null || preference.isEmpty()) { - return shardRoutings(indexShard, nodes, collectorService, nodeCounts); + return shardRoutings(indexShard, nodes, collectorService, nodeCounts, weightedRoutingMetadata); } if (preference.charAt(0) == '_') { Preference preferenceType = Preference.parse(preference); @@ -293,7 +278,7 @@ private ShardIterator preferenceActiveShardIterator( } // no more preference if (index == -1 || index == preference.length() - 1) { - return shardRoutings(indexShard, nodes, collectorService, nodeCounts); + return shardRoutings(indexShard, nodes, collectorService, nodeCounts, weightedRoutingMetadata); } else { // update the preference and continue preference = preference.substring(index + 1); @@ -336,17 +321,13 @@ private ShardIterator shardRoutings( IndexShardRoutingTable indexShard, DiscoveryNodes nodes, @Nullable ResponseCollectorService collectorService, - @Nullable Map nodeCounts + @Nullable Map nodeCounts, + @Nullable WeightedRoutingMetadata weightedRoutingMetadata ) { - WeightedRoutingMetadata weightedRoutingMetadata = null; - if (clusterService != null) { - weightedRoutingMetadata = clusterService.state().metadata().weightedRoutingMetadata(); - } if (weightedRoutingMetadata != null) { return indexShard.activeInitializingShardsWeightedIt( weightedRoutingMetadata.getWeightedRouting(), nodes, - weightedRoutingCache, getWeightedRoutingDefaultWeight() ); } else if (ignoreAwarenessAttributes()) { diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java deleted file mode 100644 index ee4fef0260a8a..0000000000000 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingCache.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.cluster.routing; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.opensearch.cluster.ClusterChangedEvent; -import org.opensearch.cluster.ClusterStateListener; -import org.opensearch.cluster.service.ClusterService; -import org.opensearch.common.cache.Cache; -import org.opensearch.common.cache.CacheBuilder; -import org.opensearch.common.lease.Releasable; -import org.opensearch.index.shard.ShardId; - -import java.util.List; - -/** - * The weighted shard routing cache allows caching shard routing iterator returned by Weighted round-robin scheduling - * policy, helping with improving similar requests. - * - * @opensearch.internal - */ -public class WeightedRoutingCache implements Releasable, ClusterStateListener { - private static final Logger logger = LogManager.getLogger(WeightedRoutingCache.class); - - private final Cache> cache; - private static final long sizeInBytes = 2000000; - - public WeightedRoutingCache(ClusterService clusterService) { - - CacheBuilder> cacheBuilder = CacheBuilder.>builder() - .removalListener(notification -> logger.info("Object" + " {} removed from cache", notification.getKey().shardId)) - .setMaximumWeight(sizeInBytes); - cache = cacheBuilder.build(); - clusterService.addListener(this); - } - - public long hits() { - return cache.stats().getHits(); - } - - public long misses() { - return cache.stats().getMisses(); - } - - public long size() { - return cache.count(); - } - - @Override - public void close() { - logger.debug("Invalidating WeightedRoutingCache on close"); - cache.invalidateAll(); - } - - /** - * Listens to cluster state change event and invalidate cache on such events - * - * @param event cluster state change event - */ - @Override - public void clusterChanged(ClusterChangedEvent event) { - logger.debug("Invalidating WeightedRoutingCache on ClusterChangedEvent"); - cache.invalidateAll(); - } - - public List get(Key k) { - return cache.get(k); - } - - public void put(Key key, List value) { - cache.put(key, value); - } - - /** - * Key for the WeightedRoutingCache - * - * @opensearch.internal - */ - public static class Key { - private final ShardId shardId; - - Key(ShardId shardId) { - this.shardId = shardId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - WeightedRoutingCache.Key key = (WeightedRoutingCache.Key) o; - if (!shardId.equals(key.shardId)) return false; - return true; - } - - @Override - public int hashCode() { - int result = shardId.hashCode(); - return result; - } - - } -} diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index d0ab73e4fcc29..92e9815313fa0 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -36,8 +36,6 @@ import org.apache.logging.log4j.Logger; import org.apache.lucene.util.Constants; import org.apache.lucene.util.SetOnce; -import org.opensearch.cluster.routing.OperationRouting; -import org.opensearch.cluster.routing.WeightedRoutingCache; import org.opensearch.common.util.FeatureFlags; import org.opensearch.cluster.routing.allocation.AwarenessReplicaBalance; import org.opensearch.index.IndexingPressureService; @@ -908,7 +906,6 @@ protected Node( ); resourcesToClose.add(persistentTasksClusterService); final PersistentTasksService persistentTasksService = new PersistentTasksService(clusterService, threadPool, client); - final WeightedRoutingCache weightedRoutingCache = new WeightedRoutingCache(clusterService); modules.add(b -> { b.bind(Node.class).toInstance(this); @@ -952,7 +949,6 @@ protected Node( b.bind(SnapshotsInfoService.class).toInstance(snapshotsInfoService); b.bind(GatewayMetaState.class).toInstance(gatewayMetaState); b.bind(Discovery.class).toInstance(discoveryModule.getDiscovery()); - b.bind(WeightedRoutingCache.class).toInstance(weightedRoutingCache); { processRecoverySettings(settingsModule.getClusterSettings(), recoverySettings); b.bind(PeerRecoverySourceService.class) @@ -990,7 +986,6 @@ protected Node( b.bind(ShardLimitValidator.class).toInstance(shardLimitValidator); b.bind(FsHealthService.class).toInstance(fsHealthService); b.bind(SystemIndices.class).toInstance(systemIndices); - b.bind(OperationRouting.class).toInstance(clusterService.operationRouting()); }); injector = modules.createInjector(); @@ -1337,7 +1332,6 @@ public synchronized void close() throws IOException { toClose.add(() -> stopWatch.stop().start("node_environment")); toClose.add(injector.getInstance(NodeEnvironment.class)); toClose.add(stopWatch::stop); - toClose.add(injector.getInstance(WeightedRoutingCache.class)); if (logger.isTraceEnabled()) { toClose.add(() -> logger.trace("Close times for each service:\n{}", stopWatch.prettyPrint())); diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index 2a2c5d0fd731b..aa32e78549125 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -33,7 +33,6 @@ import org.opensearch.Version; import org.opensearch.action.support.replication.ClusterStateCreationUtils; -import org.opensearch.cluster.ClusterChangedEvent; import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.Metadata; @@ -595,7 +594,6 @@ public void testAdaptiveReplicaSelection() throws Exception { ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); - opRouting.setClusterService(clusterService); GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -700,7 +698,6 @@ public void testAdaptiveReplicaSelectionWithZoneAwarenessIgnored() throws Except Set selectedNodes = new HashSet<>(numShards); ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); - opRouting.setClusterService(clusterService); GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -833,9 +830,6 @@ public void testWeightedOperationRouting() throws Exception { ClusterState.Builder builder = ClusterState.builder(state); ClusterServiceUtils.setState(clusterService, builder); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); - // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( state, @@ -870,8 +864,6 @@ public void testWeightedOperationRouting() throws Exception { ClusterServiceUtils.setState(clusterService, builder); opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); @@ -893,92 +885,6 @@ public void testWeightedOperationRouting() throws Exception { } } - public void testWeightedOperationRoutingCaching() throws Exception { - final int numIndices = 2; - final int numShards = 3; - final int numReplicas = 2; - // setting up indices - final String[] indexNames = new String[numIndices]; - for (int i = 0; i < numIndices; i++) { - indexNames[i] = "test" + i; - } - ClusterService clusterService = null; - TestThreadPool threadPool = null; - try { - ClusterState state = clusterStateForWeightedRouting(indexNames, numShards, numReplicas); - - Settings setting = Settings.builder().put("cluster.routing.allocation.awareness.attributes", "zone").build(); - - threadPool = new TestThreadPool("testThatOnlyNodesSupport"); - clusterService = ClusterServiceUtils.createClusterService(threadPool); - - OperationRouting opRouting = new OperationRouting( - setting, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) - ); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); - - assertTrue(opRouting.ignoreAwarenessAttributes()); - ResponseCollectorService collector = new ResponseCollectorService(clusterService); - Map outstandingRequests = new HashMap<>(); - - // Setting up weights for weighted round-robin in cluster state - Map weights = Map.of("a", 1.0, "b", 1.0, "c", 0.0); - state = setWeightedRoutingWeights(state, weights); - ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); - - // search shards call - GroupShardsIterator groupIterator = opRouting.searchShards( - state, - indexNames, - null, - null, - collector, - outstandingRequests - ); - - // shard weighted routing ordering details are not present in cache, the details are calculated and put in cache - assertEquals(6, opRouting.getWeightedRoutingCache().misses()); - assertEquals(6, opRouting.getWeightedRoutingCache().size()); - - // Calling operation routing again without any cluster state change to test that weighted routing details - // are fetched from cache - groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); - - // details are fetched from cache - assertEquals(6, opRouting.getWeightedRoutingCache().hits()); - // cache count stays same - assertEquals(6, opRouting.getWeightedRoutingCache().size()); - // cache misses stay same - assertEquals(6, opRouting.getWeightedRoutingCache().misses()); - - // Updating cluster state to test weighted routing details are calculated again - weights = Map.of("a", 1.0, "b", 0.0, "c", 1.0); - // building new cluster state - ClusterState state2 = setWeightedRoutingWeights(state, weights); - ClusterServiceUtils.setState(clusterService, ClusterState.builder(state2)); - - ClusterChangedEvent event = new ClusterChangedEvent("test", state2, state); - opRouting.getWeightedRoutingCache().clusterChanged(event); - - // cache is invalidated after cluster state change, cache count is zero - assertEquals(0, opRouting.getWeightedRoutingCache().size()); - - // search shards call - groupIterator = opRouting.searchShards(state2, indexNames, null, null, collector, outstandingRequests); - - // cache hit remain same - assertEquals(6, opRouting.getWeightedRoutingCache().hits()); - // cache miss increases by 6 - assertEquals(12, opRouting.getWeightedRoutingCache().misses()); - assertEquals(6, opRouting.getWeightedRoutingCache().size()); - } finally { - IOUtils.close(clusterService); - terminate(threadPool); - } - } - public void testWeightedOperationRoutingWeightUndefinedForOneZone() throws Exception { final int numIndices = 2; final int numShards = 3; @@ -1013,8 +919,6 @@ public void testWeightedOperationRoutingWeightUndefinedForOneZone() throws Excep state = setWeightedRoutingWeights(state, weights); ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call GroupShardsIterator groupIterator = opRouting.searchShards( state, @@ -1054,8 +958,6 @@ public void testWeightedOperationRoutingWeightUndefinedForOneZone() throws Excep ClusterServiceUtils.setState(clusterService, ClusterState.builder(state)); opRouting = new OperationRouting(setting, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); - opRouting.setClusterService(clusterService); - opRouting.setWeightedRoutingCache(new WeightedRoutingCache(clusterService)); // search shards call groupIterator = opRouting.searchShards(state, indexNames, null, null, collector, outstandingRequests); diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index 0e6e7eb51b168..75587be4762d7 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -49,7 +49,6 @@ import org.opensearch.cluster.routing.ShardShuffler; import org.opensearch.cluster.routing.ShardsIterator; import org.opensearch.cluster.routing.WeightedRouting; -import org.opensearch.cluster.routing.WeightedRoutingCache; import org.opensearch.cluster.routing.allocation.AllocationService; import org.opensearch.cluster.routing.allocation.decider.ClusterRebalanceAllocationDecider; import org.opensearch.cluster.service.ClusterService; @@ -434,7 +433,6 @@ public void testShardsAndPreferNodeRouting() { Settings.EMPTY, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); - operationRouting.setClusterService(clusterService); GroupShardsIterator shardIterators = operationRouting.searchShards( clusterState, new String[] { "test" }, @@ -548,14 +546,13 @@ public void testWeightedRouting() { clusterState = startInitializingShardsAndReroute(strategy, clusterState); clusterState = startInitializingShardsAndReroute(strategy, clusterState); - WeightedRoutingCache cache = new WeightedRoutingCache(clusterService); Map weights = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); ShardIterator shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); assertEquals(2, shardIterator.size()); ShardRouting shardRouting = shardIterator.nextOrNull(); @@ -564,34 +561,30 @@ public void testWeightedRouting() { shardRouting = shardIterator.nextOrNull(); assertNotNull(shardRouting); assertFalse(shardRouting.currentNodeId().equals("node3")); - cache.close(); weights = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 1.0); weightedRouting = new WeightedRouting("zone", weights); shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); assertEquals(3, shardIterator.size()); - cache.close(); weights = Map.of("zone1", -1.0, "zone2", 0.0, "zone3", 1.0); weightedRouting = new WeightedRouting("zone", weights); shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); assertEquals(1, shardIterator.size()); - cache.close(); weights = Map.of("zone1", 0.0, "zone2", 0.0, "zone3", 0.0); weightedRouting = new WeightedRouting("zone", weights); shardIterator = clusterState.routingTable() .index("test") .shard(0) - .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), cache, 1); + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); assertEquals(0, shardIterator.size()); - cache.close(); } finally { terminate(threadPool); } From bd6c9e7e41b43d0b015d4b196475562133f69547 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Fri, 16 Sep 2022 20:00:59 +0530 Subject: [PATCH 33/55] Fix put operation for weighted shard routings Signed-off-by: Anshu Agarwal --- .../cluster/metadata/WeightedRoutingMetadata.java | 1 - .../cluster/routing/IndexShardRoutingTable.java | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java index 6b69a208d5b97..27beb21f28f7c 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java @@ -164,5 +164,4 @@ public static void toXContent(WeightedRouting weightedRouting, XContentBuilder b public String toString() { return Strings.toString(this); } - } diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index bc24d66447a67..297100269d22a 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -664,7 +664,7 @@ private AttributesRoutings getActiveAttribute(AttributesKey key, DiscoveryNodes List to = collectAttributeShards(key, nodes, from); shardRoutings = new AttributesRoutings(to, Collections.unmodifiableList(from)); - activeShardsByAttributes = new MapBuilder().put(key, shardRoutings).immutableMap(); + activeShardsByAttributes = MapBuilder.newMapBuilder(activeShardsByAttributes).put(key, shardRoutings).immutableMap(); } } return shardRoutings; @@ -677,7 +677,9 @@ private AttributesRoutings getInitializingAttribute(AttributesKey key, Discovery ArrayList from = new ArrayList<>(allInitializingShards); List to = collectAttributeShards(key, nodes, from); shardRoutings = new AttributesRoutings(to, Collections.unmodifiableList(from)); - initializingShardsByAttributes = new MapBuilder().put(key, shardRoutings).immutableMap(); + initializingShardsByAttributes = MapBuilder.newMapBuilder(initializingShardsByAttributes) + .put(key, shardRoutings) + .immutableMap(); } } return shardRoutings; @@ -799,7 +801,7 @@ private List getActiveShardsByWeight(WeightedRouting weightedRouti if (shardRoutings == null) { synchronized (activeShardsByWeightMutex) { shardRoutings = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); - activeShardsByWeight = MapBuilder.newMapBuilder(activeShardsByWeight).put(key, shardRoutings).immutableMap(); + activeShardsByWeight = new MapBuilder().put(key, shardRoutings).immutableMap(); } } return shardRoutings; @@ -811,7 +813,7 @@ private List getInitializingShardsByWeight(WeightedRouting weighte if (shardRoutings == null) { synchronized (initializingShardsByWeightMutex) { shardRoutings = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); - initializingShardsByWeight = MapBuilder.newMapBuilder(initializingShardsByWeight).put(key, shardRoutings).immutableMap(); + initializingShardsByWeight = new MapBuilder().put(key, shardRoutings).immutableMap(); } } return shardRoutings; From d9368ab2c0f389b72cb6e2ebffe008420d29f118 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Sat, 17 Sep 2022 08:08:21 +0530 Subject: [PATCH 34/55] Add tests for shard routing in-memory store Signed-off-by: Anshu Agarwal --- .../routing/IndexShardRoutingTable.java | 8 +- .../structure/RoutingIteratorTests.java | 135 +++++++++++++++++- 2 files changed, 134 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index 297100269d22a..f24d8d86a3b3b 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -237,6 +237,10 @@ public List assignedShards() { return this.assignedShards; } + public Map> getActiveShardsByWeight() { + return activeShardsByWeight; + } + public ShardIterator shardsRandomIt() { return new PlainShardIterator(shardId, shuffler.shuffle(shards)); } @@ -772,10 +776,10 @@ public int shardsMatchingPredicateCount(Predicate predicate) { * * @opensearch.internal */ - static class WeightedRoutingKey { + public static class WeightedRoutingKey { private final WeightedRouting weightedRouting; - WeightedRoutingKey(WeightedRouting weightedRouting) { + public WeightedRoutingKey(WeightedRouting weightedRouting) { this.weightedRouting = weightedRouting; } diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index 75587be4762d7..ff314a429759b 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -40,6 +40,7 @@ import org.opensearch.cluster.metadata.Metadata; import org.opensearch.cluster.node.DiscoveryNodes; import org.opensearch.cluster.routing.GroupShardsIterator; +import org.opensearch.cluster.routing.IndexShardRoutingTable; import org.opensearch.cluster.routing.OperationRouting; import org.opensearch.cluster.routing.PlainShardIterator; import org.opensearch.cluster.routing.RotationShardShuffler; @@ -504,7 +505,7 @@ public void testReplicaShardPreferenceIters() throws Exception { } } - public void testWeightedRouting() { + public void testWeightedRoutingWithDifferentWeights() { TestThreadPool threadPool = null; try { Settings.Builder settings = Settings.builder() @@ -555,12 +556,12 @@ public void testWeightedRouting() { .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); assertEquals(2, shardIterator.size()); - ShardRouting shardRouting = shardIterator.nextOrNull(); - assertNotNull(shardRouting); - assertFalse(shardRouting.currentNodeId().equals("node3")); - shardRouting = shardIterator.nextOrNull(); - assertNotNull(shardRouting); - assertFalse(shardRouting.currentNodeId().equals("node3")); + ShardRouting shardRouting; + while (shardIterator.remaining() > 0) { + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(Arrays.asList("node3").contains(shardRouting.currentNodeId())); + } weights = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 1.0); weightedRouting = new WeightedRouting("zone", weights); @@ -577,6 +578,11 @@ public void testWeightedRouting() { .shard(0) .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); assertEquals(1, shardIterator.size()); + while (shardIterator.remaining() > 0) { + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(Arrays.asList("node2", "node1").contains(shardRouting.currentNodeId())); + } weights = Map.of("zone1", 0.0, "zone2", 0.0, "zone3", 0.0); weightedRouting = new WeightedRouting("zone", weights); @@ -589,4 +595,119 @@ public void testWeightedRouting() { terminate(threadPool); } } + + public void testWeightedRoutingInMemoryStore() { + TestThreadPool threadPool = null; + try { + Settings.Builder settings = Settings.builder() + .put("cluster.routing.allocation.node_concurrent_recoveries", 10) + .put("cluster.routing.allocation.awareness.attributes", "zone"); + AllocationService strategy = createAllocationService(settings.build()); + + Metadata metadata = Metadata.builder() + .put(IndexMetadata.builder("test").settings(settings(Version.CURRENT)).numberOfShards(1).numberOfReplicas(2)) + .build(); + + RoutingTable routingTable = RoutingTable.builder().addAsNew(metadata.index("test")).build(); + + ClusterState clusterState = ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.getDefault(Settings.EMPTY)) + .metadata(metadata) + .routingTable(routingTable) + .build(); + + threadPool = new TestThreadPool("testThatOnlyNodesSupport"); + ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); + + Map node1Attributes = new HashMap<>(); + node1Attributes.put("zone", "zone1"); + Map node2Attributes = new HashMap<>(); + node2Attributes.put("zone", "zone2"); + Map node3Attributes = new HashMap<>(); + node3Attributes.put("zone", "zone3"); + clusterState = ClusterState.builder(clusterState) + .nodes( + DiscoveryNodes.builder() + .add(newNode("node1", unmodifiableMap(node1Attributes))) + .add(newNode("node2", unmodifiableMap(node2Attributes))) + .add(newNode("node3", unmodifiableMap(node3Attributes))) + .localNodeId("node1") + ) + .build(); + clusterState = strategy.reroute(clusterState, "reroute"); + + clusterState = startInitializingShardsAndReroute(strategy, clusterState); + clusterState = startInitializingShardsAndReroute(strategy, clusterState); + + Map weights = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 0.0); + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); + + IndexShardRoutingTable indexShardRoutingTable = clusterState.routingTable().index("test").shard(0); + + assertNull( + indexShardRoutingTable.getActiveShardsByWeight().get(new IndexShardRoutingTable.WeightedRoutingKey(weightedRouting)) + ); + ShardIterator shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); + assertEquals(2, shardIterator.size()); + ShardRouting shardRouting; + while (shardIterator.remaining() > 0) { + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(Arrays.asList("node3").contains(shardRouting.currentNodeId())); + } + + // Make iterator call with same WeightedRouting instance + assertNotNull( + indexShardRoutingTable.getActiveShardsByWeight().get(new IndexShardRoutingTable.WeightedRoutingKey(weightedRouting)) + ); + shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); + assertEquals(2, shardIterator.size()); + while (shardIterator.remaining() > 0) { + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(Arrays.asList("node3").contains(shardRouting.currentNodeId())); + } + + // Make iterator call with new instance of WeightedRouting but same weights + Map weights1 = Map.of("zone1", 1.0, "zone2", 1.0, "zone3", 0.0); + weightedRouting = new WeightedRouting("zone", weights1); + assertNotNull( + indexShardRoutingTable.getActiveShardsByWeight().get(new IndexShardRoutingTable.WeightedRoutingKey(weightedRouting)) + ); + shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); + assertEquals(2, shardIterator.size()); + while (shardIterator.remaining() > 0) { + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(Arrays.asList("node3").contains(shardRouting.currentNodeId())); + } + + // Make iterator call with different weights + Map weights2 = Map.of("zone1", 1.0, "zone2", 0.0, "zone3", 1.0); + weightedRouting = new WeightedRouting("zone", weights2); + assertNull( + indexShardRoutingTable.getActiveShardsByWeight().get(new IndexShardRoutingTable.WeightedRoutingKey(weightedRouting)) + ); + shardIterator = clusterState.routingTable() + .index("test") + .shard(0) + .activeInitializingShardsWeightedIt(weightedRouting, clusterState.nodes(), 1); + assertEquals(2, shardIterator.size()); + while (shardIterator.remaining() > 0) { + shardRouting = shardIterator.nextOrNull(); + assertNotNull(shardRouting); + assertFalse(Arrays.asList("node2").contains(shardRouting.currentNodeId())); + } + } finally { + terminate(threadPool); + } + } } From 01239bfd30be680f207a0fe1a87af0f6c2dc6120 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Sat, 17 Sep 2022 11:05:11 +0530 Subject: [PATCH 35/55] Add java docs and some code refactoring Signed-off-by: Anshu Agarwal --- .../cluster/routing/IndexShardRoutingTable.java | 10 +++++++++- .../opensearch/cluster/routing/WeightedRouting.java | 2 -- .../cluster/routing/OperationRoutingTests.java | 3 ++- .../cluster/structure/RoutingIteratorTests.java | 5 +---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index f24d8d86a3b3b..fbd8050fd467c 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -772,7 +772,7 @@ public int shardsMatchingPredicateCount(Predicate predicate) { } /** - * Key for WeightedRouting + * Key for WeightedRouting Shard Iterator * * @opensearch.internal */ @@ -799,6 +799,10 @@ public int hashCode() { } } + /** + * * + * Gets active shard routing from memory if available, else calculates and put it in memory. + */ private List getActiveShardsByWeight(WeightedRouting weightedRouting, DiscoveryNodes nodes, double defaultWeight) { WeightedRoutingKey key = new WeightedRoutingKey(weightedRouting); List shardRoutings = activeShardsByWeight.get(key); @@ -811,6 +815,10 @@ private List getActiveShardsByWeight(WeightedRouting weightedRouti return shardRoutings; } + /** + * * + * Gets initializing shard routing from memory if available, else calculates and put it in memory. + */ private List getInitializingShardsByWeight(WeightedRouting weightedRouting, DiscoveryNodes nodes, double defaultWeight) { WeightedRoutingKey key = new WeightedRoutingKey(weightedRouting); List shardRoutings = initializingShardsByWeight.get(key); diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java index 02ed0a110a42e..df2d8d595eaab 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java @@ -50,9 +50,7 @@ public void writeTo(StreamOutput out) throws IOException { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - WeightedRouting that = (WeightedRouting) o; - if (!attributeName.equals(that.attributeName)) return false; return weights.equals(that.weights); } diff --git a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java index aa32e78549125..87cab4a006a63 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java @@ -698,6 +698,7 @@ public void testAdaptiveReplicaSelectionWithZoneAwarenessIgnored() throws Except Set selectedNodes = new HashSet<>(numShards); ResponseCollectorService collector = new ResponseCollectorService(clusterService); Map outstandingRequests = new HashMap<>(); + GroupShardsIterator groupIterator = opRouting.searchShards( state, indexNames, @@ -847,7 +848,7 @@ public void testWeightedOperationRouting() throws Exception { selectedNodes.add(shardRouting.currentNodeId()); } } - // tests no nodes are assigned to nodes in zone c + // tests no shards are assigned to nodes in zone c for (String nodeID : selectedNodes) { // No shards are assigned to nodes in zone c since its weight is 0 assertFalse(nodeID.contains("c")); diff --git a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java index ff314a429759b..8f5aa1b764551 100644 --- a/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java +++ b/server/src/test/java/org/opensearch/cluster/structure/RoutingIteratorTests.java @@ -427,13 +427,11 @@ public void testShardsAndPreferNodeRouting() { clusterState = startInitializingShardsAndReroute(strategy, clusterState); clusterState = startInitializingShardsAndReroute(strategy, clusterState); - TestThreadPool threadPool = new TestThreadPool("testThatOnlyNodesSupport"); - ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); - OperationRouting operationRouting = new OperationRouting( Settings.EMPTY, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) ); + GroupShardsIterator shardIterators = operationRouting.searchShards( clusterState, new String[] { "test" }, @@ -475,7 +473,6 @@ public void testShardsAndPreferNodeRouting() { } else { assertThat(it.nextOrNull().currentNodeId(), equalTo("node1")); } - terminate(threadPool); } public void testReplicaShardPreferenceIters() throws Exception { From dbbb2638a1d74289d3054e43c33c425962a613da Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 10:04:57 +0530 Subject: [PATCH 36/55] Add null check for discovery nodes and single mutex for weighted shard iterator Signed-off-by: Anshu Agarwal --- .../cluster/routing/IndexShardRoutingTable.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java index fbd8050fd467c..9026e7068e9fe 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java +++ b/server/src/main/java/org/opensearch/cluster/routing/IndexShardRoutingTable.java @@ -85,8 +85,7 @@ public class IndexShardRoutingTable implements Iterable { private volatile Map activeShardsByAttributes = emptyMap(); private volatile Map initializingShardsByAttributes = emptyMap(); private final Object shardsByAttributeMutex = new Object(); - private final Object activeShardsByWeightMutex = new Object(); - private final Object initializingShardsByWeightMutex = new Object(); + private final Object shardsByWeightMutex = new Object(); private volatile Map> activeShardsByWeight = emptyMap(); private volatile Map> initializingShardsByWeight = emptyMap(); @@ -357,10 +356,12 @@ private List> calculateShardWeight( List> shardsWithWeights = new ArrayList<>(); for (ShardRouting shard : shards) { DiscoveryNode node = nodes.get(shard.currentNodeId()); - String attVal = node.getAttributes().get(weightedRouting.attributeName()); - // If weight for a zone is not defined, considering it as 1 by default - Double weight = weightedRouting.weights().getOrDefault(attVal, defaultWeight); - shardsWithWeights.add(new WeightedRoundRobin.Entity<>(weight, shard)); + if (node != null) { + String attVal = node.getAttributes().get(weightedRouting.attributeName()); + // If weight for a zone is not defined, considering it as 1 by default + Double weight = weightedRouting.weights().getOrDefault(attVal, defaultWeight); + shardsWithWeights.add(new WeightedRoundRobin.Entity<>(weight, shard)); + } } return shardsWithWeights; } @@ -807,7 +808,7 @@ private List getActiveShardsByWeight(WeightedRouting weightedRouti WeightedRoutingKey key = new WeightedRoutingKey(weightedRouting); List shardRoutings = activeShardsByWeight.get(key); if (shardRoutings == null) { - synchronized (activeShardsByWeightMutex) { + synchronized (shardsByWeightMutex) { shardRoutings = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); activeShardsByWeight = new MapBuilder().put(key, shardRoutings).immutableMap(); } @@ -823,7 +824,7 @@ private List getInitializingShardsByWeight(WeightedRouting weighte WeightedRoutingKey key = new WeightedRoutingKey(weightedRouting); List shardRoutings = initializingShardsByWeight.get(key); if (shardRoutings == null) { - synchronized (initializingShardsByWeightMutex) { + synchronized (shardsByWeightMutex) { shardRoutings = shardsOrderedByWeight(activeShards, weightedRouting, nodes, defaultWeight); initializingShardsByWeight = new MapBuilder().put(key, shardRoutings).immutableMap(); } From f06a0398451fa5413ccfc7a671c52e8eaf77ee88 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 13:18:07 +0530 Subject: [PATCH 37/55] Refactor code Signed-off-by: Anshu Agarwal --- .../org/opensearch/action/ActionModule.java | 10 ++-- .../put/ClusterPutWeightedRoutingAction.java} | 10 ++-- .../ClusterPutWeightedRoutingRequest.java} | 56 +++++++++---------- ...usterPutWeightedRoutingRequestBuilder.java | 33 +++++++++++ .../ClusterPutWeightedRoutingResponse.java} | 8 +-- .../TransportPutWeightedRoutingAction.java} | 38 ++++++------- .../{wrr => weighted}/put/package-info.java | 2 +- .../ClusterPutWRRWeightsRequestBuilder.java | 33 ----------- .../opensearch/client/ClusterAdminClient.java | 12 ++-- .../java/org/opensearch/client/Requests.java | 6 +- .../client/support/AbstractClient.java | 20 +++---- ...rvice.java => WeightedRoutingService.java} | 38 ++++++------- ... RestClusterPutWeightedRoutingAction.java} | 12 ++-- ...lusterPutWeightedRoutingRequestTests.java} | 35 ++++++------ ...ClusterPutWeightedRoutingActionTests.java} | 26 ++++----- 15 files changed, 170 insertions(+), 169 deletions(-) rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/{wrr/put/ClusterPutWRRWeightsAction.java => weighted/put/ClusterPutWeightedRoutingAction.java} (53%) rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/{wrr/put/ClusterPutWRRWeightsRequest.java => weighted/put/ClusterPutWeightedRoutingRequest.java} (71%) create mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/{wrr/put/ClusterPutWRRWeightsResponse.java => weighted/put/ClusterPutWeightedRoutingResponse.java} (64%) rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/{wrr/put/TransportPutWRRWeightsAction.java => weighted/put/TransportPutWeightedRoutingAction.java} (74%) rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/{wrr => weighted}/put/package-info.java (78%) delete mode 100644 server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java rename server/src/main/java/org/opensearch/cluster/routing/{WRRShardRoutingService.java => WeightedRoutingService.java} (68%) rename server/src/main/java/org/opensearch/rest/action/admin/cluster/{RestClusterPutWRRWeightsAction.java => RestClusterPutWeightedRoutingAction.java} (77%) rename server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/{wrr/put/ClusterPutWRRWeightsRequestTests.java => weighted/put/ClusterPutWeightedRoutingRequestTests.java} (64%) rename server/src/test/java/org/opensearch/rest/action/admin/cluster/{RestClusterPutWRRWeightsActionTests.java => RestClusterPutWeightedRoutingActionTests.java} (68%) diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 800d00bac9135..0fda4db453249 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -79,8 +79,8 @@ import org.opensearch.action.admin.cluster.settings.TransportClusterUpdateSettingsAction; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsAction; import org.opensearch.action.admin.cluster.shards.TransportClusterSearchShardsAction; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsAction; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.TransportPutWRRWeightsAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.TransportPutWeightedRoutingAction; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.clone.TransportCloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotAction; @@ -298,7 +298,7 @@ import org.opensearch.rest.action.admin.cluster.RestClusterAllocationExplainAction; import org.opensearch.rest.action.admin.cluster.RestClusterGetSettingsAction; import org.opensearch.rest.action.admin.cluster.RestClusterHealthAction; -import org.opensearch.rest.action.admin.cluster.RestClusterPutWRRWeightsAction; +import org.opensearch.rest.action.admin.cluster.RestClusterPutWeightedRoutingAction; import org.opensearch.rest.action.admin.cluster.RestClusterRerouteAction; import org.opensearch.rest.action.admin.cluster.RestClusterSearchShardsAction; import org.opensearch.rest.action.admin.cluster.RestClusterStateAction; @@ -566,7 +566,7 @@ public void reg actions.register(CloneSnapshotAction.INSTANCE, TransportCloneSnapshotAction.class); actions.register(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class); actions.register(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class); - actions.register(ClusterPutWRRWeightsAction.INSTANCE, TransportPutWRRWeightsAction.class); + actions.register(ClusterPutWeightedRoutingAction.INSTANCE, TransportPutWeightedRoutingAction.class); actions.register(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class); actions.register(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class); actions.register(IndicesShardStoresAction.INSTANCE, TransportIndicesShardStoresAction.class); @@ -749,7 +749,7 @@ public void initRestHandlers(Supplier nodesInCluster) { registerHandler.accept(new RestCloseIndexAction()); registerHandler.accept(new RestOpenIndexAction()); registerHandler.accept(new RestAddIndexBlockAction()); - registerHandler.accept(new RestClusterPutWRRWeightsAction()); + registerHandler.accept(new RestClusterPutWeightedRoutingAction()); registerHandler.accept(new RestUpdateSettingsAction()); registerHandler.accept(new RestGetSettingsAction()); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java similarity index 53% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java index 08a46dacf41bf..56ba62277fafc 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; import org.opensearch.action.ActionType; @@ -15,13 +15,13 @@ * * @opensearch.internal */ -public final class ClusterPutWRRWeightsAction extends ActionType { +public final class ClusterPutWeightedRoutingAction extends ActionType { - public static final ClusterPutWRRWeightsAction INSTANCE = new ClusterPutWRRWeightsAction(); + public static final ClusterPutWeightedRoutingAction INSTANCE = new ClusterPutWeightedRoutingAction(); public static final String NAME = "cluster:admin/routing/awareness/weights/put"; - private ClusterPutWRRWeightsAction() { - super(NAME, ClusterPutWRRWeightsResponse::new); + private ClusterPutWeightedRoutingAction() { + super(NAME, ClusterPutWeightedRoutingResponse::new); } } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java similarity index 71% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index 2dbce86282d21..46f7a1a55c350 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,7 +14,7 @@ import org.opensearch.OpenSearchParseException; import org.opensearch.action.ActionRequestValidationException; import org.opensearch.action.support.clustermanager.ClusterManagerNodeRequest; -import org.opensearch.cluster.routing.WRRWeights; +import org.opensearch.cluster.routing.WeightedRouting; import org.opensearch.common.bytes.BytesReference; import org.opensearch.common.io.stream.StreamInput; import org.opensearch.common.io.stream.StreamOutput; @@ -37,18 +37,18 @@ * * @opensearch.internal */ -public class ClusterPutWRRWeightsRequest extends ClusterManagerNodeRequest { - private static final Logger logger = LogManager.getLogger(ClusterPutWRRWeightsRequest.class); +public class ClusterPutWeightedRoutingRequest extends ClusterManagerNodeRequest { + private static final Logger logger = LogManager.getLogger(ClusterPutWeightedRoutingRequest.class); - private WRRWeights wrrWeight; + private WeightedRouting weightedRouting; private String attributeName; - public WRRWeights wrrWeight() { - return wrrWeight; + public WeightedRouting weightedRouting() { + return weightedRouting; } - public ClusterPutWRRWeightsRequest wrrWeight(WRRWeights wrrWeight) { - this.wrrWeight = wrrWeight; + public ClusterPutWeightedRoutingRequest weightedRouting(WeightedRouting weightedRouting) { + this.weightedRouting = weightedRouting; return this; } @@ -56,29 +56,29 @@ public void attributeName(String attributeName) { this.attributeName = attributeName; } - public ClusterPutWRRWeightsRequest(StreamInput in) throws IOException { + public ClusterPutWeightedRoutingRequest(StreamInput in) throws IOException { super(in); - wrrWeight = new WRRWeights(in); + weightedRouting = new WeightedRouting(in); } - public ClusterPutWRRWeightsRequest() { + public ClusterPutWeightedRoutingRequest() { } - public void setWRRWeight(Map source) { + public void setWeightedRouting(Map source) { try { if (source.isEmpty()) { throw new OpenSearchParseException(("Empty request body")); } XContentBuilder builder = XContentFactory.jsonBuilder(); builder.map(source); - setWRRWeight(BytesReference.bytes(builder), builder.contentType()); + setWeightedRouting(BytesReference.bytes(builder), builder.contentType()); } catch (IOException e) { throw new OpenSearchGenerationException("Failed to generate [" + source + "]", e); } } - public void setWRRWeight(BytesReference source, XContentType contentType) { + public void setWeightedRouting(BytesReference source, XContentType contentType) { try ( XContentParser parser = XContentHelper.createParser( NamedXContentRegistry.EMPTY, @@ -88,22 +88,22 @@ public void setWRRWeight(BytesReference source, XContentType contentType) { ) ) { String attrValue = null; - Map weights = new HashMap<>(); - Object attrWeight = null; + Map weights = new HashMap<>(); + Double attrWeight = null; XContentParser.Token token; // move to the first alias parser.nextToken(); while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { attrValue = parser.currentName(); - } else if (token == XContentParser.Token.VALUE_STRING) { - attrWeight = parser.text(); + } else if (token == XContentParser.Token.VALUE_NUMBER) { + attrWeight = Double.parseDouble(parser.text()); weights.put(attrValue, attrWeight); } else { throw new OpenSearchParseException("failed to parse wrr request attribute [{}], unknown type", attrWeight); } } - this.wrrWeight = new WRRWeights(this.attributeName, weights); + this.weightedRouting = new WeightedRouting(this.attributeName, weights); } catch (IOException e) { logger.error("error while parsing put wrr weights request object", e); } @@ -112,19 +112,19 @@ public void setWRRWeight(BytesReference source, XContentType contentType) { @Override public ActionRequestValidationException validate() { ActionRequestValidationException validationException = null; - if (wrrWeight == null) { + if (weightedRouting == null) { validationException = addValidationError("WRRWeights object is null", validationException); } - if (wrrWeight.attributeName() == null || wrrWeight.attributeName().isEmpty()) { + if (weightedRouting.attributeName() == null || weightedRouting.attributeName().isEmpty()) { validationException = addValidationError("Attribute name is missing", validationException); } - if (wrrWeight.weights() == null || wrrWeight.weights().isEmpty()) { + if (weightedRouting.weights() == null || weightedRouting.weights().isEmpty()) { validationException = addValidationError("Weights are missing", validationException); } int countValueWithZeroWeights = 0; int weight; try { - for (Object value : wrrWeight.weights().values()) { + for (Object value : weightedRouting.weights().values()) { if (value == null) { validationException = addValidationError(("Weight is null"), validationException); } else { @@ -146,20 +146,20 @@ public ActionRequestValidationException validate() { * @param source weights definition from request body * @return this request */ - public ClusterPutWRRWeightsRequest source(Map source) { - setWRRWeight(source); + public ClusterPutWeightedRoutingRequest source(Map source) { + setWeightedRouting(source); return this; } @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); - wrrWeight.writeTo(out); + weightedRouting.writeTo(out); } @Override public String toString() { - return "ClusterPutWRRWeightsRequest{" + "wrrWeight= " + wrrWeight.toString() + "}"; + return "ClusterPutWeightedRoutingRequest{" + "weightedRouting= " + weightedRouting.toString() + "}"; } } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java new file mode 100644 index 0000000000000..e890319fda759 --- /dev/null +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; + +import org.opensearch.action.support.clustermanager.ClusterManagerNodeOperationRequestBuilder; +import org.opensearch.client.OpenSearchClient; +import org.opensearch.cluster.routing.WeightedRouting; + +/** + * Request builder to update weights for weighted round-robin shard routing policy. + * + * @opensearch.internal + */ +public class ClusterPutWeightedRoutingRequestBuilder extends ClusterManagerNodeOperationRequestBuilder< + ClusterPutWeightedRoutingRequest, + ClusterPutWeightedRoutingResponse, + ClusterPutWeightedRoutingRequestBuilder> { + public ClusterPutWeightedRoutingRequestBuilder(OpenSearchClient client, ClusterPutWeightedRoutingAction action) { + super(client, action, new ClusterPutWeightedRoutingRequest()); + } + + public ClusterPutWeightedRoutingRequestBuilder setWeightedRouting(WeightedRouting weightedRouting) { + request.weightedRouting(weightedRouting); + return this; + } + +} diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java similarity index 64% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java index cc90c34b086d5..502c933f34069 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsResponse.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; import org.opensearch.action.support.master.AcknowledgedResponse; import org.opensearch.common.io.stream.StreamInput; @@ -19,12 +19,12 @@ * * @opensearch.internal */ -public class ClusterPutWRRWeightsResponse extends AcknowledgedResponse implements ToXContentObject { - public ClusterPutWRRWeightsResponse(boolean acknowledged) { +public class ClusterPutWeightedRoutingResponse extends AcknowledgedResponse implements ToXContentObject { + public ClusterPutWeightedRoutingResponse(boolean acknowledged) { super(acknowledged); } - public ClusterPutWRRWeightsResponse(StreamInput in) throws IOException { + public ClusterPutWeightedRoutingResponse(StreamInput in) throws IOException { super(in); } } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java similarity index 74% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java index 525e28c5116a7..7251d10e958f3 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/TransportPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; import org.opensearch.action.ActionListener; import org.opensearch.action.ActionRequestValidationException; @@ -15,7 +15,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.block.ClusterBlockException; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; -import org.opensearch.cluster.routing.WRRShardRoutingService; +import org.opensearch.cluster.routing.WeightedRoutingService; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.inject.Inject; @@ -35,35 +35,35 @@ * * @opensearch.internal */ -public class TransportPutWRRWeightsAction extends TransportClusterManagerNodeAction< - ClusterPutWRRWeightsRequest, - ClusterPutWRRWeightsResponse> { +public class TransportPutWeightedRoutingAction extends TransportClusterManagerNodeAction< + ClusterPutWeightedRoutingRequest, + ClusterPutWeightedRoutingResponse> { - private final WRRShardRoutingService wrrShardRoutingService; + private final WeightedRoutingService weightedRoutingService; private volatile List awarenessAttributes; @Inject - public TransportPutWRRWeightsAction( + public TransportPutWeightedRoutingAction( Settings settings, ClusterSettings clusterSettings, TransportService transportService, ClusterService clusterService, - WRRShardRoutingService wrrShardRoutingService, + WeightedRoutingService weightedRoutingService, ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver ) { super( - ClusterPutWRRWeightsAction.NAME, + ClusterPutWeightedRoutingAction.NAME, transportService, clusterService, threadPool, actionFilters, - ClusterPutWRRWeightsRequest::new, + ClusterPutWeightedRoutingRequest::new, indexNameExpressionResolver ); - this.wrrShardRoutingService = wrrShardRoutingService; + this.weightedRoutingService = weightedRoutingService; this.awarenessAttributes = AwarenessAllocationDecider.CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTE_SETTING.get(settings); clusterSettings.addSettingsUpdateConsumer( AwarenessAllocationDecider.CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTE_SETTING, @@ -85,23 +85,23 @@ protected String executor() { } @Override - protected ClusterPutWRRWeightsResponse read(StreamInput in) throws IOException { - return new ClusterPutWRRWeightsResponse(in); + protected ClusterPutWeightedRoutingResponse read(StreamInput in) throws IOException { + return new ClusterPutWeightedRoutingResponse(in); } @Override protected void clusterManagerOperation( - ClusterPutWRRWeightsRequest request, + ClusterPutWeightedRoutingRequest request, ClusterState state, - ActionListener listener + ActionListener listener ) throws Exception { - verifyAwarenessAttribute(request.wrrWeight().attributeName()); - wrrShardRoutingService.registerWRRWeightsMetadata( + verifyAwarenessAttribute(request.weightedRouting().attributeName()); + weightedRoutingService.registerWRRWeightsMetadata( request, ActionListener.delegateFailure( listener, (delegatedListener, response) -> { - delegatedListener.onResponse(new ClusterPutWRRWeightsResponse(response.isAcknowledged())); + delegatedListener.onResponse(new ClusterPutWeightedRoutingResponse(response.isAcknowledged())); } ) ); @@ -120,7 +120,7 @@ private void verifyAwarenessAttribute(String attributeName) { } @Override - protected ClusterBlockException checkBlock(ClusterPutWRRWeightsRequest request, ClusterState state) { + protected ClusterBlockException checkBlock(ClusterPutWeightedRoutingRequest request, ClusterState state) { return null; } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/package-info.java similarity index 78% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/package-info.java index c7bccf97c2243..4f18b220cd343 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/package-info.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/package-info.java @@ -7,4 +7,4 @@ */ /** add/update weighted-round robin shard routing weights. */ -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java deleted file mode 100644 index 60e164dc01c25..0000000000000 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; - -import org.opensearch.action.support.clustermanager.ClusterManagerNodeOperationRequestBuilder; -import org.opensearch.client.OpenSearchClient; -import org.opensearch.cluster.routing.WRRWeights; - -/** - * Request builder to update weights for weighted round-robin shard routing policy. - * - * @opensearch.internal - */ -public class ClusterPutWRRWeightsRequestBuilder extends ClusterManagerNodeOperationRequestBuilder< - ClusterPutWRRWeightsRequest, - ClusterPutWRRWeightsResponse, - ClusterPutWRRWeightsRequestBuilder> { - public ClusterPutWRRWeightsRequestBuilder(OpenSearchClient client, ClusterPutWRRWeightsAction action) { - super(client, action, new ClusterPutWRRWeightsRequest()); - } - - public ClusterPutWRRWeightsRequestBuilder setWRRWeights(WRRWeights wrrWeight) { - request.wrrWeight(wrrWeight); - return this; - } - -} diff --git a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java index 3372071d993be..ce4146ffc3ed1 100644 --- a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java +++ b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java @@ -86,9 +86,9 @@ import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequestBuilder; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequestBuilder; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsResponse; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequestBuilder; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingResponse; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequestBuilder; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; @@ -793,16 +793,16 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Updates weights for weighted round-robin search routing policy. */ - ActionFuture putWRRWeights(ClusterPutWRRWeightsRequest request); + ActionFuture putWRRWeights(ClusterPutWeightedRoutingRequest request); /** * Updates weights for weighted round-robin search routing policy. */ - void putWRRWeights(ClusterPutWRRWeightsRequest request, ActionListener listener); + void putWRRWeights(ClusterPutWeightedRoutingRequest request, ActionListener listener); /** * Updates weights for weighted round-robin search routing policy. */ - ClusterPutWRRWeightsRequestBuilder prepareWRRWeights(); + ClusterPutWeightedRoutingRequestBuilder prepareWRRWeights(); } diff --git a/server/src/main/java/org/opensearch/client/Requests.java b/server/src/main/java/org/opensearch/client/Requests.java index 96e2f7d5fd76d..22a20fc9c6eaf 100644 --- a/server/src/main/java/org/opensearch/client/Requests.java +++ b/server/src/main/java/org/opensearch/client/Requests.java @@ -47,7 +47,7 @@ import org.opensearch.action.admin.cluster.reroute.ClusterRerouteRequest; import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; @@ -555,8 +555,8 @@ public static SnapshotsStatusRequest snapshotsStatusRequest(String repository) { * * @return update weight request */ - public static ClusterPutWRRWeightsRequest putWRRWeightsRequest() { - return new ClusterPutWRRWeightsRequest(); + public static ClusterPutWeightedRoutingRequest putWRRWeightsRequest() { + return new ClusterPutWeightedRoutingRequest(); } } diff --git a/server/src/main/java/org/opensearch/client/support/AbstractClient.java b/server/src/main/java/org/opensearch/client/support/AbstractClient.java index eb45b2efadaff..870da1622afaf 100644 --- a/server/src/main/java/org/opensearch/client/support/AbstractClient.java +++ b/server/src/main/java/org/opensearch/client/support/AbstractClient.java @@ -110,10 +110,10 @@ import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequestBuilder; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsAction; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequestBuilder; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsResponse; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequestBuilder; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingResponse; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequest; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotRequestBuilder; @@ -1269,18 +1269,18 @@ public ActionFuture deleteDanglingIndex(DeleteDanglingInde } @Override - public ActionFuture putWRRWeights(ClusterPutWRRWeightsRequest request) { - return execute(ClusterPutWRRWeightsAction.INSTANCE, request); + public ActionFuture putWRRWeights(ClusterPutWeightedRoutingRequest request) { + return execute(ClusterPutWeightedRoutingAction.INSTANCE, request); } @Override - public void putWRRWeights(ClusterPutWRRWeightsRequest request, ActionListener listener) { - execute(ClusterPutWRRWeightsAction.INSTANCE, request, listener); + public void putWRRWeights(ClusterPutWeightedRoutingRequest request, ActionListener listener) { + execute(ClusterPutWeightedRoutingAction.INSTANCE, request, listener); } @Override - public ClusterPutWRRWeightsRequestBuilder prepareWRRWeights() { - return new ClusterPutWRRWeightsRequestBuilder(this, ClusterPutWRRWeightsAction.INSTANCE); + public ClusterPutWeightedRoutingRequestBuilder prepareWRRWeights() { + return new ClusterPutWeightedRoutingRequestBuilder(this, ClusterPutWeightedRoutingAction.INSTANCE); } @Override diff --git a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java similarity index 68% rename from server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java rename to server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index 53e3c441c021f..c92413161dfb7 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WRRShardRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -12,14 +12,14 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; import org.opensearch.action.ActionListener; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; import org.opensearch.cluster.ClusterChangedEvent; import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.ClusterStateApplier; import org.opensearch.cluster.ClusterStateUpdateTask; import org.opensearch.cluster.ack.ClusterStateUpdateResponse; import org.opensearch.cluster.metadata.Metadata; -import org.opensearch.cluster.metadata.WeightedRoundRobinRoutingMetadata; +import org.opensearch.cluster.metadata.WeightedRoutingMetadata; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Priority; import org.opensearch.common.component.AbstractLifecycleComponent; @@ -32,45 +32,45 @@ /** * * Service responsible for updating cluster state metadata with wrr weights */ -public class WRRShardRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { - private static final Logger logger = LogManager.getLogger(WRRShardRoutingService.class); +public class WeightedRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { + private static final Logger logger = LogManager.getLogger(WeightedRoutingService.class); private final ClusterService clusterService; private final ThreadPool threadPool; @Inject - public WRRShardRoutingService(ClusterService clusterService, ThreadPool threadPool) { + public WeightedRoutingService(ClusterService clusterService, ThreadPool threadPool) { this.clusterService = clusterService; this.threadPool = threadPool; } public void registerWRRWeightsMetadata( - final ClusterPutWRRWeightsRequest request, + final ClusterPutWeightedRoutingRequest request, final ActionListener listener ) { - final WeightedRoundRobinRoutingMetadata newWRRWeightsMetadata = new WeightedRoundRobinRoutingMetadata(request.wrrWeight()); + final WeightedRoutingMetadata newWRRWeightsMetadata = new WeightedRoutingMetadata(request.weightedRouting()); clusterService.submitStateUpdateTask("update_wrr_weights", new ClusterStateUpdateTask(Priority.URGENT) { @Override public ClusterState execute(ClusterState currentState) { Metadata metadata = currentState.metadata(); Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata()); - WeightedRoundRobinRoutingMetadata wrrWeights = metadata.custom(WeightedRoundRobinRoutingMetadata.TYPE); + WeightedRoutingMetadata wrrWeights = metadata.custom(WeightedRoutingMetadata.TYPE); if (wrrWeights == null) { - logger.info("put wrr weights [{}]", request.wrrWeight()); - wrrWeights = new WeightedRoundRobinRoutingMetadata(request.wrrWeight()); + logger.info("put wrr weights [{}]", request.weightedRouting()); + wrrWeights = new WeightedRoutingMetadata(request.weightedRouting()); } else { - WeightedRoundRobinRoutingMetadata changedMetadata = new WeightedRoundRobinRoutingMetadata(new WRRWeights(null, null)); + WeightedRoutingMetadata changedMetadata = new WeightedRoutingMetadata(new WeightedRouting(null, null)); if (!checkIfSameWeightsInMetadata(newWRRWeightsMetadata, wrrWeights)) { - logger.info("updated wrr weights [{}] in metadata", request.wrrWeight()); - changedMetadata.setWrrWeight(newWRRWeightsMetadata.getWrrWeight()); + logger.info("updated wrr weights [{}] in metadata", request.weightedRouting()); + changedMetadata.setWeightedRouting(newWRRWeightsMetadata.getWeightedRouting()); } else { return currentState; } - wrrWeights = new WeightedRoundRobinRoutingMetadata(changedMetadata.getWrrWeight()); + wrrWeights = new WeightedRoutingMetadata(changedMetadata.getWeightedRouting()); } - mdBuilder.putCustom(WeightedRoundRobinRoutingMetadata.TYPE, wrrWeights); - logger.info("building cluster state with wrr weights [{}]", request.wrrWeight()); + mdBuilder.putCustom(WeightedRoutingMetadata.TYPE, wrrWeights); + logger.info("building cluster state with wrr weights [{}]", request.weightedRouting()); return ClusterState.builder(currentState).metadata(mdBuilder).build(); } @@ -89,10 +89,10 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS } private boolean checkIfSameWeightsInMetadata( - WeightedRoundRobinRoutingMetadata newWRRWeightsMetadata, - WeightedRoundRobinRoutingMetadata oldWRRWeightsMetadata + WeightedRoutingMetadata newWRRWeightsMetadata, + WeightedRoutingMetadata oldWRRWeightsMetadata ) { - if (newWRRWeightsMetadata.getWrrWeight().equals(oldWRRWeightsMetadata.getWrrWeight())) { + if (newWRRWeightsMetadata.getWeightedRouting().equals(oldWRRWeightsMetadata.getWeightedRouting())) { return true; } return false; diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java similarity index 77% rename from server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java rename to server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java index af71b95deaaf6..955af27a965c2 100644 --- a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsAction.java +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java @@ -10,7 +10,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; import org.opensearch.client.Requests; import org.opensearch.client.node.NodeClient; import org.opensearch.rest.BaseRestHandler; @@ -29,9 +29,9 @@ * @opensearch.api * */ -public class RestClusterPutWRRWeightsAction extends BaseRestHandler { +public class RestClusterPutWeightedRoutingAction extends BaseRestHandler { - private static final Logger logger = LogManager.getLogger(RestClusterPutWRRWeightsAction.class); + private static final Logger logger = LogManager.getLogger(RestClusterPutWeightedRoutingAction.class); @Override public List routes() { @@ -45,12 +45,12 @@ public String getName() { @Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { - ClusterPutWRRWeightsRequest putWRRWeightsRequest = createRequest(request); + ClusterPutWeightedRoutingRequest putWRRWeightsRequest = createRequest(request); return channel -> client.admin().cluster().putWRRWeights(putWRRWeightsRequest, new RestToXContentListener<>(channel)); } - public static ClusterPutWRRWeightsRequest createRequest(RestRequest request) throws IOException { - ClusterPutWRRWeightsRequest putWRRWeightsRequest = Requests.putWRRWeightsRequest(); + public static ClusterPutWeightedRoutingRequest createRequest(RestRequest request) throws IOException { + ClusterPutWeightedRoutingRequest putWRRWeightsRequest = Requests.putWRRWeightsRequest(); String attributeName = null; if (request.hasParam("attribute")) { attributeName = request.param("attribute"); diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java similarity index 64% rename from server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java rename to server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 3bc5917944a46..4b7bb2c7e1faf 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/wrr/put/ClusterPutWRRWeightsRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -6,33 +6,34 @@ * compatible open source license. */ -package org.opensearch.action.admin.cluster.shards.routing.wrr.put; +package org.opensearch.action.admin.cluster.shards.routing.weighted.put; import org.opensearch.action.ActionRequestValidationException; import org.opensearch.cluster.routing.WRRWeights; +import org.opensearch.cluster.routing.WeightedRouting; import org.opensearch.common.bytes.BytesArray; import org.opensearch.common.xcontent.XContentType; import org.opensearch.test.OpenSearchTestCase; import java.util.Map; -public class ClusterPutWRRWeightsRequestTests extends OpenSearchTestCase { +public class ClusterPutWeightedRoutingRequestTests extends OpenSearchTestCase { public void testSetWRRWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; - ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); - Map weights = Map.of("us-east-1a", "1", "us-east-1b", "1", "us-east-1c", "0"); - WRRWeights wrrWeight = new WRRWeights("zone", weights); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); + Map weights = Map.of("us-east-1a", 1, "us-east-1b", 1, "us-east-1c", 0); + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); request.attributeName("zone"); - request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); - assertEquals(request.wrrWeight(), wrrWeight); + request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); + assertEquals(request.weightedRouting(), weightedRouting); } public void testValidate_ValuesAreProper() { String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; - ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); request.attributeName("zone"); - request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNull(actionRequestValidationException); @@ -40,9 +41,9 @@ public void testValidate_ValuesAreProper() { public void testValidate_TwoZonesWithZeroWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; - ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); request.attributeName("zone"); - request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("More than one value has weight set as 0")); @@ -51,9 +52,9 @@ public void testValidate_TwoZonesWithZeroWeight() { public void testValidate_MissingWeights() { String reqString = "{}"; - ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); request.attributeName("zone"); - request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("Weights are missing")); @@ -62,8 +63,8 @@ public void testValidate_MissingWeights() { public void testValidate_AttributeMissing() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; - ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); - request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); + request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("Attribute name is missing")); @@ -72,9 +73,9 @@ public void testValidate_AttributeMissing() { public void testValidate_NonIntegerWeights() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"5.6\",\"us-east-1a\":\"1\"}"; - ClusterPutWRRWeightsRequest request = new ClusterPutWRRWeightsRequest(); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); request.attributeName("zone"); - request.setWRRWeight(new BytesArray(reqString), XContentType.JSON); + request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("Weight is non-integer")); diff --git a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java similarity index 68% rename from server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java rename to server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java index d7092f9c49b42..07354f29c0332 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWRRWeightsActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java @@ -11,7 +11,7 @@ import com.fasterxml.jackson.core.JsonParseException; import org.junit.Before; import org.opensearch.OpenSearchParseException; -import org.opensearch.action.admin.cluster.shards.routing.wrr.put.ClusterPutWRRWeightsRequest; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; import org.opensearch.common.bytes.BytesArray; import org.opensearch.common.xcontent.XContentType; import org.opensearch.rest.RestRequest; @@ -24,31 +24,31 @@ import static java.util.Collections.singletonMap; -public class RestClusterPutWRRWeightsActionTests extends RestActionTestCase { - private RestClusterPutWRRWeightsAction action; +public class RestClusterPutWeightedRoutingActionTests extends RestActionTestCase { + private RestClusterPutWeightedRoutingAction action; @Before public void setupAction() { - action = new RestClusterPutWRRWeightsAction(); + action = new RestClusterPutWeightedRoutingAction(); controller().registerHandler(action); } public void testCreateRequest_SupportedRequestBody() throws IOException { String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; RestRequest restRequest = buildRestRequest(req); - ClusterPutWRRWeightsRequest clusterPutWRRWeightsRequest = RestClusterPutWRRWeightsAction.createRequest(restRequest); - assertEquals("zone", clusterPutWRRWeightsRequest.wrrWeight().attributeName()); - assertNotNull(clusterPutWRRWeightsRequest.wrrWeight().weights()); - assertEquals("1", clusterPutWRRWeightsRequest.wrrWeight().weights().get("us-east-1c")); - assertEquals("1", clusterPutWRRWeightsRequest.wrrWeight().weights().get("us-east-1d")); - assertEquals("0", clusterPutWRRWeightsRequest.wrrWeight().weights().get("us-east-1a")); + ClusterPutWeightedRoutingRequest clusterPutWeightedRoutingRequest = RestClusterPutWeightedRoutingAction.createRequest(restRequest); + assertEquals("zone", clusterPutWeightedRoutingRequest.wrrWeight().attributeName()); + assertNotNull(clusterPutWeightedRoutingRequest.wrrWeight().weights()); + assertEquals("1", clusterPutWeightedRoutingRequest.wrrWeight().weights().get("us-east-1c")); + assertEquals("1", clusterPutWeightedRoutingRequest.wrrWeight().weights().get("us-east-1d")); + assertEquals("0", clusterPutWeightedRoutingRequest.wrrWeight().weights().get("us-east-1a")); } public void testCreateRequest_UnsupportedRequestBody() throws IOException { Map params = new HashMap<>(); String req = "[\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"]"; RestRequest restRequest = buildRestRequest(req); - assertThrows(OpenSearchParseException.class, () -> RestClusterPutWRRWeightsAction.createRequest(restRequest)); + assertThrows(OpenSearchParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); } public void testCreateRequest_MalformedRequestBody() throws IOException { @@ -56,13 +56,13 @@ public void testCreateRequest_MalformedRequestBody() throws IOException { String req = "{\"us-east-1c\" : \"1\" \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; RestRequest restRequest = buildRestRequest(req); - assertThrows(JsonParseException.class, () -> RestClusterPutWRRWeightsAction.createRequest(restRequest)); + assertThrows(JsonParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); } public void testCreateRequest_EmptyRequestBody() throws IOException { String req = "{}"; RestRequest restRequest = buildRestRequest(req); - assertThrows(OpenSearchParseException.class, () -> RestClusterPutWRRWeightsAction.createRequest(restRequest)); + assertThrows(OpenSearchParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); } private RestRequest buildRestRequest(String content) { From 0a4b829e37d6e63a1341f3d6de9366f9aca07591 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 15:10:48 +0530 Subject: [PATCH 38/55] Fix tests Signed-off-by: Anshu Agarwal --- .../put/ClusterPutWeightedRoutingRequest.java | 8 +++--- ...ClusterPutWeightedRoutingRequestTests.java | 16 ++--------- ...tClusterPutWeightedRoutingActionTests.java | 27 +++++++++---------- 3 files changed, 19 insertions(+), 32 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index 46f7a1a55c350..cb7f34b3db331 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -96,7 +96,7 @@ public void setWeightedRouting(BytesReference source, XContentType contentType) while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { attrValue = parser.currentName(); - } else if (token == XContentParser.Token.VALUE_NUMBER) { + } else if (token == XContentParser.Token.VALUE_STRING) { attrWeight = Double.parseDouble(parser.text()); weights.put(attrValue, attrWeight); } else { @@ -122,18 +122,18 @@ public ActionRequestValidationException validate() { validationException = addValidationError("Weights are missing", validationException); } int countValueWithZeroWeights = 0; - int weight; + double weight; try { for (Object value : weightedRouting.weights().values()) { if (value == null) { validationException = addValidationError(("Weight is null"), validationException); } else { - weight = Integer.parseInt(value.toString()); + weight = Double.parseDouble(value.toString()); countValueWithZeroWeights = (weight == 0) ? countValueWithZeroWeights + 1 : countValueWithZeroWeights; } } } catch (NumberFormatException e) { - validationException = addValidationError(("Weight is non-integer"), validationException); + validationException = addValidationError(("Weight is not number"), validationException); } if (countValueWithZeroWeights > 1) { validationException = addValidationError(("More than one value has weight set as 0 "), validationException); diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 4b7bb2c7e1faf..236262a6f0836 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -9,7 +9,6 @@ package org.opensearch.action.admin.cluster.shards.routing.weighted.put; import org.opensearch.action.ActionRequestValidationException; -import org.opensearch.cluster.routing.WRRWeights; import org.opensearch.cluster.routing.WeightedRouting; import org.opensearch.common.bytes.BytesArray; import org.opensearch.common.xcontent.XContentType; @@ -22,7 +21,7 @@ public class ClusterPutWeightedRoutingRequestTests extends OpenSearchTestCase { public void testSetWRRWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); - Map weights = Map.of("us-east-1a", 1, "us-east-1b", 1, "us-east-1c", 0); + Map weights = Map.of("us-east-1a", 1.0, "us-east-1b", 1.0, "us-east-1c", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); request.attributeName("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); @@ -30,7 +29,7 @@ public void testSetWRRWeight() { } public void testValidate_ValuesAreProper() { - String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; + String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":0,\"us-east-1a\":\"1\"}"; ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); request.attributeName("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); @@ -71,15 +70,4 @@ public void testValidate_AttributeMissing() { } - public void testValidate_NonIntegerWeights() { - String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"5.6\",\"us-east-1a\":\"1\"}"; - ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); - request.attributeName("zone"); - request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); - ActionRequestValidationException actionRequestValidationException = request.validate(); - assertNotNull(actionRequestValidationException); - assertTrue(actionRequestValidationException.getMessage().contains("Weight is non-integer")); - - } - } diff --git a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java index 07354f29c0332..7b85677bf683b 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java @@ -8,7 +8,6 @@ package org.opensearch.rest.action.admin.cluster; -import com.fasterxml.jackson.core.JsonParseException; import org.junit.Before; import org.opensearch.OpenSearchParseException; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; @@ -34,14 +33,14 @@ public void setupAction() { } public void testCreateRequest_SupportedRequestBody() throws IOException { - String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; + String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1.0\", \"us-east-1a\":\"0.0\"}"; RestRequest restRequest = buildRestRequest(req); ClusterPutWeightedRoutingRequest clusterPutWeightedRoutingRequest = RestClusterPutWeightedRoutingAction.createRequest(restRequest); - assertEquals("zone", clusterPutWeightedRoutingRequest.wrrWeight().attributeName()); - assertNotNull(clusterPutWeightedRoutingRequest.wrrWeight().weights()); - assertEquals("1", clusterPutWeightedRoutingRequest.wrrWeight().weights().get("us-east-1c")); - assertEquals("1", clusterPutWeightedRoutingRequest.wrrWeight().weights().get("us-east-1d")); - assertEquals("0", clusterPutWeightedRoutingRequest.wrrWeight().weights().get("us-east-1a")); + assertEquals("zone", clusterPutWeightedRoutingRequest.weightedRouting().attributeName()); + assertNotNull(clusterPutWeightedRoutingRequest.weightedRouting().weights()); + assertEquals("1.0", clusterPutWeightedRoutingRequest.weightedRouting().weights().get("us-east-1c").toString()); + assertEquals("1.0", clusterPutWeightedRoutingRequest.weightedRouting().weights().get("us-east-1d").toString()); + assertEquals("0.0", clusterPutWeightedRoutingRequest.weightedRouting().weights().get("us-east-1a").toString()); } public void testCreateRequest_UnsupportedRequestBody() throws IOException { @@ -51,13 +50,13 @@ public void testCreateRequest_UnsupportedRequestBody() throws IOException { assertThrows(OpenSearchParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); } - public void testCreateRequest_MalformedRequestBody() throws IOException { - Map params = new HashMap<>(); - - String req = "{\"us-east-1c\" : \"1\" \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; - RestRequest restRequest = buildRestRequest(req); - assertThrows(JsonParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); - } + // public void testCreateRequest_MalformedRequestBody() throws IOException { + // Map params = new HashMap<>(); + // + // String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; + // RestRequest restRequest = buildRestRequest(req); + // assertThrows(JsonParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); + // } public void testCreateRequest_EmptyRequestBody() throws IOException { String req = "{}"; From 4f349e924dd3908797cc6b8a263e625e746b7584 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 16:39:50 +0530 Subject: [PATCH 39/55] Refactor code Signed-off-by: Anshu Agarwal --- .../org/opensearch/client/RestHighLevelClientTests.java | 2 +- ...rr_weights.json => cluster.put_weighted_routing.json} | 2 +- .../main/java/org/opensearch/action/ActionModule.java | 2 +- .../weighted/put/ClusterPutWeightedRoutingRequest.java | 9 +++++---- 4 files changed, 8 insertions(+), 7 deletions(-) rename rest-api-spec/src/main/resources/rest-api-spec/api/{cluster.put_wrr_weights.json => cluster.put_weighted_routing.json} (92%) diff --git a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java index 003a188f5f8dd..21120c1c9ce6f 100644 --- a/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/opensearch/client/RestHighLevelClientTests.java @@ -888,7 +888,7 @@ public void testApiNamingConventions() throws Exception { "nodes.reload_secure_settings", "search_shards", "remote_store.restore", - "cluster.put_wrr_weights", }; + "cluster.put_weighted_routing", }; List booleanReturnMethods = Arrays.asList("security.enable_user", "security.disable_user", "security.change_password"); Set deprecatedMethods = new HashSet<>(); deprecatedMethods.add("indices.force_merge"); diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json similarity index 92% rename from rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json rename to rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json index c8242dd8887cc..cab2080130995 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_wrr_weights.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json @@ -1,5 +1,5 @@ { - "cluster.put_wrr_weights": { + "cluster.put_weighted_routing": { "documentation": { "url": "http://TBA", "description": "TBA" diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 0fda4db453249..20b9be73b01f4 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -531,7 +531,6 @@ public void reg ) { register(new ActionHandler<>(action, transportAction, supportTransportActions)); } - } ActionRegistry actions = new ActionRegistry(); @@ -566,6 +565,7 @@ public void reg actions.register(CloneSnapshotAction.INSTANCE, TransportCloneSnapshotAction.class); actions.register(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class); actions.register(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class); + actions.register(ClusterPutWeightedRoutingAction.INSTANCE, TransportPutWeightedRoutingAction.class); actions.register(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class); actions.register(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index cb7f34b3db331..514d3c81ff085 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -100,12 +100,13 @@ public void setWeightedRouting(BytesReference source, XContentType contentType) attrWeight = Double.parseDouble(parser.text()); weights.put(attrValue, attrWeight); } else { - throw new OpenSearchParseException("failed to parse wrr request attribute [{}], unknown type", attrWeight); + throw new OpenSearchParseException("failed to parse weighted routing request attribute [{}], " + + "unknown type", attrWeight); } } this.weightedRouting = new WeightedRouting(this.attributeName, weights); } catch (IOException e) { - logger.error("error while parsing put wrr weights request object", e); + logger.error("error while parsing put for weighted routing request object", e); } } @@ -113,7 +114,7 @@ public void setWeightedRouting(BytesReference source, XContentType contentType) public ActionRequestValidationException validate() { ActionRequestValidationException validationException = null; if (weightedRouting == null) { - validationException = addValidationError("WRRWeights object is null", validationException); + validationException = addValidationError("Weighted routing request object is null", validationException); } if (weightedRouting.attributeName() == null || weightedRouting.attributeName().isEmpty()) { validationException = addValidationError("Attribute name is missing", validationException); @@ -133,7 +134,7 @@ public ActionRequestValidationException validate() { } } } catch (NumberFormatException e) { - validationException = addValidationError(("Weight is not number"), validationException); + validationException = addValidationError(("Weight is not a number"), validationException); } if (countValueWithZeroWeights > 1) { validationException = addValidationError(("More than one value has weight set as 0 "), validationException); From e59cff2329e17a57ee4b4132b1a830c74c8732c0 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 16:54:04 +0530 Subject: [PATCH 40/55] Remove unwanted changes Signed-off-by: Anshu Agarwal --- .../opensearch/client/ClusterAdminClient.java | 15 ++++++++++----- .../java/org/opensearch/client/Requests.java | 16 ++++++++-------- .../org/opensearch/cluster/ClusterModule.java | 9 ++------- .../RestClusterPutWeightedRoutingAction.java | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java index ce4146ffc3ed1..3dea78d49e064 100644 --- a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java +++ b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java @@ -143,8 +143,9 @@ /** * Administrative actions/operations against indices. * - * @opensearch.internal * @see AdminClient#cluster() + * + * @opensearch.internal */ public interface ClusterAdminClient extends OpenSearchClient { @@ -300,7 +301,8 @@ public interface ClusterAdminClient extends OpenSearchClient { * sampled for the node ids specified in the request. Nodes usage of the * cluster. * - * @param request The nodes usage request + * @param request + * The nodes usage request * @return The result future * @see org.opensearch.client.Requests#nodesUsageRequest(String...) */ @@ -309,8 +311,10 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Nodes usage of the cluster. * - * @param request The nodes usage request - * @param listener A listener to be notified with a result + * @param request + * The nodes usage request + * @param listener + * A listener to be notified with a result * @see org.opensearch.client.Requests#nodesUsageRequest(String...) */ void nodesUsage(NodesUsageRequest request, ActionListener listener); @@ -323,6 +327,7 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Returns top N hot-threads samples per node. The hot-threads are only * sampled for the node ids specified in the request. + * */ ActionFuture nodesHotThreads(NodesHotThreadsRequest request); @@ -373,7 +378,7 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Get a task. * - * @param request the request + * @param request the request * @param listener A listener to be notified with the result * @see org.opensearch.client.Requests#getTaskRequest() */ diff --git a/server/src/main/java/org/opensearch/client/Requests.java b/server/src/main/java/org/opensearch/client/Requests.java index 22a20fc9c6eaf..48ca23cc8b4e2 100644 --- a/server/src/main/java/org/opensearch/client/Requests.java +++ b/server/src/main/java/org/opensearch/client/Requests.java @@ -171,7 +171,6 @@ public static IndicesSegmentsRequest indicesSegmentsRequest(String... indices) { /** * Creates an indices shard stores info request. - * * @param indices The indices to get shard store information on * @return The indices shard stores request * @see org.opensearch.client.IndicesAdminClient#shardStores(IndicesShardStoresRequest) @@ -385,11 +384,13 @@ public static NodesInfoRequest nodesInfoRequest(String... nodesIds) { } /** - * Creates a nodes stats request against one or more nodes. Pass {@code null} or an empty array for all nodes. + * Creates a nodes usage request against one or more nodes. Pass + * {@code null} or an empty array for all nodes. * - * @param nodesIds The nodes ids to get the stats for - * @return The nodes info request - * @see org.opensearch.client.ClusterAdminClient#nodesStats(NodesStatsRequest) + * @param nodesIds + * The nodes ids to get the usage for + * @return The nodes usage request + * @see org.opensearch.client.ClusterAdminClient#nodesUsage(NodesUsageRequest) */ public static NodesStatsRequest nodesStatsRequest(String... nodesIds) { return new NodesStatsRequest(nodesIds); @@ -541,7 +542,7 @@ public static DeleteSnapshotRequest deleteSnapshotRequest(String repository, Str } /** - * Get status of snapshots + * Get status of snapshots * * @param repository repository name * @return snapshot status request @@ -555,8 +556,7 @@ public static SnapshotsStatusRequest snapshotsStatusRequest(String repository) { * * @return update weight request */ - public static ClusterPutWeightedRoutingRequest putWRRWeightsRequest() { + public static ClusterPutWeightedRoutingRequest putWeightedRoutingRequest() { return new ClusterPutWeightedRoutingRequest(); } - } diff --git a/server/src/main/java/org/opensearch/cluster/ClusterModule.java b/server/src/main/java/org/opensearch/cluster/ClusterModule.java index 8face52cde295..46552bb5d6a03 100644 --- a/server/src/main/java/org/opensearch/cluster/ClusterModule.java +++ b/server/src/main/java/org/opensearch/cluster/ClusterModule.java @@ -320,10 +320,7 @@ public IndexNameExpressionResolver getIndexNameExpressionResolver() { } // TODO: this is public so allocation benchmark can access the default deciders...can we do that in another way? - - /** - * Return a new {@link AllocationDecider} instance with builtin deciders as well as those from plugins. - */ + /** Return a new {@link AllocationDecider} instance with builtin deciders as well as those from plugins. */ public static Collection createAllocationDeciders( Settings settings, ClusterSettings clusterSettings, @@ -357,9 +354,7 @@ public static Collection createAllocationDeciders( return deciders.values(); } - /** - * Add the given allocation decider to the given deciders collection, erroring if the class name is already used. - */ + /** Add the given allocation decider to the given deciders collection, erroring if the class name is already used. */ private static void addAllocationDecider(Map deciders, AllocationDecider decider) { if (deciders.put(decider.getClass(), decider) != null) { throw new IllegalArgumentException("Cannot specify allocation decider [" + decider.getClass().getName() + "] twice"); diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java index 955af27a965c2..4a8a1a1bd8de6 100644 --- a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java @@ -50,7 +50,7 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli } public static ClusterPutWeightedRoutingRequest createRequest(RestRequest request) throws IOException { - ClusterPutWeightedRoutingRequest putWRRWeightsRequest = Requests.putWRRWeightsRequest(); + ClusterPutWeightedRoutingRequest putWRRWeightsRequest = Requests.putWeightedRoutingRequest(); String attributeName = null; if (request.hasParam("attribute")) { attributeName = request.param("attribute"); From dc79fec66206973f6a5ca9690191df29c8a24ff7 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 16:58:09 +0530 Subject: [PATCH 41/55] Remove unwanted changes for Requests.java Signed-off-by: Anshu Agarwal --- .../main/java/org/opensearch/client/Requests.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/org/opensearch/client/Requests.java b/server/src/main/java/org/opensearch/client/Requests.java index 48ca23cc8b4e2..e1021ea3666cd 100644 --- a/server/src/main/java/org/opensearch/client/Requests.java +++ b/server/src/main/java/org/opensearch/client/Requests.java @@ -384,13 +384,11 @@ public static NodesInfoRequest nodesInfoRequest(String... nodesIds) { } /** - * Creates a nodes usage request against one or more nodes. Pass - * {@code null} or an empty array for all nodes. + * Creates a nodes stats request against one or more nodes. Pass {@code null} or an empty array for all nodes. * - * @param nodesIds - * The nodes ids to get the usage for - * @return The nodes usage request - * @see org.opensearch.client.ClusterAdminClient#nodesUsage(NodesUsageRequest) + * @param nodesIds The nodes ids to get the stats for + * @return The nodes info request + * @see org.opensearch.client.ClusterAdminClient#nodesStats(NodesStatsRequest) */ public static NodesStatsRequest nodesStatsRequest(String... nodesIds) { return new NodesStatsRequest(nodesIds); @@ -400,7 +398,8 @@ public static NodesStatsRequest nodesStatsRequest(String... nodesIds) { * Creates a nodes usage request against one or more nodes. Pass * {@code null} or an empty array for all nodes. * - * @param nodesIds The nodes ids to get the usage for + * @param nodesIds + * The nodes ids to get the usage for * @return The nodes usage request * @see org.opensearch.client.ClusterAdminClient#nodesUsage(NodesUsageRequest) */ From 7671d6318a2eeafe5f7c16946574ae8211bf0643 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 17:59:09 +0530 Subject: [PATCH 42/55] Refactore code Signed-off-by: Anshu Agarwal --- .../put/ClusterPutWeightedRoutingAction.java | 1 - .../put/ClusterPutWeightedRoutingRequest.java | 6 ++- .../TransportPutWeightedRoutingAction.java | 4 +- .../opensearch/client/ClusterAdminClient.java | 6 +-- .../client/support/AbstractClient.java | 9 +++-- .../routing/WeightedRoutingService.java | 38 +++++++++---------- .../RestClusterPutWeightedRoutingAction.java | 14 +++---- ...ClusterPutWeightedRoutingRequestTests.java | 2 +- ...tClusterPutWeightedRoutingActionTests.java | 15 ++++---- 9 files changed, 50 insertions(+), 45 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java index 56ba62277fafc..9931c3dc5782b 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java @@ -23,5 +23,4 @@ public final class ClusterPutWeightedRoutingAction extends ActionType listener ) throws Exception { verifyAwarenessAttribute(request.weightedRouting().attributeName()); - weightedRoutingService.registerWRRWeightsMetadata( + weightedRoutingService.registerWeightedRoutingMetadata( request, ActionListener.delegateFailure( listener, @@ -112,7 +112,7 @@ private void verifyAwarenessAttribute(String attributeName) { if (!getAwarenessAttributes().contains(attributeName) || !attributeName.equalsIgnoreCase("zone")) { ActionRequestValidationException validationException = null; validationException = addValidationError( - "invalid awareness attribute " + attributeName + " requested for " + "updating wrr weights", + "invalid awareness attribute " + attributeName + " requested for " + "updating weighted routing " + "weights", validationException ); throw validationException; diff --git a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java index 3dea78d49e064..2f62ab13b131c 100644 --- a/server/src/main/java/org/opensearch/client/ClusterAdminClient.java +++ b/server/src/main/java/org/opensearch/client/ClusterAdminClient.java @@ -798,16 +798,16 @@ public interface ClusterAdminClient extends OpenSearchClient { /** * Updates weights for weighted round-robin search routing policy. */ - ActionFuture putWRRWeights(ClusterPutWeightedRoutingRequest request); + ActionFuture putWeightedRouting(ClusterPutWeightedRoutingRequest request); /** * Updates weights for weighted round-robin search routing policy. */ - void putWRRWeights(ClusterPutWeightedRoutingRequest request, ActionListener listener); + void putWeightedRouting(ClusterPutWeightedRoutingRequest request, ActionListener listener); /** * Updates weights for weighted round-robin search routing policy. */ - ClusterPutWeightedRoutingRequestBuilder prepareWRRWeights(); + ClusterPutWeightedRoutingRequestBuilder prepareWeightedRouting(); } diff --git a/server/src/main/java/org/opensearch/client/support/AbstractClient.java b/server/src/main/java/org/opensearch/client/support/AbstractClient.java index 870da1622afaf..0737b109b1c07 100644 --- a/server/src/main/java/org/opensearch/client/support/AbstractClient.java +++ b/server/src/main/java/org/opensearch/client/support/AbstractClient.java @@ -1269,17 +1269,20 @@ public ActionFuture deleteDanglingIndex(DeleteDanglingInde } @Override - public ActionFuture putWRRWeights(ClusterPutWeightedRoutingRequest request) { + public ActionFuture putWeightedRouting(ClusterPutWeightedRoutingRequest request) { return execute(ClusterPutWeightedRoutingAction.INSTANCE, request); } @Override - public void putWRRWeights(ClusterPutWeightedRoutingRequest request, ActionListener listener) { + public void putWeightedRouting( + ClusterPutWeightedRoutingRequest request, + ActionListener listener + ) { execute(ClusterPutWeightedRoutingAction.INSTANCE, request, listener); } @Override - public ClusterPutWeightedRoutingRequestBuilder prepareWRRWeights() { + public ClusterPutWeightedRoutingRequestBuilder prepareWeightedRouting() { return new ClusterPutWeightedRoutingRequestBuilder(this, ClusterPutWeightedRoutingAction.INSTANCE); } diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index c92413161dfb7..9e3ee0dc4a167 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -30,7 +30,7 @@ import java.io.IOException; /** - * * Service responsible for updating cluster state metadata with wrr weights + * * Service responsible for updating cluster state metadata with weighted routing weights */ public class WeightedRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { private static final Logger logger = LogManager.getLogger(WeightedRoutingService.class); @@ -45,54 +45,54 @@ public WeightedRoutingService(ClusterService clusterService, ThreadPool threadPo this.threadPool = threadPool; } - public void registerWRRWeightsMetadata( + public void registerWeightedRoutingMetadata( final ClusterPutWeightedRoutingRequest request, final ActionListener listener ) { - final WeightedRoutingMetadata newWRRWeightsMetadata = new WeightedRoutingMetadata(request.weightedRouting()); - clusterService.submitStateUpdateTask("update_wrr_weights", new ClusterStateUpdateTask(Priority.URGENT) { + final WeightedRoutingMetadata newWeightedRoutingMetadata = new WeightedRoutingMetadata(request.weightedRouting()); + clusterService.submitStateUpdateTask("update_weighted_routing", new ClusterStateUpdateTask(Priority.URGENT) { @Override public ClusterState execute(ClusterState currentState) { Metadata metadata = currentState.metadata(); Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata()); - WeightedRoutingMetadata wrrWeights = metadata.custom(WeightedRoutingMetadata.TYPE); - if (wrrWeights == null) { - logger.info("put wrr weights [{}]", request.weightedRouting()); - wrrWeights = new WeightedRoutingMetadata(request.weightedRouting()); + WeightedRoutingMetadata weightedRoutingMetadata = metadata.custom(WeightedRoutingMetadata.TYPE); + if (weightedRoutingMetadata == null) { + logger.info("put weighted routing weights in metadata [{}]", request.weightedRouting()); + weightedRoutingMetadata = new WeightedRoutingMetadata(request.weightedRouting()); } else { WeightedRoutingMetadata changedMetadata = new WeightedRoutingMetadata(new WeightedRouting(null, null)); - if (!checkIfSameWeightsInMetadata(newWRRWeightsMetadata, wrrWeights)) { - logger.info("updated wrr weights [{}] in metadata", request.weightedRouting()); - changedMetadata.setWeightedRouting(newWRRWeightsMetadata.getWeightedRouting()); + if (!checkIfSameWeightsInMetadata(newWeightedRoutingMetadata, weightedRoutingMetadata)) { + logger.info("updated weighted routing weights [{}] in metadata", request.weightedRouting()); + changedMetadata.setWeightedRouting(newWeightedRoutingMetadata.getWeightedRouting()); } else { return currentState; } - wrrWeights = new WeightedRoutingMetadata(changedMetadata.getWeightedRouting()); + weightedRoutingMetadata = new WeightedRoutingMetadata(changedMetadata.getWeightedRouting()); } - mdBuilder.putCustom(WeightedRoutingMetadata.TYPE, wrrWeights); - logger.info("building cluster state with wrr weights [{}]", request.weightedRouting()); + mdBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); + logger.info("building cluster state with weighted routing weights [{}]", request.weightedRouting()); return ClusterState.builder(currentState).metadata(mdBuilder).build(); } @Override public void onFailure(String source, Exception e) { - logger.warn(() -> new ParameterizedMessage("failed to update cluster state for wrr weights [{}]", e)); + logger.warn(() -> new ParameterizedMessage("failed to update cluster state for weighted routing " + "weights [{}]", e)); listener.onFailure(e); } @Override public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { - logger.info("Cluster wrr weights metadata change is processed by all the nodes"); + logger.info("cluster weighted routing weights metadata change is processed by all the nodes"); listener.onResponse(new ClusterStateUpdateResponse(true)); } }); } private boolean checkIfSameWeightsInMetadata( - WeightedRoutingMetadata newWRRWeightsMetadata, - WeightedRoutingMetadata oldWRRWeightsMetadata + WeightedRoutingMetadata newWeightedroutingMetadata, + WeightedRoutingMetadata oldWeightedRoutingMetadata ) { - if (newWRRWeightsMetadata.getWeightedRouting().equals(oldWRRWeightsMetadata.getWeightedRouting())) { + if (newWeightedroutingMetadata.getWeightedRouting().equals(oldWeightedRoutingMetadata.getWeightedRouting())) { return true; } return false; diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java index 4a8a1a1bd8de6..d95df02ea73cc 100644 --- a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java @@ -40,24 +40,24 @@ public List routes() { @Override public String getName() { - return "put_wrr_weights_action"; + return "put_weighted_routing_action"; } @Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { - ClusterPutWeightedRoutingRequest putWRRWeightsRequest = createRequest(request); - return channel -> client.admin().cluster().putWRRWeights(putWRRWeightsRequest, new RestToXContentListener<>(channel)); + ClusterPutWeightedRoutingRequest putWeightedRoutingRequest = createRequest(request); + return channel -> client.admin().cluster().putWeightedRouting(putWeightedRoutingRequest, new RestToXContentListener<>(channel)); } public static ClusterPutWeightedRoutingRequest createRequest(RestRequest request) throws IOException { - ClusterPutWeightedRoutingRequest putWRRWeightsRequest = Requests.putWeightedRoutingRequest(); + ClusterPutWeightedRoutingRequest putWeightedRoutingRequest = Requests.putWeightedRoutingRequest(); String attributeName = null; if (request.hasParam("attribute")) { attributeName = request.param("attribute"); } - putWRRWeightsRequest.attributeName(attributeName); - request.applyContentParser(p -> putWRRWeightsRequest.source(p.mapStrings())); - return putWRRWeightsRequest; + putWeightedRoutingRequest.attributeName(attributeName); + request.applyContentParser(p -> putWeightedRoutingRequest.source(p.mapStrings())); + return putWeightedRoutingRequest; } } diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 236262a6f0836..6b24ac3c9ad4a 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -18,7 +18,7 @@ public class ClusterPutWeightedRoutingRequestTests extends OpenSearchTestCase { - public void testSetWRRWeight() { + public void testSetWeightedRoutingWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); Map weights = Map.of("us-east-1a", 1.0, "us-east-1b", 1.0, "us-east-1c", 0.0); diff --git a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java index 7b85677bf683b..e801b6108ac2f 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java @@ -8,6 +8,7 @@ package org.opensearch.rest.action.admin.cluster; +import com.fasterxml.jackson.core.JsonParseException; import org.junit.Before; import org.opensearch.OpenSearchParseException; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; @@ -50,13 +51,13 @@ public void testCreateRequest_UnsupportedRequestBody() throws IOException { assertThrows(OpenSearchParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); } - // public void testCreateRequest_MalformedRequestBody() throws IOException { - // Map params = new HashMap<>(); - // - // String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; - // RestRequest restRequest = buildRestRequest(req); - // assertThrows(JsonParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); - // } + public void testCreateRequest_MalformedRequestBody() throws IOException { + Map params = new HashMap<>(); + + String req = "{\"us-east-1c\" : \1\", \"us-east-1d\":\"1\", \"us-east-1a\":\"0\"}"; + RestRequest restRequest = buildRestRequest(req); + assertThrows(JsonParseException.class, () -> RestClusterPutWeightedRoutingAction.createRequest(restRequest)); + } public void testCreateRequest_EmptyRequestBody() throws IOException { String req = "{}"; From 454387d930b66af10c119857bd955907eea6e885 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 18:17:06 +0530 Subject: [PATCH 43/55] Add change log Signed-off-by: Anshu Agarwal --- CHANGELOG.md | 1 + .../weighted/put/ClusterPutWeightedRoutingRequest.java | 5 +---- .../weighted/put/TransportPutWeightedRoutingAction.java | 1 - .../opensearch/cluster/routing/WeightedRoutingService.java | 2 -- .../weighted/put/ClusterPutWeightedRoutingRequestTests.java | 4 ---- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c610c89eeaf3..cbda997eb9f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Segment Replication] Update replicas to commit SegmentInfos instead of relying on SIS files from primary shards. ([#4402](https://github.com/opensearch-project/OpenSearch/pull/4402)) - [CCR] Add getHistoryOperationsFromTranslog method to fetch the history snapshot from translogs ([#3948](https://github.com/opensearch-project/OpenSearch/pull/3948)) - [Remote Store] Change behaviour in replica recovery for remote translog enabled indices ([#4318](https://github.com/opensearch-project/OpenSearch/pull/4318)) +- PUT api for weighted shard routing ([#4272](https://github.com/opensearch-project/OpenSearch/pull/4272)) ### Deprecated diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index 556a9388c99db..0f33bb593c109 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -61,9 +61,7 @@ public ClusterPutWeightedRoutingRequest(StreamInput in) throws IOException { weightedRouting = new WeightedRouting(in); } - public ClusterPutWeightedRoutingRequest() { - - } + public ClusterPutWeightedRoutingRequest() {} public void setWeightedRouting(Map source) { try { @@ -141,7 +139,6 @@ public ActionRequestValidationException validate() { if (countValueWithZeroWeights > 1) { validationException = addValidationError(("More than one value has weight set as 0 "), validationException); } - return validationException; } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java index e50f103e109b2..4dddfe103f36e 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java @@ -40,7 +40,6 @@ public class TransportPutWeightedRoutingAction extends TransportClusterManagerNo ClusterPutWeightedRoutingResponse> { private final WeightedRoutingService weightedRoutingService; - private volatile List awarenessAttributes; @Inject diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index 9e3ee0dc4a167..3b377da8599b7 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -34,9 +34,7 @@ */ public class WeightedRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { private static final Logger logger = LogManager.getLogger(WeightedRoutingService.class); - private final ClusterService clusterService; - private final ThreadPool threadPool; @Inject diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 6b24ac3c9ad4a..929818136d27c 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -35,7 +35,6 @@ public void testValidate_ValuesAreProper() { request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNull(actionRequestValidationException); - } public void testValidate_TwoZonesWithZeroWeight() { @@ -46,7 +45,6 @@ public void testValidate_TwoZonesWithZeroWeight() { ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("More than one value has weight set as 0")); - } public void testValidate_MissingWeights() { @@ -57,7 +55,6 @@ public void testValidate_MissingWeights() { ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("Weights are missing")); - } public void testValidate_AttributeMissing() { @@ -67,7 +64,6 @@ public void testValidate_AttributeMissing() { ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); assertTrue(actionRequestValidationException.getMessage().contains("Attribute name is missing")); - } } From 027d73ae0f3117e040c5db73e777ef8bc7c8bb97 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 19 Sep 2022 19:56:01 +0530 Subject: [PATCH 44/55] Fix test failure Signed-off-by: Anshu Agarwal --- .../weighted/put/ClusterPutWeightedRoutingRequestTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 929818136d27c..d12a61cc56334 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -29,7 +29,7 @@ public void testSetWeightedRoutingWeight() { } public void testValidate_ValuesAreProper() { - String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":0,\"us-east-1a\":\"1\"}"; + String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); request.attributeName("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); From 19047e607b445f7113e24beb6d202c5f42d6cec5 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Tue, 20 Sep 2022 15:43:03 +0530 Subject: [PATCH 45/55] Make WeightedRoutingService not to imoplement ClusterStateApplier Signed-off-by: Anshu Agarwal --- .../cluster/routing/WeightedRoutingService.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index 3b377da8599b7..bd2a99128ec02 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -13,9 +13,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage; import org.opensearch.action.ActionListener; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; -import org.opensearch.cluster.ClusterChangedEvent; import org.opensearch.cluster.ClusterState; -import org.opensearch.cluster.ClusterStateApplier; import org.opensearch.cluster.ClusterStateUpdateTask; import org.opensearch.cluster.ack.ClusterStateUpdateResponse; import org.opensearch.cluster.metadata.Metadata; @@ -32,7 +30,7 @@ /** * * Service responsible for updating cluster state metadata with weighted routing weights */ -public class WeightedRoutingService extends AbstractLifecycleComponent implements ClusterStateApplier { +public class WeightedRoutingService extends AbstractLifecycleComponent { private static final Logger logger = LogManager.getLogger(WeightedRoutingService.class); private final ClusterService clusterService; private final ThreadPool threadPool; @@ -97,14 +95,17 @@ private boolean checkIfSameWeightsInMetadata( } @Override - public void applyClusterState(ClusterChangedEvent event) {} + protected void doStart() { - @Override - protected void doStart() {} + } @Override - protected void doStop() {} + protected void doStop() { + + } @Override - protected void doClose() throws IOException {} + protected void doClose() throws IOException { + + } } From 663017fcd7720f39a51efdd82ea714473bb4f29d Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Tue, 20 Sep 2022 16:46:14 +0530 Subject: [PATCH 46/55] Update metadata call Signed-off-by: Anshu Agarwal --- .../opensearch/cluster/routing/WeightedRoutingService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index bd2a99128ec02..c94c461e2d7ce 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -51,14 +51,14 @@ public void registerWeightedRoutingMetadata( public ClusterState execute(ClusterState currentState) { Metadata metadata = currentState.metadata(); Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata()); - WeightedRoutingMetadata weightedRoutingMetadata = metadata.custom(WeightedRoutingMetadata.TYPE); + WeightedRoutingMetadata weightedRoutingMetadata = metadata.weightedRoutingMetadata(); if (weightedRoutingMetadata == null) { - logger.info("put weighted routing weights in metadata [{}]", request.weightedRouting()); + logger.info("putting weighted routing weights in metadata [{}]", request.weightedRouting()); weightedRoutingMetadata = new WeightedRoutingMetadata(request.weightedRouting()); } else { WeightedRoutingMetadata changedMetadata = new WeightedRoutingMetadata(new WeightedRouting(null, null)); if (!checkIfSameWeightsInMetadata(newWeightedRoutingMetadata, weightedRoutingMetadata)) { - logger.info("updated weighted routing weights [{}] in metadata", request.weightedRouting()); + logger.info("updating weighted routing weights [{}] in metadata", request.weightedRouting()); changedMetadata.setWeightedRouting(newWeightedRoutingMetadata.getWeightedRouting()); } else { return currentState; From 70790e94584124fb59588383a15999877f84f7e0 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Wed, 21 Sep 2022 16:47:55 +0530 Subject: [PATCH 47/55] Add tests for WeightedRoutingService Signed-off-by: Anshu Agarwal --- .../put/ClusterPutWeightedRoutingRequest.java | 4 +- ...usterPutWeightedRoutingRequestBuilder.java | 2 +- .../TransportPutWeightedRoutingAction.java | 2 +- .../routing/WeightedRoutingService.java | 28 +-- ...ClusterPutWeightedRoutingRequestTests.java | 2 +- .../routing/WeightedRoutingServiceTests.java | 234 ++++++++++++++++++ ...tClusterPutWeightedRoutingActionTests.java | 10 +- 7 files changed, 255 insertions(+), 27 deletions(-) create mode 100644 server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index 0f33bb593c109..2835e253a3b39 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -43,11 +43,11 @@ public class ClusterPutWeightedRoutingRequest extends ClusterManagerNodeRequest< private WeightedRouting weightedRouting; private String attributeName; - public WeightedRouting weightedRouting() { + public WeightedRouting getWeightedRouting() { return weightedRouting; } - public ClusterPutWeightedRoutingRequest weightedRouting(WeightedRouting weightedRouting) { + public ClusterPutWeightedRoutingRequest setWeightedRouting(WeightedRouting weightedRouting) { this.weightedRouting = weightedRouting; return this; } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java index e890319fda759..83d37e781b02b 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java @@ -26,7 +26,7 @@ public ClusterPutWeightedRoutingRequestBuilder(OpenSearchClient client, ClusterP } public ClusterPutWeightedRoutingRequestBuilder setWeightedRouting(WeightedRouting weightedRouting) { - request.weightedRouting(weightedRouting); + request.setWeightedRouting(weightedRouting); return this; } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java index 4dddfe103f36e..29a1128be71da 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java @@ -94,7 +94,7 @@ protected void clusterManagerOperation( ClusterState state, ActionListener listener ) throws Exception { - verifyAwarenessAttribute(request.weightedRouting().attributeName()); + verifyAwarenessAttribute(request.getWeightedRouting().attributeName()); weightedRoutingService.registerWeightedRoutingMetadata( request, ActionListener.delegateFailure( diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index c94c461e2d7ce..753066f0ea55b 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -45,20 +45,20 @@ public void registerWeightedRoutingMetadata( final ClusterPutWeightedRoutingRequest request, final ActionListener listener ) { - final WeightedRoutingMetadata newWeightedRoutingMetadata = new WeightedRoutingMetadata(request.weightedRouting()); + final WeightedRoutingMetadata newWeightedRoutingMetadata = new WeightedRoutingMetadata(request.getWeightedRouting()); clusterService.submitStateUpdateTask("update_weighted_routing", new ClusterStateUpdateTask(Priority.URGENT) { @Override public ClusterState execute(ClusterState currentState) { Metadata metadata = currentState.metadata(); Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata()); - WeightedRoutingMetadata weightedRoutingMetadata = metadata.weightedRoutingMetadata(); + WeightedRoutingMetadata weightedRoutingMetadata = metadata.custom(WeightedRoutingMetadata.TYPE); if (weightedRoutingMetadata == null) { - logger.info("putting weighted routing weights in metadata [{}]", request.weightedRouting()); - weightedRoutingMetadata = new WeightedRoutingMetadata(request.weightedRouting()); + logger.info("put weighted routing weights in metadata [{}]", request.getWeightedRouting()); + weightedRoutingMetadata = new WeightedRoutingMetadata(request.getWeightedRouting()); } else { WeightedRoutingMetadata changedMetadata = new WeightedRoutingMetadata(new WeightedRouting(null, null)); if (!checkIfSameWeightsInMetadata(newWeightedRoutingMetadata, weightedRoutingMetadata)) { - logger.info("updating weighted routing weights [{}] in metadata", request.weightedRouting()); + logger.info("updated weighted routing weights [{}] in metadata", request.getWeightedRouting()); changedMetadata.setWeightedRouting(newWeightedRoutingMetadata.getWeightedRouting()); } else { return currentState; @@ -66,7 +66,7 @@ public ClusterState execute(ClusterState currentState) { weightedRoutingMetadata = new WeightedRoutingMetadata(changedMetadata.getWeightedRouting()); } mdBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); - logger.info("building cluster state with weighted routing weights [{}]", request.weightedRouting()); + logger.info("building cluster state with weighted routing weights [{}]", request.getWeightedRouting()); return ClusterState.builder(currentState).metadata(mdBuilder).build(); } @@ -85,27 +85,21 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS } private boolean checkIfSameWeightsInMetadata( - WeightedRoutingMetadata newWeightedroutingMetadata, + WeightedRoutingMetadata newWeightedRoutingMetadata, WeightedRoutingMetadata oldWeightedRoutingMetadata ) { - if (newWeightedroutingMetadata.getWeightedRouting().equals(oldWeightedRoutingMetadata.getWeightedRouting())) { + if (newWeightedRoutingMetadata.getWeightedRouting().equals(oldWeightedRoutingMetadata.getWeightedRouting())) { return true; } return false; } @Override - protected void doStart() { - - } + protected void doStart() {} @Override - protected void doStop() { - - } + protected void doStop() {} @Override - protected void doClose() throws IOException { - - } + protected void doClose() throws IOException {} } diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index d12a61cc56334..1180c83a8c9cd 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -25,7 +25,7 @@ public void testSetWeightedRoutingWeight() { WeightedRouting weightedRouting = new WeightedRouting("zone", weights); request.attributeName("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); - assertEquals(request.weightedRouting(), weightedRouting); + assertEquals(request.getWeightedRouting(), weightedRouting); } public void testValidate_ValuesAreProper() { diff --git a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java new file mode 100644 index 0000000000000..17e0cf5613f8c --- /dev/null +++ b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java @@ -0,0 +1,234 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.cluster.routing; + +import org.junit.After; +import org.junit.Before; +import org.opensearch.Version; +import org.opensearch.action.ActionListener; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequestBuilder; +import org.opensearch.client.node.NodeClient; +import org.opensearch.cluster.ClusterName; +import org.opensearch.cluster.ClusterState; +import org.opensearch.cluster.ack.ClusterStateUpdateResponse; +import org.opensearch.cluster.metadata.Metadata; +import org.opensearch.cluster.metadata.WeightedRoutingMetadata; +import org.opensearch.cluster.node.DiscoveryNode; +import org.opensearch.cluster.node.DiscoveryNodeRole; +import org.opensearch.cluster.node.DiscoveryNodes; +import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.Settings; +import org.opensearch.test.ClusterServiceUtils; +import org.opensearch.test.OpenSearchTestCase; +import org.opensearch.test.transport.MockTransport; +import org.opensearch.threadpool.TestThreadPool; +import org.opensearch.threadpool.ThreadPool; +import org.opensearch.transport.TransportService; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class WeightedRoutingServiceTests extends OpenSearchTestCase { + private ThreadPool threadPool; + private ClusterService clusterService; + private TransportService transportService; + private WeightedRoutingService weightedRoutingService; + private ClusterSettings clusterSettings; + NodeClient client; + + final private static Set CLUSTER_MANAGER_ROLE = Collections.unmodifiableSet( + new HashSet<>(Collections.singletonList(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE)) + ); + + final private static Set DATA_ROLE = Collections.unmodifiableSet( + new HashSet<>(Collections.singletonList(DiscoveryNodeRole.DATA_ROLE)) + ); + + @Override + public void setUp() throws Exception { + super.setUp(); + threadPool = new TestThreadPool("test", Settings.EMPTY); + clusterService = ClusterServiceUtils.createClusterService(threadPool); + } + + @Before + public void setUpService() { + ClusterState clusterState = ClusterState.builder(new ClusterName("test")).build(); + clusterState = addClusterManagerNodes(clusterState); + clusterState = addDataNodes(clusterState); + clusterState = setLocalNode(clusterState, "nodeA1"); + + ClusterState.Builder builder = ClusterState.builder(clusterState); + ClusterServiceUtils.setState(clusterService, builder); + + final MockTransport transport = new MockTransport(); + transportService = transport.createTransportService( + Settings.EMPTY, + threadPool, + TransportService.NOOP_TRANSPORT_INTERCEPTOR, + boundTransportAddress -> clusterService.state().nodes().get("nodes1"), + null, + Collections.emptySet() + + ); + + Settings.Builder settingsBuilder = Settings.builder() + .put(AwarenessAllocationDecider.CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTE_SETTING.getKey(), "zone"); + + clusterSettings = new ClusterSettings(settingsBuilder.build(), ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + transportService.start(); + transportService.acceptIncomingRequests(); + + this.weightedRoutingService = new WeightedRoutingService(clusterService, threadPool); + client = new NodeClient(Settings.EMPTY, threadPool); + } + + @After + public void shutdown() { + clusterService.stop(); + threadPool.shutdown(); + } + + private ClusterState addDataNodes(ClusterState clusterState) { + clusterState = addDataNodeForAZone(clusterState, "zone_A", "nodeA1", "nodeA2", "nodeA3"); + clusterState = addDataNodeForAZone(clusterState, "zone_B", "nodeB1", "nodeB2", "nodeB3"); + clusterState = addDataNodeForAZone(clusterState, "zone_C", "nodeC1", "nodeC2", "nodeC3"); + return clusterState; + } + + private ClusterState addClusterManagerNodes(ClusterState clusterState) { + clusterState = addClusterManagerNodeForAZone(clusterState, "zone_A", "nodeMA"); + clusterState = addClusterManagerNodeForAZone(clusterState, "zone_B", "nodeMB"); + clusterState = addClusterManagerNodeForAZone(clusterState, "zone_C", "nodeMC"); + return clusterState; + } + + private ClusterState addDataNodeForAZone(ClusterState clusterState, String zone, String... nodeIds) { + DiscoveryNodes.Builder nodeBuilder = DiscoveryNodes.builder(clusterState.nodes()); + org.opensearch.common.collect.List.of(nodeIds) + .forEach( + nodeId -> nodeBuilder.add( + new DiscoveryNode( + nodeId, + buildNewFakeTransportAddress(), + Collections.singletonMap("zone", zone), + DATA_ROLE, + Version.CURRENT + ) + ) + ); + clusterState = ClusterState.builder(clusterState).nodes(nodeBuilder).build(); + return clusterState; + } + + private ClusterState addClusterManagerNodeForAZone(ClusterState clusterState, String zone, String... nodeIds) { + + DiscoveryNodes.Builder nodeBuilder = DiscoveryNodes.builder(clusterState.nodes()); + org.opensearch.common.collect.List.of(nodeIds) + .forEach( + nodeId -> nodeBuilder.add( + new DiscoveryNode( + nodeId, + buildNewFakeTransportAddress(), + Collections.singletonMap("zone", zone), + CLUSTER_MANAGER_ROLE, + Version.CURRENT + ) + ) + ); + clusterState = ClusterState.builder(clusterState).nodes(nodeBuilder).build(); + return clusterState; + } + + private ClusterState setLocalNode(ClusterState clusterState, String nodeId) { + DiscoveryNodes.Builder nodeBuilder = DiscoveryNodes.builder(clusterState.nodes()); + nodeBuilder.localNodeId(nodeId); + nodeBuilder.clusterManagerNodeId(nodeId); + clusterState = ClusterState.builder(clusterState).nodes(nodeBuilder).build(); + return clusterState; + } + + private ClusterState setWeightedRoutingWeights(ClusterState clusterState, Map weights) { + WeightedRouting weightedRouting = new WeightedRouting("zone", weights); + WeightedRoutingMetadata weightedRoutingMetadata = new WeightedRoutingMetadata(weightedRouting); + Metadata.Builder metadataBuilder = Metadata.builder(clusterState.metadata()); + metadataBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); + clusterState = ClusterState.builder(clusterState).metadata(metadataBuilder).build(); + return clusterState; + } + + public void testRegisterWeightedRoutingMetadataWithChangedWeights() throws InterruptedException { + Map weights = Map.of("zone_A", 1.0, "zone_B", 1.0, "zone_C", 1.0); + ClusterState state = clusterService.state(); + state = setWeightedRoutingWeights(state, weights); + ClusterState.Builder builder = ClusterState.builder(state); + ClusterServiceUtils.setState(clusterService, builder); + + ClusterPutWeightedRoutingRequestBuilder request = new ClusterPutWeightedRoutingRequestBuilder( + client, + ClusterPutWeightedRoutingAction.INSTANCE + ); + WeightedRouting updatedWeightedRouting = new WeightedRouting("zone", Map.of("zone_A", 1.0, "zone_B", 0.0, "zone_C", 0.0)); + request.setWeightedRouting(updatedWeightedRouting); + final CountDownLatch countDownLatch = new CountDownLatch(1); + ActionListener listener = new ActionListener() { + @Override + public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { + assertTrue(clusterStateUpdateResponse.isAcknowledged()); + assertEquals(updatedWeightedRouting, clusterService.state().metadata().weightedRoutingMetadata().getWeightedRouting()); + countDownLatch.countDown(); + } + + @Override + public void onFailure(Exception e) { + fail("request should not fail"); + } + }; + weightedRoutingService.registerWeightedRoutingMetadata(request.request(), listener); + assertTrue(countDownLatch.await(30, TimeUnit.SECONDS)); + } + + public void testRegisterWeightedRoutingMetadataWithSameWeights() throws InterruptedException { + Map weights = Map.of("zone_A", 1.0, "zone_B", 1.0, "zone_C", 1.0); + ClusterState state = clusterService.state(); + state = setWeightedRoutingWeights(state, weights); + ClusterState.Builder builder = ClusterState.builder(state); + ClusterServiceUtils.setState(clusterService, builder); + + ClusterPutWeightedRoutingRequestBuilder request = new ClusterPutWeightedRoutingRequestBuilder( + client, + ClusterPutWeightedRoutingAction.INSTANCE + ); + WeightedRouting updatedWeightedRouting = new WeightedRouting("zone", weights); + request.setWeightedRouting(updatedWeightedRouting); + final CountDownLatch countDownLatch = new CountDownLatch(1); + ActionListener listener = new ActionListener() { + @Override + public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { + assertTrue(clusterStateUpdateResponse.isAcknowledged()); + assertEquals(updatedWeightedRouting, clusterService.state().metadata().weightedRoutingMetadata().getWeightedRouting()); + countDownLatch.countDown(); + } + + @Override + public void onFailure(Exception e) { + fail("request should not fail"); + } + }; + weightedRoutingService.registerWeightedRoutingMetadata(request.request(), listener); + assertTrue(countDownLatch.await(30, TimeUnit.SECONDS)); + } +} diff --git a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java index e801b6108ac2f..3a6655a77b74c 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java @@ -37,11 +37,11 @@ public void testCreateRequest_SupportedRequestBody() throws IOException { String req = "{\"us-east-1c\" : \"1\", \"us-east-1d\":\"1.0\", \"us-east-1a\":\"0.0\"}"; RestRequest restRequest = buildRestRequest(req); ClusterPutWeightedRoutingRequest clusterPutWeightedRoutingRequest = RestClusterPutWeightedRoutingAction.createRequest(restRequest); - assertEquals("zone", clusterPutWeightedRoutingRequest.weightedRouting().attributeName()); - assertNotNull(clusterPutWeightedRoutingRequest.weightedRouting().weights()); - assertEquals("1.0", clusterPutWeightedRoutingRequest.weightedRouting().weights().get("us-east-1c").toString()); - assertEquals("1.0", clusterPutWeightedRoutingRequest.weightedRouting().weights().get("us-east-1d").toString()); - assertEquals("0.0", clusterPutWeightedRoutingRequest.weightedRouting().weights().get("us-east-1a").toString()); + assertEquals("zone", clusterPutWeightedRoutingRequest.getWeightedRouting().attributeName()); + assertNotNull(clusterPutWeightedRoutingRequest.getWeightedRouting().weights()); + assertEquals("1.0", clusterPutWeightedRoutingRequest.getWeightedRouting().weights().get("us-east-1c").toString()); + assertEquals("1.0", clusterPutWeightedRoutingRequest.getWeightedRouting().weights().get("us-east-1d").toString()); + assertEquals("0.0", clusterPutWeightedRoutingRequest.getWeightedRouting().weights().get("us-east-1a").toString()); } public void testCreateRequest_UnsupportedRequestBody() throws IOException { From ba87256565dd3e8f37053087ac3c53e93a0beaa8 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 22 Sep 2022 10:25:44 +0530 Subject: [PATCH 48/55] Add string formatter Signed-off-by: Anshu Agarwal --- .../weighted/put/TransportPutWeightedRoutingAction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java index 29a1128be71da..bde7405c7b458 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java @@ -110,8 +110,9 @@ private void verifyAwarenessAttribute(String attributeName) { // Currently, only zone is supported if (!getAwarenessAttributes().contains(attributeName) || !attributeName.equalsIgnoreCase("zone")) { ActionRequestValidationException validationException = null; + validationException = addValidationError( - "invalid awareness attribute " + attributeName + " requested for " + "updating weighted routing " + "weights", + String.format("invalid awareness attribute %s requested for updating weighted routing", attributeName), validationException ); throw validationException; From 4057441bb28e5a6aedc375b732b5ce73dae5cc42 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Thu, 22 Sep 2022 10:40:56 +0530 Subject: [PATCH 49/55] Fix locale in string formatter Signed-off-by: Anshu Agarwal --- .../weighted/put/TransportPutWeightedRoutingAction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java index bde7405c7b458..4b56d6342f1ef 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.util.List; +import java.util.Locale; import static org.opensearch.action.ValidateActions.addValidationError; @@ -112,7 +113,7 @@ private void verifyAwarenessAttribute(String attributeName) { ActionRequestValidationException validationException = null; validationException = addValidationError( - String.format("invalid awareness attribute %s requested for updating weighted routing", attributeName), + String.format(Locale.ROOT, "invalid awareness attribute %s requested for updating weighted routing", attributeName), validationException ); throw validationException; From 83797f41129f73a0bc0e96693e40a4248fa03778 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Fri, 23 Sep 2022 15:56:18 +0530 Subject: [PATCH 50/55] Refactor code based on review comments Signed-off-by: Anshu Agarwal --- .../rest-api-spec/api/cluster.put_weighted_routing.json | 4 ++-- .../cluster/routing/WeightedRoutingService.java | 9 ++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json index cab2080130995..88498517ba336 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_weighted_routing.json @@ -1,8 +1,8 @@ { "cluster.put_weighted_routing": { "documentation": { - "url": "http://TBA", - "description": "TBA" + "url": "https://opensearch.org/docs/latest/opensearch/rest-api/weighted-routing/put", + "description": "Updates weighted shard routing weights" }, "stability": "stable", "url": { diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index 753066f0ea55b..3d93a9b7da0a9 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -56,14 +56,12 @@ public ClusterState execute(ClusterState currentState) { logger.info("put weighted routing weights in metadata [{}]", request.getWeightedRouting()); weightedRoutingMetadata = new WeightedRoutingMetadata(request.getWeightedRouting()); } else { - WeightedRoutingMetadata changedMetadata = new WeightedRoutingMetadata(new WeightedRouting(null, null)); if (!checkIfSameWeightsInMetadata(newWeightedRoutingMetadata, weightedRoutingMetadata)) { logger.info("updated weighted routing weights [{}] in metadata", request.getWeightedRouting()); - changedMetadata.setWeightedRouting(newWeightedRoutingMetadata.getWeightedRouting()); + weightedRoutingMetadata = new WeightedRoutingMetadata(newWeightedRoutingMetadata.getWeightedRouting()); } else { return currentState; } - weightedRoutingMetadata = new WeightedRoutingMetadata(changedMetadata.getWeightedRouting()); } mdBuilder.putCustom(WeightedRoutingMetadata.TYPE, weightedRoutingMetadata); logger.info("building cluster state with weighted routing weights [{}]", request.getWeightedRouting()); @@ -88,10 +86,7 @@ private boolean checkIfSameWeightsInMetadata( WeightedRoutingMetadata newWeightedRoutingMetadata, WeightedRoutingMetadata oldWeightedRoutingMetadata ) { - if (newWeightedRoutingMetadata.getWeightedRouting().equals(oldWeightedRoutingMetadata.getWeightedRouting())) { - return true; - } - return false; + return newWeightedRoutingMetadata.getWeightedRouting().equals(oldWeightedRoutingMetadata.getWeightedRouting()); } @Override From 006600c9fed794c5437505e8d6d5ecd8e0fd4877 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 26 Sep 2022 12:46:12 +0530 Subject: [PATCH 51/55] Refactor code Signed-off-by: Anshu Agarwal --- server/src/main/java/org/opensearch/action/ActionModule.java | 4 ++-- ...tingAction.java => TransportAddWeightedRoutingAction.java} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/{TransportPutWeightedRoutingAction.java => TransportAddWeightedRoutingAction.java} (97%) diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 20b9be73b01f4..34960d611b63f 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -80,7 +80,7 @@ import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsAction; import org.opensearch.action.admin.cluster.shards.TransportClusterSearchShardsAction; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; -import org.opensearch.action.admin.cluster.shards.routing.weighted.put.TransportPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.TransportAddWeightedRoutingAction; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.clone.TransportCloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotAction; @@ -566,7 +566,7 @@ public void reg actions.register(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class); actions.register(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class); - actions.register(ClusterPutWeightedRoutingAction.INSTANCE, TransportPutWeightedRoutingAction.class); + actions.register(ClusterPutWeightedRoutingAction.INSTANCE, TransportAddWeightedRoutingAction.class); actions.register(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class); actions.register(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class); actions.register(IndicesShardStoresAction.INSTANCE, TransportIndicesShardStoresAction.class); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java similarity index 97% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java index 4b56d6342f1ef..ab333efe0e0ab 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java @@ -36,7 +36,7 @@ * * @opensearch.internal */ -public class TransportPutWeightedRoutingAction extends TransportClusterManagerNodeAction< +public class TransportAddWeightedRoutingAction extends TransportClusterManagerNodeAction< ClusterPutWeightedRoutingRequest, ClusterPutWeightedRoutingResponse> { @@ -44,7 +44,7 @@ public class TransportPutWeightedRoutingAction extends TransportClusterManagerNo private volatile List awarenessAttributes; @Inject - public TransportPutWeightedRoutingAction( + public TransportAddWeightedRoutingAction( Settings settings, ClusterSettings clusterSettings, TransportService transportService, From 0240ff05f77a2680aace54c7a5c0fdb6707434ae Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 26 Sep 2022 12:58:38 +0530 Subject: [PATCH 52/55] Refactor code Signed-off-by: Anshu Agarwal --- .../src/main/java/org/opensearch/action/ActionModule.java | 4 ++-- ...ngAction.java => ClusterAddWeightedRoutingAction.java} | 6 +++--- .../put/ClusterPutWeightedRoutingRequestBuilder.java | 2 +- .../weighted/put/TransportAddWeightedRoutingAction.java | 2 +- .../org/opensearch/client/support/AbstractClient.java | 8 ++++---- .../cluster/routing/WeightedRoutingServiceTests.java | 6 +++--- ...java => RestClusterAddWeightedRoutingActionTests.java} | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) rename server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/{ClusterPutWeightedRoutingAction.java => ClusterAddWeightedRoutingAction.java} (74%) rename server/src/test/java/org/opensearch/rest/action/admin/cluster/{RestClusterPutWeightedRoutingActionTests.java => RestClusterAddWeightedRoutingActionTests.java} (98%) diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 34960d611b63f..23b2c9a78021e 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -79,7 +79,7 @@ import org.opensearch.action.admin.cluster.settings.TransportClusterUpdateSettingsAction; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsAction; import org.opensearch.action.admin.cluster.shards.TransportClusterSearchShardsAction; -import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterAddWeightedRoutingAction; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.TransportAddWeightedRoutingAction; import org.opensearch.action.admin.cluster.snapshots.clone.CloneSnapshotAction; import org.opensearch.action.admin.cluster.snapshots.clone.TransportCloneSnapshotAction; @@ -566,7 +566,7 @@ public void reg actions.register(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class); actions.register(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class); - actions.register(ClusterPutWeightedRoutingAction.INSTANCE, TransportAddWeightedRoutingAction.class); + actions.register(ClusterAddWeightedRoutingAction.INSTANCE, TransportAddWeightedRoutingAction.class); actions.register(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class); actions.register(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class); actions.register(IndicesShardStoresAction.INSTANCE, TransportIndicesShardStoresAction.class); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterAddWeightedRoutingAction.java similarity index 74% rename from server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java rename to server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterAddWeightedRoutingAction.java index 9931c3dc5782b..65c5ccca71461 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterAddWeightedRoutingAction.java @@ -15,12 +15,12 @@ * * @opensearch.internal */ -public final class ClusterPutWeightedRoutingAction extends ActionType { +public final class ClusterAddWeightedRoutingAction extends ActionType { - public static final ClusterPutWeightedRoutingAction INSTANCE = new ClusterPutWeightedRoutingAction(); + public static final ClusterAddWeightedRoutingAction INSTANCE = new ClusterAddWeightedRoutingAction(); public static final String NAME = "cluster:admin/routing/awareness/weights/put"; - private ClusterPutWeightedRoutingAction() { + private ClusterAddWeightedRoutingAction() { super(NAME, ClusterPutWeightedRoutingResponse::new); } } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java index 83d37e781b02b..b437f4c54d8d6 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestBuilder.java @@ -21,7 +21,7 @@ public class ClusterPutWeightedRoutingRequestBuilder extends ClusterManagerNodeO ClusterPutWeightedRoutingRequest, ClusterPutWeightedRoutingResponse, ClusterPutWeightedRoutingRequestBuilder> { - public ClusterPutWeightedRoutingRequestBuilder(OpenSearchClient client, ClusterPutWeightedRoutingAction action) { + public ClusterPutWeightedRoutingRequestBuilder(OpenSearchClient client, ClusterAddWeightedRoutingAction action) { super(client, action, new ClusterPutWeightedRoutingRequest()); } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java index ab333efe0e0ab..461f1c6cc232c 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java @@ -55,7 +55,7 @@ public TransportAddWeightedRoutingAction( IndexNameExpressionResolver indexNameExpressionResolver ) { super( - ClusterPutWeightedRoutingAction.NAME, + ClusterAddWeightedRoutingAction.NAME, transportService, clusterService, threadPool, diff --git a/server/src/main/java/org/opensearch/client/support/AbstractClient.java b/server/src/main/java/org/opensearch/client/support/AbstractClient.java index 0737b109b1c07..655135a229e93 100644 --- a/server/src/main/java/org/opensearch/client/support/AbstractClient.java +++ b/server/src/main/java/org/opensearch/client/support/AbstractClient.java @@ -110,7 +110,7 @@ import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequestBuilder; import org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse; -import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterAddWeightedRoutingAction; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequest; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequestBuilder; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingResponse; @@ -1270,7 +1270,7 @@ public ActionFuture deleteDanglingIndex(DeleteDanglingInde @Override public ActionFuture putWeightedRouting(ClusterPutWeightedRoutingRequest request) { - return execute(ClusterPutWeightedRoutingAction.INSTANCE, request); + return execute(ClusterAddWeightedRoutingAction.INSTANCE, request); } @Override @@ -1278,12 +1278,12 @@ public void putWeightedRouting( ClusterPutWeightedRoutingRequest request, ActionListener listener ) { - execute(ClusterPutWeightedRoutingAction.INSTANCE, request, listener); + execute(ClusterAddWeightedRoutingAction.INSTANCE, request, listener); } @Override public ClusterPutWeightedRoutingRequestBuilder prepareWeightedRouting() { - return new ClusterPutWeightedRoutingRequestBuilder(this, ClusterPutWeightedRoutingAction.INSTANCE); + return new ClusterPutWeightedRoutingRequestBuilder(this, ClusterAddWeightedRoutingAction.INSTANCE); } @Override diff --git a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java index 17e0cf5613f8c..e5cca998d3f06 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/WeightedRoutingServiceTests.java @@ -12,7 +12,7 @@ import org.junit.Before; import org.opensearch.Version; import org.opensearch.action.ActionListener; -import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingAction; +import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterAddWeightedRoutingAction; import org.opensearch.action.admin.cluster.shards.routing.weighted.put.ClusterPutWeightedRoutingRequestBuilder; import org.opensearch.client.node.NodeClient; import org.opensearch.cluster.ClusterName; @@ -179,7 +179,7 @@ public void testRegisterWeightedRoutingMetadataWithChangedWeights() throws Inter ClusterPutWeightedRoutingRequestBuilder request = new ClusterPutWeightedRoutingRequestBuilder( client, - ClusterPutWeightedRoutingAction.INSTANCE + ClusterAddWeightedRoutingAction.INSTANCE ); WeightedRouting updatedWeightedRouting = new WeightedRouting("zone", Map.of("zone_A", 1.0, "zone_B", 0.0, "zone_C", 0.0)); request.setWeightedRouting(updatedWeightedRouting); @@ -210,7 +210,7 @@ public void testRegisterWeightedRoutingMetadataWithSameWeights() throws Interrup ClusterPutWeightedRoutingRequestBuilder request = new ClusterPutWeightedRoutingRequestBuilder( client, - ClusterPutWeightedRoutingAction.INSTANCE + ClusterAddWeightedRoutingAction.INSTANCE ); WeightedRouting updatedWeightedRouting = new WeightedRouting("zone", weights); request.setWeightedRouting(updatedWeightedRouting); diff --git a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterAddWeightedRoutingActionTests.java similarity index 98% rename from server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java rename to server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterAddWeightedRoutingActionTests.java index 3a6655a77b74c..a4cd6224217b7 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/cluster/RestClusterAddWeightedRoutingActionTests.java @@ -24,7 +24,7 @@ import static java.util.Collections.singletonMap; -public class RestClusterPutWeightedRoutingActionTests extends RestActionTestCase { +public class RestClusterAddWeightedRoutingActionTests extends RestActionTestCase { private RestClusterPutWeightedRoutingAction action; @Before From 776306776a05570785c3a0b0e1ec0c8446e36efb Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 26 Sep 2022 17:28:58 +0530 Subject: [PATCH 53/55] Address review comments Signed-off-by: Anshu Agarwal --- .../put/ClusterPutWeightedRoutingRequest.java | 6 +++++- .../put/ClusterPutWeightedRoutingResponse.java | 3 +-- .../put/TransportAddWeightedRoutingAction.java | 3 ++- .../java/org/opensearch/client/Requests.java | 4 ++-- .../routing/WeightedRoutingService.java | 18 +++--------------- .../RestClusterPutWeightedRoutingAction.java | 7 +------ .../ClusterPutWeightedRoutingRequestTests.java | 12 ++++-------- 7 files changed, 18 insertions(+), 35 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index 2835e253a3b39..238675a95ae28 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -43,6 +43,8 @@ public class ClusterPutWeightedRoutingRequest extends ClusterManagerNodeRequest< private WeightedRouting weightedRouting; private String attributeName; + public ClusterPutWeightedRoutingRequest() {} + public WeightedRouting getWeightedRouting() { return weightedRouting; } @@ -61,7 +63,9 @@ public ClusterPutWeightedRoutingRequest(StreamInput in) throws IOException { weightedRouting = new WeightedRouting(in); } - public ClusterPutWeightedRoutingRequest() {} + public ClusterPutWeightedRoutingRequest(String attributeName) { + this.attributeName = attributeName; + } public void setWeightedRouting(Map source) { try { diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java index 502c933f34069..b0154aceef0c2 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingResponse.java @@ -10,7 +10,6 @@ import org.opensearch.action.support.master.AcknowledgedResponse; import org.opensearch.common.io.stream.StreamInput; -import org.opensearch.common.xcontent.ToXContentObject; import java.io.IOException; @@ -19,7 +18,7 @@ * * @opensearch.internal */ -public class ClusterPutWeightedRoutingResponse extends AcknowledgedResponse implements ToXContentObject { +public class ClusterPutWeightedRoutingResponse extends AcknowledgedResponse { public ClusterPutWeightedRoutingResponse(boolean acknowledged) { super(acknowledged); } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java index 461f1c6cc232c..922982941b4c8 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java @@ -14,6 +14,7 @@ import org.opensearch.action.support.clustermanager.TransportClusterManagerNodeAction; import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.block.ClusterBlockException; +import org.opensearch.cluster.block.ClusterBlockLevel; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.cluster.routing.WeightedRoutingService; import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider; @@ -122,7 +123,7 @@ private void verifyAwarenessAttribute(String attributeName) { @Override protected ClusterBlockException checkBlock(ClusterPutWeightedRoutingRequest request, ClusterState state) { - return null; + return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); } } diff --git a/server/src/main/java/org/opensearch/client/Requests.java b/server/src/main/java/org/opensearch/client/Requests.java index e1021ea3666cd..7154742de04fb 100644 --- a/server/src/main/java/org/opensearch/client/Requests.java +++ b/server/src/main/java/org/opensearch/client/Requests.java @@ -555,7 +555,7 @@ public static SnapshotsStatusRequest snapshotsStatusRequest(String repository) { * * @return update weight request */ - public static ClusterPutWeightedRoutingRequest putWeightedRoutingRequest() { - return new ClusterPutWeightedRoutingRequest(); + public static ClusterPutWeightedRoutingRequest putWeightedRoutingRequest(String attributeName) { + return new ClusterPutWeightedRoutingRequest(attributeName); } } diff --git a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java index 3d93a9b7da0a9..da454865ac866 100644 --- a/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java +++ b/server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java @@ -20,17 +20,14 @@ import org.opensearch.cluster.metadata.WeightedRoutingMetadata; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Priority; -import org.opensearch.common.component.AbstractLifecycleComponent; import org.opensearch.common.inject.Inject; import org.opensearch.threadpool.ThreadPool; -import java.io.IOException; - /** * * Service responsible for updating cluster state metadata with weighted routing weights */ -public class WeightedRoutingService extends AbstractLifecycleComponent { +public class WeightedRoutingService { private static final Logger logger = LogManager.getLogger(WeightedRoutingService.class); private final ClusterService clusterService; private final ThreadPool threadPool; @@ -70,13 +67,13 @@ public ClusterState execute(ClusterState currentState) { @Override public void onFailure(String source, Exception e) { - logger.warn(() -> new ParameterizedMessage("failed to update cluster state for weighted routing " + "weights [{}]", e)); + logger.warn(() -> new ParameterizedMessage("failed to update cluster state for weighted routing weights [{}]", e)); listener.onFailure(e); } @Override public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { - logger.info("cluster weighted routing weights metadata change is processed by all the nodes"); + logger.debug("cluster weighted routing weights metadata change is processed by all the nodes"); listener.onResponse(new ClusterStateUpdateResponse(true)); } }); @@ -88,13 +85,4 @@ private boolean checkIfSameWeightsInMetadata( ) { return newWeightedRoutingMetadata.getWeightedRouting().equals(oldWeightedRoutingMetadata.getWeightedRouting()); } - - @Override - protected void doStart() {} - - @Override - protected void doStop() {} - - @Override - protected void doClose() throws IOException {} } diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java index d95df02ea73cc..1cf44e665cf84 100644 --- a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterPutWeightedRoutingAction.java @@ -50,12 +50,7 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli } public static ClusterPutWeightedRoutingRequest createRequest(RestRequest request) throws IOException { - ClusterPutWeightedRoutingRequest putWeightedRoutingRequest = Requests.putWeightedRoutingRequest(); - String attributeName = null; - if (request.hasParam("attribute")) { - attributeName = request.param("attribute"); - } - putWeightedRoutingRequest.attributeName(attributeName); + ClusterPutWeightedRoutingRequest putWeightedRoutingRequest = Requests.putWeightedRoutingRequest(request.param("attribute")); request.applyContentParser(p -> putWeightedRoutingRequest.source(p.mapStrings())); return putWeightedRoutingRequest; } diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 1180c83a8c9cd..13a81678fd7e6 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -20,18 +20,16 @@ public class ClusterPutWeightedRoutingRequestTests extends OpenSearchTestCase { public void testSetWeightedRoutingWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"1\",\"us-east-1a\":\"1\"}"; - ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest("zone"); Map weights = Map.of("us-east-1a", 1.0, "us-east-1b", 1.0, "us-east-1c", 0.0); WeightedRouting weightedRouting = new WeightedRouting("zone", weights); - request.attributeName("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); assertEquals(request.getWeightedRouting(), weightedRouting); } public void testValidate_ValuesAreProper() { String reqString = "{\"us-east-1c\" : \"1\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; - ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); - request.attributeName("zone"); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNull(actionRequestValidationException); @@ -39,8 +37,7 @@ public void testValidate_ValuesAreProper() { public void testValidate_TwoZonesWithZeroWeight() { String reqString = "{\"us-east-1c\" : \"0\", \"us-east-1b\":\"0\",\"us-east-1a\":\"1\"}"; - ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); - request.attributeName("zone"); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); @@ -49,8 +46,7 @@ public void testValidate_TwoZonesWithZeroWeight() { public void testValidate_MissingWeights() { String reqString = "{}"; - ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest(); - request.attributeName("zone"); + ClusterPutWeightedRoutingRequest request = new ClusterPutWeightedRoutingRequest("zone"); request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); From 703d91818062c7e5dec20b5334b9159ad620b196 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Mon, 26 Sep 2022 18:02:39 +0530 Subject: [PATCH 54/55] Address review comments Signed-off-by: Anshu Agarwal --- .../weighted/put/TransportAddWeightedRoutingAction.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java index 922982941b4c8..8c29ab2199848 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/TransportAddWeightedRoutingAction.java @@ -109,8 +109,7 @@ protected void clusterManagerOperation( } private void verifyAwarenessAttribute(String attributeName) { - // Currently, only zone is supported - if (!getAwarenessAttributes().contains(attributeName) || !attributeName.equalsIgnoreCase("zone")) { + if (getAwarenessAttributes().contains(attributeName) == false) { ActionRequestValidationException validationException = null; validationException = addValidationError( From f3cf04d4e0a4ee1800d2ee503187781483e73d99 Mon Sep 17 00:00:00 2001 From: Anshu Agarwal Date: Tue, 27 Sep 2022 12:03:24 +0530 Subject: [PATCH 55/55] Add explicit count in request validation error message Signed-off-by: Anshu Agarwal --- .../weighted/put/ClusterPutWeightedRoutingRequest.java | 6 +++++- .../weighted/put/ClusterPutWeightedRoutingRequestTests.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java index 238675a95ae28..af229fb12b4f0 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequest.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import static org.opensearch.action.ValidateActions.addValidationError; @@ -141,7 +142,10 @@ public ActionRequestValidationException validate() { validationException = addValidationError(("Weight is not a number"), validationException); } if (countValueWithZeroWeights > 1) { - validationException = addValidationError(("More than one value has weight set as 0 "), validationException); + validationException = addValidationError( + (String.format(Locale.ROOT, "More than one [%d] value has weight set as 0", countValueWithZeroWeights)), + validationException + ); } return validationException; } diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java index 13a81678fd7e6..186e7e8638f17 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/shards/routing/weighted/put/ClusterPutWeightedRoutingRequestTests.java @@ -41,7 +41,7 @@ public void testValidate_TwoZonesWithZeroWeight() { request.setWeightedRouting(new BytesArray(reqString), XContentType.JSON); ActionRequestValidationException actionRequestValidationException = request.validate(); assertNotNull(actionRequestValidationException); - assertTrue(actionRequestValidationException.getMessage().contains("More than one value has weight set as 0")); + assertTrue(actionRequestValidationException.getMessage().contains("More than one [2] value has weight set as " + "0")); } public void testValidate_MissingWeights() {