mirror of
https://github.com/corda/corda.git
synced 2025-01-30 08:04:16 +00:00
ENT-1967: Illustration for Byteman library can be used in Node integration test. (#1204) - c396b80a
(Only took `DriverDSLImpl` changes) Simplifying internal startNode with bytemanPort parameter - d88b02f7 Manual cherry pick of these changes (c396b80a + d88b02f7)
This commit is contained in:
parent
8a2f4478d2
commit
bedfba8c3d
@ -18,6 +18,7 @@ import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.NotaryInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.Try
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.millis
|
||||
@ -57,6 +58,7 @@ import rx.schedulers.Schedulers
|
||||
import java.io.File
|
||||
import java.net.ConnectException
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Path
|
||||
import java.security.cert.X509Certificate
|
||||
import java.time.Duration
|
||||
@ -122,7 +124,15 @@ class DriverDSLImpl(
|
||||
private val state = ThreadBox(State())
|
||||
|
||||
//TODO: remove this once we can bundle quasar properly.
|
||||
private val quasarJarPath: String by lazy { resolveJar("co.paralleluniverse.fibers.Suspendable") }
|
||||
private val quasarJarPath: String by lazy { resolveJar(".*quasar.*\\.jar$").getOrThrow() }
|
||||
|
||||
private val bytemanJarPath: String? by lazy {
|
||||
val maybeResolvedJar = resolveJar(".*byteman-\\d.*\\.jar$")
|
||||
when (maybeResolvedJar) {
|
||||
is Try.Success -> maybeResolvedJar.getOrThrow()
|
||||
is Try.Failure -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun NodeConfig.checkAndOverrideForInMemoryDB(): NodeConfig = this.run {
|
||||
if (inMemoryDB && corda.dataSourceProperties.getProperty("dataSource.url").startsWith("jdbc:h2:")) {
|
||||
@ -134,14 +144,16 @@ class DriverDSLImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveJar(className: String): String {
|
||||
private fun resolveJar(jarNamePattern: String): Try<String> {
|
||||
return try {
|
||||
val type = Class.forName(className)
|
||||
val src = type.protectionDomain.codeSource
|
||||
src.location.toPath().toString()
|
||||
val cl = ClassLoader.getSystemClassLoader()
|
||||
val urls = (cl as URLClassLoader).urLs
|
||||
val jarPattern = jarNamePattern.toRegex()
|
||||
val jarFileUrl = urls.first { jarPattern.matches(it.path) }
|
||||
Try.Success(jarFileUrl.toPath().toString())
|
||||
} catch (e: Exception) {
|
||||
log.warn("Unable to locate JAR for class given by `$className` on classpath: ${e.message}", e)
|
||||
throw e
|
||||
log.warn("Unable to locate JAR `$jarNamePattern` on classpath: ${e.message}", e)
|
||||
Try.Failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +190,9 @@ class DriverDSLImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startNode(parameters: NodeParameters): CordaFuture<NodeHandle> {
|
||||
override fun startNode(parameters: NodeParameters): CordaFuture<NodeHandle> = startNode(parameters, bytemanPort = null)
|
||||
|
||||
override fun startNode(parameters: NodeParameters, bytemanPort: Int?): CordaFuture<NodeHandle> {
|
||||
val p2pAddress = portAllocation.nextHostAndPort()
|
||||
// TODO: Derive name from the full picked name, don't just wrap the common name
|
||||
val name = parameters.providedName ?: CordaX500Name("${oneOf(names).organisation}-${p2pAddress.port}", "London", "GB")
|
||||
@ -193,7 +207,7 @@ class DriverDSLImpl(
|
||||
return registrationFuture.flatMap {
|
||||
networkMapAvailability.flatMap {
|
||||
// But starting the node proper does require the network map
|
||||
startRegisteredNode(name, it, parameters, p2pAddress)
|
||||
startRegisteredNode(name, it, parameters, p2pAddress, bytemanPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,7 +215,8 @@ class DriverDSLImpl(
|
||||
private fun startRegisteredNode(name: CordaX500Name,
|
||||
localNetworkMap: LocalNetworkMap?,
|
||||
parameters: NodeParameters,
|
||||
p2pAddress: NetworkHostAndPort = portAllocation.nextHostAndPort()): CordaFuture<NodeHandle> {
|
||||
p2pAddress: NetworkHostAndPort = portAllocation.nextHostAndPort(),
|
||||
bytemanPort: Int? = null): CordaFuture<NodeHandle> {
|
||||
val rpcAddress = portAllocation.nextHostAndPort()
|
||||
val rpcAdminAddress = portAllocation.nextHostAndPort()
|
||||
val webAddress = portAllocation.nextHostAndPort()
|
||||
@ -240,7 +255,7 @@ class DriverDSLImpl(
|
||||
allowMissingConfig = true,
|
||||
configOverrides = if (overrides.hasPath("devMode")) overrides else overrides + mapOf("devMode" to true)
|
||||
)).checkAndOverrideForInMemoryDB()
|
||||
return startNodeInternal(config, webAddress, localNetworkMap, parameters)
|
||||
return startNodeInternal(config, webAddress, localNetworkMap, parameters, bytemanPort)
|
||||
}
|
||||
|
||||
private fun startNodeRegistration(
|
||||
@ -542,6 +557,8 @@ class DriverDSLImpl(
|
||||
config,
|
||||
quasarJarPath,
|
||||
debugPort,
|
||||
bytemanJarPath,
|
||||
null,
|
||||
systemProperties,
|
||||
"512m",
|
||||
null,
|
||||
@ -556,7 +573,8 @@ class DriverDSLImpl(
|
||||
private fun startNodeInternal(config: NodeConfig,
|
||||
webAddress: NetworkHostAndPort,
|
||||
localNetworkMap: LocalNetworkMap?,
|
||||
parameters: NodeParameters): CordaFuture<NodeHandle> {
|
||||
parameters: NodeParameters,
|
||||
bytemanPort: Int?): CordaFuture<NodeHandle> {
|
||||
val visibilityHandle = networkVisibilityController.register(config.corda.myLegalName)
|
||||
val baseDirectory = config.corda.baseDirectory.createDirectories()
|
||||
localNetworkMap?.networkParametersCopier?.install(baseDirectory)
|
||||
@ -602,7 +620,16 @@ class DriverDSLImpl(
|
||||
nodeFuture
|
||||
} else {
|
||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||
val process = startOutOfProcessNode(config, quasarJarPath, debugPort, systemProperties, parameters.maximumHeapSize, parameters.logLevelOverride)
|
||||
val process = startOutOfProcessNode(
|
||||
config,
|
||||
quasarJarPath,
|
||||
debugPort,
|
||||
bytemanJarPath,
|
||||
bytemanPort,
|
||||
systemProperties,
|
||||
parameters.maximumHeapSize,
|
||||
parameters.logLevelOverride
|
||||
)
|
||||
|
||||
// Destroy the child process when the parent exits.This is needed even when `waitForAllNodesToFinish` is
|
||||
// true because we don't want orphaned processes in the case that the parent process is terminated by the
|
||||
@ -730,12 +757,16 @@ class DriverDSLImpl(
|
||||
config: NodeConfig,
|
||||
quasarJarPath: String,
|
||||
debugPort: Int?,
|
||||
bytemanJarPath: String?,
|
||||
bytemanPort: Int?,
|
||||
overriddenSystemProperties: Map<String, String>,
|
||||
maximumHeapSize: String,
|
||||
logLevelOverride: String?,
|
||||
vararg extraCmdLineFlag: String
|
||||
): Process {
|
||||
log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, debug port is " + (debugPort ?: "not enabled"))
|
||||
log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, " +
|
||||
"debug port is " + (debugPort ?: "not enabled") + ", " +
|
||||
"byteMan: " + if (bytemanJarPath == null) "not in classpath" else "port is " + (bytemanPort ?: "not enabled"))
|
||||
// Write node.conf
|
||||
writeConfig(config.corda.baseDirectory, "node.conf", config.typesafe.toNodeOnly())
|
||||
|
||||
@ -777,6 +808,17 @@ class DriverDSLImpl(
|
||||
it += extraCmdLineFlag
|
||||
}.toList()
|
||||
|
||||
val bytemanJvmArgs = {
|
||||
val bytemanAgent = bytemanJarPath?.let {
|
||||
bytemanPort?.let {
|
||||
"-javaagent:$bytemanJarPath=port:$bytemanPort,listener:true"
|
||||
}
|
||||
}
|
||||
listOfNotNull(bytemanAgent) +
|
||||
if (bytemanAgent != null && debugPort != null) listOf("-Dorg.jboss.byteman.verbose=true", "-Dorg.jboss.byteman.debug=true")
|
||||
else emptyList()
|
||||
}.invoke()
|
||||
|
||||
// The following dependencies are excluded from the classpath of the created JVM, so that the environment resembles a real one as close as possible.
|
||||
// These are either classes that will be added as attachments to the node (i.e. samples, finance, opengamma etc.) or irrelevant testing libraries (test, corda-mock etc.).
|
||||
// TODO: There is pending work to fix this issue without custom blacklisting. See: https://r3-cev.atlassian.net/browse/CORDA-2164.
|
||||
@ -789,7 +831,7 @@ class DriverDSLImpl(
|
||||
className = "net.corda.node.Corda", // cannot directly get class for this, so just use string
|
||||
arguments = arguments,
|
||||
jdwpPort = debugPort,
|
||||
extraJvmArguments = extraJvmArguments,
|
||||
extraJvmArguments = extraJvmArguments + bytemanJvmArgs,
|
||||
workingDirectory = config.corda.baseDirectory,
|
||||
maximumHeapSize = maximumHeapSize,
|
||||
classPath = cp
|
||||
@ -952,6 +994,11 @@ interface InternalDriverDSL : DriverDSL {
|
||||
fun start()
|
||||
|
||||
fun shutdown()
|
||||
|
||||
fun startNode(
|
||||
parameters: NodeParameters = NodeParameters(),
|
||||
bytemanPort: Int? = null
|
||||
): CordaFuture<NodeHandle>
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user