mirror of
https://github.com/corda/corda.git
synced 2025-02-27 11:36:42 +00:00
On exit, the driver will automaticallly shutdown any nodes which weren't waited for.
The motivation for this came with the recent change that a default notary is started by the driver, which if ignored will leak the notary process. Also, waitForAllNodesToFinish() has been replaced by a driver parameter.
This commit is contained in:
parent
b0af1c715c
commit
2fe41715cc
13
.idea/compiler.xml
generated
13
.idea/compiler.xml
generated
@ -16,6 +16,9 @@
|
|||||||
<module name="client_test" target="1.8" />
|
<module name="client_test" target="1.8" />
|
||||||
<module name="confidential-identities_main" target="1.8" />
|
<module name="confidential-identities_main" target="1.8" />
|
||||||
<module name="confidential-identities_test" target="1.8" />
|
<module name="confidential-identities_test" target="1.8" />
|
||||||
|
<module name="corda-core_integrationTest" target="1.8" />
|
||||||
|
<module name="corda-core_smokeTest" target="1.8" />
|
||||||
|
<module name="corda-finance_integrationTest" target="1.8" />
|
||||||
<module name="corda-project_main" target="1.8" />
|
<module name="corda-project_main" target="1.8" />
|
||||||
<module name="corda-project_test" target="1.8" />
|
<module name="corda-project_test" target="1.8" />
|
||||||
<module name="corda-webserver_integrationTest" target="1.8" />
|
<module name="corda-webserver_integrationTest" target="1.8" />
|
||||||
@ -43,6 +46,8 @@
|
|||||||
<module name="example-code_integrationTest" target="1.8" />
|
<module name="example-code_integrationTest" target="1.8" />
|
||||||
<module name="example-code_main" target="1.8" />
|
<module name="example-code_main" target="1.8" />
|
||||||
<module name="example-code_test" target="1.8" />
|
<module name="example-code_test" target="1.8" />
|
||||||
|
<module name="experimental-kryo-hook_main" target="1.8" />
|
||||||
|
<module name="experimental-kryo-hook_test" target="1.8" />
|
||||||
<module name="experimental_main" target="1.8" />
|
<module name="experimental_main" target="1.8" />
|
||||||
<module name="experimental_test" target="1.8" />
|
<module name="experimental_test" target="1.8" />
|
||||||
<module name="explorer-capsule_main" target="1.6" />
|
<module name="explorer-capsule_main" target="1.6" />
|
||||||
@ -54,8 +59,13 @@
|
|||||||
<module name="finance_test" target="1.8" />
|
<module name="finance_test" target="1.8" />
|
||||||
<module name="graphs_main" target="1.8" />
|
<module name="graphs_main" target="1.8" />
|
||||||
<module name="graphs_test" target="1.8" />
|
<module name="graphs_test" target="1.8" />
|
||||||
|
<module name="irs-demo-cordapp_integrationTest" target="1.8" />
|
||||||
<module name="irs-demo-cordapp_main" target="1.8" />
|
<module name="irs-demo-cordapp_main" target="1.8" />
|
||||||
|
<module name="irs-demo-cordapp_main~1" target="1.8" />
|
||||||
<module name="irs-demo-cordapp_test" target="1.8" />
|
<module name="irs-demo-cordapp_test" target="1.8" />
|
||||||
|
<module name="irs-demo-cordapp_test~1" target="1.8" />
|
||||||
|
<module name="irs-demo-web_main" target="1.8" />
|
||||||
|
<module name="irs-demo-web_test" target="1.8" />
|
||||||
<module name="irs-demo_integrationTest" target="1.8" />
|
<module name="irs-demo_integrationTest" target="1.8" />
|
||||||
<module name="irs-demo_main" target="1.8" />
|
<module name="irs-demo_main" target="1.8" />
|
||||||
<module name="irs-demo_test" target="1.8" />
|
<module name="irs-demo_test" target="1.8" />
|
||||||
@ -106,6 +116,9 @@
|
|||||||
<module name="simm-valuation-demo_test" target="1.8" />
|
<module name="simm-valuation-demo_test" target="1.8" />
|
||||||
<module name="smoke-test-utils_main" target="1.8" />
|
<module name="smoke-test-utils_main" target="1.8" />
|
||||||
<module name="smoke-test-utils_test" target="1.8" />
|
<module name="smoke-test-utils_test" target="1.8" />
|
||||||
|
<module name="source-example-code_integrationTest" target="1.8" />
|
||||||
|
<module name="source-example-code_main" target="1.8" />
|
||||||
|
<module name="source-example-code_test" target="1.8" />
|
||||||
<module name="test-common_main" target="1.8" />
|
<module name="test-common_main" target="1.8" />
|
||||||
<module name="test-common_test" target="1.8" />
|
<module name="test-common_test" target="1.8" />
|
||||||
<module name="test-utils_integrationTest" target="1.8" />
|
<module name="test-utils_integrationTest" target="1.8" />
|
||||||
|
@ -83,6 +83,8 @@ UNRELEASED
|
|||||||
* Replaced node configuration parameter ``certificateSigningService`` with ``compatibilityZoneURL``, which is Corda
|
* Replaced node configuration parameter ``certificateSigningService`` with ``compatibilityZoneURL``, which is Corda
|
||||||
compatibility zone network management service's address.
|
compatibility zone network management service's address.
|
||||||
|
|
||||||
|
* ``waitForAllNodesToFinish()`` method in ``DriverDSLExposedInterface`` has instead become a parameter on driver creation.
|
||||||
|
|
||||||
.. _changelog_v1:
|
.. _changelog_v1:
|
||||||
|
|
||||||
Release 1.0
|
Release 1.0
|
||||||
|
@ -48,7 +48,7 @@ fun main(args: Array<String>) {
|
|||||||
startFlow<CashExitFlow>(),
|
startFlow<CashExitFlow>(),
|
||||||
invokeRpc(CordaRPCOps::nodeInfo)
|
invokeRpc(CordaRPCOps::nodeInfo)
|
||||||
))
|
))
|
||||||
driver(driverDirectory = baseDirectory, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
driver(driverDirectory = baseDirectory, extraCordappPackagesToScan = listOf("net.corda.finance"), waitForAllNodesToFinish = true) {
|
||||||
val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)).get()
|
val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)).get()
|
||||||
// END 1
|
// END 1
|
||||||
|
|
||||||
@ -96,7 +96,6 @@ fun main(args: Array<String>) {
|
|||||||
graph.display()
|
graph.display()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitForAllNodesToFinish()
|
|
||||||
// END 5
|
// END 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ IntelliJ
|
|||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
// No permissions required as we are not invoking flows.
|
// No permissions required as we are not invoking flows.
|
||||||
val user = User("user1", "test", permissions = setOf())
|
val user = User("user1", "test", permissions = setOf())
|
||||||
driver(isDebug = true) {
|
driver(isDebug = true, waitForNodesToFinish = true) {
|
||||||
startNode(getX500Name(O="Controller",L="London",C='GB"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
startNode(getX500Name(O="Controller",L="London",C='GB"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
||||||
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
||||||
startNode(getX500Name(O="PartyA",L="London",C="GB"), rpcUsers = listOf(user)),
|
startNode(getX500Name(O="PartyA",L="London",C="GB"), rpcUsers = listOf(user)),
|
||||||
@ -293,8 +293,6 @@ IntelliJ
|
|||||||
startWebserver(nodeA)
|
startWebserver(nodeA)
|
||||||
startWebserver(nodeB)
|
startWebserver(nodeB)
|
||||||
startWebserver(nodeC)
|
startWebserver(nodeC)
|
||||||
|
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +503,7 @@ Debugging is done via IntelliJ as follows:
|
|||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
// No permissions required as we are not invoking flows.
|
// No permissions required as we are not invoking flows.
|
||||||
val user = User("user1", "test", permissions = setOf())
|
val user = User("user1", "test", permissions = setOf())
|
||||||
driver(isDebug = true) {
|
driver(isDebug = true, waitForNodesToFinish = true) {
|
||||||
startNode(getX500Name(O="Controller",L="London",C="GB"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
startNode(getX500Name(O="Controller",L="London",C="GB"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
||||||
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
||||||
startNode(getX500Name(O="PartyA",L=London,C=GB"), rpcUsers = listOf(user)),
|
startNode(getX500Name(O="PartyA",L=London,C=GB"), rpcUsers = listOf(user)),
|
||||||
@ -515,8 +513,6 @@ Debugging is done via IntelliJ as follows:
|
|||||||
startWebserver(nodeA)
|
startWebserver(nodeA)
|
||||||
startWebserver(nodeB)
|
startWebserver(nodeB)
|
||||||
startWebserver(nodeC)
|
startWebserver(nodeC)
|
||||||
|
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,8 @@ import net.corda.testing.driver.driver
|
|||||||
*/
|
*/
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
|
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
|
||||||
driver(isDebug = true, driverDirectory = "build" / "attachment-demo-nodes") {
|
driver(isDebug = true, driverDirectory = "build" / "attachment-demo-nodes", waitForAllNodesToFinish = true) {
|
||||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
|
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
|
||||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
|
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ private class BankOfCordaDriver {
|
|||||||
try {
|
try {
|
||||||
when (role) {
|
when (role) {
|
||||||
Role.ISSUER -> {
|
Role.ISSUER -> {
|
||||||
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset")) {
|
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset"), waitForAllNodesToFinish = true) {
|
||||||
val bankUser = User(
|
val bankUser = User(
|
||||||
BANK_USERNAME,
|
BANK_USERNAME,
|
||||||
"test",
|
"test",
|
||||||
@ -76,7 +76,6 @@ private class BankOfCordaDriver {
|
|||||||
startFlow<CashConfigDataFlow>()))
|
startFlow<CashConfigDataFlow>()))
|
||||||
startNode(providedName = BIGCORP_LEGAL_NAME, rpcUsers = listOf(bigCorpUser))
|
startNode(providedName = BIGCORP_LEGAL_NAME, rpcUsers = listOf(bigCorpUser))
|
||||||
startWebserver(bankOfCorda.get())
|
startWebserver(bankOfCorda.get())
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -10,7 +10,7 @@ import net.corda.testing.driver.driver
|
|||||||
* Do not use in a production environment.
|
* Do not use in a production environment.
|
||||||
*/
|
*/
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
driver(useTestClock = true, isDebug = true) {
|
driver(useTestClock = true, isDebug = true, waitForAllNodesToFinish = true) {
|
||||||
val (nodeA, nodeB) = listOf(
|
val (nodeA, nodeB) = listOf(
|
||||||
startNode(providedName = DUMMY_BANK_A.name),
|
startNode(providedName = DUMMY_BANK_A.name),
|
||||||
startNode(providedName = DUMMY_BANK_B.name)
|
startNode(providedName = DUMMY_BANK_B.name)
|
||||||
@ -20,7 +20,5 @@ fun main(args: Array<String>) {
|
|||||||
startWebserver(controller)
|
startWebserver(controller)
|
||||||
startWebserver(nodeA)
|
startWebserver(nodeA)
|
||||||
startWebserver(nodeB)
|
startWebserver(nodeB)
|
||||||
|
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package net.corda.test.spring
|
package net.corda.test.spring
|
||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.internal.concurrent.flatMap
|
|
||||||
import net.corda.core.internal.concurrent.fork
|
|
||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.testing.driver.*
|
import net.corda.testing.driver.*
|
||||||
@ -14,7 +12,6 @@ import java.net.ConnectException
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
interface SpringDriverExposedDSLInterface : DriverDSLExposedInterface {
|
interface SpringDriverExposedDSLInterface : DriverDSLExposedInterface {
|
||||||
@ -62,17 +59,17 @@ fun <A> springDriver(
|
|||||||
coerce = { it }, dsl = dsl
|
coerce = { it }, dsl = dsl
|
||||||
)
|
)
|
||||||
|
|
||||||
data class SpringBootDriverDSL(
|
data class SpringBootDriverDSL(private val driverDSL: DriverDSL) : DriverDSLInternalInterface by driverDSL, SpringDriverInternalDSLInterface {
|
||||||
val driverDSL: DriverDSL
|
companion object {
|
||||||
) : DriverDSLInternalInterface by driverDSL, SpringDriverInternalDSLInterface {
|
|
||||||
|
|
||||||
val log = loggerFor<SpringBootDriverDSL>()
|
val log = loggerFor<SpringBootDriverDSL>()
|
||||||
|
}
|
||||||
|
|
||||||
override fun startSpringBootWebapp(clazz: Class<*>, handle: NodeHandle, checkUrl: String): CordaFuture<WebserverHandle> {
|
override fun startSpringBootWebapp(clazz: Class<*>, handle: NodeHandle, checkUrl: String): CordaFuture<WebserverHandle> {
|
||||||
val debugPort = if (driverDSL.isDebug) driverDSL.debugPortAllocation.nextPort() else null
|
val debugPort = if (driverDSL.isDebug) driverDSL.debugPortAllocation.nextPort() else null
|
||||||
val processFuture = startApplication(driverDSL.executorService, handle, debugPort, clazz)
|
val process = startApplication(handle, debugPort, clazz)
|
||||||
driverDSL.registerProcess(processFuture)
|
driverDSL.shutdownManager.registerProcessShutdown(process)
|
||||||
return processFuture.map { queryWebserver(handle, it, checkUrl) }
|
val webReadyFuture = addressMustBeBoundFuture(driverDSL.executorService, handle.webAddress, process)
|
||||||
|
return webReadyFuture.map { queryWebserver(handle, process, checkUrl) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queryWebserver(handle: NodeHandle, process: Process, checkUrl: String): WebserverHandle {
|
private fun queryWebserver(handle: NodeHandle, process: Process, checkUrl: String): WebserverHandle {
|
||||||
@ -99,10 +96,9 @@ data class SpringBootDriverDSL(
|
|||||||
throw IllegalStateException("Webserver at ${handle.webAddress} has died or was not reachable at URL ${url}")
|
throw IllegalStateException("Webserver at ${handle.webAddress} has died or was not reachable at URL ${url}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startApplication(executorService: ExecutorService, handle: NodeHandle, debugPort: Int?, clazz: Class<*>): CordaFuture<Process> {
|
private fun startApplication(handle: NodeHandle, debugPort: Int?, clazz: Class<*>): Process {
|
||||||
return executorService.fork {
|
|
||||||
val className = clazz.canonicalName
|
val className = clazz.canonicalName
|
||||||
ProcessUtilities.startJavaProcessImpl(
|
return ProcessUtilities.startJavaProcessImpl(
|
||||||
className = className, // cannot directly get class for this, so just use string
|
className = className, // cannot directly get class for this, so just use string
|
||||||
jdwpPort = debugPort,
|
jdwpPort = debugPort,
|
||||||
extraJvmArguments = listOf(
|
extraJvmArguments = listOf(
|
||||||
@ -122,6 +118,5 @@ data class SpringBootDriverDSL(
|
|||||||
),
|
),
|
||||||
maximumHeapSize = null
|
maximumHeapSize = null
|
||||||
)
|
)
|
||||||
}.flatMap { process -> addressMustBeBoundFuture(driverDSL.executorService, handle.webAddress, process).map { process } }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ import net.corda.testing.driver.driver
|
|||||||
* via the web api.
|
* via the web api.
|
||||||
*/
|
*/
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
driver(isDebug = true) {
|
driver(isDebug = true, waitForAllNodesToFinish = true) {
|
||||||
val (nodeA, nodeB, nodeC) = listOf(
|
val (nodeA, nodeB, nodeC) = listOf(
|
||||||
startNode(providedName = DUMMY_BANK_A.name),
|
startNode(providedName = DUMMY_BANK_A.name),
|
||||||
startNode(providedName = DUMMY_BANK_B.name),
|
startNode(providedName = DUMMY_BANK_B.name),
|
||||||
@ -22,7 +22,5 @@ fun main(args: Array<String>) {
|
|||||||
startWebserver(nodeA)
|
startWebserver(nodeA)
|
||||||
startWebserver(nodeB)
|
startWebserver(nodeB)
|
||||||
startWebserver(nodeC)
|
startWebserver(nodeC)
|
||||||
|
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,12 @@ fun main(args: Array<String>) {
|
|||||||
startFlow<SellerFlow>(),
|
startFlow<SellerFlow>(),
|
||||||
all())
|
all())
|
||||||
val demoUser = listOf(User("demo", "demo", permissions))
|
val demoUser = listOf(User("demo", "demo", permissions))
|
||||||
driver(driverDirectory = "build" / "trader-demo-nodes", isDebug = true) {
|
driver(driverDirectory = "build" / "trader-demo-nodes", isDebug = true, waitForAllNodesToFinish = true) {
|
||||||
val user = User("user1", "test", permissions = setOf(startFlow<CashIssueFlow>(),
|
val user = User("user1", "test", permissions = setOf(startFlow<CashIssueFlow>(),
|
||||||
startFlow<CommercialPaperIssueFlow>(),
|
startFlow<CommercialPaperIssueFlow>(),
|
||||||
startFlow<SellerFlow>()))
|
startFlow<SellerFlow>()))
|
||||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
|
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
|
||||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
|
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
|
||||||
startNode(providedName = BOC.name, rpcUsers = listOf(user))
|
startNode(providedName = BOC.name, rpcUsers = listOf(user))
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,16 @@ import net.corda.core.internal.readLines
|
|||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.NodeStartup
|
import net.corda.node.internal.NodeStartup
|
||||||
import net.corda.testing.DUMMY_BANK_A
|
import net.corda.testing.DUMMY_BANK_A
|
||||||
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.DUMMY_REGULATOR
|
import net.corda.testing.DUMMY_REGULATOR
|
||||||
import net.corda.testing.ProjectStructure.projectRootDir
|
import net.corda.testing.ProjectStructure.projectRootDir
|
||||||
|
import net.corda.testing.node.NotarySpec
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.ScheduledExecutorService
|
import java.util.concurrent.ScheduledExecutorService
|
||||||
|
|
||||||
class DriverTests {
|
class DriverTests {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
|
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
|
||||||
|
|
||||||
@ -62,4 +63,19 @@ class DriverTests {
|
|||||||
assertThat(debugLinesPresent).isTrue()
|
assertThat(debugLinesPresent).isTrue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `started node, which is not waited for in the driver, is shutdown when the driver exits`() {
|
||||||
|
// First check that the process-id file is created by the node on startup, so that we can be sure our check that
|
||||||
|
// it's deleted on shutdown isn't a false-positive.
|
||||||
|
driver {
|
||||||
|
val baseDirectory = defaultNotaryNode.getOrThrow().configuration.baseDirectory
|
||||||
|
assertThat(baseDirectory / "process-id").exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
val baseDirectory = driver(notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name))) {
|
||||||
|
(this as DriverDSL).baseDirectory(DUMMY_NOTARY.name)
|
||||||
|
}
|
||||||
|
assertThat(baseDirectory / "process-id").doesNotExist()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ import net.corda.nodeapi.internal.addShutdownHook
|
|||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
import net.corda.testing.common.internal.NetworkParametersCopier
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.setGlobalSerialization
|
|
||||||
import net.corda.testing.internal.ProcessUtilities
|
import net.corda.testing.internal.ProcessUtilities
|
||||||
import net.corda.testing.node.ClusterSpec
|
import net.corda.testing.node.ClusterSpec
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
@ -61,10 +60,8 @@ import java.util.concurrent.ScheduledExecutorService
|
|||||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||||
import java.util.concurrent.TimeUnit.SECONDS
|
import java.util.concurrent.TimeUnit.SECONDS
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file defines a small "Driver" DSL for starting up nodes that is only intended for development, demos and tests.
|
* This file defines a small "Driver" DSL for starting up nodes that is only intended for development, demos and tests.
|
||||||
*
|
*
|
||||||
@ -172,8 +169,6 @@ interface DriverDSLExposedInterface : CordformContext {
|
|||||||
*/
|
*/
|
||||||
fun startWebserver(handle: NodeHandle, maximumHeapSize: String): CordaFuture<WebserverHandle>
|
fun startWebserver(handle: NodeHandle, maximumHeapSize: String): CordaFuture<WebserverHandle>
|
||||||
|
|
||||||
fun waitForAllNodesToFinish()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Polls a function until it returns a non-null value. Note that there is no timeout on the polling.
|
* Polls a function until it returns a non-null value. Note that there is no timeout on the polling.
|
||||||
*
|
*
|
||||||
@ -338,6 +333,7 @@ fun <A> driver(
|
|||||||
useTestClock: Boolean = defaultParameters.useTestClock,
|
useTestClock: Boolean = defaultParameters.useTestClock,
|
||||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||||
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
||||||
|
waitForAllNodesToFinish: Boolean = defaultParameters.waitForNodesToFinish,
|
||||||
notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs,
|
notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs,
|
||||||
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
||||||
dsl: DriverDSLExposedInterface.() -> A
|
dsl: DriverDSLExposedInterface.() -> A
|
||||||
@ -351,6 +347,7 @@ fun <A> driver(
|
|||||||
useTestClock = useTestClock,
|
useTestClock = useTestClock,
|
||||||
isDebug = isDebug,
|
isDebug = isDebug,
|
||||||
startNodesInProcess = startNodesInProcess,
|
startNodesInProcess = startNodesInProcess,
|
||||||
|
waitForNodesToFinish = waitForAllNodesToFinish,
|
||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan
|
extraCordappPackagesToScan = extraCordappPackagesToScan
|
||||||
),
|
),
|
||||||
@ -385,6 +382,7 @@ data class DriverParameters(
|
|||||||
val useTestClock: Boolean = false,
|
val useTestClock: Boolean = false,
|
||||||
val initialiseSerialization: Boolean = true,
|
val initialiseSerialization: Boolean = true,
|
||||||
val startNodesInProcess: Boolean = false,
|
val startNodesInProcess: Boolean = false,
|
||||||
|
val waitForNodesToFinish: Boolean = false,
|
||||||
val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
|
val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
|
||||||
val extraCordappPackagesToScan: List<String> = emptyList()
|
val extraCordappPackagesToScan: List<String> = emptyList()
|
||||||
) {
|
) {
|
||||||
@ -396,6 +394,7 @@ data class DriverParameters(
|
|||||||
fun setUseTestClock(useTestClock: Boolean) = copy(useTestClock = useTestClock)
|
fun setUseTestClock(useTestClock: Boolean) = copy(useTestClock = useTestClock)
|
||||||
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
|
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
|
||||||
fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess)
|
fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess)
|
||||||
|
fun setTerminateNodesOnShutdown(terminateNodesOnShutdown: Boolean) = copy(waitForNodesToFinish = terminateNodesOnShutdown)
|
||||||
fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
|
fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
|
||||||
fun setNotarySpecs(notarySpecs: List<NotarySpec>) = copy(notarySpecs = notarySpecs)
|
fun setNotarySpecs(notarySpecs: List<NotarySpec>) = copy(notarySpecs = notarySpecs)
|
||||||
}
|
}
|
||||||
@ -446,6 +445,7 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
|
|||||||
systemProperties: Map<String, String> = defaultParameters.systemProperties,
|
systemProperties: Map<String, String> = defaultParameters.systemProperties,
|
||||||
useTestClock: Boolean = defaultParameters.useTestClock,
|
useTestClock: Boolean = defaultParameters.useTestClock,
|
||||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||||
|
waitForNodesToFinish: Boolean = defaultParameters.waitForNodesToFinish,
|
||||||
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
||||||
notarySpecs: List<NotarySpec>,
|
notarySpecs: List<NotarySpec>,
|
||||||
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
||||||
@ -462,6 +462,7 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
|
|||||||
useTestClock = useTestClock,
|
useTestClock = useTestClock,
|
||||||
isDebug = isDebug,
|
isDebug = isDebug,
|
||||||
startNodesInProcess = startNodesInProcess,
|
startNodesInProcess = startNodesInProcess,
|
||||||
|
waitForNodesToFinish = waitForNodesToFinish,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
notarySpecs = notarySpecs
|
notarySpecs = notarySpecs
|
||||||
)
|
)
|
||||||
@ -567,6 +568,7 @@ class DriverDSL(
|
|||||||
val useTestClock: Boolean,
|
val useTestClock: Boolean,
|
||||||
val isDebug: Boolean,
|
val isDebug: Boolean,
|
||||||
val startNodesInProcess: Boolean,
|
val startNodesInProcess: Boolean,
|
||||||
|
val waitForNodesToFinish: Boolean,
|
||||||
extraCordappPackagesToScan: List<String>,
|
extraCordappPackagesToScan: List<String>,
|
||||||
val notarySpecs: List<NotarySpec>
|
val notarySpecs: List<NotarySpec>
|
||||||
) : DriverDSLInternalInterface {
|
) : DriverDSLInternalInterface {
|
||||||
@ -586,7 +588,7 @@ class DriverDSL(
|
|||||||
private lateinit var networkParameters: NetworkParametersCopier
|
private lateinit var networkParameters: NetworkParametersCopier
|
||||||
|
|
||||||
class State {
|
class State {
|
||||||
val processes = ArrayList<CordaFuture<Process>>()
|
val processes = ArrayList<Process>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val state = ThreadBox(State())
|
private val state = ThreadBox(State())
|
||||||
@ -600,20 +602,12 @@ class DriverDSL(
|
|||||||
Paths.get(quasarFileUrl.toURI()).toString()
|
Paths.get(quasarFileUrl.toURI()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerProcess(process: CordaFuture<Process>) {
|
|
||||||
shutdownManager.registerProcessShutdown(process)
|
|
||||||
state.locked {
|
|
||||||
processes.add(process)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun waitForAllNodesToFinish() = state.locked {
|
|
||||||
processes.transpose().get().forEach {
|
|
||||||
it.waitFor()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shutdown() {
|
override fun shutdown() {
|
||||||
|
if (waitForNodesToFinish) {
|
||||||
|
state.locked {
|
||||||
|
processes.forEach { it.waitFor() }
|
||||||
|
}
|
||||||
|
}
|
||||||
_shutdownManager?.shutdown()
|
_shutdownManager?.shutdown()
|
||||||
_executorService?.shutdownNow()
|
_executorService?.shutdownNow()
|
||||||
}
|
}
|
||||||
@ -708,9 +702,10 @@ class DriverDSL(
|
|||||||
|
|
||||||
override fun startWebserver(handle: NodeHandle, maximumHeapSize: String): CordaFuture<WebserverHandle> {
|
override fun startWebserver(handle: NodeHandle, maximumHeapSize: String): CordaFuture<WebserverHandle> {
|
||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
val processFuture = DriverDSL.startWebserver(executorService, handle, debugPort, maximumHeapSize)
|
val process = DriverDSL.startWebserver(handle, debugPort, maximumHeapSize)
|
||||||
registerProcess(processFuture)
|
shutdownManager.registerProcessShutdown(process)
|
||||||
return processFuture.map { queryWebserver(handle, it) }
|
val webReadyFuture = addressMustBeBoundFuture(executorService, handle.webAddress, process)
|
||||||
|
return webReadyFuture.map { queryWebserver(handle, process) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
@ -892,18 +887,22 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
val processFuture = startOutOfProcessNode(executorService, configuration, config, quasarJarPath, debugPort, systemProperties, cordappPackages, maximumHeapSize)
|
val process = startOutOfProcessNode(configuration, config, quasarJarPath, debugPort, systemProperties, cordappPackages, maximumHeapSize)
|
||||||
registerProcess(processFuture)
|
if (waitForNodesToFinish) {
|
||||||
return processFuture.flatMap { process ->
|
state.locked {
|
||||||
|
processes += process
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shutdownManager.registerProcessShutdown(process)
|
||||||
|
}
|
||||||
|
val p2pReadyFuture = addressMustBeBoundFuture(executorService, configuration.p2pAddress, process)
|
||||||
|
return p2pReadyFuture.flatMap {
|
||||||
val processDeathFuture = poll(executorService, "process death") {
|
val processDeathFuture = poll(executorService, "process death") {
|
||||||
if (process.isAlive) null else process
|
if (process.isAlive) null else process
|
||||||
}
|
}
|
||||||
establishRpc(configuration, processDeathFuture).flatMap { rpc ->
|
establishRpc(configuration, processDeathFuture).flatMap { rpc ->
|
||||||
// Check for all nodes to have all other nodes in background in case RPC is failing over:
|
// Check for all nodes to have all other nodes in background in case RPC is failing over:
|
||||||
val forked = executorService.fork {
|
val networkMapFuture = executorService.fork { allNodesConnected(rpc) }.flatMap { it }
|
||||||
allNodesConnected(rpc)
|
|
||||||
}
|
|
||||||
val networkMapFuture = forked.flatMap { it }
|
|
||||||
firstOf(processDeathFuture, networkMapFuture) {
|
firstOf(processDeathFuture, networkMapFuture) {
|
||||||
if (it == processDeathFuture) {
|
if (it == processDeathFuture) {
|
||||||
throw ListenProcessDeathException(configuration.p2pAddress, process)
|
throw ListenProcessDeathException(configuration.p2pAddress, process)
|
||||||
@ -962,7 +961,6 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startOutOfProcessNode(
|
private fun startOutOfProcessNode(
|
||||||
executorService: ScheduledExecutorService,
|
|
||||||
nodeConf: NodeConfiguration,
|
nodeConf: NodeConfiguration,
|
||||||
config: Config,
|
config: Config,
|
||||||
quasarJarPath: String,
|
quasarJarPath: String,
|
||||||
@ -970,8 +968,7 @@ class DriverDSL(
|
|||||||
overriddenSystemProperties: Map<String, String>,
|
overriddenSystemProperties: Map<String, String>,
|
||||||
cordappPackages: List<String>,
|
cordappPackages: List<String>,
|
||||||
maximumHeapSize: String
|
maximumHeapSize: String
|
||||||
): CordaFuture<Process> {
|
): Process {
|
||||||
val processFuture = executorService.fork {
|
|
||||||
log.info("Starting out-of-process Node ${nodeConf.myLegalName.organisation}, debug port is " + (debugPort ?: "not enabled"))
|
log.info("Starting out-of-process Node ${nodeConf.myLegalName.organisation}, debug port is " + (debugPort ?: "not enabled"))
|
||||||
// Write node.conf
|
// Write node.conf
|
||||||
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
||||||
@ -994,7 +991,7 @@ class DriverDSL(
|
|||||||
"-javaagent:$quasarJarPath=$excludePattern"
|
"-javaagent:$quasarJarPath=$excludePattern"
|
||||||
val loggingLevel = if (debugPort == null) "INFO" else "DEBUG"
|
val loggingLevel = if (debugPort == null) "INFO" else "DEBUG"
|
||||||
|
|
||||||
ProcessUtilities.startCordaProcess(
|
return ProcessUtilities.startCordaProcess(
|
||||||
className = "net.corda.node.Corda", // cannot directly get class for this, so just use string
|
className = "net.corda.node.Corda", // cannot directly get class for this, so just use string
|
||||||
arguments = listOf(
|
arguments = listOf(
|
||||||
"--base-directory=${nodeConf.baseDirectory}",
|
"--base-directory=${nodeConf.baseDirectory}",
|
||||||
@ -1008,20 +1005,10 @@ class DriverDSL(
|
|||||||
maximumHeapSize = maximumHeapSize
|
maximumHeapSize = maximumHeapSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return processFuture.flatMap { process ->
|
|
||||||
addressMustBeBoundFuture(executorService, nodeConf.p2pAddress, process).map { process }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startWebserver(
|
private fun startWebserver(handle: NodeHandle, debugPort: Int?, maximumHeapSize: String): Process {
|
||||||
executorService: ScheduledExecutorService,
|
|
||||||
handle: NodeHandle,
|
|
||||||
debugPort: Int?,
|
|
||||||
maximumHeapSize: String
|
|
||||||
): CordaFuture<Process> {
|
|
||||||
return executorService.fork {
|
|
||||||
val className = "net.corda.webserver.WebServer"
|
val className = "net.corda.webserver.WebServer"
|
||||||
ProcessUtilities.startCordaProcess(
|
return ProcessUtilities.startCordaProcess(
|
||||||
className = className, // cannot directly get class for this, so just use string
|
className = className, // cannot directly get class for this, so just use string
|
||||||
arguments = listOf("--base-directory", handle.configuration.baseDirectory.toString()),
|
arguments = listOf("--base-directory", handle.configuration.baseDirectory.toString()),
|
||||||
jdwpPort = debugPort,
|
jdwpPort = debugPort,
|
||||||
@ -1033,7 +1020,6 @@ class DriverDSL(
|
|||||||
workingDirectory = null,
|
workingDirectory = null,
|
||||||
maximumHeapSize = maximumHeapSize
|
maximumHeapSize = maximumHeapSize
|
||||||
)
|
)
|
||||||
}.flatMap { process -> addressMustBeBoundFuture(executorService, handle.webAddress, process).map { process } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCallerPackage(): String {
|
private fun getCallerPackage(): String {
|
||||||
|
@ -3,14 +3,12 @@ package net.corda.testing.driver
|
|||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.internal.concurrent.doneFuture
|
import net.corda.core.internal.concurrent.doneFuture
|
||||||
import net.corda.core.internal.concurrent.map
|
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import java.util.concurrent.TimeoutException
|
import java.util.concurrent.TimeoutException
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
@ -46,6 +44,7 @@ class ShutdownManager(private val executorService: ExecutorService) {
|
|||||||
registeredShutdowns
|
registeredShutdowns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val shutdowns = shutdownActionFutures.map { Try.on { it.getOrThrow(1.seconds) } }
|
val shutdowns = shutdownActionFutures.map { Try.on { it.getOrThrow(1.seconds) } }
|
||||||
shutdowns.reversed().forEach {
|
shutdowns.reversed().forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
@ -63,31 +62,27 @@ class ShutdownManager(private val executorService: ExecutorService) {
|
|||||||
fun registerShutdown(shutdown: CordaFuture<() -> Unit>) {
|
fun registerShutdown(shutdown: CordaFuture<() -> Unit>) {
|
||||||
state.locked {
|
state.locked {
|
||||||
require(!isShutdown)
|
require(!isShutdown)
|
||||||
registeredShutdowns.add(shutdown)
|
registeredShutdowns += shutdown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerShutdown(shutdown: () -> Unit) = registerShutdown(doneFuture(shutdown))
|
fun registerShutdown(shutdown: () -> Unit) = registerShutdown(doneFuture(shutdown))
|
||||||
|
|
||||||
fun registerProcessShutdown(processFuture: CordaFuture<Process>) {
|
fun registerProcessShutdown(process: Process) {
|
||||||
val processShutdown = processFuture.map { process ->
|
registerShutdown {
|
||||||
{
|
|
||||||
process.destroy()
|
process.destroy()
|
||||||
/** Wait 5 seconds, then [Process.destroyForcibly] */
|
/** Wait 5 seconds, then [Process.destroyForcibly] */
|
||||||
val finishedFuture = executorService.submit {
|
val finishedFuture = executorService.submit {
|
||||||
process.waitFor()
|
process.waitFor()
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
finishedFuture.get(5, TimeUnit.SECONDS)
|
finishedFuture.getOrThrow(5.seconds)
|
||||||
} catch (exception: TimeoutException) {
|
} catch (timeout: TimeoutException) {
|
||||||
finishedFuture.cancel(true)
|
finishedFuture.cancel(true)
|
||||||
process.destroyForcibly()
|
process.destroyForcibly()
|
||||||
}
|
}
|
||||||
Unit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerShutdown(processShutdown)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Follower {
|
interface Follower {
|
||||||
fun unfollow()
|
fun unfollow()
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.client.rpc.internal.RPCClientConfiguration
|
|||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.concurrent.doneFuture
|
||||||
import net.corda.core.internal.concurrent.fork
|
import net.corda.core.internal.concurrent.fork
|
||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
@ -229,6 +230,7 @@ fun <A> rpcDriver(
|
|||||||
useTestClock: Boolean = false,
|
useTestClock: Boolean = false,
|
||||||
initialiseSerialization: Boolean = true,
|
initialiseSerialization: Boolean = true,
|
||||||
startNodesInProcess: Boolean = false,
|
startNodesInProcess: Boolean = false,
|
||||||
|
waitForNodesToFinish: Boolean = false,
|
||||||
extraCordappPackagesToScan: List<String> = emptyList(),
|
extraCordappPackagesToScan: List<String> = emptyList(),
|
||||||
notarySpecs: List<NotarySpec> = emptyList(),
|
notarySpecs: List<NotarySpec> = emptyList(),
|
||||||
dsl: RPCDriverExposedDSLInterface.() -> A
|
dsl: RPCDriverExposedDSLInterface.() -> A
|
||||||
@ -242,6 +244,7 @@ fun <A> rpcDriver(
|
|||||||
useTestClock = useTestClock,
|
useTestClock = useTestClock,
|
||||||
isDebug = isDebug,
|
isDebug = isDebug,
|
||||||
startNodesInProcess = startNodesInProcess,
|
startNodesInProcess = startNodesInProcess,
|
||||||
|
waitForNodesToFinish = waitForNodesToFinish,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
notarySpecs = notarySpecs
|
notarySpecs = notarySpecs
|
||||||
)
|
)
|
||||||
@ -404,11 +407,9 @@ data class RPCDriverDSL(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun <I : RPCOps> startRandomRpcClient(rpcOpsClass: Class<I>, rpcAddress: NetworkHostAndPort, username: String, password: String): CordaFuture<Process> {
|
override fun <I : RPCOps> startRandomRpcClient(rpcOpsClass: Class<I>, rpcAddress: NetworkHostAndPort, username: String, password: String): CordaFuture<Process> {
|
||||||
val processFuture = driverDSL.executorService.fork {
|
val process = ProcessUtilities.startJavaProcess<RandomRpcUser>(listOf(rpcOpsClass.name, rpcAddress.toString(), username, password))
|
||||||
ProcessUtilities.startJavaProcess<RandomRpcUser>(listOf(rpcOpsClass.name, rpcAddress.toString(), username, password))
|
driverDSL.shutdownManager.registerProcessShutdown(process)
|
||||||
}
|
return doneFuture(process)
|
||||||
driverDSL.shutdownManager.registerProcessShutdown(processFuture)
|
|
||||||
return processFuture
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startArtemisSession(rpcAddress: NetworkHostAndPort, username: String, password: String): ClientSession {
|
override fun startArtemisSession(rpcAddress: NetworkHostAndPort, username: String, password: String): ClientSession {
|
||||||
|
@ -16,12 +16,9 @@ fun CordformDefinition.clean() {
|
|||||||
* Creates and starts all nodes required for the demo.
|
* Creates and starts all nodes required for the demo.
|
||||||
*/
|
*/
|
||||||
// TODO add notaries to cordform!
|
// TODO add notaries to cordform!
|
||||||
fun CordformDefinition.runNodes() = driver(
|
fun CordformDefinition.runNodes() {
|
||||||
isDebug = true,
|
driver(isDebug = true, driverDirectory = driverDirectory, portAllocation = PortAllocation.Incremental(10001), waitForAllNodesToFinish = true) {
|
||||||
driverDirectory = driverDirectory,
|
|
||||||
portAllocation = PortAllocation.Incremental(10001)
|
|
||||||
) {
|
|
||||||
setup(this)
|
setup(this)
|
||||||
startNodes(nodeConfigurers.map { configurer -> CordformNode().also { configurer.accept(it) } })
|
startNodes(nodeConfigurers.map { configurer -> CordformNode().also { configurer.accept(it) } })
|
||||||
waitForAllNodesToFinish()
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ class ExplorerSimulation(private val options: OptionSet) {
|
|||||||
|
|
||||||
private fun startDemoNodes() {
|
private fun startDemoNodes() {
|
||||||
val portAllocation = PortAllocation.Incremental(20000)
|
val portAllocation = PortAllocation.Incremental(20000)
|
||||||
driver(portAllocation = portAllocation, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
driver(portAllocation = portAllocation, extraCordappPackagesToScan = listOf("net.corda.finance"), waitForAllNodesToFinish = true) {
|
||||||
// TODO : Supported flow should be exposed somehow from the node instead of set of ServiceInfo.
|
// TODO : Supported flow should be exposed somehow from the node instead of set of ServiceInfo.
|
||||||
val alice = startNode(providedName = ALICE.name, rpcUsers = listOf(user))
|
val alice = startNode(providedName = ALICE.name, rpcUsers = listOf(user))
|
||||||
val bob = startNode(providedName = BOB.name, rpcUsers = listOf(user))
|
val bob = startNode(providedName = BOB.name, rpcUsers = listOf(user))
|
||||||
@ -89,8 +89,6 @@ class ExplorerSimulation(private val options: OptionSet) {
|
|||||||
options.has("S") -> startNormalSimulation()
|
options.has("S") -> startNormalSimulation()
|
||||||
options.has("F") -> startErrorFlowsSimulation()
|
options.has("F") -> startErrorFlowsSimulation()
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForAllNodesToFinish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,10 @@ import com.typesafe.config.ConfigFactory
|
|||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.concurrent.*
|
import net.corda.core.internal.concurrent.OpenFuture
|
||||||
|
import net.corda.core.internal.concurrent.doneFuture
|
||||||
|
import net.corda.core.internal.concurrent.fork
|
||||||
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||||
@ -79,6 +82,7 @@ fun <A> verifierDriver(
|
|||||||
systemProperties: Map<String, String> = emptyMap(),
|
systemProperties: Map<String, String> = emptyMap(),
|
||||||
useTestClock: Boolean = false,
|
useTestClock: Boolean = false,
|
||||||
startNodesInProcess: Boolean = false,
|
startNodesInProcess: Boolean = false,
|
||||||
|
waitForNodesToFinish: Boolean = false,
|
||||||
extraCordappPackagesToScan: List<String> = emptyList(),
|
extraCordappPackagesToScan: List<String> = emptyList(),
|
||||||
notarySpecs: List<NotarySpec> = emptyList(),
|
notarySpecs: List<NotarySpec> = emptyList(),
|
||||||
dsl: VerifierExposedDSLInterface.() -> A
|
dsl: VerifierExposedDSLInterface.() -> A
|
||||||
@ -92,6 +96,7 @@ fun <A> verifierDriver(
|
|||||||
useTestClock = useTestClock,
|
useTestClock = useTestClock,
|
||||||
isDebug = isDebug,
|
isDebug = isDebug,
|
||||||
startNodesInProcess = startNodesInProcess,
|
startNodesInProcess = startNodesInProcess,
|
||||||
|
waitForNodesToFinish = waitForNodesToFinish,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
notarySpecs = notarySpecs
|
notarySpecs = notarySpecs
|
||||||
)
|
)
|
||||||
@ -254,17 +259,15 @@ data class VerifierDriverDSL(
|
|||||||
log.info("Starting verifier connecting to address $address")
|
log.info("Starting verifier connecting to address $address")
|
||||||
val id = verifierCount.andIncrement
|
val id = verifierCount.andIncrement
|
||||||
val jdwpPort = if (driverDSL.isDebug) driverDSL.debugPortAllocation.nextPort() else null
|
val jdwpPort = if (driverDSL.isDebug) driverDSL.debugPortAllocation.nextPort() else null
|
||||||
val processFuture = driverDSL.executorService.fork {
|
|
||||||
val verifierName = CordaX500Name(organisation = "Verifier$id", locality = "London", country = "GB")
|
val verifierName = CordaX500Name(organisation = "Verifier$id", locality = "London", country = "GB")
|
||||||
val baseDirectory = (driverDSL.driverDirectory / verifierName.organisation).createDirectories()
|
val baseDirectory = (driverDSL.driverDirectory / verifierName.organisation).createDirectories()
|
||||||
val config = createConfiguration(baseDirectory, address)
|
val config = createConfiguration(baseDirectory, address)
|
||||||
val configFilename = "verifier.conf"
|
val configFilename = "verifier.conf"
|
||||||
writeConfig(baseDirectory, configFilename, config)
|
writeConfig(baseDirectory, configFilename, config)
|
||||||
Verifier.loadConfiguration(baseDirectory, baseDirectory / configFilename).configureDevKeyAndTrustStores(verifierName)
|
Verifier.loadConfiguration(baseDirectory, baseDirectory / configFilename).configureDevKeyAndTrustStores(verifierName)
|
||||||
ProcessUtilities.startJavaProcess<Verifier>(listOf(baseDirectory.toString()), jdwpPort = jdwpPort)
|
val process = ProcessUtilities.startJavaProcess<Verifier>(listOf(baseDirectory.toString()), jdwpPort = jdwpPort)
|
||||||
}
|
driverDSL.shutdownManager.registerProcessShutdown(process)
|
||||||
driverDSL.shutdownManager.registerProcessShutdown(processFuture)
|
return doneFuture(VerifierHandle(process))
|
||||||
return processFuture.map(::VerifierHandle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <A> NodeHandle.connectToNode(closure: (ClientSession) -> A): A {
|
private fun <A> NodeHandle.connectToNode(closure: (ClientSession) -> A): A {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user