From 9a12641fde2cc9c5c1a26bf7ff035ab2d0c84d1c Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Mon, 23 Dec 2019 16:11:12 +0300 Subject: [PATCH] Allow parallel access to klib zip filesystem --- .../jetbrains/kotlin/konan/file/ZipUtil.kt | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/util-io/src/org/jetbrains/kotlin/konan/file/ZipUtil.kt b/compiler/util-io/src/org/jetbrains/kotlin/konan/file/ZipUtil.kt index 43807b44513..d6d37e8d0c0 100644 --- a/compiler/util-io/src/org/jetbrains/kotlin/konan/file/ZipUtil.kt +++ b/compiler/util-io/src/org/jetbrains/kotlin/konan/file/ZipUtil.kt @@ -7,17 +7,27 @@ package org.jetbrains.kotlin.konan.file import java.net.URI import java.nio.file.* +import java.util.concurrent.ConcurrentHashMap private val File.zipUri: URI get() = URI.create("jar:${this.toPath().toUri()}") +private val counters = ConcurrentHashMap() + +// 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 { val zipUri = this.zipUri val attributes = hashMapOf("create" to mutable.toString()) return try { - FileSystems.newFileSystem(zipUri, attributes, null) + FileSystems.newFileSystem(zipUri, attributes, null).also { + counters[it] = 1 + } } catch (e: FileSystemAlreadyExistsException) { - FileSystems.getFileSystem(zipUri) + FileSystems.getFileSystem(zipUri).also { + counters.computeIfPresent(it, { _, u -> u + 1}) + } } } @@ -46,7 +56,13 @@ fun File.withZipFileSystem(mutable: Boolean = false, action: (FileSystem) -> return try { action(zipFileSystem) } finally { - zipFileSystem.close() + val counter = counters[zipFileSystem]!! + if (counter == 1) { + zipFileSystem.close() + counters.remove(zipFileSystem) + } else { + counters.computeIfPresent(zipFileSystem, { _, u -> u - 1}) + } } }