diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2021-05-18 20:56:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-18 20:56:51 +0200 |
commit | 5ecd841d5e200f5ffbf3a22706a2eaaf57d28880 (patch) | |
tree | e4e2d010b55d14fd7acf4db034dfa25a75555433 | |
parent | 4a210b8438d20a167ecfb74b0343f3acb8cb06ce (diff) | |
parent | e712ed18759d6f198f41af5c08211c6156de5d60 (diff) |
Merge pull request #17879 from vespa-engine/jonmv/pad-target-list-with-nulls-to-avoid-index-out-of-bounds
Replace with nulls instead of removing to avoid size reduction
-rw-r--r-- | documentapi/src/main/java/com/yahoo/documentapi/messagebus/protocol/ContentPolicy.java | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/documentapi/src/main/java/com/yahoo/documentapi/messagebus/protocol/ContentPolicy.java b/documentapi/src/main/java/com/yahoo/documentapi/messagebus/protocol/ContentPolicy.java index 792d3628ba0..4561099c74e 100644 --- a/documentapi/src/main/java/com/yahoo/documentapi/messagebus/protocol/ContentPolicy.java +++ b/documentapi/src/main/java/com/yahoo/documentapi/messagebus/protocol/ContentPolicy.java @@ -24,7 +24,6 @@ import com.yahoo.vdslib.state.State; import com.yahoo.vespa.config.content.DistributionConfig; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -76,13 +75,26 @@ public class ContentPolicy extends SlobrokPolicy { private static class Targets { private final List<Integer> list; - private final int total; + private final AtomicInteger size; + final int total; Targets() { - this(Collections.emptyList(), 1); + this(List.of(), 0); } Targets(List<Integer> list, int total) { - this.list = list; - this.total = total; + this.list = new CopyOnWriteArrayList<>(list); + this.size = new AtomicInteger(list.size()); + this.total = Math.max(1, total); + } + Integer get(int i) { + return list.get(i); + } + void remove(Integer v) { + size.decrementAndGet(); + list.add(null); // Avoid index out of bounds for racing getters. + list.remove(v); + } + int size() { + return size.get(); } } @@ -99,22 +111,22 @@ public class ContentPolicy extends SlobrokPolicy { for (int i=0; i<state.getNodeCount(NodeType.DISTRIBUTOR); ++i) { if (state.getNodeState(new Node(NodeType.DISTRIBUTOR, i)).getState().oneOf(upStates)) validRandomTargets.add(i); } - validTargets.set(new Targets(new CopyOnWriteArrayList<>(validRandomTargets), state.getNodeCount(NodeType.DISTRIBUTOR))); + validTargets.set(new Targets(validRandomTargets, state.getNodeCount(NodeType.DISTRIBUTOR))); } public abstract String getTargetSpec(Integer distributor, RoutingContext context); String getRandomTargetSpec(RoutingContext context) { Targets targets = validTargets.get(); // Try to use list of random targets, if at least X % of the nodes are up - while ((targets.total != 0) && - (100 * targets.list.size() / targets.total >= requiredUpPercentageToSendToKnownGoodNodes)) + while (100 * targets.size() >= requiredUpPercentageToSendToKnownGoodNodes * targets.total) { - Integer distributor = targets.list.get(randomizer.nextInt(targets.list.size())); + Integer distributor = targets.get(randomizer.nextInt(targets.size())); + if (distributor == null) continue; String targetSpec = getTargetSpec(distributor, context); if (targetSpec != null) { context.trace(3, "Sending to random node seen up in cluster state"); return targetSpec; } - targets.list.remove(distributor); + targets.remove(distributor); } context.trace(3, "Too few nodes seen up in state. Sending totally random."); return getTargetSpec(null, context); |