From b264d4cc207f36e5adcc2d9c08c7196886e0483d Mon Sep 17 00:00:00 2001 From: Michele Sollecito Date: Tue, 18 Sep 2018 13:04:59 +0200 Subject: [PATCH] [CORDA-1971]: Improve error code derivation (#3956) --- .../node/internal/ExceptionsHashFunction.kt | 39 +++++++++++++++++ .../net/corda/node/internal/NodeStartup.kt | 42 ++++++------------- 2 files changed, 52 insertions(+), 29 deletions(-) create mode 100644 node/src/main/kotlin/net/corda/node/internal/ExceptionsHashFunction.kt diff --git a/node/src/main/kotlin/net/corda/node/internal/ExceptionsHashFunction.kt b/node/src/main/kotlin/net/corda/node/internal/ExceptionsHashFunction.kt new file mode 100644 index 0000000000..8a647cd013 --- /dev/null +++ b/node/src/main/kotlin/net/corda/node/internal/ExceptionsHashFunction.kt @@ -0,0 +1,39 @@ +package net.corda.node.internal + +import java.util.* + +fun Exception.errorCode(hashedFields: (Throwable) -> Array = Throwable::defaultHashedFields): String { + val hash = staticLocationBasedHash(hashedFields) + return hash.toBase(36) +} + +private fun Throwable.staticLocationBasedHash(hashedFields: (Throwable) -> Array, visited: Set = setOf(this)): Int { + val cause = this.cause + val fields = hashedFields.invoke(this) + return when { + cause != null && !visited.contains(cause) -> Objects.hash(*fields, cause.staticLocationBasedHash(hashedFields, visited + cause)) + else -> Objects.hash(*fields) + } +} + +private fun Int.toBase(base: Int): String = Integer.toUnsignedString(this, base) + +private fun Array.customHashCode(maxElementsToConsider: Int = this.size): Int { + + return Arrays.hashCode(take(maxElementsToConsider).map { it?.customHashCode() ?: 0 }.toIntArray()) +} + +private fun StackTraceElement.customHashCode(hashedFields: (StackTraceElement) -> Array = StackTraceElement::defaultHashedFields): Int { + + return Objects.hash(*hashedFields.invoke(this)) +} + +private fun Throwable.defaultHashedFields(): Array { + + return arrayOf(this::class.java.name, stackTrace?.customHashCode(3) ?: 0) +} + +private fun StackTraceElement.defaultHashedFields(): Array { + + return arrayOf(className, methodName) +} \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt index 0535729286..dbb92bf514 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt @@ -7,14 +7,24 @@ import io.netty.channel.unix.Errors import net.corda.cliutils.CordaCliWrapper import net.corda.cliutils.CordaVersionProvider import net.corda.cliutils.ExitCodes +import net.corda.core.CordaRuntimeException import net.corda.core.crypto.Crypto -import net.corda.core.internal.* +import net.corda.core.internal.Emoji import net.corda.core.internal.concurrent.thenMatch import net.corda.core.internal.cordapp.CordappImpl +import net.corda.core.internal.createDirectories +import net.corda.core.internal.div import net.corda.core.internal.errors.AddressBindingException +import net.corda.core.internal.exists +import net.corda.core.internal.location +import net.corda.core.internal.randomOrNull import net.corda.core.utilities.Try import net.corda.core.utilities.loggerFor -import net.corda.node.* +import net.corda.node.NodeCmdLineOptions +import net.corda.node.NodeRegistrationOption +import net.corda.node.SerialFilter +import net.corda.node.VersionInfo +import net.corda.node.defaultSerialFilter import net.corda.node.internal.cordapp.MultipleCordappsForFlowException import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfigurationImpl @@ -41,6 +51,7 @@ import java.io.Console import java.io.File import java.io.IOException import java.io.RandomAccessFile +import java.lang.IllegalStateException import java.lang.management.ManagementFactory import java.net.InetAddress import java.nio.file.Path @@ -160,19 +171,6 @@ open class NodeStartup: CordaCliWrapper("corda", "Runs a Corda Node") { private fun Exception.isOpenJdkKnownIssue() = message?.startsWith("Unknown named curve:") == true - private fun Exception.errorCode(): String { - val hash = staticLocationBasedHash() - return Integer.toOctalString(hash) - } - - private fun Throwable.staticLocationBasedHash(visited: Set = setOf(this)): Int { - val cause = this.cause - return when { - cause != null && !visited.contains(cause) -> Objects.hash(this::class.java.name, stackTrace.customHashCode(), cause.staticLocationBasedHash(visited + cause)) - else -> Objects.hash(this::class.java.name, stackTrace.customHashCode()) - } - } - private val handleRegistrationError = { error: Exception -> when (error) { is NodeRegistrationException -> error.logAsExpected("Node registration service is unavailable. Perhaps try to perform the initial registration again after a while.") @@ -198,19 +196,6 @@ open class NodeStartup: CordaCliWrapper("corda", "Runs a Corda Node") { } } - private fun Array?.customHashCode(): Int { - - if (this == null) { - return 0 - } - return Arrays.hashCode(map { it?.customHashCode() ?: 0 }.toIntArray()) - } - - private fun StackTraceElement.customHashCode(): Int { - - return Objects.hash(StackTraceElement::class.java.name, methodName, lineNumber) - } - private fun configFileNotFoundMessage(configFile: Path): String { return """ Unable to load the node config file from '$configFile'. @@ -621,4 +606,3 @@ open class NodeStartup: CordaCliWrapper("corda", "Runs a Corda Node") { } } -