From 2dfca72f383633bc100514df5dbecddcf3609e21 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 22 Oct 2015 15:13:45 +0200 Subject: [PATCH] Passing port through daemon client API to allow port reusing for client-side components, introducing operations tracer interface for testing purposes --- .../rmi/kotlinr/KotlinCompilerClient.kt | 27 +++++++++++------ .../jetbrains/kotlin/rmi/CompileService.kt | 7 +++-- .../org/jetbrains/kotlin/rmi/NetworkUtils.kt | 22 ++++++++++++++ .../kotlin/rmi/RemoteOperationsTracer.kt | 29 +++++++++++++++++++ .../kotlin/rmi/RemoteOutputStream.kt | 7 ++--- .../kotlin/rmi/service/CompileDaemon.kt | 24 +-------------- .../kotlin/rmi/service/CompileServiceImpl.kt | 19 ++++++++---- 7 files changed, 92 insertions(+), 43 deletions(-) create mode 100644 compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOperationsTracer.kt diff --git a/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/KotlinCompilerClient.kt b/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/KotlinCompilerClient.kt index afd46aac493..998e45df1d4 100644 --- a/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/KotlinCompilerClient.kt +++ b/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/KotlinCompilerClient.kt @@ -111,10 +111,15 @@ public object KotlinCompilerClient { } - public fun compile(compilerService: CompileService, targetPlatform: CompileService.TargetPlatform, args: Array, 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: 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") diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt index c1331c0975b..7126838ad53 100644 --- a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt @@ -46,7 +46,9 @@ public interface CompileService : Remote { args: Array, 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 } diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/NetworkUtils.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/NetworkUtils.kt index b2bf4d95bae..b5e7ea388b7 100644 --- a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/NetworkUtils.kt +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/NetworkUtils.kt @@ -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 { + 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) +} diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOperationsTracer.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOperationsTracer.kt new file mode 100644 index 00000000000..1494cc88b2b --- /dev/null +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOperationsTracer.kt @@ -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) +} diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.kt index c480490d3b7..848bb7591a9 100644 --- a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.kt +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.kt @@ -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) } diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileDaemon.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileDaemon.kt index efda358ec14..e46614666d9 100644 --- a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileDaemon.kt +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileDaemon.kt @@ -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 { - 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) - } } \ No newline at end of file diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt index 4892f9ac91a..d384e57bb15 100644 --- a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt @@ -76,9 +76,11 @@ class CompileServiceImpl( args: Array, 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, compilerMessagesStreamProxy: RemoteOutputStream, serviceOutputStreamProxy: RemoteOutputStream, body: (PrintStream, Profiler) -> ExitCode): Int = + private fun doCompile(args: Array, + 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") } }