From e8316dedd0a11b5a16a2a885819f5c9d28f62324 Mon Sep 17 00:00:00 2001 From: Clinton Date: Tue, 4 Apr 2017 11:58:56 +0100 Subject: [PATCH] Runnodes now exposes default ports for nodes automatically (#480) Cordformation now automatically assigns a debug port --- constants.properties | 2 +- .../kotlin/net/corda/plugins/NodeRunner.kt | 48 +++++++++++++------ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/constants.properties b/constants.properties index 362f68a1af..a2478b44ba 100644 --- a/constants.properties +++ b/constants.properties @@ -1,3 +1,3 @@ -gradlePluginsVersion=0.10.3 +gradlePluginsVersion=0.10.4 kotlinVersion=1.1.1 guavaVersion=21.0 diff --git a/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt b/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt index c0c8b428eb..6087606b5f 100644 --- a/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt +++ b/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt @@ -20,25 +20,26 @@ private val os: OS by lazy { private enum class OS { MACOS, WINDOWS, LINUX } +data class IncrementalPortAllocator(var basePort: Int = 5005) { + fun next(): Int = basePort++ +} + +val debugPortAlloc: IncrementalPortAllocator = IncrementalPortAllocator() + fun main(args: Array) { val startedProcesses = mutableListOf() val headless = (GraphicsEnvironment.isHeadless() || (!args.isEmpty() && (args[0] == HEADLESS_FLAG))) - val runJar = getJarRunner(headless) val workingDir = Paths.get(System.getProperty("user.dir")).toFile() val javaArgs = args.filter { it != HEADLESS_FLAG } println("Starting nodes in $workingDir") workingDir.list().map { File(workingDir, it) }.forEach { if (isNode(it)) { - println("Starting node in $it") - startedProcesses.add(runJar(nodeJarName, it, javaArgs)) - if (os == OS.MACOS) Thread.sleep(1000) + startedProcesses += startJarProcess(headless, it, nodeJarName, javaArgs) } if (isWebserver(it)) { - println("Starting webserver in $it") - startedProcesses.add(runJar(webJarName, it, javaArgs)) - if (os == OS.MACOS) Thread.sleep(1000) + startedProcesses += startJarProcess(headless, it, webJarName, javaArgs) } } @@ -46,32 +47,49 @@ fun main(args: Array) { println("Finished starting nodes") } +private fun startJarProcess(headless: Boolean, dir: File, jarName: String, javaArgs: List) : Process { + val runJar = getJarRunner(headless) + val debugPort = debugPortAlloc.next() + println("Starting $jarName in $dir on debug port $debugPort") + val proc = runJar(jarName, dir, javaArgs, debugPort) + if (os == OS.MACOS) Thread.sleep(1000) + return proc +} + private fun isNode(maybeNodeDir: File) = maybeNodeDir.isDirectory && File(maybeNodeDir, nodeJarName).exists() - && File(maybeNodeDir, webJarName).exists() && File(maybeNodeDir, nodeConfName).exists() -private fun isWebserver(maybeWebserverDir: File) = isNode(maybeWebserverDir) && hasWebserverPort(maybeWebserverDir) +private fun isWebserver(maybeWebserverDir: File) = maybeWebserverDir.isDirectory + && File(maybeWebserverDir, webJarName).exists() + && File(maybeWebserverDir, nodeConfName).exists() + && hasWebserverPort(maybeWebserverDir) // TODO: Add a webserver.conf, or use TypeSafe config instead of this hack private fun hasWebserverPort(nodeConfDir: File) = Files.readAllLines(File(nodeConfDir, nodeConfName).toPath()).joinToString { it }.contains("webAddress") -private fun getJarRunner(headless: Boolean): (String, File, List) -> Process = if (headless) ::execJar else ::execJarInTerminalWindow +private fun getDebugPortArg(debugPort: Int?) = if (debugPort != null) { + listOf("""-Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort"""") +} else { + emptyList() +} -private fun execJar(jarName: String, dir: File, args: List = listOf()): Process { +private fun getJarRunner(headless: Boolean): (String, File, List, Int?) -> Process = if (headless) ::execJar else ::execJarInTerminalWindow + +private fun execJar(jarName: String, dir: File, args: List = listOf(), debugPort: Int?): Process { val nodeName = dir.toPath().fileName val separator = System.getProperty("file.separator") val path = System.getProperty("java.home") + separator + "bin" + separator + "java" - val builder = ProcessBuilder(listOf(path, "-Dname=$nodeName", "-jar", jarName) + args) + val builder = ProcessBuilder(listOf(path, "-Dname=$nodeName") + getDebugPortArg(debugPort) + listOf("-jar", jarName) + args) builder.redirectError(Paths.get("error.${dir.toPath().fileName}.log").toFile()) builder.inheritIO() builder.directory(dir) return builder.start() } -private fun execJarInTerminalWindow(jarName: String, dir: File, args: List = listOf()): Process { - val javaCmd = "java -jar $jarName " + args.joinToString(" ") { it } - val nodeName = "${dir.toPath().fileName} $jarName" +private fun execJarInTerminalWindow(jarName: String, dir: File, args: List = listOf(), debugPort: Int?): Process { + val nodeName = "${dir.toPath().fileName}-$jarName" + val javaCmd = (listOf("java", "-Dname=$nodeName") + getDebugPortArg(debugPort) + listOf("-jar", jarName) + args).joinToString(" ") { it } val builder = when (os) { OS.MACOS -> ProcessBuilder( "osascript", "-e",