diff --git a/pdb-utils/src/main/java/org/lucares/utils/cache/HotEntryCache.java b/pdb-utils/src/main/java/org/lucares/utils/cache/HotEntryCache.java index 3ab22fa..28c1274 100644 --- a/pdb-utils/src/main/java/org/lucares/utils/cache/HotEntryCache.java +++ b/pdb-utils/src/main/java/org/lucares/utils/cache/HotEntryCache.java @@ -98,8 +98,8 @@ public class HotEntryCache { return value; } - public void touch(final Clock clock) { - lastAccessed = Instant.now(clock); + public void touch(final Instant instant) { + lastAccessed = instant; } } @@ -114,6 +114,8 @@ public class HotEntryCache { private Clock clock; + private Instant nextEviction = Instant.MAX; + HotEntryCache(final Duration timeToLive, final Clock clock, final long delayForEvictionThread, final TimeUnit timeUnit) { this.timeToLive = timeToLive; @@ -131,12 +133,13 @@ public class HotEntryCache { public V get(final K key) { final Entry entry = cache.computeIfPresent(key, (k, e) -> { - if (isExpired(e)) { + final Instant now = Instant.now(clock); + if (isExpired(e, now)) { handleEvent(EventType.EVICTED, k, e.getValue()); return null; } - e.touch(clock); + touch(e); return e; }); return entry != null ? entry.getValue() : null; @@ -147,7 +150,9 @@ public class HotEntryCache { final AtomicReference> oldValue = new AtomicReference<>(); cache.compute(key, (k, v) -> { oldValue.set(v); - return new Entry<>(value, clock); + final Entry newEntry = new Entry<>(value, clock); + touch(newEntry); + return newEntry; }); return oldValue.get() != null ? oldValue.get().getValue() : null; } @@ -172,9 +177,8 @@ public class HotEntryCache { return new Entry<>(value, clock); }); - if (entry != null) { - entry.touch(clock); - } + touch(entry); + return entry != null ? entry.getValue() : null; } @@ -197,26 +201,37 @@ public class HotEntryCache { public void forEach(final Consumer consumer) { cache.forEachValue(Long.MAX_VALUE, entry -> { - entry.touch(clock); + touch(entry); consumer.accept(entry.getValue()); }); } private void evict() { - for (final K key : cache.keySet()) { + final Instant now = Instant.now(clock); + if (nextEviction.isBefore(now)) { - cache.computeIfPresent(key, (k, e) -> { - if (isExpired(e)) { - handleEvent(EventType.EVICTED, k, e.getValue()); - return null; - } - return e; - }); + for (final K key : cache.keySet()) { + cache.computeIfPresent(key, (k, e) -> { + if (isExpired(e, now)) { + handleEvent(EventType.EVICTED, k, e.getValue()); + return null; + } + return e; + }); + } } } - private boolean isExpired(final Entry entry) { - return entry.getLastAccessed().plus(timeToLive).isBefore(Instant.now(clock)); + private void touch(final Entry entry) { + if (entry != null) { + final Instant now = Instant.now(clock); + entry.touch(now); + nextEviction = now.plus(timeToLive); + } + } + + private boolean isExpired(final Entry entry, final Instant now) { + return entry.getLastAccessed().plus(timeToLive).isBefore(now); } private void handleEvent(final EventType eventType, final K key, final V value) { @@ -227,5 +242,4 @@ public class HotEntryCache { } } } - }