
org.elasticsearch.transport.OutboundMessage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch - Open Source, Distributed, RESTful Search Engine
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.transport;
import org.elasticsearch.Version;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.bytes.CompositeBytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import java.io.IOException;
import java.util.Set;
abstract class OutboundMessage extends NetworkMessage {
protected final Writeable message;
OutboundMessage(ThreadContext threadContext, Version version, byte status, long requestId, Writeable message) {
super(threadContext, version, status, requestId);
this.message = message;
}
BytesReference serialize(BytesStreamOutput bytesStream) throws IOException {
bytesStream.setVersion(version);
bytesStream.skip(TcpHeader.headerSize(version));
// The compressible bytes stream will not close the underlying bytes stream
BytesReference reference;
int variableHeaderLength = -1;
final long preHeaderPosition = bytesStream.position();
if (version.onOrAfter(TcpHeader.VERSION_WITH_HEADER_SIZE)) {
writeVariableHeader(bytesStream);
variableHeaderLength = Math.toIntExact(bytesStream.position() - preHeaderPosition);
}
try (CompressibleBytesOutputStream stream =
new CompressibleBytesOutputStream(bytesStream, TransportStatus.isCompress(status))) {
stream.setVersion(version);
stream.setFeatures(bytesStream.getFeatures());
if (variableHeaderLength == -1) {
writeVariableHeader(stream);
}
reference = writeMessage(stream);
}
bytesStream.seek(0);
final int contentSize = reference.length() - TcpHeader.headerSize(version);
TcpHeader.writeHeader(bytesStream, requestId, status, version, contentSize, variableHeaderLength);
return reference;
}
protected void writeVariableHeader(StreamOutput stream) throws IOException {
threadContext.writeTo(stream);
}
protected BytesReference writeMessage(CompressibleBytesOutputStream stream) throws IOException {
final BytesReference zeroCopyBuffer;
if (message instanceof BytesTransportRequest) {
BytesTransportRequest bRequest = (BytesTransportRequest) message;
bRequest.writeThin(stream);
zeroCopyBuffer = bRequest.bytes;
} else if (message instanceof RemoteTransportException) {
stream.writeException((RemoteTransportException) message);
zeroCopyBuffer = BytesArray.EMPTY;
} else {
message.writeTo(stream);
zeroCopyBuffer = BytesArray.EMPTY;
}
// we have to call materializeBytes() here before accessing the bytes. A CompressibleBytesOutputStream
// might be implementing compression. And materializeBytes() ensures that some marker bytes (EOS marker)
// are written. Otherwise we barf on the decompressing end when we read past EOF on purpose in the
// #validateRequest method. this might be a problem in deflate after all but it's important to write
// the marker bytes.
final BytesReference message = stream.materializeBytes();
if (zeroCopyBuffer.length() == 0) {
return message;
} else {
return CompositeBytesReference.of(message, zeroCopyBuffer);
}
}
static class Request extends OutboundMessage {
private final String[] features;
private final String action;
Request(ThreadContext threadContext, String[] features, Writeable message, Version version, String action, long requestId,
boolean isHandshake, boolean compress) {
super(threadContext, version, setStatus(compress, isHandshake, message), requestId, message);
this.features = features;
this.action = action;
}
@Override
protected void writeVariableHeader(StreamOutput stream) throws IOException {
super.writeVariableHeader(stream);
if (version.onOrAfter(Version.V_6_3_0)) {
stream.writeStringArray(features);
}
stream.writeString(action);
}
private static byte setStatus(boolean compress, boolean isHandshake, Writeable message) {
byte status = 0;
status = TransportStatus.setRequest(status);
if (compress && OutboundMessage.canCompress(message)) {
status = TransportStatus.setCompress(status);
}
if (isHandshake) {
status = TransportStatus.setHandshake(status);
}
return status;
}
@Override
public String toString() {
return "Request{" + action + "}{" + requestId + "}{" + isError() + "}{" + isCompress() + "}{" + isHandshake() + "}";
}
}
static class Response extends OutboundMessage {
private final Set features;
Response(ThreadContext threadContext, Set features, Writeable message, Version version, long requestId,
boolean isHandshake, boolean compress) {
super(threadContext, version, setStatus(compress, isHandshake, message), requestId, message);
this.features = features;
}
@Override
protected void writeVariableHeader(StreamOutput stream) throws IOException {
super.writeVariableHeader(stream);
stream.setFeatures(features);
}
private static byte setStatus(boolean compress, boolean isHandshake, Writeable message) {
byte status = 0;
status = TransportStatus.setResponse(status);
if (message instanceof RemoteTransportException) {
status = TransportStatus.setError(status);
}
if (compress) {
status = TransportStatus.setCompress(status);
}
if (isHandshake) {
status = TransportStatus.setHandshake(status);
}
return status;
}
@Override
public String toString() {
return "Response{" + requestId + "}{" + isError() + "}{" + isCompress() + "}{" + isHandshake() + "}{"
+ message.getClass() + "}";
}
}
private static boolean canCompress(Writeable message) {
return message instanceof BytesTransportRequest == false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy