Display simple statistics about the node on each tab.

This commit is contained in:
Chris Rankin 2017-02-02 12:03:12 +00:00
parent 51d02e1e45
commit cd5dde70e0
6 changed files with 110 additions and 9 deletions

View File

@ -33,9 +33,13 @@ repositories {
mavenLocal()
mavenCentral()
jcenter()
maven {
url 'http://www.sparetimelabs.com/maven2'
}
maven {
url 'https://dl.bintray.com/kotlin/exposed'
}
}
dependencies {
@ -43,12 +47,16 @@ dependencies {
compile "no.tornado:tornadofx:$tornadofx_version"
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
// ONLY USING THE RPC CLIENT!?
compile project(':node')
compile "com.h2database:h2:$h2_version"
compile "net.java.dev.jna:jna:$jna_version"
compile "net.java.dev.jna:jna-platform:$jna_version"
compile "com.google.guava:guava:$guava_version"
compile "com.sparetimelabs:purejavacomm:$purejavacomm_version"
compile "org.slf4j:log4j-over-slf4j:$slf4j_version"
compile "org.slf4j:jcl-over-slf4j:$slf4j_version"
compile "org.slf4j:jul-to-slf4j:$slf4j_version"
compile "ch.qos.logback:logback-classic:$logback_version"
compile "com.typesafe:config:$typesafe_config_version"
@ -58,6 +66,11 @@ dependencies {
testCompile group: 'junit', name: 'junit', version: "$junit_version"
}
// We don't want the Node to drag these transitive dependencies in either!
configurations.compile.exclude module: 'commons-logging'
configurations.compile.exclude module: 'log4j-slf4j-impl'
configurations.compile.exclude module: 'log4j-core'
jar {
manifest {
attributes 'Main-Class': mainClassName

View File

@ -15,7 +15,10 @@ class Explorer(val explorerController: ExplorerController) : AutoCloseable {
"--host=localhost",
"--port=%d".format(config.artemisPort),
"--username=%s".format(config.user["user"]),
"--password=%s".format(config.user["password"])
"--password=%s".format(config.user["password"]),
"--certificatesDir=%s".format(config.ssl.certificatesDirectory),
"--keyStorePassword=%s".format(config.ssl.keyStorePassword),
"--trustStorePassword=%s".format(config.ssl.trustStorePassword)
)
process = p

View File

@ -4,9 +4,12 @@ import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigValue
import com.typesafe.config.ConfigValueFactory
import net.corda.node.services.config.SSLConfiguration
import java.lang.String.join
import java.nio.file.Path
class NodeConfig(
baseDir: Path,
legalName: String,
artemisPort: Int,
val nearestCity: String,
@ -15,15 +18,23 @@ class NodeConfig(
val extraServices: List<String>
) : NetworkMapConfig(legalName, artemisPort) {
val nodeDir: Path = baseDir.resolve(key)
private var networkMapValue: NetworkMapConfig? = null
var networkMap : NetworkMapConfig?
get() { return networkMapValue }
get() = networkMapValue
set(value) { networkMapValue = value }
private val userMap: Map<String, String>
val user: Map<String, String>
get() = userMap
val ssl: SSLConfiguration = object : SSLConfiguration {
override val certificatesDirectory: Path = nodeDir.resolve("certificates")
override val trustStorePassword: String = "trustpass"
override val keyStorePassword: String = "cordacadevpass"
}
val toFileConfig : Config
get() = ConfigFactory.empty()
.withValue("myLegalName", valueFor(legalName))

View File

@ -13,7 +13,7 @@ import tornadofx.Controller
class NodeController : Controller() {
private val FIRST_PORT = 10000
private val workDir = Paths.get("work", localDir).toAbsolutePath()
private val baseDir = Paths.get("work", localDir).toAbsolutePath()
private val jvm by inject<JVMConfig>()
private val cordaPath = Paths.get("corda", "corda.jar").toAbsolutePath()
@ -28,6 +28,7 @@ class NodeController : Controller() {
fun validate(nodeData: NodeData): NodeConfig? {
val config = NodeConfig(
baseDir,
nodeData.legalName.value.trim(),
nodeData.artemisPort.value,
nodeData.nearestCity.value.trim(),
@ -37,6 +38,7 @@ class NodeController : Controller() {
)
if (nodes.putIfAbsent(config.key, config) != null) {
log.warning("Node with key '" + config.key + "' already exists.")
return null
}
@ -67,7 +69,7 @@ class NodeController : Controller() {
}
fun runCorda(pty: R3Pty, config: NodeConfig): Boolean {
val nodeDir = workDir.resolve(config.key).toFile()
val nodeDir = config.nodeDir.toFile()
if (nodeDir.mkdirs()) {
try {
@ -93,7 +95,7 @@ class NodeController : Controller() {
.format(Date(ManagementFactory.getRuntimeMXBean().startTime))
init {
log.info("Working directory: " + workDir)
log.info("Base directory: " + baseDir)
log.info("Corda JAR: " + cordaPath)
}
}

View File

@ -0,0 +1,48 @@
package net.corda.demobench.rpc
import com.google.common.net.HostAndPort
import java.util.*
import java.util.concurrent.TimeUnit.SECONDS
import net.corda.core.messaging.CordaRPCOps
import net.corda.demobench.model.NodeConfig
import net.corda.node.services.messaging.CordaRPCClient
import org.slf4j.LoggerFactory
class NodeRPC(config: NodeConfig, invoke: (ops: CordaRPCOps) -> Unit): AutoCloseable {
private val log = LoggerFactory.getLogger(NodeRPC::class.java)
private val ONE_SECOND = SECONDS.toMillis(1)
private val rpcClient = CordaRPCClient(HostAndPort.fromParts("localhost", config.artemisPort), config.ssl)
private val timer = Timer()
override fun close() {
timer.cancel()
rpcClient.close()
}
init {
val setupTask = object : TimerTask() {
override fun run() {
try {
rpcClient.start(config.user.getOrElse("user") { "none" }, config.user.getOrElse("password") { "none" })
val ops = rpcClient.proxy()
// Cancel the "setup" task now that we've created the RPC client.
this.cancel()
// Schedule a new task that will refresh the display once per second.
timer.schedule(object: TimerTask() {
override fun run() {
invoke(ops)
}
}, 0, ONE_SECOND)
} catch (e: Exception) {
log.warn("Node '{}' not ready yet (Error: {})", config.legalName, e.message)
}
}
}
// Wait 5 seconds for the node to start, and then poll once per second.
timer.schedule(setupTask, 5 * ONE_SECOND, ONE_SECOND)
}
}

View File

@ -4,6 +4,7 @@ import com.jediterm.terminal.TerminalColor
import com.jediterm.terminal.TextStyle
import com.jediterm.terminal.ui.settings.DefaultSettingsProvider
import java.awt.Dimension
import javafx.application.Platform
import javafx.embed.swing.SwingNode
import javafx.scene.control.Button
import javafx.scene.control.Label
@ -12,9 +13,11 @@ import javafx.scene.layout.VBox
import javax.swing.SwingUtilities
import net.corda.demobench.model.*
import net.corda.demobench.pty.R3Pty
import net.corda.demobench.rpc.NodeRPC
import net.corda.demobench.ui.PropertyLabel
import tornadofx.Fragment
import tornadofx.vgrow
import java.util.*
class NodeTerminalView : Fragment() {
override val root by fxml<VBox>()
@ -31,9 +34,10 @@ class NodeTerminalView : Fragment() {
private val viewDatabaseButton by fxid<Button>()
private val launchExplorerButton by fxid<Button>()
val explorer = explorerController.explorer()
val viewer = DBViewer()
var pty : R3Pty? = null
private val explorer = explorerController.explorer()
private val viewer = DBViewer()
private var rpc: NodeRPC? = null
private var pty: R3Pty? = null
fun open(config: NodeConfig) {
nodeName.text = config.legalName
@ -65,18 +69,38 @@ class NodeTerminalView : Fragment() {
* the explorer has exited.
*/
launchExplorerButton.setOnAction {
launchExplorerButton.isDisable= true
launchExplorerButton.isDisable = true
explorer.open(config, onExit = {
launchExplorerButton.isDisable = false
})
}
rpc = NodeRPC(config, { ops ->
try {
val verifiedTx = ops.verifiedTransactions()
val statesInVault = ops.vaultAndUpdates()
val cashBalances = ops.getCashBalances().entries.joinToString(
separator = ", ",
transform = { e -> "%s %s".format(e.value, e.key.currencyCode) }
)
Platform.runLater {
states.value = statesInVault.first.size.toString()
transactions.value = verifiedTx.first.size.toString()
balance.value = cashBalances
}
} catch (e: Exception) {
log.warning("RPC failed: " + e)
}
})
})
}
fun close() {
explorer.close()
viewer.close()
rpc?.close()
pty?.close()
}