CORDA-2450 Creating attachment version from whitelisted JARs fails for node upgrade (#4593)

Upgrade from node 3.0 to 4.0 fails to create versions of whitelisted JARs from networkParameters - read parameters from file at first as in Corda 3.0 there no relevant table, then try from the table.
As this is migration, the code will run only once on each node, she increased log level to info for messages. Tested using https://r3-cev.atlassian.net/browse/R3T-1549
This commit is contained in:
szymonsztuka
2019-01-17 17:26:24 +00:00
committed by GitHub
parent d95c68c2ae
commit 26cfea202b
3 changed files with 44 additions and 30 deletions

View File

@ -5,10 +5,16 @@ import liquibase.database.Database
import liquibase.database.jvm.JdbcConnection
import liquibase.exception.ValidationErrors
import liquibase.resource.ResourceAccessor
import net.corda.core.internal.div
import net.corda.core.internal.readObject
import net.corda.core.node.NetworkParameters
import net.corda.core.node.services.AttachmentId
import net.corda.core.serialization.deserialize
import net.corda.core.utilities.contextLogger
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.network.SignedNetworkParameters
import net.corda.nodeapi.internal.persistence.SchemaMigration.Companion.NODE_BASE_DIR_KEY
import java.nio.file.Path
import java.nio.file.Paths
class AttachmentVersionNumberMigration : CustomTaskChange {
companion object {
@ -17,40 +23,49 @@ class AttachmentVersionNumberMigration : CustomTaskChange {
override fun execute(database: Database?) {
val connection = database?.connection as JdbcConnection
val msg = "Attachment version creation from whitelisted JARs"
try {
logger.debug("Start executing...")
val networkParameters = getNetworkParameters(connection)
if (networkParameters == null) {
logger.debug("Network parameters not found.")
return
logger.info("Start executing...")
var networkParameters: NetworkParameters?
if (System.getProperty(NODE_BASE_DIR_KEY).isNotEmpty()) {
val path = Paths.get(System.getProperty(NODE_BASE_DIR_KEY)) / NETWORK_PARAMS_FILE_NAME
networkParameters = getNetworkParametersFromFile(path)
if (networkParameters != null) {
logger.info("$msg using network parameters from $path, whitelistedContractImplementations: ${networkParameters.whitelistedContractImplementations}.")
} else {
logger.warn("$msg skipped, network parameters not found in $path.")
return
}
} else {
logger.debug("Network parameters epoch: ${networkParameters.epoch}, whitelistedContractImplementations: ${networkParameters.whitelistedContractImplementations}.")
logger.error("$msg skipped, network parameters not retrieved, could not determine node base directory due to system property $NODE_BASE_DIR_KEY being not set.")
return
}
val availableAttachments = getAttachmentsWithDefaultVersion(connection)
if (availableAttachments.isEmpty()) {
logger.debug("Attachments not found.")
logger.info("$msg skipped, no attachments not found.")
return
} else {
logger.debug("Attachments with version '1': $availableAttachments")
logger.info("$msg, candidate attachments with version '1': $availableAttachments")
}
availableAttachments.forEach { attachmentId ->
val versions = networkParameters?.whitelistedContractImplementations?.values.mapNotNull { it.indexOfFirst { it.toString() == attachmentId} }.filter { it >= 0 }
val versions = networkParameters?.whitelistedContractImplementations?.values.mapNotNull { it.indexOfFirst { it.toString() == attachmentId } }.filter { it >= 0 }
val maxPosition = versions.max() ?: 0
if (maxPosition > 0) {
val version = maxPosition + 1
val msg = "Updating version of attachment $attachmentId to '$version'"
val msg = "Updating version of attachment $attachmentId to '$version'."
if (versions.toSet().size > 1)
logger.warn("Several versions based on whitelistedContractImplementations position are available: ${versions.toSet()}. $msg")
else
logger.debug(msg)
logger.info(msg)
updateVersion(connection, attachmentId, version)
}
}
logger.debug("Done")
} catch (e: Exception) {
logger.error("Exception while retrieving network parameters ${e.message}", e)
logger.error("$msg exception ${e.message}", e)
}
}
@ -68,17 +83,10 @@ class AttachmentVersionNumberMigration : CustomTaskChange {
override fun setUp() {
}
private fun getNetworkParameters(connection: JdbcConnection): NetworkParameters? =
connection.createStatement().use {
val rs = it.executeQuery("SELECT PARAMETERS_BYTES FROM NODE_NETWORK_PARAMETERS ORDER BY EPOCH DESC")
if (rs.next()) {
val networkParametersBytes = rs.getBytes(1) as ByteArray
val networkParameters: NetworkParameters = networkParametersBytes.deserialize()
rs.close()
networkParameters
} else
null
}
private fun getNetworkParametersFromFile(path: Path): NetworkParameters? {
val networkParametersBytes = path?.readObject<SignedNetworkParameters>()
return networkParametersBytes?.raw?.deserialize()
}
private fun getAttachmentsWithDefaultVersion(connection: JdbcConnection): List<String> =
connection.createStatement().use {

View File

@ -13,6 +13,7 @@ import net.corda.core.schemas.MappedSchema
import net.corda.core.utilities.contextLogger
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.nio.file.Path
import java.sql.Statement
import javax.sql.DataSource
@ -20,10 +21,12 @@ class SchemaMigration(
val schemas: Set<MappedSchema>,
val dataSource: DataSource,
private val databaseConfig: DatabaseConfig,
private val classLoader: ClassLoader = Thread.currentThread().contextClassLoader) {
private val classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
private val currentDirectory: Path?) {
companion object {
private val logger = contextLogger()
const val NODE_BASE_DIR_KEY = "liquibase.nodeDaseDir"
}
/**
@ -86,6 +89,8 @@ class SchemaMigration(
}
}
System.setProperty(NODE_BASE_DIR_KEY, currentDirectory.toString()) // base dir for any custom change set which may need to load a file (currently AttachmentVersionNumberMigration)
val customResourceAccessor = CustomResourceAccessor(dynamicInclude, changelogList, classLoader)
val liquibase = Liquibase(dynamicInclude, customResourceAccessor, getLiquibaseDatabase(JdbcConnection(connection)))