Allow parallel access to klib zip filesystem

This commit is contained in:
Alexander Gorshenev
2019-12-23 16:11:12 +03:00
committed by alexander-gorshenev
parent ddda93ad96
commit 9a12641fde
@@ -7,17 +7,27 @@ package org.jetbrains.kotlin.konan.file
import java.net.URI import java.net.URI
import java.nio.file.* import java.nio.file.*
import java.util.concurrent.ConcurrentHashMap
private val File.zipUri: URI private val File.zipUri: URI
get() = URI.create("jar:${this.toPath().toUri()}") get() = URI.create("jar:${this.toPath().toUri()}")
private val counters = ConcurrentHashMap<FileSystem, Int>()
// Zip filesystem provider creates a singlton zip FileSystem.
// So newFileSystem can return an already existing one.
// And, more painful, closing the filesystem could close it for another consumer thread.
fun File.zipFileSystem(mutable: Boolean = false): FileSystem { fun File.zipFileSystem(mutable: Boolean = false): FileSystem {
val zipUri = this.zipUri val zipUri = this.zipUri
val attributes = hashMapOf("create" to mutable.toString()) val attributes = hashMapOf("create" to mutable.toString())
return try { return try {
FileSystems.newFileSystem(zipUri, attributes, null) FileSystems.newFileSystem(zipUri, attributes, null).also {
counters[it] = 1
}
} catch (e: FileSystemAlreadyExistsException) { } catch (e: FileSystemAlreadyExistsException) {
FileSystems.getFileSystem(zipUri) FileSystems.getFileSystem(zipUri).also {
counters.computeIfPresent(it, { _, u -> u + 1})
}
} }
} }
@@ -46,7 +56,13 @@ fun <T> File.withZipFileSystem(mutable: Boolean = false, action: (FileSystem) ->
return try { return try {
action(zipFileSystem) action(zipFileSystem)
} finally { } finally {
zipFileSystem.close() val counter = counters[zipFileSystem]!!
if (counter == 1) {
zipFileSystem.close()
counters.remove(zipFileSystem)
} else {
counters.computeIfPresent(zipFileSystem, { _, u -> u - 1})
}
} }
} }