Merge remote-tracking branch 'open/master' into os-merge-20180724

# Conflicts:
#	CONTRIBUTORS.md
#	docs/source/contributing.rst
#	docs/source/corda-configuration-file.rst
#	docs/source/index.rst
#	node/src/integration-test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt
#	node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt
#	settings.gradle
This commit is contained in:
Anthony Keenan 2018-07-24 11:33:21 +01:00
commit 4708c62de4
10 changed files with 75 additions and 113 deletions

View File

@ -1,5 +1,5 @@
=========================
Building Container Images
Building container images
=========================
To build a container image of Corda you can use the Jib gradle tasks. See the `documentation of the Jib gradle plugin <https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin>`_ for details.

View File

@ -102,9 +102,10 @@ absolute path to the node's base directory.
:dataSource.user: Database user.
:dataSource.password: Database password.
:h2port: A number that's used to pick the H2 JDBC server port. If not set a randomly chosen port will be used. For production
use you will typically be using a different, non-H2 database backend (e.g. Oracle, SQL Server, Postgres) so this option
is intended primarily for developer mode.
:h2Port: Deprecated. Use ``h2Settings`` instead.
:h2Settings: Sets the H2 JDBC server port. See :doc:`node-database-access-h2`.
:messagingServerAddress: The address of the ArtemisMQ broker instance. If not provided the node will run one locally.

View File

@ -247,7 +247,7 @@ You can clone these repos to your local machine by running the command ``git clo
.. _deb-ubuntu-label:
Debian/Ubuntu
------
-------------
.. warning:: If you are using a Mac or a Windows machine, please follow the :ref:`mac-label` or :ref:`windows-label` instructions instead.

View File

@ -13,9 +13,10 @@ Any database browsing tool that supports JDBC can be used, but if you have Intel
a tool integrated with your IDE. Just open the database window and add an H2 data source with the above details.
You will now be able to browse the tables and row data within them.
By default the node will expose its database on the localhost network interface. This behaviour can be
overridden by specifying the full network address (interface and port), using the new h2Settings
syntax in the node configuration:
By default, the node's H2 database is not exposed. This behaviour can be overridden by specifying the full network
address (interface and port), using the new ``h2Settings`` syntax in the node configuration.
The configuration below will restrict the H2 service to run on ``localhost``:
.. sourcecode:: groovy
@ -23,9 +24,21 @@ syntax in the node configuration:
address: "localhost:12345"
}
The configuration above will restrict the H2 service to run on localhost. If remote access is required, the address
can be changed to 0.0.0.0. However it is recommended to change the default username and password
before doing so.
If you want H2 to auto-select a port (mimicking the old ``h2Port`` behaviour), you can use:
.. sourcecode:: groovy
h2Settings {
address: "localhost:0"
}
If remote access is required, the address can be changed to ``0.0.0.0``. However it is recommended to change the default username and password before doing so.
.. sourcecode:: groovy
h2Settings {
address: "0.0.0.0:12345"
}
The previous ``h2Port`` syntax is now deprecated. ``h2Port`` will continue to work but the database
will only be accessible on localhost.
will only be accessible on localhost.

View File

@ -89,7 +89,7 @@ class ArtemisMessagingTest {
}
LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeInternalTestDataSourceProperties(configSupplier = { ConfigFactory.empty() }), DatabaseConfig(runMigration = true), { null }, { null })
networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database, emptyList()).start(), rigorousMock(), database)
networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database, emptyList()), rigorousMock(), database)
}
@After

View File

