mirror of
https://github.com/corda/corda.git
synced 2025-03-14 16:26:36 +00:00
Merge pull request #819 from corda/chrisr3-os-merge
Merge from OS up to fe88e99
This commit is contained in:
commit
4b3ddc3946
@ -68,7 +68,6 @@ import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
val Throwable.rootCause: Throwable get() = cause?.rootCause ?: this
|
||||
fun Throwable.getStackTraceAsString() = StringWriter().also { printStackTrace(PrintWriter(it)) }.toString()
|
||||
|
||||
infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
|
||||
|
||||
|
@ -475,47 +475,48 @@ existing object relational mapper. For example, we can update:
|
||||
.. sourcecode:: java
|
||||
|
||||
public class ObligationSchemaV1 extends MappedSchema {
|
||||
public IOUSchemaV1() {
|
||||
public ObligationSchemaV1() {
|
||||
super(Obligation.class, 1, ImmutableList.of(ObligationEntity.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "obligations")
|
||||
public static class ObligationEntity extends PersistentState {
|
||||
@Column(name = "currency") private final String currency;
|
||||
@Column(name = "amount") private final Long amount;
|
||||
@Column(name = "lender") @Lob private final Byte[] lender;
|
||||
@Column(name = "borrower") @Lob private final Byte[] borrower;
|
||||
@Column(name = "linear_id") private final UUID linearId;
|
||||
@Entity
|
||||
@Table(name = "obligations")
|
||||
public class ObligationEntity extends PersistentState {
|
||||
@Column(name = "currency") private String currency;
|
||||
@Column(name = "amount") private Long amount;
|
||||
@Column(name = "lender") @Lob private byte[] lender;
|
||||
@Column(name = "borrower") @Lob private byte[] borrower;
|
||||
@Column(name = "linear_id") private UUID linearId;
|
||||
|
||||
protected ObligationEntity(){}
|
||||
|
||||
public ObligationEntity(String currency, Long amount, Byte[] lender, Byte[] borrower, UUID linearId) {
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.lender = lender;
|
||||
this.borrower = borrower;
|
||||
this.linearId = linearId;
|
||||
}
|
||||
public ObligationEntity(String currency, Long amount, byte[] lender, byte[] borrower, UUID linearId) {
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.lender = lender;
|
||||
this.borrower = borrower;
|
||||
this.linearId = linearId;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public Long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
public Long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public ByteArray getLender() {
|
||||
return lender;
|
||||
}
|
||||
public byte[] getLender() {
|
||||
return lender;
|
||||
}
|
||||
|
||||
public ByteArray getBorrower() {
|
||||
return borrower;
|
||||
}
|
||||
public byte[] getBorrower() {
|
||||
return borrower;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return linearId;
|
||||
}
|
||||
public UUID getLinearId() {
|
||||
return linearId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,53 +541,54 @@ To:
|
||||
.. sourcecode:: java
|
||||
|
||||
public class ObligationSchemaV1 extends MappedSchema {
|
||||
public IOUSchemaV1() {
|
||||
public ObligationSchemaV1() {
|
||||
super(Obligation.class, 1, ImmutableList.of(ObligationEntity.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "obligations")
|
||||
public static class ObligationEntity extends PersistentState {
|
||||
@Column(name = "currency") private final String currency;
|
||||
@Column(name = "amount") private final Long amount;
|
||||
@Column(name = "lender") @Lob private final Byte[] lender;
|
||||
@Column(name = "borrower") @Lob private final Byte[] borrower;
|
||||
@Column(name = "linear_id") private final UUID linearId;
|
||||
@Column(name = "defaulted") private final Boolean defaulted; // NEW COLUMN!
|
||||
@Entity
|
||||
@Table(name = "obligations")
|
||||
public class ObligationEntity extends PersistentState {
|
||||
@Column(name = "currency") private String currency;
|
||||
@Column(name = "amount") private Long amount;
|
||||
@Column(name = "lender") @Lob private byte[] lender;
|
||||
@Column(name = "borrower") @Lob private byte[] borrower;
|
||||
@Column(name = "linear_id") private UUID linearId;
|
||||
@Column(name = "defaulted") private Boolean defaulted; // NEW COLUMN!
|
||||
|
||||
protected ObligationEntity(){}
|
||||
|
||||
public ObligationEntity(String currency, Long amount, Byte[] lender, Byte[] borrower, UUID linearId, Boolean defaulted) {
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.lender = lender;
|
||||
this.borrower = borrower;
|
||||
this.linearId = linearId;
|
||||
this.defaulted = defaulted;
|
||||
}
|
||||
public ObligationEntity(String currency, Long amount, byte[] lender, byte[] borrower, UUID linearId, Boolean defaulted) {
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.lender = lender;
|
||||
this.borrower = borrower;
|
||||
this.linearId = linearId;
|
||||
this.defaulted = defaulted;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public Long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
public Long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public ByteArray getLender() {
|
||||
return lender;
|
||||
}
|
||||
public byte[] getLender() {
|
||||
return lender;
|
||||
}
|
||||
|
||||
public ByteArray getBorrower() {
|
||||
return borrower;
|
||||
}
|
||||
public byte[] getBorrower() {
|
||||
return borrower;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return linearId;
|
||||
}
|
||||
public UUID getLinearId() {
|
||||
return linearId;
|
||||
}
|
||||
|
||||
public Boolean isDefaulted() {
|
||||
return defaulted;
|
||||
}
|
||||
public Boolean isDefaulted() {
|
||||
return defaulted;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,10 +134,8 @@ class CordaPersistence(
|
||||
* @param isolationLevel isolation level for the transaction.
|
||||
* @param statement to be executed in the scope of this transaction.
|
||||
*/
|
||||
fun <T> transaction(isolationLevel: TransactionIsolationLevel, statement: DatabaseTransaction.() -> T): T {
|
||||
_contextDatabase.set(this)
|
||||
return transaction(isolationLevel, 2, statement)
|
||||
}
|
||||
fun <T> transaction(isolationLevel: TransactionIsolationLevel, statement: DatabaseTransaction.() -> T): T =
|
||||
transaction(isolationLevel, 2, false, statement)
|
||||
|
||||
/**
|
||||
* Executes given statement in the scope of transaction with the transaction level specified at the creation time.
|
||||
@ -145,16 +143,26 @@ class CordaPersistence(
|
||||
*/
|
||||
fun <T> transaction(statement: DatabaseTransaction.() -> T): T = transaction(defaultIsolationLevel, statement)
|
||||
|
||||
private fun <T> transaction(isolationLevel: TransactionIsolationLevel, recoverableFailureTolerance: Int, statement: DatabaseTransaction.() -> T): T {
|
||||
/**
|
||||
* Executes given statement in the scope of transaction, with the given isolation level.
|
||||
* @param isolationLevel isolation level for the transaction.
|
||||
* @param recoverableFailureTolerance number of transaction commit retries for SQL while SQL exception is encountered.
|
||||
* @param recoverAnyNestedSQLException retry transaction on any SQL Exception wrapped as a cause of [Throwable].
|
||||
* @param statement to be executed in the scope of this transaction.
|
||||
*/
|
||||
fun <T> transaction(isolationLevel: TransactionIsolationLevel, recoverableFailureTolerance: Int,
|
||||
recoverAnyNestedSQLException: Boolean, statement: DatabaseTransaction.() -> T): T {
|
||||
_contextDatabase.set(this)
|
||||
val outer = contextTransactionOrNull
|
||||
return if (outer != null) {
|
||||
outer.statement()
|
||||
} else {
|
||||
inTopLevelTransaction(isolationLevel, recoverableFailureTolerance, statement)
|
||||
inTopLevelTransaction(isolationLevel, recoverableFailureTolerance, recoverAnyNestedSQLException, statement)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> inTopLevelTransaction(isolationLevel: TransactionIsolationLevel, recoverableFailureTolerance: Int, statement: DatabaseTransaction.() -> T): T {
|
||||
private fun <T> inTopLevelTransaction(isolationLevel: TransactionIsolationLevel, recoverableFailureTolerance: Int,
|
||||
recoverAnyNestedSQLException: Boolean, statement: DatabaseTransaction.() -> T): T {
|
||||
var recoverableFailureCount = 0
|
||||
fun <T> quietly(task: () -> T) = try {
|
||||
task()
|
||||
@ -167,13 +175,14 @@ class CordaPersistence(
|
||||
val answer = transaction.statement()
|
||||
transaction.commit()
|
||||
return answer
|
||||
} catch (e: SQLException) {
|
||||
quietly(transaction::rollback)
|
||||
if (++recoverableFailureCount > recoverableFailureTolerance) throw e
|
||||
log.warn("Caught failure, will retry:", e)
|
||||
} catch (e: Throwable) {
|
||||
quietly(transaction::rollback)
|
||||
throw e
|
||||
if (e is SQLException || (recoverAnyNestedSQLException && e.hasSQLExceptionCause())) {
|
||||
if (++recoverableFailureCount > recoverableFailureTolerance) throw e
|
||||
log.warn("Caught failure, will retry $recoverableFailureCount/$recoverableFailureTolerance:", e)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
} finally {
|
||||
quietly(transaction::close)
|
||||
}
|
||||
@ -277,4 +286,14 @@ fun parserTransactionIsolationLevel(property: String?): Int =
|
||||
}
|
||||
}
|
||||
|
||||
fun isH2Database(jdbcUrl: String) = jdbcUrl.startsWith("jdbc:h2:")
|
||||
fun isH2Database(jdbcUrl: String) = jdbcUrl.startsWith("jdbc:h2:")
|
||||
|
||||
/** Check if any nested cause is of [SQLException] type. */
|
||||
private fun Throwable.hasSQLExceptionCause(): Boolean =
|
||||
if (cause == null)
|
||||
false
|
||||
else if (cause is SQLException)
|
||||
true
|
||||
else
|
||||
cause?.hasSQLExceptionCause() ?: false
|
||||
|
||||
|
@ -12,7 +12,6 @@ package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import com.esotericsoftware.kryo.io.ByteBufferInputStream
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.getStackTraceAsString
|
||||
import net.corda.core.serialization.EncodingWhitelist
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
@ -105,7 +104,7 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun getEnvelope(byteSequence: ByteSequence) = Companion.getEnvelope(byteSequence, encodingWhitelist)
|
||||
fun getEnvelope(byteSequence: ByteSequence) = getEnvelope(byteSequence, encodingWhitelist)
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline fun <reified T : Any> deserialize(bytes: SerializedBytes<T>, context: SerializationContext): T =
|
||||
@ -119,7 +118,7 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
} catch (nse: NotSerializableException) {
|
||||
throw nse
|
||||
} catch (t: Throwable) {
|
||||
throw NotSerializableException("Unexpected throwable: ${t.message} ${t.getStackTraceAsString()}")
|
||||
throw NotSerializableException("Unexpected throwable: ${t.message}").apply { initCause(t) }
|
||||
} finally {
|
||||
objectHistory.clear()
|
||||
}
|
||||
@ -173,7 +172,7 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
if (!objectRetrieved::class.java.isSubClassOf(type.asClass()!!)) {
|
||||
throw NotSerializableException(
|
||||
"Existing reference type mismatch. Expected: '$type', found: '${objectRetrieved::class.java}' " +
|
||||
"@ ${objectIndex}")
|
||||
"@ $objectIndex")
|
||||
}
|
||||
objectRetrieved
|
||||
} else {
|
||||
|
@ -497,7 +497,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
||||
copy[valueIndex] = 0x00
|
||||
assertThatExceptionOfType(NotSerializableException::class.java).isThrownBy {
|
||||
des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java, testSerializationContext)
|
||||
}.withMessageContaining("Zero not allowed")
|
||||
}.withStackTraceContaining("Zero not allowed")
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user