Skip to content

Commit 7f0585c

Browse files
committed
for read- /write-pool selection fall back to no zone filtering levels again if no pool with correct zone was found in first go
1 parent a64420f commit 7f0585c

2 files changed

Lines changed: 117 additions & 46 deletions

File tree

modules/dcache/src/main/java/diskCacheV111/poolManager/PoolMonitorV5.java

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -252,20 +252,45 @@ public SelectedPool selectWritePool(long preallocated)
252252
.toLowerCase()));
253253
}
254254

255+
if (_zone.isPresent()) {
256+
SelectedPool pool = filterWritePool(levels, true, preallocated);
257+
if (pool != null) {
258+
return pool;
259+
}
260+
}
261+
262+
SelectedPool pool = filterWritePool(levels, false, preallocated);
263+
if (pool != null) {
264+
return pool;
265+
}
266+
267+
throw new CacheException(CacheException.NO_POOL_ONLINE,
268+
noOnlinePoolsErrorMessage(DirectionType.WRITE.name()
269+
.toLowerCase()));
270+
}
271+
272+
@Nullable
273+
private SelectedPool filterWritePool(PoolPreferenceLevel[] levels,
274+
boolean filterByZone,
275+
long preallocated) throws CacheException{
255276
CostException fallback = null;
277+
256278
for (PoolPreferenceLevel level : levels) {
257279
List<PoolInfo> pools =
258-
level.getPoolList().stream()
259-
.map(_costModule::getPoolInfo)
260-
.filter(Objects::nonNull)
261-
.collect(toList());
262-
pools = filterByZone(pools);
280+
level.getPoolList().stream()
281+
.map(_costModule::getPoolInfo)
282+
.filter(Objects::nonNull)
283+
.collect(toList());
284+
285+
if (filterByZone){
286+
pools = filterByZone(pools);
287+
}
263288

264289
if (!pools.isEmpty()) {
265290
Partition partition = _partitionManager.getPartition(level.getTag());
266291
try {
267292
return partition.selectWritePool(_costModule, pools, _fileAttributes,
268-
preallocated);
293+
preallocated);
269294
} catch (CostException e) {
270295
if (!e.shouldFallBack()) {
271296
throw e;
@@ -275,16 +300,11 @@ public SelectedPool selectWritePool(long preallocated)
275300
}
276301
}
277302

278-
/* We were asked to fall back, but all available links were
279-
* exhausted. Let the caller deal with it.
280-
*/
281303
if (fallback != null) {
282304
throw fallback;
283305
}
284306

285-
throw new CacheException(CacheException.NO_POOL_ONLINE,
286-
noOnlinePoolsErrorMessage(DirectionType.WRITE.name()
287-
.toLowerCase()));
307+
return null;
288308
}
289309

290310
@Override
@@ -318,12 +338,37 @@ public SelectedPool selectReadPool()
318338
.toLowerCase()));
319339
}
320340

341+
342+
if (_zone.isPresent()) {
343+
SelectedPool pool = filterReadPool(level, onlinePoolsWithFile, true);
344+
if (pool != null) {
345+
return pool;
346+
}
347+
}
348+
349+
SelectedPool pool = filterReadPool(level, onlinePoolsWithFile, false);
350+
if (pool != null) {
351+
return pool;
352+
}
353+
354+
/* None of the pools we were allowed to read from were
355+
* online or had the file.
356+
*/
357+
throw new PermissionDeniedCacheException(
358+
"File is online, but not in read-allowed pool");
359+
}
360+
361+
@Nullable
362+
private SelectedPool filterReadPool(PoolPreferenceLevel[] level,
363+
Map<String, PoolInfo> onlinePoolsWithFile,
364+
boolean filterByZone) throws CacheException {
365+
321366
CostException costException = null;
322367

323368
for (int prio = 0; prio < level.length; prio++) {
324369
List<String> poolsInCurrentLevel = level[prio].getPoolList();
325370
LOGGER.debug("[read] Allowed pools at level {}: {}",
326-
prio, poolsInCurrentLevel);
371+
prio, poolsInCurrentLevel);
327372

328373
if (poolsInCurrentLevel.isEmpty()) {
329374
// No pools in this level....skip it.
@@ -341,9 +386,11 @@ public SelectedPool selectReadPool()
341386
}
342387
}
343388
LOGGER.debug("[read] Available pools at level {}: {}",
344-
prio, pools);
389+
prio, pools);
345390

