AMQ-8012 - Improve thread safety of SubQueueSelectorCacheBroker

When returning a copy of the set of selectors we need to synchronize
This commit is contained in:
Christopher L. Shannon (cshannon) 2020-07-24 14:15:57 -04:00
parent 1dcc7d4b2c
commit 62f5576fe5
1 changed files with 10 additions and 11 deletions

View File

@ -69,7 +69,7 @@ public class SubQueueSelectorCacheBroker extends BrokerFilter implements Runnabl
* The subscription's selector cache. We cache compiled expressions keyed * The subscription's selector cache. We cache compiled expressions keyed
* by the target destination. * by the target destination.
*/ */
private ConcurrentMap<String, Set<String>> subSelectorCache = new ConcurrentHashMap<String, Set<String>>(); private ConcurrentMap<String, Set<String>> subSelectorCache = new ConcurrentHashMap<>();
private final File persistFile; private final File persistFile;
private boolean singleSelectorPerDestination = false; private boolean singleSelectorPerDestination = false;
@ -275,8 +275,11 @@ public class SubQueueSelectorCacheBroker extends BrokerFilter implements Runnabl
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<String> getSelectorsForDestination(String destinationName) { public Set<String> getSelectorsForDestination(String destinationName) {
if (subSelectorCache.containsKey(destinationName)) { final Set<String> cachedSelectors = subSelectorCache.get(destinationName);
return new HashSet<String>(subSelectorCache.get(destinationName)); synchronized(cachedSelectors) {
if (cachedSelectors != null) {
return new HashSet<>(cachedSelectors);
}
} }
return Collections.EMPTY_SET; return Collections.EMPTY_SET;
@ -291,17 +294,13 @@ public class SubQueueSelectorCacheBroker extends BrokerFilter implements Runnabl
} }
public boolean deleteSelectorForDestination(String destinationName, String selector) { public boolean deleteSelectorForDestination(String destinationName, String selector) {
if (subSelectorCache.containsKey(destinationName)) { final Set<String> cachedSelectors = subSelectorCache.get(destinationName);
Set<String> cachedSelectors = subSelectorCache.get(destinationName); return cachedSelectors != null ? cachedSelectors.remove(selector) : false;
return cachedSelectors.remove(selector);
}
return false;
} }
public boolean deleteAllSelectorsForDestination(String destinationName) { public boolean deleteAllSelectorsForDestination(String destinationName) {
if (subSelectorCache.containsKey(destinationName)) { final Set<String> cachedSelectors = subSelectorCache.get(destinationName);
Set<String> cachedSelectors = subSelectorCache.get(destinationName); if (cachedSelectors != null) {
cachedSelectors.clear(); cachedSelectors.clear();
} }
return true; return true;