cache

added CaffeineCache

7/16/2020 12:17:06 AM

Details

pom.xml 5(+5 -0)

diff --git a/pom.xml b/pom.xml
index 7b99582..780918f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,11 @@
             <artifactId>gson</artifactId>
             <version>2.8.5</version>
         </dependency>
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+            <version>2.5.5</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java b/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java
new file mode 100644
index 0000000..f82078f
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java
@@ -0,0 +1,120 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.cache;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * @author root
+ */
+public class Caffeine<K, V> implements Cache<K, V> {
+
+    private static final boolean CACHE_EVALUATE_PERFORMANCE = System.getenv("CACHE_EVENTS") == null || !System.getenv("CACHE_EVENTS").equals("false");
+    private static final boolean CACHE_REGISTER_SIZE = System.getenv("CACHE_REGISTER_SIZE") != null && System.getenv("CACHE_REGISTER_SIZE").equals("true");
+    private final com.github.benmanes.caffeine.cache.Cache<K, V> cache;
+    private final CachePerformance cachePerformance;
+
+    public Caffeine() {
+        this(new CachePerformance());
+    }
+
+    public Caffeine(long ttl) {
+        this(new CachePerformance(), ttl);
+    }
+
+    public Caffeine(String name) {
+        this(new CachePerformance(name));
+    }
+
+    public Caffeine(String name, long ttl) {
+        this(new CachePerformance(name), ttl);
+    }
+
+    public Caffeine(String name, Long ttl, long size) {
+        this(new CachePerformance(name), ttl, size);
+    }
+
+    public Caffeine(CachePerformance cachingPerformance) {
+        this.cachePerformance = cachingPerformance;
+        this.cache = com.github.benmanes.caffeine.cache.Caffeine.newBuilder()
+                .build();
+    }
+
+    public Caffeine(CachePerformance cachingPerformance, long ttl) {
+        this.cachePerformance = cachingPerformance;
+        this.cache = com.github.benmanes.caffeine.cache.Caffeine.newBuilder()
+                .expireAfterWrite(ttl, TimeUnit.MILLISECONDS)
+                .build();
+    }
+
+    public Caffeine(CachePerformance cachingPerformance, Long ttl, long size) {
+        this.cachePerformance = cachingPerformance;
+        if (ttl == null) {
+            this.cache = com.github.benmanes.caffeine.cache.Caffeine.newBuilder()
+                    .maximumSize(size)
+                    .build();
+
+        } else {
+            this.cache = com.github.benmanes.caffeine.cache.Caffeine.newBuilder()
+                    .expireAfterWrite(ttl, TimeUnit.MILLISECONDS)
+                    .maximumSize(size)
+                    .build();
+
+        }
+    }
+
+    public CachePerformance getCachePerformance() {
+        return this.cachePerformance;
+    }
+
+    @Override
+    public void put(K key, V value, long timeToLive) {
+        put(key, value);
+    }
+
+    @Override
+    public void put(K key, V value) {
+        this.cache.put(key, value);
+        registerEvent(EventType.ADDITION, value);
+    }
+
+    @Override
+    public V get(K key) throws KeyNotFoundException {
+        V get = this.cache.getIfPresent(key);
+        if (get == null) {
+            registerEvent(EventType.MISS, key);
+        }
+        registerEvent(EventType.HIT, get);
+        return get;
+    }
+
+    @Override
+    public void invalidate(K key) {
+        this.cache.invalidate(key);
+        registerEvent(EventType.INVALIDATION, null);
+    }
+
+    private String getIdentifier(Object object) {
+        return object != null ? String.valueOf(object.hashCode()) : "null";
+    }
+
+    private void registerEvent(EventType eventType, Object object) {
+        if (!CACHE_EVALUATE_PERFORMANCE) {
+            return;
+        }
+        String identifier = getIdentifier(object);
+        if (CACHE_REGISTER_SIZE) {
+            this.cachePerformance.registerEvent(eventType, identifier, CachePerformance.calculateObjectSize(object));
+        } else {
+            this.cachePerformance.registerEvent(eventType, identifier);
+        }
+        if (eventType.equals(EventType.ADDITION)) {
+            this.cachePerformance.registerSize((int) this.cache.stats().loadCount());
+        }
+    }
+
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineGetterCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineGetterCache.java
new file mode 100644
index 0000000..e036f6c
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineGetterCache.java
@@ -0,0 +1,57 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.cache;
+
+import java.util.function.Supplier;
+
+/**
+ *
+ * @author root
+ * @param <V>
+ */
+public class CaffeineGetterCache<V> extends CaffeineSingleCache<Void, V> {
+
+    public CaffeineGetterCache(String name) {
+        super(name);
+    }
+
+    public CaffeineGetterCache(String name, long ttl) {
+        super(name, ttl);
+    }
+
+    public CaffeineGetterCache(CachePerformance cachingPerformance) {
+        super(cachingPerformance);
+    }
+
+    public CaffeineGetterCache(CachePerformance cachingPerformance, long ttl) {
+        super(cachingPerformance, ttl);
+    }
+
+    public void put(V value, long timeToLive) {
+        super.put(null, value, timeToLive);
+    }
+
+    public void put(V value) {
+        super.put(null, value);
+    }
+
+    public V get() throws KeyNotFoundException {
+        return super.get(null);
+    }
+
+    public void invalidate() {
+        super.invalidate(null);
+    }
+
+    public V computeIfAbsent(Supplier<V> supplier, long timeToLive) {
+        return super.computeIfAbsent(null, supplier, timeToLive);
+    }
+
+    public V computeIfAbsent(Supplier<V> supplier) {
+        return super.computeIfAbsent(null, supplier);
+    }
+
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java
new file mode 100644
index 0000000..51ef925
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java
@@ -0,0 +1,32 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.cache;
+
+/**
+ *
+ * @author root
+ * @param <K>
+ * @param <V>
+ */
+public class CaffeineSingleCache<K, V> extends Caffeine<K, V> {
+
+    public CaffeineSingleCache(String name) {
+        super(name, null, 1);
+    }
+
+    public CaffeineSingleCache(String name, long ttl) {
+        super(name, ttl, 1);
+    }
+
+    public CaffeineSingleCache(CachePerformance cachingPerformance) {
+        super(cachingPerformance, null, 1);
+    }
+
+    public CaffeineSingleCache(CachePerformance cachingPerformance, long ttl) {
+        super(cachingPerformance, ttl, 1);
+    }
+
+}