/* Copyright 2012 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arbeitspferde.groningen.experimentdb;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.inject.Inject;
import org.arbeitspferde.groningen.config.NamedConfigParam;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* The Experiment Database In Memory Cache is used to store data locally in the
* system's main memory. The intention is only data in-use by the Groningen pipeline
* should be stored in classes inheriting from this one.
*
* @param T The actual type of cache entries.
*/
abstract class InMemoryCache<T extends InMemoryCache.Value<T>> {
@Inject
@NamedConfigParam("default_in_memory_cache_ttl")
private final int defaultInMemoryCacheTtl = 600000;
private final AtomicLong insertionCount = new AtomicLong(0);
private final AtomicLong hitCount = new AtomicLong(0);
private final AtomicLong missCount = new AtomicLong(0);
private final Cache<Long, T> cache = CacheBuilder
.newBuilder()
.expireAfterAccess(defaultInMemoryCacheTtl, TimeUnit.SECONDS)
.build();
public void reset() {
cache.invalidateAll();
}
public void reset(InMemoryCache<T> anotherCache) {
cache.invalidateAll();
cache.putAll(anotherCache.cache.asMap());
}
/**
* Register an element in the cache (and return it unchanged).
*/
T register(T toCache) {
cache.put(toCache.getIdOfObject(), toCache);
insertionCount.incrementAndGet();
return toCache;
}
/**
* Return the cache element with the given id, or null if it doesn't exist
*/
public T lookup(long id) {
checkArgument(id > 0, "IDs should be positive.");
final T result = cache.getIfPresent(id);
if (null == result) {
missCount.incrementAndGet();
} else {
hitCount.incrementAndGet();
}
return result;
}
abstract static class Value<T extends Value> {
private final long idOfObject;
/** Returns the id of the subject owning the cached data */
public long getIdOfObject() {
return idOfObject;
}
protected Value(long id) {
checkArgument(id > 0, "IDs should be positive.");
this.idOfObject = id;
}
}
public long getCacheSize() {
return cache.size();
}
public long getInsertionCount() {
return insertionCount.get();
}
public long getHitCount() {
return hitCount.get();
}
public long getMissCount() {
return missCount.get();
}
}