use of com.google.common.util.concurrent.ForwardingListeningExecutorService in project druid by druid-io.
the class CachingClusteredClientTest method testOutOfOrderBackgroundCachePopulation.
@Test
public void testOutOfOrderBackgroundCachePopulation() {
// to trigger the actual execution when we are ready to shuffle the order.
abstract class DrainTask implements Runnable {
}
final ForwardingListeningExecutorService randomizingExecutorService = new ForwardingListeningExecutorService() {
final ConcurrentLinkedDeque<Pair<SettableFuture, Object>> taskQueue = new ConcurrentLinkedDeque<>();
final ListeningExecutorService delegate = MoreExecutors.listeningDecorator(// are complete before moving on to the next query run.
Execs.directExecutor());
@Override
protected ListeningExecutorService delegate() {
return delegate;
}
private <T> ListenableFuture<T> maybeSubmitTask(Object task, boolean wait) {
if (wait) {
SettableFuture<T> future = SettableFuture.create();
taskQueue.addFirst(Pair.of(future, task));
return future;
} else {
List<Pair<SettableFuture, Object>> tasks = Lists.newArrayList(taskQueue.iterator());
Collections.shuffle(tasks, new Random(0));
for (final Pair<SettableFuture, Object> pair : tasks) {
ListenableFuture future = pair.rhs instanceof Callable ? delegate.submit((Callable) pair.rhs) : delegate.submit((Runnable) pair.rhs);
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(@Nullable Object result) {
pair.lhs.set(result);
}
@Override
public void onFailure(Throwable t) {
pair.lhs.setException(t);
}
});
}
}
return task instanceof Callable ? delegate.submit((Callable) task) : (ListenableFuture<T>) delegate.submit((Runnable) task);
}
@SuppressWarnings("ParameterPackage")
@Override
public <T> ListenableFuture<T> submit(Callable<T> task) {
return maybeSubmitTask(task, true);
}
@Override
public ListenableFuture<?> submit(Runnable task) {
if (task instanceof DrainTask) {
return maybeSubmitTask(task, false);
} else {
return maybeSubmitTask(task, true);
}
}
};
client = makeClient(new BackgroundCachePopulator(randomizingExecutorService, JSON_MAPPER, new CachePopulatorStats(), -1));
// callback to be run every time a query run is complete, to ensure all background
// caching tasks are executed, and cache is populated before we move onto the next query
queryCompletedCallback = new Runnable() {
@Override
public void run() {
try {
randomizingExecutorService.submit(new DrainTask() {
@Override
public void run() {
// no-op
}
}).get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
final Druids.TimeseriesQueryBuilder builder = Druids.newTimeseriesQueryBuilder().dataSource(DATA_SOURCE).intervals(SEG_SPEC).filters(DIM_FILTER).granularity(GRANULARITY).aggregators(AGGS).postAggregators(POST_AGGS).context(CONTEXT).randomQueryId();
QueryRunner runner = new FinalizeResultsQueryRunner(getDefaultQueryRunner(), new TimeseriesQueryQueryToolChest());
testQueryCaching(runner, builder.build(), Intervals.of("2011-01-05/2011-01-10"), makeTimeResults(DateTimes.of("2011-01-05"), 85, 102, DateTimes.of("2011-01-06"), 412, 521, DateTimes.of("2011-01-07"), 122, 21894, DateTimes.of("2011-01-08"), 5, 20, DateTimes.of("2011-01-09"), 18, 521), Intervals.of("2011-01-10/2011-01-13"), makeTimeResults(DateTimes.of("2011-01-10"), 85, 102, DateTimes.of("2011-01-11"), 412, 521, DateTimes.of("2011-01-12"), 122, 21894));
}
use of com.google.common.util.concurrent.ForwardingListeningExecutorService in project druid by druid-io.
the class CachingClusteredClientTest method testOutOfOrderBackgroundCachePopulation.
@Test
public void testOutOfOrderBackgroundCachePopulation() throws Exception {
// to trigger the actual execution when we are ready to shuffle the order.
abstract class DrainTask implements Runnable {
}
final ForwardingListeningExecutorService randomizingExecutorService = new ForwardingListeningExecutorService() {
final ConcurrentLinkedDeque<Pair<SettableFuture, Object>> taskQueue = new ConcurrentLinkedDeque<>();
final ListeningExecutorService delegate = MoreExecutors.listeningDecorator(// are complete before moving on to the next query run.
MoreExecutors.sameThreadExecutor());
@Override
protected ListeningExecutorService delegate() {
return delegate;
}
private <T> ListenableFuture<T> maybeSubmitTask(Object task, boolean wait) {
if (wait) {
SettableFuture<T> future = SettableFuture.create();
taskQueue.addFirst(Pair.<SettableFuture, Object>of(future, task));
return future;
} else {
List<Pair<SettableFuture, Object>> tasks = Lists.newArrayList(taskQueue.iterator());
Collections.shuffle(tasks, new Random(0));
for (final Pair<SettableFuture, Object> pair : tasks) {
ListenableFuture future = pair.rhs instanceof Callable ? delegate.submit((Callable) pair.rhs) : delegate.submit((Runnable) pair.rhs);
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(@Nullable Object result) {
pair.lhs.set(result);
}
@Override
public void onFailure(Throwable t) {
pair.lhs.setException(t);
}
});
}
}
return task instanceof Callable ? delegate.submit((Callable) task) : (ListenableFuture<T>) delegate.submit((Runnable) task);
}
@Override
public <T> ListenableFuture<T> submit(Callable<T> task) {
return maybeSubmitTask(task, true);
}
@Override
public ListenableFuture<?> submit(Runnable task) {
if (task instanceof DrainTask) {
return maybeSubmitTask(task, false);
} else {
return maybeSubmitTask(task, true);
}
}
};
client = makeClient(randomizingExecutorService);
// callback to be run every time a query run is complete, to ensure all background
// caching tasks are executed, and cache is populated before we move onto the next query
queryCompletedCallback = new Runnable() {
@Override
public void run() {
try {
randomizingExecutorService.submit(new DrainTask() {
@Override
public void run() {
// no-op
}
}).get();
} catch (Exception e) {
Throwables.propagate(e);
}
}
};
final Druids.TimeseriesQueryBuilder builder = Druids.newTimeseriesQueryBuilder().dataSource(DATA_SOURCE).intervals(SEG_SPEC).filters(DIM_FILTER).granularity(GRANULARITY).aggregators(AGGS).postAggregators(POST_AGGS).context(CONTEXT);
QueryRunner runner = new FinalizeResultsQueryRunner(client, new TimeseriesQueryQueryToolChest(QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()));
testQueryCaching(runner, builder.build(), new Interval("2011-01-05/2011-01-10"), makeTimeResults(new DateTime("2011-01-05"), 85, 102, new DateTime("2011-01-06"), 412, 521, new DateTime("2011-01-07"), 122, 21894, new DateTime("2011-01-08"), 5, 20, new DateTime("2011-01-09"), 18, 521), new Interval("2011-01-10/2011-01-13"), makeTimeResults(new DateTime("2011-01-10"), 85, 102, new DateTime("2011-01-11"), 412, 521, new DateTime("2011-01-12"), 122, 21894));
}
use of com.google.common.util.concurrent.ForwardingListeningExecutorService in project jackrabbit-oak by apache.
the class IndexCopierTest method copyInProgressStats.
@Test
public void copyInProgressStats() throws Exception {
Directory baseDir = new RAMDirectory();
IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
final List<ListenableFuture<?>> submittedTasks = Lists.newArrayList();
ExecutorService executor = new ForwardingListeningExecutorService() {
@Override
protected ListeningExecutorService delegate() {
return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
}
@Override
public void execute(Runnable command) {
submittedTasks.add(super.submit(command));
}
};
IndexCopier c1 = new RAMIndexCopier(baseDir, executor, getWorkDir());
final CountDownLatch copyProceed = new CountDownLatch(1);
final CountDownLatch copyRequestArrived = new CountDownLatch(1);
TestRAMDirectory remote = new TestRAMDirectory() {
@Override
public void copy(Directory to, String src, String dest, IOContext context) throws IOException {
copyRequestArrived.countDown();
try {
copyProceed.await();
} catch (InterruptedException e) {
}
super.copy(to, src, dest, context);
}
};
Directory wrapped = c1.wrapForRead("/foo", defn, remote, INDEX_DATA_CHILD_NAME);
byte[] t1 = writeFile(remote, "t1");
// 1. Trigger a read which should go to remote
readAndAssert(wrapped, "t1", t1);
copyRequestArrived.await();
assertEquals(1, c1.getCopyInProgressCount());
assertEquals(1, remote.openedFiles.size());
// 2. Trigger another read and this should also be
// served from remote
readAndAssert(wrapped, "t1", t1);
assertEquals(1, c1.getCopyInProgressCount());
assertEquals(IOUtils.humanReadableByteCount(t1.length), c1.getCopyInProgressSize());
assertEquals(1, c1.getCopyInProgressDetails().length);
System.out.println(Arrays.toString(c1.getCopyInProgressDetails()));
assertEquals(2, remote.openedFiles.size());
// 3. Perform copy
copyProceed.countDown();
Futures.allAsList(submittedTasks).get();
remote.reset();
// 4. Now read again after copy is done
readAndAssert(wrapped, "t1", t1);
// Now read should be served from local and not from remote
assertEquals(0, remote.openedFiles.size());
assertEquals(0, c1.getCopyInProgressCount());
executor.shutdown();
}
Aggregations