Giter VIP home page Giter VIP logo

chronicle-network's Introduction

Chronicle Network

Note
Development of Chronicle-Network has been moved to closed-source, enterprise customers can access the closed-source repository here

badge javadoc GitHub release%20notes subscribe brightgreen measure?project=OpenHFT Chronicle Network&metric=alert status

About

Chronicle Network is a high performance network library.

Purpose

This library is designed to be lower latency and support higher throughput by employing techniques used in low latency trading systems.

Transports

Chronicle Network uses TCP.

Planned support for

  • Shared Memory

UDP support can be found in Chronicle Network Enterprise (commercial product - contact [email protected])

Example

TCP Client/Server : Echo Example

The client sends a message to the server, the server immediately responds with the same message back to the client. The full source code of this example can be found at:

net.openhft.performance.tests.network.SimpleServerAndClientTest.test

Below are some of the key parts of this code explained, in a bit more detail.

TCPRegistry

The TCPRegistry is most useful for unit tests, it allows you to either provide a true host and port, say "localhost:8080" or if you would rather let the application allocate you a free port at random, you can just provide a text reference to the port, such as, "host.port", you can provide any text you want. It will always be taken as a reference. That is unless it’s correctly formed like "hostname:port", then it will use the exact host and port you provide. The reason we offer this functionality is quite often in unit tests you wish to start a test via loopback, followed often by another test, if the first test does not shut down correctly it can impact on the second test. Giving each test a unique port is one solution, but then managing those ports can become a problem in itself. So we created the TCPRegistry which manages those ports for you, when you come to clean up at the end of each test, all you have to do is call TCPRegistry.reset() and this will ensure that any open ports, will be closed.

// This is the name of a reference to the host name and port,
// allocated automatically to a free port on localhost
final String desc = "host.port";
TCPRegistry.createServerSocketChannelFor(desc);

// We use an event loop rather than lots of threads
EventLoop eg = EventGroup.builder().build();
eg.start();

Create and Start the Server

The server is configured with TextWire, so the client must also be configured with TextWire. The port that we will use will be ( in this example ) determined by the TCPRegistry, of course in a real life production environment you may decide not to use the TCPRegistry or if you still use the TCPRegistry you can use a fixed host:port.

final String expectedMessage = "<my message>";
AcceptorEventHandler eah = new AcceptorEventHandler(desc,
    () -> new WireEchoRequestHandler(WireType.TEXT), VanillaSessionDetails::new, 0, 0);
eg.addHandler(eah);
final SocketChannel sc = TCPRegistry.createSocketChannel(desc);
sc.configureBlocking(false);

Server Message Processing

The server code that processes a message:

In this simple example we receive and update a message and then immediately send back a response, however there are other solutions that can be implemented using Chronicle Network, such as the server responding later to a client subscription.

/**
 * This code is used to read the tid and payload from a wire message,
 * and send the same tid and message back to the client
 */
public class WireEchoRequestHandler extends WireTcpHandler {

    public WireEchoRequestHandler(@NotNull Function<Bytes<?>, Wire> bytesToWire) {
        super(bytesToWire);
    }

    /**
     * Simply reads the csp,tid and payload and sends back the tid and payload
     *
     * @param inWire  the wire from the client
     * @param outWire the wire to be sent back to the server
     * @param sd      details about this session
     */
    @Override
    protected void process(@NotNull WireIn inWire,
                           @NotNull WireOut outWire,
                           @NotNull SessionDetailsProvider sd) {

        inWire.readDocument(m -> {
            outWire.writeDocument(true, meta -> meta.write("tid")
                    .int64(inWire.read("tid").int64()));
        }, d -> {
            outWire.writeDocument(false, data -> data.write("payloadResponse")
                    .text(inWire.read("payload").text()));
        });
    }
}

Create and Start the Client

The client code that creates the TcpChannelHub:

The TcpChannelHub is used to send your messages to the server and then read the servers response. The TcpChannelHub ensures that each response is marshalled back onto the appropriate client thread. It does this through the use of a unique transaction ID ( we call this transaction ID the "tid" ), when the server responds to the client, its expected that the server sends back the tid as the very first field in the message. The TcpChannelHub will look at each message and read the tid, and then marshall the message onto your appropriate client thread.

TcpChannelHub tcpChannelHub = TcpChannelHub(null, eg, WireType.TEXT, "",
    SocketAddressSupplier.uri(desc), false);

In this example we are not implementing fail-over support, so the simple SocketAddressSupplier.uri(desc) is used.

Client Message

Creates the message the client sends to the server