@ -22,16 +22,7 @@ import net.corda.core.context.InvocationContext
import net.corda.core.crypto.isCRLDistributionPointBlacklisted
import net.corda.core.crypto.newSecureRandom
import net.corda.core.crypto.sign
import net.corda.core.flows.ContractUpgradeFlow
import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowLogicRefFactory
import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.NotaryChangeFlow
import net.corda.core.flows.NotaryFlow
import net.corda.core.flows.StartableByService
import net.corda.core.flows.*
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
@ -56,22 +47,21 @@ import net.corda.core.node.services.CordaService
import net.corda.core.node.services.IdentityService
import net.corda.core.node.services.KeyManagementService
import net.corda.core.node.services.TransactionVerifierService
import net.corda.core.internal.uncheckedCast
import net.corda.core.messaging.*
import net.corda.core.node.*
import net.corda.core.node.services.*
import net.corda.core.serialization.SerializationWhitelist
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.days
import net.corda.core.utilities.debug
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.minutes
import net.corda.core.utilities.*
import net.corda.node.CordaClock
import net.corda.node.VersionInfo
import net.corda.node.cordapp.CordappLoader
import net.corda.node.internal.CheckpointVerifier.verifyCheckpointsCompatible
import net.corda.node.internal.classloading.requireAnnotation
import net.corda.node.internal.cordapp.CordappConfigFileProvider
import net.corda.node.internal.cordapp.JarScanningCordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.node.internal.cordapp.CordappProviderInternal
import net.corda.node.internal.rpc.proxies.AuthenticatedRpcOpsProxy
@ -81,26 +71,9 @@ import net.corda.node.internal.security.RPCSecurityManager
import net.corda.node.services.ContractUpgradeHandler
import net.corda.node.services.FinalityHandler
import net.corda.node.services.NotaryChangeHandler
import net.corda.node.services.api.CheckpointStorage
import net.corda.node.services.api.DummyAuditService
import net.corda.node.services.api.FlowStarter
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.api.MonitoringService
import net.corda.node.services.api.NetworkMapCacheBaseInternal
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.node.services.api.NodePropertiesStore
import net.corda.node.services.api.SchedulerService
import net.corda.node.services.api.SchemaService
import net.corda.node.services.api.ServiceHubInternal
import net.corda.node.services.api.StartedNodeServices
import net.corda.node.services.api.VaultServiceInternal
import net.corda.node.services.api.WritableTransactionStorage
import net.corda.node.services.config.BFTSMaRtConfiguration
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.config.configureWithDevSSLCertificate
import net.corda.node.services.api.*
import net.corda.node.services.config.*
import net.corda.node.services.config.shell.toShellConfig
import net.corda.node.services.config.shouldInitCrashShell
import net.corda.node.services.events.NodeSchedulerService
import net.corda.node.services.events.ScheduledActivityObserver
import net.corda.node.services.identity.PersistentIdentityService
@ -139,6 +112,12 @@ import net.corda.node.services.transactions.RaftUniquenessProvider
import net.corda.node.services.transactions.RaftValidatingNotaryService
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.node.services.network.*
import net.corda.node.services.persistence.*
import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.statemachine.*
import net.corda.node.services.transactions.*
import net.corda.node.services.upgrade.ContractUpgradeServiceImpl
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.utilities.AffinityExecutor
@ -292,7 +271,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
// TODO The fact that we need to specify an empty list of notaries just to generate our node info looks
// like a design smell.
val persistentNetworkMapCache = PersistentNetworkMapCache(database, notaries = emptyList())
persistentNetworkMapCache.start()
val (_, nodeInfo) = updateNodeInfo(persistentNetworkMapCache, null, identity, identityKeyPair)
nodeInfo
}
@ -303,8 +281,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
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()
PersistentNetworkMapCache(it, emptyList()).clearNetworkMapCache()
}
}
@ -357,7 +334,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
"Node's platform version is lower than network's required minimumPlatformVersion"
}
val (startedImpl, schedulerService) = database.transaction {
val networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database, networkParameters.notaries).start(), identityService, database)
val networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database, networkParameters.notaries), identityService, database)
val (keyPairs, nodeInfo) = updateNodeInfo(networkMapCache, networkMapClient, identity, identityKeyPair)
identityService.loadIdentities(nodeInfo.legalIdentitiesAndCerts)
val metrics = MetricRegistry()
@ -908,13 +885,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
}
}
protected open fun checkNetworkMapIsInitialized() {
if (!services.networkMapCache.loadDBSuccess) {
// TODO: There should be a consistent approach to configuration error exceptions.
throw NetworkMapCacheEmptyException()
}
}
protected open fun makeKeyManagementService(identityService: IdentityService, keyPairs: Set<KeyPair>, database: CordaPersistence): KeyManagementService {
return PersistentKeyManagementService(identityService, keyPairs, database)
}
@ -1149,11 +1119,6 @@ internal class FlowStarterImpl(private val smm: StateMachineManager, private val
class ConfigurationException(message: String) : CordaException(message)
/**
* Thrown when a node is about to start and its network map cache doesn't contain any node.
*/
internal class NetworkMapCacheEmptyException : Exception()
/**
* Creates the connection pool to the database.
*

View File

@ -34,7 +34,6 @@ import net.corda.node.services.network.NetworkMapUpdater
import net.corda.node.services.statemachine.ExternalEvent
import net.corda.node.services.statemachine.FlowStateMachineImpl
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.contextDatabase
interface NetworkMapCacheInternal : NetworkMapCache, NetworkMapCacheBaseInternal
interface NetworkMapCacheBaseInternal : NetworkMapCacheBase {
@ -51,9 +50,6 @@ interface NetworkMapCacheBaseInternal : NetworkMapCacheBase {
/** Removes a node from the local cache. */
fun removeNode(node: NodeInfo)
/** Indicates if loading network map data from database was successful. */
val loadDBSuccess: Boolean
}
interface ServiceHubInternal : ServiceHub {

View File

@ -101,26 +101,8 @@ open class PersistentNetworkMapCache(
// TODO revisit the logic under which nodeReady and loadDBSuccess are set.
// with the NetworkMapService redesign their meaning is not too well defined.
private val _registrationFuture = openFuture<Void?>()
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
private var _loadDBSuccess: Boolean = false
override val loadDBSuccess get() = _loadDBSuccess
fun start(): PersistentNetworkMapCache {
// if we find any network map information in the db, we are good to go - if not
// we have to wait for some being added
synchronized(_changed) {
val allNodes = database.transaction { getAllInfos(session) }
if (allNodes.isNotEmpty()) {
_loadDBSuccess = true
}
allNodes.forEach {
changePublisher.onNext(MapChange.Added(it.toNodeInfo()))
}
_registrationFuture.set(null)
}
return this
}
private val _nodeReady = openFuture<Void?>()
override val nodeReady: CordaFuture<Void?> = _nodeReady
override val notaryIdentities: List<Party> = notaries.map { it.identity }
private val validatingNotaries = notaries.mapNotNullTo(HashSet()) { if (it.validating) it.identity else null }
@ -176,11 +158,15 @@ open class PersistentNetworkMapCache(
}
}
override fun getNodesByLegalName(name: CordaX500Name): List<NodeInfo> = database.transaction { queryByLegalName(session, name) }.sortedByDescending { it.serial }
override fun getNodesByLegalName(name: CordaX500Name): List<NodeInfo> {
return database.transaction { queryByLegalName(session, name) }.sortedByDescending { it.serial }
}
override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> = nodesByKeyCache[identityKey]!!
private val nodesByKeyCache = NonInvalidatingCache<PublicKey, List<NodeInfo>>(1024, { key -> database.transaction { queryByIdentityKey(session, key) } })
private val nodesByKeyCache = NonInvalidatingCache<PublicKey, List<NodeInfo>>(1024) { key ->
database.transaction { queryByIdentityKey(session, key) }
}
override fun getNodesByOwningKeyIndex(identityKeyIndex: String): List<NodeInfo> {
return database.transaction {
@ -188,16 +174,21 @@ open class PersistentNetworkMapCache(
}
}
override fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo? = database.transaction { queryByAddress(session, address) }
override fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo? {
return database.transaction { queryByAddress(session, address) }
}
override fun getPeerCertificateByLegalName(name: CordaX500Name): PartyAndCertificate? = identityByLegalNameCache.get(name)!!.orElse(null)
override fun getPeerCertificateByLegalName(name: CordaX500Name): PartyAndCertificate? {
return identityByLegalNameCache.get(name)!!.orElse(null)
}
private val identityByLegalNameCache = NonInvalidatingCache<CordaX500Name, Optional<PartyAndCertificate>>(1024, { name -> Optional.ofNullable(database.transaction { queryIdentityByLegalName(session, name) }) })
private val identityByLegalNameCache = NonInvalidatingCache<CordaX500Name, Optional<PartyAndCertificate>>(1024) { name ->
Optional.ofNullable(database.transaction { queryIdentityByLegalName(session, name) })
}
override fun track(): DataFeed<List<NodeInfo>, MapChange> {
synchronized(_changed) {
val allInfos = database.transaction { getAllInfos(session).map { it.toNodeInfo() } }
return DataFeed(allInfos, _changed.bufferUntilSubscribed().wrapWithDatabaseTransaction())
return DataFeed(allNodes, _changed.bufferUntilSubscribed().wrapWithDatabaseTransaction())
}
}
@ -224,9 +215,8 @@ open class PersistentNetworkMapCache(
logger.info("Previous node was identical to incoming one - doing nothing")
}
}
_loadDBSuccess = true // This is used in AbstractNode to indicate that node is ready.
_registrationFuture.set(null)
logger.info("Done adding node with info: $node")
_nodeReady.set(null)
logger.debug { "Done adding node with info: $node" }
}
override fun removeNode(node: NodeInfo) {
@ -237,15 +227,16 @@ open class PersistentNetworkMapCache(
changePublisher.onNext(MapChange.Removed(node))
}
}
logger.info("Done removing node with info: $node")
logger.debug { "Done removing node with info: $node" }
}
override val allNodes: List<NodeInfo>
get() = database.transaction {
getAllInfos(session).map { it.toNodeInfo() }
override val allNodes: List<NodeInfo> get() {
return database.transaction {
getAllNodeInfos(session).map { it.toNodeInfo() }
}
}
private fun getAllInfos(session: Session): List<NodeInfoSchemaV1.PersistentNodeInfo> {
private fun getAllNodeInfos(session: Session): List<NodeInfoSchemaV1.PersistentNodeInfo> {
val criteria = session.criteriaBuilder.createQuery(NodeInfoSchemaV1.PersistentNodeInfo::class.java)
criteria.select(criteria.from(NodeInfoSchemaV1.PersistentNodeInfo::class.java))
return session.createQuery(criteria).resultList
@ -355,7 +346,7 @@ open class PersistentNetworkMapCache(
logger.info("Clearing Network Map Cache entries")
invalidateCaches()
database.transaction {
val result = getAllInfos(session)
val result = getAllNodeInfos(session)
logger.debug { "Number of node infos to be cleared: ${result.size}" }
for (nodeInfo in result) session.remove(nodeInfo)
}

View File

@ -312,12 +312,6 @@ open class InternalMockNetwork(defaultParameters: MockNetworkParameters = MockNe
return Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, counter)
}
/**
* InternalMockNetwork will ensure nodes are connected to each other. The nodes themselves
* won't be able to tell if that happened already or not.
*/
override fun checkNetworkMapIsInitialized() = Unit
override fun makeTransactionVerifierService() = InMemoryTransactionVerifierService(1)
// NodeInfo requires a non-empty addresses list and so we give it a dummy value for mock nodes.

View File

@ -155,9 +155,11 @@ class NodeTabView : Fragment() {
hbox {
button("Add CorDapp") {
setOnAction {
val app = (chooser.showOpenDialog(null) ?: return@setOnAction).toPath()
if (!cordapps.contains(app)) {
cordapps.add(app)
(chooser.showOpenMultipleDialog(null) ?: return@setOnAction).forEach {
val app = it.toPath()
if (!cordapps.contains(app)) {
cordapps.add(app)
}
}
}