5050import java .util .ArrayList ;
5151import java .util .Collection ;
5252import java .util .Collections ;
53- import java .util .HashSet ;
5453import java .util .Iterator ;
5554import java .util .List ;
56- import java .util .Set ;
5755import java .util .concurrent .ArrayBlockingQueue ;
5856import java .util .concurrent .BlockingQueue ;
5957import java .util .concurrent .ExecutorService ;
6058import java .util .concurrent .RejectedExecutionException ;
6159import java .util .concurrent .Semaphore ;
6260import java .util .concurrent .atomic .AtomicBoolean ;
61+ import java .util .concurrent .atomic .AtomicLong ;
6362import java .util .function .Function ;
6463import java .util .function .Predicate ;
6564import java .util .function .Supplier ;
@@ -84,7 +83,6 @@ final class RemoteClusterConnection implements TransportConnectionListener, Clos
8483
8584 private final TransportService transportService ;
8685 private final ConnectionManager connectionManager ;
87- private final ConnectedNodes connectedNodes ;
8886 private final String clusterAlias ;
8987 private final int maxNumRemoteConnections ;
9088 private final Predicate <DiscoveryNode > nodePredicate ;
@@ -123,7 +121,6 @@ final class RemoteClusterConnection implements TransportConnectionListener, Clos
123121 this .nodePredicate = nodePredicate ;
124122 this .clusterAlias = clusterAlias ;
125123 this .connectionManager = connectionManager ;
126- this .connectedNodes = new ConnectedNodes (clusterAlias );
127124 this .seedNodes = Collections .unmodifiableList (seedNodes );
128125 this .skipUnavailable = RemoteClusterService .REMOTE_CLUSTER_SKIP_UNAVAILABLE
129126 .getConcreteSettingForNamespace (clusterAlias ).get (settings );
@@ -176,8 +173,7 @@ boolean isSkipUnavailable() {
176173
177174 @ Override
178175 public void onNodeDisconnected (DiscoveryNode node ) {
179- boolean remove = connectedNodes .remove (node );
180- if (remove && connectedNodes .size () < maxNumRemoteConnections ) {
176+ if (connectionManager .size () < maxNumRemoteConnections ) {
181177 // try to reconnect and fill up the slot of the disconnected node
182178 connectHandler .forceConnect ();
183179 }
@@ -188,7 +184,7 @@ public void onNodeDisconnected(DiscoveryNode node) {
188184 * will invoke the listener immediately.
189185 */
190186 void ensureConnected (ActionListener <Void > voidActionListener ) {
191- if (connectedNodes .size () == 0 ) {
187+ if (connectionManager .size () == 0 ) {
192188 connectHandler .connect (voidActionListener );
193189 } else {
194190 voidActionListener .onResponse (null );
@@ -466,14 +462,13 @@ private void collectRemoteNodes(Iterator<Supplier<DiscoveryNode>> seedNodes, fin
466462 }
467463
468464 final DiscoveryNode handshakeNode = maybeAddProxyAddress (proxyAddress , handshakeResponse .getDiscoveryNode ());
469- if (nodePredicate .test (handshakeNode ) && connectedNodes .size () < maxNumRemoteConnections ) {
465+ if (nodePredicate .test (handshakeNode ) && manager .size () < maxNumRemoteConnections ) {
470466 PlainActionFuture .get (fut -> manager .connectToNode (handshakeNode , null ,
471467 transportService .connectionValidator (handshakeNode ), ActionListener .map (fut , x -> null )));
472468 if (remoteClusterName .get () == null ) {
473469 assert handshakeResponse .getClusterName ().value () != null ;
474470 remoteClusterName .set (handshakeResponse .getClusterName ());
475471 }
476- connectedNodes .add (handshakeNode );
477472 }
478473 ClusterStateRequest request = new ClusterStateRequest ();
479474 request .clear ();
@@ -580,12 +575,11 @@ public void handleResponse(ClusterStateResponse response) {
580575 Iterable <DiscoveryNode > nodesIter = nodes .getNodes ()::valuesIt ;
581576 for (DiscoveryNode n : nodesIter ) {
582577 DiscoveryNode node = maybeAddProxyAddress (proxyAddress , n );
583- if (nodePredicate .test (node ) && connectedNodes .size () < maxNumRemoteConnections ) {
578+ if (nodePredicate .test (node ) && connectionManager .size () < maxNumRemoteConnections ) {
584579 try {
585580 // noop if node is connected
586581 PlainActionFuture .get (fut -> connectionManager .connectToNode (node , null ,
587582 transportService .connectionValidator (node ), ActionListener .map (fut , x -> null )));
588- connectedNodes .add (node );
589583 } catch (ConnectTransportException | IllegalStateException ex ) {
590584 // ISE if we fail the handshake with an version incompatible node
591585 // fair enough we can't connect just move on
@@ -628,15 +622,20 @@ boolean assertNoRunningConnections() { // for testing only
628622 }
629623
630624 boolean isNodeConnected (final DiscoveryNode node ) {
631- return connectedNodes . contains (node );
625+ return connectionManager . nodeConnected (node );
632626 }
633627
634- DiscoveryNode getAnyConnectedNode () {
635- return connectedNodes .getAny ();
636- }
628+ private final AtomicLong nextNodeId = new AtomicLong ();
637629
638- void addConnectedNode (DiscoveryNode node ) {
639- connectedNodes .add (node );
630+ DiscoveryNode getAnyConnectedNode () {
631+ List <DiscoveryNode > nodes = new ArrayList <>(connectionManager .connectedNodes ());
632+ if (nodes .isEmpty ()) {
633+ throw new NoSuchRemoteClusterException (clusterAlias );
634+ } else {
635+ long curr ;
636+ while ((curr = nextNodeId .incrementAndGet ()) == Long .MIN_VALUE );
637+ return nodes .get (Math .floorMod (curr , nodes .size ()));
638+ }
640639 }
641640
642641 /**
@@ -647,67 +646,13 @@ public RemoteConnectionInfo getConnectionInfo() {
647646 clusterAlias ,
648647 seedNodes .stream ().map (Tuple ::v1 ).collect (Collectors .toList ()),
649648 maxNumRemoteConnections ,
650- connectedNodes . size (),
649+ getNumNodesConnected (),
651650 initialConnectionTimeout ,
652651 skipUnavailable );
653652 }
654653
655654 int getNumNodesConnected () {
656- return connectedNodes .size ();
657- }
658-
659- private static final class ConnectedNodes {
660-
661- private final Set <DiscoveryNode > nodeSet = new HashSet <>();
662- private final String clusterAlias ;
663-
664- private Iterator <DiscoveryNode > currentIterator = null ;
665-
666- private ConnectedNodes (String clusterAlias ) {
667- this .clusterAlias = clusterAlias ;
668- }
669-
670- public synchronized DiscoveryNode getAny () {
671- ensureIteratorAvailable ();
672- if (currentIterator .hasNext ()) {
673- return currentIterator .next ();
674- } else {
675- throw new NoSuchRemoteClusterException (clusterAlias );
676- }
677- }
678-
679- synchronized boolean remove (DiscoveryNode node ) {
680- final boolean setRemoval = nodeSet .remove (node );
681- if (setRemoval ) {
682- currentIterator = null ;
683- }
684- return setRemoval ;
685- }
686-
687- synchronized boolean add (DiscoveryNode node ) {
688- final boolean added = nodeSet .add (node );
689- if (added ) {
690- currentIterator = null ;
691- }
692- return added ;
693- }
694-
695- synchronized int size () {
696- return nodeSet .size ();
697- }
698-
699- synchronized boolean contains (DiscoveryNode node ) {
700- return nodeSet .contains (node );
701- }
702-
703- private synchronized void ensureIteratorAvailable () {
704- if (currentIterator == null ) {
705- currentIterator = nodeSet .iterator ();
706- } else if (currentIterator .hasNext () == false && nodeSet .isEmpty () == false ) {
707- // iterator rollover
708- currentIterator = nodeSet .iterator ();
709- }
710- }
655+ return connectionManager .size ();
711656 }
712657
713658 private static ConnectionManager createConnectionManager (ConnectionProfile connectionProfile , TransportService transportService ) {
0 commit comments