use of org.neo4j.util.concurrent.Futures in project neo4j by neo4j.
the class PageSwapperTest method concurrentPositionedVectoredReadsAndWritesMustNotInterfere.
@Test
void concurrentPositionedVectoredReadsAndWritesMustNotInterfere() throws Exception {
Path file = file("file");
PageSwapperFactory factory = createSwapperFactory(getFs());
final PageSwapper swapper = createSwapperAndFile(factory, file, 4);
final int pageCount = 100;
final int iterations = 20000;
final CountDownLatch startLatch = new CountDownLatch(1);
long output = createPage(4);
for (int i = 0; i < pageCount; i++) {
putInt(output, 0, i + 1);
write(swapper, i, output);
}
Callable<Void> work = () -> {
ThreadLocalRandom rng = ThreadLocalRandom.current();
int length = 10;
int pageSize = 4;
long[] pages = new long[length];
int[] sizes = new int[length];
for (int i = 0; i < length; i++) {
pages[i] = createPage(pageSize);
sizes[i] = pageSize;
}
startLatch.await();
for (int i = 0; i < iterations; i++) {
long startFilePageId = rng.nextLong(0, pageCount - pages.length);
if (rng.nextBoolean()) {
// Do read
long bytesRead = read(swapper, startFilePageId, pages, sizes, pages.length);
assertThat(bytesRead).isEqualTo(pages.length * 4L);
for (int j = 0; j < pages.length; j++) {
int expectedValue = (int) (1 + j + startFilePageId);
int actualValue = getInt(pages[j], 0);
assertThat(actualValue).isEqualTo(expectedValue);
}
} else {
// Do write
for (int j = 0; j < pages.length; j++) {
int value = (int) (1 + j + startFilePageId);
putInt(pages[j], 0, value);
}
assertThat(write(swapper, startFilePageId, pages, sizes, pages.length, pages.length)).isEqualTo(pages.length * 4L);
}
}
return null;
};
int threads = 8;
ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(threads, r -> {
Thread thread = Executors.defaultThreadFactory().newThread(r);
thread.setDaemon(true);
return thread;
});
List<Future<?>> futures = new ArrayList<>(threads);
for (int i = 0; i < threads; i++) {
futures.add(executor.submit(work));
}
startLatch.countDown();
Futures.getAll(futures);
} finally {
if (executor != null) {
executor.shutdown();
}
}
}
use of org.neo4j.util.concurrent.Futures in project neo4j by neo4j.
the class TransactionLogFileTest method shouldBatchUpMultipleWaitingForceRequests.
@Test
void shouldBatchUpMultipleWaitingForceRequests() throws Throwable {
LogFiles logFiles = buildLogFiles();
life.start();
life.add(logFiles);
LogFile logFile = logFiles.getLogFile();
var capturingChannel = wrappingFileSystem.getCapturingChannel();
var flushesBefore = capturingChannel.getFlushCounter().get();
var writesBefore = capturingChannel.getWriteAllCounter().get();
ReentrantLock writeAllLock = capturingChannel.getWriteAllLock();
writeAllLock.lock();
int executors = 10;
var executorService = Executors.newFixedThreadPool(executors);
try {
List<Future<?>> futures = Stream.iterate(0, i -> i + 1).limit(executors).map(v -> executorService.submit(() -> logFile.forceAfterAppend(LogAppendEvent.NULL))).collect(toList());
while (!writeAllLock.hasQueuedThreads()) {
parkNanos(100);
}
writeAllLock.unlock();
assertThat(futures).hasSize(executors);
Futures.getAll(futures);
} finally {
if (writeAllLock.isLocked()) {
writeAllLock.unlock();
}
executorService.shutdownNow();
}
assertThat(capturingChannel.getFlushCounter().get() - flushesBefore).isLessThanOrEqualTo(executors);
assertThat(capturingChannel.getWriteAllCounter().get() - writesBefore).isLessThanOrEqualTo(executors);
}
Aggregations