346-
pools = filterByZone(pools);
391+
if (filterByZone) {
392+
pools = filterByZone(pools);
393+
}
347394

348395
/* If allowed, fallback to next link if current link doesn't point
349396
* to any pool holding the file.
@@ -360,14 +407,14 @@ public SelectedPool selectReadPool()
360407
* to select a pool.
361408
*/
362409
_partition =
363-
_partitionManager.getPartition(level[prio].getTag());
410+
_partitionManager.getPartition(level[prio].getTag());
364411

365412
/* The actual pool selection is delegated to the
366413
* Partition.
367414
*/
368415
try {
369416
return _partition.selectReadPool(_costModule, pools,
370-
_fileAttributes);
417+
_fileAttributes);
371418
} catch (CostException e) {
372419
costException = e;
373420
if (!e.shouldFallBack()) {
@@ -376,35 +423,21 @@ public SelectedPool selectReadPool()
376423
}
377424
}
378425

379-
/* If we have a CostException where a pool was selected and
380-
* shouldTryAlternatives not set then we return that pool anyway.
381-
* REVISIT: consider updating partitions so they don't throw
382-
* an exception in this case.
383-
*/
384426
if (costException != null) {
385427
if (costException.getPool() != null
386-
&& !costException.shouldTryAlternatives()) {
428+
&& !costException.shouldTryAlternatives()) {
387429
return costException.getPool();
388430
}
389-
390431
throw costException;
391432
}
392433

393-
/* None of the pools we were allowed to read from were
394-
* online or had the file.
395-
*/
396-
throw new PermissionDeniedCacheException(
397-
"File is online, but not in read-allowed pool");
434+
return null;
398435
}
399436

400437
private List<PoolInfo> filterByZone(List<PoolInfo> pools) {
401-
if (_zone.isPresent()) {
402-
List<PoolInfo> poolsZ =
403-
pools.stream()
438+
pools = pools.stream()
404439
.filter(p -> Objects.equals(p.getTags().get("zone"), _zone.get()))
405440
.toList();
406-
pools = (poolsZ.isEmpty()) ? pools : poolsZ;
407-
}
408441
return pools;
409442
}
410443

modules/dcache/src/test/java/org/dcache/tests/poolmanager/PoolMonitorTest.java

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,47 @@ public void testReadPoolZonePreference() throws Exception {
179179
assertEquals("pool1", selector.selectReadPool().name());
180180
}
181181

182+
@Test
183+
public void testReadPoolZoneFallback() throws Exception {
184+
prepareCostModule(false, true);
185+
186+
// Only pool2 in zone 2 has the file
187+
FileAttributes attributes = FileAttributes.of()
188+
.pnfsId(_pnfsId)
189+
.locations(Collections.singleton("pool2"))
190+
.build();
191+
StorageInfos.injectInto(_storageInfo, attributes);
192+
193+
PoolSelector selector = _poolMonitor.getPoolSelector(attributes, _protocolInfo,
194+
null, Optional.of("1"), Collections.EMPTY_SET);
195+
196+
assertEquals("pool2", selector.selectReadPool().name());
197+
}
198+
199+
@Test
200+
public void testWritePoolZoneFallback() throws Exception {
201+
// pool2 is offline zone 2 requested so falls back to pool1
202+
prepareCostModule(false, true, true);
203+
204+
FileAttributes attributes = FileAttributes.of().pnfsId(_pnfsId).build();
205+
StorageInfos.injectInto(_storageInfo, attributes);
206+
207+
PoolSelector selector = _poolMonitor.getPoolSelector(attributes, _protocolInfo,
208+
null, Optional.of("2"), Collections.EMPTY_SET);
209+
210+
assertEquals("pool1", selector.selectWritePool(0).name());
211+
}
212+
182213
private void prepareCostModule(boolean linkPerPool) throws Exception {
183214
prepareCostModule(linkPerPool, false);
184215
}
185216

