Tweak the simulation so that the startup sequence of the network (with map registration etc) can be observed.

This commit is contained in:
Mike Hearn 2016-05-11 18:08:41 +02:00 committed by Mike Hearn
parent 474054411d
commit 5de2ba4ef9
6 changed files with 45 additions and 27 deletions

View File

@ -28,7 +28,7 @@ class IRSSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork
private val executeOnNextIteration = Collections.synchronizedList(LinkedList<() -> Unit>()) private val executeOnNextIteration = Collections.synchronizedList(LinkedList<() -> Unit>())
override fun start() { override fun startMainSimulation() {
startIRSDealBetween(0, 1).success { startIRSDealBetween(0, 1).success {
// Next iteration is a pause. // Next iteration is a pause.
executeOnNextIteration.add {} executeOnNextIteration.add {}

View File

@ -99,12 +99,13 @@ class MockNetwork(private val threadPerNode: Boolean = false,
return this return this
} }
val place: PhysicalLocation get() = info.physicalLocation!! // This does not indirect through the NodeInfo object so it can be called before the node is started.
val place: PhysicalLocation get() = findMyLocation()!!
} }
/** Returns a started node, optionally created by the passed factory method */ /** Returns a node, optionally created by the passed factory method. */
fun createNode(networkMapAddress: NodeInfo? = null, forcedID: Int = -1, nodeFactory: Factory = defaultFactory, fun createNode(networkMapAddress: NodeInfo? = null, forcedID: Int = -1, nodeFactory: Factory = defaultFactory,
legalName: String? = null, keyPair: KeyPair? = null, vararg advertisedServices: ServiceType): MockNode { start: Boolean = true, legalName: String? = null, keyPair: KeyPair? = null, vararg advertisedServices: ServiceType): MockNode {
val newNode = forcedID == -1 val newNode = forcedID == -1
val id = if (newNode) counter++ else forcedID val id = if (newNode) counter++ else forcedID
@ -116,7 +117,8 @@ class MockNetwork(private val threadPerNode: Boolean = false,
override val exportJMXto: String = "" override val exportJMXto: String = ""
override val nearestCity: String = "Atlantis" override val nearestCity: String = "Atlantis"
} }
val node = nodeFactory.create(path, config, this, networkMapAddress, advertisedServices.toSet(), id, keyPair).start() val node = nodeFactory.create(path, config, this, networkMapAddress, advertisedServices.toSet(), id, keyPair)
if (start) node.start()
_nodes.add(node) _nodes.add(node)
return node return node
} }
@ -143,13 +145,23 @@ class MockNetwork(private val threadPerNode: Boolean = false,
fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> { fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> {
require(nodes.isEmpty()) require(nodes.isEmpty())
return Pair( return Pair(
createNode(null, -1, nodeFactory, null, notaryKeyPair, NetworkMapService.Type, NotaryService.Type), createNode(null, -1, nodeFactory, true, null, notaryKeyPair, NetworkMapService.Type, NotaryService.Type),
createNode(nodes[0].info, -1, nodeFactory, null) createNode(nodes[0].info, -1, nodeFactory, true, null)
) )
} }
fun createNotaryNode(legalName: String? = null, keyPair: KeyPair? = null) = createNode(null, -1, defaultFactory, legalName, keyPair, NetworkMapService.Type, NotaryService.Type) fun createNotaryNode(legalName: String? = null, keyPair: KeyPair? = null) = createNode(null, -1, defaultFactory, true, legalName, keyPair, NetworkMapService.Type, NotaryService.Type)
fun createPartyNode(networkMapAddr: NodeInfo, legalName: String? = null, keyPair: KeyPair? = null) = createNode(networkMapAddr, -1, defaultFactory, legalName, keyPair) fun createPartyNode(networkMapAddr: NodeInfo, legalName: String? = null, keyPair: KeyPair? = null) = createNode(networkMapAddr, -1, defaultFactory, true, legalName, keyPair)
fun addressToNode(address: SingleMessageRecipient): MockNode = nodes.single { it.net.myAddress == address } fun addressToNode(address: SingleMessageRecipient): MockNode = nodes.single { it.net.myAddress == address }
fun startNodes() {
require(nodes.isNotEmpty())
nodes.forEach { if (!it.started) it.start() }
}
fun stopNodes() {
require(nodes.isNotEmpty())
nodes.forEach { if (it.started) it.stop() }
}
} }

View File

