Hibernate session leak fix

* Hibernate session was not closed when JDBC connection was closed

* combined few instances of HibernateSession objects into one field inside CordaPersistence 

* HibernateConfiguration improved caching of schema factories
This commit is contained in:
szymonsztuka 2017-08-22 13:08:36 +01:00 committed by GitHub
parent a4052f9126
commit 09adba8275
19 changed files with 67 additions and 68 deletions

View File

@ -42,7 +42,7 @@ class JDBCHashMapTestSuite {
@BeforeClass @BeforeClass
fun before() { fun before() {
initialiseTestSerialization() initialiseTestSerialization()
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = { throw UnsupportedOperationException("Identity Service should not be in use") }) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = { throw UnsupportedOperationException("Identity Service should not be in use") })
setUpDatabaseTx() setUpDatabaseTx()
loadOnInitFalseMap = JDBCHashMap<String, String>("test_map_false", loadOnInit = false) loadOnInitFalseMap = JDBCHashMap<String, String>("test_map_false", loadOnInit = false)
memoryConstrainedMap = JDBCHashMap<String, String>("test_map_constrained", loadOnInit = false, maxBuckets = 1) memoryConstrainedMap = JDBCHashMap<String, String>("test_map_constrained", loadOnInit = false, maxBuckets = 1)
@ -228,7 +228,7 @@ class JDBCHashMapTestSuite {
@Before @Before
fun before() { fun before() {
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = { throw UnsupportedOperationException("Identity Service should not be in use") }) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = { throw UnsupportedOperationException("Identity Service should not be in use") })
} }
@After @After

View File

