From 12494dafd3cc53af9cbf0f4ab31dd9cab4b6cfe4 Mon Sep 17 00:00:00 2001 From: Davide Grohmann Date: Mon, 10 Aug 2015 14:59:39 +0200 Subject: [PATCH] Truncate the counts store file before writing new values This should fix a problem during counts store rotation when the counts store file is partially written but it cannot be recognized as corrupted. Hence it will be loaded on the next recovery and lead to inconsistencies. --- .../io/fs/DefaultFileSystemAbstraction.java | 6 + .../neo4j/io/fs/FileSystemAbstraction.java | 34 +++--- .../fs/AdversarialFileSystemAbstraction.java | 8 ++ .../DelegatingFileSystemAbstraction.java | 6 + .../EphemeralFileSystemAbstraction.java | 11 ++ .../mockfs/LimitedFilesystemAbstraction.java | 22 ++-- .../kvstore/KeyValueStoreFileFormat.java | 6 + .../impl/store/kvstore/KeyValueWriter.java | 12 +- .../BreakableFileSystemAbstraction.java | 5 + .../kernel/CannedFileSystemAbstraction.java | 22 ++-- .../core/JumpingFileSystemAbstraction.java | 50 ++++---- .../kvstore/KeyValueStoreFileFormatTest.java | 112 +++++++++++++++++- .../store/kvstore/KeyValueWriterTest.java | 14 ++- .../java/org/neo4j/com/ServerUtilTest.java | 6 + 14 files changed, 246 insertions(+), 68 deletions(-) diff --git a/community/io/src/main/java/org/neo4j/io/fs/DefaultFileSystemAbstraction.java b/community/io/src/main/java/org/neo4j/io/fs/DefaultFileSystemAbstraction.java index b63cf5551d4ed..9622a2865bb38 100644 --- a/community/io/src/main/java/org/neo4j/io/fs/DefaultFileSystemAbstraction.java +++ b/community/io/src/main/java/org/neo4j/io/fs/DefaultFileSystemAbstraction.java @@ -195,4 +195,10 @@ public synchronized K getOrCreateThirdPartyFile } return clazz.cast( fileSystem ); } + + @Override + public void truncate( File path, long size ) throws IOException + { + FileUtils.truncateFile( path, size ); + } } diff --git a/community/io/src/main/java/org/neo4j/io/fs/FileSystemAbstraction.java b/community/io/src/main/java/org/neo4j/io/fs/FileSystemAbstraction.java index 97f7b6034b261..2ca54092e13dd 100644 --- a/community/io/src/main/java/org/neo4j/io/fs/FileSystemAbstraction.java +++ b/community/io/src/main/java/org/neo4j/io/fs/FileSystemAbstraction.java @@ -33,47 +33,49 @@ public interface FileSystemAbstraction { StoreChannel open( File fileName, String mode ) throws IOException; - + OutputStream openAsOutputStream( File fileName, boolean append ) throws IOException; - + InputStream openAsInputStream( File fileName ) throws IOException; - + Reader openAsReader( File fileName, String encoding ) throws IOException; - + Writer openAsWriter( File fileName, String encoding, boolean append ) throws IOException; - + FileLock tryLock( File fileName, StoreChannel channel ) throws IOException; - + StoreChannel create( File fileName ) throws IOException; - + boolean fileExists( File fileName ); - + boolean mkdir( File fileName ); - + void mkdirs( File fileName ) throws IOException; - + long getFileSize( File fileName ); boolean deleteFile( File fileName ); - + void deleteRecursively( File directory ) throws IOException; - + boolean renameFile( File from, File to ) throws IOException; - + File[] listFiles( File directory ); File[] listFiles( File directory, FilenameFilter filter ); boolean isDirectory( File file ); - + void moveToDirectory( File file, File toDirectory ) throws IOException; - + void copyFile( File from, File to ) throws IOException; - + void copyRecursively( File fromDirectory, File toDirectory ) throws IOException; K getOrCreateThirdPartyFileSystem( Class clazz, Function, K> creator ); + void truncate( File path, long size ) throws IOException; + interface ThirdPartyFileSystem { void close(); diff --git a/community/io/src/test/java/org/neo4j/adversaries/fs/AdversarialFileSystemAbstraction.java b/community/io/src/test/java/org/neo4j/adversaries/fs/AdversarialFileSystemAbstraction.java index 1abe3467badca..7903c6865f5dc 100644 --- a/community/io/src/test/java/org/neo4j/adversaries/fs/AdversarialFileSystemAbstraction.java +++ b/community/io/src/test/java/org/neo4j/adversaries/fs/AdversarialFileSystemAbstraction.java @@ -203,6 +203,14 @@ public synchronized K getOrCreateThirdPartyFile return (K) fileSystem; } + @Override + public void truncate( File path, long size ) throws IOException + { + adversary.injectFailure( FileNotFoundException.class, IOException.class, IllegalArgumentException.class, + SecurityException.class, NullPointerException.class ); + delegate.truncate( path, size ); + } + private ThirdPartyFileSystem adversarialProxy( final ThirdPartyFileSystem fileSystem, Class clazz ) diff --git a/community/io/src/test/java/org/neo4j/graphdb/mockfs/DelegatingFileSystemAbstraction.java b/community/io/src/test/java/org/neo4j/graphdb/mockfs/DelegatingFileSystemAbstraction.java index 2c1dd99596082..40f465c0bc4fc 100644 --- a/community/io/src/test/java/org/neo4j/graphdb/mockfs/DelegatingFileSystemAbstraction.java +++ b/community/io/src/test/java/org/neo4j/graphdb/mockfs/DelegatingFileSystemAbstraction.java @@ -72,6 +72,12 @@ public K getOrCreateThird return delegate.getOrCreateThirdPartyFileSystem( clazz, creator ); } + @Override + public void truncate( File path, long size ) throws IOException + { + delegate.truncate( path, size ); + } + @Override public boolean renameFile( File from, File to ) throws IOException { diff --git a/community/io/src/test/java/org/neo4j/graphdb/mockfs/EphemeralFileSystemAbstraction.java b/community/io/src/test/java/org/neo4j/graphdb/mockfs/EphemeralFileSystemAbstraction.java index 0dced9e579a8c..40b492e75e42a 100644 --- a/community/io/src/test/java/org/neo4j/graphdb/mockfs/EphemeralFileSystemAbstraction.java +++ b/community/io/src/test/java/org/neo4j/graphdb/mockfs/EphemeralFileSystemAbstraction.java @@ -569,6 +569,17 @@ public synchronized K getOrCreateThirdPartyFile return clazz.cast( fileSystem ); } + @Override + public void truncate( File file, long size ) throws IOException + { + EphemeralFileData data = files.get( file ); + if ( data == null ) + { + throw new FileNotFoundException( "File " + file + " not found" ); + } + data.truncate( size ); + } + @SuppressWarnings( "serial" ) private static class FileStillOpenException extends Exception { diff --git a/community/io/src/test/java/org/neo4j/graphdb/mockfs/LimitedFilesystemAbstraction.java b/community/io/src/test/java/org/neo4j/graphdb/mockfs/LimitedFilesystemAbstraction.java index dadfefec9afad..928c43b37fe36 100644 --- a/community/io/src/test/java/org/neo4j/graphdb/mockfs/LimitedFilesystemAbstraction.java +++ b/community/io/src/test/java/org/neo4j/graphdb/mockfs/LimitedFilesystemAbstraction.java @@ -51,7 +51,7 @@ public StoreChannel open( File fileName, String mode ) throws IOException { return new LimitedFileChannel( inner.open( fileName, mode ), this ); } - + @Override public OutputStream openAsOutputStream( File fileName, boolean append ) throws IOException { @@ -69,7 +69,7 @@ public Reader openAsReader( File fileName, String encoding ) throws IOException { return new InputStreamReader( openAsInputStream( fileName ), encoding ); } - + @Override public Writer openAsWriter( File fileName, String encoding, boolean append ) throws IOException { @@ -106,7 +106,7 @@ public boolean deleteFile( File fileName ) { return inner.deleteFile( fileName ); } - + @Override public void deleteRecursively( File directory ) throws IOException { @@ -118,7 +118,7 @@ public boolean mkdir( File fileName ) { return inner.mkdir( fileName ); } - + @Override public void mkdirs( File fileName ) throws IOException { @@ -157,25 +157,25 @@ public File[] listFiles( File directory, FilenameFilter filter ) { return inner.listFiles( directory, filter ); } - + @Override public boolean isDirectory( File file ) { return inner.isDirectory( file ); } - + @Override public void moveToDirectory( File file, File toDirectory ) throws IOException { inner.moveToDirectory( file, toDirectory ); } - + @Override public void copyFile( File from, File to ) throws IOException { inner.copyFile( from, to ); } - + @Override public void copyRecursively( File fromDirectory, File toDirectory ) throws IOException { @@ -188,4 +188,10 @@ public K getOrCreateThirdPartyFileSystem( { return inner.getOrCreateThirdPartyFileSystem( clazz, creator ); } + + @Override + public void truncate( File path, long size ) throws IOException + { + inner.truncate( path, size ); + } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormat.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormat.java index d3e412d319c48..565c86ab51575 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormat.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormat.java @@ -146,6 +146,12 @@ private KeyValueStoreFile create( "Invalid sizes: keySize=%d, valueSize=%d, format maxSize=%d", keySize, valueSize, maxSize ) ); } + + if ( fs.fileExists( path ) ) + { + fs.truncate( path, 0 ); + } + BigEndianByteArrayBuffer key = new BigEndianByteArrayBuffer( new byte[keySize] ); BigEndianByteArrayBuffer value = new BigEndianByteArrayBuffer( new byte[valueSize] ); writeFormatSpecifier( value ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriter.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriter.java index 28a93f4a23778..4b3efa8005ed5 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriter.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriter.java @@ -265,11 +265,7 @@ static abstract class Writer abstract void close() throws IOException; - void writeTrailer( String trailer ) throws IOException - { - write( UTF8.encode( trailer ) ); - } - + abstract void writeTrailer( String trailer ) throws IOException; static Writer create( FileSystemAbstraction fs, PageCache pages, File path, int pageSize ) throws IOException { if ( pages == null ) @@ -302,6 +298,12 @@ void write( byte[] data ) throws IOException out.write( data ); } + @Override + void writeTrailer( String trailer ) throws IOException + { + write( UTF8.encode( trailer ) ); + } + @Override KeyValueStoreFile open( Metadata metadata, int keySize, int valueSize ) throws IOException { diff --git a/community/kernel/src/test/java/org/neo4j/graphdb/mockfs/BreakableFileSystemAbstraction.java b/community/kernel/src/test/java/org/neo4j/graphdb/mockfs/BreakableFileSystemAbstraction.java index 7b2ebcb31f446..98364ecd9e9e0 100644 --- a/community/kernel/src/test/java/org/neo4j/graphdb/mockfs/BreakableFileSystemAbstraction.java +++ b/community/kernel/src/test/java/org/neo4j/graphdb/mockfs/BreakableFileSystemAbstraction.java @@ -186,4 +186,9 @@ public K getOrCreateThirdPartyFileSystem( Class return inner.getOrCreateThirdPartyFileSystem( clazz, creator ); } + @Override + public void truncate( File path, long size ) throws IOException + { + inner.truncate( path, size ); + } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/CannedFileSystemAbstraction.java b/community/kernel/src/test/java/org/neo4j/kernel/CannedFileSystemAbstraction.java index 0e0fbf90d7b5e..e84beac32cb67 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/CannedFileSystemAbstraction.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/CannedFileSystemAbstraction.java @@ -44,7 +44,7 @@ public void run() { } }; - + public static Runnable callCounter( final AtomicInteger count ) { return new Runnable() @@ -56,7 +56,7 @@ public void run() } }; } - + private final boolean fileExists; private final IOException cannotCreateStoreDir; private final IOException cannotOpenLockFile; @@ -86,7 +86,7 @@ public StoreChannel open( File fileName, String mode ) throws IOException return emptyFileChannel; } - + private final StoreChannel emptyFileChannel = new AbstractStoreChannel() { @Override @@ -153,7 +153,7 @@ public void close() throws IOException { onClose.run(); } - + private IOException unsupported() { return new IOException( "Unsupported" ); @@ -177,7 +177,7 @@ public Reader openAsReader( File fileName, String encoding ) throws IOException { throw new UnsupportedOperationException( "TODO" ); } - + @Override public Writer openAsWriter( File fileName, String encoding, boolean append ) throws IOException { @@ -191,7 +191,7 @@ public FileLock tryLock( File fileName, StoreChannel channel ) throws IOExceptio { throw new IOException( "Unable to create lock file " + fileName ); } - + return SYMBOLIC_FILE_LOCK; } @@ -262,7 +262,7 @@ public File[] listFiles( File directory, FilenameFilter filter ) { return new File[0]; } - + @Override public void moveToDirectory( File file, File toDirectory ) throws IOException { @@ -274,7 +274,7 @@ public void copyFile( File file, File toDirectory ) throws IOException { throw new UnsupportedOperationException( "TODO" ); } - + @Override public void copyRecursively( File fromDirectory, File toDirectory ) throws IOException { @@ -288,6 +288,12 @@ public K getOrCreateThirdPartyFileSystem( Class throw new UnsupportedOperationException( "not implemented" ); } + @Override + public void truncate( File path, long size ) throws IOException + { + throw new UnsupportedOperationException( "TODO" ); + } + private static final FileLock SYMBOLIC_FILE_LOCK = new FileLock() { @Override diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/core/JumpingFileSystemAbstraction.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/core/JumpingFileSystemAbstraction.java index 7efa211452165..25aa54ca138f8 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/core/JumpingFileSystemAbstraction.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/core/JumpingFileSystemAbstraction.java @@ -56,7 +56,7 @@ public JumpingFileSystemAbstraction( int sizePerJump ) { this.sizePerJump = sizePerJump; } - + @Override public StoreChannel open( File fileName, String mode ) throws IOException { @@ -69,18 +69,18 @@ public StoreChannel open( File fileName, String mode ) throws IOException fileName.getName().equals( "neostore.propertystore.db.strings" ) || fileName.getName().equals( "neostore.propertystore.db.arrays" ) || fileName.getName().equals( "neostore.relationshipgroupstore.db" ) ) - { + { return new JumpingFileChannel( channel, recordSizeFor( fileName ) ); } return channel; } - + @Override public OutputStream openAsOutputStream( File fileName, boolean append ) throws IOException { return new ChannelOutputStream( open( fileName, "rw" ), append ); } - + @Override public InputStream openAsInputStream( File fileName ) throws IOException { @@ -92,7 +92,7 @@ public Reader openAsReader( File fileName, String encoding ) throws IOException { return new InputStreamReader( openAsInputStream( fileName ), encoding ); } - + @Override public Writer openAsWriter( File fileName, String encoding, boolean append ) throws IOException { @@ -104,43 +104,43 @@ public StoreChannel create( File fileName ) throws IOException { return open( fileName, "rw" ); } - + @Override public boolean fileExists( File fileName ) { return actualFileSystem.fileExists( fileName ); } - + @Override public long getFileSize( File fileName ) { return actualFileSystem.getFileSize( fileName ); } - + @Override public boolean deleteFile( File fileName ) { return actualFileSystem.deleteFile( fileName ); } - + @Override public void deleteRecursively( File directory ) throws IOException { actualFileSystem.deleteRecursively( directory ); } - + @Override public boolean mkdir( File fileName ) { return actualFileSystem.mkdir( fileName ); } - + @Override public void mkdirs( File fileName ) { actualFileSystem.mkdirs( fileName ); } - + @Override public boolean renameFile( File from, File to ) throws IOException { @@ -152,7 +152,7 @@ public FileLock tryLock( File fileName, StoreChannel channel ) throws IOExceptio { return actualFileSystem.tryLock( fileName, channel ); } - + @Override public File[] listFiles( File directory ) { @@ -164,31 +164,31 @@ public File[] listFiles( File directory, FilenameFilter filter ) { return actualFileSystem.listFiles( directory, filter ); } - + @Override public boolean isDirectory( File file ) { return actualFileSystem.isDirectory( file ); } - + @Override public void moveToDirectory( File file, File toDirectory ) throws IOException { actualFileSystem.moveToDirectory( file, toDirectory ); } - + @Override public void copyFile( File from, File to ) throws IOException { actualFileSystem.copyFile( from, to ); } - + @Override public void copyRecursively( File fromDirectory, File toDirectory ) throws IOException { actualFileSystem.copyRecursively( fromDirectory, toDirectory ); } - + private int recordSizeFor( File fileName ) { if ( fileName.getName().endsWith( "nodestore.db" ) ) @@ -223,17 +223,17 @@ else if ( fileName.getName().endsWith( "relationshipgroupstore.db" ) ) } throw new IllegalArgumentException( fileName.getPath() ); } - + public class JumpingFileChannel extends StoreFileChannel { private final int recordSize; - + public JumpingFileChannel( StoreFileChannel actual, int recordSize ) { super( actual ); this.recordSize = recordSize; } - + private long translateIncoming( long position ) { return translateIncoming( position, false ); @@ -255,7 +255,7 @@ private long translateIncoming( long position, boolean allowFix ) return offsettedRecord*recordSize; } } - + private long translateOutgoing( long offsettedPosition ) { long offsettedRecord = offsettedPosition/recordSize; @@ -341,6 +341,12 @@ public K getOrCreateThirdPartyFileSystem( return actualFileSystem.getOrCreateThirdPartyFileSystem( clazz, creator ); } + @Override + public void truncate( File path, long size ) throws IOException + { + actualFileSystem.truncate( path, size ); + } + @Override public void shutdown() { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormatTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormatTest.java index c41a9452bb37b..f3e3a97a22f11 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormatTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueStoreFileFormatTest.java @@ -19,8 +19,13 @@ */ package org.neo4j.kernel.impl.store.kvstore; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -28,12 +33,9 @@ import java.util.List; import java.util.Map; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.Pair; +import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.configuration.Config; import org.neo4j.test.EphemeralFileSystemRule; import org.neo4j.test.PageCacheRule; @@ -43,7 +45,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - import static org.neo4j.kernel.impl.store.kvstore.KeyValueStoreFileFormatTest.Data.data; import static org.neo4j.kernel.impl.store.kvstore.KeyValueStoreFileFormatTest.DataEntry.entry; import static org.neo4j.test.ResourceRule.testPath; @@ -258,6 +259,105 @@ public void shouldNotFindAnythingWhenSearchKeyIsAfterTheLastKey() throws Excepti } } + @Test + public void shouldTruncateTheFile() throws Exception + { + Map config = new HashMap<>(); + config.put( GraphDatabaseSettings.pagecache_memory.name(), "8M" ); + config.put( GraphDatabaseSettings.mapped_memory_page_size.name(), "128" ); + + // given a well written file + { + Format format = new Format( "one", "two" ); + Map headers = new HashMap<>(); + headers.put( "one", new byte[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,} ); + headers.put( "two", new byte[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,} ); + + + Data data = data( // two full pages (and nothing more) + // page 0 + entry( bytes( 12 ), bytes( 'v', 'a', 'l', 1 ) ), + entry( bytes( 13 ), bytes( 'v', 'a', 'l', 2 ) ), + // page 1 + entry( bytes( 15 ), bytes( 'v', 'a', 'l', 3 ) ), + entry( bytes( 16 ), bytes( 'v', 'a', 'l', 4 ) ), + entry( bytes( 17 ), bytes( 'v', 'a', 'l', 5 ) ), + entry( bytes( 18 ), bytes( 'v', 'a', 'l', 6 ) ) ); + + try ( KeyValueStoreFile ignored = format.create( config, headers, data ) ) + { + } + } + + + { + // when failing on creating the next version of that file + Format format = new Format( "three", "four" ); + Map headers = new HashMap<>(); + headers.put( "three", new byte[]{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,} ); + headers.put( "four", new byte[]{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,} ); + + DataProvider data = new DataProvider() + { + @Override + public void close() throws IOException + { + } + @Override + public boolean visit( WritableBuffer key, WritableBuffer value ) throws IOException + { + throw new IOException( "boom!" ); + } + }; + + try ( KeyValueStoreFile ignored = format.create( config, headers, data ) ) + { + } + catch ( IOException io ) + { + // then only headers are present in the file and not the old content + assertEquals( "boom!", io.getMessage() ); + assertFormatSpecifierAndHeadersOnly( headers, fs.get(), storeFile.get() ); + } + } + } + + private void assertFormatSpecifierAndHeadersOnly( Map headers, FileSystemAbstraction fs, File file ) + throws IOException + { + assertTrue( fs.fileExists( file ) ); + try( InputStream stream = fs.openAsInputStream( file ) ) + { + // format specifier + int read; + int size = 16; + byte[] readEntry = new byte[size]; + byte[] allZeros = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + read = stream.read( readEntry ); + assertEquals( size, read ); + assertArrayEquals( allZeros, readEntry ); + + read = stream.read( readEntry ); + assertEquals( size, read ); + assertArrayEquals( new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, readEntry ); + + for ( Map.Entry entry : headers.entrySet() ) + { + read = stream.read( readEntry ); + assertEquals( size, read ); + assertArrayEquals( allZeros, readEntry ); + + read = stream.read( readEntry ); + assertEquals( size, read ); + assertArrayEquals( entry.getValue(), readEntry ); + } + + assertEquals( -1, stream.read() ); + } + + } + private static void assertFind( KeyValueStoreFile file, int min, int max, boolean exact, Bytes... expected ) throws IOException { @@ -569,4 +669,4 @@ static Map noHeaders() { return Collections.emptyMap(); } -} \ No newline at end of file +} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriterTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriterTest.java index 5e9817f293fbd..9aba5267ea5a0 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriterTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/kvstore/KeyValueWriterTest.java @@ -19,11 +19,13 @@ */ package org.neo4j.kernel.impl.store.kvstore; +import org.junit.After; +import org.junit.Test; + import java.io.ByteArrayOutputStream; import java.io.IOException; -import org.junit.After; -import org.junit.Test; +import org.neo4j.helpers.UTF8; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -263,6 +265,12 @@ void close() throws IOException io(); } + @Override + void writeTrailer( String trailer ) throws IOException + { + write( UTF8.encode( trailer ) ); + } + public void assertData( byte... expected ) { assertArrayEquals( expected, this.data.toByteArray() ); @@ -283,4 +291,4 @@ private void io() throws IOException } } } -} \ No newline at end of file +} diff --git a/enterprise/com/src/test/java/org/neo4j/com/ServerUtilTest.java b/enterprise/com/src/test/java/org/neo4j/com/ServerUtilTest.java index db1f01fadceaf..b168f2651bca9 100644 --- a/enterprise/com/src/test/java/org/neo4j/com/ServerUtilTest.java +++ b/enterprise/com/src/test/java/org/neo4j/com/ServerUtilTest.java @@ -426,5 +426,11 @@ public K getOrCreateThirdPartyFileSystem( { return null; } + + @Override + public void truncate( File path, long size ) throws IOException + { + + } } }