// The tid must be unique, its reflected back by the server, it must be at the start
// of each message sent from the server to the client. Its use by the client to identify which
// thread will handle this message
final long tid = tcpChannelHub.nextUniqueTransaction(System.currentTimeMillis());

// We will use a text wire backed by a elasticByteBuffer
final Wire wire = new TextWire(Bytes.elasticByteBuffer());

wire.writeDocument(true, w -> w.write("tid").int64(tid));
wire.writeDocument(false, w -> w.write("payload").text(expectedMessage));

Write the Data to the Socket

When you have multiple client threads it’s important to lock before writing the data to the socket.

tcpChannelHub.lock(() -> tcpChannelHub.writeSocket(wire));

Read the Reply from the Server

In order that the correct reply can be sent to your thread you have to specify the tid.

Wire reply = tcpChannelHub.proxyReply(TimeUnit.SECONDS.toMillis(1), tid);

Check the Result of the Reply

// Reads the reply and check the result
reply.readDocument(null, data -> {
    final String text = data.read("payloadResponse").text();
    Assert.assertEquals(expectedMessage, text);
});

Shutdown and Cleanup

eg.stop();
TcpChannelHub.closeAllHubs();
TCPRegistry.reset();
tcpChannelHub.close();

Server Threading Strategy

By default the Chronicle Network server uses a single thread to process all messages. However, if you wish to dedicate each client connection to its own thread, then you can change the server threading strategy, to:

-DServerThreadingStrategy=CONCURRENT

see the following enum for more details net.openhft.chronicle.network.ServerThreadingStrategy

Java Version

This library requires Java 8 or Java 11.

Testing

The target environment is to support TCP over 10 Gigabit Ethernet. In prototype testing, this library has half the latency and supports 30% more bandwidth.

A key test is that it shouldn’t GC more than once (to allow for warm up) with -mx64m.

Downsides

This comes at the cost of scalability for large number of connections. In this situation, this library should perform at least as well as Netty.

Comparisons

Netty

Netty has a much wider range of functionality, however it creates some garbage in its operation (less than using plain NIO Selectors) and isn’t designed to support busy waiting which gives up a small but significant delay.

chronicle-network's People

Contributors

alamar avatar chipfraser avatar danielshaya avatar dkhamitov avatar dpisklov avatar epickrram avatar glukos avatar hft-team-city avatar j4sm1ne96 avatar jansturenielsen avatar jerryshea avatar jkolobok avatar lburgazzoli avatar maithem avatar minborg avatar nicktindall avatar nickward avatar peter-lawrey avatar robaustin avatar rogersimmons avatar scottkidder avatar tgd avatar tomshercliff avatar vach-chronicle avatar zelenij avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chronicle-network's Issues

UDP Roadmap

What is the timeline/roadmap for UDP support?

Erroneous use of @see tag in Javadoc

@see should be replaced with @link at these locations:

