diff --git a/modules/dcache/src/main/java/diskCacheV111/poolManager/LinkMap.java b/modules/dcache/src/main/java/diskCacheV111/poolManager/LinkMap.java index 668b5ca6b37..3c6ecb47c2e 100644 --- a/modules/dcache/src/main/java/diskCacheV111/poolManager/LinkMap.java +++ b/modules/dcache/src/main/java/diskCacheV111/poolManager/LinkMap.java @@ -1,19 +1,18 @@ package diskCacheV111.poolManager; -import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; class LinkMap { - private static class LinkMapEntry { + static class LinkMapEntry { - private final Link _link; - private int _counter; + final Link _link; + int _counter; - private LinkMapEntry(Link link) { + LinkMapEntry(Link link) { _link = link; _counter = link._uGroupList.size() - 1; } @@ -37,4 +36,7 @@ void addLink(Link link) { } } + Collection entries() { + return _linkHash.values(); + } } diff --git a/modules/dcache/src/main/java/diskCacheV111/poolManager/PoolSelectionUnitV2.java b/modules/dcache/src/main/java/diskCacheV111/poolManager/PoolSelectionUnitV2.java index 598a927d39c..0d89afcbaa6 100644 --- a/modules/dcache/src/main/java/diskCacheV111/poolManager/PoolSelectionUnitV2.java +++ b/modules/dcache/src/main/java/diskCacheV111/poolManager/PoolSelectionUnitV2.java @@ -703,7 +703,8 @@ public PoolPreferenceLevel[] match(DirectionType type, String netUnitName, addNetUnit(units, netUnitName); LinkGroup linkGroup = resolveLinkGroup(linkGroupName); - Set sortedSet = findMatchingLinks(units, linkGroup, type); + Set sortedSet = findMatchingLinks(units, linkGroup, type, + protocolUnitName == null, netUnitName == null); List> linkLists = matchPreferences(type, sortedSet); result = buildPreferenceLevels(type, linkLists, fileAttributes, exclude); @@ -848,18 +849,28 @@ private LinkGroup resolveLinkGroup(String linkGroupName) { } private Set findMatchingLinks(List units, LinkGroup linkGroup, - DirectionType type) { + DirectionType type, boolean ignoreProtocol, boolean ignoreNet) { Set sortedSet = new TreeSet<>(new LinkComparator(type)); LinkMap matchingLinks = new LinkMap(); - int fitCount = units.size(); for (Unit unit : units) { matchingLinks = match(matchingLinks, unit, linkGroup, type); } - Iterator linkIterator = matchingLinks.iterator(); - while (linkIterator.hasNext()) { - Link link = linkIterator.next(); - if (link._uGroupList.size() <= fitCount) { + for (LinkMap.LinkMapEntry entry : matchingLinks.entries()) { + Link link = entry._link; + int ignored = 0; + if (ignoreProtocol || ignoreNet) { + for (UGroup uGroup : link._uGroupList.values()) { + UnitType groupType = uGroup._unitList.values().stream() + .findFirst().map(Unit::getType).orElse(null); + if ((ignoreProtocol && groupType == PROTOCOL) + || (ignoreNet && groupType == NET)) { + entry._counter--; + ignored++; + } + } + } + if (entry._counter <= 0 && link._uGroupList.size() <= units.size() + ignored) { sortedSet.add(link); } } diff --git a/modules/dcache/src/test/java/diskCacheV111/poolManager/PoolSelectionUnitV2Test.java b/modules/dcache/src/test/java/diskCacheV111/poolManager/PoolSelectionUnitV2Test.java index 48a6c009d91..1bae3729684 100644 --- a/modules/dcache/src/test/java/diskCacheV111/poolManager/PoolSelectionUnitV2Test.java +++ b/modules/dcache/src/test/java/diskCacheV111/poolManager/PoolSelectionUnitV2Test.java @@ -443,4 +443,17 @@ private void whenMatchIsCalledWith(String params) { assertNull("Unexpected exception", e); } } + + /** + * Regression test for hot file replication issue introduced in 96c4db4f8b. + * When protocol and network are null, they should match any protocol or network requirement + * of a link. + */ + @Test + public void testThatReadWithNullProtocolAndNetMatchesTapePools() { + diskCacheV111.vehicles.StorageInfo storageInfo = diskCacheV111.vehicles.GenericStorageInfo.valueOf("tape.dcache-devel-test@enstore", "*"); + org.dcache.vehicles.FileAttributes fileAttributes = org.dcache.vehicles.FileAttributes.ofStorageInfo(storageInfo); + levels = psu.match(PoolSelectionUnit.DirectionType.READ, null, null, fileAttributes, null, p -> false); + assertThatPoolsAre(TAPE_POOLS); + } } \ No newline at end of file