Support relocatable cache for InputCache

This commit is contained in:
justin.wei
2020-12-01 14:49:28 -08:00
committed by nataliya.valtman
parent 45ba035431
commit 34274dd032
6 changed files with 156 additions and 13 deletions
@@ -42,7 +42,7 @@ abstract class IncrementalCachesManager<PlatformCache : AbstractIncrementalCache
private val inputSnapshotsCacheDir = File(cachesRootDir, "inputs").apply { mkdirs() }
private val lookupCacheDir = File(cachesRootDir, "lookups").apply { mkdirs() }
val inputsCache: InputsCache = InputsCache(inputSnapshotsCacheDir, reporter).apply { registerCache() }
val inputsCache: InputsCache = InputsCache(inputSnapshotsCacheDir, reporter, pathConverter).apply { registerCache() }
val lookupCache: LookupStorage = LookupStorage(lookupCacheDir, pathConverter).apply { registerCache() }
abstract val platformCache: PlatformCache
@@ -21,20 +21,22 @@ import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.report.ICReporter
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
import org.jetbrains.kotlin.incremental.storage.SourceToOutputFilesMap
import java.io.File
class InputsCache(
workingDir: File,
private val reporter: ICReporter
private val reporter: ICReporter,
pathConverter: FileToPathConverter
) : BasicMapsOwner(workingDir) {
companion object {
private const val SOURCE_SNAPSHOTS = "source-snapshot"
private const val SOURCE_TO_OUTPUT_FILES = "source-to-output"
}
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile))
private val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile))
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile, pathConverter))
private val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile, pathConverter))
fun removeOutputForSourceFiles(sources: Iterable<File>) {
for (sourceFile in sources) {
@@ -18,11 +18,16 @@ package org.jetbrains.kotlin.incremental.snapshots
import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
import java.io.File
import java.util.*
class FileSnapshotMap(storageFile: File) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
class FileSnapshotMap(
storageFile: File,
private val pathConverter: FileToPathConverter
) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
override fun dumpValue(value: FileSnapshot): String =
value.toString()
@@ -32,16 +37,16 @@ class FileSnapshotMap(storageFile: File) : BasicStringMap<FileSnapshot>(storageF
val newOrModified = ArrayList<File>()
val removed = ArrayList<File>()
val newPaths = newFiles.mapTo(HashSet()) { it.canonicalPath }
val newPaths = newFiles.mapTo(HashSet(), transform = pathConverter::toPath)
for (oldPath in storage.keys) {
if (oldPath !in newPaths) {
storage.remove(oldPath)
removed.add(File(oldPath))
removed.add(pathConverter.toFile(oldPath))
}
}
for (path in newPaths) {
val file = File(path)
val file = pathConverter.toFile(path)
val oldSnapshot = storage[path]
val newSnapshot = snapshotProvider[file]
@@ -9,21 +9,22 @@ import org.jetbrains.kotlin.incremental.dumpCollection
import java.io.File
class SourceToOutputFilesMap(
storageFile: File
storageFile: File,
private val pathConverter: FileToPathConverter
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
@Synchronized
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
storage[sourceFile.absolutePath] = outputFiles.map { it.absolutePath }
storage[pathConverter.toPath(sourceFile)] = outputFiles.map(pathConverter::toPath)
}
operator fun get(sourceFile: File): Collection<File> =
storage[sourceFile.absolutePath].orEmpty().map(::File)
storage[pathConverter.toPath(sourceFile)].orEmpty().map(pathConverter::toFile)
override fun dumpValue(value: Collection<String>) =
value.dumpCollection()
@Synchronized
fun remove(file: File): Collection<File> =
get(file).also { storage.remove(file.absolutePath) }
get(file).also { storage.remove(pathConverter.toPath(file)) }
}
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.incremental.snapshots
import org.jetbrains.kotlin.TestWithWorkingDir
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Before
@@ -15,13 +17,15 @@ import kotlin.properties.Delegates
class FileSnapshotMapTest : TestWithWorkingDir() {
private var snapshotMap: FileSnapshotMap by Delegates.notNull()
private var pathConverter: FileToPathConverter by Delegates.notNull()
@Before
override fun setUp() {
super.setUp()
val caches = File(workingDir, "caches").apply { mkdirs() }
val snapshotMapFile = File(caches, "snapshots.tab")
snapshotMap = FileSnapshotMap(snapshotMapFile)
pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
snapshotMap = FileSnapshotMap(snapshotMapFile, pathConverter)
}
@After
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.incremental.storage
import org.jetbrains.kotlin.TestWithWorkingDir
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Before
import org.junit.Test
import java.io.File
import kotlin.properties.Delegates
class SourceToOutputFilesMapTest : TestWithWorkingDir() {
private var stofMap: SourceToOutputFilesMap by Delegates.notNull()
private var pathConverter: FileToPathConverter by Delegates.notNull()
@Before
override fun setUp() {
super.setUp()
val caches = File(workingDir, "caches").apply { mkdirs() }
val stofMapFile = File(caches, "stof.tab")
pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
stofMap = SourceToOutputFilesMap(stofMapFile, pathConverter)
}
@After
override fun tearDown() {
stofMap.flush(false)
stofMap.close()
super.tearDown()
}
@Test
fun testEmptyGetReturnsEmpty() {
assertTrue(stofMap.get(File("")).isEmpty())
}
@Test
fun testSetGetOneReturnsOne() {
stofMap.set(
File(""),
listOf(File("one").canonicalFile))
assertEquals(
listOf(File("one").canonicalFile),
stofMap.get(File("")))
}
@Test
fun testSetDupeReturnsUnique() {
stofMap.set(
File(""),
listOf(File("one").canonicalFile, File("one").canonicalFile, File("one").canonicalFile))
assertEquals(
listOf(File("one").canonicalFile),
stofMap.get(File("")))
}
@Test
fun testSetOverwriteReturnsNew() {
stofMap.set(
File(""),
listOf(File("old").canonicalFile, File("old").canonicalFile, File("old").canonicalFile))
stofMap.set(
File(""),
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile))
assertArrayEquals(
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
stofMap.get(File("")).toSortedPaths())
}
@Test
fun testRelativeInReturnsAbsolute() {
stofMap.set(
File(""),
listOf(File("one"), File("two"), File("three")))
assertArrayEquals(
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
stofMap.get(File("")).toSortedPaths()
)
}
@Test
fun testSetRelativeGetAbsolute() {
stofMap.set(
File("blah"),
listOf(File("one"), File("two"), File("three")))
assertArrayEquals(
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
stofMap.get(File("blah").canonicalFile).toSortedPaths()
)
}
@Test
fun testSetRemove() {
stofMap.set(
File("blah"),
listOf(File("one"), File("two"), File("three")))
assertArrayEquals(
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
stofMap.remove(File("blah")).toSortedPaths()
)
assertTrue(stofMap.get(File("blah")).isEmpty())
}
@Test
fun testSetRemoveLoop() {
repeat(5) {
stofMap.set(
File("blah"),
listOf(File("one"), File("two"), File("three"))
)
assertArrayEquals(
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
stofMap.remove(File("blah")).toSortedPaths()
)
assertTrue(stofMap.get(File("blah")).isEmpty())
}
}
private fun Iterable<File>.toSortedPaths(): Array<String> =
map { it.canonicalPath }.sorted().toTypedArray()
}