All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.microsoft.azure.documentdb.internal.AsyncCache Maven / Gradle / Ivy
package com.microsoft.azure.documentdb.internal;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Cache which supports asynchronous value initialization for the Azure Cosmos DB database service Java SDK.
* It ensures that for given key only single initialization function is running at any point in time.
*/
public final class AsyncCache {
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncCache.class);
private final ConcurrentHashMap> values;
private final ExecutorService executorService;
public AsyncCache(ExecutorService executorService) {
this.values = new ConcurrentHashMap>();
this.executorService = executorService;
}
public Set getKeys() {
return this.values.keySet();
}
public AsyncLazy put(TKey key, final TValue value) {
return this.values.put(key, new AsyncLazy(new Callable() {
@Override
public TValue call() throws Exception {
return value;
}
}, this.executorService));
}
public Future get(TKey key, TValue obsoleteValue, Callable callable) {
AsyncLazy initialAsyncLazy = this.values.get(key);
if (initialAsyncLazy != null && !initialAsyncLazy.isCancelled()) {
try {
if (!initialAsyncLazy.isDone() || !this.areEqual(initialAsyncLazy.getValue().get(), obsoleteValue)) {
LOGGER.debug("Use cache[{}], obsoleteValue: {}", key, obsoleteValue);
return initialAsyncLazy.getValue();
}
} catch (CancellationException | ExecutionException | InterruptedException e) {
// Nothing to do, proceed with replacing new AsyncLazy
LOGGER.debug("Cache[{}] encountered an exception during evaluation", key, e);
}
}
AsyncLazy newAsyncLazy = new AsyncLazy(callable, this.executorService);
// $ISSUE-felixfan-2016-08-03: We should use ConcurrentHashMap.merge when moving to Java 8
AsyncLazy actualAsyncLazy;
if (initialAsyncLazy == null) {
actualAsyncLazy = this.values.putIfAbsent(key, newAsyncLazy);
if (actualAsyncLazy == null) {
LOGGER.debug("Add cache [{}], obsoleteValue: {}", key, obsoleteValue);
actualAsyncLazy = newAsyncLazy;
}
} else if (this.values.replace(key, initialAsyncLazy, newAsyncLazy)) {
LOGGER.debug("Replace cache [{}], obsoleteValue: {}", key, obsoleteValue);
actualAsyncLazy = newAsyncLazy;
} else {
LOGGER.debug("Use cache in the end [{}], obsoleteValue: {}", key, obsoleteValue);
actualAsyncLazy = this.values.get(key);
}
return actualAsyncLazy.getValue();
}
public AsyncLazy remove(TKey key) {
return this.values.remove(key);
}
public void clear() {
this.values.clear();
}
public void refresh(TKey key, Callable callable) {
AsyncLazy initialAsyncLazy = this.values.get(key);
if (initialAsyncLazy != null && initialAsyncLazy.isDone()) {
AsyncLazy newAsyncLazy = new AsyncLazy(callable, this.executorService);
// $ISSUE-felixfan-2016-08-03: We should use ConcurrentHashMap.merge when moving to Java 8
if (this.values.replace(key, initialAsyncLazy, newAsyncLazy)) {
newAsyncLazy.getValue();
}
}
}
private boolean areEqual(TValue value1, TValue value2) {
if (value1 == value2)
return true;
if (value1 == null || value2 == null)
return false;
return value1.equals(value2);
}
}