mirror of
https://github.com/corda/corda.git
synced 2025-06-17 06:38:21 +00:00
CORDA-530 Unduplicate code (#1791)
This commit is contained in:
@ -12,7 +12,6 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.persistence.NodeAttachmentService
|
import net.corda.node.services.persistence.NodeAttachmentService
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
|
||||||
import net.corda.nodeapi.internal.ServiceInfo
|
import net.corda.nodeapi.internal.ServiceInfo
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.ALICE_NAME
|
import net.corda.testing.ALICE_NAME
|
||||||
@ -147,7 +146,7 @@ class AttachmentTests {
|
|||||||
|
|
||||||
val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = attachment)
|
val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = attachment)
|
||||||
aliceNode.database.transaction {
|
aliceNode.database.transaction {
|
||||||
DatabaseTransactionManager.current().session.update(corruptAttachment)
|
session.update(corruptAttachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
||||||
|
@ -16,7 +16,7 @@ import net.corda.node.internal.InitiatedFlowFactory
|
|||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.persistence.NodeAttachmentService
|
import net.corda.node.services.persistence.NodeAttachmentService
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
import net.corda.node.utilities.currentDBSession
|
||||||
import net.corda.nodeapi.internal.ServiceInfo
|
import net.corda.nodeapi.internal.ServiceInfo
|
||||||
import net.corda.testing.chooseIdentity
|
import net.corda.testing.chooseIdentity
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
@ -54,7 +54,7 @@ private fun StartedNode<*>.hackAttachment(attachmentId: SecureHash, content: Str
|
|||||||
* @see NodeAttachmentService.importAttachment
|
* @see NodeAttachmentService.importAttachment
|
||||||
*/
|
*/
|
||||||
private fun updateAttachment(attachmentId: SecureHash, data: ByteArray) {
|
private fun updateAttachment(attachmentId: SecureHash, data: ByteArray) {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val attachment = session.get<NodeAttachmentService.DBAttachment>(NodeAttachmentService.DBAttachment::class.java, attachmentId.toString())
|
val attachment = session.get<NodeAttachmentService.DBAttachment>(NodeAttachmentService.DBAttachment::class.java, attachmentId.toString())
|
||||||
attachment?.let {
|
attachment?.let {
|
||||||
attachment.content = data
|
attachment.content = data
|
||||||
|
@ -31,7 +31,6 @@ import net.corda.node.services.messaging.sendRequest
|
|||||||
import net.corda.node.services.network.NetworkMapService.FetchMapResponse
|
import net.corda.node.services.network.NetworkMapService.FetchMapResponse
|
||||||
import net.corda.node.services.network.NetworkMapService.SubscribeResponse
|
import net.corda.node.services.network.NetworkMapService.SubscribeResponse
|
||||||
import net.corda.node.utilities.AddOrRemove
|
import net.corda.node.utilities.AddOrRemove
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
|
||||||
import net.corda.node.utilities.bufferUntilDatabaseCommit
|
import net.corda.node.utilities.bufferUntilDatabaseCommit
|
||||||
import net.corda.node.utilities.wrapWithDatabaseTransaction
|
import net.corda.node.utilities.wrapWithDatabaseTransaction
|
||||||
import org.hibernate.Session
|
import org.hibernate.Session
|
||||||
@ -39,7 +38,6 @@ import rx.Observable
|
|||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.SignatureException
|
import java.security.SignatureException
|
||||||
import java.time.Duration
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.annotation.concurrent.ThreadSafe
|
import javax.annotation.concurrent.ThreadSafe
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
@ -93,7 +91,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
loadFromFiles()
|
loadFromFiles()
|
||||||
serviceHub.database.transaction { loadFromDB() }
|
serviceHub.database.transaction { loadFromDB(session) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFromFiles() {
|
private fun loadFromFiles() {
|
||||||
@ -102,7 +100,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getPartyInfo(party: Party): PartyInfo? {
|
override fun getPartyInfo(party: Party): PartyInfo? {
|
||||||
val nodes = serviceHub.database.transaction { queryByIdentityKey(party.owningKey) }
|
val nodes = serviceHub.database.transaction { queryByIdentityKey(session, party.owningKey) }
|
||||||
if (nodes.size == 1 && nodes[0].isLegalIdentity(party)) {
|
if (nodes.size == 1 && nodes[0].isLegalIdentity(party)) {
|
||||||
return PartyInfo.SingleNode(party, nodes[0].addresses)
|
return PartyInfo.SingleNode(party, nodes[0].addresses)
|
||||||
}
|
}
|
||||||
@ -117,9 +115,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getNodeByLegalName(name: CordaX500Name): NodeInfo? = getNodesByLegalName(name).firstOrNull()
|
override fun getNodeByLegalName(name: CordaX500Name): NodeInfo? = getNodesByLegalName(name).firstOrNull()
|
||||||
override fun getNodesByLegalName(name: CordaX500Name): List<NodeInfo> = serviceHub.database.transaction { queryByLegalName(name) }
|
override fun getNodesByLegalName(name: CordaX500Name): List<NodeInfo> = serviceHub.database.transaction { queryByLegalName(session, name) }
|
||||||
override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> =
|
override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> =
|
||||||
serviceHub.database.transaction { queryByIdentityKey(identityKey) }
|
serviceHub.database.transaction { queryByIdentityKey(session, identityKey) }
|
||||||
|
|
||||||
override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? {
|
override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? {
|
||||||
val wellKnownParty = serviceHub.identityService.wellKnownPartyFromAnonymous(party)
|
val wellKnownParty = serviceHub.identityService.wellKnownPartyFromAnonymous(party)
|
||||||
@ -128,9 +126,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo? = serviceHub.database.transaction { queryByAddress(address) }
|
override fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo? = serviceHub.database.transaction { queryByAddress(session, address) }
|
||||||
|
|
||||||
override fun getPeerCertificateByLegalName(name: CordaX500Name): PartyAndCertificate? = serviceHub.database.transaction { queryIdentityByLegalName(name) }
|
override fun getPeerCertificateByLegalName(name: CordaX500Name): PartyAndCertificate? = serviceHub.database.transaction { queryIdentityByLegalName(session, name) }
|
||||||
|
|
||||||
override fun track(): DataFeed<List<NodeInfo>, MapChange> {
|
override fun track(): DataFeed<List<NodeInfo>, MapChange> {
|
||||||
synchronized(_changed) {
|
synchronized(_changed) {
|
||||||
@ -204,7 +202,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
synchronized(_changed) {
|
synchronized(_changed) {
|
||||||
registeredNodes.remove(node.legalIdentities.first().owningKey)
|
registeredNodes.remove(node.legalIdentities.first().owningKey)
|
||||||
serviceHub.database.transaction {
|
serviceHub.database.transaction {
|
||||||
removeInfoDB(node)
|
removeInfoDB(session, node)
|
||||||
changePublisher.onNext(MapChange.Removed(node))
|
changePublisher.onNext(MapChange.Removed(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,9 +237,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
|
|
||||||
override val allNodes: List<NodeInfo>
|
override val allNodes: List<NodeInfo>
|
||||||
get() = serviceHub.database.transaction {
|
get() = serviceHub.database.transaction {
|
||||||
createSession {
|
getAllInfos(session).map { it.toNodeInfo() }
|
||||||
getAllInfos(it).map { it.toNodeInfo() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processRegistration(reg: NodeRegistration) {
|
private fun processRegistration(reg: NodeRegistration) {
|
||||||
@ -259,10 +255,6 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
// Changes related to NetworkMap redesign
|
// Changes related to NetworkMap redesign
|
||||||
// TODO It will be properly merged into network map cache after services removal.
|
// TODO It will be properly merged into network map cache after services removal.
|
||||||
|
|
||||||
private inline fun <T> createSession(block: (Session) -> T): T {
|
|
||||||
return DatabaseTransactionManager.current().session.let { block(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAllInfos(session: Session): List<NodeInfoSchemaV1.PersistentNodeInfo> {
|
private fun getAllInfos(session: Session): List<NodeInfoSchemaV1.PersistentNodeInfo> {
|
||||||
val criteria = session.criteriaBuilder.createQuery(NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
val criteria = session.criteriaBuilder.createQuery(NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
||||||
criteria.select(criteria.from(NodeInfoSchemaV1.PersistentNodeInfo::class.java))
|
criteria.select(criteria.from(NodeInfoSchemaV1.PersistentNodeInfo::class.java))
|
||||||
@ -272,10 +264,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
/**
|
/**
|
||||||
* Load NetworkMap data from the database if present. Node can start without having NetworkMapService configured.
|
* Load NetworkMap data from the database if present. Node can start without having NetworkMapService configured.
|
||||||
*/
|
*/
|
||||||
private fun loadFromDB() {
|
private fun loadFromDB(session: Session) {
|
||||||
logger.info("Loading network map from database...")
|
logger.info("Loading network map from database...")
|
||||||
createSession {
|
val result = getAllInfos(session)
|
||||||
val result = getAllInfos(it)
|
|
||||||
for (nodeInfo in result) {
|
for (nodeInfo in result) {
|
||||||
try {
|
try {
|
||||||
logger.info("Loaded node info: $nodeInfo")
|
logger.info("Loaded node info: $nodeInfo")
|
||||||
@ -290,7 +281,6 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
_registrationFuture.set(null) // Useful only if we don't have NetworkMapService configured so StateMachineManager can start.
|
_registrationFuture.set(null) // Useful only if we don't have NetworkMapService configured so StateMachineManager can start.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateInfoDB(nodeInfo: NodeInfo) {
|
private fun updateInfoDB(nodeInfo: NodeInfo) {
|
||||||
// TODO Temporary workaround to force isolated transaction (otherwise it causes race conditions when processing
|
// TODO Temporary workaround to force isolated transaction (otherwise it causes race conditions when processing
|
||||||
@ -313,11 +303,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeInfoDB(nodeInfo: NodeInfo) {
|
private fun removeInfoDB(session: Session, nodeInfo: NodeInfo) {
|
||||||
createSession {
|
val info = findByIdentityKey(session, nodeInfo.legalIdentitiesAndCerts.first().owningKey).single()
|
||||||
val info = findByIdentityKey(it, nodeInfo.legalIdentitiesAndCerts.first().owningKey).single()
|
session.remove(info)
|
||||||
it.remove(info)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findByIdentityKey(session: Session, identityKey: PublicKey): List<NodeInfoSchemaV1.PersistentNodeInfo> {
|
private fun findByIdentityKey(session: Session, identityKey: PublicKey): List<NodeInfoSchemaV1.PersistentNodeInfo> {
|
||||||
@ -328,16 +316,13 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
return query.resultList
|
return query.resultList
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queryByIdentityKey(identityKey: PublicKey): List<NodeInfo> {
|
private fun queryByIdentityKey(session: Session, identityKey: PublicKey): List<NodeInfo> {
|
||||||
createSession {
|
val result = findByIdentityKey(session, identityKey)
|
||||||
val result = findByIdentityKey(it, identityKey)
|
|
||||||
return result.map { it.toNodeInfo() }
|
return result.map { it.toNodeInfo() }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun queryIdentityByLegalName(name: CordaX500Name): PartyAndCertificate? {
|
private fun queryIdentityByLegalName(session: Session, name: CordaX500Name): PartyAndCertificate? {
|
||||||
createSession {
|
val query = session.createQuery(
|
||||||
val query = it.createQuery(
|
|
||||||
// We do the JOIN here to restrict results to those present in the network map
|
// We do the JOIN here to restrict results to those present in the network map
|
||||||
"SELECT DISTINCT l FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.name = :name",
|
"SELECT DISTINCT l FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.name = :name",
|
||||||
NodeInfoSchemaV1.DBPartyAndCertificate::class.java)
|
NodeInfoSchemaV1.DBPartyAndCertificate::class.java)
|
||||||
@ -346,22 +331,18 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
// The map is restricted to holding a single identity for any X.500 name, so firstOrNull() is correct here.
|
// The map is restricted to holding a single identity for any X.500 name, so firstOrNull() is correct here.
|
||||||
return candidates.firstOrNull()
|
return candidates.firstOrNull()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun queryByLegalName(name: CordaX500Name): List<NodeInfo> {
|
private fun queryByLegalName(session: Session, name: CordaX500Name): List<NodeInfo> {
|
||||||
createSession {
|
val query = session.createQuery(
|
||||||
val query = it.createQuery(
|
|
||||||
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.name = :name",
|
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.name = :name",
|
||||||
NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
||||||
query.setParameter("name", name.toString())
|
query.setParameter("name", name.toString())
|
||||||
val result = query.resultList
|
val result = query.resultList
|
||||||
return result.map { it.toNodeInfo() }
|
return result.map { it.toNodeInfo() }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun queryByAddress(hostAndPort: NetworkHostAndPort): NodeInfo? {
|
private fun queryByAddress(session: Session, hostAndPort: NetworkHostAndPort): NodeInfo? {
|
||||||
createSession {
|
val query = session.createQuery(
|
||||||
val query = it.createQuery(
|
|
||||||
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.addresses a WHERE a.pk.host = :host AND a.pk.port = :port",
|
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.addresses a WHERE a.pk.host = :host AND a.pk.port = :port",
|
||||||
NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
NodeInfoSchemaV1.PersistentNodeInfo::class.java)
|
||||||
query.setParameter("host", hostAndPort.host)
|
query.setParameter("host", hostAndPort.host)
|
||||||
@ -370,7 +351,6 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
return if (result.isEmpty()) null
|
return if (result.isEmpty()) null
|
||||||
else result.map { it.toNodeInfo() }.singleOrNull() ?: throw IllegalStateException("More than one node with the same host and port")
|
else result.map { it.toNodeInfo() }.singleOrNull() ?: throw IllegalStateException("More than one node with the same host and port")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Object Relational Mapping support. */
|
/** Object Relational Mapping support. */
|
||||||
private fun generateMappedObject(nodeInfo: NodeInfo): NodeInfoSchemaV1.PersistentNodeInfo {
|
private fun generateMappedObject(nodeInfo: NodeInfo): NodeInfoSchemaV1.PersistentNodeInfo {
|
||||||
@ -388,10 +368,8 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
|
|
||||||
override fun clearNetworkMapCache() {
|
override fun clearNetworkMapCache() {
|
||||||
serviceHub.database.transaction {
|
serviceHub.database.transaction {
|
||||||
createSession {
|
val result = getAllInfos(session)
|
||||||
val result = getAllInfos(it)
|
for (nodeInfo in result) session.remove(nodeInfo)
|
||||||
for (nodeInfo in result) it.remove(nodeInfo)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package net.corda.node.services.persistence
|
|||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import net.corda.node.services.api.Checkpoint
|
import net.corda.node.services.api.Checkpoint
|
||||||
import net.corda.node.services.api.CheckpointStorage
|
import net.corda.node.services.api.CheckpointStorage
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
|
||||||
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||||
|
import net.corda.node.utilities.currentDBSession
|
||||||
import javax.persistence.Column
|
import javax.persistence.Column
|
||||||
import javax.persistence.Entity
|
import javax.persistence.Entity
|
||||||
import javax.persistence.Id
|
import javax.persistence.Id
|
||||||
@ -28,15 +28,14 @@ class DBCheckpointStorage : CheckpointStorage {
|
|||||||
)
|
)
|
||||||
|
|
||||||
override fun addCheckpoint(checkpoint: Checkpoint) {
|
override fun addCheckpoint(checkpoint: Checkpoint) {
|
||||||
val session = DatabaseTransactionManager.current().session
|
currentDBSession().save(DBCheckpoint().apply {
|
||||||
session.save(DBCheckpoint().apply {
|
|
||||||
checkpointId = checkpoint.id.toString()
|
checkpointId = checkpoint.id.toString()
|
||||||
this.checkpoint = checkpoint.serializedFiber.bytes
|
this.checkpoint = checkpoint.serializedFiber.bytes
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeCheckpoint(checkpoint: Checkpoint) {
|
override fun removeCheckpoint(checkpoint: Checkpoint) {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
val delete = criteriaBuilder.createCriteriaDelete(DBCheckpoint::class.java)
|
val delete = criteriaBuilder.createCriteriaDelete(DBCheckpoint::class.java)
|
||||||
val root = delete.from(DBCheckpoint::class.java)
|
val root = delete.from(DBCheckpoint::class.java)
|
||||||
@ -45,7 +44,7 @@ class DBCheckpointStorage : CheckpointStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun forEach(block: (Checkpoint) -> Boolean) {
|
override fun forEach(block: (Checkpoint) -> Boolean) {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaQuery = session.criteriaBuilder.createQuery(DBCheckpoint::class.java)
|
val criteriaQuery = session.criteriaBuilder.createQuery(DBCheckpoint::class.java)
|
||||||
val root = criteriaQuery.from(DBCheckpoint::class.java)
|
val root = criteriaQuery.from(DBCheckpoint::class.java)
|
||||||
criteriaQuery.select(root)
|
criteriaQuery.select(root)
|
||||||
|
@ -13,8 +13,8 @@ import net.corda.core.crypto.SecureHash
|
|||||||
import net.corda.core.node.services.AttachmentStorage
|
import net.corda.core.node.services.AttachmentStorage
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.*
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
|
||||||
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||||
|
import net.corda.node.utilities.currentDBSession
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.jar.JarInputStream
|
import java.util.jar.JarInputStream
|
||||||
@ -50,7 +50,7 @@ class NodeAttachmentService(metrics: MetricRegistry) : AttachmentStorage, Single
|
|||||||
private val attachmentCount = metrics.counter("Attachments")
|
private val attachmentCount = metrics.counter("Attachments")
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
val criteriaQuery = criteriaBuilder.createQuery(Long::class.java)
|
val criteriaQuery = criteriaBuilder.createQuery(Long::class.java)
|
||||||
criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(NodeAttachmentService.DBAttachment::class.java)))
|
criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(NodeAttachmentService.DBAttachment::class.java)))
|
||||||
@ -140,7 +140,7 @@ class NodeAttachmentService(metrics: MetricRegistry) : AttachmentStorage, Single
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun openAttachment(id: SecureHash): Attachment? {
|
override fun openAttachment(id: SecureHash): Attachment? {
|
||||||
val attachment = DatabaseTransactionManager.current().session.get(NodeAttachmentService.DBAttachment::class.java, id.toString())
|
val attachment = currentDBSession().get(NodeAttachmentService.DBAttachment::class.java, id.toString())
|
||||||
attachment?.let {
|
attachment?.let {
|
||||||
return AttachmentImpl(id, { attachment.content }, checkAttachmentsOnLoad)
|
return AttachmentImpl(id, { attachment.content }, checkAttachmentsOnLoad)
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ class NodeAttachmentService(metrics: MetricRegistry) : AttachmentStorage, Single
|
|||||||
checkIsAValidJAR(ByteArrayInputStream(bytes))
|
checkIsAValidJAR(ByteArrayInputStream(bytes))
|
||||||
val id = SecureHash.SHA256(hs.hash().asBytes())
|
val id = SecureHash.SHA256(hs.hash().asBytes())
|
||||||
|
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
val criteriaQuery = criteriaBuilder.createQuery(Long::class.java)
|
val criteriaQuery = criteriaBuilder.createQuery(Long::class.java)
|
||||||
val attachments = criteriaQuery.from(NodeAttachmentService.DBAttachment::class.java)
|
val attachments = criteriaQuery.from(NodeAttachmentService.DBAttachment::class.java)
|
||||||
|
@ -29,6 +29,7 @@ import net.corda.node.services.persistence.HibernateConfiguration
|
|||||||
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
import net.corda.node.utilities.DatabaseTransactionManager
|
||||||
import net.corda.node.utilities.bufferUntilDatabaseCommit
|
import net.corda.node.utilities.bufferUntilDatabaseCommit
|
||||||
|
import net.corda.node.utilities.currentDBSession
|
||||||
import net.corda.node.utilities.wrapWithDatabaseTransaction
|
import net.corda.node.utilities.wrapWithDatabaseTransaction
|
||||||
import org.hibernate.Session
|
import org.hibernate.Session
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@ -38,6 +39,15 @@ import java.time.Clock
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.persistence.Tuple
|
import javax.persistence.Tuple
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder
|
||||||
|
import javax.persistence.criteria.CriteriaUpdate
|
||||||
|
import javax.persistence.criteria.Predicate
|
||||||
|
import javax.persistence.criteria.Root
|
||||||
|
|
||||||
|
private fun CriteriaBuilder.executeUpdate(session: Session, configure: Root<*>.(CriteriaUpdate<*>) -> Any?) = createCriteriaUpdate(VaultSchemaV1.VaultStates::class.java).let { update ->
|
||||||
|
update.from(VaultSchemaV1.VaultStates::class.java).run { configure(update) }
|
||||||
|
session.createQuery(update).executeUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently, the node vault service is a very simple RDBMS backed implementation. It will change significantly when
|
* Currently, the node vault service is a very simple RDBMS backed implementation. It will change significantly when
|
||||||
@ -73,7 +83,7 @@ class NodeVaultService(private val clock: Clock, private val keyManagementServic
|
|||||||
val consumedStateRefs = update.consumed.map { it.ref }
|
val consumedStateRefs = update.consumed.map { it.ref }
|
||||||
log.trace { "Removing $consumedStateRefs consumed contract states and adding $producedStateRefs produced contract states to the database." }
|
log.trace { "Removing $consumedStateRefs consumed contract states and adding $producedStateRefs produced contract states to the database." }
|
||||||
|
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
producedStateRefsMap.forEach { stateAndRef ->
|
producedStateRefsMap.forEach { stateAndRef ->
|
||||||
val state = VaultSchemaV1.VaultStates(
|
val state = VaultSchemaV1.VaultStates(
|
||||||
notary = stateAndRef.value.state.notary,
|
notary = stateAndRef.value.state.notary,
|
||||||
@ -189,7 +199,7 @@ class NodeVaultService(private val clock: Clock, private val keyManagementServic
|
|||||||
private fun loadStates(refs: Collection<StateRef>): HashSet<StateAndRef<ContractState>> {
|
private fun loadStates(refs: Collection<StateRef>): HashSet<StateAndRef<ContractState>> {
|
||||||
val states = HashSet<StateAndRef<ContractState>>()
|
val states = HashSet<StateAndRef<ContractState>>()
|
||||||
if (refs.isNotEmpty()) {
|
if (refs.isNotEmpty()) {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
val criteriaQuery = criteriaBuilder.createQuery(VaultSchemaV1.VaultStates::class.java)
|
val criteriaQuery = criteriaBuilder.createQuery(VaultSchemaV1.VaultStates::class.java)
|
||||||
val vaultStates = criteriaQuery.from(VaultSchemaV1.VaultStates::class.java)
|
val vaultStates = criteriaQuery.from(VaultSchemaV1.VaultStates::class.java)
|
||||||
@ -223,11 +233,11 @@ class NodeVaultService(private val clock: Clock, private val keyManagementServic
|
|||||||
|
|
||||||
override fun addNoteToTransaction(txnId: SecureHash, noteText: String) {
|
override fun addNoteToTransaction(txnId: SecureHash, noteText: String) {
|
||||||
val txnNoteEntity = VaultSchemaV1.VaultTxnNote(txnId.toString(), noteText)
|
val txnNoteEntity = VaultSchemaV1.VaultTxnNote(txnId.toString(), noteText)
|
||||||
DatabaseTransactionManager.current().session.save(txnNoteEntity)
|
currentDBSession().save(txnNoteEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTransactionNotes(txnId: SecureHash): Iterable<String> {
|
override fun getTransactionNotes(txnId: SecureHash): Iterable<String> {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
val criteriaQuery = criteriaBuilder.createQuery(VaultSchemaV1.VaultTxnNote::class.java)
|
val criteriaQuery = criteriaBuilder.createQuery(VaultSchemaV1.VaultTxnNote::class.java)
|
||||||
val vaultStates = criteriaQuery.from(VaultSchemaV1.VaultTxnNote::class.java)
|
val vaultStates = criteriaQuery.from(VaultSchemaV1.VaultTxnNote::class.java)
|
||||||
@ -241,35 +251,34 @@ class NodeVaultService(private val clock: Clock, private val keyManagementServic
|
|||||||
override fun softLockReserve(lockId: UUID, stateRefs: NonEmptySet<StateRef>) {
|
override fun softLockReserve(lockId: UUID, stateRefs: NonEmptySet<StateRef>) {
|
||||||
val softLockTimestamp = clock.instant()
|
val softLockTimestamp = clock.instant()
|
||||||
try {
|
try {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
val criteriaUpdate = criteriaBuilder.createCriteriaUpdate(VaultSchemaV1.VaultStates::class.java)
|
fun execute(configure: Root<*>.(CriteriaUpdate<*>, Array<Predicate>) -> Any?) = criteriaBuilder.executeUpdate(session) { update ->
|
||||||
val vaultStates = criteriaUpdate.from(VaultSchemaV1.VaultStates::class.java)
|
|
||||||
val stateStatusPredication = criteriaBuilder.equal(vaultStates.get<Vault.StateStatus>(VaultSchemaV1.VaultStates::stateStatus.name), Vault.StateStatus.UNCONSUMED)
|
|
||||||
val lockIdPredicate = criteriaBuilder.or(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name).isNull,
|
|
||||||
criteriaBuilder.equal(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString()))
|
|
||||||
val persistentStateRefs = stateRefs.map { PersistentStateRef(it.txhash.bytes.toHexString(), it.index) }
|
val persistentStateRefs = stateRefs.map { PersistentStateRef(it.txhash.bytes.toHexString(), it.index) }
|
||||||
val compositeKey = vaultStates.get<PersistentStateRef>(VaultSchemaV1.VaultStates::stateRef.name)
|
val compositeKey = get<PersistentStateRef>(VaultSchemaV1.VaultStates::stateRef.name)
|
||||||
val stateRefsPredicate = criteriaBuilder.and(compositeKey.`in`(persistentStateRefs))
|
val stateRefsPredicate = criteriaBuilder.and(compositeKey.`in`(persistentStateRefs))
|
||||||
criteriaUpdate.set(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
configure(update, arrayOf(stateRefsPredicate))
|
||||||
criteriaUpdate.set(vaultStates.get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
}
|
||||||
criteriaUpdate.where(stateStatusPredication, lockIdPredicate, stateRefsPredicate)
|
|
||||||
val updatedRows = session.createQuery(criteriaUpdate).executeUpdate()
|
val updatedRows = execute { update, commonPredicates ->
|
||||||
|
val stateStatusPredication = criteriaBuilder.equal(get<Vault.StateStatus>(VaultSchemaV1.VaultStates::stateStatus.name), Vault.StateStatus.UNCONSUMED)
|
||||||
|
val lockIdPredicate = criteriaBuilder.or(get<String>(VaultSchemaV1.VaultStates::lockId.name).isNull,
|
||||||
|
criteriaBuilder.equal(get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString()))
|
||||||
|
update.set(get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
||||||
|
update.set(get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
||||||
|
update.where(stateStatusPredication, lockIdPredicate, *commonPredicates)
|
||||||
|
}
|
||||||
if (updatedRows > 0 && updatedRows == stateRefs.size) {
|
if (updatedRows > 0 && updatedRows == stateRefs.size) {
|
||||||
log.trace("Reserving soft lock states for $lockId: $stateRefs")
|
log.trace("Reserving soft lock states for $lockId: $stateRefs")
|
||||||
FlowStateMachineImpl.currentStateMachine()?.hasSoftLockedStates = true
|
FlowStateMachineImpl.currentStateMachine()?.hasSoftLockedStates = true
|
||||||
} else {
|
} else {
|
||||||
// revert partial soft locks
|
// revert partial soft locks
|
||||||
val criteriaRevertUpdate = criteriaBuilder.createCriteriaUpdate(VaultSchemaV1.VaultStates::class.java)
|
val revertUpdatedRows = execute { update, commonPredicates ->
|
||||||
val vaultStatesRevert = criteriaRevertUpdate.from(VaultSchemaV1.VaultStates::class.java)
|
val lockIdPredicate = criteriaBuilder.equal(get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
||||||
val lockIdPredicateRevert = criteriaBuilder.equal(vaultStatesRevert.get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
val lockUpdateTime = criteriaBuilder.equal(get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
||||||
val lockUpdateTime = criteriaBuilder.equal(vaultStatesRevert.get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
update.set(get<String>(VaultSchemaV1.VaultStates::lockId.name), criteriaBuilder.nullLiteral(String::class.java))
|
||||||
val persistentStateRefsRevert = stateRefs.map { PersistentStateRef(it.txhash.bytes.toHexString(), it.index) }
|
update.where(lockUpdateTime, lockIdPredicate, *commonPredicates)
|
||||||
val compositeKeyRevert = vaultStatesRevert.get<PersistentStateRef>(VaultSchemaV1.VaultStates::stateRef.name)
|
}
|
||||||
val stateRefsPredicateRevert = criteriaBuilder.and(compositeKeyRevert.`in`(persistentStateRefsRevert))
|
|
||||||
criteriaRevertUpdate.set(vaultStatesRevert.get<String>(VaultSchemaV1.VaultStates::lockId.name), criteriaBuilder.nullLiteral(String::class.java))
|
|
||||||
criteriaRevertUpdate.where(lockUpdateTime, lockIdPredicateRevert, stateRefsPredicateRevert)
|
|
||||||
val revertUpdatedRows = session.createQuery(criteriaRevertUpdate).executeUpdate()
|
|
||||||
if (revertUpdatedRows > 0) {
|
if (revertUpdatedRows > 0) {
|
||||||
log.trace("Reverting $revertUpdatedRows partially soft locked states for $lockId")
|
log.trace("Reverting $revertUpdatedRows partially soft locked states for $lockId")
|
||||||
}
|
}
|
||||||
@ -286,33 +295,30 @@ class NodeVaultService(private val clock: Clock, private val keyManagementServic
|
|||||||
|
|
||||||
override fun softLockRelease(lockId: UUID, stateRefs: NonEmptySet<StateRef>?) {
|
override fun softLockRelease(lockId: UUID, stateRefs: NonEmptySet<StateRef>?) {
|
||||||
val softLockTimestamp = clock.instant()
|
val softLockTimestamp = clock.instant()
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaBuilder = session.criteriaBuilder
|
val criteriaBuilder = session.criteriaBuilder
|
||||||
|
fun execute(configure: Root<*>.(CriteriaUpdate<*>, Array<Predicate>) -> Any?) = criteriaBuilder.executeUpdate(session) { update ->
|
||||||
|
val stateStatusPredication = criteriaBuilder.equal(get<Vault.StateStatus>(VaultSchemaV1.VaultStates::stateStatus.name), Vault.StateStatus.UNCONSUMED)
|
||||||
|
val lockIdPredicate = criteriaBuilder.equal(get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
||||||
|
update.set<String>(get<String>(VaultSchemaV1.VaultStates::lockId.name), criteriaBuilder.nullLiteral(String::class.java))
|
||||||
|
update.set(get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
||||||
|
configure(update, arrayOf(stateStatusPredication, lockIdPredicate))
|
||||||
|
}
|
||||||
if (stateRefs == null) {
|
if (stateRefs == null) {
|
||||||
val criteriaUpdate = criteriaBuilder.createCriteriaUpdate(VaultSchemaV1.VaultStates::class.java)
|
val update = execute { update, commonPredicates ->
|
||||||
val vaultStates = criteriaUpdate.from(VaultSchemaV1.VaultStates::class.java)
|
update.where(*commonPredicates)
|
||||||
val stateStatusPredication = criteriaBuilder.equal(vaultStates.get<Vault.StateStatus>(VaultSchemaV1.VaultStates::stateStatus.name), Vault.StateStatus.UNCONSUMED)
|
}
|
||||||
val lockIdPredicate = criteriaBuilder.equal(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
|
||||||
criteriaUpdate.set<String>(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name), criteriaBuilder.nullLiteral(String::class.java))
|
|
||||||
criteriaUpdate.set(vaultStates.get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
|
||||||
criteriaUpdate.where(stateStatusPredication, lockIdPredicate)
|
|
||||||
val update = session.createQuery(criteriaUpdate).executeUpdate()
|
|
||||||
if (update > 0) {
|
if (update > 0) {
|
||||||
log.trace("Releasing $update soft locked states for $lockId")
|
log.trace("Releasing $update soft locked states for $lockId")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
val criteriaUpdate = criteriaBuilder.createCriteriaUpdate(VaultSchemaV1.VaultStates::class.java)
|
val updatedRows = execute { update, commonPredicates ->
|
||||||
val vaultStates = criteriaUpdate.from(VaultSchemaV1.VaultStates::class.java)
|
|
||||||
val stateStatusPredication = criteriaBuilder.equal(vaultStates.get<Vault.StateStatus>(VaultSchemaV1.VaultStates::stateStatus.name), Vault.StateStatus.UNCONSUMED)
|
|
||||||
val lockIdPredicate = criteriaBuilder.equal(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name), lockId.toString())
|
|
||||||
val persistentStateRefs = stateRefs.map { PersistentStateRef(it.txhash.bytes.toHexString(), it.index) }
|
val persistentStateRefs = stateRefs.map { PersistentStateRef(it.txhash.bytes.toHexString(), it.index) }
|
||||||
val compositeKey = vaultStates.get<PersistentStateRef>(VaultSchemaV1.VaultStates::stateRef.name)
|
val compositeKey = get<PersistentStateRef>(VaultSchemaV1.VaultStates::stateRef.name)
|
||||||
val stateRefsPredicate = criteriaBuilder.and(compositeKey.`in`(persistentStateRefs))
|
val stateRefsPredicate = criteriaBuilder.and(compositeKey.`in`(persistentStateRefs))
|
||||||
criteriaUpdate.set<String>(vaultStates.get<String>(VaultSchemaV1.VaultStates::lockId.name), criteriaBuilder.nullLiteral(String::class.java))
|
update.where(*commonPredicates, stateRefsPredicate)
|
||||||
criteriaUpdate.set(vaultStates.get<Instant>(VaultSchemaV1.VaultStates::lockUpdateTime.name), softLockTimestamp)
|
}
|
||||||
criteriaUpdate.where(stateStatusPredication, lockIdPredicate, stateRefsPredicate)
|
|
||||||
val updatedRows = session.createQuery(criteriaUpdate).executeUpdate()
|
|
||||||
if (updatedRows > 0) {
|
if (updatedRows > 0) {
|
||||||
log.trace("Releasing $updatedRows soft locked states for $lockId and stateRefs $stateRefs")
|
log.trace("Releasing $updatedRows soft locked states for $lockId and stateRefs $stateRefs")
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,11 @@ class AppendOnlyPersistentMap<K, V, E, out EK>(
|
|||||||
* Returns all key/value pairs from the underlying storage.
|
* Returns all key/value pairs from the underlying storage.
|
||||||
*/
|
*/
|
||||||
fun allPersisted(): Sequence<Pair<K, V>> {
|
fun allPersisted(): Sequence<Pair<K, V>> {
|
||||||
val criteriaQuery = DatabaseTransactionManager.current().session.criteriaBuilder.createQuery(persistentEntityClass)
|
val session = currentDBSession()
|
||||||
|
val criteriaQuery = session.criteriaBuilder.createQuery(persistentEntityClass)
|
||||||
val root = criteriaQuery.from(persistentEntityClass)
|
val root = criteriaQuery.from(persistentEntityClass)
|
||||||
criteriaQuery.select(root)
|
criteriaQuery.select(root)
|
||||||
val query = DatabaseTransactionManager.current().session.createQuery(criteriaQuery)
|
val query = session.createQuery(criteriaQuery)
|
||||||
val result = query.resultList
|
val result = query.resultList
|
||||||
return result.map { x -> fromPersistentEntity(x) }.asSequence()
|
return result.map { x -> fromPersistentEntity(x) }.asSequence()
|
||||||
}
|
}
|
||||||
@ -87,7 +88,7 @@ class AppendOnlyPersistentMap<K, V, E, out EK>(
|
|||||||
*/
|
*/
|
||||||
operator fun set(key: K, value: V) =
|
operator fun set(key: K, value: V) =
|
||||||
set(key, value, logWarning = false) { k, v ->
|
set(key, value, logWarning = false) { k, v ->
|
||||||
DatabaseTransactionManager.current().session.save(toPersistentEntity(k, v))
|
currentDBSession().save(toPersistentEntity(k, v))
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,9 +99,10 @@ class AppendOnlyPersistentMap<K, V, E, out EK>(
|
|||||||
*/
|
*/
|
||||||
fun addWithDuplicatesAllowed(key: K, value: V, logWarning: Boolean = true): Boolean =
|
fun addWithDuplicatesAllowed(key: K, value: V, logWarning: Boolean = true): Boolean =
|
||||||
set(key, value, logWarning) { k, v ->
|
set(key, value, logWarning) { k, v ->
|
||||||
val existingEntry = DatabaseTransactionManager.current().session.find(persistentEntityClass, toPersistentEntityKey(k))
|
val session = currentDBSession()
|
||||||
|
val existingEntry = session.find(persistentEntityClass, toPersistentEntityKey(k))
|
||||||
if (existingEntry == null) {
|
if (existingEntry == null) {
|
||||||
DatabaseTransactionManager.current().session.save(toPersistentEntity(k, v))
|
session.save(toPersistentEntity(k, v))
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
fromPersistentEntity(existingEntry).second
|
fromPersistentEntity(existingEntry).second
|
||||||
@ -114,7 +116,7 @@ class AppendOnlyPersistentMap<K, V, E, out EK>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadValue(key: K): V? {
|
private fun loadValue(key: K): V? {
|
||||||
val result = DatabaseTransactionManager.current().session.find(persistentEntityClass, toPersistentEntityKey(key))
|
val result = currentDBSession().find(persistentEntityClass, toPersistentEntityKey(key))
|
||||||
return result?.let(fromPersistentEntity)?.second
|
return result?.let(fromPersistentEntity)?.second
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +127,7 @@ class AppendOnlyPersistentMap<K, V, E, out EK>(
|
|||||||
* WARNING!! The method is not thread safe.
|
* WARNING!! The method is not thread safe.
|
||||||
*/
|
*/
|
||||||
fun clear() {
|
fun clear() {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val deleteQuery = session.criteriaBuilder.createCriteriaDelete(persistentEntityClass)
|
val deleteQuery = session.criteriaBuilder.createCriteriaDelete(persistentEntityClass)
|
||||||
deleteQuery.from(persistentEntityClass)
|
deleteQuery.from(persistentEntityClass)
|
||||||
session.createQuery(deleteQuery).executeUpdate()
|
session.createQuery(deleteQuery).executeUpdate()
|
||||||
|
@ -62,6 +62,7 @@ class DatabaseTransaction(isolation: Int, val threadLocal: ThreadLocal<DatabaseT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun currentDBSession() = DatabaseTransactionManager.current().session
|
||||||
class DatabaseTransactionManager(initDataSource: CordaPersistence) {
|
class DatabaseTransactionManager(initDataSource: CordaPersistence) {
|
||||||
companion object {
|
companion object {
|
||||||
private val threadLocalDb = ThreadLocal<CordaPersistence>()
|
private val threadLocalDb = ThreadLocal<CordaPersistence>()
|
||||||
|
@ -28,7 +28,7 @@ class PersistentMap<K, V, E, out EK>(
|
|||||||
removalListener = ExplicitRemoval(toPersistentEntityKey, persistentEntityClass)
|
removalListener = ExplicitRemoval(toPersistentEntityKey, persistentEntityClass)
|
||||||
).apply {
|
).apply {
|
||||||
//preload to allow all() to take data only from the cache (cache is unbound)
|
//preload to allow all() to take data only from the cache (cache is unbound)
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaQuery = session.criteriaBuilder.createQuery(persistentEntityClass)
|
val criteriaQuery = session.criteriaBuilder.createQuery(persistentEntityClass)
|
||||||
criteriaQuery.select(criteriaQuery.from(persistentEntityClass))
|
criteriaQuery.select(criteriaQuery.from(persistentEntityClass))
|
||||||
getAll(session.createQuery(criteriaQuery).resultList.map { e -> fromPersistentEntity(e as E).first }.asIterable())
|
getAll(session.createQuery(criteriaQuery).resultList.map { e -> fromPersistentEntity(e as E).first }.asIterable())
|
||||||
@ -38,7 +38,7 @@ class PersistentMap<K, V, E, out EK>(
|
|||||||
override fun onRemoval(notification: RemovalNotification<K, V>?) {
|
override fun onRemoval(notification: RemovalNotification<K, V>?) {
|
||||||
when (notification?.cause) {
|
when (notification?.cause) {
|
||||||
RemovalCause.EXPLICIT -> {
|
RemovalCause.EXPLICIT -> {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val elem = session.find(persistentEntityClass, toPersistentEntityKey(notification.key))
|
val elem = session.find(persistentEntityClass, toPersistentEntityKey(notification.key))
|
||||||
if (elem != null) {
|
if (elem != null) {
|
||||||
session.remove(elem)
|
session.remove(elem)
|
||||||
@ -101,7 +101,7 @@ class PersistentMap<K, V, E, out EK>(
|
|||||||
set(key, value,
|
set(key, value,
|
||||||
logWarning = false,
|
logWarning = false,
|
||||||
store = { k: K, v: V ->
|
store = { k: K, v: V ->
|
||||||
DatabaseTransactionManager.current().session.save(toPersistentEntity(k, v))
|
currentDBSession().save(toPersistentEntity(k, v))
|
||||||
null
|
null
|
||||||
},
|
},
|
||||||
replace = { _: K, _: V -> Unit }
|
replace = { _: K, _: V -> Unit }
|
||||||
@ -115,9 +115,10 @@ class PersistentMap<K, V, E, out EK>(
|
|||||||
fun addWithDuplicatesAllowed(key: K, value: V) =
|
fun addWithDuplicatesAllowed(key: K, value: V) =
|
||||||
set(key, value,
|
set(key, value,
|
||||||
store = { k, v ->
|
store = { k, v ->
|
||||||
val existingEntry = DatabaseTransactionManager.current().session.find(persistentEntityClass, toPersistentEntityKey(k))
|
val session = currentDBSession()
|
||||||
|
val existingEntry = session.find(persistentEntityClass, toPersistentEntityKey(k))
|
||||||
if (existingEntry == null) {
|
if (existingEntry == null) {
|
||||||
DatabaseTransactionManager.current().session.save(toPersistentEntity(k, v))
|
session.save(toPersistentEntity(k, v))
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
fromPersistentEntity(existingEntry).second
|
fromPersistentEntity(existingEntry).second
|
||||||
@ -145,18 +146,19 @@ class PersistentMap<K, V, E, out EK>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun merge(key: K, value: V): V? {
|
private fun merge(key: K, value: V): V? {
|
||||||
val existingEntry = DatabaseTransactionManager.current().session.find(persistentEntityClass, toPersistentEntityKey(key))
|
val session = currentDBSession()
|
||||||
|
val existingEntry = session.find(persistentEntityClass, toPersistentEntityKey(key))
|
||||||
return if (existingEntry != null) {
|
return if (existingEntry != null) {
|
||||||
DatabaseTransactionManager.current().session.merge(toPersistentEntity(key, value))
|
session.merge(toPersistentEntity(key, value))
|
||||||
fromPersistentEntity(existingEntry).second
|
fromPersistentEntity(existingEntry).second
|
||||||
} else {
|
} else {
|
||||||
DatabaseTransactionManager.current().session.save(toPersistentEntity(key, value))
|
session.save(toPersistentEntity(key, value))
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadValue(key: K): V? {
|
private fun loadValue(key: K): V? {
|
||||||
val result = DatabaseTransactionManager.current().session.find(persistentEntityClass, toPersistentEntityKey(key))
|
val result = currentDBSession().find(persistentEntityClass, toPersistentEntityKey(key))
|
||||||
return result?.let(fromPersistentEntity)?.second
|
return result?.let(fromPersistentEntity)?.second
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +258,7 @@ class PersistentMap<K, V, E, out EK>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun load() {
|
fun load() {
|
||||||
val session = DatabaseTransactionManager.current().session
|
val session = currentDBSession()
|
||||||
val criteriaQuery = session.criteriaBuilder.createQuery(persistentEntityClass)
|
val criteriaQuery = session.criteriaBuilder.createQuery(persistentEntityClass)
|
||||||
criteriaQuery.select(criteriaQuery.from(persistentEntityClass))
|
criteriaQuery.select(criteriaQuery.from(persistentEntityClass))
|
||||||
cache.getAll(session.createQuery(criteriaQuery).resultList.map { e -> fromPersistentEntity(e as E).first }.asIterable())
|
cache.getAll(session.createQuery(criteriaQuery).resultList.map { e -> fromPersistentEntity(e as E).first }.asIterable())
|
||||||
|
@ -11,7 +11,6 @@ import net.corda.core.internal.write
|
|||||||
import net.corda.core.internal.writeLines
|
import net.corda.core.internal.writeLines
|
||||||
import net.corda.node.services.transactions.PersistentUniquenessProvider
|
import net.corda.node.services.transactions.PersistentUniquenessProvider
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
|
||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
import net.corda.testing.LogHelper
|
import net.corda.testing.LogHelper
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
@ -98,8 +97,7 @@ class NodeAttachmentStorageTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `corrupt entry throws exception`() {
|
fun `corrupt entry throws exception`() {
|
||||||
val testJar = makeTestJar()
|
val testJar = makeTestJar()
|
||||||
val id =
|
val id = database.transaction {
|
||||||
database.transaction {
|
|
||||||
val storage = NodeAttachmentService(MetricRegistry())
|
val storage = NodeAttachmentService(MetricRegistry())
|
||||||
val id = testJar.read { storage.importAttachment(it) }
|
val id = testJar.read { storage.importAttachment(it) }
|
||||||
|
|
||||||
@ -108,7 +106,7 @@ class NodeAttachmentStorageTest {
|
|||||||
val corruptBytes = "arggghhhh".toByteArray()
|
val corruptBytes = "arggghhhh".toByteArray()
|
||||||
System.arraycopy(corruptBytes, 0, bytes, 0, corruptBytes.size)
|
System.arraycopy(corruptBytes, 0, bytes, 0, corruptBytes.size)
|
||||||
val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = bytes)
|
val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = bytes)
|
||||||
DatabaseTransactionManager.current().session.merge(corruptAttachment)
|
session.merge(corruptAttachment)
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
|
Reference in New Issue
Block a user