mirror of
https://github.com/corda/corda.git
synced 2025-02-03 09:41:10 +00:00
parent
d15efcec10
commit
940bb3bdbd
@ -84,6 +84,7 @@ class CordaPersistence(
|
|||||||
check(!connection.metaData.isReadOnly) { "Database should not be readonly." }
|
check(!connection.metaData.isReadOnly) { "Database should not be readonly." }
|
||||||
|
|
||||||
checkCorrectAttachmentsContractsTableName(connection)
|
checkCorrectAttachmentsContractsTableName(connection)
|
||||||
|
checkCorrectCheckpointTypeOnPostgres(connection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +251,18 @@ fun <T : Any> rx.Observable<T>.wrapWithDatabaseTransaction(db: CordaPersistence?
|
|||||||
|
|
||||||
class IncompatibleAttachmentsContractsTableName(override val message: String?, override val cause: Throwable? = null) : Exception()
|
class IncompatibleAttachmentsContractsTableName(override val message: String?, override val cause: Throwable? = null) : Exception()
|
||||||
|
|
||||||
|
/** Check if any nested cause is of [SQLException] type. */
|
||||||
|
private fun Throwable.hasSQLExceptionCause(): Boolean =
|
||||||
|
when (cause) {
|
||||||
|
null -> false
|
||||||
|
is SQLException -> true
|
||||||
|
else -> cause?.hasSQLExceptionCause() ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
class CouldNotCreateDataSourceException(override val message: String?, override val cause: Throwable? = null) : Exception()
|
||||||
|
|
||||||
|
class DatabaseIncompatibleException(override val message: String?, override val cause: Throwable? = null) : Exception()
|
||||||
|
|
||||||
private fun checkCorrectAttachmentsContractsTableName(connection: Connection) {
|
private fun checkCorrectAttachmentsContractsTableName(connection: Connection) {
|
||||||
val correctName = "NODE_ATTACHMENTS_CONTRACTS"
|
val correctName = "NODE_ATTACHMENTS_CONTRACTS"
|
||||||
val incorrectV30Name = "NODE_ATTACHMENTS_CONTRACT_CLASS_NAME"
|
val incorrectV30Name = "NODE_ATTACHMENTS_CONTRACT_CLASS_NAME"
|
||||||
@ -258,7 +271,22 @@ private fun checkCorrectAttachmentsContractsTableName(connection: Connection) {
|
|||||||
fun warning(incorrectName: String, version: String) = "The database contains the older table name $incorrectName instead of $correctName, see upgrade notes to migrate from Corda database version $version https://docs.corda.net/head/upgrade-notes.html."
|
fun warning(incorrectName: String, version: String) = "The database contains the older table name $incorrectName instead of $correctName, see upgrade notes to migrate from Corda database version $version https://docs.corda.net/head/upgrade-notes.html."
|
||||||
|
|
||||||
if (!connection.metaData.getTables(null, null, correctName, null).next()) {
|
if (!connection.metaData.getTables(null, null, correctName, null).next()) {
|
||||||
if (connection.metaData.getTables(null, null, incorrectV30Name, null).next()) { throw IncompatibleAttachmentsContractsTableName(warning(incorrectV30Name, "3.0")) }
|
if (connection.metaData.getTables(null, null, incorrectV30Name, null).next()) { throw DatabaseIncompatibleException(warning(incorrectV30Name, "3.0")) }
|
||||||
if (connection.metaData.getTables(null, null, incorrectV31Name, null).next()) { throw IncompatibleAttachmentsContractsTableName(warning(incorrectV31Name, "3.1")) }
|
if (connection.metaData.getTables(null, null, incorrectV31Name, null).next()) { throw DatabaseIncompatibleException(warning(incorrectV31Name, "3.1")) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCorrectCheckpointTypeOnPostgres(connection: Connection) {
|
||||||
|
val metaData = connection.metaData
|
||||||
|
if (metaData.getDatabaseProductName() != "PostgreSQL") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = metaData.getColumns(null, null, "node_checkpoints", "checkpoint_value")
|
||||||
|
if (result.next()) {
|
||||||
|
val type = result.getString("TYPE_NAME")
|
||||||
|
if (type != "bytea") {
|
||||||
|
throw DatabaseIncompatibleException("The type of the 'checkpoint_value' table must be 'bytea', but 'oid' was found. See upgrade notes to migrate from Corda database version 3.1 https://docs.corda.net/head/upgrade-notes.html.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ class FailNodeOnNotMigratedAttachmentContractsTableNameTests {
|
|||||||
it.createStatement().execute("ALTER TABLE $tableNameFromMapping RENAME TO $tableNameInDB")
|
it.createStatement().execute("ALTER TABLE $tableNameFromMapping RENAME TO $tableNameInDB")
|
||||||
it.commit()
|
it.commit()
|
||||||
}
|
}
|
||||||
assertFailsWith(net.corda.nodeapi.internal.persistence.IncompatibleAttachmentsContractsTableName::class) {
|
assertFailsWith(net.corda.nodeapi.internal.persistence.DatabaseIncompatibleException::class) {
|
||||||
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user)).getOrThrow()
|
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user)).getOrThrow()
|
||||||
nodeHandle.stop()
|
nodeHandle.stop()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import net.corda.node.shell.InteractiveShell
|
|||||||
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
||||||
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
||||||
import net.corda.nodeapi.internal.addShutdownHook
|
import net.corda.nodeapi.internal.addShutdownHook
|
||||||
import net.corda.nodeapi.internal.persistence.IncompatibleAttachmentsContractsTableName
|
import net.corda.nodeapi.internal.persistence.DatabaseIncompatibleException
|
||||||
import org.fusesource.jansi.Ansi
|
import org.fusesource.jansi.Ansi
|
||||||
import org.fusesource.jansi.AnsiConsole
|
import org.fusesource.jansi.AnsiConsole
|
||||||
import org.slf4j.bridge.SLF4JBridgeHandler
|
import org.slf4j.bridge.SLF4JBridgeHandler
|
||||||
@ -114,7 +114,7 @@ open class NodeStartup(val args: Array<String>) {
|
|||||||
try {
|
try {
|
||||||
cmdlineOptions.baseDirectory.createDirectories()
|
cmdlineOptions.baseDirectory.createDirectories()
|
||||||
startNode(conf, versionInfo, startTime, cmdlineOptions)
|
startNode(conf, versionInfo, startTime, cmdlineOptions)
|
||||||
} catch (e: IncompatibleAttachmentsContractsTableName) {
|
} catch (e: DatabaseIncompatibleException) {
|
||||||
e.message?.let { Node.printWarning(it) }
|
e.message?.let { Node.printWarning(it) }
|
||||||
logger.error(e.message)
|
logger.error(e.message)
|
||||||
return false
|
return false
|
||||||
|
@ -9,7 +9,7 @@ import java.io.Serializable
|
|||||||
import javax.persistence.Column
|
import javax.persistence.Column
|
||||||
import javax.persistence.Entity
|
import javax.persistence.Entity
|
||||||
import javax.persistence.Id
|
import javax.persistence.Id
|
||||||
import javax.persistence.Lob
|
import org.hibernate.annotations.Type
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple checkpoint key value storage in DB.
|
* Simple checkpoint key value storage in DB.
|
||||||
@ -23,8 +23,8 @@ class DBCheckpointStorage : CheckpointStorage {
|
|||||||
@Column(name = "checkpoint_id", length = 64, nullable = false)
|
@Column(name = "checkpoint_id", length = 64, nullable = false)
|
||||||
var checkpointId: String = "",
|
var checkpointId: String = "",
|
||||||
|
|
||||||
@Lob
|
@Column(name = "checkpoint_value")
|
||||||
@Column(name = "checkpoint_value", nullable = false)
|
@Type(type="org.hibernate.type.ImageType")
|
||||||
var checkpoint: ByteArray = ByteArray(0)
|
var checkpoint: ByteArray = ByteArray(0)
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user