Refactoring related to obsolete attachments directory (#1150)

* No longer create obsolete "attachments" directory
* Remove redundant NodeAttachmentService param
* Add type param to MockNetwork.Factory to eliminate casts
* Use null not -1 for unforced node ID
* Remove redundant createNode args
This commit is contained in:
Andrzej Cichocki 2017-08-03 11:06:22 +01:00 committed by GitHub
parent 3c8368e25d
commit 73528d287d
15 changed files with 75 additions and 103 deletions

View File

@ -151,7 +151,7 @@ class AttachmentSerializationTest {
private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String { private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String {
client.stop() client.stop()
client = mockNet.createNode(server.network.myAddress, client.id, object : MockNetwork.Factory { client = mockNet.createNode(server.network.myAddress, client.id, object : MockNetwork.Factory<MockNetwork.MockNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, entropyRoot: BigInteger): MockNetwork.MockNode { override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, entropyRoot: BigInteger): MockNetwork.MockNode {
return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) { return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {
override fun startMessagingService(rpcOps: RPCOps) { override fun startMessagingService(rpcOps: RPCOps) {

View File

@ -413,7 +413,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeServices(): MutableList<Any> { private fun makeServices(): MutableList<Any> {
checkpointStorage = DBCheckpointStorage() checkpointStorage = DBCheckpointStorage()
_services = ServiceHubInternalImpl() _services = ServiceHubInternalImpl()
attachments = createAttachmentStorage() attachments = NodeAttachmentService(configuration.dataSourceProperties, services.monitoringService.metrics, configuration.database)
network = makeMessagingService() network = makeMessagingService()
info = makeInfo() info = makeInfo()
@ -762,11 +762,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected open fun generateKeyPair() = cryptoGenerateKeyPair() protected open fun generateKeyPair() = cryptoGenerateKeyPair()
private fun createAttachmentStorage(): NodeAttachmentService {
val attachmentsDir = (configuration.baseDirectory / "attachments").createDirectories()
return NodeAttachmentService(attachmentsDir, configuration.dataSourceProperties, services.monitoringService.metrics, configuration.database)
}
private inner class ServiceHubInternalImpl : ServiceHubInternal, SingletonSerializeAsToken() { private inner class ServiceHubInternalImpl : ServiceHubInternal, SingletonSerializeAsToken() {
override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>() override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>()
override val uploaders = ArrayList<FileUploader>() override val uploaders = ArrayList<FileUploader>()

View File

@ -9,7 +9,6 @@ import com.google.common.io.CountingInputStream
import net.corda.core.contracts.AbstractAttachment import net.corda.core.contracts.AbstractAttachment
import net.corda.core.contracts.Attachment import net.corda.core.contracts.Attachment
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.internal.isDirectory
import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.AttachmentStorage
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
@ -22,7 +21,6 @@ import java.io.FilterInputStream
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.nio.file.FileAlreadyExistsException import java.nio.file.FileAlreadyExistsException
import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.util.* import java.util.*
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
@ -32,7 +30,7 @@ import javax.annotation.concurrent.ThreadSafe
* Stores attachments in H2 database. * Stores attachments in H2 database.
*/ */
@ThreadSafe @ThreadSafe
class NodeAttachmentService(val storePath: Path, dataSourceProperties: Properties, metrics: MetricRegistry, databaseProperties: Properties?) class NodeAttachmentService(dataSourceProperties: Properties, metrics: MetricRegistry, databaseProperties: Properties?)
: AttachmentStorage, AcceptsFileUpload, SingletonSerializeAsToken() { : AttachmentStorage, AcceptsFileUpload, SingletonSerializeAsToken() {
companion object { companion object {
private val log = loggerFor<NodeAttachmentService>() private val log = loggerFor<NodeAttachmentService>()
@ -47,8 +45,6 @@ class NodeAttachmentService(val storePath: Path, dataSourceProperties: Propertie
private val attachmentCount = metrics.counter("Attachments") private val attachmentCount = metrics.counter("Attachments")
init { init {
require(storePath.isDirectory()) { "$storePath must be a directory" }
session.withTransaction { session.withTransaction {
attachmentCount.inc(session.count(AttachmentEntity::class).get().value().toLong()) attachmentCount.inc(session.count(AttachmentEntity::class).get().value().toLong())
} }

View File

@ -103,7 +103,7 @@ class AttachmentTests {
@Test @Test
fun `malicious response`() { fun `malicious response`() {
// Make a node that doesn't do sanity checking at load time. // Make a node that doesn't do sanity checking at load time.
val n0 = mockNet.createNode(null, -1, object : MockNetwork.Factory { val n0 = mockNet.createNode(nodeFactory = object : MockNetwork.Factory<MockNetwork.MockNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, advertisedServices: Set<ServiceInfo>, id: Int,
overrideServices: Map<ServiceInfo, KeyPair>?, overrideServices: Map<ServiceInfo, KeyPair>?,
@ -115,7 +115,7 @@ class AttachmentTests {
} }
} }
} }
}, true, null, null, ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)) }, advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
val n1 = mockNet.createNode(n0.network.myAddress) val n1 = mockNet.createNode(n0.network.myAddress)
val attachment = fakeAttachment() val attachment = fakeAttachment()

View File

@ -249,7 +249,7 @@ class TwoPartyTradeFlowTests {
// ... bring the node back up ... the act of constructing the SMM will re-register the message handlers // ... bring the node back up ... the act of constructing the SMM will re-register the message handlers
// that Bob was waiting on before the reboot occurred. // that Bob was waiting on before the reboot occurred.
bobNode = mockNet.createNode(networkMapAddress, bobAddr.id, object : MockNetwork.Factory { bobNode = mockNet.createNode(networkMapAddress, bobAddr.id, object : MockNetwork.Factory<MockNetwork.MockNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): MockNetwork.MockNode {
@ -290,10 +290,9 @@ class TwoPartyTradeFlowTests {
// of gets and puts. // of gets and puts.
private fun makeNodeWithTracking( private fun makeNodeWithTracking(
networkMapAddress: SingleMessageRecipient?, networkMapAddress: SingleMessageRecipient?,
name: X500Name, name: X500Name): MockNetwork.MockNode {
overridenServices: Map<ServiceInfo, KeyPair>? = null): MockNetwork.MockNode {
// Create a node in the mock network ... // Create a node in the mock network ...
return mockNet.createNode(networkMapAddress, -1, object : MockNetwork.Factory { return mockNet.createNode(networkMapAddress, nodeFactory = object : MockNetwork.Factory<MockNetwork.MockNode> {
override fun create(config: NodeConfiguration, override fun create(config: NodeConfiguration,
network: MockNetwork, network: MockNetwork,
networkMapAddr: SingleMessageRecipient?, networkMapAddr: SingleMessageRecipient?,
@ -307,7 +306,7 @@ class TwoPartyTradeFlowTests {
} }
} }
} }
}, true, name, overridenServices) }, legalName = name)
} }
@Test @Test

View File

@ -1,7 +1,6 @@
package net.corda.node.services.network package net.corda.node.services.network
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.crypto.random63BitValue
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
@ -53,8 +52,11 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(defaultFactory = nodeFactory) mockNet = MockNetwork(defaultFactory = nodeFactory)
mapServiceNode = mockNet.createNode(null, -1, nodeFactory, true, DUMMY_MAP.name, null, BigInteger.valueOf(random63BitValue()), ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)) mapServiceNode = mockNet.createNode(
alice = mockNet.createNode(mapServiceNode.network.myAddress, -1, nodeFactory, true, ALICE.name) nodeFactory = nodeFactory,
legalName = DUMMY_MAP.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
alice = mockNet.createNode(mapServiceNode.network.myAddress, nodeFactory = nodeFactory, legalName = ALICE.name)
mockNet.runNetwork() mockNet.runNetwork()
lastSerial = System.currentTimeMillis() lastSerial = System.currentTimeMillis()
} }
@ -64,7 +66,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
mockNet.stopNodes() mockNet.stopNodes()
} }
protected abstract val nodeFactory: MockNetwork.Factory protected abstract val nodeFactory: MockNetwork.Factory<*>
protected abstract val networkMapService: S protected abstract val networkMapService: S
@ -249,7 +251,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
} }
private fun addNewNodeToNetworkMap(legalName: X500Name): MockNode { private fun addNewNodeToNetworkMap(legalName: X500Name): MockNode {
val node = mockNet.createNode(networkMapAddress = mapServiceNode.network.myAddress, legalName = legalName) val node = mockNet.createNode(mapServiceNode.network.myAddress, legalName = legalName)
mockNet.runNetwork() mockNet.runNetwork()
lastSerial = System.currentTimeMillis() lastSerial = System.currentTimeMillis()
return node return node
@ -269,7 +271,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
} }
} }
private object NoNMSNodeFactory : MockNetwork.Factory { private object NoNMSNodeFactory : MockNetwork.Factory<MockNode> {
override fun create(config: NodeConfiguration, override fun create(config: NodeConfiguration,
network: MockNetwork, network: MockNetwork,
networkMapAddr: SingleMessageRecipient?, networkMapAddr: SingleMessageRecipient?,

View File

@ -38,8 +38,8 @@ class InMemoryNetworkMapCacheTest {
@Test @Test
fun `key collision`() { fun `key collision`() {
val entropy = BigInteger.valueOf(24012017L) val entropy = BigInteger.valueOf(24012017L)
val nodeA = mockNet.createNode(null, -1, MockNetwork.DefaultFactory, true, ALICE.name, null, entropy, ServiceInfo(NetworkMapService.type)) val nodeA = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
val nodeB = mockNet.createNode(null, -1, MockNetwork.DefaultFactory, true, BOB.name, null, entropy, ServiceInfo(NetworkMapService.type)) val nodeB = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = BOB.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
assertEquals(nodeA.info.legalIdentity, nodeB.info.legalIdentity) assertEquals(nodeA.info.legalIdentity, nodeB.info.legalIdentity)
mockNet.runNetwork() mockNet.runNetwork()

View File

@ -1,10 +1,9 @@
package net.corda.node.services.network package net.corda.node.services.network
import net.corda.node.services.network.InMemoryNetworkMapService
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
class InMemoryNetworkMapServiceTest : AbstractNetworkMapServiceTest<InMemoryNetworkMapService>() { class InMemoryNetworkMapServiceTest : AbstractNetworkMapServiceTest<InMemoryNetworkMapService>() {
override val nodeFactory: MockNetwork.Factory get() = MockNetwork.DefaultFactory override val nodeFactory get() = MockNetwork.DefaultFactory
override val networkMapService: InMemoryNetworkMapService get() = mapServiceNode.inNodeNetworkMapService as InMemoryNetworkMapService override val networkMapService: InMemoryNetworkMapService get() = mapServiceNode.inNodeNetworkMapService as InMemoryNetworkMapService
override fun swizzle() = Unit override fun swizzle() = Unit
} }

View File

@ -15,7 +15,7 @@ import java.security.KeyPair
*/ */
class PersistentNetworkMapServiceTest : AbstractNetworkMapServiceTest<PersistentNetworkMapService>() { class PersistentNetworkMapServiceTest : AbstractNetworkMapServiceTest<PersistentNetworkMapService>() {
override val nodeFactory: MockNetwork.Factory get() = NodeFactory override val nodeFactory: MockNetwork.Factory<*> get() = NodeFactory
override val networkMapService: PersistentNetworkMapService override val networkMapService: PersistentNetworkMapService
get() = (mapServiceNode.inNodeNetworkMapService as SwizzleNetworkMapService).delegate get() = (mapServiceNode.inNodeNetworkMapService as SwizzleNetworkMapService).delegate
@ -26,7 +26,7 @@ class PersistentNetworkMapServiceTest : AbstractNetworkMapServiceTest<Persistent
} }
} }
private object NodeFactory : MockNetwork.Factory { private object NodeFactory : MockNetwork.Factory<MockNode> {
override fun create(config: NodeConfiguration, override fun create(config: NodeConfiguration,
network: MockNetwork, network: MockNetwork,
networkMapAddr: SingleMessageRecipient?, networkMapAddr: SingleMessageRecipient?,

View File

@ -60,7 +60,7 @@ class NodeAttachmentStorageTest {
val expectedHash = testJar.readAll().sha256() val expectedHash = testJar.readAll().sha256()
database.transaction { database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties()) val storage = NodeAttachmentService(dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
val id = testJar.read { storage.importAttachment(it) } val id = testJar.read { storage.importAttachment(it) }
assertEquals(expectedHash, id) assertEquals(expectedHash, id)
@ -86,7 +86,7 @@ class NodeAttachmentStorageTest {
fun `duplicates not allowed`() { fun `duplicates not allowed`() {
val testJar = makeTestJar() val testJar = makeTestJar()
database.transaction { database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties()) val storage = NodeAttachmentService(dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
testJar.read { testJar.read {
storage.importAttachment(it) storage.importAttachment(it)
} }
@ -102,7 +102,7 @@ class NodeAttachmentStorageTest {
fun `corrupt entry throws exception`() { fun `corrupt entry throws exception`() {
val testJar = makeTestJar() val testJar = makeTestJar()
database.transaction { database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties()) val storage = NodeAttachmentService(dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
val id = testJar.read { storage.importAttachment(it) } val id = testJar.read { storage.importAttachment(it) }
// Corrupt the file in the store. // Corrupt the file in the store.
@ -130,7 +130,7 @@ class NodeAttachmentStorageTest {
@Test @Test
fun `non jar rejected`() { fun `non jar rejected`() {
database.transaction { database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties()) val storage = NodeAttachmentService(dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
val path = fs.getPath("notajar") val path = fs.getPath("notajar")
path.writeLines(listOf("Hey", "there!")) path.writeLines(listOf("Hey", "there!"))
path.read { path.read {

View File

@ -170,7 +170,7 @@ class FlowFrameworkTests {
node3.disableDBCloseOnStop() node3.disableDBCloseOnStop()
node3.stop() node3.stop()
node3 = mockNet.createNode(node1.network.myAddress, forcedID = node3.id) node3 = mockNet.createNode(node1.network.myAddress, node3.id)
val restoredFlow = node3.getSingleFlow<NoOpFlow>().first val restoredFlow = node3.getSingleFlow<NoOpFlow>().first
assertEquals(false, restoredFlow.flowStarted) // Not started yet as no network activity has been allowed yet assertEquals(false, restoredFlow.flowStarted) // Not started yet as no network activity has been allowed yet
mockNet.runNetwork() // Allow network map messages to flow mockNet.runNetwork() // Allow network map messages to flow
@ -180,7 +180,7 @@ class FlowFrameworkTests {
node3.stop() node3.stop()
// Now it is completed the flow should leave no Checkpoint. // Now it is completed the flow should leave no Checkpoint.
node3 = mockNet.createNode(node1.network.myAddress, forcedID = node3.id) node3 = mockNet.createNode(node1.network.myAddress, node3.id)
mockNet.runNetwork() // Allow network map messages to flow mockNet.runNetwork() // Allow network map messages to flow
node3.smm.executor.flush() node3.smm.executor.flush()
assertTrue(node3.smm.findStateMachines(NoOpFlow::class.java).isEmpty()) assertTrue(node3.smm.findStateMachines(NoOpFlow::class.java).isEmpty())

View File

@ -37,7 +37,7 @@ class NotaryServiceTests {
notaryNode = mockNet.createNode( notaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
clientNode = mockNet.createNode(networkMapAddress = notaryNode.network.myAddress) clientNode = mockNet.createNode(notaryNode.network.myAddress)
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
} }

View File

@ -39,7 +39,7 @@ class ValidatingNotaryServiceTests {
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type)) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type))
) )
clientNode = mockNet.createNode(networkMapAddress = notaryNode.network.myAddress) clientNode = mockNet.createNode(notaryNode.network.myAddress)
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
} }

View File

@ -61,12 +61,12 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
} }
inner class BankFactory : MockNetwork.Factory { inner class BankFactory : MockNetwork.Factory<SimulatedNode> {
var counter = 0 var counter = 0
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): SimulatedNode {
val letter = 'A' + counter val letter = 'A' + counter
val (city, country) = bankLocations[counter++ % bankLocations.size] val (city, country) = bankLocations[counter++ % bankLocations.size]
@ -79,17 +79,17 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
fun createAll(): List<SimulatedNode> { fun createAll(): List<SimulatedNode> {
return bankLocations.mapIndexed { i, _ -> return bankLocations.mapIndexed { i, _ ->
// Use deterministic seeds so the simulation is stable. Needed so that party owning keys are stable. // Use deterministic seeds so the simulation is stable. Needed so that party owning keys are stable.
mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = this, entropyRoot = BigInteger.valueOf(i.toLong())) as SimulatedNode mockNet.createNode(networkMap.network.myAddress, nodeFactory = this, start = false, entropyRoot = BigInteger.valueOf(i.toLong()))
} }
} }
} }
val bankFactory = BankFactory() val bankFactory = BankFactory()
object NetworkMapNodeFactory : MockNetwork.Factory { object NetworkMapNodeFactory : MockNetwork.Factory<SimulatedNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): SimulatedNode {
require(advertisedServices.containsType(NetworkMapService.type)) require(advertisedServices.containsType(NetworkMapService.type))
val cfg = testNodeConfiguration( val cfg = testNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
@ -98,10 +98,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
} }
object NotaryNodeFactory : MockNetwork.Factory { object NotaryNodeFactory : MockNetwork.Factory<SimulatedNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): SimulatedNode {
require(advertisedServices.containsType(SimpleNotaryService.type)) require(advertisedServices.containsType(SimpleNotaryService.type))
val cfg = testNodeConfiguration( val cfg = testNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
@ -110,13 +110,13 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
} }
object RatesOracleFactory : MockNetwork.Factory { object RatesOracleFactory : MockNetwork.Factory<SimulatedNode> {
// TODO: Make a more realistic legal name // TODO: Make a more realistic legal name
val RATES_SERVICE_NAME = X500Name("CN=Rates Service Provider,O=R3,OU=corda,L=Madrid,C=ES") val RATES_SERVICE_NAME = X500Name("CN=Rates Service Provider,O=R3,OU=corda,L=Madrid,C=ES")
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): SimulatedNode {
require(advertisedServices.containsType(NodeInterestRates.Oracle.type)) require(advertisedServices.containsType(NodeInterestRates.Oracle.type))
val cfg = testNodeConfiguration( val cfg = testNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
@ -136,10 +136,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
} }
object RegulatorFactory : MockNetwork.Factory { object RegulatorFactory : MockNetwork.Factory<SimulatedNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): SimulatedNode {
val cfg = testNodeConfiguration( val cfg = testNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = DUMMY_REGULATOR.name) myLegalName = DUMMY_REGULATOR.name)
@ -153,13 +153,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val mockNet = MockNetwork(networkSendManuallyPumped, runAsync) val mockNet = MockNetwork(networkSendManuallyPumped, runAsync)
// This one must come first. // This one must come first.
val networkMap: SimulatedNode val networkMap = mockNet.createNode(nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type))
= mockNet.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) as SimulatedNode val notary = mockNet.createNode(networkMap.network.myAddress, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type))
val notary: SimulatedNode val regulators = listOf(mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RegulatorFactory))
= mockNet.createNode(networkMap.network.myAddress, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode val ratesOracle = mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type))
val regulators: List<SimulatedNode> = listOf(mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
val ratesOracle: SimulatedNode
= mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.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)

View File

@ -13,7 +13,6 @@ import net.corda.core.getOrThrow
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectories
import net.corda.core.internal.createDirectory import net.corda.core.internal.createDirectory
import net.corda.core.internal.div
import net.corda.core.messaging.MessageRecipients import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.RPCOps import net.corda.core.messaging.RPCOps
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
@ -38,11 +37,9 @@ import org.apache.activemq.artemis.utils.ReusableLatch
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.slf4j.Logger import org.slf4j.Logger
import java.math.BigInteger import java.math.BigInteger
import java.nio.file.FileSystem
import java.nio.file.Path import java.nio.file.Path
import java.security.KeyPair import java.security.KeyPair
import java.security.cert.X509Certificate import java.security.cert.X509Certificate
import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
@ -63,23 +60,19 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
private val threadPerNode: Boolean = false, private val threadPerNode: Boolean = false,
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy =
InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(), InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(),
private val defaultFactory: Factory = MockNetwork.DefaultFactory, private val defaultFactory: Factory<*> = MockNetwork.DefaultFactory,
private val initialiseSerialization: Boolean = true) { private val initialiseSerialization: Boolean = true) {
val nextNodeId var nextNodeId = 0
get() = _nextNodeId private set
private var _nextNodeId = 0 private val filesystem = Jimfs.newFileSystem(unix())
val filesystem: FileSystem = Jimfs.newFileSystem(unix()) private val busyLatch = ReusableLatch()
private val busyLatch: ReusableLatch = ReusableLatch()
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch) val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
// A unique identifier for this network to segregate databases with the same nodeID but different networks. // A unique identifier for this network to segregate databases with the same nodeID but different networks.
private val networkId = random63BitValue() private val networkId = random63BitValue()
private val identities = mutableListOf<PartyAndCertificate>()
val identities = ArrayList<PartyAndCertificate>() private val _nodes = mutableListOf<MockNode>()
private val _nodes = ArrayList<MockNode>()
/** A read only view of the current set of executing nodes. */ /** A read only view of the current set of executing nodes. */
val nodes: List<MockNode> = _nodes val nodes: List<MockNode> get() = _nodes
init { init {
if (initialiseSerialization) initialiseTestSerialization() if (initialiseSerialization) initialiseTestSerialization()
@ -87,7 +80,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
} }
/** Allows customisation of how nodes are created. */ /** Allows customisation of how nodes are created. */
interface Factory { interface Factory<out N : MockNode> {
/** /**
* @param overrideServices a set of service entries to use in place of the node's default service entries, * @param overrideServices a set of service entries to use in place of the node's default service entries,
* for example where a node's service is part of a cluster. * for example where a node's service is part of a cluster.
@ -96,10 +89,10 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
*/ */
fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNode entropyRoot: BigInteger): N
} }
object DefaultFactory : Factory { object DefaultFactory : Factory<MockNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNode { entropyRoot: BigInteger): MockNode {
@ -277,16 +270,6 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
} }
} }
/**
* Returns a node, optionally created by the passed factory method.
* @param overrideServices a set of service entries to use in place of the node's default service entries,
* for example where a node's service is part of a cluster.
*/
fun createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int = -1, nodeFactory: Factory = defaultFactory,
start: Boolean = true, legalName: X500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
vararg advertisedServices: ServiceInfo): MockNode
= createNode(networkMapAddress, forcedID, nodeFactory, start, legalName, overrideServices, BigInteger.valueOf(random63BitValue()), *advertisedServices)
/** /**
* Returns a node, optionally created by the passed factory method. * Returns a node, optionally created by the passed factory method.
* @param overrideServices a set of service entries to use in place of the node's default service entries, * @param overrideServices a set of service entries to use in place of the node's default service entries,
@ -295,29 +278,31 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
* but can be overridden to cause nodes to have stable or colliding identity/service keys. * but can be overridden to cause nodes to have stable or colliding identity/service keys.
* @param configOverrides add/override behaviour of the [NodeConfiguration] mock object. * @param configOverrides add/override behaviour of the [NodeConfiguration] mock object.
*/ */
fun createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int = -1, nodeFactory: Factory = defaultFactory, fun createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int? = null,
start: Boolean = true, legalName: X500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null, start: Boolean = true, legalName: X500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()), entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
vararg advertisedServices: ServiceInfo, vararg advertisedServices: ServiceInfo,
configOverrides: (NodeConfiguration) -> Any? = {}): MockNode { configOverrides: (NodeConfiguration) -> Any? = {}): MockNode {
val newNode = forcedID == -1 return createNode(networkMapAddress, forcedID, defaultFactory, start, legalName, overrideServices, entropyRoot, *advertisedServices, configOverrides = configOverrides)
val id = if (newNode) _nextNodeId++ else forcedID }
val path = baseDirectory(id)
if (newNode)
(path / "attachments").createDirectories()
/** Like the other [createNode] but takes a [Factory] and propagates its [MockNode] subtype. */
fun <N : MockNode> createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int? = null, nodeFactory: Factory<N>,
start: Boolean = true, legalName: X500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
vararg advertisedServices: ServiceInfo,
configOverrides: (NodeConfiguration) -> Any? = {}): N {
val id = forcedID ?: nextNodeId++
val config = testNodeConfiguration( val config = testNodeConfiguration(
baseDirectory = path, baseDirectory = baseDirectory(id).createDirectories(),
myLegalName = legalName ?: getTestX509Name("Mock Company $id")).also { myLegalName = legalName ?: getTestX509Name("Mock Company $id")).also {
whenever(it.dataSourceProperties).thenReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")) whenever(it.dataSourceProperties).thenReturn(makeTestDataSourceProperties("node_${id}_net_$networkId"))
configOverrides(it) configOverrides(it)
} }
return nodeFactory.create(config, this, networkMapAddress, advertisedServices.toSet(), id, overrideServices, entropyRoot).apply { return nodeFactory.create(config, this, networkMapAddress, advertisedServices.toSet(), id, overrideServices, entropyRoot).apply {
if (start) { if (start) {
configuration.baseDirectory.createDirectories()
start() start()
if (threadPerNode && networkMapAddress != null) networkMapRegistrationFuture.getOrThrow() if (threadPerNode && networkMapAddress != null) networkMapRegistrationFuture.getOrThrow() // XXX: What about manually-started nodes?
} }
_nodes.add(this) _nodes.add(this)
} }
@ -354,20 +339,19 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
/** /**
* Sets up a network with the requested number of nodes (defaulting to two), with one or more service nodes that * Sets up a network with the requested number of nodes (defaulting to two), with one or more service nodes that
* run a notary, network map, any oracles etc. Can't be combined with [createTwoNodes]. * run a notary, network map, any oracles etc.
*/ */
@JvmOverloads @JvmOverloads
fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes { fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory<*> = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes {
require(nodes.isEmpty()) require(nodes.isEmpty())
val notaryServiceInfo = ServiceInfo(SimpleNotaryService.type) val notaryServiceInfo = ServiceInfo(SimpleNotaryService.type)
val notaryOverride = if (notaryKeyPair != null) val notaryOverride = if (notaryKeyPair != null)
mapOf(Pair(notaryServiceInfo, notaryKeyPair)) mapOf(Pair(notaryServiceInfo, notaryKeyPair))
else else
null null
val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) val mapNode = createNode(nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type))
val mapAddress = mapNode.network.myAddress val mapAddress = mapNode.network.myAddress
val notaryNode = createNode(mapAddress, nodeFactory = nodeFactory, overrideServices = notaryOverride, val notaryNode = createNode(mapAddress, nodeFactory = nodeFactory, overrideServices = notaryOverride, advertisedServices = notaryServiceInfo)
advertisedServices = notaryServiceInfo)
val nodes = ArrayList<MockNode>() val nodes = ArrayList<MockNode>()
repeat(numPartyNodes) { repeat(numPartyNodes) {
nodes += createPartyNode(mapAddress) nodes += createPartyNode(mapAddress)
@ -382,14 +366,14 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
legalName: X500Name? = null, legalName: X500Name? = null,
overrideServices: Map<ServiceInfo, KeyPair>? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
serviceName: X500Name? = null): MockNode { serviceName: X500Name? = null): MockNode {
return createNode(networkMapAddress, -1, defaultFactory, true, legalName, overrideServices, BigInteger.valueOf(random63BitValue()), return createNode(networkMapAddress, legalName = legalName, overrideServices = overrideServices,
ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type, serviceName)) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type, serviceName)))
} }
fun createPartyNode(networkMapAddress: SingleMessageRecipient, fun createPartyNode(networkMapAddress: SingleMessageRecipient,
legalName: X500Name? = null, legalName: X500Name? = null,
overrideServices: Map<ServiceInfo, KeyPair>? = null): MockNode { overrideServices: Map<ServiceInfo, KeyPair>? = null): MockNode {
return createNode(networkMapAddress, -1, defaultFactory, true, legalName, overrideServices) return createNode(networkMapAddress, legalName = legalName, overrideServices = overrideServices)
} }
@Suppress("unused") // This is used from the network visualiser tool. @Suppress("unused") // This is used from the network visualiser tool.