Passing port through daemon client API to allow port reusing for client-side components, introducing operations tracer interface for testing purposes
This commit is contained in:
@@ -111,10 +111,15 @@ public object KotlinCompilerClient {
|
||||
}
|
||||
|
||||
|
||||
public fun compile(compilerService: CompileService, targetPlatform: CompileService.TargetPlatform, args: Array<out String>, out: OutputStream): Int {
|
||||
|
||||
val outStrm = RemoteOutputStreamServer(out)
|
||||
return compilerService.remoteCompile(targetPlatform, args, CompilerCallbackServicesFacadeServer(), outStrm, CompileService.OutputFormat.PLAIN, outStrm)
|
||||
public fun compile(compilerService: CompileService,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
args: Array<out String>,
|
||||
out: OutputStream,
|
||||
port: Int = SOCKET_ANY_FREE_PORT,
|
||||
operationsTracer: RemoteOperationsTracer? = null
|
||||
): Int {
|
||||
val outStrm = RemoteOutputStreamServer(out, port = port)
|
||||
return compilerService.remoteCompile(targetPlatform, args, CompilerCallbackServicesFacadeServer(port = port), outStrm, CompileService.OutputFormat.PLAIN, outStrm, operationsTracer)
|
||||
}
|
||||
|
||||
|
||||
@@ -124,16 +129,20 @@ public object KotlinCompilerClient {
|
||||
callbackServices: CompilationServices,
|
||||
compilerOut: OutputStream,
|
||||
daemonOut: OutputStream,
|
||||
profiler: Profiler = DummyProfiler()
|
||||
port: Int = SOCKET_ANY_FREE_PORT,
|
||||
profiler: Profiler = DummyProfiler(),
|
||||
operationsTracer: RemoteOperationsTracer? = null
|
||||
): Int = profiler.withMeasure(this) {
|
||||
compileService.remoteIncrementalCompile(
|
||||
targetPlatform,
|
||||
args,
|
||||
CompilerCallbackServicesFacadeServer(incrementalCompilationComponents = callbackServices.incrementalCompilationComponents,
|
||||
compilationCancelledStatus = callbackServices.compilationCanceledStatus),
|
||||
RemoteOutputStreamServer(compilerOut),
|
||||
compilationCancelledStatus = callbackServices.compilationCanceledStatus,
|
||||
port = port),
|
||||
RemoteOutputStreamServer(compilerOut, port),
|
||||
CompileService.OutputFormat.XML,
|
||||
RemoteOutputStreamServer(daemonOut))
|
||||
RemoteOutputStreamServer(daemonOut, port),
|
||||
operationsTracer)
|
||||
}
|
||||
|
||||
public val COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY: String = "kotlin.daemon.client.options"
|
||||
@@ -207,7 +216,7 @@ public object KotlinCompilerClient {
|
||||
val memBefore = daemon.getUsedMemory() / 1024
|
||||
val startTime = System.nanoTime()
|
||||
|
||||
val res = daemon.remoteCompile(CompileService.TargetPlatform.JVM, filteredArgs.toArrayList().toTypedArray(), servicesFacade, outStrm, CompileService.OutputFormat.PLAIN, outStrm)
|
||||
val res = daemon.remoteCompile(CompileService.TargetPlatform.JVM, filteredArgs.toArrayList().toTypedArray(), servicesFacade, outStrm, CompileService.OutputFormat.PLAIN, outStrm, null)
|
||||
|
||||
val endTime = System.nanoTime()
|
||||
println("Compilation result code: $res")
|
||||
|
||||
@@ -46,7 +46,9 @@ public interface CompileService : Remote {
|
||||
args: Array<out String>,
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
outputFormat: OutputFormat, serviceOutputStream: RemoteOutputStream
|
||||
outputFormat: OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): Int
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
@@ -56,6 +58,7 @@ public interface CompileService : Remote {
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
compilerOutputFormat: OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): Int
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@ import java.io.Serializable
|
||||
import java.net.InetAddress
|
||||
import java.net.ServerSocket
|
||||
import java.net.Socket
|
||||
import java.rmi.RemoteException
|
||||
import java.rmi.registry.LocateRegistry
|
||||
import java.rmi.registry.Registry
|
||||
import java.rmi.server.RMIClientSocketFactory
|
||||
import java.rmi.server.RMIServerSocketFactory
|
||||
import java.util.*
|
||||
|
||||
|
||||
public val SOCKET_ANY_FREE_PORT = 0
|
||||
@@ -70,4 +74,22 @@ public object LoopbackNetworkInterface {
|
||||
}
|
||||
|
||||
|
||||
private val portSelectionRng = Random()
|
||||
|
||||
public fun findPortAndCreateRegistry(attempts: Int, portRangeStart: Int, portRangeEnd: Int) : Pair<Registry, Int> {
|
||||
var i = 0
|
||||
var lastException: RemoteException? = null
|
||||
|
||||
while (i++ < attempts) {
|
||||
val port = portSelectionRng.nextInt(portRangeEnd - portRangeStart) + portRangeStart
|
||||
try {
|
||||
return Pair(LocateRegistry.createRegistry(port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory), port)
|
||||
}
|
||||
catch (e: RemoteException) {
|
||||
// assuming that the port is already taken
|
||||
lastException = e
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Cannot find free port in $attempts attempts", lastException)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.rmi
|
||||
|
||||
import java.rmi.Remote
|
||||
import java.rmi.RemoteException
|
||||
|
||||
public interface RemoteOperationsTracer : Remote {
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
public fun before(id: String)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
public fun after(id: String)
|
||||
}
|
||||
@@ -16,18 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.rmi
|
||||
|
||||
import java.io.IOException
|
||||
import java.rmi.Remote
|
||||
import java.rmi.RemoteException
|
||||
|
||||
public interface RemoteOutputStream : Remote {
|
||||
|
||||
@Throws(IOException::class, RemoteException::class)
|
||||
@Throws(RemoteException::class)
|
||||
public fun close()
|
||||
|
||||
@Throws(IOException::class, RemoteException::class)
|
||||
@Throws(RemoteException::class)
|
||||
public fun write(data: ByteArray, offset: Int, length: Int)
|
||||
|
||||
@Throws(IOException::class, RemoteException::class)
|
||||
@Throws(RemoteException::class)
|
||||
public fun write(dataByte: Int)
|
||||
}
|
||||
|
||||
@@ -26,9 +26,6 @@ import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.net.URLClassLoader
|
||||
import java.rmi.RemoteException
|
||||
import java.rmi.registry.LocateRegistry
|
||||
import java.rmi.registry.Registry
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.jar.Manifest
|
||||
@@ -121,7 +118,7 @@ public object CompileDaemon {
|
||||
//
|
||||
// setDaemonPpermissions(daemonOptions.port)
|
||||
|
||||
val (registry, port) = createRegistry(COMPILE_DAEMON_FIND_PORT_ATTEMPTS)
|
||||
val (registry, port) = findPortAndCreateRegistry(COMPILE_DAEMON_FIND_PORT_ATTEMPTS, COMPILE_DAEMON_PORTS_RANGE_START, COMPILE_DAEMON_PORTS_RANGE_END)
|
||||
val runFileDir = File(if (daemonOptions.runFilesPath.isBlank()) COMPILE_DAEMON_DEFAULT_RUN_DIR_PATH else daemonOptions.runFilesPath)
|
||||
runFileDir.mkdirs()
|
||||
val runFile = File(runFileDir,
|
||||
@@ -199,23 +196,4 @@ public object CompileDaemon {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
val random = Random()
|
||||
|
||||
private fun createRegistry(attempts: Int) : Pair<Registry, Int> {
|
||||
var i = 0
|
||||
var lastException: RemoteException? = null
|
||||
|
||||
while (i++ < attempts) {
|
||||
val port = random.nextInt(COMPILE_DAEMON_PORTS_RANGE_END - COMPILE_DAEMON_PORTS_RANGE_START) + COMPILE_DAEMON_PORTS_RANGE_START
|
||||
try {
|
||||
return Pair(LocateRegistry.createRegistry(port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory), port)
|
||||
}
|
||||
catch (e: RemoteException) {
|
||||
// assuming that the port is already taken
|
||||
lastException = e
|
||||
}
|
||||
}
|
||||
throw IllegalStateException("Cannot find free port in $attempts attempts", lastException)
|
||||
}
|
||||
}
|
||||
@@ -76,9 +76,11 @@ class CompileServiceImpl(
|
||||
args: Array<out String>,
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
outputFormat: CompileService.OutputFormat, serviceOutputStream: RemoteOutputStream
|
||||
outputFormat: CompileService.OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): Int =
|
||||
doCompile(args, compilerOutputStream, serviceOutputStream) { printStream, profiler ->
|
||||
doCompile(args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, profiler ->
|
||||
when (outputFormat) {
|
||||
CompileService.OutputFormat.PLAIN -> compiler[targetPlatform].exec(printStream, *args)
|
||||
CompileService.OutputFormat.XML -> compiler[targetPlatform].execAndOutputXml(printStream, createCompileServices(servicesFacade, profiler), *args)
|
||||
@@ -90,9 +92,10 @@ class CompileServiceImpl(
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
compilerOutputFormat: CompileService.OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): Int =
|
||||
doCompile(args, compilerOutputStream, serviceOutputStream) { printStream, profiler ->
|
||||
doCompile(args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, profiler ->
|
||||
when (compilerOutputFormat) {
|
||||
CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation")
|
||||
CompileService.OutputFormat.XML -> compiler[targetPlatform].execAndOutputXml(printStream, createCompileServices(servicesFacade, profiler), *args)
|
||||
@@ -137,8 +140,13 @@ class CompileServiceImpl(
|
||||
alive = true
|
||||
}
|
||||
|
||||
private fun doCompile(args: Array<out String>, compilerMessagesStreamProxy: RemoteOutputStream, serviceOutputStreamProxy: RemoteOutputStream, body: (PrintStream, Profiler) -> ExitCode): Int =
|
||||
private fun doCompile(args: Array<out String>,
|
||||
compilerMessagesStreamProxy: RemoteOutputStream,
|
||||
serviceOutputStreamProxy: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?,
|
||||
body: (PrintStream, Profiler) -> ExitCode): Int =
|
||||
ifAlive {
|
||||
operationsTracer?.before("compile")
|
||||
val rpcProfiler = if (daemonOptions.reportPerf) WallAndThreadTotalProfiler() else DummyProfiler()
|
||||
val compilerMessagesStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(compilerMessagesStreamProxy, rpcProfiler), 4096))
|
||||
val serviceOutputStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(serviceOutputStreamProxy, rpcProfiler), 4096))
|
||||
@@ -152,6 +160,7 @@ class CompileServiceImpl(
|
||||
finally {
|
||||
serviceOutputStream.flush()
|
||||
compilerMessagesStream.flush()
|
||||
operationsTracer?.after("compile")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user