From 06b3ca8343654c842186bb7e95f0e3de3a41f25c Mon Sep 17 00:00:00 2001 From: ligee Date: Mon, 10 Aug 2015 18:15:29 +0200 Subject: [PATCH] Initial version of rmi-interface, compile server and kotlinr - commandline compile server client app --- .idea/modules.xml | 3 + build.xml | 24 ++++- compiler/rmi/kotlinr/kotlinr.iml | 13 +++ .../rmi/kotlinr/src/KotlinCompilerClient.kt | 49 ++++++++++ .../kotlinr/src/RemoteOutputStreamServer.kt | 42 +++++++++ compiler/rmi/rmi-interface/rmi-interface.iml | 13 +++ .../jetbrains/kotlin/rmi/CompilerFacade.java | 43 +++++++++ .../kotlin/rmi/RemoteOutputStream.java | 30 ++++++ compiler/rmi/rmi-server/rmi-server.iml | 16 ++++ .../kotlin/rmi/service/CompileServer.kt | 47 ++++++++++ .../kotlin/rmi/service/CompilerFacadeImpl.kt | 92 +++++++++++++++++++ .../rmi/service/RemoteOutputStreamClient.kt | 34 +++++++ 12 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 compiler/rmi/kotlinr/kotlinr.iml create mode 100644 compiler/rmi/kotlinr/src/KotlinCompilerClient.kt create mode 100644 compiler/rmi/kotlinr/src/RemoteOutputStreamServer.kt create mode 100644 compiler/rmi/rmi-interface/rmi-interface.iml create mode 100644 compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompilerFacade.java create mode 100644 compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.java create mode 100644 compiler/rmi/rmi-server/rmi-server.iml create mode 100644 compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServer.kt create mode 100644 compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompilerFacadeImpl.kt create mode 100644 compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteOutputStreamClient.kt diff --git a/.idea/modules.xml b/.idea/modules.xml index 21e53538f25..8bd75e0c6c8 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -50,10 +50,13 @@ + + + diff --git a/build.xml b/build.xml index 53607d88ee4..6ef2272dc24 100644 --- a/build.xml +++ b/build.xml @@ -86,6 +86,8 @@ + + @@ -535,6 +537,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -839,7 +861,7 @@ depends="builtins,stdlib,core,reflection,pack-runtime,pack-runtime-sources"/> + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/rmi/kotlinr/src/KotlinCompilerClient.kt b/compiler/rmi/kotlinr/src/KotlinCompilerClient.kt new file mode 100644 index 00000000000..e37a030ec69 --- /dev/null +++ b/compiler/rmi/kotlinr/src/KotlinCompilerClient.kt @@ -0,0 +1,49 @@ +/* + * 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.kotlinr + +import org.jetbrains.kotlin.rmi.CompilerFacade +import java.rmi.registry.LocateRegistry +import kotlin.platform.platformStatic + +public class KotlinCompilerClient { + + companion object { + platformStatic public fun main(vararg args: String) { + val compilerObj = LocateRegistry.getRegistry("localhost", 17031).lookup("KotlinJvmCompilerService") + if (compilerObj == null) + println("Unable to find compiler service") + else { + val compiler = compilerObj as? CompilerFacade + if (compiler == null) + println("Unable to cast compiler service: ${compilerObj.javaClass}") + else { + println("Executing daemon compilation with args: " + args.joinToString(" ")) + val outStrm = RemoteOutputStreamServer(System.out) + try { + val res = compiler.remoteCompile(args, outStrm, CompilerFacade.OutputFormat.PLAIN) + println("Compilation result code: $res") + } + finally { + outStrm.close() + } + } + } + } + } +} + diff --git a/compiler/rmi/kotlinr/src/RemoteOutputStreamServer.kt b/compiler/rmi/kotlinr/src/RemoteOutputStreamServer.kt new file mode 100644 index 00000000000..9e3ed540291 --- /dev/null +++ b/compiler/rmi/kotlinr/src/RemoteOutputStreamServer.kt @@ -0,0 +1,42 @@ +/* + * 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.kotlinr + +import org.jetbrains.kotlin.rmi.RemoteOutputStream +import java.io.OutputStream +import java.rmi.server.UnicastRemoteObject + + +class RemoteOutputStreamServer(val out: OutputStream) : RemoteOutputStream { + + init { + UnicastRemoteObject.exportObject(this, 0) + } + + override fun close() { + out.close() + UnicastRemoteObject.unexportObject(this, true) + } + + override fun write(data: ByteArray, start: Int, length: Int) { + out.write(data, start, length) + } + + override fun write(dataByte: Int) { + out.write(dataByte) + } +} diff --git a/compiler/rmi/rmi-interface/rmi-interface.iml b/compiler/rmi/rmi-interface/rmi-interface.iml new file mode 100644 index 00000000000..0bd974ce23a --- /dev/null +++ b/compiler/rmi/rmi-interface/rmi-interface.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompilerFacade.java b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompilerFacade.java new file mode 100644 index 00000000000..9401cd62316 --- /dev/null +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompilerFacade.java @@ -0,0 +1,43 @@ +/* + * 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 org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.util.Map; + + +public interface CompilerFacade extends Remote { + + enum OutputFormat implements java.io.Serializable { + PLAIN, + XML + } + + interface RemoteIncrementalCache extends Remote, IncrementalCache {} + + + int remoteCompile(String[] args, RemoteOutputStream errStream, OutputFormat outputFormat) throws RemoteException; + + int remoteIncrementalCompile( + String[] args, + Map caches, + RemoteOutputStream outputStream, + OutputFormat outputFormat + ) throws RemoteException; +} diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.java b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.java new file mode 100644 index 00000000000..09694f0fdfb --- /dev/null +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/RemoteOutputStream.java @@ -0,0 +1,30 @@ +/* + * 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.io.IOException; +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface RemoteOutputStream extends Remote { + + void close() throws IOException, RemoteException; + + void write(byte[] data, int offset, int length) throws IOException, RemoteException; + + void write(int dataByte) throws IOException, RemoteException; +} diff --git a/compiler/rmi/rmi-server/rmi-server.iml b/compiler/rmi/rmi-server/rmi-server.iml new file mode 100644 index 00000000000..1083739c346 --- /dev/null +++ b/compiler/rmi/rmi-server/rmi-server.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServer.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServer.kt new file mode 100644 index 00000000000..1b2f1c6bf58 --- /dev/null +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServer.kt @@ -0,0 +1,47 @@ +/* + * 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.service + +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler +import org.jetbrains.kotlin.rmi.CompilerFacade +import java.rmi.RMISecurityManager +import java.rmi.registry.LocateRegistry +import java.rmi.server.UnicastRemoteObject +import kotlin.platform.platformStatic + +public class CompileServer { + + companion object { + platformStatic public fun main(args: Array) { + if (System.getSecurityManager() == null) + System.setSecurityManager (RMISecurityManager()) + + val registry = LocateRegistry.createRegistry(17031); + + val server = CompilerFacadeImpl(K2JVMCompiler()) + try { + UnicastRemoteObject.unexportObject(server, false) + } + catch (e: java.rmi.NoSuchObjectException) { + // ignoring if object already exported + } + + val stub = UnicastRemoteObject.exportObject(server, 0) as CompilerFacade + registry.rebind ("KotlinJvmCompilerService", stub); + } + } +} \ No newline at end of file diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompilerFacadeImpl.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompilerFacadeImpl.kt new file mode 100644 index 00000000000..63bab51e845 --- /dev/null +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompilerFacadeImpl.kt @@ -0,0 +1,92 @@ +/* + * 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.service + +import org.jetbrains.kotlin.cli.common.CLICompiler +import org.jetbrains.kotlin.config.Services +import org.jetbrains.kotlin.incremental.components.UsageCollector +import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache +import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents +import org.jetbrains.kotlin.rmi.CompilerFacade +import org.jetbrains.kotlin.rmi.RemoteOutputStream +import java.io.PrintStream +import java.rmi.server.UnicastRemoteObject +import java.util.concurrent.TimeUnit + + +class CompilerFacadeImpl>(val compiler: Compiler) : CompilerFacade, UnicastRemoteObject() { + + public class IncrementalCompilationComponentsImpl(val idToCache: Map): IncrementalCompilationComponents { + override fun getIncrementalCache(moduleId: String): IncrementalCache = idToCache[moduleId]!! + override fun getUsageCollector(): UsageCollector = UsageCollector.DO_NOTHING + } + + private fun createCompileServices(incrementalCaches: Map): Services = + Services.Builder() + .register(javaClass(), IncrementalCompilationComponentsImpl(incrementalCaches)) +// .register(javaClass(), object: CompilationCanceledStatus { +// override fun checkCanceled(): Unit = if (context.getCancelStatus().isCanceled()) throw CompilationCanceledException() +// }) + .build() + + fun usedMemoryKb(): Long { + System.gc() + val rt = Runtime.getRuntime() + return (rt.totalMemory() - rt.freeMemory()) / 1024 + } + + fun checked(args: Array, body: () -> R): R { + try { + if (args.none()) + throw IllegalArgumentException("Error: empty arguments list.") + println("Starting compilation with args: " + args.joinToString(" ")) + val startMem = usedMemoryKb() + val startTime = System.nanoTime() + val res = body() + val endTime = System.nanoTime() + val endMem = usedMemoryKb() + println("Done") + println("Elapsed time: " + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + " ms") + println("Used memory: $endMem kb (${"%+d".format(endMem - startMem)} kb)") + return res + } + catch (e: Exception) { + println("Error: $e") + throw e + } + } + + override fun remoteCompile(args: Array, errStream: RemoteOutputStream, outputFormat: CompilerFacade.OutputFormat): Int = + checked(args) { + val strm = RemoteOutputStreamClient(errStream) + val printStrm = PrintStream(strm) + when (outputFormat) { + CompilerFacade.OutputFormat.PLAIN -> compiler.exec(printStrm, *args) + CompilerFacade.OutputFormat.XML -> compiler.execAndOutputXml(printStrm, Services.EMPTY, *args) + }.code + } + + override fun remoteIncrementalCompile(args: Array, caches: Map, errStream: RemoteOutputStream, outputFormat: CompilerFacade.OutputFormat): Int = + checked(args) { + val strm = RemoteOutputStreamClient(errStream) + val printStrm = PrintStream(strm) + when (outputFormat) { + CompilerFacade.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation") + CompilerFacade.OutputFormat.XML -> compiler.execAndOutputXml(printStrm, createCompileServices(caches), *args) + }.code + } +} diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteOutputStreamClient.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteOutputStreamClient.kt new file mode 100644 index 00000000000..33bd30b3006 --- /dev/null +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteOutputStreamClient.kt @@ -0,0 +1,34 @@ +/* + * 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.service + +import org.jetbrains.kotlin.rmi.RemoteOutputStream +import java.io.OutputStream + +class RemoteOutputStreamClient(val remote: RemoteOutputStream): OutputStream() { + override fun write(data: ByteArray) { + remote.write(data, 0, data.size()) + } + + override fun write(data: ByteArray, offset: Int, length: Int) { + remote.write(data, offset, length) + } + + override fun write(byte: Int) { + remote.write(byte) + } +}