use of org.neo4j.io.fs.DelegatingStoreChannel in project neo4j by neo4j.
the class PageCacheTest method pageFaultForWriteMustThrowIfOutOfStorageSpace.
@Test
void pageFaultForWriteMustThrowIfOutOfStorageSpace() {
assertTimeoutPreemptively(ofMillis(SHORT_TIMEOUT_MILLIS), () -> {
final AtomicInteger writeCounter = new AtomicInteger();
AtomicBoolean restrictWrites = new AtomicBoolean(true);
FileSystemAbstraction fs = new DelegatingFileSystemAbstraction(this.fs) {
private final List<StoreChannel> channels = new CopyOnWriteArrayList<>();
@Override
public StoreChannel open(Path fileName, Set<OpenOption> options) throws IOException {
StoreChannel channel = new DelegatingStoreChannel(super.open(fileName, options)) {
@Override
public void writeAll(ByteBuffer src, long position) throws IOException {
if (restrictWrites.get() && writeCounter.incrementAndGet() > 10) {
throw new IOException("No space left on device");
}
super.writeAll(src, position);
}
};
channels.add(channel);
return channel;
}
@Override
public void close() throws IOException {
IOUtils.closeAll(channels);
super.close();
}
};
fs.write(file("a")).close();
getPageCache(fs, maxPages, PageCacheTracer.NULL);
PagedFile pagedFile = map(file("a"), filePageSize);
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_WRITE_LOCK, NULL)) {
assertThrows(IOException.class, () -> {
// noinspection StatementWithEmptyBody
while (cursor.next()) {
// Profound and interesting I/O.
}
});
} finally {
restrictWrites.set(false);
pagedFile.close();
pageCache.close();
fs.close();
}
});
}
use of org.neo4j.io.fs.DelegatingStoreChannel in project neo4j by neo4j.
the class PageCacheTest method mustRecoverViaFileFlushFromFullDriveWhenMoreStorageBecomesAvailable.
@Test
void mustRecoverViaFileFlushFromFullDriveWhenMoreStorageBecomesAvailable() throws Exception {
final AtomicBoolean hasSpace = new AtomicBoolean();
final AtomicBoolean hasThrown = new AtomicBoolean();
FileSystemAbstraction fs = new DelegatingFileSystemAbstraction(this.fs) {
@Override
public StoreChannel open(Path fileName, Set<OpenOption> options) throws IOException {
return new DelegatingStoreChannel(super.open(fileName, options)) {
@Override
public void writeAll(ByteBuffer src, long position) throws IOException {
if (!hasSpace.get()) {
hasThrown.set(true);
throw new IOException("No space left on device");
}
super.writeAll(src, position);
}
};
}
};
fs.write(file("a")).close();
getPageCache(fs, maxPages, PageCacheTracer.NULL);
PagedFile pagedFile = map(file("a"), filePageSize);
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_WRITE_LOCK, NULL)) {
while (// Keep writing until we get an exception! (when the cache starts evicting stuff)
!hasThrown.get()) {
assertTrue(cursor.next());
writeRecords(cursor);
}
} catch (IOException ignore) {
// We're out of space! Salty tears...
}
// Fix the situation:
hasSpace.set(true);
// Flushing the paged file implies the eviction exception gets cleared, and mustn't itself throw:
pagedFile.flushAndForce();
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_READ_LOCK, NULL)) {
// this should not throw
assertTrue(cursor.next());
}
pagedFile.close();
}
use of org.neo4j.io.fs.DelegatingStoreChannel in project neo4j by neo4j.
the class PageCacheTest method mustNotFlushCleanPagesWhenEvicting.
@Test
void mustNotFlushCleanPagesWhenEvicting() {
assertTimeoutPreemptively(ofMillis(SEMI_LONG_TIMEOUT_MILLIS), () -> {
final AtomicBoolean observedWrite = new AtomicBoolean();
FileSystemAbstraction fs = new DelegatingFileSystemAbstraction(this.fs) {
@Override
public StoreChannel open(Path fileName, Set<OpenOption> options) throws IOException {
StoreChannel channel = super.open(fileName, options);
return new DelegatingStoreChannel(channel) {
@Override
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
observedWrite.set(true);
throw new IOException("not allowed");
}
@Override
public void writeAll(ByteBuffer src, long position) throws IOException {
observedWrite.set(true);
throw new IOException("not allowed");
}
@Override
public void writeAll(ByteBuffer src) throws IOException {
observedWrite.set(true);
throw new IOException("not allowed");
}
@Override
public int write(ByteBuffer src) throws IOException {
observedWrite.set(true);
throw new IOException("not allowed");
}
@Override
public long write(ByteBuffer[] srcs) throws IOException {
observedWrite.set(true);
throw new IOException("not allowed");
}
};
}
};
getPageCache(fs, maxPages, PageCacheTracer.NULL);
generateFileWithRecords(file("a"), recordCount, recordSize);
try (PagedFile pagedFile = map(file("a"), filePageSize);
PageCursor cursor = pagedFile.io(0, PF_SHARED_READ_LOCK, NULL)) {
while (cursor.next()) {
verifyRecordsMatchExpected(cursor);
}
}
assertFalse(observedWrite.get());
});
}
use of org.neo4j.io.fs.DelegatingStoreChannel in project neo4j by neo4j.
the class PageCacheTest method pageFaultForReadMustThrowIfOutOfStorageSpace.
@Test
void pageFaultForReadMustThrowIfOutOfStorageSpace() {
try {
assertTimeoutPreemptively(ofMillis(SEMI_LONG_TIMEOUT_MILLIS), () -> {
final AtomicInteger writeCounter = new AtomicInteger();
AtomicBoolean restrictWrites = new AtomicBoolean(true);
FileSystemAbstraction fs = new DelegatingFileSystemAbstraction(this.fs) {
private final List<StoreChannel> channels = new CopyOnWriteArrayList<>();
@Override
public StoreChannel open(Path fileName, Set<OpenOption> options) throws IOException {
StoreChannel channel = new DelegatingStoreChannel(super.open(fileName, options)) {
@Override
public void writeAll(ByteBuffer src, long position) throws IOException {
if (restrictWrites.get() && writeCounter.incrementAndGet() >= 1) {
throw new IOException("No space left on device");
}
super.writeAll(src, position);
}
};
channels.add(channel);
return channel;
}
@Override
public void close() throws IOException {
IOUtils.closeAll(channels);
super.close();
}
};
getPageCache(fs, maxPages, PageCacheTracer.NULL);
generateFileWithRecords(file("a"), recordCount, recordSize);
PagedFile pagedFile = map(file("a"), filePageSize);
// Create 1 dirty page
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_WRITE_LOCK, NULL)) {
assertTrue(cursor.next());
}
// Read pages until the dirty page gets flushed
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_READ_LOCK, NULL)) {
// noinspection InfiniteLoopStatement
for (; ; ) {
// noinspection StatementWithEmptyBody
while (cursor.next()) {
// Profound and interesting I/O.
}
// Use rewind if we get to the end, because it is non-
// deterministic which pages get evicted and when.
cursor.rewind();
}
} finally {
restrictWrites.set(false);
pagedFile.close();
pageCache.close();
fs.close();
}
});
} catch (Exception e) {
assertThat(e).isInstanceOf(IOException.class);
}
}
use of org.neo4j.io.fs.DelegatingStoreChannel in project neo4j by neo4j.
the class PageCacheTest method mustRecoverViaFileCloseFromFullDriveWhenMoreStorageBecomesAvailable.
@Test
void mustRecoverViaFileCloseFromFullDriveWhenMoreStorageBecomesAvailable() {
assertTimeoutPreemptively(ofMillis(SHORT_TIMEOUT_MILLIS), () -> {
final AtomicBoolean hasSpace = new AtomicBoolean();
FileSystemAbstraction fs = new DelegatingFileSystemAbstraction(this.fs) {
@Override
public StoreChannel open(Path fileName, Set<OpenOption> options) throws IOException {
return new DelegatingStoreChannel(super.open(fileName, options)) {
@Override
public void writeAll(ByteBuffer src, long position) throws IOException {
if (!hasSpace.get()) {
throw new IOException("No space left on device");
}
super.writeAll(src, position);
}
};
}
};
fs.write(file("a")).close();
getPageCache(fs, maxPages, PageCacheTracer.NULL);
PagedFile pagedFile = map(file("a"), filePageSize);
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_WRITE_LOCK, NULL)) {
// noinspection InfiniteLoopStatement
for (; ; ) // Keep writing until we get an exception! (when the cache starts evicting stuff)
{
assertTrue(cursor.next());
writeRecords(cursor);
}
} catch (IOException ignore) {
// We're out of space! Salty tears...
}
// Fix the situation:
hasSpace.set(true);
// Closing the last reference of a paged file implies a flush, and it mustn't throw:
pagedFile.close();
try (PagedFile pf = map(file("a"), filePageSize);
PageCursor cursor = pf.io(0, PF_SHARED_READ_LOCK, NULL)) {
// this should not throw
assertTrue(cursor.next());
}
});
}
Aggregations