[IC] Add back flush() API to PersistentStorage
In commit 4e89dcf, we removed `flush()` from `PersistentStorage`
(previously called `LazyStorage`) because it is not used in Gradle
builds.
However, `flush()` is still used in JPS builds, so we need to add that
API back in this commit.
#KT-62486 Fixed
Co-authored-by: Hung Nguyen <hungnv@google.com>
Merge-request: KOTLIN-MR-796
Merged-by: Aleksei Cherepanov <aleksei.cherepanov@jetbrains.com>
This commit is contained in:
@@ -197,12 +197,12 @@ open class LookupStorage(
|
|||||||
@TestOnly
|
@TestOnly
|
||||||
fun forceGC() {
|
fun forceGC() {
|
||||||
removeGarbageForTests()
|
removeGarbageForTests()
|
||||||
flush(false)
|
flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun dump(lookupSymbols: Set<LookupSymbol>): String {
|
fun dump(lookupSymbols: Set<LookupSymbol>): String {
|
||||||
flush(false)
|
flush()
|
||||||
|
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
val p = Printer(sb)
|
val p = Printer(sb)
|
||||||
|
|||||||
@@ -33,15 +33,6 @@ interface BasicMap<KEY, VALUE> : PersistentStorage<KEY, VALUE> {
|
|||||||
keys.forEach { remove(it) }
|
keys.forEach { remove(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DEPRECATED: This method should be removed because
|
|
||||||
* - The `memoryCachesOnly` parameter is not used (it is always `false`).
|
|
||||||
* - There is currently no good use case for flushing. In fact, the current implementation of this method does nothing.
|
|
||||||
*/
|
|
||||||
fun flush(memoryCachesOnly: Boolean) {
|
|
||||||
check(!memoryCachesOnly) { "Expected memoryCachesOnly = false but it is `true`" }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes [storageFile] or a group of files associated with [storageFile] (e.g., an implementation of [PersistentStorage] may use a
|
* Deletes [storageFile] or a group of files associated with [storageFile] (e.g., an implementation of [PersistentStorage] may use a
|
||||||
* [com.intellij.util.io.PersistentHashMap], which creates files such as "storageFile.tab", "storageFile.tab.len", etc.).
|
* [com.intellij.util.io.PersistentHashMap], which creates files such as "storageFile.tab", "storageFile.tab.len", etc.).
|
||||||
@@ -54,18 +45,6 @@ interface BasicMap<KEY, VALUE> : PersistentStorage<KEY, VALUE> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DEPRECATED: This method should be removed because:
|
|
||||||
* - The method name is ambiguous (it may be confused with [clear], and it does not exactly describe the current implementation).
|
|
||||||
* - The method currently calls close(). However, close() is often already called separately and automatically, so calling this method
|
|
||||||
* means that close() will likely be called twice.
|
|
||||||
* Instead, just inline this method or call either close() or deleteStorageFiles() directly.
|
|
||||||
*/
|
|
||||||
fun clean() {
|
|
||||||
close()
|
|
||||||
deleteStorageFiles()
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun dump(): String {
|
fun dump(): String {
|
||||||
return StringBuilder().apply {
|
return StringBuilder().apply {
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
open class BasicMapsOwner(val cachesDir: File) {
|
open class BasicMapsOwner(val cachesDir: File) : Closeable {
|
||||||
private val maps = arrayListOf<BasicMap<*, *>>()
|
private val maps = arrayListOf<BasicMap<*, *>>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -36,11 +37,11 @@ open class BasicMapsOwner(val cachesDir: File) {
|
|||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
fun flush(memoryCachesOnly: Boolean) {
|
fun flush() {
|
||||||
forEachMapSafe("flush") { it.flush(memoryCachesOnly) }
|
forEachMapSafe("flush", BasicMap<*, *>::flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun close() {
|
override fun close() {
|
||||||
forEachMapSafe("close", BasicMap<*, *>::close)
|
forEachMapSafe("close", BasicMap<*, *>::close)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,8 +49,32 @@ open class BasicMapsOwner(val cachesDir: File) {
|
|||||||
forEachMapSafe("deleteStorageFiles", BasicMap<*, *>::deleteStorageFiles)
|
forEachMapSafe("deleteStorageFiles", BasicMap<*, *>::deleteStorageFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: This API should be removed because
|
||||||
|
* - It's not clear what [memoryCachesOnly] means.
|
||||||
|
* - In the past, when `memoryCachesOnly=true` we applied a small optimization: Checking
|
||||||
|
* [com.intellij.util.io.PersistentHashMap.isDirty] before calling [com.intellij.util.io.PersistentHashMap.force]. However, if that
|
||||||
|
* optimization is useful, it's better to always do it (perhaps inside the [com.intellij.util.io.PersistentHashMap.force] method
|
||||||
|
* itself) rather than doing it based on the value of this parameter.
|
||||||
|
*
|
||||||
|
* Instead, just call [flush] (without a parameter) directly.
|
||||||
|
*/
|
||||||
|
fun flush(@Suppress("UNUSED_PARAMETER") memoryCachesOnly: Boolean) {
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: This API should be removed because:
|
||||||
|
* - It's not obvious what "clean" means: It does not exactly describe the current implementation, and it also sounds similar to
|
||||||
|
* "clear" which means removing all the map entries, but this method does not do that.
|
||||||
|
* - This method currently calls [close] (and [deleteStorageFiles]). However, [close] is often already called separately and
|
||||||
|
* automatically, so this API makes it more likely for [close] to be accidentally called twice.
|
||||||
|
*
|
||||||
|
* Instead, just call [close] and/or [deleteStorageFiles] explicitly.
|
||||||
|
*/
|
||||||
fun clean() {
|
fun clean() {
|
||||||
forEachMapSafe("clean", BasicMap<*, *>::clean)
|
close()
|
||||||
|
deleteStorageFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|||||||
@@ -9,11 +9,16 @@ import org.jetbrains.kotlin.utils.ThreadSafe
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [PersistentStorage] which reads from another underlying [PersistentStorage], keeps all changes to it in memory, and writes the changes
|
* [PersistentStorage] which reads from another underlying [PersistentStorage], keeps all changes to it in memory, and writes the changes
|
||||||
* back to the underlying storage on [applyChanges] or [close].
|
* back to the underlying storage on [applyChanges], [flush], or [close].
|
||||||
*/
|
*/
|
||||||
interface InMemoryStorageInterface<KEY, VALUE> : PersistentStorage<KEY, VALUE> {
|
interface InMemoryStorageInterface<KEY, VALUE> : PersistentStorage<KEY, VALUE> {
|
||||||
|
|
||||||
/** Applies in-memory changes to the underlying [PersistentStorage], then calls [clearChanges]. */
|
/**
|
||||||
|
* Applies in-memory changes to the underlying [PersistentStorage], then calls [clearChanges].
|
||||||
|
*
|
||||||
|
* Note that the changes are only propagated to the underlying [PersistentStorage], they may not be written to [storageFile] yet. If
|
||||||
|
* you want to propagate the changes to [storageFile], call [flush] instead.
|
||||||
|
*/
|
||||||
fun applyChanges()
|
fun applyChanges()
|
||||||
|
|
||||||
/** Removes all in-memory changes. */
|
/** Removes all in-memory changes. */
|
||||||
@@ -120,6 +125,12 @@ open class InMemoryStorage<KEY, VALUE>(
|
|||||||
removedKeys.clear()
|
removedKeys.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun flush() {
|
||||||
|
applyChanges()
|
||||||
|
storage.flush()
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun close() {
|
override fun close() {
|
||||||
applyChanges()
|
applyChanges()
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ open class LazyStorage<KEY, VALUE>(
|
|||||||
getStorageIfExists()?.remove(key)
|
getStorageIfExists()?.remove(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun flush() {
|
||||||
|
storage?.force()
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun close() {
|
override fun close() {
|
||||||
storage?.close()
|
storage?.close()
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import java.io.File
|
|||||||
/**
|
/**
|
||||||
* Represents an in-memory map that is backed by a [storageFile].
|
* Represents an in-memory map that is backed by a [storageFile].
|
||||||
*
|
*
|
||||||
* Changes to this map may be written to [storageFile] at any time, and it is guaranteed to be written on [close].
|
* Changes to this map may be written to [storageFile] at any time, and it is guaranteed to be written on [flush] or [close].
|
||||||
*
|
*
|
||||||
* This interface is similar to but simpler than [com.intellij.util.io.PersistentMapBase].
|
* This interface is similar to but simpler than [com.intellij.util.io.PersistentMapBase].
|
||||||
*/
|
*/
|
||||||
@@ -43,7 +43,10 @@ interface PersistentStorage<KEY, VALUE> : Closeable {
|
|||||||
|
|
||||||
fun remove(key: KEY)
|
fun remove(key: KEY)
|
||||||
|
|
||||||
/** Writes any remaining in-memory changes to [storageFile] and closes this map. */
|
/** Writes any remaining in-memory changes to [storageFile]. */
|
||||||
|
fun flush()
|
||||||
|
|
||||||
|
/** Writes any remaining in-memory changes to [storageFile] ([flush]) and closes this map. */
|
||||||
override fun close()
|
override fun close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +100,11 @@ abstract class PersistentStorageWrapper<KEY, VALUE>(
|
|||||||
storage.remove(key)
|
storage.remove(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun flush() {
|
||||||
|
storage.flush()
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun close() {
|
override fun close() {
|
||||||
storage.close()
|
storage.close()
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ abstract class PersistentStorageAdapter<KEY, VALUE, INTERNAL_KEY, INTERNAL_VALUE
|
|||||||
storage.remove(publicToInternalKey(key))
|
storage.remove(publicToInternalKey(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun flush() {
|
||||||
|
storage.close()
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun close() {
|
override fun close() {
|
||||||
storage.close()
|
storage.close()
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ private class InMemoryStorageWrapperMock : InMemoryStorageInterface<Any, Any> {
|
|||||||
|
|
||||||
override val keys: Set<Any> = emptySet()
|
override val keys: Set<Any> = emptySet()
|
||||||
|
|
||||||
|
override fun flush() {}
|
||||||
|
|
||||||
override fun close() {}
|
override fun close() {}
|
||||||
|
|
||||||
override fun remove(key: Any) {}
|
override fun remove(key: Any) {}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class RelocatableCachesTest : TestWithWorkingDir() {
|
|||||||
val filesToAdd = if (reverseFiles) files.reversedSet() else files
|
val filesToAdd = if (reverseFiles) files.reversedSet() else files
|
||||||
val lookupsToAdd = if (reverseLookups) lookups.reversedMultiMap() else lookups
|
val lookupsToAdd = if (reverseLookups) lookups.reversedMultiMap() else lookups
|
||||||
lookupStorage.addAll(lookupsToAdd, filesToAdd)
|
lookupStorage.addAll(lookupsToAdd, filesToAdd)
|
||||||
lookupStorage.flush(memoryCachesOnly = false)
|
lookupStorage.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val File.storageRoot: File
|
private val File.storageRoot: File
|
||||||
|
|||||||
Reference in New Issue
Block a user