Fix expiration time check in ExpirationMap
Add helper methods for checking past and future timestamp
Co-authored-by: Kristijan Mitrovic <kmitrovic@itekako.com>
Reviewed-on: https://git.bubblev.org/bubblev/cobbzilla-utils/pulls/2
if (lastCleaned+cleanInterval > now()) cleanExpired();
if (isTimestampInPast(nextCleaningTime)) cleanExpired();
final ExpirationMapEntry<V> val = map.putIfAbsent(key, new ExpirationMapEntry<>(value));
final ExpirationMapEntry<V> val = map.putIfAbsent(key, new ExpirationMapEntry<>(value));
return val == null ? null : val.value;
return val == null ? null : val.value;
}
}
@Override public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
@Override public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
if (lastCleaned+cleanInterval > now()) cleanExpired();
if (isTimestampInPast(nextCleaningTime)) cleanExpired();
return map.computeIfAbsent(key, k -> new ExpirationMapEntry<>(mappingFunction.apply(k))).value;
return map.computeIfAbsent(key, k -> new ExpirationMapEntry<>(mappingFunction.apply(k))).value;
}
}
@Override public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
@Override public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (lastCleaned+cleanInterval > now()) cleanExpired();
if (isTimestampInPast(nextCleaningTime)) cleanExpired();
final ExpirationMapEntry<V> found = map.computeIfPresent(key, (k, vExpirationMapEntry) -> new ExpirationMapEntry<>(remappingFunction.apply(k, vExpirationMapEntry.value)));
final ExpirationMapEntry<V> found = map.computeIfPresent(key, (k, vExpirationMapEntry) -> new ExpirationMapEntry<>(remappingFunction.apply(k, vExpirationMapEntry.value)));
return found == null ? null : found.value;
return found == null ? null : found.value;
}
}
@@ -135,12 +158,13 @@ public class ExpirationMap<K, V> implements Map<K, V> {
}
}
@Override public Set<Entry<K, V>> entrySet() {
@Override public Set<Entry<K, V>> entrySet() {
if (isTimestampInPast(nextCleaningTime)) cleanExpired();
return map.entrySet().stream().map(e -> new EMEntry<>(e.getKey(), e.getValue().value)).collect(Collectors.toSet());
return map.entrySet().stream().map(e -> new EMEntry<>(e.getKey(), e.getValue().value)).collect(Collectors.toSet());
}
}
private synchronized void cleanExpired () {
private synchronized void cleanExpired () {
if (lastCleaned+cleanInterval < now()) return;
lastCleaned = now();
if (isTimestampInFuture(nextCleaningTime)) return;
nextCleaningTime = now() + cleanInterval;
final Set<K> toRemove = new HashSet<>();
final Set<K> toRemove = new HashSet<>();
for (Map.Entry<K, ExpirationMapEntry<V>> entry : map.entrySet()) {
for (Map.Entry<K, ExpirationMapEntry<V>> entry : map.entrySet()) {
if (entry.getValue().expired()) toRemove.add(entry.getKey());
if (entry.getValue().expired()) toRemove.add(entry.getKey());