mirror of
https://github.com/corda/corda.git
synced 2025-01-18 10:46:38 +00:00
CORDA-1493: add --clear-network-map-cache command line option (#3272)
CORDA-1493: add --clear-network-map-cache command
This commit is contained in:
parent
5d1cc0bd54
commit
3758dbea34
@ -55,6 +55,7 @@ class NodeArgsParser : AbstractArgsParser<CmdLineOptions>() {
|
||||
private val justGenerateNodeInfoArg = optionParser.accepts("just-generate-node-info",
|
||||
"Perform the node start-up task necessary to generate its nodeInfo, save it to disk, then quit")
|
||||
private val bootstrapRaftClusterArg = optionParser.accepts("bootstrap-raft-cluster", "Bootstraps Raft cluster. The node forms a single node cluster (ignoring otherwise configured peer addresses), acting as a seed for other nodes to join the cluster.")
|
||||
private val clearNetworkMapCache = optionParser.accepts("clear-network-map-cache", "Clears local copy of network map, on node startup it will be restored from server or file system.")
|
||||
|
||||
override fun doParse(optionSet: OptionSet): CmdLineOptions {
|
||||
require(!optionSet.has(baseDirectoryArg) || !optionSet.has(configFileArg)) {
|
||||
@ -74,6 +75,7 @@ class NodeArgsParser : AbstractArgsParser<CmdLineOptions>() {
|
||||
val networkRootTrustStorePassword = optionSet.valueOf(networkRootTrustStorePasswordArg)
|
||||
val unknownConfigKeysPolicy = optionSet.valueOf(unknownConfigKeysPolicy)
|
||||
val devMode = optionSet.has(devModeArg)
|
||||
val clearNetworkMapCache = optionSet.has(clearNetworkMapCache)
|
||||
|
||||
val registrationConfig = if (isRegistration) {
|
||||
requireNotNull(networkRootTrustStorePassword) { "Network root trust store password must be provided in registration mode using --network-root-truststore-password." }
|
||||
@ -94,7 +96,8 @@ class NodeArgsParser : AbstractArgsParser<CmdLineOptions>() {
|
||||
justGenerateNodeInfo,
|
||||
bootstrapRaftCluster,
|
||||
unknownConfigKeysPolicy,
|
||||
devMode)
|
||||
devMode,
|
||||
clearNetworkMapCache)
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +114,8 @@ data class CmdLineOptions(val baseDirectory: Path,
|
||||
val justGenerateNodeInfo: Boolean,
|
||||
val bootstrapRaftCluster: Boolean,
|
||||
val unknownConfigKeysPolicy: UnknownConfigKeysPolicy,
|
||||
val devMode: Boolean) {
|
||||
val devMode: Boolean,
|
||||
val clearNetworkMapCache: Boolean) {
|
||||
fun loadConfig(): Pair<Config, Try<NodeConfiguration>> {
|
||||
val rawConfig = ConfigHelper.loadConfig(
|
||||
baseDirectory,
|
||||
|
@ -274,6 +274,15 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
fun clearNetworkMapCache() {
|
||||
Node.printBasicNodeInfo("Clearing network map cache entries")
|
||||
log.info("Starting clearing of network map cache entries...")
|
||||
configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use {
|
||||
val networkMapCache = PersistentNetworkMapCache(it, emptyList())
|
||||
networkMapCache.clearNetworkMapCache()
|
||||
}
|
||||
}
|
||||
|
||||
open fun start(): StartedNode<AbstractNode> {
|
||||
check(started == null) { "Node has already been started" }
|
||||
if (configuration.devMode) {
|
||||
|
@ -58,7 +58,6 @@ open class NodeStartup(val args: Array<String>) {
|
||||
return false
|
||||
}
|
||||
val cmdlineOptions = NodeArgsParser().parseOrExit(*args)
|
||||
|
||||
// We do the single node check before we initialise logging so that in case of a double-node start it
|
||||
// doesn't mess with the running node's logs.
|
||||
enforceSingleNodeIsRunning(cmdlineOptions.baseDirectory)
|
||||
@ -153,6 +152,10 @@ open class NodeStartup(val args: Array<String>) {
|
||||
|
||||
protected open fun startNode(conf: NodeConfiguration, versionInfo: VersionInfo, startTime: Long, cmdlineOptions: CmdLineOptions) {
|
||||
val node = createNode(conf, versionInfo)
|
||||
if (cmdlineOptions.clearNetworkMapCache) {
|
||||
node.clearNetworkMapCache()
|
||||
return
|
||||
}
|
||||
if (cmdlineOptions.justGenerateNodeInfo) {
|
||||
// Perform the minimum required start-up logic to be able to write a nodeInfo to disk
|
||||
node.generateAndSaveNodeInfo()
|
||||
|
@ -19,6 +19,7 @@ import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.debug
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.internal.schemas.NodeInfoSchemaV1
|
||||
import net.corda.node.services.api.NetworkMapCacheBaseInternal
|
||||
@ -339,9 +340,11 @@ open class PersistentNetworkMapCache(
|
||||
}
|
||||
|
||||
override fun clearNetworkMapCache() {
|
||||
logger.info("Clearing Network Map Cache entries")
|
||||
invalidateCaches()
|
||||
database.transaction {
|
||||
val result = getAllInfos(session)
|
||||
logger.debug { "Number of node infos to be cleared: ${result.size}" }
|
||||
for (nodeInfo in result) session.remove(nodeInfo)
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ class NodeArgsParserTest {
|
||||
justGenerateNodeInfo = false,
|
||||
bootstrapRaftCluster = false,
|
||||
unknownConfigKeysPolicy = UnknownConfigKeysPolicy.FAIL,
|
||||
devMode = false))
|
||||
devMode = false,
|
||||
clearNetworkMapCache = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -158,6 +159,12 @@ class NodeArgsParserTest {
|
||||
assertThat(cmdLineOptions.justGenerateNodeInfo).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clear network map cache`() {
|
||||
val cmdLineOptions = parser.parse("--clear-network-map-cache")
|
||||
assertThat(cmdLineOptions.clearNetworkMapCache).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `bootstrap raft cluster`() {
|
||||
val cmdLineOptions = parser.parse("--bootstrap-raft-cluster")
|
||||
|
@ -7,15 +7,21 @@ import net.corda.core.internal.delete
|
||||
import net.corda.core.internal.list
|
||||
import net.corda.core.internal.readObject
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.internal.schemas.NodeInfoSchemaV1
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier.Companion.NODE_INFO_FILE_NAME_PREFIX
|
||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.internal.createNodeInfoAndSigned
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
@ -52,12 +58,58 @@ class NodeTest {
|
||||
|
||||
@Test
|
||||
fun `generateAndSaveNodeInfo works`() {
|
||||
val nodeAddress = NetworkHostAndPort("0.1.2.3", 456)
|
||||
val nodeName = CordaX500Name("Manx Blockchain Corp", "Douglas", "IM")
|
||||
val configuration = createConfig()
|
||||
val platformVersion = 789
|
||||
configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use { database ->
|
||||
val node = Node(configuration, rigorousMock<VersionInfo>().also {
|
||||
doReturn(platformVersion).whenever(it).platformVersion
|
||||
}, initialiseSerialization = false)
|
||||
assertEquals(node.generateNodeInfo(), node.generateNodeInfo()) // Node info doesn't change (including the serial)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clear network map cache works`() {
|
||||
val configuration = createConfig()
|
||||
val (nodeInfo, _) = createNodeInfoAndSigned(ALICE_NAME)
|
||||
configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use {
|
||||
it.transaction {
|
||||
val persistentNodeInfo = NodeInfoSchemaV1.PersistentNodeInfo(
|
||||
id = 0,
|
||||
hash = nodeInfo.serialize().hash.toString(),
|
||||
addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) },
|
||||
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.mapIndexed { idx, elem ->
|
||||
NodeInfoSchemaV1.DBPartyAndCertificate(elem, isMain = idx == 0)
|
||||
},
|
||||
platformVersion = nodeInfo.platformVersion,
|
||||
serial = nodeInfo.serial
|
||||
)
|
||||
// Save some NodeInfo
|
||||
session.save(persistentNodeInfo)
|
||||
}
|
||||
val node = Node(configuration, rigorousMock<VersionInfo>().also {
|
||||
doReturn(10).whenever(it).platformVersion
|
||||
}, initialiseSerialization = false)
|
||||
assertThat(getAllInfos(it)).isNotEmpty
|
||||
node.clearNetworkMapCache()
|
||||
assertThat(getAllInfos(it)).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllInfos(database: CordaPersistence): List<NodeInfoSchemaV1.PersistentNodeInfo> {
|
||||
return database.transaction {
|
||||
val criteria = session.criteriaBuilder.createQuery(NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
||||
criteria.select(criteria.from(NodeInfoSchemaV1.PersistentNodeInfo::class.java))
|
||||
session.createQuery(criteria).resultList
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConfig(): NodeConfiguration {
|
||||
val dataSourceProperties = makeTestDataSourceProperties()
|
||||
val databaseConfig = DatabaseConfig()
|
||||
val configuration = rigorousMock<AbstractNodeConfiguration>().also {
|
||||
val nodeAddress = NetworkHostAndPort("0.1.2.3", 456)
|
||||
val nodeName = CordaX500Name("Manx Blockchain Corp", "Douglas", "IM")
|
||||
return rigorousMock<AbstractNodeConfiguration>().also {
|
||||
doReturn(nodeAddress).whenever(it).p2pAddress
|
||||
doReturn(nodeName).whenever(it).myLegalName
|
||||
doReturn(null).whenever(it).notary // Don't add notary identity.
|
||||
@ -68,11 +120,5 @@ class NodeTest {
|
||||
doReturn("tsp").whenever(it).trustStorePassword
|
||||
doReturn("ksp").whenever(it).keyStorePassword
|
||||
}
|
||||
configureDatabase(dataSourceProperties, databaseConfig, { null }, { null }).use { database ->
|
||||
val node = Node(configuration, rigorousMock<VersionInfo>().also {
|
||||
doReturn(platformVersion).whenever(it).platformVersion
|
||||
}, initialiseSerialization = false)
|
||||
assertEquals(node.generateNodeInfo(), node.generateNodeInfo()) // Node info doesn't change (including the serial)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user