Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java
index 3b2a650..94c7fea 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java
@@ -5,18 +5,41 @@
*/
package br.ufrgs.inf.prosoft.cache;
+import java.util.function.Function;
+
/**
*
* @author romulo
+ * @param <K>
+ * @param <V>
*/
-public interface Cache {
+public interface Cache<K, V> {
+
+ public V put(K key, V value, long timeToLive);
- public Object put(Object key, Object value, long timeToLive);
+ public V put(K key, V value);
- public Object put(Object key, Object value);
+ public V get(K key);
- public Object get(Object key);
+ public void invalidate(K key);
- public void invalidate(Object key);
+ public default V computeIfAbsent(K key, Function<K, V> function, long timeToLive) {
+ V get = get(key);
+ if (get != null) {
+ return get;
+ }
+ V apply = function.apply(key);
+ put(key, apply, timeToLive);
+ return apply;
+ }
+ public default V computeIfAbsent(K key, Function<K, V> function) {
+ V get = get(key);
+ if (get != null) {
+ return get;
+ }
+ V apply = function.apply(key);
+ put(key, apply);
+ return apply;
+ }
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/CachingPerformance.java b/src/main/java/br/ufrgs/inf/prosoft/cache/CachingPerformance.java
index 7e9b4f4..cfffd66 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/CachingPerformance.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/CachingPerformance.java
@@ -5,6 +5,9 @@
*/
package br.ufrgs.inf.prosoft.cache;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -16,6 +19,7 @@ public class CachingPerformance {
private int misses;
private int hits;
+ private int bytesHits;
private int invalidations;
private int maximumSize;
private String name;
@@ -49,6 +53,10 @@ public class CachingPerformance {
this.hits++;
}
+ public void registerBytesHit(int size) {
+ this.bytesHits += size;
+ }
+
public void registerMiss() {
this.misses++;
}
@@ -73,10 +81,26 @@ public class CachingPerformance {
return this.hits * 100.0 / (this.hits + this.misses);
}
+ public double getByteHitRatio() {
+ return 100.0 * (this.bytesHits / (this.bytesHits + (this.bytesHits / this.hits) * this.misses));
+ }
+
public String needInvalidation() {
return this.invalidations > 0 ? "yes" : "no";
}
+ public static int calculateObjectSize(Object object) {
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) {
+ objectOutputStream.writeObject(object);
+ byte[] toByteArray = outputStream.toByteArray();
+ return toByteArray.length;
+ } catch (IOException ex) {
+ System.err.println("[Cache] size exception: " + ex);
+ }
+ return 0;
+ }
+
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java
index 380ca1c..c9936b5 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java
@@ -11,11 +11,12 @@ import java.util.logging.Logger;
/**
*
* @author romulo
+ * @param <V>
*/
-public class GetterCache {
+public class GetterCache<V> {
private final CachingPerformance cachingPerformance;
- private Object result;
+ private V result;
private boolean isFilled;
public GetterCache() {
@@ -33,8 +34,8 @@ public class GetterCache {
this.cachingPerformance = cachingPerformance;
}
- public Object put(Object value, long timeToLive) {
- Object put = put(value);
+ public V put(V value, long timeToLive) {
+ V put = put(value);
Thread thread = new Thread(() -> {
try {
Thread.sleep(timeToLive);
@@ -48,18 +49,19 @@ public class GetterCache {
return put;
}
- public Object put(Object value) {
+ public V put(V value) {
this.result = value;
this.isFilled = true;
this.cachingPerformance.registerSize(1);
return this.result;
}
- public Object get() {
+ public V get() {
if (this.isFilled == false) {
this.cachingPerformance.registerMiss();
return null;
}
+ this.cachingPerformance.registerBytesHit(CachingPerformance.calculateObjectSize(this.result));
this.cachingPerformance.registerHit();
return this.result;
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java
index a4476f2..43d3cab 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java
@@ -12,21 +12,27 @@ import java.util.logging.Logger;
/**
*
* @author romulo
+ * @param <K>
+ * @param <V>
*/
-public class MultiCache extends HashMap<Object, Object> implements Cache {
+public class MultiCache<K, V> implements Cache<K, V> {
+ private final HashMap<K, V> map;
private final CachingPerformance cachingPerformance;
public MultiCache() {
this.cachingPerformance = new CachingPerformance();
+ this.map = new HashMap<>();
}
-
+
public MultiCache(String name) {
this.cachingPerformance = new CachingPerformance(name);
+ this.map = new HashMap<>();
}
public MultiCache(CachingPerformance cachingPerformance) {
this.cachingPerformance = cachingPerformance;
+ this.map = new HashMap<>();
}
public CachingPerformance getCachingPerformance() {
@@ -34,43 +40,44 @@ public class MultiCache extends HashMap<Object, Object> implements Cache {
}
@Override
- public Object put(Object key, Object value, long timeToLive) {
- Object put = put(key, value);
+ public V put(K key, V value, long timeToLive) {
+ V put = put(key, value);
Thread thread = new Thread(() -> {
try {
Thread.sleep(timeToLive);
} catch (InterruptedException ex) {
Logger.getLogger(MultiCache.class.getName()).log(Level.SEVERE, "interrupted time to live");
}
- MultiCache.super.remove(key);
+ this.map.remove(key);
});
thread.start();
return put;
}
@Override
- public Object put(Object key, Object value) {
- Object oldReference = super.put(key, value);
+ public V put(K key, V value) {
+ V oldReference = this.map.put(key, value);
if (oldReference == null) {
- this.cachingPerformance.registerSize(size());
+ this.cachingPerformance.registerSize(this.map.size());
}
return oldReference;
}
@Override
- public Object get(Object key) {
- Object get = super.get(key);
+ public V get(K key) {
+ V get = this.map.get(key);
if (get == null) {
this.cachingPerformance.registerMiss();
} else {
this.cachingPerformance.registerHit();
+ this.cachingPerformance.registerBytesHit(CachingPerformance.calculateObjectSize(get));
}
return get;
}
@Override
- public void invalidate(Object key) {
- Object remove = this.remove(key);
+ public void invalidate(K key) {
+ V remove = this.map.remove(key);
if (remove != null) {
this.cachingPerformance.registerInvalidation();
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/SingleCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/SingleCache.java
index 9427f1c..37c32d9 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/SingleCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/SingleCache.java
@@ -11,17 +11,19 @@ import java.util.logging.Logger;
/**
*
* @author romulo
+ * @param <K>
+ * @param <V>
*/
-public class SingleCache implements Cache {
+public class SingleCache<K, V> implements Cache<K, V> {
private final CachingPerformance cachingPerformance;
- private Object lastInput;
- private Object result;
+ private K lastInput;
+ private V result;
public SingleCache() {
this.cachingPerformance = new CachingPerformance();
}
-
+
public SingleCache(String name) {
this.cachingPerformance = new CachingPerformance(name);
}
@@ -35,8 +37,8 @@ public class SingleCache implements Cache {
}
@Override
- public Object put(Object key, Object value, long timeToLive) {
- Object put = put(key, value);
+ public V put(K key, V value, long timeToLive) {
+ V put = put(key, value);
Thread thread = new Thread(() -> {
try {
Thread.sleep(timeToLive);
@@ -51,7 +53,7 @@ public class SingleCache implements Cache {
}
@Override
- public Object put(Object key, Object value) {
+ public V put(K key, V value) {
this.lastInput = key;
this.result = value;
this.cachingPerformance.registerSize(1);
@@ -59,9 +61,10 @@ public class SingleCache implements Cache {
}
@Override
- public Object get(Object key) {
+ public V get(K key) {
if (key.equals(this.lastInput)) {
this.cachingPerformance.registerHit();
+ this.cachingPerformance.registerBytesHit(CachingPerformance.calculateObjectSize(this.result));
return this.result;
}
this.cachingPerformance.registerMiss();
@@ -69,7 +72,7 @@ public class SingleCache implements Cache {
}
@Override
- public void invalidate(Object key) {
+ public void invalidate(K key) {
this.lastInput = null;
this.result = null;
this.cachingPerformance.registerInvalidation();