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>())
override fun start() {
override fun startMainSimulation() {
startIRSDealBetween(0, 1).success {
// Next iteration is a pause.
executeOnNextIteration.add {}

View File

@ -99,12 +99,13 @@ class MockNetwork(private val threadPerNode: Boolean = false,
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,
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 id = if (newNode) counter++ else forcedID
@ -116,7 +117,8 @@ class MockNetwork(private val threadPerNode: Boolean = false,
override val exportJMXto: String = ""
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)
return node
}
@ -143,13 +145,23 @@ class MockNetwork(private val threadPerNode: Boolean = false,
fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> {
require(nodes.isEmpty())
return Pair(
createNode(null, -1, nodeFactory, null, notaryKeyPair, NetworkMapService.Type, NotaryService.Type),
createNode(nodes[0].info, -1, nodeFactory, null)
createNode(null, -1, nodeFactory, true, null, notaryKeyPair, NetworkMapService.Type, NotaryService.Type),
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 createPartyNode(networkMapAddr: NodeInfo, legalName: String? = null, keyPair: KeyPair? = null) = createNode(networkMapAddr, -1, defaultFactory, legalName, keyPair)
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, true, legalName, keyPair)
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
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import core.node.CityDatabase
import core.node.NodeConfiguration
@ -58,7 +59,7 @@ abstract class Simulation(val runAsync: Boolean,
}
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()
@ -128,26 +129,19 @@ abstract class Simulation(val runAsync: Boolean,
}
val network = MockNetwork(false)
val regulators: List<SimulatedNode> = listOf(network.createNode(null, nodeFactory = RegulatorFactory) as SimulatedNode)
// This one must come first.
val networkMap: SimulatedNode
= network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = NetworkMapService.Type) as 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
= 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.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)
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 _doneSteps = PublishSubject.create<Collection<SimulatedNode>>()
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() {
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).
*/
class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(runAsync, latencyInjector) {
override fun start() {
override fun startMainSimulation() {
BriefLogFormatter.loggingOn("bank", "core.contract.TransactionGroup", "recordingmap")
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)
// 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 {
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
bobNode.storage.validatedTransactions.putAll(recordedTransactions)
@ -213,7 +213,7 @@ class TwoPartyTradeProtocolTests {
}
}
}
}, name, keyPair)
}, true, name, keyPair)
}
@Test