[SQUASHME] Review fixes

This commit is contained in:
Ilya Matveev
2017-08-23 13:19:03 +07:00
committed by ilmat192
parent 7116801dc6
commit d2c3e320c6
5 changed files with 37 additions and 58 deletions
@@ -15,8 +15,8 @@
*/ */
// //
// Example startup helper for Kotlin N compiler. Compile to JAR and add it to // Example startup helper for Kotlin/Native compiler. Compile to JAR and add it to
// Kotlin N classpath - it will get loaded and executed automatically. // Kotlin/Native classpath - it will get loaded and executed automatically.
// //
package org.jetbrains.kotlin.konan.util package org.jetbrains.kotlin.konan.util
+3 -1
View File
@@ -174,7 +174,9 @@ class HelperNativeDep extends TgzNativeDep {
@TaskAction @TaskAction
public void downloadAndExtract() { public void downloadAndExtract() {
new DependencyProcessor(baseOutDir, konanProperties, [baseName], baseUrl).run() def downloader = new DependencyProcessor(baseOutDir, konanProperties, [baseName], baseUrl)
downloader.showInfo = false
downloader.run()
} }
} }
@@ -186,9 +186,12 @@ fun Path.recursiveCopyTo(destPath: Path) {
val newPath = destFs.getPath(destPath.toString(), relative.toString()) val newPath = destFs.getPath(destPath.toString(), relative.toString())
// File systems don't allow replacing an existing root. // File systems don't allow replacing an existing root.
if (newPath == newPath.getRoot()) return@next if (newPath == newPath.getRoot()) return@next
Files.copy(oldPath, newPath, if (Files.isDirectory(newPath)) {
StandardCopyOption.REPLACE_EXISTING) Files.createDirectories(newPath)
} else {
Files.copy(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING)
}
} }
} }
@@ -6,15 +6,13 @@ import java.net.URL
import java.net.URLConnection import java.net.URLConnection
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.util.concurrent.TimeUnit import java.util.concurrent.*
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.thread
import kotlin.concurrent.withLock
class DependencyDownloader( class DependencyDownloader(
var maxAttempts: Int = DEFAULT_MAX_ATTEMPTS, var maxAttempts: Int = DEFAULT_MAX_ATTEMPTS,
var attemptIntervalMs: Long = DEFAULT_ATTEMPT_INTERVAL_MS var attemptIntervalMs: Long = DEFAULT_ATTEMPT_INTERVAL_MS
) { ) {
val executor = ExecutorCompletionService<Unit>(Executors.newSingleThreadExecutor())
enum class ReplacingMode { enum class ReplacingMode {
/** Redownload the file and replace the existing one. */ /** Redownload the file and replace the existing one. */
@@ -25,41 +23,8 @@ class DependencyDownloader(
RETURN_EXISTING RETURN_EXISTING
} }
class DownloadingProgress(@Volatile var currentBytes: Long, val totalBytes: Long) { class DownloadingProgress(@Volatile var currentBytes: Long) {
@Volatile var done: Boolean = false
private set
@Volatile var exception: Throwable? = null
private set
private val lock = ReentrantLock()
private val condition = lock.newCondition()
val doneCorrectly: Boolean
get() = done && exception != null
fun update(readBytes: Int) { currentBytes += readBytes } fun update(readBytes: Int) { currentBytes += readBytes }
fun done() = lock.withLock {
done = true
condition.signalAll()
}
fun done(e: Throwable) = lock.withLock {
done = true
exception = e
condition.signalAll()
}
fun trackProgress(interval: Long,
intervalTimeUnit: TimeUnit = TimeUnit.MILLISECONDS,
action: (progress: DownloadingProgress) -> Unit) =
lock.withLock {
action(this)
while (!done) {
condition.await(interval, intervalTimeUnit)
action(this)
}
}
} }
private fun doDownload(originalUrl: URL, private fun doDownload(originalUrl: URL,
@@ -68,33 +33,40 @@ class DependencyDownloader(
currentBytes: Long, currentBytes: Long,
totalBytes: Long, totalBytes: Long,
append: Boolean) { append: Boolean) {
val progress = DownloadingProgress(currentBytes, totalBytes) val progress = DownloadingProgress(currentBytes)
// TODO: Implement multi-thread downloading + use some sort of thread pool. // TODO: Implement multi-thread downloading.
thread { executor.submit {
Thread.setDefaultUncaughtExceptionHandler { _, throwable -> progress.done(throwable) }
connection.getInputStream().use { from -> connection.getInputStream().use { from ->
FileOutputStream(tmpFile, append).use { to -> FileOutputStream(tmpFile, append).use { to ->
val buffer = ByteArray(DEFAULT_BUFFER_SIZE) val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
var read = from.read(buffer) var read = from.read(buffer)
while (read != -1) { while (read != -1) {
if (Thread.interrupted()) {
throw InterruptedException()
}
to.write(buffer, 0, read) to.write(buffer, 0, read)
progress.update(read) progress.update(read)
read = from.read(buffer) read = from.read(buffer)
} }
if (currentBytes != totalBytes) { if (progress.currentBytes != totalBytes) {
throw EOFException("The stream closed before end of downloading.") throw EOFException("The stream closed before end of downloading.")
} }
progress.done()
} }
} }
} }
progress.trackProgress(1000) { var result: Future<Unit>?
updateProgressMsg(originalUrl.toString(), it.currentBytes, it.totalBytes) do {
} updateProgressMsg(originalUrl.toString(), progress.currentBytes, totalBytes)
if (!progress.doneCorrectly) { result = executor.poll(1, TimeUnit.SECONDS)
throw progress.exception!! } while(result == null)
updateProgressMsg(originalUrl.toString(), progress.currentBytes, totalBytes)
try {
result.get()
} catch (e: ExecutionException) {
throw e.cause ?: e
} }
} }
@@ -112,6 +84,7 @@ class DependencyDownloader(
connection.setRequestProperty("range", "bytes=$currentBytes-") connection.setRequestProperty("range", "bytes=$currentBytes-")
connection.connect() connection.connect()
} else { } else {
currentBytes = 0
tmpFile.delete() tmpFile.delete()
} }
} }
@@ -148,10 +121,10 @@ class DependencyDownloader(
replace: ReplacingMode = ReplacingMode.RETURN_EXISTING): File { replace: ReplacingMode = ReplacingMode.RETURN_EXISTING): File {
if (destination.exists()) { if (destination.exists()) {
@Suppress("NON_EXHAUSTIVE_WHEN")
when (replace) { when (replace) {
ReplacingMode.RETURN_EXISTING -> return destination ReplacingMode.RETURN_EXISTING -> return destination
ReplacingMode.THROW -> throw FileAlreadyExistsException(destination) ReplacingMode.THROW -> throw FileAlreadyExistsException(destination)
ReplacingMode.REPLACE -> Unit // Just continue with downloading.
} }
} }
val tmpFile = File("${destination.canonicalPath}.$TMP_SUFFIX") val tmpFile = File("${destination.canonicalPath}.$TMP_SUFFIX")
@@ -160,7 +133,7 @@ class DependencyDownloader(
"A temporary file is a directory: ${tmpFile.canonicalPath}. Remove it and try again." "A temporary file is a directory: ${tmpFile.canonicalPath}. Remove it and try again."
} }
check(!destination.isDirectory) { check(!destination.isDirectory) {
"The destination file is a directory: ${tmpFile.canonicalPath}. Remove it and try again." "The destination file is a directory: ${destination.canonicalPath}. Remove it and try again."
} }
var attempt = 1 var attempt = 1
@@ -73,6 +73,7 @@ class DependencyProcessor(dependenciesRoot: File,
val lockFile = File(cacheDirectory, ".lock").apply { if (!exists()) createNewFile() } val lockFile = File(cacheDirectory, ".lock").apply { if (!exists()) createNewFile() }
var showInfo = true
private var isInfoShown = false private var isInfoShown = false
// TOOO: Rename pause -> interval // TOOO: Rename pause -> interval
@@ -135,7 +136,7 @@ class DependencyProcessor(dependenciesRoot: File,
return return
} }
if (!isInfoShown) { if (showInfo && !isInfoShown) {
println("Downloading native dependencies (LLVM, sysroot etc). This is a one-time action performed only on the first run of the compiler.") println("Downloading native dependencies (LLVM, sysroot etc). This is a one-time action performed only on the first run of the compiler.")
isInfoShown = true isInfoShown = true
} }