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 + { + + } } }