mirror of
https://github.com/corda/corda.git
synced 2024-12-20 05:28:21 +00:00
Merged in simplify-demo-execution (pull request #99)
Simplify demo execution
This commit is contained in:
commit
5b1b5773ee
13
build.gradle
13
build.gradle
@ -84,7 +84,7 @@ tasks.withType(JavaExec) {
|
||||
jvmArgs "-Dco.paralleluniverse.fibers.verifyInstrumentation"
|
||||
}
|
||||
|
||||
// Package up the other demo programs.
|
||||
// Package up the demo programs.
|
||||
task getRateFixDemo(type: CreateStartScripts) {
|
||||
mainClassName = "demos.RateFixDemoKt"
|
||||
applicationName = "get-rate-fix"
|
||||
@ -101,6 +101,14 @@ task getIRSDemo(type: CreateStartScripts) {
|
||||
classpath = jar.outputs.files + project.configurations.runtime
|
||||
}
|
||||
|
||||
task getTraderDemo(type: CreateStartScripts) {
|
||||
mainClassName = "demos.TraderDemoKt"
|
||||
applicationName = "trader-demo"
|
||||
defaultJvmOpts = ["-javaagent:${configurations.quasar.singleFile}"]
|
||||
outputDir = new File(project.buildDir, 'scripts')
|
||||
classpath = jar.outputs.files + project.configurations.runtime
|
||||
}
|
||||
|
||||
// Force windows script classpath to wildcard path to avoid the 'Command Line Is Too Long' issues
|
||||
// with generated scripts. Include Jolokia .war explicitly as this isn't picked up by wildcard
|
||||
tasks.withType(CreateStartScripts)
|
||||
@ -138,5 +146,6 @@ jar.dependsOn quasarScan
|
||||
applicationDistribution.into("bin") {
|
||||
from(getRateFixDemo)
|
||||
from(getIRSDemo)
|
||||
from(getTraderDemo)
|
||||
fileMode = 0755
|
||||
}
|
||||
}
|
||||
|
@ -14,29 +14,27 @@ The demos have only been tested on MacOS X and Ubuntu Linux. If you have success
|
||||
The demos create node data directories in the root of the project. If something goes wrong with them, blow away the
|
||||
directories and try again.
|
||||
|
||||
For Windows users, the contents of the shell scripts are very trivial and can easily be done by hand from a command
|
||||
window. Essentially, it just runs Gradle to create the startup scripts, and then starts the node with one set of
|
||||
flags or another. Alternatively you could play with the new Linux syscall support in Windows 10!
|
||||
|
||||
Trader demo
|
||||
-----------
|
||||
|
||||
Open two terminals, and in the first run:::
|
||||
|
||||
./scripts/trader-demo.sh buyer
|
||||
gradle installDist && ./build/install/r3prototyping/trader-demo.sh --mode=buyer
|
||||
|
||||
It will compile things, if necessary, then create a directory named "buyer" with a bunch of files inside and start
|
||||
the node. You should see it waiting for a trade to begin.
|
||||
It will compile things, if necessary, then create a directory named trader-demo/buyer with a bunch of files inside and
|
||||
start the node. You should see it waiting for a trade to begin.
|
||||
|
||||
In the second terminal, run::
|
||||
|
||||
./scripts/trader-demo.sh seller
|
||||
./build/install/r3prototyping/trader-demo.sh --mode=seller
|
||||
|
||||
You should see some log lines scroll past, and within a few seconds the messages "Purchase complete - we are a
|
||||
happy customer!" and "Sale completed - we have a happy customer!" should be printed.
|
||||
|
||||
If it doesn't work, jump on the mailing list and let us know.
|
||||
|
||||
On Windows, use the same commands, but run the batch file instead of the shell file.
|
||||
|
||||
|
||||
IRS demo
|
||||
--------
|
||||
|
@ -94,11 +94,16 @@ class StateMachineManager(val serviceHub: ServiceHub, val executor: AffinityExec
|
||||
field.get(null)
|
||||
}
|
||||
|
||||
companion object {
|
||||
var restoreCheckpointsOnStart = true
|
||||
}
|
||||
|
||||
init {
|
||||
Fiber.setDefaultUncaughtExceptionHandler { fiber, throwable ->
|
||||
(fiber as ProtocolStateMachineImpl<*>).logger.error("Caught exception from protocol", throwable)
|
||||
}
|
||||
restoreCheckpoints()
|
||||
if (restoreCheckpointsOnStart)
|
||||
restoreCheckpoints()
|
||||
}
|
||||
|
||||
/** Reads the database map and resurrects any serialised state machines. */
|
||||
|
@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
mode=$1
|
||||
|
||||
if [ ! -e ./gradlew ]; then
|
||||
echo "Run from the root directory please"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_INSTALL" == "" ]]; then
|
||||
./gradlew installDist
|
||||
fi
|
||||
|
||||
if [[ "$mode" == "buyer" ]]; then
|
||||
if [ ! -d buyer ]; then
|
||||
mkdir buyer
|
||||
echo "myLegalName = Bank A" >buyer/config
|
||||
fi
|
||||
|
||||
build/install/r3prototyping/bin/r3prototyping --dir=buyer --service-fake-trades --network-address=localhost
|
||||
elif [[ "$mode" == "seller" ]]; then
|
||||
if [ ! -d seller ]; then
|
||||
mkdir seller
|
||||
echo "myLegalName = Bank B" >seller/config
|
||||
fi
|
||||
|
||||
build/install/r3prototyping/bin/r3prototyping --dir=seller --fake-trade-with=localhost --network-address=localhost:31340 --network-map-identity-file=buyer/identity-public --network-map-address=localhost
|
||||
else
|
||||
echo "Run like this, one in each tab:"
|
||||
echo
|
||||
echo " scripts/trader-demo.sh buyer"
|
||||
echo " scripts/trader-demo.sh seller"
|
||||
fi
|
@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import com.google.common.net.HostAndPort
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import contracts.CommercialPaper
|
||||
import core.*
|
||||
import core.contracts.*
|
||||
import core.crypto.Party
|
||||
import core.crypto.SecureHash
|
||||
import core.crypto.generateKeyPair
|
||||
import core.days
|
||||
import core.logElapsedTime
|
||||
import core.messaging.SingleMessageRecipient
|
||||
import core.messaging.StateMachineManager
|
||||
import core.node.Node
|
||||
import core.node.NodeConfiguration
|
||||
import core.node.NodeConfigurationFromConfig
|
||||
import core.node.NodeInfo
|
||||
import core.node.services.NetworkMapService
|
||||
@ -21,6 +22,8 @@ import core.node.services.ServiceType
|
||||
import core.node.subsystems.ArtemisMessagingService
|
||||
import core.node.subsystems.NodeWalletService
|
||||
import core.protocols.ProtocolLogic
|
||||
import core.random63BitValue
|
||||
import core.seconds
|
||||
import core.serialization.deserialize
|
||||
import core.utilities.ANSIProgressRenderer
|
||||
import core.utilities.BriefLogFormatter
|
||||
@ -43,17 +46,10 @@ import kotlin.test.assertEquals
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val parser = OptionParser()
|
||||
val networkAddressArg = parser.accepts("network-address").withRequiredArg().required()
|
||||
val dirArg = parser.accepts("directory").withRequiredArg().defaultsTo("nodedata")
|
||||
|
||||
// Some dummy functionality that won't last long ...
|
||||
|
||||
// Mode flags for the first demo.
|
||||
val serviceFakeTradesArg = parser.accepts("service-fake-trades")
|
||||
val fakeTradeWithArg = parser.accepts("fake-trade-with").requiredUnless(serviceFakeTradesArg).withRequiredArg()
|
||||
|
||||
val networkMapIdentityFile = parser.accepts("network-map-identity-file").requiredIf(fakeTradeWithArg).withRequiredArg()
|
||||
val networkMapNetAddr = parser.accepts("network-map-address").requiredIf(networkMapIdentityFile).withRequiredArg()
|
||||
val modeArg = parser.accepts("mode").withRequiredArg().required()
|
||||
val myNetworkAddress = parser.accepts("network-address").withRequiredArg().defaultsTo("localhost")
|
||||
val theirNetworkAddress = parser.accepts("other-network-address").withRequiredArg().defaultsTo("localhost")
|
||||
|
||||
val options = try {
|
||||
parser.parse(*args)
|
||||
@ -63,39 +59,46 @@ fun main(args: Array<String>) {
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
// Suppress the Artemis MQ noise, and activate the demo logging.
|
||||
BriefLogFormatter.initVerbose("+demo.buyer", "+demo.seller", "-org.apache.activemq")
|
||||
val mode = options.valueOf(modeArg)
|
||||
|
||||
val dir = Paths.get(options.valueOf(dirArg))
|
||||
val configFile = dir.resolve("config")
|
||||
val DIRNAME = "trader-demo"
|
||||
val BUYER = "buyer"
|
||||
val SELLER = "seller"
|
||||
|
||||
if (!Files.exists(dir)) {
|
||||
Files.createDirectory(dir)
|
||||
}
|
||||
|
||||
val config = loadConfigFile(configFile)
|
||||
|
||||
val advertisedServices: Set<ServiceType>
|
||||
val myNetAddr = HostAndPort.fromString(options.valueOf(networkAddressArg)).withDefaultPort(Node.DEFAULT_PORT)
|
||||
val listening = options.has(serviceFakeTradesArg)
|
||||
|
||||
if (listening && config.myLegalName != "Bank A") {
|
||||
println("The buyer node must have a legal name of 'Bank A'. Please edit the config file.")
|
||||
if (mode !in setOf(BUYER, SELLER)) {
|
||||
printHelp()
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
val networkMapId = if (options.has(networkMapIdentityFile)) {
|
||||
val addr = HostAndPort.fromString(options.valueOf(networkMapNetAddr)).withDefaultPort(Node.DEFAULT_PORT)
|
||||
val path = Paths.get(options.valueOf(networkMapIdentityFile))
|
||||
// Suppress the Artemis MQ noise, and activate the demo logging.
|
||||
BriefLogFormatter.initVerbose("+demo.buyer", "+demo.seller", "-org.apache.activemq")
|
||||
|
||||
val dir = Paths.get(DIRNAME, mode)
|
||||
Files.createDirectories(dir)
|
||||
|
||||
val advertisedServices: Set<ServiceType>
|
||||
val myNetAddr = HostAndPort.fromString(options.valueOf(myNetworkAddress)).withDefaultPort(if (mode == BUYER) Node.DEFAULT_PORT else 31340)
|
||||
val theirNetAddr = HostAndPort.fromString(options.valueOf(theirNetworkAddress)).withDefaultPort(if (mode == SELLER) Node.DEFAULT_PORT else 31340)
|
||||
|
||||
val listening = mode == BUYER
|
||||
val config = run {
|
||||
val override = ConfigFactory.parseString("""myLegalName = ${ if (mode == BUYER) "Bank A" else "Bank B" }""")
|
||||
NodeConfigurationFromConfig(override.withFallback(ConfigFactory.load()))
|
||||
}
|
||||
|
||||
val networkMapId = if (mode == SELLER) {
|
||||
val path = Paths.get(DIRNAME, BUYER, "identity-public")
|
||||
val party = Files.readAllBytes(path).deserialize<Party>()
|
||||
advertisedServices = emptySet()
|
||||
NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, setOf(NetworkMapService.Type))
|
||||
NodeInfo(ArtemisMessagingService.makeRecipient(theirNetAddr), party, setOf(NetworkMapService.Type))
|
||||
} else {
|
||||
// We must be the network map service
|
||||
advertisedServices = setOf(NetworkMapService.Type, NotaryService.Type)
|
||||
null
|
||||
}
|
||||
|
||||
// TODO: Remove this once checkpoint resume works.
|
||||
StateMachineManager.restoreCheckpointsOnStart = false
|
||||
val node = logElapsedTime("Node startup") { Node(dir, myNetAddr, config, networkMapId, advertisedServices).start() }
|
||||
|
||||
if (listening) {
|
||||
@ -110,11 +113,6 @@ fun main(args: Array<String>) {
|
||||
ANSIProgressRenderer.progressTracker = buyer.progressTracker
|
||||
node.smm.add("demo.buyer", buyer).get() // This thread will halt forever here.
|
||||
} else {
|
||||
if (!options.has(fakeTradeWithArg)) {
|
||||
println("Need the --fake-trade-with command line argument")
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
// Make sure we have the transaction prospectus attachment loaded into our store.
|
||||
if (node.storage.attachments.openAttachment(TraderDemoProtocolSeller.PROSPECTUS_HASH) == null) {
|
||||
TraderDemoProtocolSeller::class.java.getResourceAsStream("bank-of-london-cp.jar").use {
|
||||
@ -123,8 +121,7 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
val peerAddr = HostAndPort.fromString(options.valuesOf(fakeTradeWithArg).single()).withDefaultPort(Node.DEFAULT_PORT)
|
||||
val otherSide = ArtemisMessagingService.makeRecipient(peerAddr)
|
||||
val otherSide = ArtemisMessagingService.makeRecipient(theirNetAddr)
|
||||
val seller = TraderDemoProtocolSeller(myNetAddr, otherSide)
|
||||
ANSIProgressRenderer.progressTracker = seller.progressTracker
|
||||
node.smm.add("demo.seller", seller).get()
|
||||
@ -277,43 +274,6 @@ class TraderDemoProtocolSeller(val myAddress: HostAndPort,
|
||||
|
||||
}
|
||||
|
||||
private fun loadConfigFile(configFile: Path): NodeConfiguration {
|
||||
fun askAdminToEditConfig(configFile: Path?) {
|
||||
println()
|
||||
println("This is the first run, so you should edit the config file in $configFile and then start the node again.")
|
||||
println()
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
val defaultLegalName = "Global MegaCorp, Ltd."
|
||||
|
||||
if (!Files.exists(configFile)) {
|
||||
createDefaultConfigFile(configFile, defaultLegalName)
|
||||
askAdminToEditConfig(configFile)
|
||||
}
|
||||
|
||||
System.setProperty("config.file", configFile.toAbsolutePath().toString())
|
||||
val config = NodeConfigurationFromConfig(ConfigFactory.load())
|
||||
|
||||
// Make sure admin did actually edit at least the legal name.
|
||||
if (config.myLegalName == defaultLegalName)
|
||||
askAdminToEditConfig(configFile)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
private fun createDefaultConfigFile(configFile: Path?, defaultLegalName: String) {
|
||||
Files.write(configFile,
|
||||
"""
|
||||
# Node configuration: give the buyer node the name 'Bank of Zurich' (no quotes)
|
||||
# The seller node can be named whatever you like.
|
||||
|
||||
myLegalName = $defaultLegalName
|
||||
""".trimIndent().toByteArray())
|
||||
}
|
||||
|
||||
private fun printHelp() {
|
||||
println("""
|
||||
Please refer to the documentation in docs/build/index.html to learn how to run the demo.
|
||||
""".trimIndent())
|
||||
println("Please refer to the documentation in docs/build/index.html to learn how to run the demo.")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user