public Cache<K, V> allowOutdated(long ttlSec) { outdated = new Cache<K, V>(name + ".outdated", ttlSec); return this; }
private void putToOutdated(Holder<K, V> h) { if (outdated != null) outdated.put(h.k, h.v); }
public boolean putIfAbsent(final K key, final V value) { return putIfAbsent(key, value, ttl); }
public boolean putIfAbsent(final K key, final V value, long ttl) { long latency = System.nanoTime(); Holder<K, V> h = new Holder<K, V>(key, value, findTimingsHolder(ttl)); if (map.putIfAbsent(key, h) == null) { updateTimingCache(h); try { onAddItem(key, value); } finally { latency = System.nanoTime() - latency; statistics.putCount.incrementAndGet(); statistics.putLatency.addAndGet(latency); updateSizeMetric(); } return true; } return false; }
@Test public void test_statistics_3() throws InterruptedException { Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { @Override public String compute(String s) { return s.toUpperCase(); }).onAdd(new CacheListener<String, String>() { @Override public void onEvent(String key, String value) { cache.get("foo"); CacheStatistics statistics = cache.getStatistics(); long put = statistics.putLatency.get(); long compute = statistics.computeLatency.get(); cache.get("foo"); Assert.assertEquals(1, statistics.getSize()); Assert.assertEquals(2, statistics.getGetCount());
f = ft; try { computeMeasured(key, c, ft); failed = false; } catch (Exception e) { f.setRemoved(); } else { updateTimingCache(f); onAddItem(f.getKey(), f.get()); if (outdated != null) outdated.remove(key); statistics.putCount.incrementAndGet(); statistics.putLatency.addAndGet(latency); updateSizeMetric(); Holder<K, V> h = outdated.getHolder(key); if (h != null) return h; updateTimingCache(f);
@Test public void destroy_test() throws InterruptedException { System.gc(); Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { @Override public String compute(String s) { return s.toUpperCase(); } }); cache.get("foo"); Assert.assertEquals(1, cache.size()); Thread.sleep(1020); Assert.assertEquals(0, cache.size()); Assert.assertEquals(1, CacheCleaner.size()); cache.get("foo"); Assert.assertEquals(1, cache.size()); cache.destroy(); Assert.assertEquals(0, cache.size()); Assert.assertEquals(true, cache.isDestroyed()); Assert.assertEquals(1, CacheCleaner.size()); Thread.sleep(1020); Assert.assertEquals(0, CacheCleaner.size()); }
@Test public void test_statistics_4() throws InterruptedException { Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { @Override public String compute(String s) { return s.toUpperCase(); }).onRemove(new CacheListener<String, String>() { @Override public void onEvent(String key, String value) { cache.get("foo"); CacheStatistics statistics = cache.getStatistics(); long compute = statistics.computeLatency.get(); long remove = statistics.removeLatency.get(); cache.put("foo", "bar"); Assert.assertEquals(1, statistics.getSize()); Assert.assertEquals(1, statistics.getGetCount());
@Test public void outdated_test() throws InterruptedException { final Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { AtomicInteger counter = new AtomicInteger(); @Override public String compute(String s) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return s + "_" + counter.getAndIncrement(); } }).allowOutdated(); Assert.assertEquals("foo_0", cache.get("foo")); Assert.assertEquals(1, cache.size()); Thread.sleep(1200); final CountDownLatch latch = new CountDownLatch(1); new Thread(new Runnable() { @Override public void run() { Assert.assertEquals("foo_1", cache.get("foo")); latch.countDown(); } }).start(); Thread.sleep(100); Assert.assertEquals("foo_0", cache.get("foo")); latch.await(); }
@Test public void testCustomTTL() throws InterruptedException { Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { @Override public String compute(String s) { return s.toUpperCase(); } }); cache.get("foo"); String bar = "BAR"; cache.put("bar", bar, 500); Assert.assertTrue(bar == cache.get("bar")); Thread.sleep(550); Assert.assertTrue(bar != cache.get("bar")); }
@Test public void test_cache_timings_cleanup() { Cache<String, String> cache = new Cache<String, String>(1); Assert.assertEquals(1, cache.timings.size()); Cache.TimingsHolder<String, String> timingsHolder = cache.findTimingsHolder(2); Assert.assertEquals(2, cache.timings.size()); System.gc(); Assert.assertEquals(2, cache.timings.size()); timingsHolder = null; System.gc(); Assert.assertEquals(2, cache.timings.size()); cache.refresh(); Assert.assertEquals(1, cache.timings.size()); int hash = cache.findTimingsHolder(2).hashCode(); Assert.assertEquals(2, cache.timings.size()); Assert.assertEquals(hash, cache.findTimingsHolder(2).hashCode()); System.gc(); Assert.assertEquals(2, cache.timings.size()); cache.findTimingsHolder(2); Assert.assertNotEquals(hash, cache.findTimingsHolder(2).hashCode()); } }
@Test public void exceptions() { Cache<Integer, Integer> cache = new Cache<Integer, Integer>(0, new Computable<Integer, Integer>() { @Override public Integer compute(Integer s) { throw new RuntimeException(); } }); try { cache.get(1); assert false; } catch (Exception e) { } try { cache.get(1); assert false; } catch (Exception e) { } }
@Test public void testTTL() throws InterruptedException { Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { @Override public String compute(String s) { return s.toUpperCase(); } }); cache.get("foo", true); Thread.sleep(500); cache.get("bar"); Thread.sleep(490); Assert.assertEquals(2, cache.size()); Thread.sleep(500); Assert.assertEquals(1, cache.size()); Thread.sleep(20); Assert.assertEquals(0, cache.size()); }
@Test public void test_statistics_2() throws InterruptedException { Cache<String, String> cache = new Cache<String, String>(1, new Computable<String, String>() { @Override public String compute(String s) throws InterruptedException { cache.get("foo"); CacheStatistics statistics = cache.getStatistics(); long put = statistics.putLatency.get(); long compute = statistics.computeLatency.get(); cache.get("foo"); Assert.assertEquals(1, statistics.getSize()); Assert.assertEquals(2, statistics.getGetCount());
Cache<?, ?> cache = iterator.next().get(); if (cache == null || cache.isDestroyed()) { iterator.remove(); continue; long l = cache.refresh(time); if (l > 0 && l < wakeup) wakeup = l;
public void removeOldest() { Holder<K, V> holder = null; TimingsHolder<K, V> th; Iterator<WeakReference<TimingsHolder<K, V>>> i = timings.values().iterator(); while ((th = next(i)) != null) { Iterator<TimingEntry<Holder<K, V>>> iterator = th.timings.iterator(); while (iterator.hasNext()) { TimingEntry<Holder<K, V>> next = iterator.next(); Holder<K, V> temp = next.value.get(); if (temp == null || temp.isRemoved() || next.timing != temp.validUntil) { iterator.remove(); continue; } if (holder == null || temp.validUntil < holder.validUntil) holder = temp; break; } } if (holder != null) remove(holder.getKey()); }
protected void injectDependencies(Object ob) { boolean ok = true; Iterator<FieldReflection> i = dependencies.get(ob.getClass()).iterator(); while (ok && i.hasNext()) { FieldReflection f = i.next(); ArrayList<FieldReflection> list = new ArrayList<>(dependencies.get(ob.getClass())); Iterator<FieldReflection> iterator = list.iterator(); dependencies.put(ob.getClass(), list);
public boolean isValid() { Cache cache = this.cache.get(); return cache != null && !cache.isDestroyed(); }
public Cache<K, V> allowOutdated() { return allowOutdated(ttl <= 1000 ? 1 : ttl / 2000); }