Location location,
DistributedCallable<K, V, T> callable,
Combiner<T> combiner ) throws InterruptedException, ExecutionException {
if (location == null) location = Location.LOCALLY;
DistributedExecutorService distributedExecutor = new DefaultExecutorService(cache);
List<StoreConfiguration> stores = cache.getCacheConfiguration().persistence().stores();
boolean shared = (stores != null) && !stores.isEmpty() && stores.get(0).shared();
T result = null;
if (!shared) {
// store is not shared so every node must return key list of the store
List<Future<T>> futures = null;
switch (location) {
case EVERYWHERE:
futures = distributedExecutor.submitEverywhere(callable);
break;
case LOCALLY:
futures = Collections.singletonList(distributedExecutor.submit(callable));
break;
}
while (futures != null && !futures.isEmpty()) {
// Get the next future that is ready ...
Iterator<Future<T>> futureIter = futures.iterator();
while (futureIter.hasNext()) {
Future<T> future = futureIter.next();
try {
// But done't wait too long for this future ...
T value = future.get(100, TimeUnit.MILLISECONDS);
// We got some keys, so this future is done and should be removed from our list ...
futureIter.remove();
result = combiner.combine(result, value);
} catch (TimeoutException e) {
// continue;
}
}
if (futures.isEmpty()) break;
}
} else {
// store is shared, so we can short-circuit the logic and just run locally; otherwise, if distributed
// each process will see the all of the keys ...
result = distributedExecutor.submit(callable).get();
}
return result;
}