Don't use forbidden API in FailableCache

This commit is contained in:
Simon Willnauer 2015-09-14 13:53:59 +02:00
parent 57c5efacf6
commit bd025080c4
1 changed files with 28 additions and 32 deletions

View File

@ -16,12 +16,7 @@
package org.elasticsearch.common.inject.internal;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.elasticsearch.common.SuppressForbidden;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ConcurrentHashMap;
/**
* Lazily creates (and caches) values for keys. If creating the value fails (with errors), an
@ -29,39 +24,40 @@ import java.util.concurrent.ExecutionException;
*
* @author jessewilson@google.com (Jesse Wilson)
*/
// TODO remove this suppression once we get rid of the CacheBuilder and friends
@SuppressForbidden(reason = "this uses Function in it's method declaration somewhere")
public abstract class FailableCache<K, V> {
private final LoadingCache<K, Object> delegate = CacheBuilder.newBuilder().build(new CacheLoader<K, Object>() {
@Override
public Object load(K key) throws Exception {
Errors errors = new Errors();
V result = null;
try {
result = FailableCache.this.create(key, errors);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
return errors.hasErrors() ? errors : result;
}
});
private final ConcurrentHashMap<K, Object> cache = new ConcurrentHashMap<>();
protected abstract V create(K key, Errors errors) throws ErrorsException;
public V get(K key, Errors errors) throws ErrorsException {
try {
Object resultOrError = delegate.get(key);
if (resultOrError instanceof Errors) {
errors.merge((Errors) resultOrError);
throw errors.toException();
} else {
@SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
V result = (V) resultOrError;
return result;
Object resultOrError = cache.get(key);
if (resultOrError == null) {
synchronized (this) {
resultOrError = load(key);
// we can't use cache.computeIfAbsent since this might be recursively call this API
cache.putIfAbsent(key, resultOrError);
}
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
if (resultOrError instanceof Errors) {
errors.merge((Errors) resultOrError);
throw errors.toException();
} else {
@SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
V result = (V) resultOrError;
return result;
}
}
private Object load(K key) {
Errors errors = new Errors();
V result = null;
try {
result = create(key, errors);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
return errors.hasErrors() ? errors : result;
}
}