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);
|
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>(
|
H2CacheImpl<K, V> cache = new H2CacheImpl<K, V>(
|
||||||
executor, store, def.keyType(),
|
executor, store, def.keyType(),
|
||||||
(Cache<K, ValueHolder<V>>) defaultFactory.create(def, true).build());
|
(Cache<K, ValueHolder<V>>) defaultFactory.create(def, true).build());
|
||||||
@@ -182,7 +183,8 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
|
|||||||
return defaultFactory.build(def, loader);
|
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>>)
|
Cache<K, ValueHolder<V>> mem = (Cache<K, ValueHolder<V>>)
|
||||||
defaultFactory.create(def, true)
|
defaultFactory.create(def, true)
|
||||||
.build((CacheLoader<K, V>) new H2CacheImpl.Loader<K, V>(
|
.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(
|
private <V, K> SqlStore<K, V> newSqlStore(
|
||||||
String name,
|
String name,
|
||||||
TypeLiteral<K> keyType,
|
TypeLiteral<K> keyType,
|
||||||
long maxSize) {
|
long maxSize,
|
||||||
|
Long expireAfterWrite) {
|
||||||
File db = new File(cacheDir, name).getAbsoluteFile();
|
File db = new File(cacheDir, name).getAbsoluteFile();
|
||||||
String url = "jdbc:h2:" + db.toURI().toString();
|
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 String url;
|
||||||
private final KeyType<K> keyType;
|
private final KeyType<K> keyType;
|
||||||
private final long maxSize;
|
private final long maxSize;
|
||||||
|
private final long expireAfterWrite;
|
||||||
private final BlockingQueue<SqlHandle> handles;
|
private final BlockingQueue<SqlHandle> handles;
|
||||||
private final AtomicLong hitCount = new AtomicLong();
|
private final AtomicLong hitCount = new AtomicLong();
|
||||||
private final AtomicLong missCount = new AtomicLong();
|
private final AtomicLong missCount = new AtomicLong();
|
||||||
private volatile BloomFilter<K> bloomFilter;
|
private volatile BloomFilter<K> bloomFilter;
|
||||||
private int estimatedSize;
|
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.url = jdbcUrl;
|
||||||
this.keyType = KeyType.create(keyType);
|
this.keyType = KeyType.create(keyType);
|
||||||
this.maxSize = maxSize;
|
this.maxSize = maxSize;
|
||||||
|
this.expireAfterWrite = expireAfterWrite;
|
||||||
|
|
||||||
int cores = Runtime.getRuntime().availableProcessors();
|
int cores = Runtime.getRuntime().availableProcessors();
|
||||||
int keep = Math.min(cores, 16);
|
int keep = Math.min(cores, 16);
|
||||||
@@ -408,7 +411,7 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
|||||||
try {
|
try {
|
||||||
c = acquire();
|
c = acquire();
|
||||||
if (c.get == null) {
|
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);
|
keyType.set(c.get, 1, key);
|
||||||
ResultSet r = c.get.executeQuery();
|
ResultSet r = c.get.executeQuery();
|
||||||
@@ -418,6 +421,13 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timestamp created = r.getTimestamp(2);
|
||||||
|
if (expired(created)) {
|
||||||
|
invalidate(key);
|
||||||
|
missCount.incrementAndGet();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
V val = (V) r.getObject(1);
|
V val = (V) r.getObject(1);
|
||||||
ValueHolder<V> h = new ValueHolder<>(val);
|
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 {
|
private void touch(SqlHandle c, K key) throws SQLException {
|
||||||
if (c.touch == null) {
|
if (c.touch == null) {
|
||||||
c.touch =c.conn.prepareStatement("UPDATE data SET accessed=? WHERE k=?");
|
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"
|
r = s.executeQuery("SELECT"
|
||||||
+ " k"
|
+ " k"
|
||||||
+ ",OCTET_LENGTH(k) + OCTET_LENGTH(v)"
|
+ ",OCTET_LENGTH(k) + OCTET_LENGTH(v)"
|
||||||
|
+ ",created"
|
||||||
+ " FROM data"
|
+ " FROM data"
|
||||||
+ " ORDER BY accessed");
|
+ " ORDER BY accessed");
|
||||||
try {
|
try {
|
||||||
while (maxSize < used && r.next()) {
|
while (maxSize < used && r.next()) {
|
||||||
K key = keyType.get(r, 1);
|
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);
|
touch(c, key);
|
||||||
} else {
|
} else {
|
||||||
invalidate(c, key);
|
invalidate(c, key);
|
||||||
|
|||||||
Reference in New Issue
Block a user