Search in sources :

Example 1 with DelegatingStoreChannel

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();
        }
    });
}
Also used : Path(java.nio.file.Path) AdversarialFileSystemAbstraction(org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) EphemeralFileSystemAbstraction(org.neo4j.io.fs.EphemeralFileSystemAbstraction) FileSystemAbstraction(org.neo4j.io.fs.FileSystemAbstraction) SwapperSet(org.neo4j.io.pagecache.impl.muninn.SwapperSet) Set(java.util.Set) ImmutableSet(org.eclipse.collections.api.set.ImmutableSet) StoreChannel(org.neo4j.io.fs.StoreChannel) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) ByteBuffer(java.nio.ByteBuffer) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) LinkedList(java.util.LinkedList) RepeatedTest(org.junit.jupiter.api.RepeatedTest) Test(org.junit.jupiter.api.Test)

Example 2 with DelegatingStoreChannel

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();
}
Also used : Path(java.nio.file.Path) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AdversarialFileSystemAbstraction(org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) EphemeralFileSystemAbstraction(org.neo4j.io.fs.EphemeralFileSystemAbstraction) FileSystemAbstraction(org.neo4j.io.fs.FileSystemAbstraction) SwapperSet(org.neo4j.io.pagecache.impl.muninn.SwapperSet) Set(java.util.Set) ImmutableSet(org.eclipse.collections.api.set.ImmutableSet) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) ByteBuffer(java.nio.ByteBuffer) RepeatedTest(org.junit.jupiter.api.RepeatedTest) Test(org.junit.jupiter.api.Test)

Example 3 with DelegatingStoreChannel

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());
    });
}
Also used : Path(java.nio.file.Path) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AdversarialFileSystemAbstraction(org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) EphemeralFileSystemAbstraction(org.neo4j.io.fs.EphemeralFileSystemAbstraction) FileSystemAbstraction(org.neo4j.io.fs.FileSystemAbstraction) SwapperSet(org.neo4j.io.pagecache.impl.muninn.SwapperSet) Set(java.util.Set) ImmutableSet(org.eclipse.collections.api.set.ImmutableSet) StoreChannel(org.neo4j.io.fs.StoreChannel) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) ByteBuffer(java.nio.ByteBuffer) RepeatedTest(org.junit.jupiter.api.RepeatedTest) Test(org.junit.jupiter.api.Test)

Example 4 with DelegatingStoreChannel

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);
    }
}
Also used : Path(java.nio.file.Path) AdversarialFileSystemAbstraction(org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) EphemeralFileSystemAbstraction(org.neo4j.io.fs.EphemeralFileSystemAbstraction) FileSystemAbstraction(org.neo4j.io.fs.FileSystemAbstraction) SwapperSet(org.neo4j.io.pagecache.impl.muninn.SwapperSet) Set(java.util.Set) ImmutableSet(org.eclipse.collections.api.set.ImmutableSet) StoreChannel(org.neo4j.io.fs.StoreChannel) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) ByteBuffer(java.nio.ByteBuffer) NoSuchFileException(java.nio.file.NoSuchFileException) FileIsNotMappedException(org.neo4j.io.pagecache.impl.FileIsNotMappedException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) ReadOnlyBufferException(java.nio.ReadOnlyBufferException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) LinkedList(java.util.LinkedList) RepeatedTest(org.junit.jupiter.api.RepeatedTest) Test(org.junit.jupiter.api.Test)

Example 5 with DelegatingStoreChannel

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());
        }
    });
}
Also used : Path(java.nio.file.Path) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AdversarialFileSystemAbstraction(org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) EphemeralFileSystemAbstraction(org.neo4j.io.fs.EphemeralFileSystemAbstraction) FileSystemAbstraction(org.neo4j.io.fs.FileSystemAbstraction) SwapperSet(org.neo4j.io.pagecache.impl.muninn.SwapperSet) Set(java.util.Set) ImmutableSet(org.eclipse.collections.api.set.ImmutableSet) DelegatingStoreChannel(org.neo4j.io.fs.DelegatingStoreChannel) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) DelegatingFileSystemAbstraction(org.neo4j.io.fs.DelegatingFileSystemAbstraction) ByteBuffer(java.nio.ByteBuffer) RepeatedTest(org.junit.jupiter.api.RepeatedTest) Test(org.junit.jupiter.api.Test)

Aggregations

Path (java.nio.file.Path)10 DelegatingFileSystemAbstraction (org.neo4j.io.fs.DelegatingFileSystemAbstraction)10 DelegatingStoreChannel (org.neo4j.io.fs.DelegatingStoreChannel)10 IOException (java.io.IOException)9 FileSystemAbstraction (org.neo4j.io.fs.FileSystemAbstraction)9 ByteBuffer (java.nio.ByteBuffer)8 Set (java.util.Set)8 Test (org.junit.jupiter.api.Test)8 UncheckedIOException (java.io.UncheckedIOException)6 ImmutableSet (org.eclipse.collections.api.set.ImmutableSet)6 RepeatedTest (org.junit.jupiter.api.RepeatedTest)6 AdversarialFileSystemAbstraction (org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction)6 EphemeralFileSystemAbstraction (org.neo4j.io.fs.EphemeralFileSystemAbstraction)6 SwapperSet (org.neo4j.io.pagecache.impl.muninn.SwapperSet)6 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 StoreChannel (org.neo4j.io.fs.StoreChannel)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 LinkedList (java.util.LinkedList)2 List (java.util.List)2 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)2