Skip to content

Commit fb20f7c

Browse files
committed
poolmanager: update wrandom partition to respect gap
Motivation: The wrandom partition ignores pool gap, thus can select a full pull. Issue: #7863 Modification: Update WRandomPartition to skip pools that will run into gap if accept the file. Added unit test to ensure the behavior. Result: full pulls are skipped by wrandom partition. Acked-by: Dmitry Litvintsev Target: master, 11.0, 10.2, 10.1, 10.0, 9.2 Require-book: no Require-notes: yes (cherry picked from commit a778f97) Signed-off-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
1 parent a569bc6 commit fb20f7c

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

modules/dcache/src/main/java/org/dcache/poolmanager/WRandomPartition.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import java.security.SecureRandom;
77
import java.util.Arrays;
8-
import java.util.Collection;
98
import java.util.Collections;
109
import java.util.Comparator;
1110
import java.util.List;
@@ -84,26 +83,46 @@ public SelectedPool selectStagePool(CostModule cm, List<PoolInfo> pools, Optiona
8483

8584
@Override
8685
public SelectedPool selectWritePool(CostModule cm, List<PoolInfo> pools, FileAttributes attributes, long preallocated) throws CacheException {
87-
WeightedPool weightedPools[] = toWeightedWritePoolsArray(pools);
86+
WeightedPool weightedPools[] = toWeightedWritePoolsArray(pools, preallocated);
87+
if (weightedPools.length == 0) {
88+
throw new CostException("All pools are full", null, false, false);
89+
}
8890
int index = selectWrandomIndex(weightedPools);
8991
return new SelectedPool(weightedPools[index].getCostInfo());
9092
}
9193

92-
private WeightedPool[] toWeightedWritePoolsArray(Collection<PoolInfo> costInfos) {
94+
private WeightedPool[] toWeightedWritePoolsArray(List<PoolInfo> costInfos, long fileSize)
95+
throws CacheException {
9396

9497
long totalFree = 0;
98+
int validCount = 0;
9599
for (PoolInfo costInfo : costInfos) {
100+
long gap = costInfo.getCostInfo().getSpaceInfo().getGap();
101+
96102
long spaceToUse = costInfo.getCostInfo().getSpaceInfo().getFreeSpace()
97103
+ costInfo.getCostInfo().getSpaceInfo().getRemovableSpace();
104+
if (fileSize > spaceToUse - gap) {
105+
continue; // skip pools that do not have enough space
106+
}
98107
totalFree += spaceToUse;
108+
validCount++;
99109
}
100110

101-
WeightedPool[] weightedPools = new WeightedPool[costInfos.size()];
102-
int i = 0;
103-
for (PoolInfo costInfo : costInfos) {
111+
// the validCount should macht the number of pools that have enough space, thus elegible for selection
112+
WeightedPool[] weightedPools = new WeightedPool[validCount];
113+
for (int i = 0; i < weightedPools.length; /* incremented in the loop */) {
114+
115+
var costInfo = costInfos.get(i);
116+
117+
long gap = costInfo.getCostInfo().getSpaceInfo().getGap();
118+
104119
long spaceToUse = costInfo.getCostInfo().getSpaceInfo().getFreeSpace()
105120
+ costInfo.getCostInfo().getSpaceInfo().getRemovableSpace();
106121

122+
if (fileSize > spaceToUse - gap) {
123+
continue; // skip pools that do not have enough space
124+
}
125+
107126
weightedPools[i] = new WeightedPool(costInfo, (double) spaceToUse / totalFree);
108127
i++;
109128
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.dcache.poolmanager;
2+
3+
import com.google.common.collect.ImmutableMap;
4+
import diskCacheV111.pools.PoolCostInfo;
5+
import diskCacheV111.util.CacheException;
6+
import dmg.cells.nucleus.CellAddressCore;
7+
import org.hamcrest.MatcherAssert;
8+
import org.junit.Assert;
9+
import org.junit.Test;
10+
import org.mockito.AdditionalMatchers;
11+
12+
import java.util.Map;
13+
import java.util.stream.IntStream;
14+
15+
import static org.junit.Assert.*;
16+
17+
public class WRandomPartitionTest {
18+
19+
20+
@Test(expected = CostException.class)
21+
public void shouldFailIfAllocatesIntoGap() throws CacheException {
22+
23+
var wrandom = new WRandomPartition(Map.of());
24+
var pools = IntStream.range(0, 10).mapToObj(i -> {
25+
var cost = new PoolCostInfo("pool" + i, "default-queue");
26+
cost.setSpaceUsage(10_000L, 3000L, 0L, 0L);
27+
cost.getSpaceInfo().setParameter(0.0d, 2500L);
28+
29+
return new PoolInfo(new CellAddressCore("pool" + i), cost, ImmutableMap.of());
30+
}
31+
).toList();
32+
33+
long fileSize = 1000L;
34+
var selectedPool = wrandom.selectWritePool(null, pools, null, fileSize);
35+
}
36+
37+
@Test
38+
public void shouldSelectValidPool() throws CacheException {
39+
40+
var wrandom = new WRandomPartition(Map.of());
41+
var pools = IntStream.range(0, 10).mapToObj(i -> {
42+
var cost = new PoolCostInfo("pool" + i, "default-queue");
43+
cost.setSpaceUsage(10_000L, 5000L, 0L, 0L);
44+
cost.getSpaceInfo().setParameter(0.0d, 2500L);
45+
46+
return new PoolInfo(new CellAddressCore("pool" + i), cost, ImmutableMap.of());
47+
}
48+
).toList();
49+
50+
long fileSize = 1000L;
51+
var selectedPool = wrandom.selectWritePool(null, pools, null, fileSize);
52+
53+
var spaceInfo = selectedPool.info().getCostInfo().getSpaceInfo();
54+
assertTrue("selected pool has no sufficient space", spaceInfo.getFreeSpace() + spaceInfo.getRemovableSpace() - fileSize > spaceInfo.getGap());
55+
}
56+
57+
}

0 commit comments

Comments
 (0)