[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/connection/FatalFailureConnectionStrategy.java:38: warning - invalid usage of tag >
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/BytesBufferHandler.java:18: warning - invalid usage of tag {@see NetworkContext}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/BytesBufferHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:18: warning - invalid usage of tag {@see TcpEventHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:23: warning - invalid usage of tag {@see SslEngineStateMachine}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}
[ERROR] /Users/pemi/git/chronicle/opensource/Chronicle-Network/src/main/java/net/openhft/chronicle/network/ssl/SslDelegatingTcpHandler.java:15: warning - invalid usage of tag {@see TcpHandler}

Obscured cause of exception in UberHandler

When running DataGrid, the following messages appeared:

2020-04-21T15:04:35.107 main/replication-tcp-handler-2 UberHandler java.lang.NullPointerException
2020-04-21T15:04:35.107 main/replication-tcp-handler-2 UberHandler java.lang.NullPointerException
2020-04-21T15:04:35.107 main/replication-tcp-handler-2 UberHandler java.lang.NullPointerException

[Hundreds of similar lines not shown for brevity]

This provides little or no information pointing to the root cause of the problem.

A network client attempts to reconnect when closing.

When the client is closed it calls a listener which attempt to re-opne the connection.

[main/event-loop-monitor] INFO software.chronicle.runner.v2.Monitor -
at net.openhft.chronicle.wire.BinaryWire.write(BinaryWire.java:1031)
at net.openhft.chronicle.network.cluster.handlers.UberHandler.writeMarshallable(UberHandler.java:88)
at net.openhft.chronicle.wire.BinaryWire$FixedBinaryValueOut.marshallable(BinaryWire.java:1721)
at net.openhft.chronicle.wire.ValueOut.typedMarshallable(ValueOut.java:420)
at net.openhft.chronicle.network.cluster.handlers.UberHandler.lambda$uberHandler$5(UberHandler.java:64)
at net.openhft.chronicle.network.cluster.handlers.UberHandler$$Lambda$229/1711639613.writeMarshallable(Unknown Source)
at net.openhft.chronicle.network.connection.VanillaWireOutPublisher.put(VanillaWireOutPublisher.java:175)
at net.openhft.chronicle.network.connection.WireOutPublisher.publish(WireOutPublisher.java:114)
at net.openhft.chronicle.network.cluster.HostConnector.connect(HostConnector.java:118)
at net.openhft.chronicle.network.cluster.HostConnector.reconnect(HostConnector.java:130)
at net.openhft.chronicle.network.cluster.ClusterNotifier.onClose(ClusterNotifier.java:66)
at net.openhft.chronicle.network.cluster.ClusterNotifier.onConnectionChanged(ClusterNotifier.java:54)
at net.openhft.chronicle.network.cluster.handlers.UberHandler.close(UberHandler.java:189)
at net.openhft.chronicle.core.io.Closeable.closeQuietly(Closeable.java:42)
at net.openhft.chronicle.network.TcpEventHandler.closeSC(TcpEventHandler.java:367)
at net.openhft.chronicle.network.TcpEventHandler.close(TcpEventHandler.java:361)
at net.openhft.chronicle.core.io.Closeable.closeQuietly(Closeable.java:42)
at net.openhft.chronicle.threads.VanillaEventLoop.lambda$closeAll$0(VanillaEventLoop.java:118)
at net.openhft.chronicle.threads.VanillaEventLoop$$Lambda$390/972152147.accept(Unknown Source)
at java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:891)
at net.openhft.chronicle.threads.VanillaEventLoop.closeAll(VanillaEventLoop.java:116)
at net.openhft.chronicle.threads.VanillaEventLoop.closeAllHandlers(VanillaEventLoop.java:508)
at net.openhft.chronicle.threads.VanillaEventLoop.close(VanillaEventLoop.java:461)
at net.openhft.chronicle.core.io.Closeable.closeQuietly(Closeable.java:42)
at net.openhft.chronicle.core.io.Closeable$$Lambda$388/1091202270.accept(Unknown Source)

WireTcpHandlerTest fails due to heartbeat

Two of the three tests in WireTcpHandlerTest fail for me with the following exception on TextWire and BinaryWire. Cuirioulsy RawWire seems to pass without a problem.

I can workaround this by commenting out the heartbeats on WireTcpHandler.sendHeartBeat.

java.lang.UnsupportedOperationException: Unordered fields not supported yet. key=key1, was=heartbeat, data='heartbeat'
at net.openhft.chronicle.wire.TextWire.read(TextWire.java:260)
at net.openhft.performance.tests.network.TestData.lambda$read$5(TestData.java:46)
at net.openhft.performance.tests.network.TestData$$Lambda$13/742394451.readMarshallable(Unknown Source)
at net.openhft.chronicle.wire.Wires.lambda$readData$58(Wires.java:132)
at net.openhft.chronicle.wire.Wires$$Lambda$14/1916389359.accept(Unknown Source)
at net.openhft.chronicle.bytes.StreamingDataInput.lambda$readWithLength$1(StreamingDataInput.java:42)
at net.openhft.chronicle.bytes.StreamingDataInput$$Lambda$15/1063288177.apply(Unknown Source)
at net.openhft.chronicle.bytes.StreamingDataInput.parseWithLength(StreamingDataInput.java:54)
at net.openhft.chronicle.bytes.StreamingDataInput.readWithLength(StreamingDataInput.java:41)
at net.openhft.chronicle.wire.Wires.readData(Wires.java:132)
at net.openhft.chronicle.wire.WireIn.readDocument(WireIn.java:82)
at net.openhft.performance.tests.network.TestData.read(TestData.java:45)
at net.openhft.performance.tests.network.WireTcpHandlerTest.testLatency(WireTcpHandlerTest.java:113)
at net.openhft.performance.tests.network.WireTcpHandlerTest.testProcess(WireTcpHandlerTest.java:153)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runners.Suite.runChild(Suite.java:127)
at org.junit.runners.Suite.runChild(Suite.java:26)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

TcpSocketConsumer java.lang.AssertionError: Found tid=1486392198574 in the old map

While trying to use ChronicleEngine to access a queue remotely, we occasionally see the following AssertionError (once every few runs):

