mirror of
https://github.com/corda/corda.git
synced 2025-06-16 22:28:15 +00:00
[CORDA-442] let Driver run without network map (#1890)
* [CORDA-442] let Driver run without network map - Nodes started by driver run without a networkMapNode. - Driver does not take a networkMapStartStrategy anymore - a new parameter in the configuration "noNetworkMapServiceMode" allows for a node not to be a networkMapNode nor to connect to one. - Driver now waits for each node to write its own NodeInfo file to disk and then copies it into each other node. - When driver starts a node N, it waits for every node to be have N nodes in their network map. Note: the code to copy around the NodeInfo files was already in DemoBench, the NodeInfoFilesCopier class was just moved from DemoBench into core (I'm very open to core not being the best place, please advise)
This commit is contained in:
@ -14,7 +14,6 @@ import net.corda.nodeapi.internal.ServiceType
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.ProjectStructure.projectRootDir
|
||||
import net.corda.testing.driver.ListenProcessDeathException
|
||||
import net.corda.testing.driver.NetworkMapStartStrategy
|
||||
import net.corda.testing.driver.driver
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
@ -59,7 +58,7 @@ class BootTests {
|
||||
@Test
|
||||
fun `node quits on failure to register with network map`() {
|
||||
val tooManyAdvertisedServices = (1..100).map { ServiceInfo(ServiceType.notary.getSubType("$it")) }.toSet()
|
||||
driver(networkMapStartStrategy = NetworkMapStartStrategy.Nominated(ALICE.name)) {
|
||||
driver {
|
||||
val future = startNode(providedName = ALICE.name)
|
||||
assertFailsWith(ListenProcessDeathException::class) { future.getOrThrow() }
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.corda.node
|
||||
|
||||
import com.google.common.base.Stopwatch
|
||||
import net.corda.testing.driver.NetworkMapStartStrategy
|
||||
import net.corda.testing.driver.driver
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
@ -14,8 +13,7 @@ class NodeStartupPerformanceTests {
|
||||
// Measure the startup time of nodes. Note that this includes an RPC roundtrip, which causes e.g. Kryo initialisation.
|
||||
@Test
|
||||
fun `single node startup time`() {
|
||||
driver(networkMapStartStrategy = NetworkMapStartStrategy.Dedicated(startAutomatically = false)) {
|
||||
startDedicatedNetworkMapService().get()
|
||||
driver {
|
||||
val times = ArrayList<Long>()
|
||||
for (i in 1..10) {
|
||||
val time = Stopwatch.createStarted().apply {
|
||||
|
@ -8,6 +8,7 @@ import net.corda.core.internal.div
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.KeyManagementService
|
||||
import net.corda.node.services.identity.InMemoryIdentityService
|
||||
import net.corda.nodeapi.NodeInfoFilesCopier
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.ALICE_KEY
|
||||
import net.corda.testing.DEV_TRUST_ROOT
|
||||
@ -42,7 +43,6 @@ class NodeInfoWatcherTest : NodeBasedTest() {
|
||||
lateinit var nodeInfoWatcher: NodeInfoWatcher
|
||||
|
||||
companion object {
|
||||
val nodeInfoFileRegex = Regex("nodeInfo\\-.*")
|
||||
val nodeInfo = NodeInfo(listOf(), listOf(getTestPartyAndCertificate(ALICE)), 0, 0)
|
||||
}
|
||||
|
||||
@ -56,13 +56,14 @@ class NodeInfoWatcherTest : NodeBasedTest() {
|
||||
|
||||
@Test
|
||||
fun `save a NodeInfo`() {
|
||||
assertEquals(0, folder.root.list().filter { it.matches(nodeInfoFileRegex) }.size)
|
||||
assertEquals(0,
|
||||
folder.root.list().filter { it.startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX) }.size)
|
||||
NodeInfoWatcher.saveToFile(folder.root.toPath(), nodeInfo, keyManagementService)
|
||||
|
||||
val nodeInfoFiles = folder.root.list().filter { it.matches(nodeInfoFileRegex) }
|
||||
val nodeInfoFiles = folder.root.list().filter { it.startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX) }
|
||||
assertEquals(1, nodeInfoFiles.size)
|
||||
val fileName = nodeInfoFiles.first()
|
||||
assertTrue(fileName.matches(nodeInfoFileRegex))
|
||||
assertTrue(fileName.startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX))
|
||||
val file = (folder.root.path / fileName).toFile()
|
||||
// Just check that something is written, another tests verifies that the written value can be read back.
|
||||
assertThat(contentOf(file)).isNotEmpty()
|
||||
|
@ -552,8 +552,16 @@ abstract class AbstractNode(config: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupInNodeNetworkMapService(networkMapCache: NetworkMapCacheInternal) {
|
||||
inNodeNetworkMapService =
|
||||
if (configuration.networkMapService == null && !configuration.noNetworkMapServiceMode)
|
||||
makeNetworkMapService(network, networkMapCache)
|
||||
else
|
||||
NullNetworkMapService
|
||||
}
|
||||
|
||||
private fun makeNetworkServices(network: MessagingService, networkMapCache: NetworkMapCacheInternal, tokenizableServices: MutableList<Any>) {
|
||||
inNodeNetworkMapService = if (configuration.networkMapService == null) makeNetworkMapService(network, networkMapCache) else NullNetworkMapService
|
||||
setupInNodeNetworkMapService(networkMapCache)
|
||||
configuration.notary?.let {
|
||||
val notaryService = makeCoreNotaryService(it)
|
||||
tokenizableServices.add(notaryService)
|
||||
@ -612,7 +620,7 @@ abstract class AbstractNode(config: NodeConfiguration,
|
||||
|
||||
/** This is overriden by the mock node implementation to enable operation without any network map service */
|
||||
protected open fun noNetworkMapConfigured(): CordaFuture<Unit> {
|
||||
if (services.networkMapCache.loadDBSuccess) {
|
||||
if (services.networkMapCache.loadDBSuccess || configuration.noNetworkMapServiceMode) {
|
||||
return doneFuture(Unit)
|
||||
} else {
|
||||
// TODO: There should be a consistent approach to configuration error exceptions.
|
||||
|
@ -20,6 +20,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
* service.
|
||||
*/
|
||||
val networkMapService: NetworkMapInfo?
|
||||
val noNetworkMapServiceMode: Boolean
|
||||
val minimumPlatformVersion: Int
|
||||
val emailAddress: String
|
||||
val exportJMXto: String
|
||||
@ -78,6 +79,7 @@ data class FullNodeConfiguration(
|
||||
override val database: Properties?,
|
||||
override val certificateSigningService: URL,
|
||||
override val networkMapService: NetworkMapInfo?,
|
||||
override val noNetworkMapServiceMode: Boolean = false,
|
||||
override val minimumPlatformVersion: Int = 1,
|
||||
override val rpcUsers: List<User>,
|
||||
override val verifierType: VerifierType,
|
||||
|
@ -9,6 +9,7 @@ import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.nodeapi.NodeInfoFilesCopier
|
||||
import rx.Observable
|
||||
import rx.Scheduler
|
||||
import rx.schedulers.Schedulers
|
||||
@ -55,7 +56,8 @@ class NodeInfoWatcher(private val nodePath: Path,
|
||||
val serializedBytes = nodeInfo.serialize()
|
||||
val regSig = keyManager.sign(serializedBytes.bytes, nodeInfo.legalIdentities.first().owningKey)
|
||||
val signedData = SignedData(serializedBytes, regSig)
|
||||
signedData.serialize().open().copyTo(path / "nodeInfo-${serializedBytes.hash}")
|
||||
signedData.serialize().open().copyTo(
|
||||
path / "${NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX}${serializedBytes.hash}")
|
||||
} catch (e: Exception) {
|
||||
logger.warn("Couldn't write node info to file", e)
|
||||
}
|
||||
|
Reference in New Issue
Block a user