-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Add version to handshake requests #36171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9184c7f
49f669e
3f2e905
a3ce774
4ae5ea1
78d4309
ff53b81
21063be
212b30e
22b9524
6ee3b7a
e8b9dba
f327e4c
5681a8f
62581f8
f6c4c0b
f684c1f
affe58a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,12 +21,15 @@ | |
| import org.elasticsearch.Version; | ||
| import org.elasticsearch.action.ActionListener; | ||
| import org.elasticsearch.cluster.node.DiscoveryNode; | ||
| import org.elasticsearch.common.bytes.BytesReference; | ||
| import org.elasticsearch.common.io.stream.BytesStreamOutput; | ||
| import org.elasticsearch.common.io.stream.StreamInput; | ||
| import org.elasticsearch.common.io.stream.StreamOutput; | ||
| import org.elasticsearch.common.metrics.CounterMetric; | ||
| import org.elasticsearch.common.unit.TimeValue; | ||
| import org.elasticsearch.threadpool.ThreadPool; | ||
|
|
||
| import java.io.EOFException; | ||
| import java.io.IOException; | ||
| import java.util.Set; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
@@ -37,7 +40,7 @@ | |
| * Sends and receives transport-level connection handshakes. This class will send the initial handshake, | ||
| * manage state/timeouts while the handshake is in transit, and handle the eventual response. | ||
| */ | ||
| final class TcpTransportHandshaker { | ||
| final class TransportHandshaker { | ||
|
|
||
| static final String HANDSHAKE_ACTION_NAME = "internal:tcp/handshake"; | ||
| private final ConcurrentMap<Long, HandshakeResponseHandler> pendingHandshakes = new ConcurrentHashMap<>(); | ||
|
|
@@ -48,8 +51,8 @@ final class TcpTransportHandshaker { | |
| private final HandshakeRequestSender handshakeRequestSender; | ||
| private final HandshakeResponseSender handshakeResponseSender; | ||
|
|
||
| TcpTransportHandshaker(Version version, ThreadPool threadPool, HandshakeRequestSender handshakeRequestSender, | ||
| HandshakeResponseSender handshakeResponseSender) { | ||
| TransportHandshaker(Version version, ThreadPool threadPool, HandshakeRequestSender handshakeRequestSender, | ||
| HandshakeResponseSender handshakeResponseSender) { | ||
| this.version = version; | ||
| this.threadPool = threadPool; | ||
| this.handshakeRequestSender = handshakeRequestSender; | ||
|
|
@@ -83,11 +86,19 @@ void sendHandshake(long requestId, DiscoveryNode node, TcpChannel channel, TimeV | |
| } | ||
| } | ||
|
|
||
| void handleHandshake(Version version, Set<String> features, TcpChannel channel, long requestId) throws IOException { | ||
| handshakeResponseSender.sendResponse(version, features, channel, new VersionHandshakeResponse(this.version), requestId); | ||
| void handleHandshake(Version version, Set<String> features, TcpChannel channel, long requestId, StreamInput stream) throws IOException { | ||
| // Must read the handshake request to exhaust the stream | ||
| HandshakeRequest handshakeRequest = new HandshakeRequest(stream); | ||
| final int nextByte = stream.read(); | ||
| if (nextByte != -1) { | ||
| throw new IllegalStateException("Handshake request not fully read for requestId [" + requestId + "], action [" | ||
| + TransportHandshaker.HANDSHAKE_ACTION_NAME + "], available [" + stream.available() + "]; resetting"); | ||
| } | ||
| HandshakeResponse response = new HandshakeResponse(this.version); | ||
| handshakeResponseSender.sendResponse(version, features, channel, response, requestId); | ||
| } | ||
|
|
||
| TransportResponseHandler<VersionHandshakeResponse> removeHandlerForHandshake(long requestId) { | ||
| TransportResponseHandler<HandshakeResponse> removeHandlerForHandshake(long requestId) { | ||
| return pendingHandshakes.remove(requestId); | ||
| } | ||
|
|
||
|
|
@@ -99,7 +110,7 @@ long getNumHandshakes() { | |
| return numHandshakes.count(); | ||
| } | ||
|
|
||
| private class HandshakeResponseHandler implements TransportResponseHandler<VersionHandshakeResponse> { | ||
| private class HandshakeResponseHandler implements TransportResponseHandler<HandshakeResponse> { | ||
|
|
||
| private final long requestId; | ||
| private final Version currentVersion; | ||
|
|
@@ -113,14 +124,14 @@ private HandshakeResponseHandler(long requestId, Version currentVersion, ActionL | |
| } | ||
|
|
||
| @Override | ||
| public VersionHandshakeResponse read(StreamInput in) throws IOException { | ||
| return new VersionHandshakeResponse(in); | ||
| public HandshakeResponse read(StreamInput in) throws IOException { | ||
| return new HandshakeResponse(in); | ||
| } | ||
|
|
||
| @Override | ||
| public void handleResponse(VersionHandshakeResponse response) { | ||
| public void handleResponse(HandshakeResponse response) { | ||
| if (isDone.compareAndSet(false, true)) { | ||
| Version version = response.version; | ||
| Version version = response.responseVersion; | ||
| if (currentVersion.isCompatible(version) == false) { | ||
| listener.onFailure(new IllegalStateException("Received message from unsupported version: [" + version | ||
| + "] minimal compatible version is: [" + currentVersion.minimumCompatibilityVersion() + "]")); | ||
|
|
@@ -149,24 +160,75 @@ public String executor() { | |
| } | ||
| } | ||
|
|
||
| static final class VersionHandshakeResponse extends TransportResponse { | ||
| static final class HandshakeRequest extends TransportRequest { | ||
|
|
||
| private final Version version; | ||
|
|
||
| VersionHandshakeResponse(Version version) { | ||
| HandshakeRequest(Version version) { | ||
| this.version = version; | ||
| } | ||
|
|
||
| private VersionHandshakeResponse(StreamInput in) throws IOException { | ||
| HandshakeRequest(StreamInput streamInput) throws IOException { | ||
| super(streamInput); | ||
| BytesReference remainingMessage; | ||
| try { | ||
| remainingMessage = streamInput.readBytesReference(); | ||
| } catch (EOFException e) { | ||
| remainingMessage = null; | ||
| } | ||
| if (remainingMessage == null) { | ||
| version = null; | ||
| } else { | ||
| try (StreamInput messageStreamInput = remainingMessage.streamInput()) { | ||
| this.version = Version.readVersion(messageStreamInput); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void readFrom(StreamInput in) { | ||
| throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable"); | ||
| } | ||
|
|
||
| @Override | ||
| public void writeTo(StreamOutput streamOutput) throws IOException { | ||
| super.writeTo(streamOutput); | ||
| assert version != null; | ||
| try (BytesStreamOutput messageStreamOutput = new BytesStreamOutput(4)) { | ||
| Version.writeVersion(version, messageStreamOutput); | ||
| BytesReference reference = messageStreamOutput.bytes(); | ||
| streamOutput.writeBytesReference(reference); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static final class HandshakeResponse extends TransportResponse { | ||
|
|
||
| private final Version responseVersion; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the plan is to replace
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is follow-up work. We need the version the the request to bootstrap the follow-up work. Once we have the version in the request, we can serialize arbitrary responses that are compatible with the remote node's version.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it, thanks. |
||
|
|
||
| HandshakeResponse(Version responseVersion) { | ||
| this.responseVersion = responseVersion; | ||
| } | ||
|
|
||
| private HandshakeResponse(StreamInput in) throws IOException { | ||
| super.readFrom(in); | ||
| version = Version.readVersion(in); | ||
| responseVersion = Version.readVersion(in); | ||
| } | ||
|
|
||
| @Override | ||
| public void readFrom(StreamInput in) { | ||
| throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable"); | ||
| } | ||
|
|
||
| @Override | ||
| public void writeTo(StreamOutput out) throws IOException { | ||
| super.writeTo(out); | ||
| assert version != null; | ||
| Version.writeVersion(version, out); | ||
| assert responseVersion != null; | ||
| Version.writeVersion(responseVersion, out); | ||
| } | ||
|
|
||
| Version getResponseVersion() { | ||
| return responseVersion; | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.