24
24
import org .apache .logging .log4j .message .ParameterizedMessage ;
25
25
import org .elasticsearch .Version ;
26
26
import org .elasticsearch .action .ActionListener ;
27
+ import org .elasticsearch .action .NotifyOnceListener ;
27
28
import org .elasticsearch .cluster .node .DiscoveryNode ;
28
29
import org .elasticsearch .common .Randomness ;
29
30
import org .elasticsearch .common .UUIDs ;
@@ -70,7 +71,7 @@ public HandshakingTransportAddressConnector(Settings settings, TransportService
70
71
public void connectToRemoteMasterNode (TransportAddress transportAddress , ActionListener <DiscoveryNode > listener ) {
71
72
transportService .getThreadPool ().generic ().execute (new AbstractRunnable () {
72
73
@ Override
73
- protected void doRun () throws Exception {
74
+ protected void doRun () {
74
75
75
76
// TODO if transportService is already connected to this address then skip the handshaking
76
77
@@ -80,38 +81,68 @@ protected void doRun() throws Exception {
80
81
emptySet (), Version .CURRENT .minimumCompatibilityVersion ());
81
82
82
83
logger .trace ("[{}] opening probe connection" , this );
83
- final Connection connection = transportService .openConnection (targetNode ,
84
+ transportService .openConnection (targetNode ,
84
85
ConnectionProfile .buildSingleChannelProfile (Type .REG , probeConnectTimeout , probeHandshakeTimeout ,
85
- TimeValue .MINUS_ONE , null ));
86
- logger .trace ("[{}] opened probe connection" , this );
87
-
88
- final DiscoveryNode remoteNode ;
89
- try {
90
- remoteNode = transportService .handshake (connection , probeHandshakeTimeout .millis ());
91
- // success means (amongst other things) that the cluster names match
92
- logger .trace ("[{}] handshake successful: {}" , this , remoteNode );
93
- } catch (Exception e ) {
94
- // we opened a connection and successfully performed a low-level handshake, so we were definitely talking to an
95
- // Elasticsearch node, but the high-level handshake failed indicating some kind of mismatched configurations
96
- // (e.g. cluster name) that the user should address
97
- logger .warn (new ParameterizedMessage ("handshake failed for [{}]" , this ), e );
98
- listener .onFailure (e );
99
- return ;
100
- } finally {
101
- IOUtils .closeWhileHandlingException (connection );
102
- }
103
-
104
- if (remoteNode .equals (transportService .getLocalNode ())) {
105
- // TODO cache this result for some time? forever?
106
- listener .onFailure (new ConnectTransportException (remoteNode , "local node found" ));
107
- } else if (remoteNode .isMasterNode () == false ) {
108
- // TODO cache this result for some time?
109
- listener .onFailure (new ConnectTransportException (remoteNode , "non-master-eligible node found" ));
110
- } else {
111
- transportService .connectToNode (remoteNode );
112
- logger .trace ("[{}] full connection successful: {}" , this , remoteNode );
113
- listener .onResponse (remoteNode );
114
- }
86
+ TimeValue .MINUS_ONE , null ), new ActionListener <>() {
87
+ @ Override
88
+ public void onResponse (Connection connection ) {
89
+ logger .trace ("[{}] opened probe connection" , this );
90
+
91
+ // use NotifyOnceListener to make sure the following line does not result in onFailure being called when
92
+ // the connection is closed in the onResponse handler
93
+ transportService .handshake (connection , probeHandshakeTimeout .millis (), new NotifyOnceListener <DiscoveryNode >() {
94
+
95
+ @ Override
96
+ protected void innerOnResponse (DiscoveryNode remoteNode ) {
97
+ try {
98
+ // success means (amongst other things) that the cluster names match
99
+ logger .trace ("[{}] handshake successful: {}" , this , remoteNode );
100
+ IOUtils .closeWhileHandlingException (connection );
101
+
102
+ if (remoteNode .equals (transportService .getLocalNode ())) {
103
+ // TODO cache this result for some time? forever?
104
+ listener .onFailure (new ConnectTransportException (remoteNode , "local node found" ));
105
+ } else if (remoteNode .isMasterNode () == false ) {
106
+ // TODO cache this result for some time?
107
+ listener .onFailure (new ConnectTransportException (remoteNode , "non-master-eligible node found" ));
108
+ } else {
109
+ transportService .connectToNode (remoteNode , new ActionListener <Void >() {
110
+ @ Override
111
+ public void onResponse (Void ignored ) {
112
+ logger .trace ("[{}] full connection successful: {}" , this , remoteNode );
113
+ listener .onResponse (remoteNode );
114
+ }
115
+
116
+ @ Override
117
+ public void onFailure (Exception e ) {
118
+ listener .onFailure (e );
119
+ }
120
+ });
121
+ }
122
+ } catch (Exception e ) {
123
+ listener .onFailure (e );
124
+ }
125
+ }
126
+
127
+ @ Override
128
+ protected void innerOnFailure (Exception e ) {
129
+ // we opened a connection and successfully performed a low-level handshake, so we were definitely
130
+ // talking to an Elasticsearch node, but the high-level handshake failed indicating some kind of
131
+ // mismatched configurations (e.g. cluster name) that the user should address
132
+ logger .warn (new ParameterizedMessage ("handshake failed for [{}]" , this ), e );
133
+ IOUtils .closeWhileHandlingException (connection );
134
+ listener .onFailure (e );
135
+ }
136
+
137
+ });
138
+
139
+ }
140
+
141
+ @ Override
142
+ public void onFailure (Exception e ) {
143
+ listener .onFailure (e );
144
+ }
145
+ });
115
146
}
116
147
117
148
@ Override
0 commit comments