CORDA-599 Remove unnecessary laziness (#1517)

This commit is contained in:
Andrzej Cichocki 2017-10-03 16:30:17 +01:00 committed by GitHub
parent eb0e2535ed
commit ab7507db69
10 changed files with 30 additions and 37 deletions

View File

@ -185,8 +185,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
check(started == null) { "Node has already been started" }
initCertificate()
log.info("Generating nodeInfo ...")
initialiseDatabasePersistence {
makeServices()
val schemaService = NodeSchemaService()
initialiseDatabasePersistence(schemaService) {
makeServices(schemaService)
saveOwnNodeInfo()
}
}
@ -195,9 +196,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
check(started == null) { "Node has already been started" }
initCertificate()
log.info("Node starting up ...")
val schemaService = NodeSchemaService()
// Do all of this in a database transaction so anything that might need a connection has one.
val startedImpl = initialiseDatabasePersistence {
val tokenizableServices = makeServices()
val startedImpl = initialiseDatabasePersistence(schemaService) {
val tokenizableServices = makeServices(schemaService)
saveOwnNodeInfo()
smm = StateMachineManager(services,
checkpointStorage,
@ -391,10 +393,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
* Builds node internal, advertised, and plugin services.
* Returns a list of tokenizable services to be added to the serialisation context.
*/
private fun makeServices(): MutableList<Any> {
private fun makeServices(schemaService: SchemaService): MutableList<Any> {
checkpointStorage = DBCheckpointStorage()
cordappProvider = CordappProviderImpl(cordappLoader)
_services = ServiceHubInternalImpl()
_services = ServiceHubInternalImpl(schemaService)
attachments = NodeAttachmentService(services.monitoringService.metrics)
cordappProvider.start(attachments)
legalIdentity = obtainIdentity()
@ -482,10 +484,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
// Specific class so that MockNode can catch it.
class DatabaseConfigurationException(msg: String) : CordaException(msg)
protected open fun <T> initialiseDatabasePersistence(insideTransaction: () -> T): T {
protected open fun <T> initialiseDatabasePersistence(schemaService: SchemaService, insideTransaction: () -> T): T {
val props = configuration.dataSourceProperties
if (props.isNotEmpty()) {
this.database = configureDatabase(props, configuration.database, { _services.schemaService }, createIdentityService = { _services.identityService })
this.database = configureDatabase(props, configuration.database, schemaService, { _services.identityService })
// Now log the vendor string as this will also cause a connection to be tested eagerly.
database.transaction {
log.info("Connected to ${database.dataSource.connection.metaData.databaseProductName} database.")
@ -689,15 +691,13 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected open fun generateKeyPair() = cryptoGenerateKeyPair()
private inner class ServiceHubInternalImpl : ServiceHubInternal, SingletonSerializeAsToken() {
private inner class ServiceHubInternalImpl(override val schemaService: SchemaService) : ServiceHubInternal, SingletonSerializeAsToken() {
override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>()
override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage()
override val auditService = DummyAuditService()
override val monitoringService = MonitoringService(MetricRegistry())
override val validatedTransactions = makeTransactionStorage()
override val transactionVerifierService by lazy { makeTransactionVerifierService() }
override val schemaService by lazy { NodeSchemaService() }
override val networkMapCache by lazy { PersistentNetworkMapCache(this) }
override val vaultService by lazy { NodeVaultService(this, database.hibernateConfig) }
override val contractUpgradeService by lazy { ContractUpgradeServiceImpl() }

View File

@ -15,11 +15,11 @@ import net.corda.core.node.ServiceHub
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.utilities.*
import net.corda.node.VersionInfo
import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.node.serialization.NodeClock
import net.corda.node.services.RPCUserService
import net.corda.node.services.RPCUserServiceImpl
import net.corda.node.services.api.SchemaService
import net.corda.nodeapi.internal.ServiceInfo
import net.corda.node.services.config.FullNodeConfiguration
import net.corda.node.services.messaging.ArtemisMessagingServer
@ -287,7 +287,7 @@ open class Node(override val configuration: FullNodeConfiguration,
* This is not using the H2 "automatic mixed mode" directly but leans on many of the underpinnings. For more details
* on H2 URLs and configuration see: http://www.h2database.com/html/features.html#database_url
*/
override fun <T> initialiseDatabasePersistence(insideTransaction: () -> T): T {
override fun <T> initialiseDatabasePersistence(schemaService: SchemaService, insideTransaction: () -> T): T {
val databaseUrl = configuration.dataSourceProperties.getProperty("dataSource.url")
val h2Prefix = "jdbc:h2:file:"
if (databaseUrl != null && databaseUrl.startsWith(h2Prefix)) {
@ -304,7 +304,7 @@ open class Node(override val configuration: FullNodeConfiguration,
printBasicNodeInfo("Database connection url is", "jdbc:h2:$url/node")
}
}
return super.initialiseDatabasePersistence(insideTransaction)
return super.initialiseDatabasePersistence(schemaService, insideTransaction)
}
private val _startupComplete = openFuture<Unit>()

View File

@ -24,7 +24,7 @@ import java.sql.Connection
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class HibernateConfiguration(createSchemaService: () -> SchemaService, private val databaseProperties: Properties, private val createIdentityScervice: () -> IdentityService) {
class HibernateConfiguration(val schemaService: SchemaService, private val databaseProperties: Properties, private val createIdentityService: () -> IdentityService) {
companion object {
val logger = loggerFor<HibernateConfiguration>()
}
@ -33,7 +33,6 @@ class HibernateConfiguration(createSchemaService: () -> SchemaService, private v
private val sessionFactories = ConcurrentHashMap<Set<MappedSchema>, SessionFactory>()
private val transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel") ?:"")
var schemaService = createSchemaService()
init {
logger.info("Init HibernateConfiguration for schemas: ${schemaService.schemaOptions.keys}")
@ -86,7 +85,7 @@ class HibernateConfiguration(createSchemaService: () -> SchemaService, private v
}
})
// register custom converters
applyAttributeConverter(AbstractPartyToX500NameAsStringConverter(createIdentityScervice))
applyAttributeConverter(AbstractPartyToX500NameAsStringConverter(createIdentityService))
// Register a tweaked version of `org.hibernate.type.MaterializedBlobType` that truncates logged messages.
// to avoid OOM when large blobs might get logged.
applyBasicType(CordaMaterializedBlobType, CordaMaterializedBlobType.name)

View File

@ -23,13 +23,13 @@ import java.util.concurrent.CopyOnWriteArrayList
const val NODE_DATABASE_PREFIX = "node_"
//HikariDataSource implements Closeable which allows CordaPersistence to be Closeable
class CordaPersistence(var dataSource: HikariDataSource, private var createSchemaService: () -> SchemaService,
class CordaPersistence(var dataSource: HikariDataSource, private val schemaService: SchemaService,
private val createIdentityService: ()-> IdentityService, databaseProperties: Properties): Closeable {
var transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel"))
val hibernateConfig: HibernateConfiguration by lazy {
transaction {
HibernateConfiguration(createSchemaService, databaseProperties, createIdentityService)
HibernateConfiguration(schemaService, databaseProperties, createIdentityService)
}
}
@ -40,8 +40,8 @@ class CordaPersistence(var dataSource: HikariDataSource, private var createSchem
}
companion object {
fun connect(dataSource: HikariDataSource, createSchemaService: () -> SchemaService, createIdentityService: () -> IdentityService, databaseProperties: Properties): CordaPersistence {
return CordaPersistence(dataSource, createSchemaService, createIdentityService, databaseProperties).apply {
fun connect(dataSource: HikariDataSource, schemaService: SchemaService, createIdentityService: () -> IdentityService, databaseProperties: Properties): CordaPersistence {
return CordaPersistence(dataSource, schemaService, createIdentityService, databaseProperties).apply {
DatabaseTransactionManager(this)
}
}
@ -107,10 +107,10 @@ class CordaPersistence(var dataSource: HikariDataSource, private var createSchem
}
}
fun configureDatabase(dataSourceProperties: Properties, databaseProperties: Properties?, createSchemaService: () -> SchemaService = { NodeSchemaService() }, createIdentityService: () -> IdentityService): CordaPersistence {
fun configureDatabase(dataSourceProperties: Properties, databaseProperties: Properties?, schemaService: SchemaService = NodeSchemaService(), createIdentityService: () -> IdentityService): CordaPersistence {
val config = HikariConfig(dataSourceProperties)
val dataSource = HikariDataSource(config)
val persistence = CordaPersistence.connect(dataSource, createSchemaService, createIdentityService, databaseProperties ?: Properties())
val persistence = CordaPersistence.connect(dataSource, schemaService, createIdentityService, databaseProperties ?: Properties())
// Check not in read-only mode.
persistence.transaction {

View File

@ -42,11 +42,7 @@ class DBTransactionStorageTests : TestDependencyInjectionBase() {
fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class)
val dataSourceProps = makeTestDataSourceProperties()
val createSchemaService = { NodeSchemaService() }
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(), createSchemaService, ::makeTestIdentityService)
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(), NodeSchemaService(), ::makeTestIdentityService)
database.transaction {
services = object : MockServices(BOB_KEY) {

View File

@ -77,8 +77,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, BOB_KEY, BOC_KEY)
val dataSourceProps = makeTestDataSourceProperties()
val defaultDatabaseProperties = makeTestDatabaseProperties()
val createSchemaService = { NodeSchemaService() }
database = configureDatabase(dataSourceProps, defaultDatabaseProperties, createSchemaService, ::makeTestIdentityService)
database = configureDatabase(dataSourceProps, defaultDatabaseProperties, NodeSchemaService(), ::makeTestIdentityService)
database.transaction {
hibernateConfig = database.hibernateConfig
services = object : MockServices(BOB_KEY, BOC_KEY, DUMMY_NOTARY_KEY) {

View File

@ -70,8 +70,7 @@ class HibernateObserverTests {
return parent
}
}
val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { schemaService }, createIdentityService = ::makeTestIdentityService)
val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), schemaService, createIdentityService = ::makeTestIdentityService)
@Suppress("UNUSED_VARIABLE")
val observer = HibernateObserver(rawUpdatesPublisher, database.hibernateConfig)
database.transaction {

View File

@ -26,6 +26,7 @@ import net.corda.core.utilities.loggerFor
import net.corda.finance.utils.WorldMapLocation
import net.corda.node.internal.AbstractNode
import net.corda.node.internal.StartedNode
import net.corda.node.services.api.SchemaService
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.identity.PersistentIdentityService
import net.corda.node.services.keys.E2ETestKeyManagementService
@ -248,7 +249,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
@Suppress("unused") val place: WorldMapLocation get() = findMyLocation()!!
private var dbCloser: (() -> Any?)? = null
override fun <T> initialiseDatabasePersistence(insideTransaction: () -> T) = super.initialiseDatabasePersistence {
override fun <T> initialiseDatabasePersistence(schemaService: SchemaService, insideTransaction: () -> T) = super.initialiseDatabasePersistence(schemaService) {
dbCloser = database::close
insideTransaction()
}

View File

@ -100,9 +100,8 @@ open class MockServices(cordappPackages: List<String> = emptyList(), vararg val
cordappPackages: List<String> = emptyList()): Pair<CordaPersistence, MockServices> {
val dataSourceProps = makeTestDataSourceProperties()
val databaseProperties = makeTestDatabaseProperties()
val createSchemaService = { NodeSchemaService(customSchemas) }
val identityServiceRef: IdentityService by lazy { createIdentityService() }
val database = configureDatabase(dataSourceProps, databaseProperties, createSchemaService, { identityServiceRef })
val database = configureDatabase(dataSourceProps, databaseProperties, NodeSchemaService(customSchemas), { identityServiceRef })
val mockService = database.transaction {
object : MockServices(cordappPackages, *(keys.toTypedArray())) {
override val identityService: IdentityService = database.transaction { identityServiceRef }
@ -158,7 +157,7 @@ open class MockServices(cordappPackages: List<String> = emptyList(), vararg val
lateinit var hibernatePersister: HibernateObserver
fun makeVaultService(hibernateConfig: HibernateConfiguration = HibernateConfiguration( { NodeSchemaService() }, makeTestDatabaseProperties(), { identityService })): VaultService {
fun makeVaultService(hibernateConfig: HibernateConfiguration = HibernateConfiguration(NodeSchemaService(), makeTestDatabaseProperties(), { identityService })): VaultService {
val vaultService = NodeVaultService(this, hibernateConfig)
hibernatePersister = HibernateObserver(vaultService.rawUpdates, hibernateConfig)
return vaultService

View File

@ -37,7 +37,7 @@ class SimpleNode(val config: NodeConfiguration, val address: NetworkHostAndPort
val monitoringService = MonitoringService(MetricRegistry())
val identity: KeyPair = generateKeyPair()
val identityService: IdentityService = InMemoryIdentityService(trustRoot = trustRoot)
val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database, { NodeSchemaService() }, { InMemoryIdentityService(trustRoot = trustRoot) })
val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database, NodeSchemaService(), { InMemoryIdentityService(trustRoot = trustRoot) })
val keyService: KeyManagementService = E2ETestKeyManagementService(identityService, setOf(identity))
val executor = ServiceAffinityExecutor(config.myLegalName.organisation, 1)
// TODO: We should have a dummy service hub rather than change behaviour in tests