}
// Keep looping around until the group no longer exceeds its limit.
boolean purgeRequired;
do {
InternalCacheEntry entry = null;
// Synchronize on the group to get an entry. The entry cannot be
// removed at this point because in order to do that the code needs
// to synchronize on the entry which must always be done before
// synchronizing on the group's entry mutex.
synchronized(entries) {
// While inside this block the group entries cannot be modified
// but nested groups may have removed entries and are blocking
// waiting to update this group. This means that we may
// purge entries that we do not strictly need to purge but that
// is unavoidable. We may also not be able to find any entries
// to purge in the nested groups, they may all be empty for
// example. In that case we just loop around and try again.
if (totalCount > maxCount) {
purgeRequired = true;
if (logger.isDebugEnabled()) {
logger.debug("Count " + totalCount + " max count " +
maxCount);
}
} else {
purgeRequired = false;
if (logger.isDebugEnabled()) {
logger.debug("Purge no longer required");
}
}
}
// If a purge was required and an entry to remove was found then
// try and remove it.
if (purgeRequired) {
// Select the entry that is from the group with the highest
// percentage usage and is the least recently used.
entry = selectLeastRecentlyUsedEntry();
if (entry != null) {
if (logger.isDebugEnabled()) {
logger.debug("Attempting to purge " + entry);
}
boolean removed = entry.removeFromCache(null);
if (logger.isDebugEnabled()) {
if (removed) {
logger.debug("Removed " + entry);
} else {
logger.debug("Failed to remove " + entry);