From 9ffe0cafa1bfbfb53e3d132c96dcc990b6fa41c9 Mon Sep 17 00:00:00 2001 From: MishaDemianenko Date: Mon, 13 Aug 2018 12:23:26 +0200 Subject: [PATCH] Always use canonical representation in database and store layout. --- .../main/java/org/neo4j/io/fs/FileUtils.java | 8 +- .../org/neo4j/io/layout/DatabaseLayout.java | 5 +- .../java/org/neo4j/io/layout/StoreLayout.java | 4 +- .../neo4j/io/layout/DatabaseLayoutTest.java | 88 +++++++++++++++++++ .../org/neo4j/io/layout/StoreLayoutTest.java | 69 +++++++++++++++ .../java/org/neo4j/kernel/RecoveryTest.java | 1 + .../neo4j/kernel/impl/util/FileUtilsTest.java | 6 +- .../factory/module/PlatformModule.java | 8 +- .../neo4j/com/storecopy/StoreCopyServer.java | 4 +- 9 files changed, 177 insertions(+), 16 deletions(-) create mode 100644 community/io/src/test/java/org/neo4j/io/layout/DatabaseLayoutTest.java create mode 100644 community/io/src/test/java/org/neo4j/io/layout/StoreLayoutTest.java diff --git a/community/io/src/main/java/org/neo4j/io/fs/FileUtils.java b/community/io/src/main/java/org/neo4j/io/fs/FileUtils.java index 5f2cdf0e73b07..5e95b10652e13 100644 --- a/community/io/src/main/java/org/neo4j/io/fs/FileUtils.java +++ b/community/io/src/main/java/org/neo4j/io/fs/FileUtils.java @@ -36,6 +36,7 @@ import java.io.PrintStream; import java.io.PrintWriter; import java.io.RandomAccessFile; +import java.io.UncheckedIOException; import java.io.Writer; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; @@ -584,16 +585,15 @@ public static String relativePath( File baseDir, File storeFile ) return path; } - // TODO javadoc what this one does. It comes from Serverutil initially. - public static File getMostCanonicalFile( File file ) + public static File getCanonicalFile( File file ) { try { - return file.getCanonicalFile().getAbsoluteFile(); + return file.getCanonicalFile(); } catch ( IOException e ) { - return file.getAbsoluteFile(); + throw new UncheckedIOException( e ); } } diff --git a/community/io/src/main/java/org/neo4j/io/layout/DatabaseLayout.java b/community/io/src/main/java/org/neo4j/io/layout/DatabaseLayout.java index 68aafed64711c..d9d06cc6e6aae 100644 --- a/community/io/src/main/java/org/neo4j/io/layout/DatabaseLayout.java +++ b/community/io/src/main/java/org/neo4j/io/layout/DatabaseLayout.java @@ -23,6 +23,8 @@ import java.io.FilenameFilter; import java.util.Objects; +import static org.neo4j.io.fs.FileUtils.getCanonicalFile; + public class DatabaseLayout { private static final File[] EMPTY_FILES_ARRAY = new File[0]; @@ -37,7 +39,8 @@ public static DatabaseLayout of( StoreLayout storeLayout, String databaseName ) public static DatabaseLayout of( File databaseDirectory ) { - return of( databaseDirectory.getParentFile(), databaseDirectory.getName() ); + File canonicalFile = getCanonicalFile( databaseDirectory ); + return of( canonicalFile.getParentFile(), canonicalFile.getName() ); } public static DatabaseLayout of( File rootDirectory, String databaseName ) diff --git a/community/io/src/main/java/org/neo4j/io/layout/StoreLayout.java b/community/io/src/main/java/org/neo4j/io/layout/StoreLayout.java index 338da9338383f..e268cd4b98ee0 100644 --- a/community/io/src/main/java/org/neo4j/io/layout/StoreLayout.java +++ b/community/io/src/main/java/org/neo4j/io/layout/StoreLayout.java @@ -22,6 +22,8 @@ import java.io.File; import java.util.Objects; +import static org.neo4j.io.fs.FileUtils.getCanonicalFile; + public class StoreLayout { private static final String STORE_LOCK_FILENAME = "store_lock"; @@ -30,7 +32,7 @@ public class StoreLayout public static StoreLayout of( File storeDirectory ) { - return new StoreLayout( storeDirectory ); + return new StoreLayout( getCanonicalFile( storeDirectory ) ); } private StoreLayout( File rootStoreDirectory ) diff --git a/community/io/src/test/java/org/neo4j/io/layout/DatabaseLayoutTest.java b/community/io/src/test/java/org/neo4j/io/layout/DatabaseLayoutTest.java new file mode 100644 index 0000000000000..31867bfeb8c46 --- /dev/null +++ b/community/io/src/test/java/org/neo4j/io/layout/DatabaseLayoutTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.io.layout; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.neo4j.test.extension.Inject; +import org.neo4j.test.extension.TestDirectoryExtension; +import org.neo4j.test.rule.TestDirectory; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith( TestDirectoryExtension.class ) +class DatabaseLayoutTest +{ + @Inject + private TestDirectory testDirectory; + + @Test + void databaseLayoutForAbsoluteFile() + { + File databaseDir = testDirectory.databaseDir(); + DatabaseLayout databaseLayout = DatabaseLayout.of( databaseDir ); + assertEquals( databaseLayout.databaseDirectory(), databaseDir ); + } + + @Test + void databaseLayoutResolvesLinks() throws IOException + { + Path basePath = testDirectory.directory().toPath(); + File databaseDir = testDirectory.databaseDir("notAbsolute"); + Path linkPath = basePath.resolve( "link" ); + Path symbolicLink = Files.createSymbolicLink( linkPath, databaseDir.toPath() ); + DatabaseLayout databaseLayout = DatabaseLayout.of( symbolicLink.toFile() ); + assertEquals( databaseLayout.databaseDirectory(), databaseDir ); + } + + @Test + void databaseLayoutUseCanonicalRepresentation() + { + File storeDir = testDirectory.storeDir( "notCanonical" ); + Path basePath = testDirectory.databaseDir( storeDir ).toPath(); + Path notCanonicalPath = basePath.resolve( "../anotherDatabase" ); + DatabaseLayout databaseLayout = DatabaseLayout.of( notCanonicalPath.toFile() ); + File expectedDirectory = StoreLayout.of( storeDir ).databaseLayout( "anotherDatabase" ).databaseDirectory(); + assertEquals( expectedDirectory, databaseLayout.databaseDirectory() ); + } + + @Test + void databaseLayoutForName() + { + String databaseName = "testDatabase"; + StoreLayout storeLayout = testDirectory.storeLayout(); + DatabaseLayout testDatabase = DatabaseLayout.of( storeLayout, databaseName ); + assertEquals( new File( storeLayout.storeDirectory(), databaseName ), testDatabase.databaseDirectory() ); + } + + @Test + void databaseLayoutForFolderAndName() + { + String database = "database"; + DatabaseLayout databaseLayout = DatabaseLayout.of( testDirectory.storeDir(), database ); + assertEquals( testDirectory.databaseLayout( database ).databaseDirectory(), databaseLayout.databaseDirectory() ); + } +} diff --git a/community/io/src/test/java/org/neo4j/io/layout/StoreLayoutTest.java b/community/io/src/test/java/org/neo4j/io/layout/StoreLayoutTest.java new file mode 100644 index 0000000000000..3c5ab2c5230b1 --- /dev/null +++ b/community/io/src/test/java/org/neo4j/io/layout/StoreLayoutTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.io.layout; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.neo4j.test.extension.Inject; +import org.neo4j.test.extension.TestDirectoryExtension; +import org.neo4j.test.rule.TestDirectory; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith( TestDirectoryExtension.class ) +class StoreLayoutTest +{ + @Inject + private TestDirectory testDirectory; + + @Test + void storeLayoutForAbsoluteFile() + { + File storeDir = testDirectory.storeDir(); + StoreLayout storeLayout = StoreLayout.of( storeDir ); + assertEquals( storeDir, storeLayout.storeDirectory() ); + } + + @Test + void storeLayoutResolvesLinks() throws IOException + { + Path basePath = testDirectory.directory().toPath(); + File storeDir = testDirectory.storeDir("notAbsolute"); + Path linkPath = basePath.resolve( "link" ); + Path symbolicLink = Files.createSymbolicLink( linkPath, storeDir.toPath() ); + StoreLayout storeLayout = StoreLayout.of( symbolicLink.toFile() ); + assertEquals( storeDir, storeLayout.storeDirectory() ); + } + + @Test + void storeLayoutUseCanonicalRepresentation() + { + Path basePath = testDirectory.storeDir("notCanonical").toPath(); + Path notCanonicalPath = basePath.resolve( "../anotherLocation" ); + StoreLayout storeLayout = StoreLayout.of( notCanonicalPath.toFile() ); + assertEquals( testDirectory.directory( "anotherLocation" ), storeLayout.storeDirectory() ); + } +} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/RecoveryTest.java b/community/kernel/src/test/java/org/neo4j/kernel/RecoveryTest.java index d884628db0261..93114ecdddcf1 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/RecoveryTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/RecoveryTest.java @@ -109,6 +109,7 @@ public class RecoveryTest @Before public void setUp() throws Exception { + storeDir = directory.storeDir(); logFiles = LogFilesBuilder.builder( directory.databaseLayout(), fileSystemRule.get() ) .withLogVersionRepository( logVersionRepository ) .withTransactionIdStore( transactionIdStore ) diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/FileUtilsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/FileUtilsTest.java index 507303547eed6..0f4b355e13898 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/FileUtilsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/FileUtilsTest.java @@ -47,9 +47,9 @@ public class FileUtilsTest { - public TestDirectory testDirectory = TestDirectory.testDirectory(); - public ExpectedException expected = ExpectedException.none(); - public FileSystemAbstraction fs = new DefaultFileSystemAbstraction(); + public final TestDirectory testDirectory = TestDirectory.testDirectory(); + public final ExpectedException expected = ExpectedException.none(); + public final FileSystemAbstraction fs = new DefaultFileSystemAbstraction(); @Rule public RuleChain chain = RuleChain.outerRule( testDirectory ).around( expected ); diff --git a/community/neo4j/src/main/java/org/neo4j/graphdb/factory/module/PlatformModule.java b/community/neo4j/src/main/java/org/neo4j/graphdb/factory/module/PlatformModule.java index a702379111a12..1590a2f4e5002 100644 --- a/community/neo4j/src/main/java/org/neo4j/graphdb/factory/module/PlatformModule.java +++ b/community/neo4j/src/main/java/org/neo4j/graphdb/factory/module/PlatformModule.java @@ -150,14 +150,12 @@ public PlatformModule( File providedStoreDir, Config config, DatabaseInfo databa dependencies.satisfyDependency( databaseInfo ); clock = dependencies.satisfyDependency( createClock() ); - life = dependencies.satisfyDependency( createLife() ); - // SPI - provided services - config.augmentDefaults( GraphDatabaseSettings.neo4j_home, providedStoreDir.getAbsolutePath() ); - this.config = dependencies.satisfyDependency( config ); + this.storeLayout = StoreLayout.of( providedStoreDir ); - this.storeLayout = StoreLayout.of( providedStoreDir.getAbsoluteFile() ); + config.augmentDefaults( GraphDatabaseSettings.neo4j_home, storeLayout.storeDirectory().getPath() ); + this.config = dependencies.satisfyDependency( config ); fileSystem = dependencies.satisfyDependency( createFileSystemAbstraction() ); life.add( new FileSystemLifecycleAdapter( fileSystem ) ); diff --git a/enterprise/com/src/main/java/org/neo4j/com/storecopy/StoreCopyServer.java b/enterprise/com/src/main/java/org/neo4j/com/storecopy/StoreCopyServer.java index d93e5fa077f99..eb1e3eae0f6b9 100644 --- a/enterprise/com/src/main/java/org/neo4j/com/storecopy/StoreCopyServer.java +++ b/enterprise/com/src/main/java/org/neo4j/com/storecopy/StoreCopyServer.java @@ -43,7 +43,7 @@ import org.neo4j.storageengine.api.StoreFileMetadata; import static org.neo4j.com.RequestContext.anonymous; -import static org.neo4j.io.fs.FileUtils.getMostCanonicalFile; +import static org.neo4j.io.fs.FileUtils.getCanonicalFile; import static org.neo4j.io.fs.FileUtils.relativePath; /** @@ -128,7 +128,7 @@ public StoreCopyServer( NeoStoreDataSource dataSource, CheckPointer checkPointer this.dataSource = dataSource; this.checkPointer = checkPointer; this.fileSystem = fileSystem; - this.databaseDirectory = getMostCanonicalFile( databaseDirectory ); + this.databaseDirectory = getCanonicalFile( databaseDirectory ); this.monitor = monitor; }