@ -1,5 +1,6 @@
package core.testing package core.testing
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import core.node.CityDatabase import core.node.CityDatabase
import core.node.NodeConfiguration import core.node.NodeConfiguration
@ -58,7 +59,7 @@ abstract class Simulation(val runAsync: Boolean,
} }
fun createAll(): List<SimulatedNode> = bankLocations. fun createAll(): List<SimulatedNode> = bankLocations.
map { network.createNode(networkMap.info, nodeFactory = this) as SimulatedNode } map { network.createNode(networkMap.info, start = false, nodeFactory = this) as SimulatedNode }
} }
val bankFactory = BankFactory() val bankFactory = BankFactory()
@ -128,26 +129,19 @@ abstract class Simulation(val runAsync: Boolean,
} }
val network = MockNetwork(false) val network = MockNetwork(false)
// This one must come first.
val regulators: List<SimulatedNode> = listOf(network.createNode(null, nodeFactory = RegulatorFactory) as SimulatedNode)
val networkMap: SimulatedNode val networkMap: SimulatedNode
= network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = NetworkMapService.Type) as SimulatedNode = network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = NetworkMapService.Type) as SimulatedNode
val notary: SimulatedNode val notary: SimulatedNode
= network.createNode(null, nodeFactory = NotaryNodeFactory, advertisedServices = NotaryService.Type) as SimulatedNode = network.createNode(networkMap.info, nodeFactory = NotaryNodeFactory, advertisedServices = NotaryService.Type) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
val ratesOracle: SimulatedNode val ratesOracle: SimulatedNode
= network.createNode(null, nodeFactory = RatesOracleFactory, advertisedServices = NodeInterestRates.Type) as SimulatedNode = network.createNode(networkMap.info, start = false, nodeFactory = RatesOracleFactory, advertisedServices = NodeInterestRates.Type) as SimulatedNode
// All nodes must be in one of these two lists for the purposes of the visualiser tool. // All nodes must be in one of these two lists for the purposes of the visualiser tool.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap) val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)
val banks: List<SimulatedNode> = bankFactory.createAll() val banks: List<SimulatedNode> = bankFactory.createAll()
init {
// Now wire up the network maps for each node.
for (node in regulators + serviceProviders + banks) {
node.services.networkMapCache.addNode(node.info)
}
}
private val _allProtocolSteps = PublishSubject.create<Pair<SimulatedNode, ProgressTracker.Change>>() private val _allProtocolSteps = PublishSubject.create<Pair<SimulatedNode, ProgressTracker.Change>>()
private val _doneSteps = PublishSubject.create<Collection<SimulatedNode>>() private val _doneSteps = PublishSubject.create<Collection<SimulatedNode>>()
val allProtocolSteps: Observable<Pair<SimulatedNode, ProgressTracker.Change>> = _allProtocolSteps val allProtocolSteps: Observable<Pair<SimulatedNode, ProgressTracker.Change>> = _allProtocolSteps
@ -214,11 +208,23 @@ abstract class Simulation(val runAsync: Boolean,
} }
} }
open fun start() { fun start() {
network.startNodes()
// Wait for all the nodes to have finished registering with the network map service.
Futures.allAsList(network.nodes.map { it.networkMapRegistrationFuture }).then {
startMainSimulation()
}
}
/**
* Sub-classes should override this to trigger whatever they want to simulate. This method will be invoked once the
* network bringup has been simulated.
*/
protected open fun startMainSimulation() {
} }
fun stop() { fun stop() {
network.nodes.forEach { it.stop() } network.stopNodes()
} }
/** /**

View File

@ -16,7 +16,7 @@ import java.time.Instant
* then B and C trade with each other, then C and A etc). * then B and C trade with each other, then C and A etc).
*/ */
class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(runAsync, latencyInjector) { class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(runAsync, latencyInjector) {
override fun start() { override fun startMainSimulation() {
BriefLogFormatter.loggingOn("bank", "core.contract.TransactionGroup", "recordingmap") BriefLogFormatter.loggingOn("bank", "core.contract.TransactionGroup", "recordingmap")
startTradingCircle { i, j -> tradeBetween(i, j) } startTradingCircle { i, j -> tradeBetween(i, j) }
} }

View File

@ -100,7 +100,7 @@ class AttachmentTests {
} }
} }
} }
}, null, null, NetworkMapService.Type, NotaryService.Type) }, true, null, null, NetworkMapService.Type, NotaryService.Type)
val n1 = network.createNode(n0.info) val n1 = network.createNode(n0.info)
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.

View File

@ -180,7 +180,7 @@ class TwoPartyTradeProtocolTests {
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
return MockNetwork.MockNode(dir, config, network, networkMapAddr, advertisedServices, bobAddr.id, BOB_KEY) return MockNetwork.MockNode(dir, config, network, networkMapAddr, advertisedServices, bobAddr.id, BOB_KEY)
} }
}, BOB.name, BOB_KEY) }, true, BOB.name, BOB_KEY)
// TODO: remove once validated transactions are persisted to disk // TODO: remove once validated transactions are persisted to disk
bobNode.storage.validatedTransactions.putAll(recordedTransactions) bobNode.storage.validatedTransactions.putAll(recordedTransactions)
@ -213,7 +213,7 @@ class TwoPartyTradeProtocolTests {
} }
} }
} }
}, name, keyPair) }, true, name, keyPair)
} }
@Test @Test