Honor expireAfterWrite in the H2CacheImpl
The H2CacheImpl didn't honor the expireAfterWrite. This had an effect that persisted entries never expired. For example, the web_sessions cache entries didn't expire after their maxAge was reached. Change-Id: I3a7c754ee05fe9ac92d96652db4b862bb597eba1 Signed-off-by: Saša Živkov <sasa.zivkov@sap.com> Signed-off-by: Adrian Görler <adrian.goerler@sap.com>
This commit is contained in:
committed by
Adrian Görler
parent
c07d0d0f04
commit
98adfd5c53
@@ -161,7 +161,8 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
|
||||
return defaultFactory.build(def);
|
||||
}
|
||||
|
||||
SqlStore<K, V> store = newSqlStore(def.name(), def.keyType(), limit);
|
||||
SqlStore<K, V> store = newSqlStore(def.name(), def.keyType(), limit,
|
||||
def.expireAfterWrite(TimeUnit.SECONDS));
|
||||
H2CacheImpl<K, V> cache = new H2CacheImpl<K, V>(
|
||||
executor, store, def.keyType(),
|
||||
(Cache<K, ValueHolder<V>>) defaultFactory.create(def, true).build());
|
||||
@@ -182,7 +183,8 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
|
||||
return defaultFactory.build(def, loader);
|
||||
}
|
||||
|
||||
SqlStore<K, V> store = newSqlStore(def.name(), def.keyType(), limit);
|
||||
SqlStore<K, V> store = newSqlStore(def.name(), def.keyType(), limit,
|
||||
def.expireAfterWrite(TimeUnit.SECONDS));
|
||||
Cache<K, ValueHolder<V>> mem = (Cache<K, ValueHolder<V>>)
|
||||
defaultFactory.create(def, true)
|
||||
.build((CacheLoader<K, V>) new H2CacheImpl.Loader<K, V>(
|
||||
@@ -209,9 +211,11 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
|
||||
private <V, K> SqlStore<K, V> newSqlStore(
|
||||
String name,
|
||||
TypeLiteral<K> keyType,
|
||||
long maxSize) {
|
||||
long maxSize,
|
||||
Long expireAfterWrite) {
|
||||
File db = new File(cacheDir, name).getAbsoluteFile();
|
||||
String url = "jdbc:h2:" + db.toURI().toString();
|
||||
return new SqlStore<>(url, keyType, maxSize);
|
||||
return new SqlStore<>(url, keyType, maxSize,
|
||||
expireAfterWrite == null ? 0 : expireAfterWrite.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,16 +313,19 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
||||
private final String url;
|
||||
private final KeyType<K> keyType;
|
||||
private final long maxSize;
|
||||
private final long expireAfterWrite;
|
||||
private final BlockingQueue<SqlHandle> handles;
|
||||
private final AtomicLong hitCount = new AtomicLong();
|
||||
private final AtomicLong missCount = new AtomicLong();
|
||||
private volatile BloomFilter<K> bloomFilter;
|
||||
private int estimatedSize;
|
||||
|
||||
SqlStore(String jdbcUrl, TypeLiteral<K> keyType, long maxSize) {
|
||||
SqlStore(String jdbcUrl, TypeLiteral<K> keyType, long maxSize,
|
||||
long expireAfterWrite) {
|
||||
this.url = jdbcUrl;
|
||||
this.keyType = KeyType.create(keyType);
|
||||
this.maxSize = maxSize;
|
||||
this.expireAfterWrite = expireAfterWrite;
|
||||
|
||||
int cores = Runtime.getRuntime().availableProcessors();
|
||||
int keep = Math.min(cores, 16);
|
||||
@@ -408,7 +411,7 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
||||
try {
|
||||
c = acquire();
|
||||
if (c.get == null) {
|
||||
c.get = c.conn.prepareStatement("SELECT v FROM data WHERE k=?");
|
||||
c.get = c.conn.prepareStatement("SELECT v, created FROM data WHERE k=?");
|
||||
}
|
||||
keyType.set(c.get, 1, key);
|
||||
ResultSet r = c.get.executeQuery();
|
||||
@@ -418,6 +421,13 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
||||
return null;
|
||||
}
|
||||
|
||||
Timestamp created = r.getTimestamp(2);
|
||||
if (expired(created)) {
|
||||
invalidate(key);
|
||||
missCount.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
V val = (V) r.getObject(1);
|
||||
ValueHolder<V> h = new ValueHolder<>(val);
|
||||
@@ -438,6 +448,14 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
||||
}
|
||||
}
|
||||
|
||||
private boolean expired(Timestamp created) {
|
||||
if (expireAfterWrite == 0) {
|
||||
return false;
|
||||
}
|
||||
long age = TimeUtil.nowMs() - created.getTime();
|
||||
return 1000 * expireAfterWrite < age;
|
||||
}
|
||||
|
||||
private void touch(SqlHandle c, K key) throws SQLException {
|
||||
if (c.touch == null) {
|
||||
c.touch =c.conn.prepareStatement("UPDATE data SET accessed=? WHERE k=?");
|
||||
@@ -552,12 +570,14 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
||||
r = s.executeQuery("SELECT"
|
||||
+ " k"
|
||||
+ ",OCTET_LENGTH(k) + OCTET_LENGTH(v)"
|
||||
+ ",created"
|
||||
+ " FROM data"
|
||||
+ " ORDER BY accessed");
|
||||
try {
|
||||
while (maxSize < used && r.next()) {
|
||||
K key = keyType.get(r, 1);
|
||||
if (mem.getIfPresent(key) != null) {
|
||||
Timestamp created = r.getTimestamp(3);
|
||||
if (mem.getIfPresent(key) != null && !expired(created)) {
|
||||
touch(c, key);
|
||||
} else {
|
||||
invalidate(c, key);
|
||||
|
||||
Reference in New Issue
Block a user