#55, #644 Address comments

This commit is contained in:
Andras Slemmer
2017-05-09 10:38:50 +01:00
parent 5db4e4723d
commit f153e9a347
4 changed files with 40 additions and 46 deletions

View File

@ -42,7 +42,7 @@ class BootTests {
startNode(ALICE.name).getOrThrow() startNode(ALICE.name).getOrThrow()
} }
// We count the number of nodes that wrote into the logfile by counting "Logs can be found in" // We count the number of nodes that wrote into the logfile by counting "Logs can be found in"
val numberOfNodesThatLogged = Files.lines(logFile.toPath()).filter { it.contains("Logs can be found in") }.count() val numberOfNodesThatLogged = Files.lines(logFile.toPath()).filter { it.contains(LOGS_CAN_BE_FOUND_IN_STRING) }.count()
assertEquals(1, numberOfNodesThatLogged) assertEquals(1, numberOfNodesThatLogged)
} }
} }

View File

@ -9,8 +9,8 @@ import net.corda.core.*
import net.corda.core.node.VersionInfo import net.corda.core.node.VersionInfo
import net.corda.core.utilities.Emoji import net.corda.core.utilities.Emoji
import net.corda.core.utilities.LogHelper.withLevel import net.corda.core.utilities.LogHelper.withLevel
import net.corda.node.internal.EnforceSingleNodeIsRunning
import net.corda.node.internal.Node import net.corda.node.internal.Node
import net.corda.node.internal.enforceSingleNodeIsRunning
import net.corda.node.services.config.FullNodeConfiguration import net.corda.node.services.config.FullNodeConfiguration
import net.corda.node.shell.InteractiveShell import net.corda.node.shell.InteractiveShell
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
@ -36,6 +36,7 @@ fun printBasicNodeInfo(description: String, info: String? = null) {
} }
val LOGS_DIRECTORY_NAME = "logs" val LOGS_DIRECTORY_NAME = "logs"
val LOGS_CAN_BE_FOUND_IN_STRING = "Logs can be found in"
private val log by lazy { LoggerFactory.getLogger("Main") } private val log by lazy { LoggerFactory.getLogger("Main") }
private fun initLogging(cmdlineOptions: CmdLineOptions) { private fun initLogging(cmdlineOptions: CmdLineOptions) {
@ -64,10 +65,9 @@ fun main(args: Array<String>) {
exitProcess(1) exitProcess(1)
} }
val enforceSingleNodeIsRunning = EnforceSingleNodeIsRunning(cmdlineOptions.baseDirectory)
// We do the single node check before we initialise logging so that in case of a double-node start it doesn't mess // We do the single node check before we initialise logging so that in case of a double-node start it doesn't mess
// with the running node's logs. // with the running node's logs.
enforceSingleNodeIsRunning.start() enforceSingleNodeIsRunning(cmdlineOptions.baseDirectory)
initLogging(cmdlineOptions) initLogging(cmdlineOptions)
disableJavaDeserialization() // Should be after initLogging to avoid TMI. disableJavaDeserialization() // Should be after initLogging to avoid TMI.
@ -97,7 +97,7 @@ fun main(args: Array<String>) {
drawBanner(versionInfo) drawBanner(versionInfo)
printBasicNodeInfo("Logs can be found in", System.getProperty("log-path")) printBasicNodeInfo(LOGS_CAN_BE_FOUND_IN_STRING, System.getProperty("log-path"))
val conf = try { val conf = try {
cmdlineOptions.loadConfig() cmdlineOptions.loadConfig()

View File

@ -340,15 +340,18 @@ class ShutdownManager(private val executorService: ExecutorService) {
} }
val shutdowns = shutdownFutures.map { ErrorOr.catch { it.get(1, SECONDS) } } val shutdowns = shutdownFutures.map { ErrorOr.catch { it.get(1, SECONDS) } }
shutdowns.reversed().forEach { errorOrShutdown -> shutdowns.reversed().forEach { errorOrShutdown ->
try { errorOrShutdown.match(
if (errorOrShutdown.error == null) { onValue = { shutdown ->
errorOrShutdown.value?.invoke() try {
} else { shutdown()
log.error("Exception while getting shutdown method, disregarding", errorOrShutdown.error) } catch (throwable: Throwable) {
} log.error("Exception while shutting down", throwable)
} catch (throwable: Throwable) { }
log.error("Exception while shutting down", throwable) },
} onError = { error ->
log.error("Exception while getting shutdown method, disregarding", error)
}
)
} }
} }

View File

@ -7,38 +7,29 @@ import java.lang.management.ManagementFactory
import java.nio.file.Path import java.nio.file.Path
/** /**
* This class enforces that only a single node is running using the given [baseDirectory] by using a file lock. * This function enforces that only a single node is running using the given [baseDirectory] by using a file lock.
*/ */
class EnforceSingleNodeIsRunning(val baseDirectory: Path) { fun enforceSingleNodeIsRunning(baseDirectory: Path) {
private companion object { // Write out our process ID (which may or may not resemble a UNIX process id - to us it's just a string) to a
val log = loggerFor<EnforceSingleNodeIsRunning>() // file that we'll do our best to delete on exit. But if we don't, it'll be overwritten next time. If it already
} // exists, we try to take the file lock first before replacing it and if that fails it means we're being started
// twice with the same directory: that's a user error and we should bail out.
fun start() { val pidFile = (baseDirectory / "process-id").toFile()
// Write out our process ID (which may or may not resemble a UNIX process id - to us it's just a string) to a pidFile.createNewFile()
// file that we'll do our best to delete on exit. But if we don't, it'll be overwritten next time. If it already pidFile.deleteOnExit()
// exists, we try to take the file lock first before replacing it and if that fails it means we're being started val pidFileRw = RandomAccessFile(pidFile, "rw")
// twice with the same directory: that's a user error and we should bail out. val pidFileLock = pidFileRw.channel.tryLock()
val pidPath = baseDirectory / "process-id" if (pidFileLock == null) {
val pidFile = pidPath.toFile() println("It appears there is already a node running with the specified data directory $baseDirectory")
if (!pidFile.exists()) { println("Shut that other node down and try again. It may have process ID ${pidFile.readText()}")
pidFile.createNewFile() System.exit(1)
}
pidFile.deleteOnExit()
val pidFileRw = RandomAccessFile(pidFile, "rw")
val pidFileLock = pidFileRw.channel.tryLock()
if (pidFileLock == null) {
log.error("It appears there is already a node running with the specified data directory $baseDirectory")
log.error("Shut that other node down and try again. It may have process ID ${pidFile.readText()}")
System.exit(1)
}
// Avoid the lock being garbage collected. We don't really need to release it as the OS will do so for us
// when our process shuts down, but we try in stop() anyway just to be nice.
Runtime.getRuntime().addShutdownHook(Thread {
pidFileLock.release()
})
val ourProcessID: String = ManagementFactory.getRuntimeMXBean().name.split("@")[0]
pidFileRw.setLength(0)
pidFileRw.write(ourProcessID.toByteArray())
} }
// Avoid the lock being garbage collected. We don't really need to release it as the OS will do so for us
// when our process shuts down, but we try in stop() anyway just to be nice.
Runtime.getRuntime().addShutdownHook(Thread {
pidFileLock.release()
})
val ourProcessID: String = ManagementFactory.getRuntimeMXBean().name.split("@")[0]
pidFileRw.setLength(0)
pidFileRw.write(ourProcessID.toByteArray())
} }