All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.incremental.storage.BasicMap.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/*
 * Copyright 2010-2015 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.incremental.storage

import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.IOUtil
import com.intellij.util.io.KeyDescriptor
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
import org.jetbrains.kotlin.utils.Printer
import java.io.File

/** [PersistentStorage] that provides a few extra utility methods. */
interface BasicMap : PersistentStorage {

    /** Removes all entries. */
    fun clear() {
        synchronized(this) {
            keys.forEach { remove(it) }
        }
    }

    /**
     * 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.).
     *
     * Make sure the storage has been closed first before calling this method.
     */
    fun deleteStorageFiles() {
        synchronized(this) {
            check(IOUtil.deleteAllFilesStartingWith(storageFile)) {
                "Unable to delete storage file(s) with name prefix: ${storageFile.path}"
            }
        }
    }

    @TestOnly
    fun dump(): String {
        val map: Map = synchronized(this) {
            keys.associateWith { this[it]!! }
        }
        val printableMap: Map = map.map {
            dumpKey(it.key) to dumpValue(it.value)
        }.sortedBy { it.first }.toMap()

        return StringBuilder().apply {
            Printer(this).apply {
                println("${storageFile.name.substringBefore(".tab")} (${this@BasicMap::class.java.simpleName})")
                pushIndent()
                printableMap.forEach {
                    println("${it.key} -> ${it.value}")
                }
                popIndent()
            }
        }.toString()
    }

    @TestOnly
    fun dumpKey(key: KEY): String = key.toString()

    @TestOnly
    fun dumpValue(value: VALUE): String {
        return if (value is Collection<*>) {
            // Sort the elements so that we can reliably compare `Collection`s in tests (in case the order of the elements is not stable).
            value.sortedBy { it.toString() }.toString()
        } else {
            value.toString()
        }
    }
}

abstract class BasicMapBase(
    // TODO(KT-63456): Remove `protected val` (currently this property is still used by BasicStringMap)
    protected val persistentStorage: PersistentStorage,
) : PersistentStorageWrapper(persistentStorage), BasicMap

abstract class AppendableBasicMapBase(
    storage: AppendablePersistentStorage,
) : AppendablePersistentStorageWrapper(storage), BasicMap>

abstract class AbstractBasicMap(
    storageFile: File,
    keyDescriptor: KeyDescriptor,
    valueExternalizer: DataExternalizer,
    icContext: IncrementalCompilationContext,
) : BasicMapBase(
    createPersistentStorage(storageFile, keyDescriptor, valueExternalizer, icContext)
)

abstract class AppendableBasicMap(
    storageFile: File,
    keyDescriptor: KeyDescriptor,
    elementExternalizer: DataExternalizer,
    icContext: IncrementalCompilationContext,
) : AppendableBasicMapBase(
    createAppendablePersistentStorage(storageFile, keyDescriptor, elementExternalizer, icContext)
)

abstract class AppendableSetBasicMap(
    storageFile: File,
    keyDescriptor: KeyDescriptor,
    elementExternalizer: DataExternalizer,
    icContext: IncrementalCompilationContext,
) : PersistentStorage>, BasicMap> {

    private val storage = createAppendablePersistentStorage(storageFile, keyDescriptor, elementExternalizer, icContext)

    override val storageFile: File = storage.storageFile

    @get:Synchronized
    override val keys: Set
        get() = storage.keys

    @Synchronized
    override fun contains(key: KEY): Boolean =
        storage.contains(key)

    @Synchronized
    override fun get(key: KEY): Set? {
        // Note: To optimize this getter, consider changing the type of `storage` from PersistentStorage> to
        // PersistentStorage> so that we don't have to call `toSet()`. The downside is that it will make the code more complex,
        // so we'll do it only if it's necessary.
        return storage[key]?.toSet()
    }

    @Synchronized
    override fun set(key: KEY, value: Set) {
        storage[key] = value
    }

    @Synchronized
    override fun remove(key: KEY) {
        storage.remove(key)
    }

    @Synchronized
    override fun flush() {
        storage.flush()
    }

    @Synchronized
    override fun close() {
        storage.close()
    }

    @Synchronized
    fun append(key: KEY, element: E) {
        storage.append(key, setOf(element))
    }

    @Synchronized
    fun append(key: KEY, elements: Set) {
        storage.append(key, elements)
    }

    @Synchronized
    override fun clean() {
        storage.clean()
    }
}

abstract class BasicStringMap(
    storageFile: File,
    valueExternalizer: DataExternalizer,
    icContext: IncrementalCompilationContext,
) : AbstractBasicMap(
    storageFile,
    StringExternalizer.toDescriptor(),
    valueExternalizer,
    icContext
) {
    // TODO(KT-63456): Remove this property
    // (To do this, we need to refactor all subclasses of BasicStringMap such that they don't use this property. For examples of what the
    // outcome of the refactoring should look like, see other subclasses of AbstractBasicMap.)
    protected val storage: PersistentStorage = persistentStorage
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy