diff --git a/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveAction.java b/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveAction.java index da15bd6a41004..2a49272bf97af 100644 --- a/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveAction.java +++ b/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveAction.java @@ -38,7 +38,7 @@ public interface FileMoveAction File file(); - static FileMoveAction copyViaPageCache( File file, PageCache pageCache ) + static FileMoveAction moveViaPageCache( File file, PageCache pageCache ) { return new FileMoveAction() { @@ -83,4 +83,23 @@ public File file() } }; } + + static FileMoveAction moveViaFileSystem( File sourceFile, File sourceDirectory ) + { + return new FileMoveAction() + { + @Override + public void move( File toDir, CopyOption... copyOptions ) throws IOException + { + copyViaFileSystem( sourceFile, sourceDirectory ).move( toDir, copyOptions ); + assert sourceFile.delete() : sourceFile; + } + + @Override + public File file() + { + return sourceFile; + } + }; + } } diff --git a/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveProvider.java b/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveProvider.java index 02620d250f60d..3070e03fe18e0 100644 --- a/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveProvider.java +++ b/enterprise/com/src/main/java/org/neo4j/com/storecopy/FileMoveProvider.java @@ -126,7 +126,7 @@ private Stream expandTraverseFiles( File dir, File basePath ) File base = basePath; // Capture effectively-final base path snapshot. Stream files = listing.stream().filter( this::isFile ); Stream dirs = listing.stream().filter( this::isDirectory ); - Stream moveFiles = files.map( f -> copyFileCorrectly( f, base ) ); + Stream moveFiles = files.map( f -> moveFileCorrectly( f, base ) ); Stream traverseDirectories = dirs.flatMap( d -> traverseForMoving( d, base ) ); return Stream.concat( moveFiles, traverseDirectories ); } @@ -168,15 +168,14 @@ private List listFiles( File dir ) /** * Some files are handled via page cache for CAPI flash, others are only used on the default file system. This - * contains the logic for handling files between - * the 2 systems + * contains the logic for handling files between the 2 systems */ - private FileMoveAction copyFileCorrectly( File fileToMove, File basePath ) + private FileMoveAction moveFileCorrectly( File fileToMove, File basePath ) { if ( fileMoveActionInformer.shouldBeManagedByPageCache( fileToMove.getName() ) ) { - return FileMoveAction.copyViaPageCache( fileToMove, pageCache ); + return FileMoveAction.moveViaPageCache( fileToMove, pageCache ); } - return FileMoveAction.copyViaFileSystem( fileToMove, basePath ); + return FileMoveAction.moveViaFileSystem( fileToMove, basePath ); } } diff --git a/enterprise/com/src/main/java/org/neo4j/com/storecopy/ToFileStoreWriter.java b/enterprise/com/src/main/java/org/neo4j/com/storecopy/ToFileStoreWriter.java index f3f52c1567030..19083fb5c123f 100644 --- a/enterprise/com/src/main/java/org/neo4j/com/storecopy/ToFileStoreWriter.java +++ b/enterprise/com/src/main/java/org/neo4j/com/storecopy/ToFileStoreWriter.java @@ -103,7 +103,7 @@ public long write( String path, ReadableByteChannel data, ByteBuffer temporaryBu // the page cache later on when we want to move the files written through the page cache. private void addPageCacheMoveAction( File file ) { - fileMoveActions.add( FileMoveAction.copyViaPageCache( file, pageCache ) ); + fileMoveActions.add( FileMoveAction.moveViaPageCache( file, pageCache ) ); } private int filePageSize( int alignment ) diff --git a/enterprise/com/src/test/java/org/neo4j/com/storecopy/FileMoveActionTest.java b/enterprise/com/src/test/java/org/neo4j/com/storecopy/FileMoveActionTest.java new file mode 100644 index 0000000000000..6629e8305a8c7 --- /dev/null +++ b/enterprise/com/src/test/java/org/neo4j/com/storecopy/FileMoveActionTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j Enterprise Edition. The included source + * code can be redistributed and/or modified under the terms of the + * GNU AFFERO GENERAL PUBLIC LICENSE Version 3 + * (http://www.fsf.org/licensing/licenses/agpl-3.0.html) with the + * Commons Clause, as found in the associated LICENSE.txt file. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * Neo4j object code can be licensed independently from the source + * under separate terms from the AGPL. Inquiries can be directed to: + * licensing@neo4j.com + * + * More information is also available at: + * https://neo4j.com/licensing/ + */ +package org.neo4j.com.storecopy; + +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.StandardOpenOption; + +import org.neo4j.io.fs.DefaultFileSystemAbstraction; +import org.neo4j.io.fs.FileSystemAbstraction; +import org.neo4j.io.pagecache.PageCache; +import org.neo4j.io.pagecache.PagedFile; +import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.pagecache.ConfigurableStandalonePageCacheFactory; +import org.neo4j.test.rule.TestDirectory; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class FileMoveActionTest +{ + @Rule + public final TestDirectory testDirectory = TestDirectory.testDirectory(); + + private FileSystemAbstraction fileSystemAbstraction = new DefaultFileSystemAbstraction(); + private Config config = Config.defaults(); + + @Test + public void pageCacheFilesMovedDoNotLeaveOriginal() throws IOException + { + // given + PageCache pageCache = aPageCache(); + + // and + File pageCacheFile = testDirectory.file( "page-cache-file" ); + PagedFile pagedFile = pageCache.map( pageCacheFile, 100, StandardOpenOption.CREATE ); + + // when + File targetRename = testDirectory.file( "destination" ); + FileMoveAction action = FileMoveAction.moveViaPageCache( pageCacheFile, pageCache ); + pagedFile.close(); + action.move( targetRename ); + + // then + assertFalse( pageCacheFile.exists() ); + assertTrue( targetRename.exists() ); + } + + @Test + public void nonPageCacheFilesMovedDoNotLeaveOriginal() throws IOException + { + // given + File baseDirectory = testDirectory.directory(); + File sourceDirectory = new File( baseDirectory, "source" ); + File targetDirectory = new File( baseDirectory, "destination" ); + File sourceFile = new File( sourceDirectory, "theFileName" ); + File targetFile = new File( targetDirectory, "theFileName" ); + sourceFile.getParentFile().mkdirs(); + targetDirectory.mkdirs(); + + // and sanity check + assertTrue( sourceFile.createNewFile() ); + assertTrue( sourceFile.exists() ); + assertFalse( targetFile.exists() ); + + // when + FileMoveAction.moveViaFileSystem( sourceFile, sourceDirectory ).move( targetDirectory ); + + // then + assertTrue( targetFile.exists() ); + assertFalse( sourceFile.exists() ); + } + + @Test + public void nonPageCacheFilesCopiedLeaveOriginal() throws IOException + { + // given + File baseDirectory = testDirectory.directory(); + File sourceDirectory = new File( baseDirectory, "source" ); + File targetDirectory = new File( baseDirectory, "destination" ); + File sourceFile = new File( sourceDirectory, "theFileName" ); + File targetFile = new File( targetDirectory, "theFileName" ); + sourceFile.getParentFile().mkdirs(); + targetDirectory.mkdirs(); + + // and sanity check + assertTrue( sourceFile.createNewFile() ); + assertTrue( sourceFile.exists() ); + assertFalse( targetFile.exists() ); + + // when + FileMoveAction.copyViaFileSystem( sourceFile, sourceDirectory ).move( targetDirectory ); + + // then + assertTrue( targetFile.exists() ); + assertTrue( sourceFile.exists() ); + } + + private PageCache aPageCache() + { + return ConfigurableStandalonePageCacheFactory.createPageCache( fileSystemAbstraction, config ); + } +}