mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
Merge from Corda/OS
This commit is contained in:
@ -63,6 +63,9 @@ dependencies {
|
||||
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
|
||||
|
||||
// For caches rather than guava
|
||||
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
|
||||
|
||||
// Unit testing helpers.
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:$assertj_version"
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
package net.corda.nodeapi.internal
|
||||
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import com.google.common.cache.CacheLoader
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import java.time.Duration
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
@ -21,11 +21,11 @@ import java.util.concurrent.atomic.AtomicLong
|
||||
*/
|
||||
class DeduplicationChecker(cacheExpiry: Duration) {
|
||||
// dedupe identity -> watermark cache
|
||||
private val watermarkCache = CacheBuilder.newBuilder()
|
||||
private val watermarkCache = Caffeine.newBuilder()
|
||||
.expireAfterAccess(cacheExpiry.toNanos(), TimeUnit.NANOSECONDS)
|
||||
.build(WatermarkCacheLoader)
|
||||
|
||||
private object WatermarkCacheLoader : CacheLoader<Any, AtomicLong>() {
|
||||
private object WatermarkCacheLoader : CacheLoader<Any, AtomicLong> {
|
||||
override fun load(key: Any) = AtomicLong(-1)
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ class DeduplicationChecker(cacheExpiry: Duration) {
|
||||
* @return true if the message is unique, false if it's a duplicate.
|
||||
*/
|
||||
fun checkDuplicateMessageId(identity: Any, sequenceNumber: Long): Boolean {
|
||||
return watermarkCache[identity].getAndUpdate { maxOf(sequenceNumber, it) } >= sequenceNumber
|
||||
return watermarkCache[identity]!!.getAndUpdate { maxOf(sequenceNumber, it) } >= sequenceNumber
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,8 @@ class CordaPersistence(
|
||||
databaseConfig: DatabaseConfig,
|
||||
schemas: Set<MappedSchema>,
|
||||
val jdbcUrl: String,
|
||||
attributeConverters: Collection<AttributeConverter<*, *>> = emptySet()
|
||||
attributeConverters: Collection<AttributeConverter<*, *>> = emptySet(),
|
||||
val cordappClassLoader: ClassLoader? = null
|
||||
) : Closeable {
|
||||
companion object {
|
||||
private val log = contextLogger()
|
||||
@ -74,7 +75,7 @@ class CordaPersistence(
|
||||
val hibernateConfig: HibernateConfiguration by lazy {
|
||||
|
||||
transaction {
|
||||
HibernateConfiguration(schemas, databaseConfig, attributeConverters, jdbcUrl)
|
||||
HibernateConfiguration(schemas, databaseConfig, attributeConverters, jdbcUrl, cordappClassLoader)
|
||||
}
|
||||
}
|
||||
val entityManagerFactory get() = hibernateConfig.sessionFactoryForRegisteredSchemas
|
||||
|
@ -19,6 +19,8 @@ import org.hibernate.boot.Metadata
|
||||
import org.hibernate.boot.MetadataBuilder
|
||||
import org.hibernate.boot.MetadataSources
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder
|
||||
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService
|
||||
import org.hibernate.cfg.Configuration
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider
|
||||
import org.hibernate.service.UnknownUnwrapTypeException
|
||||
@ -36,7 +38,8 @@ class HibernateConfiguration(
|
||||
schemas: Set<MappedSchema>,
|
||||
private val databaseConfig: DatabaseConfig,
|
||||
private val attributeConverters: Collection<AttributeConverter<*, *>>,
|
||||
private val jdbcUrl: String
|
||||
private val jdbcUrl: String,
|
||||
val cordappClassLoader: ClassLoader? = null
|
||||
) {
|
||||
companion object {
|
||||
private val logger = contextLogger()
|
||||
@ -93,7 +96,7 @@ class HibernateConfiguration(
|
||||
schema.mappedTypes.forEach { config.addAnnotatedClass(it) }
|
||||
}
|
||||
|
||||
val sessionFactory = buildSessionFactory(config, metadataSources)
|
||||
val sessionFactory = buildSessionFactory(config, metadataSources, cordappClassLoader)
|
||||
logger.info("Created session factory for schemas: $schemas")
|
||||
|
||||
// export Hibernate JMX statistics
|
||||
@ -119,11 +122,17 @@ class HibernateConfiguration(
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildSessionFactory(config: Configuration, metadataSources: MetadataSources): SessionFactory {
|
||||
private fun buildSessionFactory(config: Configuration, metadataSources: MetadataSources, cordappClassLoader: ClassLoader?): SessionFactory {
|
||||
config.standardServiceRegistryBuilder.applySettings(config.properties)
|
||||
|
||||
if (cordappClassLoader != null) {
|
||||
config.standardServiceRegistryBuilder.addService(
|
||||
ClassLoaderService::class.java,
|
||||
ClassLoaderServiceImpl(cordappClassLoader))
|
||||
}
|
||||
|
||||
val metadataBuilder = metadataSources.getMetadataBuilder(config.standardServiceRegistryBuilder.build())
|
||||
val metadata = buildHibernateMetadata(metadataBuilder, jdbcUrl, attributeConverters)
|
||||
|
||||
return metadata.sessionFactoryBuilder.run {
|
||||
allowOutOfTransactionUpdateOperations(true)
|
||||
applySecondLevelCacheSupport(false)
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization
|
||||
|
||||
import com.google.common.cache.Cache
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import com.github.benmanes.caffeine.cache.Cache
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import net.corda.core.contracts.Attachment
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.internal.copyBytes
|
||||
@ -40,7 +40,7 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
|
||||
override val useCase: SerializationContext.UseCase,
|
||||
override val encoding: SerializationEncoding?,
|
||||
override val encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist) : SerializationContext {
|
||||
private val cache: Cache<List<SecureHash>, AttachmentsClassLoader> = CacheBuilder.newBuilder().weakValues().maximumSize(1024).build()
|
||||
private val cache: Cache<List<SecureHash>, AttachmentsClassLoader> = Caffeine.newBuilder().weakValues().maximumSize(1024).build()
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -59,7 +59,7 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
|
||||
}
|
||||
missing.isNotEmpty() && throw MissingAttachmentsException(missing)
|
||||
AttachmentsClassLoader(attachments, parent = deserializationClassLoader)
|
||||
})
|
||||
}!!)
|
||||
} catch (e: ExecutionException) {
|
||||
// Caught from within the cache get, so unwrap.
|
||||
throw e.cause!!
|
||||
|
@ -28,7 +28,8 @@ private typealias MapCreationFunction = (Map<*, *>) -> Map<*, *>
|
||||
* Serialization / deserialization of certain supported [Map] types.
|
||||
*/
|
||||
class MapSerializer(private val declaredType: ParameterizedType, factory: SerializerFactory) : AMQPSerializer<Any> {
|
||||
override val type: Type = declaredType as? DeserializedParameterizedType ?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType))
|
||||
override val type: Type = (declaredType as? DeserializedParameterizedType) ?:
|
||||
DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType), factory.classloader)
|
||||
override val typeDescriptor: Symbol = Symbol.valueOf(
|
||||
"$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
|
||||
|
||||
|
Reference in New Issue
Block a user