summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2021-05-18 20:56:51 +0200
committerGitHub <noreply@github.com>2021-05-18 20:56:51 +0200
commit5ecd841d5e200f5ffbf3a22706a2eaaf57d28880 (patch)
treee4e2d010b55d14fd7acf4db034dfa25a75555433
parent4a210b8438d20a167ecfb74b0343f3acb8cb06ce (diff)
parente712ed18759d6f198f41af5c08211c6156de5d60 (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.java32
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);