524748  [1, Demo Asset remote]
2017-02-06T16:43:18.847 /TcpChannelHub-Reads-(none) TcpSocketConsumer java.lang.AssertionError: Found tid=1486392198574 in the old map.
        at net.openhft.chronicle.network.connection.TcpChannelHub$TcpSocketConsumer.processData(TcpChannelHub.java:1346)
        at net.openhft.chronicle.network.connection.TcpChannelHub$TcpSocketConsumer.running(TcpChannelHub.java:1231)
        at net.openhft.chronicle.network.connection.TcpChannelHub$TcpSocketConsumer.lambda$start$3(TcpChannelHub.java:1160)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

and sometimes (not always) it is then immediately followed in the logs by this:

525660  [2, Demo Asset remote]
2017-02-06T16:43:18.852 tree-1/conc-event-loop-0 TcpEventHandler java.io.IOException: Broken pipe
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
        at sun.nio.ch.IOUtil.write(IOUtil.java:51)
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
        at net.openhft.chronicle.network.TcpEventHandler.tryWrite(TcpEventHandler.java:332)
        at net.openhft.chronicle.network.TcpEventHandler.invokeHandler(TcpEventHandler.java:253)
        at net.openhft.chronicle.network.TcpEventHandler.action(TcpEventHandler.java:183)
        at net.openhft.chronicle.threads.VanillaEventLoop.runAllMediumHandler(VanillaEventLoop.java:286)
        at net.openhft.chronicle.threads.VanillaEventLoop.run(VanillaEventLoop.java:206)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

After the assertion error (with or without the IOException) the logs are silent for a few seconds, and then there is what appears to be a loop of acquires and releases (onAcquired/onReleased callbacks) that never stops.

Being an assertion, I take it to mean it's a code error that should never occur, but the cryptic message doesn't help much in understanding what the issue is... we hope it means something to you and can be fixed soon :-)

net.openhft.chronicle.bytes.util.DecoratedBufferUnderflowException: readPosition failed. Position: 838 > readLimit: 834

Really don't know what's to be done.
The heart beat messages are routed also to my inherited class of WireTcpHandler, i.e in the onRead() method.
So If I read using in.wire().read("heartbeat") to see if it's null, it bails out on my read "payload" messages.
If I read in.wire().read("payload") if bails on "heartbeat" messages.
A heartbeat message handler should be installed automatically???
Why should my code have to handle heartbeat messages also?
Am I doing something wrong?

Thanks,
TJ

Allow the VanillaNetworkContext to be used for all network contexts

Allow the VanillaNetworkContext to be used for all network context so that a single port can serve a number of uses, in other words, remove the

QueueClusterNetworkContext
DatagridWireNetworkContext
MapClusterNetworkContext

and allow all the data to be stored and configured into the VanillaNetworkContext

Suspicious code in AbstractStatelessClient

The following code might fail if the condition is true:

        if (resultType == CharSequence.class && usingValue != null)
            return f -> {
                f.textTo((StringBuilder) usingValue);
                return usingValue;
            };

If the resultType is equal CharSequence, then, by definition, it is not a StringBuilder even though the usingValue might be a StringBuilder

Is it possible to add a sample for server side push

Hi there,
I'm trying to leverage chronicle network to build a bidirectional communication channel, both side need the ability to send request to the other side and wait reply, could you help to build a sample on how to push data from server to client (TcpChannelHub) or give some suggestions on how to do it.

Thanks a lot
Yunpeng Li

Add atomic VanillaNetworkContext.close() method to avoid race condition

I found a bug in this method exposed by occasional failure of FIX AcceptorInitiatorTest.testStartAndEndOfConnection()

Basically both the main thread and the event-loop-thread of the client FixEngine would attempt to call FixNetworkContext.close() and in fact enter the method simultaneously owing to lack of mutex. This would result in listener being notified twice and failing the test.

I think making the FixNetworkContext.close() method synchronised as in the base class is dangerous because it invokes listeners that could potentially do something to deadlock. And it would be better to avoid locks altogether.

My suggestion instead is to add a new VanillaNetworkContext.closeWithCAS() method to return boolean if state is actually changed (using AtomicBoolean member instead of volatile boolean).

AlwaysStartOnPrimaryConnectionStrategy doesn't honor Thread interruption

If a host is unavailable and connection thread is interrupted, i.e. the JVM is being terminated, then AlwaysStartOnPrimaryConnectionStrategy starts an infinite loop of connection fails. Technically, it alternates between

, and
socketChannel = openSocketChannel(socketAddress, tcpBufferSize, pausePeriodMs, socketConnectionTimeoutMs);

The issue was discovered while working with Chronicle-Fix engine

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.