186217
private void prepareCostModule(boolean linkPerPool, boolean withZones) throws Exception {
218+
prepareCostModule(linkPerPool, withZones, false);
219+
}
220+
221+
private void prepareCostModule(boolean linkPerPool, boolean withZones, boolean pool2Offline)
222+
throws Exception {
187223
if (linkPerPool) {
188224
PoolMonitorHelper.prepareLinkPerPool(_selectionUnit, _access, _pools);
189225
} else {
@@ -198,31 +234,33 @@ private void prepareCostModule(boolean linkPerPool, boolean withZones) throws Ex
198234
PoolV2Mode poolMode = new PoolV2Mode(PoolV2Mode.ENABLED);
199235

200236
PoolCostInfo poolCost1 = new PoolCostInfo("pool1", IoQueueManager.DEFAULT_QUEUE);
201-
PoolCostInfo poolCost2 = new PoolCostInfo("pool2", IoQueueManager.DEFAULT_QUEUE);
202-
203237
poolCost1.setSpaceUsage(100, 20, 30, 50);
204-
poolCost2.setSpaceUsage(100, 20, 30, 50);
205238

206239
PoolManagerPoolUpMessage pool1UpMessage = new PoolManagerPoolUpMessage("pool1",
207240
serialId, poolMode, poolCost1);
208-
PoolManagerPoolUpMessage pool2UpMessage = new PoolManagerPoolUpMessage("pool2",
209-
serialId, poolMode, poolCost2);
210-
211241
pool1UpMessage.setHostName(_localhost);
212-
pool2UpMessage.setHostName(_localhost);
213242

214243
if (withZones) {
215244
pool1UpMessage.setTagMap(Map.of("zone", "1"));
216-
pool2UpMessage.setTagMap(Map.of("zone", "2"));
217245
}
218246

219247
CellMessage envelope1 = new CellMessage(new CellAddressCore("PoolManager"), null);
220248
envelope1.addSourceAddress(new CellAddressCore("pool1"));
221-
CellMessage envelope2 = new CellMessage(new CellAddressCore("PoolManager"), null);
222-
envelope2.addSourceAddress(new CellAddressCore("pool2"));
223-
224249
_costModule.messageArrived(envelope1, pool1UpMessage);
225-
_costModule.messageArrived(envelope2, pool2UpMessage);
250+
251+
if (!pool2Offline) {
252+
PoolCostInfo poolCost2 = new PoolCostInfo("pool2", IoQueueManager.DEFAULT_QUEUE);
253+
poolCost2.setSpaceUsage(100, 20, 30, 50);
254+
PoolManagerPoolUpMessage pool2UpMessage = new PoolManagerPoolUpMessage("pool2",
255+
serialId, poolMode, poolCost2);
256+
pool2UpMessage.setHostName(_localhost);
257+
if (withZones) {
258+
pool2UpMessage.setTagMap(Map.of("zone", "2"));
259+
}
260+
CellMessage envelope2 = new CellMessage(new CellAddressCore("PoolManager"), null);
261+
envelope2.addSourceAddress(new CellAddressCore("pool2"));
262+
_costModule.messageArrived(envelope2, pool2UpMessage);
263+
}
226264
}
227265

228266
private PoolSelector prepareHostExclusion() throws Exception {

0 commit comments

Comments
 (0)