@ -480,7 +480,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeVaultObservers() { private fun makeVaultObservers() {
VaultSoftLockManager(services.vaultService, smm) VaultSoftLockManager(services.vaultService, smm)
ScheduledActivityObserver(services) ScheduledActivityObserver(services)
HibernateObserver(services.vaultService.rawUpdates, HibernateConfiguration(services.schemaService, configuration.database ?: Properties(), {services.identityService})) HibernateObserver(services.vaultService.rawUpdates, services.database.hibernateConfig)
} }
private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo { private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo {
@ -538,7 +538,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected open fun initialiseDatabasePersistence(insideTransaction: () -> Unit) { protected open fun initialiseDatabasePersistence(insideTransaction: () -> Unit) {
val props = configuration.dataSourceProperties val props = configuration.dataSourceProperties
if (props.isNotEmpty()) { if (props.isNotEmpty()) {
this.database = configureDatabase(props, configuration.database, identitySvc = { _services.identityService }) this.database = configureDatabase(props, configuration.database, { _services.schemaService }, createIdentityService = { _services.identityService })
// Now log the vendor string as this will also cause a connection to be tested eagerly. // Now log the vendor string as this will also cause a connection to be tested eagerly.
database.transaction { database.transaction {
log.info("Connected to ${database.database.vendor} database.") log.info("Connected to ${database.database.vendor} database.")
@ -750,8 +750,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private inner class ServiceHubInternalImpl : ServiceHubInternal, SingletonSerializeAsToken() { private inner class ServiceHubInternalImpl : ServiceHubInternal, SingletonSerializeAsToken() {
private val hibernateConfig by lazy { HibernateConfiguration(schemaService, configuration.database ?: Properties(), { identityService }) }
override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>() override val rpcFlows = ArrayList<Class<out FlowLogic<*>>>()
override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage() override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage()
override val auditService = DummyAuditService() override val auditService = DummyAuditService()
@ -761,7 +759,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
override val networkMapCache by lazy { InMemoryNetworkMapCache(this) } override val networkMapCache by lazy { InMemoryNetworkMapCache(this) }
override val vaultService by lazy { NodeVaultService(this) } override val vaultService by lazy { NodeVaultService(this) }
override val vaultQueryService by lazy { override val vaultQueryService by lazy {
HibernateVaultQueryImpl(hibernateConfig, vaultService) HibernateVaultQueryImpl(database.hibernateConfig, vaultService)
} }
// Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because // Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because
// the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with // the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with

View File

@ -21,39 +21,37 @@ import java.sql.Connection
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
class HibernateConfiguration(val schemaService: SchemaService, val databaseProperties: Properties, private val identitySvc: () -> IdentityService) { class HibernateConfiguration(createSchemaService: () -> SchemaService, private val databaseProperties: Properties, private val createIdentityScervice: () -> IdentityService) {
companion object { companion object {
val logger = loggerFor<HibernateConfiguration>() val logger = loggerFor<HibernateConfiguration>()
} }
// TODO: make this a guava cache or similar to limit ability for this to grow forever. // TODO: make this a guava cache or similar to limit ability for this to grow forever.
val sessionFactories = ConcurrentHashMap<MappedSchema, SessionFactory>() private val sessionFactories = ConcurrentHashMap<Set<MappedSchema>, SessionFactory>()
private val transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel") ?:"") private val transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel") ?:"")
var schemaService = createSchemaService()
init { init {
schemaService.schemaOptions.map { it.key }.forEach { mappedSchema -> logger.info("Init HibernateConfiguration for schemas: ${schemaService.schemaOptions.keys}")
sessionFactories.computeIfAbsent(mappedSchema, { makeSessionFactoryForSchema(mappedSchema) }) sessionFactoryForRegisteredSchemas()
}
} }
fun sessionFactoryForRegisteredSchemas(): SessionFactory { fun sessionFactoryForRegisteredSchemas(): SessionFactory {
return sessionFactoryForSchemas(*schemaService.schemaOptions.map { it.key }.toTypedArray()) return sessionFactoryForSchemas(*schemaService.schemaOptions.keys.toTypedArray())
} }
fun sessionFactoryForSchema(schema: MappedSchema): SessionFactory { fun sessionFactoryForSchema(schema: MappedSchema): SessionFactory {
return sessionFactories.computeIfAbsent(schema, { sessionFactoryForSchemas(schema) }) return sessionFactoryForSchemas(schema)
} }
//vararg to set conversions left to preserve method signature for now
fun sessionFactoryForSchemas(vararg schemas: MappedSchema): SessionFactory { fun sessionFactoryForSchemas(vararg schemas: MappedSchema): SessionFactory {
return makeSessionFactoryForSchemas(schemas.iterator()) val schemaSet: Set<MappedSchema> = schemas.toSet()
return sessionFactories.computeIfAbsent(schemaSet, { makeSessionFactoryForSchemas(schemaSet) })
} }
private fun makeSessionFactoryForSchema(schema: MappedSchema): SessionFactory { private fun makeSessionFactoryForSchemas(schemas: Set<MappedSchema>): SessionFactory {
return makeSessionFactoryForSchemas(setOf(schema).iterator())
}
private fun makeSessionFactoryForSchemas(schemas: Iterator<MappedSchema>): SessionFactory {
logger.info("Creating session factory for schemas: $schemas") logger.info("Creating session factory for schemas: $schemas")
val serviceRegistry = BootstrapServiceRegistryBuilder().build() val serviceRegistry = BootstrapServiceRegistryBuilder().build()
val metadataSources = MetadataSources(serviceRegistry) val metadataSources = MetadataSources(serviceRegistry)
@ -84,7 +82,7 @@ class HibernateConfiguration(val schemaService: SchemaService, val databasePrope
} }
}) })
// register custom converters // register custom converters
applyAttributeConverter(AbstractPartyToX500NameAsStringConverter(identitySvc)) applyAttributeConverter(AbstractPartyToX500NameAsStringConverter(createIdentityScervice))
build() build()
} }

View File

@ -3,7 +3,7 @@ package net.corda.node.utilities
import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource import com.zaxxer.hikari.HikariDataSource
import net.corda.core.node.services.IdentityService import net.corda.core.node.services.IdentityService
import net.corda.core.schemas.MappedSchema import net.corda.node.services.api.SchemaService
import net.corda.node.services.database.HibernateConfiguration import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.NodeSchemaService
import org.hibernate.SessionFactory import org.hibernate.SessionFactory
@ -20,21 +20,28 @@ import java.util.concurrent.CopyOnWriteArrayList
//HikariDataSource implements Closeable which allows CordaPersistence to be Closeable //HikariDataSource implements Closeable which allows CordaPersistence to be Closeable
class CordaPersistence(var dataSource: HikariDataSource, var nodeSchemaService: NodeSchemaService, val identitySvc: ()-> IdentityService, databaseProperties: Properties): Closeable { class CordaPersistence(var dataSource: HikariDataSource, private var createSchemaService: () -> SchemaService,
private val createIdentityService: ()-> IdentityService, databaseProperties: Properties): Closeable {
/** Holds Exposed database, the field will be removed once Exposed library is removed */ /** Holds Exposed database, the field will be removed once Exposed library is removed */
lateinit var database: Database lateinit var database: Database
var transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel")) var transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel"))
val entityManagerFactory: SessionFactory by lazy(LazyThreadSafetyMode.NONE) { val hibernateConfig: HibernateConfiguration by lazy {
transaction { transaction {
HibernateConfiguration(nodeSchemaService, databaseProperties, identitySvc).sessionFactoryForRegisteredSchemas() HibernateConfiguration(createSchemaService, databaseProperties, createIdentityService)
}
}
val entityManagerFactory: SessionFactory by lazy {
transaction {
hibernateConfig.sessionFactoryForRegisteredSchemas()
} }
} }
companion object { companion object {
fun connect(dataSource: HikariDataSource, nodeSchemaService: NodeSchemaService, identitySvc: () -> IdentityService, databaseProperties: Properties): CordaPersistence { fun connect(dataSource: HikariDataSource, createSchemaService: () -> SchemaService, createIdentityService: () -> IdentityService, databaseProperties: Properties): CordaPersistence {
return CordaPersistence(dataSource, nodeSchemaService, identitySvc, databaseProperties).apply { return CordaPersistence(dataSource, createSchemaService, createIdentityService, databaseProperties).apply {
DatabaseTransactionManager(this) DatabaseTransactionManager(this)
} }
} }
@ -100,10 +107,10 @@ class CordaPersistence(var dataSource: HikariDataSource, var nodeSchemaService:
} }
} }
fun configureDatabase(dataSourceProperties: Properties, databaseProperties: Properties?, entitySchemas: Set<MappedSchema> = emptySet<MappedSchema>(), identitySvc: ()-> IdentityService): CordaPersistence { fun configureDatabase(dataSourceProperties: Properties, databaseProperties: Properties?, createSchemaService: () -> SchemaService = { NodeSchemaService() }, createIdentityService: () -> IdentityService): CordaPersistence {
val config = HikariConfig(dataSourceProperties) val config = HikariConfig(dataSourceProperties)
val dataSource = HikariDataSource(config) val dataSource = HikariDataSource(config)
val persistence = CordaPersistence.connect(dataSource, NodeSchemaService(entitySchemas), identitySvc, databaseProperties ?: Properties()) val persistence = CordaPersistence.connect(dataSource, createSchemaService, createIdentityService, databaseProperties ?: Properties())
//org.jetbrains.exposed.sql.Database will be removed once Exposed library is removed //org.jetbrains.exposed.sql.Database will be removed once Exposed library is removed
val database = Database.connect(dataSource) { _ -> ExposedTransactionManager() } val database = Database.connect(dataSource) { _ -> ExposedTransactionManager() }
@ -197,7 +204,7 @@ fun <T : Any> rx.Observable<T>.wrapWithDatabaseTransaction(db: CordaPersistence?
wrappingSubscriber.cleanUp() wrappingSubscriber.cleanUp()
// If cleanup removed the last subscriber reset the system, as future subscribers might need the stream again // If cleanup removed the last subscriber reset the system, as future subscribers might need the stream again
if (wrappingSubscriber.delegates.isEmpty()) { if (wrappingSubscriber.delegates.isEmpty()) {
wrappingSubscriber = DatabaseTransactionWrappingSubscriber<T>(db) wrappingSubscriber = DatabaseTransactionWrappingSubscriber(db)
} }
} }
} }

View File

@ -32,7 +32,7 @@ class DatabaseTransaction(isolation: Int, val threadLocal: ThreadLocal<DatabaseT
val session: Session by sessionDelegate val session: Session by sessionDelegate
private lateinit var hibernateTransaction : Transaction private lateinit var hibernateTransaction : Transaction
val outerTransaction: DatabaseTransaction? = threadLocal.get() private val outerTransaction: DatabaseTransaction? = threadLocal.get()
fun commit() { fun commit() {
if (sessionDelegate.isInitialized()) { if (sessionDelegate.isInitialized()) {
@ -51,6 +51,9 @@ class DatabaseTransaction(isolation: Int, val threadLocal: ThreadLocal<DatabaseT
} }
fun close() { fun close() {
if (sessionDelegate.isInitialized() && session.isOpen) {
session.close()
}
connection.close() connection.close()
threadLocal.set(outerTransaction) threadLocal.set(outerTransaction)
if (outerTransaction == null) { if (outerTransaction == null) {

View File

@ -69,12 +69,13 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, BOB_KEY, BOC_KEY) issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, BOB_KEY, BOC_KEY)
val dataSourceProps = makeTestDataSourceProperties() val dataSourceProps = makeTestDataSourceProperties()
val defaultDatabaseProperties = makeTestDatabaseProperties() val defaultDatabaseProperties = makeTestDatabaseProperties()
database = configureDatabase(dataSourceProps, defaultDatabaseProperties, identitySvc = ::makeTestIdentityService)
val customSchemas = setOf(VaultSchemaV1, CashSchemaV1, SampleCashSchemaV2, SampleCashSchemaV3) val customSchemas = setOf(VaultSchemaV1, CashSchemaV1, SampleCashSchemaV2, SampleCashSchemaV3)
val createSchemaService = { NodeSchemaService(customSchemas) }
database = configureDatabase(dataSourceProps, defaultDatabaseProperties, createSchemaService, ::makeTestIdentityService)
database.transaction { database.transaction {
hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties(), ::makeTestIdentityService) hibernateConfig = database.hibernateConfig
services = object : MockServices(BOB_KEY, BOC_KEY, DUMMY_NOTARY_KEY) { services = object : MockServices(BOB_KEY, BOC_KEY, DUMMY_NOTARY_KEY) {
override val vaultService: VaultService = makeVaultService(hibernateConfig) override val vaultService: VaultService = makeVaultService(database.hibernateConfig)
override fun recordTransactions(notifyVault: Boolean, txs: Iterable<SignedTransaction>) { override fun recordTransactions(notifyVault: Boolean, txs: Iterable<SignedTransaction>) {
for (stx in txs) { for (stx in txs) {

View File

@ -74,7 +74,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
calls = 0 calls = 0
val dataSourceProps = makeTestDataSourceProperties() val dataSourceProps = makeTestDataSourceProperties()
val databaseProperties = makeTestDatabaseProperties() val databaseProperties = makeTestDatabaseProperties()
database = configureDatabase(dataSourceProps, databaseProperties, identitySvc = ::makeTestIdentityService) database = configureDatabase(dataSourceProps, databaseProperties, createIdentityService = ::makeTestIdentityService)
val identityService = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate) val identityService = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val kms = MockKeyManagementService(identityService, ALICE_KEY) val kms = MockKeyManagementService(identityService, ALICE_KEY)

View File

@ -71,7 +71,7 @@ class ArtemisMessagingTests : TestDependencyInjectionBase() {
baseDirectory = baseDirectory, baseDirectory = baseDirectory,
myLegalName = ALICE.name) myLegalName = ALICE.name)
LogHelper.setLevel(PersistentUniquenessProvider::class) LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
networkMapRegistrationFuture = doneFuture(Unit) networkMapRegistrationFuture = doneFuture(Unit)
} }

View File

@ -33,7 +33,7 @@ class DBCheckpointStorageTests : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class) LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
newCheckpointStorage() newCheckpointStorage()
} }

View File

@ -38,8 +38,6 @@ class DBTransactionStorageTests : TestDependencyInjectionBase() {
lateinit var transactionStorage: DBTransactionStorage lateinit var transactionStorage: DBTransactionStorage
lateinit var services: MockServices lateinit var services: MockServices
val vault: VaultService get() = services.vaultService val vault: VaultService get() = services.vaultService
// Hibernate configuration objects
lateinit var hibernateConfig: HibernateConfiguration
@Before @Before
fun setUp() { fun setUp() {
@ -49,18 +47,16 @@ class DBTransactionStorageTests : TestDependencyInjectionBase() {
val transactionSchema = MappedSchema(schemaFamily = javaClass, version = 1, val transactionSchema = MappedSchema(schemaFamily = javaClass, version = 1,
mappedTypes = listOf(DBTransactionStorage.DBTransaction::class.java)) mappedTypes = listOf(DBTransactionStorage.DBTransaction::class.java))
val customSchemas = setOf(VaultSchemaV1, CashSchemaV1, SampleCashSchemaV2, SampleCashSchemaV3, transactionSchema) val createSchemaService = { NodeSchemaService(setOf(VaultSchemaV1, CashSchemaV1, SampleCashSchemaV2, SampleCashSchemaV3, transactionSchema)) }
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(), customSchemas, identitySvc = ::makeTestIdentityService) database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(), createSchemaService, ::makeTestIdentityService)
database.transaction { database.transaction {
hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService)
services = object : MockServices(BOB_KEY) { services = object : MockServices(BOB_KEY) {
override val vaultService: VaultService get() { override val vaultService: VaultService get() {
val vaultService = NodeVaultService(this) val vaultService = NodeVaultService(this)
hibernatePersister = HibernateObserver(vaultService.rawUpdates, hibernateConfig) hibernatePersister = HibernateObserver(vaultService.rawUpdates, database.hibernateConfig)
return vaultService return vaultService
} }

View File

@ -40,7 +40,7 @@ class NodeAttachmentStorageTest {
LogHelper.setLevel(PersistentUniquenessProvider::class) LogHelper.setLevel(PersistentUniquenessProvider::class)
val dataSourceProperties = makeTestDataSourceProperties() val dataSourceProperties = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProperties, makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) database = configureDatabase(dataSourceProperties, makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
fs = Jimfs.newFileSystem(Configuration.unix()) fs = Jimfs.newFileSystem(Configuration.unix())
} }

View File

@ -9,13 +9,8 @@ import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.QueryableState import net.corda.core.schemas.QueryableState
import net.corda.testing.LogHelper import net.corda.testing.LogHelper
import net.corda.node.services.api.SchemaService import net.corda.node.services.api.SchemaService
import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
import net.corda.testing.DUMMY_CA
import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP
import net.corda.testing.MOCK_IDENTITIES
import net.corda.testing.node.makeTestDataSourceProperties import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.node.makeTestIdentityService import net.corda.testing.node.makeTestIdentityService
@ -31,17 +26,14 @@ import kotlin.test.assertEquals
class HibernateObserverTests { class HibernateObserverTests {
lateinit var database: CordaPersistence
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(HibernateObserver::class) LogHelper.setLevel(HibernateObserver::class)
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService)
} }
@After @After
fun cleanUp() { fun cleanUp() {
database.close()
LogHelper.reset(HibernateObserver::class) LogHelper.reset(HibernateObserver::class)
} }
@ -104,9 +96,10 @@ class HibernateObserverTests {
return parent return parent
} }
} }
val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { schemaService }, createIdentityService = ::makeTestIdentityService)
@Suppress("UNUSED_VARIABLE") @Suppress("UNUSED_VARIABLE")
val observer = HibernateObserver(rawUpdatesPublisher, HibernateConfiguration(schemaService, makeTestDatabaseProperties(), ::makeTestIdentityService)) val observer = HibernateObserver(rawUpdatesPublisher, database.hibernateConfig)
database.transaction { database.transaction {
rawUpdatesPublisher.onNext(Vault.Update(emptySet(), setOf(StateAndRef(TransactionState(TestState(), MEGA_CORP), StateRef(SecureHash.sha256("dummy"), 0))))) rawUpdatesPublisher.onNext(Vault.Update(emptySet(), setOf(StateAndRef(TransactionState(TestState(), MEGA_CORP), StateRef(SecureHash.sha256("dummy"), 0)))))
val parentRowCountResult = TransactionManager.current().connection.prepareStatement("select count(*) from Parents").executeQuery() val parentRowCountResult = TransactionManager.current().connection.prepareStatement("select count(*) from Parents").executeQuery()
@ -120,5 +113,7 @@ class HibernateObserverTests {
assertEquals(1, parentRows, "Expected one parent") assertEquals(1, parentRows, "Expected one parent")
assertEquals(2, childrenRows, "Expected two children") assertEquals(2, childrenRows, "Expected two children")
} }
database.close()
} }
} }

View File

@ -34,7 +34,7 @@ class DistributedImmutableMapTests : TestDependencyInjectionBase() {
fun setup() { fun setup() {
LogHelper.setLevel("-org.apache.activemq") LogHelper.setLevel("-org.apache.activemq")
LogHelper.setLevel(NetworkMapService::class) LogHelper.setLevel(NetworkMapService::class)
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
cluster = setUpCluster() cluster = setUpCluster()
} }

View File

@ -23,7 +23,7 @@ class PersistentUniquenessProviderTests : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class) LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
} }
@After @After

View File

@ -17,6 +17,7 @@ import net.corda.core.node.services.vault.*
import net.corda.core.node.services.vault.QueryCriteria.* import net.corda.core.node.services.vault.QueryCriteria.*
import net.corda.core.utilities.* import net.corda.core.utilities.*
import net.corda.finance.* import net.corda.finance.*
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.CordaPersistence import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
import net.corda.schemas.CashSchemaV1 import net.corda.schemas.CashSchemaV1
@ -64,7 +65,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
// register additional identities // register additional identities
identitySvc.verifyAndRegisterIdentity(CASH_NOTARY_IDENTITY) identitySvc.verifyAndRegisterIdentity(CASH_NOTARY_IDENTITY)
identitySvc.verifyAndRegisterIdentity(BOC_IDENTITY) identitySvc.verifyAndRegisterIdentity(BOC_IDENTITY)
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY), identitySvc = { identitySvc }) val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY), createIdentityService = { identitySvc })
database = databaseAndServices.first database = databaseAndServices.first
services = databaseAndServices.second services = databaseAndServices.second
notaryServices = MockServices(DUMMY_NOTARY_KEY, DUMMY_CASH_ISSUER_KEY, BOC_KEY, MEGA_CORP_KEY) notaryServices = MockServices(DUMMY_NOTARY_KEY, DUMMY_CASH_ISSUER_KEY, BOC_KEY, MEGA_CORP_KEY)
@ -81,7 +82,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
@Ignore @Ignore
@Test @Test
fun createPersistentTestDb() { fun createPersistentTestDb() {
val database = configureDatabase(makePersistentDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = { identitySvc }) val database = configureDatabase(makePersistentDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = { identitySvc })
setUpDb(database, 5000) setUpDb(database, 5000)

View File

@ -21,7 +21,7 @@ class ObservablesTests {
val toBeClosed = mutableListOf<Closeable>() val toBeClosed = mutableListOf<Closeable>()
fun createDatabase(): CordaPersistence { fun createDatabase(): CordaPersistence {
val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
toBeClosed += database toBeClosed += database
return database return database
} }

View File

@ -58,7 +58,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService) database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), createIdentityService = ::makeTestIdentityService)
database.transaction { database.transaction {
oracle = NodeInterestRates.Oracle( oracle = NodeInterestRates.Oracle(
MEGA_CORP, MEGA_CORP,

View File

@ -87,7 +87,7 @@ open class MockServices(vararg val keys: KeyPair) : ServiceHub {
lateinit var hibernatePersister: HibernateObserver 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) val vaultService = NodeVaultService(this)
hibernatePersister = HibernateObserver(vaultService.rawUpdates, hibernateConfig) hibernatePersister = HibernateObserver(vaultService.rawUpdates, hibernateConfig)
return vaultService return vaultService
@ -219,15 +219,14 @@ fun makeTestIdentityService() = InMemoryIdentityService(MOCK_IDENTITIES, trustRo
fun makeTestDatabaseAndMockServices(customSchemas: Set<MappedSchema> = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1, CashSchemaV1), fun makeTestDatabaseAndMockServices(customSchemas: Set<MappedSchema> = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1, CashSchemaV1),
keys: List<KeyPair> = listOf(MEGA_CORP_KEY), keys: List<KeyPair> = listOf(MEGA_CORP_KEY),
identitySvc: ()-> IdentityService = { makeTestIdentityService() }): Pair<CordaPersistence, MockServices> { createIdentityService: () -> IdentityService = { makeTestIdentityService() }): Pair<CordaPersistence, MockServices> {
val dataSourceProps = makeTestDataSourceProperties() val dataSourceProps = makeTestDataSourceProperties()
val databaseProperties = makeTestDatabaseProperties() val databaseProperties = makeTestDatabaseProperties()
val createSchemaService = { NodeSchemaService(customSchemas) }
val database = configureDatabase(dataSourceProps, databaseProperties, identitySvc = identitySvc) val database = configureDatabase(dataSourceProps, databaseProperties, createSchemaService, createIdentityService)
val mockService = database.transaction { val mockService = database.transaction {
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), databaseProperties, identitySvc = identitySvc)
object : MockServices(*(keys.toTypedArray())) { object : MockServices(*(keys.toTypedArray())) {
override val vaultService: VaultService = makeVaultService(hibernateConfig) override val vaultService: VaultService = makeVaultService(database.hibernateConfig)
override fun recordTransactions(notifyVault: Boolean, txs: Iterable<SignedTransaction>) { override fun recordTransactions(notifyVault: Boolean, txs: Iterable<SignedTransaction>) {
for (stx in txs) { for (stx in txs) {
@ -237,7 +236,7 @@ fun makeTestDatabaseAndMockServices(customSchemas: Set<MappedSchema> = setOf(Com
vaultService.notifyAll(txs.map { it.tx }) vaultService.notifyAll(txs.map { it.tx })
} }
override val vaultQueryService: VaultQueryService = HibernateVaultQueryImpl(hibernateConfig, vaultService) override val vaultQueryService: VaultQueryService = HibernateVaultQueryImpl(database.hibernateConfig, vaultService)
override fun jdbcSession(): Connection = database.createSession() override fun jdbcSession(): Connection = database.createSession()
} }

View File

@ -16,6 +16,7 @@ import net.corda.node.services.keys.E2ETestKeyManagementService
import net.corda.node.services.messaging.ArtemisMessagingServer import net.corda.node.services.messaging.ArtemisMessagingServer
import net.corda.node.services.messaging.NodeMessagingClient import net.corda.node.services.messaging.NodeMessagingClient
import net.corda.node.services.network.InMemoryNetworkMapCache import net.corda.node.services.network.InMemoryNetworkMapCache
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.node.utilities.CordaPersistence import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
@ -36,7 +37,7 @@ class SimpleNode(val config: NodeConfiguration, val address: NetworkHostAndPort
val monitoringService = MonitoringService(MetricRegistry()) val monitoringService = MonitoringService(MetricRegistry())
val identity: KeyPair = generateKeyPair() val identity: KeyPair = generateKeyPair()
val identityService: IdentityService = InMemoryIdentityService(trustRoot = trustRoot) val identityService: IdentityService = InMemoryIdentityService(trustRoot = trustRoot)
val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database, identitySvc = {InMemoryIdentityService(trustRoot = trustRoot)}) val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database, { NodeSchemaService() }, { InMemoryIdentityService(trustRoot = trustRoot) })
val keyService: KeyManagementService = E2ETestKeyManagementService(identityService, setOf(identity)) val keyService: KeyManagementService = E2ETestKeyManagementService(identityService, setOf(identity))
val executor = ServiceAffinityExecutor(config.myLegalName.commonName, 1) val executor = ServiceAffinityExecutor(config.myLegalName.commonName, 1)
// TODO: We should have a dummy service hub rather than change behaviour in tests // TODO: We should have a dummy service hub rather than change behaviour in tests