From 74fd5b9e9d3ed17b2992f2caefda7326049dd92e Mon Sep 17 00:00:00 2001 From: Katarzyna Streich Date: Thu, 31 May 2018 17:44:38 +0100 Subject: [PATCH 1/3] Add documentation on clearing network map cache (#3280) Add documentation on clearing network map cache CORDA-1562 --- docs/source/messaging.rst | 24 ++++++++++-------------- docs/source/network-map.rst | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/docs/source/messaging.rst b/docs/source/messaging.rst index 242e77b674..ebba7c3013 100644 --- a/docs/source/messaging.rst +++ b/docs/source/messaging.rst @@ -24,21 +24,17 @@ Network Map Service Supporting the messaging layer is a network map service, which is responsible for tracking public nodes on the network. -Nodes have an internal component, the network map cache, which contains a copy of the network map (which is just a -document). When a node starts up its cache fetches a copy of the full network map, and requests to be notified of -changes. The node then registers itself with the network map service, and the service notifies subscribers that a new -node has joined the network. Nodes do not automatically deregister themselves, so (for example) nodes going offline -briefly for maintenance are retained in the network map, and messages for them will be queued, minimising disruption. +Nodes have an internal component, the network map cache, which contains a copy of the network map (which is backed up in the database +to persist that information across the restarts in case the network map server is down). When a node starts up its cache +fetches a copy of the full network map (from the server or from filesystem for development mode). After that it polls on +regular time interval for network map and applies any related changes locally. +Nodes do not automatically deregister themselves, so (for example) nodes going offline briefly for maintenance are retained +in the network map, and messages for them will be queued, minimising disruption. -Nodes submit signed changes to the map service, which then forwards update notifications on to nodes which have -requested to be notified of changes. - -The network map currently supports: - -* Looking up nodes by service -* Looking up node for a party -* Suggesting a node providing a specific service, based on suitability for a contract and parties, for example suggesting - an appropriate interest rates oracle for an interest rate swap contract. Currently no recommendation logic is in place. +Additionally, on every restart and on daily basis nodes submit signed `NodeInfo`s to the map service. When network map gets +signed, these changes are distributed as new network data. `NodeInfo` republishing is treated as a heartbeat from the node, +based on that network map service is able to figure out which nodes can be considered as stale and removed from the network +map document after `eventHorizon` time. Message queues -------------- diff --git a/docs/source/network-map.rst b/docs/source/network-map.rst index a4e6ea6e2a..2b90e7ee85 100644 --- a/docs/source/network-map.rst +++ b/docs/source/network-map.rst @@ -173,3 +173,19 @@ shell (see :doc:`shell`): If the administrator does not accept the update then next time the node polls network map after the deadline, the advertised network parameters will be the updated ones. The previous set of parameters will no longer be valid. At this point the node will automatically shutdown and will require the node operator to bring it back again. + +Cleaning the network map cache +------------------------------ + +Sometimes it may happen that the node ends up with an inconsistent view of the network. This can occur due to changes in deployment +leading to stale data in the database, different data distribution time and mistakes in configuration. For these unlikely +events both RPC method and command line option for clearing local network map cache database exist. To use them +you either need to run from the command line: + +.. code-block:: shell + + java -jar corda.jar --clear-network-map-cache + +or call RPC method `clearNetworkMapCache` (it can be invoked through the node's shell as `run clearNetworkMapCache`, for more information on +how to log into node's shell see :doc:`shell`). As we are testing and hardening the implementation this step shouldn't be required. +After cleaning the cache, network map data is restored on the next poll from the server or filesystem. From 51c359c48d1e77e3306091ce70b51f13d0541bff Mon Sep 17 00:00:00 2001 From: Rick Parker Date: Thu, 31 May 2018 18:43:50 +0100 Subject: [PATCH 2/3] CORDA-1564 Clean up old sessions when retrying flows. (#3278) --- .../statemachine/SingleThreadedStateMachineManager.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/SingleThreadedStateMachineManager.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/SingleThreadedStateMachineManager.kt index b61aa7e51f..a98daaf9d9 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/SingleThreadedStateMachineManager.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/SingleThreadedStateMachineManager.kt @@ -354,6 +354,10 @@ class SingleThreadedStateMachineManager( null } externalEventMutex.withLock { + // Remove any sessions the old flow has. + for (sessionId in getFlowSessionIds(currentState.checkpoint)) { + sessionToFlow.remove(sessionId) + } if (flow != null) addAndStartFlow(flowId, flow) // Deliver all the external events from the old flow instance. val unprocessedExternalEvents = mutableListOf() From 52fa86079bb778ad1b6b315e3ecc582182f6a4a7 Mon Sep 17 00:00:00 2001 From: Michele Sollecito Date: Thu, 31 May 2018 18:50:35 +0100 Subject: [PATCH 3/3] [CORDA-1569]: Shell doesn't yield control back to the user after a completed flow and throws NullPointerExceptions (#3281) * [CORDA-1569]: Shell doesn't yield control back to the user after a completed flow and throws NullPointerExceptions --- .../src/main/java/net/corda/tools/shell/FlowShellCommand.java | 2 +- .../src/main/java/net/corda/tools/shell/RunShellCommand.java | 2 +- .../src/main/java/net/corda/tools/shell/StartShellCommand.java | 2 +- .../src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java b/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java index 56607c948d..6fbf4cb003 100644 --- a/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java +++ b/tools/shell/src/main/java/net/corda/tools/shell/FlowShellCommand.java @@ -36,7 +36,7 @@ public class FlowShellCommand extends InteractiveShellCommand { @Usage("The class name of the flow to run, or an unambiguous substring") @Argument String name, @Usage("The data to pass as input") @Argument(unquote = false) List input ) { - logger.info("Executing command \"flow start {} {}\",", name, input.stream().collect(joining(" "))); + logger.info("Executing command \"flow start {} {}\",", name, (input != null) ? input.stream().collect(joining(" ")) : ""); startFlow(name, input, out, ops(), ansiProgressRenderer(), objectMapper()); } diff --git a/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java b/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java index 11ec5e8e76..9ac5cff1b9 100644 --- a/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java +++ b/tools/shell/src/main/java/net/corda/tools/shell/RunShellCommand.java @@ -37,7 +37,7 @@ public class RunShellCommand extends InteractiveShellCommand { ) @Usage("runs a method from the CordaRPCOps interface on the node.") public Object main(InvocationContext context, @Usage("The command to run") @Argument(unquote = false) List command) { - logger.info("Executing command \"run {}\",", command.stream().collect(joining(" "))); + logger.info("Executing command \"run {}\",", (command != null) ? command.stream().collect(joining(" ")) : ""); StringToMethodCallParser parser = new StringToMethodCallParser<>(CordaRPCOps.class, objectMapper()); if (command == null) { diff --git a/tools/shell/src/main/java/net/corda/tools/shell/StartShellCommand.java b/tools/shell/src/main/java/net/corda/tools/shell/StartShellCommand.java index 6fd3ffae7e..c37d4b78c3 100644 --- a/tools/shell/src/main/java/net/corda/tools/shell/StartShellCommand.java +++ b/tools/shell/src/main/java/net/corda/tools/shell/StartShellCommand.java @@ -21,7 +21,7 @@ public class StartShellCommand extends InteractiveShellCommand { public void main(@Usage("The class name of the flow to run, or an unambiguous substring") @Argument String name, @Usage("The data to pass as input") @Argument(unquote = false) List input) { - logger.info("Executing command \"start {} {}\",", name, input.stream().collect(joining(" "))); + logger.info("Executing command \"start {} {}\",", name, (input != null) ? input.stream().collect(joining(" ")) : ""); ANSIProgressRenderer ansiProgressRenderer = ansiProgressRenderer(); FlowShellCommand.startFlow(name, input, out, ops(), ansiProgressRenderer != null ? ansiProgressRenderer : new CRaSHANSIProgressRenderer(out), objectMapper()); } diff --git a/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt b/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt index e5ffe1e0ca..87b4ad4b8d 100644 --- a/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt +++ b/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt @@ -281,6 +281,7 @@ object InteractiveShell { while (!Thread.currentThread().isInterrupted) { try { latch.await() + break } catch (e: InterruptedException) { try { rpcOps.killFlow(stateObservable.id)