Introduce new Kotlin Daemon without RMI abstraction
This commit is contained in:
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.daemon.client.KotlinCompilerDaemonClient.Companion.instantiate
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.common.ReportSeverity
|
||||
import org.jetbrains.kotlin.daemon.common.DummyProfiler
|
||||
import org.jetbrains.kotlin.daemon.common.Profiler
|
||||
import java.io.File
|
||||
|
||||
data class CompileServiceSessionAsync(val compileService: CompileServiceAsync, val sessionId: Int)
|
||||
|
||||
fun CompileServiceSession.toAsync() = CompileServiceSessionAsync(this.compileService.toClient(), this.sessionId)
|
||||
fun CompileServiceSessionAsync.toRMI() = CompileServiceSession(this.compileService.toRMI(), this.sessionId)
|
||||
|
||||
interface KotlinCompilerDaemonClient {
|
||||
suspend fun connectToCompileService(
|
||||
compilerId: CompilerId,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean,
|
||||
checkId: Boolean
|
||||
): CompileServiceAsync?
|
||||
|
||||
suspend fun connectToCompileService(
|
||||
compilerId: CompilerId,
|
||||
clientAliveFlagFile: File,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean
|
||||
): CompileServiceAsync?
|
||||
|
||||
suspend fun connectAndLease(
|
||||
compilerId: CompilerId,
|
||||
clientAliveFlagFile: File,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean,
|
||||
leaseSession: Boolean,
|
||||
sessionAliveFlagFile: File? = null
|
||||
): CompileServiceSessionAsync?
|
||||
|
||||
suspend fun shutdownCompileService(compilerId: CompilerId, daemonOptions: DaemonOptions)
|
||||
|
||||
suspend fun leaseCompileSession(compilerService: CompileServiceAsync, aliveFlagPath: String?): Int
|
||||
suspend fun releaseCompileSession(compilerService: CompileServiceAsync, sessionId: Int): Unit
|
||||
suspend fun compile(
|
||||
compilerService: CompileServiceAsync,
|
||||
sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
args: Array<out String>,
|
||||
messageCollector: MessageCollector,
|
||||
outputsCollector: ((File, List<File>) -> Unit)? = null,
|
||||
compilerMode: CompilerMode = CompilerMode.NON_INCREMENTAL_COMPILER,
|
||||
reportSeverity: ReportSeverity = ReportSeverity.INFO,
|
||||
port: Int = SOCKET_ANY_FREE_PORT,
|
||||
profiler: Profiler = DummyProfiler()
|
||||
): Int
|
||||
|
||||
fun getOrCreateClientFlagFile(daemonOptions: DaemonOptions): File
|
||||
|
||||
fun createCompResults(): CompilationResultsAsync
|
||||
|
||||
fun main(vararg args: String)
|
||||
|
||||
companion object {
|
||||
fun instantiate(daemonProtocolVariant: DaemonProtocolVariant): KotlinCompilerDaemonClient =
|
||||
KotlinCompilerDaemonClient::class.java
|
||||
.classLoader
|
||||
.loadClass(
|
||||
when(daemonProtocolVariant) {
|
||||
DaemonProtocolVariant.RMI -> "org.jetbrains.kotlin.daemon.client.impls.KotlinCompilerClientImpl"
|
||||
DaemonProtocolVariant.SOCKETS -> "org.jetbrains.kotlin.daemon.client.experimental.KotlinCompilerClient"
|
||||
}
|
||||
)
|
||||
.newInstance() as KotlinCompilerDaemonClient
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object KotlinCompilerClientInstance {
|
||||
|
||||
const val RMI_FLAG = "-old"
|
||||
const val SOCKETS_FLAG = "-new_with_sockets"
|
||||
|
||||
@JvmStatic
|
||||
fun main(vararg args: String) {
|
||||
val clientInstance: KotlinCompilerDaemonClient? = when (args.last()) {
|
||||
SOCKETS_FLAG ->
|
||||
instantiate(DaemonProtocolVariant.SOCKETS)
|
||||
else ->
|
||||
instantiate(DaemonProtocolVariant.RMI)
|
||||
}
|
||||
clientInstance?.main(*args.sliceArray(0..args.lastIndex))
|
||||
}
|
||||
|
||||
}
|
||||
+27
-27
@@ -19,40 +19,40 @@ package org.jetbrains.kotlin.daemon.client
|
||||
import org.jetbrains.kotlin.daemon.common.DaemonReportCategory
|
||||
import java.io.IOException
|
||||
|
||||
private class NativePlatformLauncherWrapper {
|
||||
class NativePlatformLauncherWrapper {
|
||||
private val nativeLauncher: net.rubygrapefruit.platform.ProcessLauncher by lazy {
|
||||
net.rubygrapefruit.platform.Native.get(net.rubygrapefruit.platform.ProcessLauncher::class.java)
|
||||
}
|
||||
|
||||
fun launch(processBuilder: ProcessBuilder): Process =
|
||||
try {
|
||||
nativeLauncher.start(processBuilder)
|
||||
}
|
||||
catch (e: net.rubygrapefruit.platform.NativeException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
try {
|
||||
nativeLauncher.start(processBuilder)
|
||||
}
|
||||
catch (e: net.rubygrapefruit.platform.NativeException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun launchProcessWithFallback(processBuilder: ProcessBuilder, reportingTargets: DaemonReportingTargets, reportingSource: String = "process launcher"): Process =
|
||||
try {
|
||||
// A separate class to delay classloading until this point, where we can catch class loading errors in case then the native lib is not in the classpath
|
||||
NativePlatformLauncherWrapper().launch(processBuilder)
|
||||
}
|
||||
catch (e: UnsatisfiedLinkError) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start process with native process launcher, falling back to ProcessBuilder#start ($e)", reportingSource)
|
||||
null
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start process with native process launcher, falling back to ProcessBuilder#start (${e.cause})", reportingSource)
|
||||
null
|
||||
}
|
||||
catch (e: NoClassDefFoundError) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start ($e)", reportingSource)
|
||||
null
|
||||
}
|
||||
catch (e: ClassNotFoundException) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start ($e)", reportingSource)
|
||||
null
|
||||
}
|
||||
try {
|
||||
// A separate class to delay classloading until this point, where we can catch class loading errors in case then the native lib is not in the classpath
|
||||
NativePlatformLauncherWrapper().launch(processBuilder)
|
||||
}
|
||||
catch (e: UnsatisfiedLinkError) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start process with native process launcher, falling back to ProcessBuilder#start ($e)", reportingSource)
|
||||
null
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start process with native process launcher, falling back to ProcessBuilder#start (${e.cause})", reportingSource)
|
||||
null
|
||||
}
|
||||
catch (e: NoClassDefFoundError) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start ($e)", reportingSource)
|
||||
null
|
||||
}
|
||||
catch (e: ClassNotFoundException) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start ($e)", reportingSource)
|
||||
null
|
||||
}
|
||||
?: processBuilder.start()
|
||||
|
||||
+4
-1
@@ -50,7 +50,10 @@ class RemoteReplCompilerStateHistory(private val state: RemoteReplCompilerState)
|
||||
override val lock: ReentrantReadWriteLock get() = state.lock
|
||||
}
|
||||
|
||||
class RemoteReplCompilerState(internal val replStateFacade: ReplStateFacade, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : IReplStageState<Unit> {
|
||||
class RemoteReplCompilerState(
|
||||
internal val replStateFacade: ReplStateFacade,
|
||||
override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()
|
||||
) : IReplStageState<Unit> {
|
||||
|
||||
override val currentGeneration: Int get() = (history as RemoteReplCompilerStateHistory).currentGeneration.get()
|
||||
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client.impls
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.daemon.client.*
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.common.ReportSeverity
|
||||
import org.jetbrains.kotlin.daemon.common.Profiler
|
||||
import java.io.File
|
||||
|
||||
object KotlinCompilerClientImpl : KotlinCompilerDaemonClient {
|
||||
|
||||
val oldClient = KotlinCompilerClient
|
||||
|
||||
override suspend fun connectToCompileService(
|
||||
compilerId: CompilerId,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean,
|
||||
checkId: Boolean
|
||||
): CompileServiceAsync? = oldClient.connectToCompileService(
|
||||
compilerId,
|
||||
daemonJVMOptions,
|
||||
daemonOptions,
|
||||
reportingTargets,
|
||||
autostart,
|
||||
checkId
|
||||
)?.toClient()
|
||||
|
||||
override suspend fun connectToCompileService(
|
||||
compilerId: CompilerId,
|
||||
clientAliveFlagFile: File,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean
|
||||
): CompileServiceAsync? = oldClient.connectToCompileService(
|
||||
compilerId,
|
||||
clientAliveFlagFile,
|
||||
daemonJVMOptions,
|
||||
daemonOptions,
|
||||
reportingTargets,
|
||||
autostart
|
||||
)?.toClient()
|
||||
|
||||
override suspend fun connectAndLease(
|
||||
compilerId: CompilerId,
|
||||
clientAliveFlagFile: File,
|
||||
daemonJVMOptions: DaemonJVMOptions,
|
||||
daemonOptions: DaemonOptions,
|
||||
reportingTargets: DaemonReportingTargets,
|
||||
autostart: Boolean,
|
||||
leaseSession: Boolean,
|
||||
sessionAliveFlagFile: File?
|
||||
): CompileServiceSessionAsync? = oldClient.connectAndLease(
|
||||
compilerId,
|
||||
clientAliveFlagFile,
|
||||
daemonJVMOptions,
|
||||
daemonOptions,
|
||||
reportingTargets,
|
||||
autostart,
|
||||
leaseSession,
|
||||
sessionAliveFlagFile
|
||||
)?.toAsync()
|
||||
|
||||
override suspend fun shutdownCompileService(
|
||||
compilerId: CompilerId,
|
||||
daemonOptions: DaemonOptions
|
||||
) = oldClient.shutdownCompileService(
|
||||
compilerId,
|
||||
daemonOptions
|
||||
)
|
||||
|
||||
override suspend fun leaseCompileSession(
|
||||
compilerService: CompileServiceAsync,
|
||||
aliveFlagPath: String?
|
||||
) = oldClient.leaseCompileSession(
|
||||
compilerService.toRMI(),
|
||||
aliveFlagPath
|
||||
)
|
||||
|
||||
override suspend fun releaseCompileSession(
|
||||
compilerService: CompileServiceAsync,
|
||||
sessionId: Int
|
||||
) = oldClient.releaseCompileSession(
|
||||
compilerService.toRMI(),
|
||||
sessionId
|
||||
)
|
||||
|
||||
override suspend fun compile(
|
||||
compilerService: CompileServiceAsync,
|
||||
sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
args: Array<out String>,
|
||||
messageCollector: MessageCollector,
|
||||
outputsCollector: ((File, List<File>) -> Unit)?,
|
||||
compilerMode: CompilerMode,
|
||||
reportSeverity: ReportSeverity,
|
||||
port: Int,
|
||||
profiler: Profiler
|
||||
): Int = oldClient.compile(
|
||||
compilerService.toRMI(),
|
||||
sessionId,
|
||||
targetPlatform,
|
||||
args,
|
||||
messageCollector,
|
||||
outputsCollector,
|
||||
compilerMode,
|
||||
reportSeverity,
|
||||
port,
|
||||
profiler
|
||||
)
|
||||
|
||||
override fun getOrCreateClientFlagFile(daemonOptions: DaemonOptions): File = oldClient.getOrCreateClientFlagFile(daemonOptions)
|
||||
|
||||
override fun createCompResults() = TODO("not implemented")
|
||||
|
||||
override fun main(vararg args: String) = oldClient.main(*args)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user