Merge pull request #576 from corda/merges/1 2018-03-16

Merge OS to Enterprise.
This commit is contained in:
szymonsztuka 2018-03-19 08:18:40 +00:00 committed by GitHub
commit fef30e49a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 51 additions and 311 deletions

View File

@ -25,6 +25,7 @@ import net.corda.nodeapi.RPCApi
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.internal.testThreadFactory
import net.corda.testing.node.internal.*
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration
import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.After
import org.junit.Assert.assertEquals
@ -56,15 +57,15 @@ class RPCStabilityTests {
override val protocolVersion = 0
}
private fun waitUntilNumberOfThreadsStable(executorService: ScheduledExecutorService): Int {
val values = ConcurrentLinkedQueue<Int>()
private fun waitUntilNumberOfThreadsStable(executorService: ScheduledExecutorService): Map<Thread, List<StackTraceElement>> {
val values = ConcurrentLinkedQueue<Map<Thread, List<StackTraceElement>>>()
return poll(executorService, "number of threads to become stable", 250.millis) {
values.add(Thread.activeCount())
values.add(Thread.getAllStackTraces().mapValues { it.value.toList() })
if (values.size > 5) {
values.poll()
}
val first = values.peek()
if (values.size == 5 && values.all { it == first }) {
if (values.size == 5 && values.all { it.keys.size == first.keys.size }) {
first
} else {
null
@ -74,30 +75,39 @@ class RPCStabilityTests {
@Test
fun `client and server dont leak threads`() {
val executor = Executors.newScheduledThreadPool(1)
fun startAndStop() {
rpcDriver {
val server = startRpcServer<RPCOps>(ops = DummyOps).get()
startRpcClient<RPCOps>(server.broker.hostAndPort!!).get()
}
}
repeat(5) {
startAndStop()
runBlockAndCheckThreads(::startAndStop)
}
private fun runBlockAndCheckThreads(block: () -> Unit) {
val executor = Executors.newScheduledThreadPool(1)
try {
// Warm-up so that all the thread pools & co. created
block()
val threadsBefore = waitUntilNumberOfThreadsStable(executor)
repeat(5) {
block()
}
val threadsAfter = waitUntilNumberOfThreadsStable(executor)
// This is a less than check because threads from other tests may be shutting down while this test is running.
// This is therefore a "best effort" check. When this test is run on its own this should be a strict equality.
// In case of failure we output the threads along with their stacktraces to get an idea what was running at a time.
assert(threadsBefore.keys.size >= threadsAfter.keys.size, { "threadsBefore: $threadsBefore\nthreadsAfter: $threadsAfter" })
} finally {
executor.shutdownNow()
}
val numberOfThreadsBefore = waitUntilNumberOfThreadsStable(executor)
repeat(5) {
startAndStop()
}
val numberOfThreadsAfter = waitUntilNumberOfThreadsStable(executor)
// This is a less than check because threads from other tests may be shutting down while this test is running.
// This is therefore a "best effort" check. When this test is run on its own this should be a strict equality.
assertTrue(numberOfThreadsBefore >= numberOfThreadsAfter)
executor.shutdownNow()
}
@Test
fun `client doesnt leak threads when it fails to start`() {
val executor = Executors.newScheduledThreadPool(1)
fun startAndStop() {
rpcDriver {
Try.on { startRpcClient<RPCOps>(NetworkHostAndPort("localhost", 9999)).get() }
@ -110,20 +120,10 @@ class RPCStabilityTests {
}
}
}
repeat(5) {
startAndStop()
}
val numberOfThreadsBefore = waitUntilNumberOfThreadsStable(executor)
repeat(5) {
startAndStop()
}
val numberOfThreadsAfter = waitUntilNumberOfThreadsStable(executor)
assertTrue(numberOfThreadsBefore >= numberOfThreadsAfter)
executor.shutdownNow()
runBlockAndCheckThreads(::startAndStop)
}
fun RpcBrokerHandle.getStats(): Map<String, Any> {
private fun RpcBrokerHandle.getStats(): Map<String, Any> {
return serverControl.run {
mapOf(
"connections" to listConnectionIDs().toSet(),
@ -221,14 +221,14 @@ class RPCStabilityTests {
val server = startRpcServer<LeakObservableOps>(ops = leakObservableOpsImpl)
val proxy = startRpcClient<LeakObservableOps>(server.get().broker.hostAndPort!!).get()
// Leak many observables
val N = 200
(1..N).map {
val count = 200
(1..count).map {
pool.fork { proxy.leakObservable(); Unit }
}.transpose().getOrThrow()
// In a loop force GC and check whether the server is notified
while (true) {
System.gc()
if (leakObservableOpsImpl.leakedUnsubscribedCount.get() == N) break
if (leakObservableOpsImpl.leakedUnsubscribedCount.get() == count) break
Thread.sleep(100)
}
}
@ -371,11 +371,11 @@ class RPCStabilityTests {
clients[0].destroyForcibly()
pollUntilClientNumber(server, numberOfClients - 1)
// Kill the rest
(1..numberOfClients - 1).forEach {
(1 until numberOfClients).forEach {
clients[it].destroyForcibly()
}
pollUntilClientNumber(server, 0)
// Now poll until the server detects the disconnects and unsubscribes from all obserables.
// Now poll until the server detects the disconnects and un-subscribes from all observables.
pollUntilTrue("number of times subscribe() has been called") { trackSubscriberOpsImpl.subscriberCount.get() == 0 }.get()
}
}
@ -401,7 +401,7 @@ class RPCStabilityTests {
// Construct an RPC session manually so that we can hang in the message handler
val myQueue = "${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.test.${random63BitValue()}"
val session = startArtemisSession(server.broker.hostAndPort!!)
session.createTemporaryQueue(myQueue, myQueue)
session.createTemporaryQueue(myQueue, ActiveMQDefaultConfiguration.getDefaultRoutingType(), myQueue)
val consumer = session.createConsumer(myQueue, null, -1, -1, false)
consumer.setMessageHandler {
Thread.sleep(50) // 5x slower than the server producer
@ -438,7 +438,7 @@ class RPCStabilityTests {
// Construct an RPC client session manually
val myQueue = "${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.test.${random63BitValue()}"
val session = startArtemisSession(server.broker.hostAndPort!!)
session.createTemporaryQueue(myQueue, myQueue)
session.createTemporaryQueue(myQueue, ActiveMQDefaultConfiguration.getDefaultRoutingType(), myQueue)
val consumer = session.createConsumer(myQueue, null, -1, -1, false)
val replies = ArrayList<Any>()
consumer.setMessageHandler {

View File

@ -61,7 +61,6 @@ data class LedgerTransaction @JvmOverloads constructor(
}
private companion object {
@JvmStatic
private fun createContractFor(className: ContractClassName, classLoader: ClassLoader?): Try<Contract> {
return Try.on {
(classLoader ?: this::class.java.classLoader)

View File

@ -27,7 +27,7 @@ RPC permissions
---------------
For a node's owner to interact with their node via RPC, they must define one or more RPC users. Each user is
authenticated with a username and password, and is assigned a set of permissions that control which RPC operations they
can perform.
can perform. Permissions are not required to interact with the node via the shell, unless the shell is being accessed via SSH.
RPC users are created by adding them to the ``rpcUsers`` list in the node's ``node.conf`` file:

View File

@ -1,4 +0,0 @@
Frequently asked questions
==========================
A list of frequently asked questions can be found here: `<https://discourse.corda.net/c/faq>`_.

View File

@ -1,75 +0,0 @@
Glossary
========
AMQP
The serialisation mechanism used within Corda for everything except flow checkpoints and RPC.
Artemis
The message queuing middleware used within Corda
Attachment
An attachment is a piece of data that can be referred to within a transaction but is never marked as used, i.e. can be referred to multiple times.
Command
Used for directing a transaction, sometimes containing command data. For example, a Cash contract may include an Issue command, which signals that one of the purposes of the transaction is to issue cash on to the ledger (i.e. by creating one or more Cash outputs, without any corresponding inputs.)
Composite Key
A tree data structure containing regular cryptographic public keys. It allows expressing threshold signature requirements, e.g. “either Alice or Bob” needs to sign.
Contract
A contract is code that specifies how states are to be created and used within Corda.
Corda
A Distributed Ledger for recording and managing financial agreements
CorDapp
A Corda Distributed Application. A shared ledger application on Corda consisting of components from: State objects (data), Contract Code (allowable operations), Flows (aka Transaction Flows, the business logic choreography), any necessary APIs, wallet plugins, and UI components.
Cordformation
A gradle plugin that can be configured via your gradle buildscripts to locally deploy a set of Corda nodes
Counterparty
The other party in a financial or contract transaction
DSL
Domain Specific Language - a language specifically designed for a particular domain. Kotlin allows the definition of DSLs and they are used within the Corda framework.
Flow
The set of instructions which determines how nodes communicate over Corda with the goal of arriving at consensus.
Fungible
An item that can be exchanged or interchanged for another identical item, e.g. Cash (as a $10 note can be exchanged for two $5 notes), but not diamonds (as they tend to have very identifying characteristics).
Gradle
Industry standard build and deployment tool. Used extensively within Corda.
Kotlin
The language used to code Corda. Fully compatible with any JVM language, including (obviously) Java.
Kryo
The serialisation mechanism used within Corda for flow checkpoints and RPC.
Input
In Corda terms, an input state is one that is used and consumed within a transaction. Once consumed, it cannot be re-used.
JVM
The Java Virtual Machine. The "computing machine" that Corda is executed within.
Lizard People
I would put their true identity in here but I fear the overlords may banish me.
Merkle Tree
A tree where each non leaf node is tagged with a hash of the data within that node and also the nodes beneath it. This ensures that the data in any node cannot be modified without causing hash verification failures in the parent node, and therefore all subsequent parents.
Network Map Service
A network service that maintains a map of node names and their network locations. Used by nodes such that they can communicate with other parties directly (after locating).
Node
A communication point on the Corda network and also the provider of the virtual machine in which Corda runs.
Notary Service
A network service that guarantees that it will only add its signature to transactions if all input states have not been consumed
Oracle
An oracle is a well known service that signs transactions if they state a fact and that fact is considered to be true. They may also optionally also provide the facts.
Output
In the Corda model, an output is a state generated from a transaction (note that multiple outputs can be generated from one transaction). They are then used as inputs for subsequent transactions.
Protocol
The old name for a Corda "Flow"
Quasar
A library that provides performant lightweight threads that can be suspended and restored extremely quickly.
SIMM
Standard Initial Margin Model. A way of determining a counterparty's margin payment to another counterparty based on a collection of trades such that, in the event of default, the receiving counterparty has limited exposure.
Serialization
Object serialization is the process of converting objects into a stream of bytes and, deserialization, the reverse process.
Service Hub
A hub in each Corda node that manages the services upon which other components of the node depend. Services may include facilities for identity management, storage management, network map management etc.
Signed Transaction
A signed transaction is a transaction that has been agreed by all parties relevant to that transaction as well as optionally a notary if relevant.
State
An element of data that is output from one transaction and then used / consumed in another transaction. States can only be consumed once and this confirmation is performed by the Notary service.
Transaction
A transaction is the means by which states are both created and consumed. They can be designed to accept between zero and any number of input states, and then generate between zero and any number of output states.
UTXO
Unspent Transaction Output. First introduced by the bitcoin model, an unspent transaction is data that has been output from a transaction but not yet used in another transaction.
Verify
To confirm that the transaction is valid by ensuring the the outputs are correctly derived from the inputs combined with the command of the transaction.
Whitelisting
To indicate that a class is intended to be passed between nodes or between a node and an RPC client, it is added to a whitelist. This prevents the node presenting a large surface area of all classes in all dependencies of the node as containing possible vulnerabilities.

View File

@ -17,7 +17,7 @@ If you want to start coding on Corda, then familiarise yourself with the :doc:`k
our :doc:`Hello, World! tutorial </hello-world-introduction>`. For the background behind Corda, read the non-technical
`introductory white paper`_ or for more detail, the `technical white paper`_.
If you have questions or comments, then get in touch on `Slack <https://slack.corda.net/>`_ or write a question on
If you have questions or comments, then get in touch on `Slack <https://slack.corda.net/>`_ or ask a question on
`Stack Overflow <https://stackoverflow.com/questions/tagged/corda>`_ .
We look forward to seeing what you can do with Corda!
@ -38,7 +38,5 @@ We look forward to seeing what you can do with Corda!
node-internals-index.rst
component-library-index.rst
release-process-index.rst
faq.rst
troubleshooting.rst
other-index.rst
glossary.rst

View File

@ -1,7 +1,7 @@
.. _log4j2: http://logging.apache.org/log4j/2.x/
Creating a Corda network
========================
Setting up a Corda network
==========================
A Corda network consists of a number of machines running nodes. These nodes communicate using persistent protocols in
order to create and validate transactions.
@ -61,11 +61,7 @@ be done with the network bootstrapper. This is a tool that scans all the node co
generate the network parameters file which is copied to the nodes' directories. It also copies each node's node-info file
to every other node so that they can all transact with each other.
The bootstrapper tool can be built with the command:
``gradlew buildBootstrapperJar``
The resulting jar can be found in ``tools/bootstrapper/build/libs/``.
The bootstrapper tool can be downloaded from http://downloads.corda.net/network-bootstrapper-corda-X.Y.jar, where ``X`` is the major Corda version and ``Y`` is the minor Corda version.
To use it, create a directory containing a ``node.conf`` file for each node you want to create. Then run the following command:

View File

@ -1,186 +1,4 @@
Troubleshooting
===============
Java issues
-----------
Outdated/non-Oracle JDKs
************************
Many users have faced issues when running versions of Java that are either outdated, or are produced by organisations other than Oracle (e.g. OpenJDK). The errors generated by these issues will not always clearly point to the JDK as the cause. If in doubt, check your JDK version by following the instructions `here <https://java.com/en/download/help/version_manual.xml>`_. You can download the latest version of Oracle's JDK `here <http://www.oracle.com/technetwork/java/javase/downloads/index.html>`_.
"Unresolved reference: javafx"
******************************
JavaFX is not bundled with OpenJDK. If you are using OpenJDK and get an 'Unresolved reference: javafx' error, this means that you need to install OpenJFX.
If you have APT installed and OpenJFX is part of your Unix distribution's package list, you can do this by running ``sudo apt install openjfx``, and possibly ``sudo apt install libopenjfx-jav``. Other users will want to refer to the guide `here <https://wiki.openjdk.java.net/display/OpenJFX/Building+OpenJFX>`_, or to the list of Community Builds `here <https://wiki.openjdk.java.net/display/OpenJFX/Community+Builds>`_.
"Check that you have the -parameters option specified in the Java compiler"
***************************************************************************
Some of the unit tests, and our serialization framework in general, rely on the constructor parameter names being visible
to Java reflection. Make sure you have specified the ``-parameters`` option to the Java compiler. We attempt to set this globally
for gradle and IntelliJ, but it's possible this option is not present in your environment for some reason.
"No matching constructor found: - [arg0: int, arg1: Party]: missing parameter arg0"
***********************************************************************************
Your CorDapp is written in Java and you haven't specified the ``-parameters`` compiler argument. See
:doc:`generating-a-node` for how it can be done using Gradle.
IDEA issues
-----------
Fiber classes not instrumented
******************************
If you run JUnit tests that use flows then IntelliJ will use a default JVM command line of just ``-ea``, which is
insufficient. You will need to open the run config and change it to read ``-ea -javaagent:lib/quasar.jar`` and make
sure the working directory is set to the root of the Corda repository. Alternatively, make sure you have the quasar.jar
file in your application source tree and set the paths appropriately so the JVM can find it.
You can edit the default JUnit run config in the run configs window to avoid having to do this every time you pick a
new test to run.
No source files are present
***************************
When opening a project in IDEA for the first time, you will need to build the project. You should see "Unlinked Gradle project?"
in a pop-up window in the top-right corner or in a popup alert window. It will also appear in the "Event Log" window which can be
opened by clicking on "Event Log" at the bottom right of the IDEA window. Find one of these links and click on "Import Gradle Project".
.. image:: resources/unlinked-gradle.png
:height: 50 px
:width: 410 px
:alt: IDEA Gradle Prompt
Wait for it to download the dependencies. You may then see another popup titled "Unindexed remote maven repositories found." This won't affect Corda,
so you can choose to leave them unindexed.
If still have problems, the JetBrains website has more information on `here <https://www.jetbrains.com/help/idea/2016.2/working-with-gradle-projects.html>`_.
Run configurations are missing
******************************
If you opened the Corda project by clicking "Import Project" on the IDEA splash screen rather than clicking "Open", a bug
in IDEA will cause it to wipe and recreate the ``.idea`` directory where the run configurations are stored. The fix is
simple and doesn't require you to re-import the project: just undelete the files! You can do that by either:
1. Running ``git checkout .idea/runConfigurations`` to redownload the files.
2. Using the "Version Control" pane in IDEA to undelete the files via the GUI.
IDEA complains about lack of an SDK
***********************************
If IDEA refuses to open a project because an SDK has not been selected, you may need to fix the project structure. Do this by following `these instructions <https://www.jetbrains.com/help/idea/2016.2/configuring-global-project-and-module-sdks.html>`_. The correct JDK is often found on a path such as ``jdk1.8.0_xx…/Contents/Home``. Ensure that you have the Project language level set at 8.
If you are having trouble selecting the correct JDK, the JetBrains website provides the `following guidelines <https://intellij-support.jetbrains.com/hc/en-us/articles/206544879-Selecting-the-JDK-version-the-IDE-will-run-under>`_.
IDEA complains about JVM target
*******************************
If you receive a ``Cannot inline bytecode build with JVM target 1.8 into bytecode...``, please ensure JDK is not
outdated and check that
.. parsed-literal::
Settings/Build, Execution, Deployment/Compiler/Kotlin Compiler/Target JVM Version=1.8
..
IDEA red-lining - Unresolved reference: function
************************************************
If you are running under an outdated SDK, IntelliJ will not complain about lack of an SDK, but you might notice
some functions are red-lined and compilation fails. In this case you should update you SDK, see JetBrains website
`following guidelines <https://intellij-support.jetbrains.com/hc/en-us/articles/206544879-Selecting-the-JDK-version-the-IDE-will-run-under>`_.
IDEA fails to compile Corda because it refuses to find some dependencies
************************************************************************
First check that Corda compiles successfully from the command line using ``gradlew clean build``. If this succeeds then IntelliJ may just have imported the project's Gradle files incorrectly. Try opening the
.. parsed-literal::
View/Tool Windows/Gradle
..
pane and clicking the "Refresh all Gradle projects" button. Then retry compiling Corda within IntelliJ. If this still fails then try
.. parsed-literal::
File/Invalidate Caches, Restart...
..
or checking the
.. parsed-literal::
Settings/Build, Execution, Deployment/Build Tools/Gradle/Runner/Delegate IDE build-run actions to gradle
..
checkbox, and then refreshing Gradle again.
IDEA fails to compile in VaultSchemaTest.kt
*******************************************
Run ``gradlew kaptKotlin`` to generate the sources IntelliJ is missing.
Kotlin plugin
*************
There are two ways to configure Kotlin in IDEA:
1. Via the initial project opening screen, by using the ``Configure > Plugins`` tab.
2. From an open IDEA project, by clicking ``IDEA -> Preferences ...`` (on OS X) or ``File -> Settings`` (on Windows). Select the Plugins bar to confirm that Kotlin is installed and up-to-date.
If you are still having trouble installing Kotlin, first try upgrading the Kotlin plugin. At the time of writing, you can
identify the latest version of the Kotlin plugin on `this page <https://plugins.jetbrains.com/plugin/6954>`_.
"Unable to make the module: related gradle configuration was not found. Please, re-import the Gradle project and try again"
***************************************************************************************************************************
This can usually be solved by updating IDEA. Check that you have the latest version `here <https://www.jetbrains.com/idea/download/>`_.
"Check that you have the -parameters option specified in the Java compiler"
***************************************************************************
See entry under Java (above).
Other common issues
-------------------
Slow localhost resolution
*************************
Out of the box, Apple Macs have machine names that end in ".local", by default something like "MacBook-Pro.local".
This can cause long delays with starting Corda nodes as every attempt to look up the name of the local computer triggers
a five second pause. This is not a bug in Corda but rather `a problem with the macOS networking stack <http://stackoverflow.com/questions/39636792/jvm-takes-a-long-time-to-resolve-ip-address-for-localhost>`_.
To fix it, you will need to use the Terminal app and edit your ``/etc/hosts`` file. For instance, you can do this by
typing:
``sudo nano /etc/hosts``
then typing in your own password, assuming you are an administrator user of the computer.
You will need to ensure there are two lines for the name of your machine (which you can find in the Sharing section
of System Preferences), which look like this:
.. parsed-literal::
127.0.0.1 MacBook-Pro.local
fe80::1%lo0 MacBook-Pro.local
If you've changed the name of your computer in Sharing or via the ``hostname`` command, obviously ensure you replace
``MacBook-Pro.local`` with the correct name. Then press Ctrl-O to save the file and Ctrl-X to exit.
“xterm: command not found”
**************************
On some machines, running the samples requires xterm. You can download it `here <http://invisible-island.net/xterm/#download>`_.
Please report any issues on our StackOverflow page: https://stackoverflow.com/questions/tagged/corda.

View File

@ -313,7 +313,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
if (configuration.rpcOptions.address == null) {
throw ConfigurationException("Cannot init CrashShell because node RPC address is not set (via 'rpcSettings' option).")
}
InteractiveShell.startShell(configuration.toShellConfig())
InteractiveShell.startShell(configuration.toShellConfig(), cordappLoader.appClassLoader)
}
}

View File

@ -82,6 +82,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
notary = [validating : true]
p2pPort 10002
cordapp project(':finance')
rpcSettings {
address "localhost:10014"
adminAddress "localhost:10015"
}
extraConfig = [
custom: [
jvmArgs: ["-Xmx1g"]

View File

@ -63,6 +63,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
p2pPort 10002
rpcSettings {
address "localhost:10003"
adminAddress "localhost:10004"
}
cordapps = ["$project.group:finance:$corda_release_version"]
}
node {