diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java index 0fa269cfa758..fff705e48756 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java @@ -244,7 +244,7 @@ public final class FSRecordsImpl implements Closeable { //bumped main version (60 -> 61) because of PFSRecords header enlargement (HEADER_ERRORS_ACCUMULATED) final int mainVFSFormatVersion = 61; //@formatter:off (nextMask better be aligned) - return nextMask(mainVFSFormatVersion + (PersistentFSRecordsStorageKind.storageImplementation().ordinal()), /* acceptable range is [0..255] */ 8, + return nextMask(mainVFSFormatVersion + (PersistentFSRecordsStorageFactory.storageImplementation().getId()), /* acceptable range is [0..255] */ 8, nextMask(!USE_CONTENT_STORAGE_OVER_MMAPPED_FILE, //former USE_CONTENT_HASHES=true, this is why negation nextMask(IOUtil.useNativeByteOrderForByteBuffers(), nextMask(PageCacheUtils.LOCK_FREE_PAGE_CACHE_ENABLED && USE_ATTRIBUTES_OVER_NEW_FILE_PAGE_CACHE,//pageSize was changed on old<->new transition diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSLoader.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSLoader.java index 2830fe9ec7fd..77a6e72b379d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSLoader.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSLoader.java @@ -777,7 +777,7 @@ public final class PersistentFSLoader { } public @NotNull PersistentFSRecordsStorage createRecordsStorage(@NotNull Path recordsFile) throws IOException { - StorageFactory recordsStorageFactory = PersistentFSRecordsStorageKind.storageImplementation(); + StorageFactory recordsStorageFactory = PersistentFSRecordsStorageFactory.storageImplementation(); LOG.trace("VFS uses " + recordsStorageFactory + " storage for main file records table"); return recordsStorageFactory.wrapStorageSafely(recordsFile, records -> { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageKind.kt b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageFactory.kt similarity index 62% rename from platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageKind.kt rename to platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageFactory.kt index 650eaa7c08c5..a4a1cccdee91 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageKind.kt +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageFactory.kt @@ -8,29 +8,39 @@ import com.intellij.util.io.StorageLockContext import com.intellij.util.io.dev.StorageFactory import com.intellij.util.io.dev.mmapped.MMappedFileStorageFactory import com.intellij.util.io.pagecache.impl.PageContentLockingStrategy +import org.jetbrains.annotations.ApiStatus.Internal import org.jetbrains.annotations.VisibleForTesting import java.io.IOException import java.nio.file.Path -enum class PersistentFSRecordsStorageKind : StorageFactory { +@Internal +abstract class PersistentFSRecordsStorageFactory(val id: Int) : StorageFactory { + /** Currently the default impl */ - OVER_MMAPPED_FILE { + data class OverMMappedFile(val pageSize: Int = PersistentFSRecordsLockFreeOverMMappedFile.DEFAULT_MAPPED_CHUNK_SIZE) + : PersistentFSRecordsStorageFactory(id = 0) { override fun open(storagePath: Path): PersistentFSRecordsLockFreeOverMMappedFile = MMappedFileStorageFactory.withDefaults() - .pageSize(PersistentFSRecordsLockFreeOverMMappedFile.DEFAULT_MAPPED_CHUNK_SIZE) - .wrapStorageSafely(storagePath) { storage -> - PersistentFSRecordsLockFreeOverMMappedFile(storage) + .pageSize(pageSize) + .wrapStorageSafely(storagePath) { mappedFileStorage -> + PersistentFSRecordsLockFreeOverMMappedFile(mappedFileStorage) } - }, + } - /** Fallback impl for [OVER_MMAPPED_FILE] if something goes terribly wrong, and we can't fix it quickly */ - OVER_LOCK_FREE_FILE_CACHE { + /** Fallback impl for [OverMMappedFile] if something goes terribly wrong, and we can't fix it quickly */ + data class OverLockFreeFileCache(val pageSize: Int = PageCacheUtils.DEFAULT_PAGE_SIZE) : PersistentFSRecordsStorageFactory(id = 1) { private val PERSISTENT_FS_STORAGE_CONTEXT_RW = StorageLockContext(true, true, true) - override fun open(storagePath: Path): PersistentFSRecordsOverLockFreePagedStorage { + init { val recordLength = PersistentFSRecordsOverLockFreePagedStorage.RECORD_SIZE_IN_BYTES - val pageSize = PageCacheUtils.DEFAULT_PAGE_SIZE + val recordsArePageAligned = pageSize % recordLength == 0 + if (!recordsArePageAligned) { + throw AssertionError("Bug: record length(=$recordLength) is not aligned with page size(=$pageSize)") + } + } + + override fun open(storagePath: Path): PersistentFSRecordsOverLockFreePagedStorage { if (!PageCacheUtils.LOCK_FREE_PAGE_CACHE_ENABLED) { throw IOException( @@ -38,11 +48,6 @@ enum class PersistentFSRecordsStorageKind : StorageFactory can't create PersistentFSRecordsOverLockFreePagedStorage if FilePageCacheLockFree is disabled") } - val recordsArePageAligned = pageSize % recordLength == 0 - if (!recordsArePageAligned) { - throw AssertionError("Bug: record length(=$recordLength) is not aligned with page size(=$pageSize)") - } - val pagedStorage = PagedFileStorageWithRWLockedPageContent( storagePath, PERSISTENT_FS_STORAGE_CONTEXT_RW, @@ -55,35 +60,41 @@ enum class PersistentFSRecordsStorageKind : StorageFactory OverLockFreeFileCache() + "IN_MEMORY" -> InMemory() + else -> OverMMappedFile() + } + } } } \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageOverLockFreePagedStorageTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageOverLockFreePagedStorageTest.java index 1f61211caf9e..ca8c2f3196cc 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageOverLockFreePagedStorageTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsStorageOverLockFreePagedStorageTest.java @@ -48,7 +48,7 @@ public class PersistentFSRecordsStorageOverLockFreePagedStorageTest @NotNull @Override protected PersistentFSRecordsOverLockFreePagedStorage openStorage(final Path storagePath) throws IOException { - return (PersistentFSRecordsOverLockFreePagedStorage)PersistentFSRecordsStorageKind.OVER_LOCK_FREE_FILE_CACHE.open(storagePath); + return new PersistentFSRecordsStorageFactory.OverLockFreeFileCache().open(storagePath); } @Test diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/VFSInitializationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/VFSInitializationTest.java index 8dabf97bf7a7..297768819d31 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/VFSInitializationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/VFSInitializationTest.java @@ -3,6 +3,8 @@ package com.intellij.openapi.vfs.newvfs.persistent; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.newvfs.FileAttribute; +import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSRecordsStorageFactory.OverLockFreeFileCache; +import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSRecordsStorageFactory.OverMMappedFile; import com.intellij.openapi.vfs.newvfs.persistent.recovery.VFSInitializationResult; import com.intellij.openapi.vfs.newvfs.persistent.recovery.VFSRecoverer; import com.intellij.testFramework.TemporaryDirectory; @@ -17,7 +19,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static com.intellij.openapi.vfs.newvfs.persistent.PersistentFSRecordsStorageKind.*; import static com.intellij.openapi.vfs.newvfs.persistent.VFSInitException.ErrorCategory.*; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.*; @@ -195,17 +196,17 @@ public class VFSInitializationTest { //skip IN_MEMORY impl, since it is not really persistent //skip OVER_LOCK_FREE_FILE_CACHE impl if !LOCK_FREE_PAGE_CACHE_ENABLED (fails otherwise) - List allStorageKinds = PageCacheUtils.LOCK_FREE_PAGE_CACHE_ENABLED ? - List.of(OVER_LOCK_FREE_FILE_CACHE, OVER_MMAPPED_FILE) : - List.of(OVER_MMAPPED_FILE); + List allStorageKinds = PageCacheUtils.LOCK_FREE_PAGE_CACHE_ENABLED ? + List.of(new OverLockFreeFileCache(), new OverMMappedFile()) : + List.of(new OverMMappedFile()); List filesNotLeadingToVFSRebuild = new ArrayList<>(); - for (PersistentFSRecordsStorageKind storageKind : allStorageKinds) { + for (PersistentFSRecordsStorageFactory storageKind : allStorageKinds) { int vfsFilesCount = 1; int vfsVersion; for (int i = 0; i < vfsFilesCount; i++) { Path cachesDir = temporaryDirectory.createDir(); - PersistentFSRecordsStorageKind.setStorageImplementation(storageKind); + PersistentFSRecordsStorageFactory.setStorageImplementation(storageKind); FSRecordsImpl fsRecords = FSRecordsImpl.connect(cachesDir); try { @@ -238,7 +239,7 @@ public class VFSInitializationTest { FileUtil.delete(fileToDelete); //reopen: - PersistentFSRecordsStorageKind.setStorageImplementation(storageKind); + PersistentFSRecordsStorageFactory.setStorageImplementation(storageKind); try { PersistentFSConnection connection = tryInit(cachesDir, vfsVersion, Collections.emptyList()); try { @@ -269,15 +270,15 @@ public class VFSInitializationTest { public void VFS_isRebuilt_OnlyIf_ImplementationVersionChanged() throws Exception { //skip IN_MEMORY impl, since it is not really persistent //skip OVER_LOCK_FREE_FILE_CACHE impl if !LOCK_FREE_PAGE_CACHE_ENABLED (will fail) - final List allKinds = PageCacheUtils.LOCK_FREE_PAGE_CACHE_ENABLED ? - List.of(OVER_LOCK_FREE_FILE_CACHE, OVER_MMAPPED_FILE) : - List.of(OVER_MMAPPED_FILE); + final List allKinds = PageCacheUtils.LOCK_FREE_PAGE_CACHE_ENABLED ? + List.of(new OverLockFreeFileCache(), new OverMMappedFile()) : + List.of(new OverMMappedFile()); //check all combinations (from->to) of implementations: - for (PersistentFSRecordsStorageKind kindBefore : allKinds) { - for (PersistentFSRecordsStorageKind kindAfter : allKinds) { + for (PersistentFSRecordsStorageFactory kindBefore : allKinds) { + for (PersistentFSRecordsStorageFactory kindAfter : allKinds) { Path cachesDir = temporaryDirectory.createDir(); - PersistentFSRecordsStorageKind.setStorageImplementation(kindBefore); + PersistentFSRecordsStorageFactory.setStorageImplementation(kindBefore); long firstVfsCreationTimestamp; FSRecordsImpl vfs = FSRecordsImpl.connect(cachesDir); try { @@ -289,7 +290,7 @@ public class VFSInitializationTest { Thread.sleep(500);//ensure system clock is moving //reopen: - PersistentFSRecordsStorageKind.setStorageImplementation(kindAfter); + PersistentFSRecordsStorageFactory.setStorageImplementation(kindAfter); FSRecordsImpl reopenedVfs = FSRecordsImpl.connect(cachesDir); try { long reopenedVfsCreationTimestamp = reopenedVfs.getCreationTimestamp(); @@ -413,7 +414,7 @@ public class VFSInitializationTest { @After public void tearDown() throws Exception { - PersistentFSRecordsStorageKind.resetStorageImplementation(); + PersistentFSRecordsStorageFactory.resetStorageImplementation(); for (PersistentFSConnection connection : connectionsOpened) { PersistentFSConnector.disconnect(connection);