use of java.io.Flushable in project neo4j by neo4j.
the class PageCacheTest method flushAndForceMustNotLockPageCacheForWholeDuration.
@Test
void flushAndForceMustNotLockPageCacheForWholeDuration() {
assertTimeoutPreemptively(ofMillis(SHORT_TIMEOUT_MILLIS), () -> {
maxPages = 5000;
configureStandardPageCache();
Path a = existingFile("a");
Path b = existingFile("b");
BinaryLatch limiterStartLatch = new BinaryLatch();
BinaryLatch limiterBlockLatch = new BinaryLatch();
var ioController = new EmptyIOController() {
@Override
public void maybeLimitIO(int recentlyCompletedIOs, Flushable flushable, MajorFlushEvent flushEvent) {
limiterStartLatch.release();
limiterBlockLatch.await();
super.maybeLimitIO(recentlyCompletedIOs, flushable, flushEvent);
}
};
try (PagedFile pfA = pageCache.map(a, filePageSize, DEFAULT_DATABASE_NAME, immutable.empty(), ioController)) {
// Dirty a bunch of pages.
try (PageCursor cursor = pfA.io(0, PF_SHARED_WRITE_LOCK, NULL)) {
for (int i = 0; i < maxPages; i++) {
assertTrue(cursor.next());
}
}
Future<?> flusher = executor.submit(() -> {
pfA.flushAndForce();
return null;
});
// Flusher is now stuck inside flushAndForce.
limiterStartLatch.await();
// We should be able to map and close paged files.
map(pageCache, b, filePageSize).close();
// We should be able to get and list existing mappings.
pageCache.listExistingMappings();
pageCache.getExistingMapping(a).ifPresent(PagedFile::close);
limiterBlockLatch.release();
flusher.get();
}
});
}
use of java.io.Flushable in project neo4j by neo4j.
the class TransactionLogFile method force.
private void force() throws IOException {
// Empty buffer into writer. We want to synchronize with appenders somehow so that they
// don't append while we're doing that. The way rotation is coordinated we can't synchronize
// on logFile because it would cause deadlocks. Synchronizing on writer assumes that appenders
// also synchronize on writer.
Flushable flushable;
synchronized (this) {
databaseHealth.assertHealthy(IOException.class);
flushable = writer.prepareForFlush();
}
// This allows other threads access to the buffer while the writer is being forced.
try {
flushable.flush();
} catch (ClosedChannelException ignored) {
// This is ok, we were already successful in emptying the buffer, so the channel being closed here means
// that some other thread is rotating the log and has closed the underlying channel. But since we were
// successful in emptying the buffer *UNDER THE LOCK* we know that the rotating thread included the changes
// we emptied into the channel, and thus it is already flushed by that thread.
}
}
Aggregations